Script Python per comporre e inviare su Telegram messaggi calendarizzati, a partire da un calendario JSONL e, opzionalmente, da una configurazione YAML per header e footer. Include anche una piccola UI Streamlit per modificare i file JSONL prima dell'invio schedulato.
Python script to compose and send scheduled Telegram messages, using a JSONL calendar and, optionally, a YAML configuration file for header and footer. It also includes a small Streamlit UI to edit JSONL files before scheduled sending.
- Applicazione CLI in Python.
- Calendario JSONL usato come sorgente dati append-friendly.
- Configurazione YAML opzionale separata dai dati del calendario.
- Gestione dei secret tramite variabili d'ambiente.
- Integrazione con Telegram Bot API.
- UI Streamlit per modificare i calendari JSONL.
- Modalita
--dry-runper validare il messaggio senza effetti collaterali. - Tracciamento dello stato di invio tramite
inviatoemessage_id. - Blocco dell'invio se il messaggio contiene marker di verifica.
- Schedulazione tramite GitHub Actions.
L'AI e stata usata come supporto allo sviluppo per revisione del codice, documentazione, progettazione dei test e rifinitura della struttura del progetto.
Nell'uso in produzione puo essere impiegata anche come supporto alla preparazione del calendario JSONL, mantenendo comunque una revisione manuale prima dell'invio dei messaggi.
Calendario JSONL
|
Configurazione YAML opzionale + variabili d'ambiente
|
tabula.py
|
Telegram Bot API
|
Canale o chat Telegram
tabula.py legge il primo elemento del calendario con inviato: false, genera il messaggio, chiede conferma e lo invia tramite Telegram. Se viene passato --more, aggiunge header e footer dal file YAML. Dopo l'invio aggiorna la riga del calendario impostando inviato: true e salvando il message_id restituito da Telegram.
ui.py e separato dal flusso di invio: serve solo a scegliere e modificare un file JSONL. Lo script tabula.py resta il punto di ingresso per invio manuale o schedulato.
- Python 3
- Un bot Telegram
- Un
chat_idTelegram valido - Un
chat_idpersonale opzionale per ricevere avvisi quando un invio viene bloccato
Installa le dipendenze:
pip install -r requirements.txtLa cartella examples contiene modelli pronti da copiare o adattare:
examples/calendario.jsonl: calendario in formato JSONLexamples/tabula.yaml: configurazione opzionale di header e footerexamples/.env.example: variabili d'ambiente richieste
Avvia la UI con:
streamlit run ui.pyAll'avvio compare solo il selettore del file calendario. La UI cerca file .jsonl nelle cartelle data/ ed examples/. Dopo la selezione mostra l'elenco dei periodi e l'editor del testo.
Nell'editor, una riga vuota separa i blocchi di messaggio. I blocchi vuoti vengono scartati al salvataggio:
Messaggio 1
Messaggio 2
viene salvato come:
"messaggi": ["Messaggio 1", "Messaggio 2"]La UI non invia messaggi Telegram e non richiede token.
Esempio:
message:
header: "*Aggiornamenti settimanali*"
footer: "---\nPer contatti: info@example.org"Campi usati dallo script quando viene passata l'opzione --more:
message.header: intestazione del messaggio Telegrammessage.footer: testo finale del messaggio Telegram
Ogni riga del file calendario è un oggetto JSON indipendente.
{"inviato": false, "valido-da": "2026-06-07", "valido-a": "2026-06-13", "messaggi": ["*Lunedi 8/06 - Stand-up team prodotto*\n9:30 - Canale operativo\n\n*Mercoledi 10/06 - Revisione roadmap*\n15:00 - Sala riunioni virtuale"]}Campi:
inviato:falsese il messaggio deve ancora essere inviato,truedopo l'inviovalido-da: data di inizio validita nel formatoYYYY-MM-DDvalido-a: data di fine validita nel formatoYYYY-MM-DDmessaggi: elenco dei blocchi di testo da inserire nel messaggiomessage_id: identificativo Telegram del messaggio inviato, aggiunto o aggiornato dallo script
Se un blocco in messaggi contiene il marker ???, l'invio viene bloccato. In questo caso il messaggio non viene pubblicato sul canale Telegram.
Lo script richiede:
TELEGRAM_BOT_TOKEN=1234567890:AAExampleTokenDaSostituire
TELEGRAM_CHAT_ID=-1001234567890
TELEGRAM_ALERT_CHAT_ID=123456789TELEGRAM_ALERT_CHAT_ID e opzionale ma consigliato per l'esecuzione schedulata: se un invio viene bloccato dalla validazione, il bot invia un messaggio di avviso a quella chat privata. Per ricevere messaggi privati dal bot, devi prima aprire Telegram e scrivere al bot almeno una volta.
Puoi caricarle da file con l'opzione -e:
python3 tabula.py -e examples/.env.example --more examples/tabula.yaml examples/calendario.jsonlPer verificare il messaggio senza inviarlo e senza modificare il calendario:
python3 tabula.py --dry-run examples/calendario.jsonlPer includere header e footer dal file YAML:
python3 tabula.py --dry-run --more examples/tabula.yaml examples/calendario.jsonlPer inviare senza richiesta di conferma:
python3 tabula.py -f -e config/.env.dev --more config/tabula.yaml data/2026.jsonlNon pubblicare token reali o file .env privati nel repository.
Il workflow .github/workflows/send.yml esegue l'invio ogni venerdi mattina:
06:00 UTC, cioe08:00in Italia durante l'ora legale e07:00in inverno- usa
config/tabula.yamledata/2026.jsonl - dopo un invio riuscito committa il calendario aggiornato con
inviato: trueemessage_id
Configura questi secret in GitHub, in Settings > Secrets and variables > Actions:
TELEGRAM_BOT_TOKEN
TELEGRAM_CHAT_ID
TELEGRAM_ALERT_CHAT_ID
- Validazione esplicita dei file JSONL/YAML con messaggi di errore chiari.
- Scrittura atomica del calendario per ridurre il rischio di corruzione del file durante l'aggiornamento.
- Miglioramento dell'escaping MarkdownV2 per Telegram.
- Link dinamico alla configurazione YAML, per poter richiamare oggetti definiti nel file YAML all'interno del file JSONL.
- Python CLI application.
- JSONL calendar used as an append-friendly data source.
- Optional YAML configuration separated from calendar data.
- Secret management through environment variables.
- Telegram Bot API integration.
- Streamlit UI to edit JSONL calendars.
--dry-runmode to validate messages without side effects.- Delivery state tracking through
inviatoandmessage_id. - Sending is blocked when the message contains review markers.
- Scheduled execution through GitHub Actions.
AI was used as a development assistant for code review, documentation, test design, and project structure refinement.
In production usage, it may also support the preparation of the JSONL calendar, with manual review before messages are sent.
JSONL calendar
|
Optional YAML configuration + environment variables
|
tabula.py
|
Telegram Bot API
|
Telegram channel or chat
tabula.py reads the first calendar entry with inviato: false, builds the Telegram message, asks for confirmation, and sends it through the Telegram Bot API. When --more is provided, it adds header and footer from the YAML file. After a successful send, it updates the calendar line by setting inviato: true and storing the Telegram message_id.
ui.py is separate from the sending flow: it only selects and edits a JSONL file. tabula.py remains the entry point for manual or scheduled sending.
- Python 3
- A Telegram bot
- A valid Telegram
chat_id - An optional personal
chat_idto receive alerts when a send is blocked
Install dependencies:
pip install -r requirements.txtThe examples directory contains templates that can be copied or adapted:
examples/calendario.jsonl: JSONL calendarexamples/tabula.yaml: optional header and footer configurationexamples/.env.example: required environment variables
Start the UI with:
streamlit run ui.pyAt startup, only the calendar file selector is shown. The UI looks for .jsonl files in data/ and examples/. After selecting a file, it shows the period list and text editor.
In the editor, an empty line separates message blocks. Empty blocks are discarded when saving:
Message 1
Message 2
is saved as:
"messaggi": ["Message 1", "Message 2"]The UI does not send Telegram messages and does not require tokens.
Example:
message:
header: "*Weekly Updates*"
footer: "---\nContacts: info@example.org"Fields used by the script when the --more option is provided:
message.header: Telegram message headermessage.footer: Telegram message footer
Each line in the calendar file is an independent JSON object.
{"inviato": false, "valido-da": "2026-06-07", "valido-a": "2026-06-13", "messaggi": ["*Monday 8/06 - Product team stand-up*\n9:30 - Operations channel\n\n*Wednesday 10/06 - Roadmap review*\n15:00 - Virtual meeting room"]}Fields:
inviato:falseif the message still has to be sent,trueafter sendingvalido-da: start date inYYYY-MM-DDformatvalido-a: end date inYYYY-MM-DDformatmessaggi: list of text blocks to include in the messagemessage_id: Telegram message identifier, added or updated by the script
If a block in messaggi contains the ??? marker, sending is blocked. In that case, the message is not published to the Telegram channel.
The script requires:
TELEGRAM_BOT_TOKEN=1234567890:AAExampleTokenToReplace
TELEGRAM_CHAT_ID=-1001234567890
TELEGRAM_ALERT_CHAT_ID=123456789TELEGRAM_ALERT_CHAT_ID is optional but recommended for scheduled runs: if a send is blocked by validation, the bot sends an alert message to that private chat. To receive private messages from the bot, you must first open Telegram and send the bot at least one message.
Load them from a file with -e:
python3 tabula.py -e examples/.env.example --more examples/tabula.yaml examples/calendario.jsonlPreview the message without sending it or updating the calendar:
python3 tabula.py --dry-run examples/calendario.jsonlInclude header and footer from the YAML file:
python3 tabula.py --dry-run --more examples/tabula.yaml examples/calendario.jsonlSend without confirmation:
python3 tabula.py -f -e config/.env.dev --more config/tabula.yaml data/2026.jsonlDo not publish real tokens or private .env files in the repository.
The .github/workflows/send.yml workflow runs the sender every Friday morning:
06:00 UTC, which is08:00in Italy during daylight saving time and07:00in winter- uses
config/tabula.yamlanddata/2026.jsonl - after a successful send, commits the updated calendar with
inviato: trueandmessage_id
Configure these secrets in GitHub, under Settings > Secrets and variables > Actions:
TELEGRAM_BOT_TOKEN
TELEGRAM_CHAT_ID
TELEGRAM_ALERT_CHAT_ID
- Explicit JSONL/YAML validation with clear error messages.
- Atomic calendar writes to reduce the risk of corrupting the file during updates.
- Improved MarkdownV2 escaping for Telegram.