Per il linguaggio PHP esistono molte alternative per la
realizzazione di TelegramBot. La documentazione ufficiale
ne mostra un elenco. Solo per citarne alcune, tra le varie soluzioni troviamo:
Si tratta comunque di meccanismi che utilizzano la comunicazione via HTTP per raggiungere il sistema di API di
Telegram e poter scambiare messaggi. Nel caso del linguaggio PHP, per scegliere la libreria che più fa al proprio caso conviene
valutare una serie di aspetti. In primis, la ricchezza di funzionalità implementate e la sinteticità del codice che risulta
necessario utilizzare. Inoltre, dato il massiccio impiego di PHP nella realizzazione di siti web, l'integrabilità di
tali librerie in framework quali Symfony e
Laravel. Molte di esse infatti nascono già
con una innata predisposizione per l'integrazione in questi ambienti o leggendo la documentazione della libreria
si vede come gli autori si siano premurati di fornire istruzioni in merito.
Primo esempio: servizio echo
Tra le varie alternative abbiamo scelto di utilizzare per il nostro esempio il Bot API PHP SDK.
Come molte altre librerie, si tratta di un wrapper che permette al programmatore di dialogare con le API Telegram in una maniera
più comoda passando per una serie di metodi di utilità: a livello concettuale, tutto quello che faremo sarà applicabile anche alle
altre librerie.
Questa libreria potrà esse installata velocemente mediante Composer con
la seguente direttiva:
composer require irazasyed/telegram-bot-sdk ^2.0
Come già spiegato nella guida, è necessario creare un
nuovo TelegramBot presso il BotFather ottenendo una chiave di autenticazione in formato alfanumerico. Per iniziare ad usare la libreria
dovremo importare il file autoload.php, secondo la consueta prassi di Composer, ed importare la classe Api.
Infine, creeremo un'istanza di quest'ultima al cui costruttore forniremo la chiave prodotta dal BotFather:
<?php
require 'vendor/autoload.php';
use Telegram\Bot\Api;
$client = new Api('123456789ABCDEFGHI');
/*
* Codice per l'implementazione del Bot
*
*/
?>
Tramite l'oggetto $client potremo inoltrare le richieste da svolgere verso le API di Telegram. La chiave indicata (123456789ABCDEFGHI)
è un codice fittizio impostato come segnaposto che andrà opportunamente sostituito con quello prodotto dal BotFather al momento dell'utilizzo.
I metodi della classe Api richiamano quelli HTTP delle API. Ad esempio, il codice che segue produce un effetto "echo" ovvero restituisce
in output all'utente lo stesso messaggio che egli gli ha inviato.
<?php
require 'vendor/autoload.php';
use Telegram\Bot\Api;
// creazione dell'oggetto client
$client = new Api('123456789ABCDEFGHI');
/* per l'attivazione del long polling memorizziamo
l'id dell'ultimo update elaborato */
$last_update_id=0;
while(true){
// leggiamo gli ultimi update ottenuti
$response = $client->getUpdates(['offset'=>$last_update_id, 'timeout'=>5]);
if (count($response)<=0) continue;
/* per ogni update scaricato restituiamo il messaggio
sulla stessa chat su cui è stato ricevuto */
foreach ($response as $r){
$last_update_id=$r->getUpdateId()+1;
$message=$r->getMessage();
$chatId=$message->getChat()->getId();
$text=$message->getText();
$response = $client->sendMessage([
'chat_id' => $chatId,
'text' => 'Hai scritto: '.$text
]);
}
}
?>
Tale codice può essere riportato in un file php ed avviato mediante l'interprete. Nel nostro caso, l'abbiamo
chiamato echo_bot.php e l'abbiamo avviato da riga di comando con:
php echo_bot.php
L'utilizzo da riga di comando, come si può immaginare, è a solo scopo esemplificativo ma tali librerie possono essere
impiegate anche in applicazioni web soprattutto con un linguaggio particolarmente adatto come PHP.
Al fine di mantenere attivo il servizio abbiamo utilizzato un ciclo infinito con while(true) riservandoci però di richiedere ad
ogni iterazione solo gli update più recenti mediante la memorizzazione degli id degli ultimi consultati.
I metodi che abbiamo invocato della libreria sono essenzialmente due:
- getUpdates con sui scarichiamo gli aggiornamenti che il Bot ha ricevuto. Come parametri passiamo offset che servirà per
specificare qual è il primo update che vogliamo scaricare, ciò al fine di evitare di ricevere ogni volta l'intera lista di messaggi
che Telegram custodisce attualmente. Il parametro timeout serve per cadenzare le comunicazioni evitando un polling troppo intenso; - sendMessage che viene utilizzato per rispondere al messaggio ricevuto. Per ogni messaggio da inviare, si dovrà specificare
la chat su cui rispondere (identificata mediante l'id) ed il testo da restituire.
Notare come con la libreria ci si possa muovere tra le informazioni mediante oggetti, rileggiamo il contenuto del ciclo foreach:
$message=$r->getMessage();
$chatId=$message->getChat()->getId();
$text=$message->getText();
L'oggetto $r è di classe Update e contiene tutto ciò che l'utente ha inviato mediante messaggio al Bot. Con il metodo getMessage
estraiamo tutte le informazioni relative al messaggio dall'update. Ottenuto il messaggio possiamo arrivare alla chat e poi al suo id con
getChat mentre con getText otteniamo il testo del messaggio. Per avere, altrimenti, l'id dell'update stesso non serve esplorare l'oggetto messaggio
ma basta invocare getUpdateId direttamente su $r.
Il convertitore di valute
Concludiamo il tutto a questo punto con un esempio leggermente più completo in cui creiamo un piccolo convertitore di valute euro/dollaro.
Questo utilizzerà un valore fisso memorizzato in una costante per trasformare i valori da una valuta all'altra.
Useremo comandi di nostra invenzione: /usd per convertire l'importo passato da dollari a euro e viceversa /eur per passare euro in dollari.
Ecco il codice:
require 'vendor/autoload.php';
use Telegram\Bot\Api;
// tasso di conversione che adottiamo per l'esempio
$EXCHANGE=1.125;
// creazione dell'oggetto client
$client = new Api('123456789ABCDEFGHI');
function conversione($testo){
global $EXCHANGE;
if (!preg_match('/^\/(usd|eur) [0-9]+(\.[0-9]+)?$/', $testo))
return "ERRORE: formato non valido";
$testo=substr($testo, 1);
list($comando, $valore)=explode(" ", $testo);
switch($comando){
case "eur":
return ($valore*$EXCHANGE)." USD";
break;
case "usd":
return ($valore/$EXCHANGE)." EUR";
}
}
/* per l'attivazione del long polling memorizziamo
l'id dell'ultimo update elaborato */
$last_update_id=0;
while(true){
// leggiamo gli ultimi update ottenuti
$response = $client->getUpdates(['offset'=>$last_update_id, 'timeout'=>5]);
if (count($response)<=0) continue;
/* per ogni update scaricato restituiamo il messaggio
sulla stessa chat su cui è stato ricevuto */
foreach ($response as $r){
$last_update_id=$r->getUpdateId()+1;
$message=$r->getMessage();
$chatId=$message->getChat()->getId();
$text=$message->getText();
$controvalore=conversione($text);
$response = $client->sendMessage([
'chat_id' => $chatId,
'text' => $controvalore
]);
}
}
L'immagine mostra il funzionamento del Bot. Il codice ha una struttura simile all'esempio precedente tranne per il fatto che facciamo intervenire
la funzione conversione che elabora il comando inviato e trasforma il valore da una valuta all'altra.