Un bot Telegram come pro memoria e archivio

Avevo bisogno di due cose semplici: qualcuno che mi ricordasse le cose al momento giusto e un posto dove ritrovarle dopo. Un bot Telegram fa entrambe, perché Telegram c'è già sul telefono e non richiede di costruire un'interfaccia.

#Come si parla con Telegram

Un bot è un account speciale. Lo si crea con @BotFather, che consegna un token. Il token è la sola credenziale: chi lo ha può comandare il bot, quindi va tenuto fuori dal repository.

Da lì tutto passa da HTTPS. Ogni metodo è una chiamata a un indirizzo con questa forma:

 1curl -s "https://api.telegram.org/bot<TOKEN>/sendMessage" \
 2  -d chat_id=<CHAT_ID> \
 3  -d text="Ciao"

Si parla in due direzioni.

  • Il bot scrive. Si chiamano metodi come sendMessage, sendPoll o pinChatMessage, indicando la chat con il suo chat_id.
  • Il bot ascolta. Ogni messaggio, comando o voto è un update. Ci sono due modi per riceverli.

I due modi di ricevere gli update:

| Modo | Come funziona | Quando ha senso | | --- | --- | --- | | getUpdates (polling) | Il bot chiede a Telegram se c'è qualcosa di nuovo, a ripetizione. | Sviluppo locale, nessun indirizzo pubblico. | | setWebhook | Telegram fa una POST a un indirizzo HTTPS tuo, a ogni update. | Server raggiungibile da internet, nessun processo sempre acceso. |

Con il webhook non c'è niente da tenere in esecuzione: arriva una richiesta, la gestisci, rispondi 200. Telegram permette anche di impostare un secret_token, che rimanda in un header a ogni chiamata, per verificare che la richiesta venga davvero da lui.

#La scelta tecnica

L'applicazione era già Laravel, quindi il bot vive lì dentro invece di diventare un servizio a parte. Uso irazasyed/telegram-bot-sdk, che nasconde le chiamate HTTP dietro una facciata Telegram.

Le parti sono tre:

  1. Una rotta POST pubblica riceve il webhook e lo passa al gestore dei comandi dell'SDK. Le query inline per ora rispondono solo che non sono supportate.
  2. Una classe per comando, in app/Console/Commands/Telegram/, registrata in config/telegram.php. Ognuna dichiara nome e alias, per esempio /calcetto, e la logica nel metodo handle().
  3. Lo scheduler di Laravel per tutto ciò che deve partire da solo, senza che nessuno scriva al bot.

Il token e l'indirizzo del webhook stanno nel file .env, letti solo dalla configurazione.

Due tabelle tengono lo stato:

  • bot_chats elenca le chat che il bot conosce. Il comando /start registra la chat con enabled = false: il bot non agisce finché non viene abilitata a mano. È una guardia semplice contro chi aggiunge il bot dove non deve.
  • bot_messages ricorda cosa è già stato inviato: chat, id del messaggio, compito, anno e settimana.

#Pro memoria e archivio nella pratica

L'esempio più concreto è il sondaggio settimanale del calcetto. Il sabato alle 08:00 il comando soccer:send pubblica nelle chat abilitate un sondaggio con i giorni della settimana successiva. Il sondaggio viene fissato in alto e quello della settimana precedente viene sganciato.

Il flusso del sondaggio: a richiesta o da scheduler, sempre passando da bot_messages
Il flusso del sondaggio: a richiesta o da scheduler, sempre passando da bot_messages

Ogni invio viene scritto in bot_messages. Questo è l'archivio, ed è anche ciò che rende il pro memoria affidabile:

  • se per la settimana esiste già un messaggio, il bot non ne crea un secondo ma risponde con un rimando a quello esistente;
  • se qualcuno chiede /calcetto a mano, ottiene lo stesso sondaggio e non un duplicato;
  • il messaggio passato resta ritrovabile per chat, anno e settimana.

Il comando può essere richiamato anche a mano, con next o con il numero della settimana ISO.

#Per chiudere

Lo schema è questo: un invio automatico e un registro di ciò che è partito. Un webhook, una classe per comando, lo scheduler e due tabelle bastano per un pro memoria che non si ripete e non si perde.

Hüton · canzone del giorno

Playlist · Radio Hüton

cat radio-huton.md

Gemme nascoste e brani da riscoprire, dall’indie italiano a ogni genere.

Ascolta su Spotify

UT99 · server di gioco

  • Onlineut99.spinelli.dev:77770/10 giocatori · CTFGame · CTF-FaceOpen to all players, balanced teams, fast-paced matches.
  • Onlineprivate.ut99.spinelli.dev:77870/6 giocatori · CTFGame · CTF-FaceInvite-only competitive 3v3 CTF. Contact the CTs squad for access credentials.