This commit is contained in:
Lizandro Guarnizo
2026-05-16 21:54:17 -05:00
parent 65f35fbc51
commit 4b2003c752
7 changed files with 179 additions and 5 deletions
+79
View File
@@ -1,7 +1,10 @@
package controllers
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
@@ -620,6 +623,7 @@ func TelegramPortalWebhook(c *fiber.Ctx) error {
chatID := update.Message.Chat.ID
text := strings.TrimSpace(update.Message.Text)
log.Printf("[TelegramPortalWebhook] chatID=%d text=%q", chatID, text)
if chatID == 0 || text == "" {
return c.SendStatus(fiber.StatusOK)
}
@@ -666,3 +670,78 @@ func portalTelegramReply(chatID int64, text string) {
}
}
// PortalTelegramValidar llama getUpdates en todos los bots activos, busca el mensaje
// "/vincular TOKEN" del usuario y vincula el chat_id si coincide.
// POST /portal/mi-perfil/telegram-validar
func PortalTelegramValidar(c *fiber.Ctx) error {
u := middlewares.PortalUserFromLocals(c)
if u == nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "No autenticado"})
}
// Recuperar el token vigente del usuario
tkn, err := models.GetTelegramPortalTokenByUser(u.ID)
if err != nil || tkn == nil {
return c.Status(400).JSON(fiber.Map{"error": "No tienes un código activo. Genera uno primero."})
}
configs, _ := models.GetAllTelegramConfigs()
for _, cfg := range configs {
if !cfg.Activo || cfg.BotToken == "" {
continue
}
chatID, found := searchTokenInUpdates(cfg.BotToken, tkn.Token)
if !found {
continue
}
// Vincular
if err := models.UpdatePortalUserTelegramChatID(u.ID, fmt.Sprintf("%d", chatID)); err != nil {
return c.Status(500).JSON(fiber.Map{"error": "No se pudo vincular. Intenta de nuevo."})
}
models.DeleteTelegramPortalToken(u.ID)
svc := &services.TelegramService{BotToken: cfg.BotToken}
_ = svc.SendMessage(chatID, "✅ ¡Tu Telegram ha sido vinculado al portal correctamente!\n\nRecibirás notificaciones importantes por este medio.")
log.Printf("[PortalTelegramValidar] usuario=%d chatID=%d vinculado", u.ID, chatID)
return c.JSON(fiber.Map{"ok": true, "chat_id": fmt.Sprintf("%d", chatID)})
}
return c.Status(200).JSON(fiber.Map{"ok": false, "error": "No se encontró el mensaje. Asegúrate de enviar /vincular " + tkn.Token + " al bot."})
}
// searchTokenInUpdates llama getUpdates y busca un mensaje que contenga el token.
// Retorna el chat_id y true si lo encuentra.
func searchTokenInUpdates(botToken, token string) (int64, bool) {
apiURL := fmt.Sprintf("https://api.telegram.org/bot%s/getUpdates?limit=100", botToken)
resp, err := http.Get(apiURL) //nolint:noctx
if err != nil {
log.Printf("[searchTokenInUpdates] error getUpdates: %v", err)
return 0, false
}
defer resp.Body.Close()
var result struct {
OK bool `json:"ok"`
Result []struct {
Message struct {
Chat struct {
ID int64 `json:"id"`
} `json:"chat"`
Text string `json:"text"`
} `json:"message"`
} `json:"result"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil || !result.OK {
return 0, false
}
upperToken := strings.ToUpper(token)
for _, upd := range result.Result {
txt := strings.ToUpper(strings.TrimSpace(upd.Message.Text))
if strings.Contains(txt, upperToken) && upd.Message.Chat.ID != 0 {
log.Printf("[searchTokenInUpdates] token=%s chatID=%d", token, upd.Message.Chat.ID)
return upd.Message.Chat.ID, true
}
}
return 0, false
}