ip
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,15 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/app"
|
||||
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
||||
)
|
||||
|
||||
@@ -204,3 +207,61 @@ func sendTelegramMessage(botToken, chatID, text string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ─── Webhook portal (set + info) ─────────────────────────────────────────────
|
||||
|
||||
// SetPortalWebhook registra el webhook del portal en la API de Telegram para el bot indicado.
|
||||
// POST /app/telegram/:id/set-portal-webhook
|
||||
func SetPortalWebhook(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
|
||||
}
|
||||
cfg, err := models.GetTelegramConfigByID(uint(id))
|
||||
if err != nil {
|
||||
return c.Status(404).JSON(fiber.Map{"error": "Configuración no encontrada"})
|
||||
}
|
||||
|
||||
// Construir URL base desde la configuración de la app
|
||||
baseURL := app.Http.Server.Url
|
||||
if len(baseURL) > 0 && baseURL[len(baseURL)-1] == '/' {
|
||||
baseURL = baseURL[:len(baseURL)-1]
|
||||
}
|
||||
webhookURL := baseURL + "/webhooks/telegram-portal"
|
||||
|
||||
apiURL := fmt.Sprintf("https://api.telegram.org/bot%s/setWebhook", cfg.BotToken)
|
||||
payload, _ := json.Marshal(map[string]string{"url": webhookURL})
|
||||
resp, err := http.Post(apiURL, "application/json", bytes.NewReader(payload)) //nolint:noctx
|
||||
if err != nil {
|
||||
return c.Status(502).JSON(fiber.Map{"ok": false, "error": err.Error()})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
raw, _ := io.ReadAll(resp.Body)
|
||||
|
||||
var tgResp map[string]interface{}
|
||||
_ = json.Unmarshal(raw, &tgResp)
|
||||
log.Printf("[SetPortalWebhook] bot=%d url=%s resp=%s", id, webhookURL, string(raw))
|
||||
return c.JSON(fiber.Map{"ok": tgResp["ok"], "webhook_url": webhookURL, "telegram": tgResp})
|
||||
}
|
||||
|
||||
// GetPortalWebhookInfo consulta el estado actual del webhook en Telegram.
|
||||
// GET /app/telegram/:id/webhook-info
|
||||
func GetPortalWebhookInfo(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 32)
|
||||
if err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
|
||||
}
|
||||
cfg, err := models.GetTelegramConfigByID(uint(id))
|
||||
if err != nil {
|
||||
return c.Status(404).JSON(fiber.Map{"error": "Configuración no encontrada"})
|
||||
}
|
||||
apiURL := fmt.Sprintf("https://api.telegram.org/bot%s/getWebhookInfo", cfg.BotToken)
|
||||
resp, err := http.Get(apiURL) //nolint:noctx
|
||||
if err != nil {
|
||||
return c.Status(502).JSON(fiber.Map{"ok": false, "error": err.Error()})
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var result map[string]interface{}
|
||||
_ = json.NewDecoder(resp.Body).Decode(&result)
|
||||
return c.JSON(result)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user