Files
projet_gestion_commande/backend/gestion/services/telegram.go
T
2026-06-12 13:33:07 +02:00

184 lines
4.4 KiB
Go

package services
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
)
var TelegramBot *TelegramService
type TelegramService struct {
botToken string
webhookSecret string
BotUsername string
notificationsEnabled bool
}
func NewTelegramService() *TelegramService {
svc := &TelegramService{
botToken: os.Getenv("TELEGRAM_BOT_TOKEN"),
webhookSecret: os.Getenv("TELEGRAM_WEBHOOK_SECRET"),
BotUsername: os.Getenv("TELEGRAM_BOT_USERNAME"),
}
TelegramBot = svc
return svc
}
func (t *TelegramService) IsConfigured() bool {
return t.botToken != ""
}
func (t *TelegramService) IsNotificationsEnabled() bool {
return t.notificationsEnabled
}
func (t *TelegramService) SetNotificationsEnabled(enabled bool) {
t.notificationsEnabled = enabled
}
// Reload met à jour le token et le username (appelé après UpdateSettings)
func (t *TelegramService) Reload(token, username string) {
if token != "" {
t.botToken = token
}
if username != "" {
t.BotUsername = username
}
}
func (t *TelegramService) ValidateWebhookSecret(header string) bool {
if t.webhookSecret == "" {
return true // pas de secret configuré = accepté
}
return header == t.webhookSecret
}
// SendMessage envoie un message texte (HTML) à un chat Telegram
func (t *TelegramService) SendMessage(chatID int64, text string) error {
if !t.IsConfigured() {
return fmt.Errorf("telegram non configuré")
}
payload := map[string]interface{}{
"chat_id": chatID,
"text": text,
"parse_mode": "HTML",
}
body, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("marshal: %w", err)
}
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", t.botToken)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return fmt.Errorf("création requête: %w", err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("envoi: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("telegram API status %d", resp.StatusCode)
}
return nil
}
// SendMessageWithButtons envoie un message HTML avec des boutons inline (URL buttons).
// buttons est une liste de paires [texte, url].
func (t *TelegramService) SendMessageWithButtons(chatID int64, text string, buttons [][2]string) error {
if !t.IsConfigured() {
return fmt.Errorf("telegram non configuré")
}
row := make([]map[string]string, 0, len(buttons))
for _, b := range buttons {
row = append(row, map[string]string{"text": b[0], "url": b[1]})
}
payload := map[string]interface{}{
"chat_id": chatID,
"text": text,
"parse_mode": "HTML",
"reply_markup": map[string]interface{}{
"inline_keyboard": [][]map[string]string{row},
},
}
body, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("marshal: %w", err)
}
url := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", t.botToken)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return fmt.Errorf("création requête: %w", err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("envoi: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("telegram API status %d", resp.StatusCode)
}
return nil
}
// SetWebhook enregistre l'URL webhook auprès de Telegram
func (t *TelegramService) SetWebhook(webhookURL string) error {
if !t.IsConfigured() {
return fmt.Errorf("telegram non configuré")
}
payload := map[string]interface{}{
"url": webhookURL,
"allowed_updates": []string{"message"},
}
if t.webhookSecret != "" {
payload["secret_token"] = t.webhookSecret
}
body, err := json.Marshal(payload)
if err != nil {
return err
}
url := fmt.Sprintf("https://api.telegram.org/bot%s/setWebhook", t.botToken)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("setWebhook status %d", resp.StatusCode)
}
log.Printf("✅ [TELEGRAM] Webhook enregistré: %s", webhookURL)
return nil
}