Come realizzare un bot Telegram (uno dei tanti modi)

Evviva le API e i microservizi!

Intro

Sono l’ultimo dei primi, ci sono già tanti tutorial a tema. Voglio comunque condividere la mia piccola esperienza, perché quella descritta sotto mi sembra una modalità comoda e didattica per entrare in questo mondo.
Mostrerò come creare un bot Telegram, scritto in Python, basato su un microservice e che dialoga con delle API.

Un bot — in questo caso un chat bot — è un utente un po’ diverso con cui chattare, perché fatto di codice. Come se dialogassimo con un robot.

Telegram è una bella piattaforma di istant messaging che offre anche la possibilità di creare dei chat bot e di interagire con questi.

Per definire un microservizio userò le parole di Martin Fowler:

Lo stile architetturale a microservizi è un approccio allo sviluppo di una singola applicazione come insieme di piccoli servizi, ciascuno dei quali viene eseguito da un proprio processo e comunica con un meccanismo snello, spesso una HTTP API.

Bot “pappagallo” in Python

Il bot “pappagallo” fa una cosa sola: risponde ai messaggi che riceve, con le stesse parole che ha avuto inviato.

È una cosa che sembra inutile, mentre è un fondamentale punto di partenza. Perché il core di un chat bot è fare in modo che elabori quanto ricevuto e lo rimandi indietro: un “pappagallo” è l’esempio “ciao mondo” per un chat bot.

Si inizia con installare Telegram e usare proprio un bot (@botfather) per crearne un nuovo.

Non entro nei dettagli, è semplice e trovate molti articoli sul tema. Creato il bot, annotate da qualche parte nome e token.

Il prossimo passo è quello di creare un microservizio. Per farlo sfrutturermo una gran bella piattaforma online: hook.io.

Questi gli step:

  • create un nuovo microservizio e dategli un nome. Ogni microservizio è qui chiamato Hook;
  • scegliete python come linguaggio;
  • inserite il codice sottostante e salvate il microservizio.
import requests
# raccolgo nella variabile `testo` ciò che gli utenti scriveranno in chat al bot
testo=Hook['params']['message']['text']
# raccolgo la chat ID
chatID=Hook['params']['message']['chat']['id']
# imposto l'URL per inviare i messaggi indietro al bot
URL='https://api.telegram.org/bot' + Hook['env']['parrot_bot_key'] + '/sendMessage'
# invio indietro alla chat ID il messaggio ricevuto
richiesta=requests.get(URL,verify=False,data={'chat_id':chatID,'text':testo})

Il passo successivo è quello di dire al bot di usare il microservizio appena creato. Per farlo chiamate (anche via browser) questo URL inserendo i vostri dati:

https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://hook.io/<hook-user>/<hook-name>
  • <TOKEN> è il token del vostro bot;
  • <hook-user> è il nome utente creato su hook.io;
  • <hook-name> è il nome del microservizio che avete creato.

Una volta lanciato l’URL, se tutto va bene, avrete in risposta qualcosa come:

{"ok":true,"result":true,"description":"Webhook was set"}

Questo è un punto chiave: impostando un Webhook, stiamo dicendo al bot di reindirizzare al microservizio tutto ciò che gli viene inviato in chat.

Nel codice del microservizio queste le parti chiave:

  • viene importato il modulo python requests, che consentirà di fare “parlare” il chat bot con gli utenti, facendo delle chiamate in HTTP;
  • tutti i parametri HTTP in ingresso — in questo caso i messaggi di chat — vengono raccolti nell’oggetto Hook.params, che in python è Hook['params'] (python è uno dei tanti linguaggi supportati in hook.io);
  • alle variabili di ambiente si accede con Hook['env'] e ne facciamo uso per recuperare il token del bot Telegram;
  • raccogliamo in una variabile il testo che il microservizio riceve;
  • in un’altra l’ID della chat in corso. Ogni utente avrà infatti con il bot la propria chatID;
  • inviamo indietro alla chatID da cui il bot ha ricevuto il messaggio, una copia dello stesso, tramite il modulo requests di python.

Non resta che aprire il bot e chattare con lui. Ne ho creato uno di test e potete provarlo qui: @hellomoonParrot_bot.

Tutto questo non è straordinario?? :)

“hellomoon”, un bot basato sulle API della NASA

Alcuni giorni fa la NASA ha reso pubblico un bel motore di ricerca che consente di cercare nel suo fantastico archivio multimediale: https://images.nasa.gov

È possibile usarlo anche tramite API e quindi si presta bene a creare un bot che, data una (o più) parola chiave, mostri le immagini correlate del catalogo.
Se voglio ad esempio cercare, soltanto tra le immagini, la stringa “palermo”, interrogherò le API con questo URL:

https://images-api.nasa.gov/search?media_type=image&q=palermo

La NASA risponde in JSON:

Per creare questo bot non è necessario fare molto di più di quanto fatto sopra per il “pappagallo”:

  • studiare un po’ le API della NASA, fare qualche query di test e leggerne gli output;
  • creare un bot Telegram;
  • creare un microservizio in python, a cui aggiungere un modulo per leggere dati in formato JSON e il metodo delle API di Telegram per inviare foto;
  • impostare nel microservizio la variabile d’ambiente per il token del bot.

Il codice è solo un po’ più complesso ed è quello sottostante.
Oltre al modulo json ne ho aggiunti altri due: random per generare dei numeri casuali, che uso per non ricevere per le stessa query sempre le stesse foto, e il modulo time per impostare un intervallo minimo tra una chiamata e un’altra alle API di Telegram (ne faccio una ogni secondo).

Lo script fa questo:

  • raccoglie la parola (o le parole) inviate in chat dall’utente;
  • lancia la query sulle API della NASA, ne raccoglie l’output e conteggia i risultati;
  • se pari a zero lo script si ferma e da un avviso all’utente;
  • se sono >= 1, ne seleziona non più di 4 in modo random;
  • estrae per ognuno l’URL dell’immagine a bassa risoluzione, la descrizione e l’ID;
  • aggiunge una tastiera con il solo tasto Info;
  • invia la foto alla chat da cui è arrivata la parola da cercare, con una didascalia (di non più di 200 caratteri) che contiene l’URL alla scheda dell’immagine e la sua descrizione.

Se volete testarlo il bot è @hellomoonbot e qui sotto lo vedete in azione.

Considerazioni finali

Non avrei mai scritto questo post, senza prima aver letto quello di Nicola Malizia (citato sotto tra le letture consigliate). Lo ringrazio molto.

hook.io è un servizio eccellente, che fa molto di più di quanto qui descritto e per cui vale la pena di “fare un giro” nel sito
È opensource e trovate il codice qui: con questo potrete replicare una piattaforma di hosting di microservizi.
Se invece volete mettere in piedi in autonomia uno o più microservizi, il progetto open-source da attenzionare è microcule.

Diffidate sempre un po’ delle guide che mostrano come realizzare qualcosa con poco sforzo, poca conoscenza di dominio e senza spese. Quindi fatelo anche con questo tutorial. 
Ho usato ad esempio la versione free di hook.io che è limitata a 1000 richieste mensili: sono poche per realizzare qualcosa che (si spera) verrà usato da molti utenti. La soluzione è pagare o realizzare un bot in totale autonomia (quindi ci vuole una competenza più “larga”).

La gran parte dei bot Telegram sono poco utili. Spesso infatti (come in questo caso), si tratta di poco più di motori di query che restituiscono un risultato all’utente, per i quali sarebbe probabilmente preferibile un minisito basato su php, python, ecc. e con una interfaccia che si adatti al terminale. 
Se può bastare un browser, meglio non aggiungere una dipendenza da un’altra app.

Ciò che utile e “intelligente” dipende in ogni caso anche da noi. 
Un po’ perché è questione di gusti. Io ho un amico che impazziva per il bot dedicato a Jovanotti, che rimpiazzava tutte le ‘s’ (e anche le ‘z’) con ‘f’ in tutte le risposte che dava. 
Un po’ perché oggi esistono eccellenti librerie e API di analisi (di testi, immagini, audio, video, ecc.), di machine learning, di Natural Language Processing, di intelligenza artificiale, che consentono di aggiungere molta intelligenza a una buona idea di bot e a una preparazione adeguata per usarle.

Questo tutorial è scritto per mettere un piede dentro questo spazio, tutto il resto del cammino starà a ognuno di noi. Il codice l’ho raccolto in questo repository.

Dedico questo post a Giovanni Pirrotta.

Letture consigliate