This commit is contained in:
Lizandro Guarnizo
2025-04-18 07:38:32 -05:00
parent 462eb0d42c
commit 79d6cca94d
23 changed files with 821 additions and 73 deletions
+162
View File
@@ -0,0 +1,162 @@
package controllers
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"image/png"
"log"
"os"
"github.com/chai2010/webp"
"github.com/gofiber/fiber/v2"
"github.com/sujit-baniya/fiber-boilerplate/app"
"github.com/sujit-baniya/fiber-boilerplate/pkg/helpers"
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
"gorm.io/gorm"
// Importa el repositorio
)
func CreateQr(c *fiber.Ctx) error {
var data services.ContactData
if err := json.Unmarshal(c.Body(), &data); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Datos inválidos",
})
}
// 1. Generar el QR en formato PNG
qrBytes, err := services.GenerateVCardQR(data)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "No se pudo generar el QR",
})
}
// 2. Decodificar PNG
img, err := png.Decode(bytes.NewReader(qrBytes))
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error al decodificar QR PNG",
})
}
// 3. Convertir a WebP
var webpBuf bytes.Buffer
if err := webp.Encode(&webpBuf, img, nil); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error al convertir QR a WebP",
})
}
random := helpers.RandomString(4)
fileName := fmt.Sprintf("qrs/qr-%s-%s.webp", data.FirstName, random)
tmpPath := fmt.Sprintf("/tmp/%s.webp", data.FirstName)
// 4. Guardar archivo temporal
if err := os.WriteFile(tmpPath, webpBuf.Bytes(), 0644); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "No se pudo guardar el QR temporalmente",
})
}
defer os.Remove(tmpPath)
// 5. Subir a OSS
ossService, err := services.NewOSSServiceFromDB()
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error de conexión con OSS",
})
}
if err := ossService.UploadFile(fileName, tmpPath); err != nil {
log.Printf("Error subiendo archivo a OSS: %v", err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error subiendo archivo a OSS",
})
}
// 6. URL del archivo
url := fmt.Sprintf("https://%s.%s/%s", ossService.BucketName, ossService.Endpoint, fileName)
// 7. Buscar si ya existe un registro con ese vcard_id
var existing models.QrVcard
db := app.Http.Database.DB
err = db.Where("vcard_id = ?", data.VcardID).First(&existing).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
// No existe, crear nuevo
newQr := models.QrVcard{
Qr: url,
UsuarioID: data.FirstName,
Email: data.Email,
VcardID: data.VcardID,
}
if err := models.CreateQrVcard(&newQr); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error al guardar nuevo QR en la base de datos",
})
}
} else {
// Otro error
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error al consultar la base de datos",
})
}
} else {
// Ya existe, actualizar
existing.Qr = url
existing.UsuarioID = data.FirstName
existing.Email = data.Email
if err := models.UpdateQrVcard(&existing); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error al actualizar el QR en la base de datos",
})
}
}
// 8. Retornar la URL
return c.JSON(fiber.Map{
"url": url,
})
}
func CreateQrTmp(c *fiber.Ctx) error {
var data services.ContactData
if err := json.Unmarshal(c.Body(), &data); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Datos inválidos",
})
}
qrBytes, err := services.GenerateVCardQR(data)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "No se pudo generar el QR",
})
}
// Decodificar PNG
img, err := png.Decode(bytes.NewReader(qrBytes))
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "No se pudo procesar la imagen",
})
}
// Codificar a WebP
var webpBuffer bytes.Buffer
if err := webp.Encode(&webpBuffer, img, &webp.Options{Lossless: true}); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "No se pudo convertir a WebP",
})
}
c.Type("webp")
return c.Send(webpBuffer.Bytes())
}
+2 -25
View File
@@ -80,52 +80,29 @@ func ReenvioEmail(c *fiber.Ctx) error {
// Función para manejar la solicitud de restablecimiento de contraseña
func RequestPasswordResetPost(c *fiber.Ctx) error {
// Crear una estructura para mapear los datos entrantes
type Request struct {
NombreUsuario string `json:"nombre_usuario"` // Mapeo con la clave del JSON
}
var req Request
// Parsear el cuerpo JSON de la solicitud
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "Invalid JSON format",
})
}
// Obtener el usuario del JSON parseado
usuario := req.NombreUsuario
usuario := c.FormValue("nombre_usuario")
fmt.Println("Usuario recibido:", usuario)
// Intentar obtener el usuario por nombre de usuario
user, err := models.GetUserByUsuario(usuario)
if err != nil || user == nil {
// Devolver respuesta de error en formato JSON
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"success": false,
"message": "Usuario inactivo o no existente",
})
}
// Obtener el email del usuario
usuario_email := user.Email
// Imprimir el email en la consola
log.Println("Sending password reset email to:", usuario_email)
// Enviar el correo de restablecimiento de contraseña de forma asíncrona
go services.SendPasswordResetEmail(usuario_email, app.Http.Server.Url)
// Devolver respuesta de éxito en formato JSON
return c.JSON(fiber.Map{
"success": true,
"message": "We've sent an email to reset your password to your registered email address",
})
}
// todo: Generar contrasenas aleatorias /do/generate-password
func generatePassword(length int) (string, error) {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&"
+28
View File
@@ -0,0 +1,28 @@
package controllers
import (
"fmt"
"github.com/sujit-baniya/fiber-boilerplate/pkg/services"
)
type TelegramController struct {
Service *services.TelegramService
}
func NewTelegramController(service *services.TelegramService) *TelegramController {
return &TelegramController{Service: service}
}
func (tc *TelegramController) SendMessage(chatID interface{}, message string) error {
if chatID == "" || message == "" {
return fmt.Errorf("chat_id and message are required")
}
err := tc.Service.SendMessage(chatID, message)
if err != nil {
return fmt.Errorf("error sending message: %v", err)
}
return nil
}