\n\n\n\n Il mio viaggio con l'API Bot di Telegram: Oltre le semplici notifiche - AI7Bot \n

Il mio viaggio con l’API Bot di Telegram: Oltre le semplici notifiche

📖 12 min read2,291 wordsUpdated Apr 3, 2026

Ciao a tutti, Marcus qui da ai7bot.com. È il 20 marzo 2026 e ultimamente penso molto a qualcosa che è diventato un po’ un cavallo di battaglia silenzioso nel mondo dei bot: il Telegram Bot API. Non è il più nuovo della piazza, né così appariscente come alcuni framework di intelligenza artificiale che fanno notizia, ma, cavolo, è potente e, cosa più importante, incredibilmente accessibile. Oggi voglio parlare di come il Telegram Bot API non sia più solo per notifiche semplici. Esploreremo come puoi usarlo per costruire strumenti interattivi sorprendentemente sofisticati – specificamente, un’esperienza utente a più fasi per la raccolta di dati o l’esecuzione di comandi complessi. Dimentica quegli esempi di “invia un messaggio”; stiamo cercando qualcosa di più sostanzioso.

Ricordo il mio primo approccio ai bot di Telegram nel 2018. Ho costruito un bot super semplice che semplicemente replicava qualsiasi cosa gli inviassi. Rivoluzionario, lo so. Ma anche allora, la semplicità di iniziare con l’API era notevole. Oggi, l’ho usato per tutto, da strumenti interni per il team che tracciano aggiornamenti di progetto a un bot che mi aiuta a gestire il mio backlog di articoli da scrivere in continua crescita. Ciò che spesso viene trascurato è quanto bene Telegram abbia costruito la sua API per gestire interazioni complesse senza farti strappare i capelli. Stiamo parlando di gestione dello stato, tastiere inline e tastiere personalizzate – tutti gli ingredienti per un’esperienza di bot davvero coinvolgente.

Oltre i Comandi Semplici: Costruire un Flusso di Lavoro a Più Fasi

Il maggior ostacolo che le persone affrontano quando si passa oltre ai semplici “comandi slash” è gestire il contesto. Se il tuo bot fa una domanda, come può sapere che il prossimo messaggio dell’utente è la risposta a quella specifica domanda, e non un nuovo comando o un pensiero a caso? Qui entra in gioco la gestione dello stato. Non stiamo parlando di un database completo, anche se potresti sicuramente integrarne uno. Per molte applicazioni, un semplice dizionario in memoria o uno store chiave-valore leggero è perfettamente sufficiente.

Immaginiamo di voler costruire un bot che aiuti un utente a registrare un nuovo “compito” o “idea.” Deve chiedere un titolo, poi una descrizione, poi forse un livello di priorità. Tre passaggi distinti, tre pezzi distinti di informazioni che dobbiamo raccogliere in ordine. Se abbiamo solo un gruppo di /start e /log comandi, diventa rapidamente ingombrante.

L’Idea Centrale: Stato dell’Utente e Flusso della Conversazione

Il mio approccio prevede di solito il mantenimento di un dizionario in cui la chiave è l’ID dell’utente e il valore è un oggetto che rappresenta il loro attuale stato di conversazione. Questo oggetto di stato può contenere:

  • current_step: Un enum o una stringa che indica dove si trovano nel flusso di lavoro (ad es., ‘AWAITING_TITLE’, ‘AWAITING_DESCRIPTION’).
  • temp_data: Un dizionario per memorizzare i pezzi di informazione raccolti finora per il flusso di lavoro attuale (ad es., {'title': 'La mia nuova idea', 'description': ''}).

Quando arriva un messaggio, il bot controlla lo stato dell’utente. Se si trova in uno specifico passaggio del flusso di lavoro, elabora il loro messaggio come input per quel passaggio. Se no, lo tratta come un comando generale.

Esempio Pratico: Un Semplice Bot per Registrare Compiti

Mettiamoci al lavoro. Costruiremo un bot per registrare compiti molto semplificato. L’utente inizierà un comando “nuovo compito”, il bot chiederà un titolo, poi una descrizione e infine confermerà. Per semplicità, memorizzeremo lo stato in un dizionario Python. Per la produzione, probabilmente vorresti qualcosa di più persistente come Redis o un piccolo database SQLite.

Configurare il Tuo Bot e Ottenere il Token API

Prima di tutto, hai bisogno di un bot. Vai su BotFather su Telegram (cerca @BotFather), invialo /newbot, segui le istruzioni e ti darà un token API. Tieni quel token segreto!

Utilizzeremo la libreria python-telegram-bot, che semplifica notevolmente l’interazione con il Telegram Bot API. Installala con pip install python-telegram-bot.

La Struttura del Codice: Gestione dello Stato e Handler

Ecco uno scheletro di base per il nostro bot. Nota come utilizzeremo un dizionario globale user_states per tenere traccia di dove si trova ogni utente nella loro conversazione. In uno scenario reale, vorresti preservarlo tra i riavvii del bot.


from telegram import Update, ForceReply
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes

# Sostituisci con il tuo token bot reale
BOT_TOKEN = "YOUR_BOT_TOKEN_HERE"

# --- Gestione dello Stato dell'Utente ---
# In un'app reale, questo sarebbe persistente (es., Redis, database)
user_states = {}

# Definire stati per il nostro flusso di lavoro
STATE_NONE = 0
STATE_AWAITING_TITLE = 1
STATE_AWAITING_DESCRIPTION = 2

# --- Comandi del Bot ---

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Invia un messaggio di benvenuto quando viene emesso il comando /start."""
 user_id = update.effective_user.id
 user_states[user_id] = {'current_step': STATE_NONE, 'task_data': {}}
 await update.message.reply_text('Ciao! Sono il tuo bot per registrare compiti. Usa /new_task per iniziare a registrare un compito.')

async def new_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Inizia il flusso di lavoro per il nuovo compito."""
 user_id = update.effective_user.id
 user_states[user_id] = {'current_step': STATE_AWAITING_TITLE, 'task_data': {}}
 await update.message.reply_text('Bene, creiamo un nuovo compito. Qual è il titolo?')

# --- Handler dei Messaggi per i Passaggi di Lavoro ---

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Gestisce tutti i messaggi in arrivo e li indirizza in base allo stato dell'utente."""
 user_id = update.effective_user.id
 text = update.message.text

 current_state = user_states.get(user_id, {'current_step': STATE_NONE})['current_step']
 task_data = user_states.get(user_id, {'task_data': {}})['task_data']

 if current_state == STATE_AWAITING_TITLE:
 task_data['title'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_AWAITING_DESCRIPTION
 await update.message.reply_text(f'Ricevuto. Titolo: "{text}". Ora, per favore fornisci una descrizione per il compito.')
 
 elif current_state == STATE_AWAITING_DESCRIPTION:
 task_data['description'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_NONE # Reset stato
 
 # Qui di solito salveresti task_data in un database o file
 await update.message.reply_text(
 f'Compito creato!\nTitolo: {task_data["title"]}\nDescrizione: {task_data["description"]}\n\n'
 f'Puoi iniziare un nuovo compito con /new_task.'
 )
 # Azzerare i dati del compito per questo utente
 user_states[user_id]['task_data'] = {}
 
 else:
 # Se non è attivo un flusso di lavoro specifico, rispondi con un messaggio predefinito
 await update.message.reply_text('Non capisco. Prova /new_task per iniziare a creare un compito.')

# --- Configurazione Principale del Bot ---

def main() -> None:
 """Avvia il bot."""
 application = Application.builder().token(BOT_TOKEN).build()

 # Registrare gli handler
 application.add_handler(CommandHandler("start", start))
 application.add_handler(CommandHandler("new_task", new_task))
 application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))

 # Esegui il bot fino a quando l'utente preme Ctrl-C
 application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
 main()

Alcune cose da notare qui:

  • user_states: Questo dizionario è la nostra semplice macchina a stati. Ogni ID utente mappa al loro passaggio attuale e ai dati raccolti.
  • start e new_task comandi: Questi iniziano o ripristinano lo stato. new_task imposta specificamente lo stato dell’utente a STATE_AWAITING_TITLE.
  • handle_message: Questo è il motore. Controlla lo stato attuale dell’utente e agisce di conseguenza. Se è STATE_AWAITING_TITLE, assume che il messaggio sia il titolo. Se è STATE_AWAITING_DESCRIPTION, assume che il messaggio sia la descrizione. Dopo aver raccolto tutte le informazioni, ripristina lo stato a STATE_NONE.
  • filters.TEXT & ~filters.COMMAND: Questo è cruciale per handle_message. Assicura che questo handler elabori solo messaggi di testo semplici che NON sono comandi (come /start o /new_task), evitando conflitti con i nostri handler di comando.

Aggiungere un Tocco di Interattività: Tastiere Inline per Conferma

Invece di chiedere semplicemente una descrizione, cosa succederebbe se volessimo chiedere un livello di priorità e fornire all’utente opzioni predefinite? Ecco dove brillano le Tastiere Inline di Telegram. Appaiono direttamente attaccate a un messaggio e inviano “dati di callback” quando vengono toccate, piuttosto che un messaggio completo.

Modifichiamo il nostro flusso di lavoro per chiedere la priorità utilizzando una tastiera inline dopo la descrizione.


from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, CallbackQueryHandler, filters, ContextTypes

# ... (BOT_TOKEN, user_states, STATE_NONE, STATE_AWAITING_TITLE, STATE_AWAITING_DESCRIPTION) ...

STATE_AWAITING_PRIORITY = 3 # Nuovo stato

# ... (i comandi start e new_task rimangono gli stessi) ...

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 user_id = update.effective_user.id
 text = update.message.text

 current_state = user_states.get(user_id, {'current_step': STATE_NONE})['current_step']
 task_data = user_states.get(user_id, {'task_data': {}})['task_data']

 if current_state == STATE_AWAITING_TITLE:
 task_data['title'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_AWAITING_DESCRIPTION
 await update.message.reply_text(f'Ricevuto. Titolo: "{text}". Ora, per favore forniscimi una descrizione per il compito.')
 
 elif current_state == STATE_AWAITING_DESCRIPTION:
 task_data['description'] = text
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_AWAITING_PRIORITY # Passa al nuovo stato
 
 keyboard = [
 [InlineKeyboardButton("Alta", callback_data="priority_high")],
 [InlineKeyboardButton("Media", callback_data="priority_medium")],
 [InlineKeyboardButton("Bassa", callback_data="priority_low")],
 ]
 reply_markup = InlineKeyboardMarkup(keyboard)
 await update.message.reply_text('Grazie per la descrizione! Qual è la priorità per questo compito?', reply_markup=reply_markup)
 
 else:
 await update.message.reply_text('Non capisco. Prova /new_task per iniziare a creare un compito.')

async def handle_callback_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 """Gestisce la pressione dei pulsanti della tastiera inline."""
 query = update.callback_query
 await query.answer() # Rispondi sempre alle query di callback, anche se vuote

 user_id = query.from_user.id
 data = query.data # Questo è il callback_data che abbiamo definito nei pulsanti

 current_state = user_states.get(user_id, {'current_step': STATE_NONE})['current_step']
 task_data = user_states.get(user_id, {'task_data': {}})['task_data']

 if current_state == STATE_AWAITING_PRIORITY and data.startswith('priority_'):
 task_data['priority'] = data.split('_')[1] # Estrai 'high', 'medium', 'low'
 user_states[user_id]['task_data'] = task_data
 user_states[user_id]['current_step'] = STATE_NONE # Reimposta lo stato
 
 # Modifica il messaggio per rimuovere la tastiera e mostrare conferma
 await query.edit_message_text(
 f'Compito creato!\nTitolo: {task_data["title"]}\nDescrizione: {task_data["description"]}\n'
 f'Priorità: {task_data["priority"].capitalize()}\n\nPuoi iniziare un nuovo compito con /new_task.'
 )
 # Cancella i dati del compito per questo utente
 user_states[user_id]['task_data'] = {}
 else:
 await query.edit_message_text('Qualcosa è andato storto o la tua sessione è scaduta. Per favore inizia di nuovo con /new_task.')

# --- Configurazione principale del bot (aggiornata) ---

def main() -> None:
 application = Application.builder().token(BOT_TOKEN).build()

 application.add_handler(CommandHandler("start", start))
 application.add_handler(CommandHandler("new_task", new_task))
 application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
 application.add_handler(CallbackQueryHandler(handle_callback_query)) # Nuovo gestore per i pulsanti inline

 application.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == "__main__":
 main()

Le aggiunte chiave qui sono:

  • STATE_AWAITING_PRIORITY: Un nuovo stato da gestire.
  • InlineKeyboardButton e InlineKeyboardMarkup: Utilizzati per costruire i pulsanti interattivi.
  • callback_data: Una stringa associata a ciascun pulsante. È ciò che viene inviato di nuovo al tuo bot quando il pulsante viene premuto. È limitato a 64 byte, quindi mantienilo conciso.
  • CallbackQueryHandler: Un nuovo tipo di gestore nella nostra configurazione principale, specificamente per ascoltare queste pressioni dei pulsanti inline.
  • query.answer(): Importante per l’UX. Telegram si aspetta una risposta rapida a una query di callback, anche se è vuota, per mostrare all’utente che il suo tocco è stato registrato.
  • query.edit_message_text(): Invece di inviare un nuovo messaggio, aggiorniamo quello esistente. Questo rende il flusso della conversazione molto più pulito, poiché la tastiera inline scompare una volta che viene effettuata una scelta.

Questo approccio trasforma una serie di prompt testuali potenzialmente ingombrante in un’esperienza molto più intuitiva e amichevole per l’utente. Immagina di espandere questo alla selezione di categorie, date da un selettore di calendario (utilizzando più pulsanti inline) o alla conferma delle azioni prima che vengano eseguite.

Conclusioni pratiche per il tuo prossimo progetto bot

  1. Abbraccia la gestione degli stati precocemente: Per qualsiasi cosa oltre ai bot a comando singolo, dovrai monitorare lo stato degli utenti. Inizia semplice con un dizionario, ma pianifica una persistenza se il tuo bot deve ricordare le conversazioni attraverso i riavvii.
  2. Usa gli elementi UI di Telegram: Le tastiere inline e le tastiere di risposta personalizzate sono incredibilmente potenti per guidare gli utenti, offrire scelte e semplificare l’immissione. Non far digitare tutto agli utenti se puoi offrire un pulsante.
  3. Modularizza i tuoi gestori: Man mano che il tuo bot cresce, separa la logica in funzioni distinte o addirittura in moduli. Una gigantesca funzione handle_message diventa rapidamente ingestibile.
  4. Gestisci i casi limite e i ripristini: Cosa succede se un utente digita /new_task nel mezzo di un altro flusso di lavoro? E se smettono di rispondere? Implementa modi per ripristinare le conversazioni in modo elegante o riportarli nel flusso. Il mio esempio gestisce implicitamente questo ripristinando lo stato con /new_task.
  5. Testa, testa, testa: Usa un bot di test (da BotFather) per lo sviluppo. Testa diversi flussi utente, input imprevisti e utilizzo concorrente.

L’API di Telegram Bot, specialmente con librerie come python-telegram-bot, offre un fantastico campo di gioco per costruire applicazioni interattive. Non è solo per inviare immagini di gatti; puoi costruire strumenti realmente utili con sorprendentemente poco sforzo. Quindi, vai avanti, sperimenta con questi concetti e costruisci qualcosa di interessante!

Articoli correlati

🕒 Published:

💬
Written by Jake Chen

Bot developer who has built 50+ chatbots across Discord, Telegram, Slack, and WhatsApp. Specializes in conversational AI and NLP.

Learn more →
Browse Topics: Best Practices | Bot Building | Bot Development | Business | Operations
Scroll to Top