feat: enviar factura por Telegram como documento adjunto
El bot solo procesaba mensajes de texto: un documento o foto enviado al chat se ignoraba por completo (Telegram lo manda en message.document/photo con caption, no en el campo text). Ahora el webhook detecta el adjunto, lo descarga desde la API de Telegram y lo deja pendiente para el chat; el agente usa la nueva tool adjuntar_factura para asociarlo a un cliente (preguntando cliente/monto si el caption no los trae) y crear la Factura con el archivo ya vinculado, igual que si se subiera desde el dashboard. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
8fce587304
commit
b292d98cf6
@@ -25,11 +25,26 @@ type tgChat struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type tgDocument struct {
|
||||
FileID string `json:"file_id"`
|
||||
FileName string `json:"file_name"`
|
||||
MimeType string `json:"mime_type"`
|
||||
}
|
||||
|
||||
type tgPhotoSize struct {
|
||||
FileID string `json:"file_id"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
}
|
||||
|
||||
type tgMessage struct {
|
||||
MessageID int `json:"message_id"`
|
||||
From tgUser `json:"from"`
|
||||
Chat tgChat `json:"chat"`
|
||||
Text string `json:"text"`
|
||||
MessageID int `json:"message_id"`
|
||||
From tgUser `json:"from"`
|
||||
Chat tgChat `json:"chat"`
|
||||
Text string `json:"text"`
|
||||
Caption string `json:"caption"`
|
||||
Document *tgDocument `json:"document"`
|
||||
Photo []tgPhotoSize `json:"photo"`
|
||||
}
|
||||
|
||||
type tgUpdate struct {
|
||||
@@ -53,13 +68,18 @@ func TelegramAgentWebhook(c *fiber.Ctx) error {
|
||||
if err := c.BodyParser(&update); err != nil {
|
||||
return c.SendStatus(200) // siempre 200 a Telegram
|
||||
}
|
||||
if update.Message == nil || strings.TrimSpace(update.Message.Text) == "" {
|
||||
if update.Message == nil {
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
|
||||
msg := update.Message
|
||||
chatID := msg.Chat.ID
|
||||
text := strings.TrimSpace(msg.Text)
|
||||
caption := strings.TrimSpace(msg.Caption)
|
||||
hasAttachment := msg.Document != nil || len(msg.Photo) > 0
|
||||
if text == "" && caption == "" && !hasAttachment {
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
|
||||
// Buscar el config del agente que tenga este bot token
|
||||
ai, tgCfg, err := models.GetAgenteBotConfig()
|
||||
@@ -86,6 +106,45 @@ func TelegramAgentWebhook(c *fiber.Ctx) error {
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
|
||||
// Documento o foto adjunto: se descarga y queda "pendiente" para que el
|
||||
// agente lo asocie a una factura (tool adjuntar_factura) según lo que diga
|
||||
// el caption o lo que responda el usuario a continuación.
|
||||
if hasAttachment {
|
||||
fileID, fileName, mimeType := "", "documento", ""
|
||||
switch {
|
||||
case msg.Document != nil:
|
||||
fileID = msg.Document.FileID
|
||||
if msg.Document.FileName != "" {
|
||||
fileName = msg.Document.FileName
|
||||
}
|
||||
mimeType = msg.Document.MimeType
|
||||
case len(msg.Photo) > 0:
|
||||
// Telegram manda varias resoluciones de la misma foto; la última es la de mayor calidad.
|
||||
best := msg.Photo[len(msg.Photo)-1]
|
||||
fileID = best.FileID
|
||||
fileName = "foto.jpg"
|
||||
mimeType = "image/jpeg"
|
||||
}
|
||||
if fileID != "" {
|
||||
path, dlErr := services.DescargarDocumentoTelegram(tgCfg.BotToken, fileID, fileName, mimeType)
|
||||
if dlErr != nil {
|
||||
log.Printf("[AGENT_WEBHOOK] Error descargando adjunto: %v", dlErr)
|
||||
sendAgentReply(tgCfg.BotToken, chatID, "No pude descargar el archivo que enviaste, intenta de nuevo.")
|
||||
return c.SendStatus(200)
|
||||
}
|
||||
services.StageFacturaAttachment(chatID, path, fileName, mimeType)
|
||||
nota := fmt.Sprintf("[Documento adjunto recibido: %s]", fileName)
|
||||
switch {
|
||||
case caption != "":
|
||||
text = nota + " " + caption
|
||||
case text == "":
|
||||
text = nota + " ¿A qué cliente corresponde y cuál es el monto de la factura?"
|
||||
default:
|
||||
text = nota + " " + text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Procesar en goroutine para responder 200 inmediatamente a Telegram
|
||||
go func() {
|
||||
response, err := services.ProcessAgentMessage(chatID, text, ai)
|
||||
|
||||
Reference in New Issue
Block a user