Files
telegram-gateway/HOWTO_ADD_BOT.md
Gabriel Radureau f90d5efdae
All checks were successful
Docker Build / build-and-push-image (push) Successful in 52s
docs(HOWTO): add Cas 2.5 — http forward handler (Phase 2a livrée)
2026-05-09 14:29:40 +02:00

6.7 KiB

Ajouter un nouveau bot

Trois cas selon ce que tu veux faire.


Cas 1 — Envoi seul (Cowork → Telegram, pas d'interaction)

Le gateway n'est pas nécessaire. Une session Cowork qui envoie juste des notifications appelle directement la Bot API.

Setup une fois (humain) :

  1. @BotFather → /newbot → noter le token
  2. Trouver ton chat_id via @userinfobot ou en messageant le bot et en regardant getUpdates

Prompt à donner à la session Cowork :

Tu peux envoyer une notification Telegram via :

  curl -sS -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
       -H 'Content-Type: application/json' \
       -d '{"chat_id":<CHAT_ID>,"text":"<message>"}'

Variables :
  BOT_TOKEN=<token-botfather>     # à fournir en env ou en clair
  CHAT_ID=<ton-chat-id-numerique>

Pas besoin du gateway pour de l'envoi pur. Préfère cette voie quand
la session n'a rien à recevoir en retour.

Cas 2 — Bot echo simple via le gateway (Phase 1, gated par auth)

Utile pour valider la chaîne, créer un canal de log conversationnel, etc.

Auth (Phase 1.5, ADR 20260509) : par défaut, requireAuth: true s'applique → tout user qui DM ce bot doit d'abord ouvrir une session via /auth <code> chez @arcodange_factory_bot. Voir AUTH.md. Pour rendre un bot public, ajouter explicitement requireAuth: false.

Steps (humain ou session Claude avec accès au cluster + au repo) :

  1. @BotFather crée le bot, noter le TOKEN.

    TOKEN='1234:AAA...'
    SLUG='monbot'                                    # kebab-case, [a-z0-9-]+
    ENV_SLUG=$(echo "$SLUG" | tr 'a-z-' 'A-Z_')      # ex: monbot → MONBOT
    SECRET=$(openssl rand -hex 32)
    
  2. Patcher le Secret cluster (ajoute les 2 clés sans toucher aux existantes) :

    kubectl -n telegram-gateway patch secret telegram-gateway-bots --type=json -p="[
      {\"op\":\"add\",\"path\":\"/data/BOT_${ENV_SLUG}_TOKEN\",\"value\":\"$(echo -n "$TOKEN" | base64)\"},
      {\"op\":\"add\",\"path\":\"/data/BOT_${ENV_SLUG}_SECRET\",\"value\":\"$(echo -n "$SECRET" | base64)\"}
    ]"
    
  3. Déclarer le bot dans chart/values.yaml sous bots: :

    bots:
      monbot:
        handler: echo
        # requireAuth: true  (implicite — défaut sécurisé)
    

    Pour un bot public (notifications status, etc.), opt-out explicite :

    bots:
      statusbot:
        handler: echo
        requireAuth: false
    
  4. Push + rollout :

    cd /Users/gabrielradureau/Work/Vibe/telegram-gateway
    git add chart/values.yaml
    git commit -m "bots: add $SLUG"
    git push
    kubectl -n telegram-gateway rollout restart deploy/telegram-gateway
    kubectl -n telegram-gateway rollout status  deploy/telegram-gateway
    
  5. Enregistrer le webhook côté Telegram :

    export BOT_${ENV_SLUG}_TOKEN="$TOKEN"
    export BOT_${ENV_SLUG}_SECRET="$SECRET"
    make setwebhook SLUG="$SLUG" BASE_URL=https://tg.arcodange.fr
    
  6. Test :

    • Si requireAuth est laissé à true : envoie un message → réponse 🔒 /auth chez @arcodange_factory_bot ; fais /auth <code> chez factory ; renvoie un message → echo en < 2 s.
    • Si requireAuth: false : echo direct en < 2 s.

Limite handler echo : tous les bots echo répondent toujours pareil. Pour de la logique métier, voir Cas 2.5 (HTTP forward) ou Cas 3 (agent async).


Cas 2.5 — Bot piloté par un service interne via HTTP forward (Phase 2a, livré)

Cible : un service du cluster (par ex. webapp, ou un mini-service Go/Python dédié) reçoit l'Update Telegram complet en POST JSON, traite sa logique, renvoie {"text": "<reply>"}. Le gateway envoie text au user.

Sync : le webhook ack attend la réponse (timeout par défaut 5 s, plafond 30 s — Telegram coupe vers 60 s). Pour des backends lents, voir Cas 3.

Setup côté gateway (suit Cas 2 pour le bot Telegram + le Secret) puis :

  1. Déclarer le bot avec handler: http dans chart/values.yaml :

    bots:
      webappbot:
        handler: http
        http:
          url: http://webapp.webapp.svc.cluster.local:8080/telegram/update
          timeout: 5s
        # requireAuth: true  (implicite — défaut sécurisé)
    
  2. Côté service interne, exposer un endpoint qui :

    • Accepte POST <url> avec un body = JSON Telegram Update (champs : update_id, message.text, message.from.id, message.chat.id, etc.)
    • Lit le header X-Bot-Slug: <slug> pour distinguer plusieurs bots qui forwarderaient au même service
    • Renvoie 200 {"text": "réponse au user"} (ou 200 body vide si pas de réponse à envoyer)
    • Respecte le timeout configuré (le gateway coupe à timeout)
  3. Push values.yaml + rollout comme dans Cas 2.

Exemple minimal de upstream service (Go) :

http.HandleFunc("/telegram/update", func(w http.ResponseWriter, r *http.Request) {
    var u struct {
        Message struct {
            Text string `json:"text"`
            From struct{ ID int64 `json:"id"` } `json:"from"`
        } `json:"message"`
    }
    json.NewDecoder(r.Body).Decode(&u)
    reply := fmt.Sprintf("hello user %d, you said: %s", u.Message.From.ID, u.Message.Text)
    json.NewEncoder(w).Encode(map[string]string{"text": reply})
})

Cas 3 — Bot interactif piloté par un agent async (Phase 3, pas encore livré)

Cible : utilisateur DM le bot → gateway enqueue le job → worker async exécute un wrapper shell (ex. claude --print, mistral-vibe, ou un script Python qui appelle Ollama) → la réponse est renvoyée via Telegram, même si le backend (Macbook Ollama) dort au moment du DM (retry exponentiel jusqu'à 1 h).

Pour l'instant non supporté. Requiert :

  • Phase 2b (queue Postgres + worker — fondation async)
  • Phase 3 (handlers shell / script / ollama + WoL Macbook optionnel)

Quand Phase 3 sera up, l'ajout d'un tel bot sera : steps Cas 2 + handler shell/script/ollama au lieu d'echo, plus la commande/script à exécuter.

Plan complet : ~/.claude/plans/pour-les-notifications-on-inherited-seal.md.


Récap : quel cas choisir ?

Besoin Cas État Gateway impliqué ?
Notifs sortantes one-way (Cowork → user) Cas 1 livré non, Bot API directe
Bot qui répond toujours pareil (echo, ack, ping) Cas 2 livré (Phase 1) oui
Bot piloté par un service interne du cluster (webapp, mini-service custom) Cas 2.5 livré (Phase 2a) oui
Bot conversationnel piloté par agent async (Claude / Mistral / Ollama / script, retry si backend dort) Cas 3 futur (Phase 3) oui