package services import ( "bytes" "encoding/json" "fmt" "log" "net/http" "os" "time" ) // TelegramBot est l'instance globale accessible depuis le package db 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 } // 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 }