← Tutti i progetti
Personale 📅 2026 GitHub

Bot Tracker Biglietti Concerti

Bot Telegram che monitora la disponibilità di biglietti su FanSale (rivendita) e TicketOne (primaria) e notifica l'utente appena un biglietto per la data tracciata diventa disponibile. Tre componenti disaccoppiati: API di scraping, bot e worker asincrono.

✦ Caching per-artista per minimizzare le richieste✦ Fallback anti-bot a due livelli✦ Reverse engineering documentato dei siti

Contesto

Comprare biglietti per i concerti su siti di rivendita come FanSale è una corsa contro il tempo: i biglietti compaiono e spariscono in minuti. Il progetto è un bot Telegram che permette di impostare “tracker” su date specifiche e notifica appena un biglietto diventa disponibile.

Il sistema doveva essere efficiente (poche richieste ai siti, rischio di blocco anti-bot) e manutenibile (i siti cambiano struttura HTML e API continuamente).

Architettura

Il sistema è progettato come tre componenti disaccoppiati, ciascuno con una responsabilità chiara:

flowchart LR
  U["Utente Telegram"] <--> B["Bot Telegram<br/>python-telegram-bot"]
  B -->|"scelte utente"| API["API FastAPI<br/>scraping centralizzato"]
  API -->|"scrapling / Playwright"| FAN["FanSale"]
  API -->|"API ufficiale"| T1["TicketOne"]
  W["Worker asincrono<br/>(asyncio)"] -->|"aggiornamenti periodici"| API
  W <--> DB[("SQLite<br/>artists / events / trackers")]
  B <--> DB

API, bot e worker: tre componenti che condividono il database

  1. Livello API (FastAPI). Interfaccia RESTful centralizzata per tutto lo scraping. Il bot non contiene logica di scraping: se un sito cambia struttura, si aggiorna solo l’endpoint. Lo scraping usa scrapling (httpx + selectolax) con fallback Playwright per contenuti caricati via JavaScript.

  2. Livello Bot (python-telegram-bot). ConversationHandler per flussi guidati a stati (aggiunta/rimozione tracker). Il bot è “stupido”: presenta informazioni e raccoglie scelte, tutta la logica di business è nell’API e negli helper.

  3. Livello Worker (asyncio). Esegue i task periodici in background: aggiorna i dati FanSale a intervalli brevi, i dati TicketOne ogni 24h (nuove date o cancellazioni), e processa le notifiche confrontando i dati aggiornati con i tracker degli utenti.

Ottimizzazione chiave: il caching nel database

Il problema: se 100 utenti tracciano 10 concerti diversi dello stesso artista, un approccio ingenuo farebbe 100 richieste alla stessa pagina FanSale. La soluzione:

  • Il worker esegue una sola richiesta per artista e salva la lista completa dei biglietti in JSON nel campo fansale_tickets_body della tabella artists.
  • Quando si controllano le notifiche, il sistema legge il dato in cache dal DB per tutti gli utenti, senza più contattare FanSale.

Riduce drasticamente il numero di richieste e il rischio di essere bloccati, a costo di una latenza di aggiornamento pari all’intervallo del worker (configurabile).

Strategia anti-bot

Il reverse engineering dei siti è documentato nel repository: su FanSale, Playwright headless intercetta solo la challenge Akamai e poi Access Denied; curl_cffi con impersonazione safari17_0 riceve invece l’HTML reale. Lo scraper prova quindi prima la strada leggera e usa Playwright solo come fallback. Due script di discovery (tools/) permettono di ispezionare endpoint nascosti senza toccare il bot produttivo.

Scelte progettuali

  • API separata dal bot: disaccoppiamento che rende lo scraping riusabile (futura dashboard/mobile) e isolato da modifiche dei siti.
  • Aggiornamenti in batch: prima l’aggiornamento di massa di artisti/eventi, poi l’elaborazione notifiche — non un controllo tracker per tracker.
  • Query efficienti: get_all_active_trackers_efficiently() carica i dati degli artisti (con i body cache) e li unisce in Python con i tracker, invece di JOIN complessi per utente.

Risultati

Un sistema funzionante end-to-end: l’utente cerca l’artista/tour via API TicketOne, seleziona l’evento e la data, e riceve notifiche Telegram istantanee quando il biglietto compare su FanSale. Docker Compose per l’avvio dell’intero stack.

Link