in Tutorial, Tutorial Python, Tutorial Telegram + Python

Telegram Bot API – Interfacciarsi con i Bot Telegram tramite Python

L’articolo di oggi è il primo di una serie in cui andrò a trattare l’utilizzo di Telegram tramite Python, partendo dal come utilizzare i Bot di Telegram in maniera programmatica.

Questo è uno dei miei argomenti preferiti ed è anche legato ad una delle domande che sento di più quando parlo con altri appassionati del settore: come posso inviare facilmente delle notifiche al cellulare dal mio sistema?. Quando ho utilizzato per la prima volta questa feature di Telegram, ero andato a creare piccoli programmi che andassero a monitorare delle pagine web in attesa di aggiornamenti; questo è quanto vedremo alla fine di questo capitolo.

Proseguendo con la serie, andrò a trattare ed approfondire il tema, proponendo un progetto in più scaglioni tramite cui utilizzare un bot per la gestione remota di smart devices in casa, anche utilizzando schede come ESP8266, che abbiamo visto spesso su antima.it, come target.

Creare un bot utilizzando BotFather

Il primo passo per potere utilizzare i Bot di Telegram è quello di crearne uno: per farlo, bisognerà aprire una chat Telegram con l’account BotFather.

BotFather è un bot Telegram che permette di creare altri bot; la procedura per la creazione è piuttosto semplice e diretta:

  • Aprite una chat con il bot andando in Contatti ed inserendo nella barra di ricerca la stringa @BotFather.
  • Una volta aperta la chat, inserite il comando di creazione di un nuovo bot inviando la stringa /newbot (includendo la barra iniziale).
  • Verrete presentati con la richiesta di un nome per il bot, che rappresenterà il nome mostrato agli utenti che chatteranno col bot, inserite pure qualsiasi nome vogliate.
  • A questo punto verrà richiesto l’inserimento di un username, che deve essere univoco e deve terminare per Bot; potreste dovere provare diverse volte questo ultimo passo nel caso in cui il nome che stiate scegliendo sia già preso da un altro bot.

Una volta effettuati questi passi, BotFather risponderà informandovi del successo della procedura e rilasciandovi un token che andremo ad usare per potere utilizzare le API di Telegram. Questo token è fondamentale per qualsiasi operazione da effettuare col bot e va salvato e tenuto come informazione privata.

La libreria python-telegram-bot

Abbiamo recuperato il token del nostro nuovo bot, e ora? Ora è possibile creare applicazioni programmaticamente, utilizzando una delle librerie che supporti le API di Telegram nel nostro linguaggio prescelto.

In questo articolo, come nei prossimi, vi presenterò applicazioni scritte in Python, ma sappiate che è possibile utilizzare le stesse funzionalità in altri linguaggi. A questo proposito, potete trovare una lista delle librerie community-driven, pronte all’uso a questo indirizzo.

Come anticipato, andremo a focalizzare la nostra attenzione su Python ed, in particolare, sulla libreria python-telegram-bot. La possiamo installare tramite pip utilizzando il solito:

pip install python-telegram-bot

Per controllare il corretto funzionamento della libreria, possiamo andare a scrivere un veloce esempio, che inizializzerà la connessione con il bot e ne stamperà alcune informazioni. Nell’esempio la variabile token è una stringa all’interno della quale va inserito il token ottenuto con il procedimento precedente. 

import telegram

token = ""
bot = telegram.Bot(token)

print(bot.get_me())

Se tutto è andato bene, una volta eseguito questo codice, verranno visualizzate alcune informazioni sul nostro bot, che risulteranno familiari, dato che sono in parte quelle scelte da noi poco prima!

Gestione dei comandi e pattern Updater/Dispatcher

Una delle caratteristiche più interessanti dei bot Telegram è quella di potere gestire dei comandi mandati dagli utenti, eseguendo delle operazioni ben precise alla loro ricezione.

Per pensare a come possiamo implementare questa feature nei nostri bot, è prima doveroso capire come la libreria si interfaccia con le API Telegram. Tutto ciò avviene tramite due astrazioni utilizzabili attraverso le classi UpdaterDispatcher.

Updater e Dispatcher non sono altro che i due attori del classico modello produttore consumatore. Un Updater sta in continua attesa di nuovi messaggi provenienti da Telegram, che rende disponibili al Dispatcher tramite una coda in comune.

Una volta che un messaggio arriva al Dispatcher, possiamo gestirlo in maniera specifica utilizzando degli Handler.
Gli Handler ci offrono la possibilità di gestire specifici tipi di messaggi in arrivo in maniera particolare, tramite delle funzioni di callback personalizzabili.

Un semplice esempio di gestione dei comandi

Ci sono vari tipi di Handler già disponibili per diversi tipi di messaggi: concentriamoci per ora su quelle per gestire i comandi, e proviamo ad intercettare i comandi di /start ed /end. La classe in questione è CommandHandler, che possiamo trovare all’interno del modulo telegram.ext, insieme ad Updater.

Vediamo come scrivere una callback adatta a quanto vogliamo ottenere:

def start(update, context):
    chat_id = update.effective_chat.id
    update.message.reply_text("start")
    print("start called from chat with id = {}".format(chat_id))

Andiamo a commentare quello che abbiamo scritto:

  • La callback ha due parametri di ingresso, update che rappresenta un update in arrivo, e context per portare dietro informazioni aggiuntive sull’update.
  • Tramite il parametro update.effective_chat.id, possiamo recuperare l’id della chat da cui stiamo ricevendo il comando.
  • reply_text è un’utility per poter rispondere velocemente al messaggio ricevuto.

Per mandare tutto in esecuzione, creiamo l’updater passandogli il token, ed accediamo al dispatcher collegato tramite il parametro dispatcher. Per passare gli handler dei comandi, la sintassi è add_handler(“comando“, callback). Una volta fatto ciò, mandiamo in esecuzione l’applicazione tramite start_polling ed idle.

updater = Updater(token)
updater.dispatcher.add_handler(CommandHandler("start", start))
updater.dispatcher.add_handler(CommandHandler("end", end))
updater.start_polling()
updater.idle()

Dove token è sempre una stringa contenente il token relativo al vostro bot. Potete trovare il codice completo di questo esempio a questo indirizzo.

Un webpage watcher

Abbiamo visto le basi dell’utilizzo dei bot e dei comandi, ora proviamo a sporcarci un po’ le mani!

L’applicazione che voglio proporvi è il motivo per cui qualche anno fa mi ero imbattuto nelle API dei bot di Telegram, ed è una semplice app che monitora una pagina web per eventuali update. Avevo utilizzato questo tipo di approccio per stare in attesa dei risultati di esami che venivano pubblicati sull’home page del docente.

In questo esempio l’intervallo di controllo degli aggiornamenti e l’url della pagina sono predefiniti, per semplicità:  in futuro vedremo come modificare l’applicazione per passare queste configurazioni tramite bot.

L’idea è la seguente: un Thread in background va ad effettuare il controllo ad intervalli regolari sulla pagina target,  ma solo se almeno un utente ha attivato il bot. Implementeremo il controllo semplicemente andando a verificare che la risposta alla HTTP GET della pagina target sia diversa da quella registrata precedentemente.

Ad esempio il controllo potrebbe avere questo aspetto:

def page_updated():
    interval = 5
    older = requests.get(target_url).text

    while True:
        if len(chat_ids) > 0:
            page_data = requests.get(target_url).text
            if page_data != older:
                older = page_data
                for chat_id in chat_ids:
                    updater.bot.send_message(chat_id=chat_id, text="Pagina aggiornata!")
        time.sleep(interval)

Se la pagina è effettivamente stata modificata, riceveremo una notifica tramite il bot. Per fare sì che il bot sappia risponderci in un secondo momento rispetto alla start, salviamo l’id della chat in un set quando il bot riceve un comando /start. Rimuoveremo poi l’id alla ricezione di un comando /end.

chat_ids = set()
def start(update, context): chat_id = update.effective_chat.id chat_ids.add(chat_id) def end(update, context): chat_id = update.effective_chat.id chat_ids.remove(chat_id)

Potete trovare il codice completo di questo esempio a questo indirizzo.

Conclusioni

In questo articolo abbiamo visto tante cose basilari ma interessanti per quanto riguarda il mondo dei bot Telegram e la loro gestione via Python. Come al solito ho condiviso tutto il codice relativo agli esempi trattati nell’articolo in una repository sul GitHub di antima.it. Vi invito a clonare la repo e sperimentare con gli esempi, sostituendo il token del vostro bot all’interno di ogni file.

Per questo articolo è tutto, per eventuali approfondimenti o richieste di chiarimenti vi invito come al solito a commentare nella sezione qui sotto!

Scrivi un commento

Commento

  1. pip install python-telegram-bot
    Su pycharm mi installa un’altra versione , la quale non funziona con i comandi descritti da te… hai una soluzione? Grazie

    • Ciao, ho provato a riprodurre il problema ma non riesco ad ottenere lo stesso errore, puoi fornirmi qualche informazione in più, tipo che versione di python stai utilizzando, quale versione ti installa della libreria o se sei dentro un ambiente virtuale?

  2. Ciao
    Ti ringrazio per l’esempio, grazie al tuo codice sono riuscito a comprendere un pò il funzionamento.
    Mi sono arenato su 2 punti:
    1)Mi chiedevo se fosse possibile inviare un messaggio senza attendere che dal bot venga fatta richiesta con “\”
    2)Il mio scopo è che data una condizione raggiunta il bot mi invii un messaggio con questo dato, ho un ciclo while che crea un loop in cui viene stampato un prezzo, se questo prezzo raggiunge un prezzo impostato vorrei mi inviasse sul bot un messaggio con il prezzo.
    Grazie