GOLEM Telegram Bot

Da GolemWiki.
Versione del 24 set 2017 alle 20:49 di Giomba (discussione | contributi) (Aggiornamenti sul codice github e il VPS)
Jump to navigation Jump to search

Il bot Telegram del GOLEM è in fase di testing.

Il codice sorgente può essere consultato su github.

Al momento tutto sta correttamente funzionando sul nostro VPS.

Creare un BOT

Aprire una chat col bot BotFather e creare un nuovo bot seguendo le intuitive istruzioni interattive. Generare anche il token. Il token è un codice casuale, ma univoco una volta creato, che serve agli sviluppatori per accedere al bot.

È una cosa brutta che assomiglia a questo:

110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw

Contattare il bot tramite token

Costruire un URL tipo questo: https://api.telegram.org/botTOKEN/metodo

  • TOKEN è ovviamente il token che abbiamo generato
  • metodo è l'operazione che vogliamo effettuare

Ne esistono tante [1], noi ne vedremo alcune che ci servono.

getMe

Ottiene informazioni sul bot. Lo usiamo per vedere se i server di Telegram funzionano. Esempio di URL da consultare:

https://api.telegram.org/bot110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/getMe

Riceveremo in risposta un documento JSON che possiamo facilmente interpretare tramite Python o PHP per estrapolare le varie informazioni attraverso il nostro programma.

Ricevere gli aggiornamenti

Quando qualcuno scrive al bot, il messaggio viene inviato ai server di Telegram, che lo mantengono per un certo periodo (max 24 ore). Per leggerlo tramite il nostro bot (il nostro programma) esistono due modi:

  • query attiva via HTTP (getUpdates): a intervalli regolari, il nostro programma interroga i server di Telegram per sapere se c'è un nuovo messaggio. CONTRO: è grande spreco di risorse; PRO: utile per fare debugging;
  • query passiva via HTTP (WebHook): quando i server di Telegram ricevono un messaggio per il bot, saranno loro a contattare il nostro programma via HTTP; PRO: non spreca risorse CONTRO: necessità di un server web dedicato e debugging più ostico.

Alla fine, la soluzione con query passiva WebHook è decisamente quella più sensata.

Mentre si usa un WebHook non si può usare il getUpdates, e viceversa (ma va?).

WebHook

Per impostare un WebHook bisogna usare il metodo setWebhook, con una cosa del genere:

https://api.telegram.org/bot110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/setWebhook?url=

Se lasciamo url= vuoto in questo modo, cancelliamo il WebHook e Telegram non contatterà il nostro programma quando il nostro bot riceverà un messaggio. Utile per tornare nella modalità getUpdates e fare debugging.

Altrimenti, dobbiamo specificare l'URL a cui si trova il nostro programma, per esempio:

https://api.telegram.org/bot110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/setWebhook?url=https://golem.linux.it/directory/bot.php

Ovviamente non è quello, mica siamo così citrulli da scriverlo qui! :-) È meglio usare URL con nomi strani e caratteri casuali, così si evita che qualcuno possa inavvertitamente (o intenzionalmente) usare il nostro programma a sproposito. Siccome ci fa fatica pensare a dei caratteri casuali, facciamoci aiutare da questo comando:

dd if=/dev/urandom bs=1 count=12 | base64

Certificato SSL

Importante: tutte le query devono avvenire attraverso HTTPS (HTTP su SSL). Si può acquistare un certificato (sganciando parecchi euri), si può generare con Let's Encrypt oppure si può generare in locale e autofirmarlo (self-signed). La prima soluzione è la più immediata e costosa, la seconda e la terza sono meno immediate ma sono gratuita (free as in free beer, che non è poi così male).

Generiamo il nostro certificato [2]:

openssl req -newkey rsa:2048 -sha256 -nodes -keyout golem.linux.it.key -x509 -days 720 -out golem.linux.it.pem -subj "/C=IT/ST=Italy/L=Florence/O=GruppoLinuxEmpoli/CN=golem.linux.it"
  • -days 720 imposta la scadenza (nel caso specifico, tra due anni)
  • -keyout golem.linux.it.key specifica il nome del file su cui verrà scritta la nostra chiave privata (da custodire gelosamente)
  • -out golem.linux.it.pem specifica il nome del file su cui verrà scritta la nostra chiave pubblica (che manderemo a Telegram)

E impostiamo il nostro webserver per usarlo come certificato per l'HTTPS. Per esempio, ecco qui come farlo su Apache.

Mandiamo a Telegram la nostra chiave pubblica effettuando una richiesta HTTP di tipo POST invece che GET, con lo stesso URL di prima, e ovviamente allegando il nostro certificato pubblico. Per farlo possiamo usare curl con questo praticissimo comando:

curl -F "url=https://golem.linux.it/directory/bot.php" -F "certificate=@golem.linux.it.pem" https://api.telegram.org/bot110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw/setWebhook

Il comando dovrebbe restituire un messaggio di successo dai server di Telegram.

Come doppio controllo, controlliamo che tutto funzioni davvero provando il metodo getUpdates: deve dare errore perché abbiamo impostato il WebHook.

Programma

Scriviamo il nostro programma (per esempio in PHP) e mettiamolo all'URL appena indicato a Telegram. Mandiamo un messaggio al nostro bot, e notiamo che il nostro script viene contattato (possiamo controllare /var/log/apache2/access.log per vedere se davvero viene chiamato. Si può usare tail -f su quel file per controllarlo in tempo reale)

A questo punto il nostro programma non deve far altro che leggere il JSON che gli è stato inviato tramite HTTP POST e decidere cosa fare. Il JSON contiene il messaggio e tutti i metadati relativi ad esso (presenza di link, emoticon, allegati come foto, video, ecc...) e per il suo contenuto ci sono varie strutture documentate [3].

Cosa fa il nostro bot

Il nostro bot è raggiungibile col nome @GOLEMpoliBot, naturalmente riceve messaggi da chiunque, ma prende in considerazione solo quelli provenienti dagli utenti che noi abilitiamo (per ragioni che saranno ovvie presto).

Il messaggio viene sempre inoltrato al nostro canale su Telegram, indipendentemente dal contenuto. Se il messaggio contiene un URL, allora si suppone che il link sia adatto per la mailing list, e allora viene analizzato, e se punta ad una pagina HTML con un campo title valido, viene inoltrato anche sulla nostra mailing list tradizionale.

Oss: a proposito di questo uso "strano" del bot, abbiamo scelto di scrivere direttamente a lui e non di fargli leggere i comandi all'interno del nostro gruppo per snellire il processo di condivisione. Così, per condividere un link interessante, basterà inviarlo al bot e lui penserà a inoltrarlo ai canali di comunicazione giusti, senza necessità di usare comandi strani.

Tempo stimato per la condivisione: 3 secondi. Immediatezza d'uso: 1 Googol (circa 10100)

Infine, un altro script indipendente osserva i cambiamenti sul feed RSS del nostro blog Wordpress, e quando ci sono dei nuovi articoli li inoltra sulla mailing list e sul canale. Di nuovo, penserà a tutto lui.