Skip to main content
When the IDS detects an intrusion, it sends an alert to one or more Telegram chats. Alerts are delivered asynchronously so the packet sniffer is never blocked waiting for an HTTP response.

Create a bot

1

Open @BotFather

Start a conversation with @BotFather in Telegram and send /newbot.
2

Name your bot

Follow the prompts to choose a name and username for the bot. BotFather replies with your BOT_TOKEN — a string in the format <numeric_id>:<alphanumeric_hash>.
3

Get your chat ID

Send any message to your bot, then open the following URL in a browser (replace <BOT_TOKEN> with your actual token):
https://api.telegram.org/bot<BOT_TOKEN>/getUpdates
Look for the "id" field inside the "chat" object in the response. That integer is your chat_id.

Configuration

Open telegram_alert.py and set the two constants at the top of the file:
telegram_alert.py
# Token from @BotFather
BOT_TOKEN = "<your_bot_token>"

# One or more Telegram chat IDs (one per admin or group)
CHAT_IDS = [1016030596]
  • BOT_TOKEN — the credential that identifies your bot to the Telegram API.
  • CHAT_IDS — a list of integers. Add multiple IDs to notify several administrators or groups with every alert.
Never commit BOT_TOKEN to source control. In production, load it from an environment variable:
import os
BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]

How enviar_alerta works

enviar_alerta(mensaje) iterates over every ID in CHAT_IDS and sends an HTTP POST to the Telegram Bot API:
telegram_alert.py
def enviar_alerta(mensaje):
    url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"

    for chat_id in CHAT_IDS:
        data = {
            "chat_id": chat_id,
            "text": mensaje
        }

        try:
            response = requests.post(url, data=data)

            if response.status_code == 200:
                print(f"📨 Alerta enviada a Telegram (chat_id {chat_id}) con éxito.")
            else:
                print(f"[X] Error al enviar alerta a {chat_id}: {response.text}")

        except Exception as e:
            print(f"[X] Excepción al enviar alerta a {chat_id}: {e}")
The request body uses application/x-www-form-urlencoded (the data= parameter), which is the format the Telegram Bot API expects.

Alert message format

Alerts are composed inside guardar_ataque in ids.py using the detected event fields:
SISTEMA DE INTRUSIÓN:
ALERT [IDS] <tipo_final> detectado
IP Origen: <ip_src>
Protocolo: <protocolo>
Puerto Destino: <puerto>
IP Destino: <ip_dst>
tipo_final contains either the ML verdict with confidence score (e.g., SYN Flood (ML: 94.3%)) or the heuristic label (e.g., SYN Flood (Heurística)).

Async delivery

Telegram HTTP calls can take 1–5 seconds. Running them on the sniffer thread would drop packets during that window. _enviar_alerta_async wraps enviar_alerta in a short-lived daemon thread so the call returns immediately:
ids.py
def _enviar_alerta_async(mensaje: str):
    Thread(target=lambda: enviar_alerta(mensaje), daemon=True).start()
Using daemon=True means these threads are automatically killed when the main process exits — they will never hold the process open after the sniffer shuts down.

Error handling

Both network errors and API errors are caught inside enviar_alerta and printed to the console. A failed Telegram delivery does not raise an exception back to guardar_ataque, so a connectivity problem never interrupts detection or logging.

Test the bot

Run telegram_alert.py directly to send a test message to every configured chat_id:
python telegram_alert.py
This executes the if __name__ == "__main__": block, which calls enviar_alerta("[ALERT] Prueba de alerta desde mi bot!"). If the message arrives in Telegram, your token and chat IDs are correct.

Build docs developers (and LLMs) love