Tempo fa avevo pubblicato qui una discussione sulla programmazione di un bot in Python ma non avevo parlato del lato hosting, estremamente importante per far funzionare il nostro bot!
Costruire un bot su Telegram richiede un servizio di hosting, anche gratuito se con flusso di richieste non troppo eccessivo. Ad esempio si possono utilizzare i "Workers" di Cloudflare.
Iniziamo registrandoci su Cloudflare poi andiamo nella sezione "Workers & Pages" e avviamo la nostra applicazione.
Completati questi passaggi vi si aprirà l'IDE di Cloudflare, questo è il vero e proprio spazio di sviluppo per il nostro bot.
Se non volete perdere tempo a scrivere sempre il TOKEN del bot per ogni istruzione vi conviene specificarlo nella sezioni variabili, quindi dashboard>settings>variabili:
Ricordatevi di chiamarla sempre "API_KEY".
Ora manca solo impostare il nostro endpoint Webhook sul nostro bot Telegram, per farlo:
https://api.telegram.org/bot{bot-token}/setWebhook?url={worker-url}
Dovrete riscrivere worker url con quella che trovate sotto "Preview" nella dashboard.
Ecco ad esempio il mio bot personale creato con questo metodo di hosting (nick: samueleexbot):
export default {
async fetch(request, env, ctx) {
if (request.method === "POST") {
const payload = await request.json();
if ('message' in payload && 'text' in payload.message) {
const chatId = payload.message.chat.id;
const messageText = payload.message.text;
if (messageText === '/start') {
const response = "Ciao! Ecco una lista di comandi utili:\n" +
"/chisono - Per conoscere di più su di me\n" +
"/links - Per i miei link\n" +
"/search - Ricerca sul forum di informatica!";
await this.sendMessage(env.API_KEY, chatId, response);
} else if (messageText === '/chisono') {
const info = "Sono uno studente dell'ITIS e mi appassiono alla programmazione frontend. Programmo in JavaScript ES6+, React.js, " +
"Node.js, React Native, TypeScript, Three.js, Python, C++, SQL e Next.js. Sono anche appassionato di cybersecurity.";
await this.sendMessage(env.API_KEY, chatId, info);
} else if (messageText === '/links') {
const buttons = {
inline_keyboard: [
[
{ text: "Forum IT", url: "https://ethicalhacking.freeflarum.com" },
{ text: "Portfolio", url: "https://samueleex.repl.co" }
],
[
{ text: "LinkedIn", url: "https://www.linkedin.com/in/samueleex/" },
{ text: "Instagram", url: "https://www.instagram.com/samuelee.x/" }
]
]
};
const response = "Ecco i miei link:";
await this.sendMessage(env.API_KEY, chatId, response, buttons);
} else if (messageText.startsWith('/search ')) {
const query = messageText.slice('/search '.length);
const searchUrl = `https://ethicalhacking.freeflarum.com/?q=${encodeURI(query)}`;
const response = `Ecco i risultati della ricerca sul forum di informatica: ${searchUrl}`;
await this.sendMessage(env.API_KEY, chatId, response);
}
}
}
return new Response('OK');
},
async sendMessage(apiKey, chatId, text, replyMarkup) {
const url = `https://api.telegram.org/bot${apiKey}/sendMessage`;
const data = {
chat_id: chatId,
text: text,
};
if (replyMarkup) {
data.reply_markup = JSON.stringify(replyMarkup);
}
await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
},
};
Si definisce un handler per gestire le richieste in arrivo e inviare risposte, fetch
serve per gestire le richieste in arrivo da Telegram, accetta tre parametri: request
, env
, e ctx
.
fetch
verifica se la richiesta è di tipo POST con if (request.method === "POST")
. Le richieste POST sono tipiche delle richieste inviate da Telegram ai webhook dei bot quando gli utenti inviano messaggi.
Se la richiesta è POST il bot legge la richiesta JSON con const payload = await request.json();
. La payload contiene i dati del messaggio inviato dall'utente.
Il bot verifica se la payload contiene un campo "message" e se quel campo contiene un campo "text".
Se il messaggio è di testo il bot estrae l'ID della chat e il testo del messaggio dal payload ed esegue i comandi.
sendMessage
serve per semplificare l'invio di messaggi e ha tre parametri: apiKey
(TOKEN), chatId
(LINK), text
(testo del messaggio da inviare) e replyMarkup
(per i bottoni inline).