How Telegram Bots Work Using Python and SQLite3

How Telegram Bots Work Using Python and SQLite3


Building Your First Telegram Bot with Python and SQLite3: A Step-by-Step Guide

Ever wanted to create your own automated assistant on Telegram? Telegram bots can automate tasks, provide information, play games, and much more. Python, with its rich ecosystem and straightforward syntax, is a fantastic language for bot development. Combined with SQLite3, a lightweight, built-in Python database module, you can easily store and manage user data or bot state.

This guide will walk you through creating a simple Telegram bot using the python-telegram-bot library and SQLite3 for basic data persistence. We'll cover everything from setting up your environment to handling user messages and storing information.

What You'll Need:

  • Python 3.x installed.
  • A Telegram account.
  • Basic understanding of Python programming.

Let's get started!

Step 1: Project Initialization and Setup

First, we need to set up our project directory and install the necessary library.

  1. Install the Library: Open your terminal or command prompt and install the python-telegram-bot library:

    Bash
    pip install python-telegram-bot
    

    (Note: sqlite3 is included with Python, so no separate installation is needed.)

  2. Create Project Structure: Organize your files logically. A good structure might be:

    Plaintext
    telegram_bot/
    |-- main.py        # Main bot application logic
    |-- database.py    # Functions for database interaction (SQLite3)
    |-- config.py      # Stores your API token and potentially other settings
    |-- bot_database.db # The SQLite database file (will be created automatically)
    

Step 2: Register Your Bot on Telegram

To interact with the Telegram API, your bot needs an identity and an API token.

  1. Talk to BotFather: Open Telegram and search for "BotFather" (it's the official bot for managing bots).
  2. Create a New Bot: Send the /newbot command to BotFather.
  3. Choose Name & Username: Follow the prompts to give your bot a display name (e.g., "My Test Bot") and a unique username (must end in "bot", e.g., "my_test_xyz_bot").
  4. Get Your Token: BotFather will provide you with an API Token. This is crucial – treat it like a password!
  5. Store the Token: Create the config.py file in your project directory and save your token there:
    Python
    # config.py
    API_TOKEN = "YOUR_ACTUAL_API_TOKEN_HERE"
    

Step 3: Setting Up the SQLite3 Database

We'll use SQLite3 to store basic information about users who interact with our bot.

Create the database.py file and add the following functions:

Python
# database.py
import sqlite3
import datetime
import os

DB_NAME = "bot_database.db"

def init_db():
    """Initializes the database and creates the users table if it doesn't exist."""
    if not os.path.exists(DB_NAME):
        print(f"Creating database file: {DB_NAME}")
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()

    # Create a table for storing user data
    cursor.execute("""
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        telegram_id INTEGER UNIQUE NOT NULL, -- Ensure telegram IDs are unique
        username TEXT,
        joined_date TEXT NOT NULL
    )
    """)
    print("Database initialized and 'users' table ensured.")
    conn.commit()
    conn.close()

def add_user(telegram_id: int, username: str):
    """Adds a new user to the database or ignores if the user already exists."""
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    joined_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    try:
        cursor.execute("""
        INSERT OR IGNORE INTO users (telegram_id, username, joined_date)
        VALUES (?, ?, ?)
        """, (telegram_id, username, joined_date))
        conn.commit()
        if cursor.rowcount > 0:
             print(f"User {username} (ID: {telegram_id}) added to the database.")
        # else:
             # print(f"User {username} (ID: {telegram_id}) already exists.")
    except sqlite3.Error as e:
        print(f"Database error: {e}")
    finally:
        conn.close()

# Optional: Add functions to retrieve or update user data later
# def get_user(telegram_id): ...
# def update_user_data(telegram_id, ...): ...

This script defines:

  • init_db(): Creates the database file (bot_database.db) if it doesn't exist and ensures the users table is set up with columns for an internal ID, the unique Telegram user ID, their username, and the date they first started the bot.
  • add_user(): Inserts a new user record into the table. INSERT OR IGNORE prevents errors if we try to add a user who's already in the database (based on the UNIQUE constraint on telegram_id).

Step 4: Writing the Bot's Core Logic

Now, let's write the main part of our bot in main.py. This script will use the python-telegram-bot library to listen for commands and messages.

Python
# main.py
import logging
from telegram import Update
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext

# Import our database functions and API token
from database import init_db, add_user
from config import API_TOKEN
import datetime

# Enable logging (optional but recommended)
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)

# --- Command Handlers ---

def start(update: Update, context: CallbackContext) -> None:
    """Handles the /start command."""
    user = update.effective_user
    telegram_id = user.id
    # Use first_name if username is not available
    username = user.username or user.first_name

    logger.info(f"User {username} (ID: {telegram_id}) started the bot.")

    # Add user to the database
    add_user(telegram_id, username)

    update.message.reply_text(f"Hello, {user.first_name}! Welcome to the bot. I've noted your visit.")

# --- Message Handlers ---

def echo(update: Update, context: CallbackContext) -> None:
    """Echoes the user's message."""
    user = update.effective_user
    text = update.message.text
    logger.info(f"User {user.first_name} (ID: {user.id}) said: {text}")
    update.message.reply_text(f"You said: {text}")

# --- Error Handler ---

def error_handler(update: Update, context: CallbackContext) -> None:
    """Log Errors caused by Updates."""
    logger.error(msg="Exception while handling an update:", exc_info=context.error)
    # Optionally, inform the user that something went wrong
    # if update and update.effective_message:
    #    update.effective_message.reply_text("An error occurred. Please try again later.")


# --- Main Function to Run the Bot ---

def main() -> None:
    """Start the bot."""
    # Initialize the database first
    print("Initializing database...")
    init_db()
    print("Database ready.")

    # Create the Updater and pass it your bot's token.
    updater = Updater(API_TOKEN)

    # Get the dispatcher to register handlers
    dispatcher = updater.dispatcher

    # --- Register Handlers ---
    # On different commands - answer in Telegram
    dispatcher.add_handler(CommandHandler("start", start))

    # On non-command textual messages - echo the message on Telegram
    dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, echo))

    # Register the error handler
    dispatcher.add_handler(error_handler)

    # Start the Bot
    print("Starting bot polling...")
    updater.start_polling()
    print("Bot is running. Press Ctrl+C to stop.")

    # Run the bot until you press Ctrl-C
    updater.idle()

if __name__ == "__main__":
    main()

Explanation:

  1. Imports: We import necessary classes from telegram.ext, our database functions, the API token, and standard libraries like logging and datetime.
  2. Logging: Basic logging is set up to see bot activity and potential errors in the console.
  3. start() function: This function is triggered when a user sends the /start command. It extracts user information (id, username, first_name), calls add_user to save/update the user in the database, and sends a welcome message back.
  4. echo() function: This handles any regular text message (that isn't a command). It simply sends the same message back to the user.
  5. error_handler() function: Catches and logs errors from the python-telegram-bot library.
  6. main() function:
    • Calls init_db() to ensure the database is ready.
    • Creates an Updater instance, which continuously fetches updates from Telegram.
    • Gets the Dispatcher, which routes updates to the correct handlers.
    • Registers handlers: CommandHandler for /start and MessageHandler for text messages. The error handler is also registered.
    • Starts the bot using updater.start_polling().
    • updater.idle() keeps the script running until manually stopped (e.g., with Ctrl+C).
  7. if __name__ == "__main__":: Ensures main() runs only when the script is executed directly.

Step 5: Understanding Key Libraries Used

  • python-telegram-bot: The core library enabling interaction with the Telegram Bot API. It handles receiving updates (messages, commands) and sending responses. Key components used here are Updater, Dispatcher, CommandHandler, and MessageHandler.
  • sqlite3: Python's built-in library for working with SQLite databases. We use it to connect to the database file, execute SQL commands (like CREATE TABLE, INSERT OR IGNORE), commit changes, and close the connection.
  • datetime: Used here to get the current timestamp when a user starts the bot, which is then stored in the database.
  • logging: Python's standard logging module, helpful for monitoring the bot's operation and diagnosing issues.
  • os: Used briefly in database.py to check if the database file exists before potentially creating it (though sqlite3.connect handles file creation itself).

Step 6: Running and Testing Your Bot

  1. Navigate: Open your terminal or command prompt and navigate to your telegram_bot directory.
  2. Run: Execute the main script:
    Bash
    python main.py
    
    You should see output indicating the database initialization and that the bot is polling.
  3. Test: Open Telegram, find the bot you created (using its username), and send the /start command. You should receive the welcome message. Try sending other text messages – the bot should echo them back. Check your console output to see the logging messages, including user additions to the database.

Visualizing the Process: Diagrams

Understanding the flow can be easier with diagrams. Here are conceptual representations using Mermaid syntax (which can be rendered by many Markdown tools) or descriptions:

1. High-Level Workflow (Process Map / Workflow Diagram)

This shows the overall journey of a user interaction:

Code snippet
sequenceDiagram
    participant User
    participant Telegram API
    participant Python Bot (Updater/Dispatcher)
    participant Start Handler (`start`)
    participant Database (`database.py`)
    participant Echo Handler (`echo`)

    User->>Telegram API: Sends /start command
    Telegram API->>Python Bot (Updater/Dispatcher): Delivers Update
    Python Bot (Updater/Dispatcher)->>Start Handler (`start`): Routes update
    Start Handler (`start`)->>Database (`database.py`): Calls add_user(id, name)
    Database (`database.py`)-->>Start Handler (`start`): User added/ignored
    Start Handler (`start`)->>Telegram API: Sends "Hello..." reply
    Telegram API->>User: Displays reply

    User->>Telegram API: Sends "some text"
    Telegram API->>Python Bot (Updater/Dispatcher): Delivers Update
    Python Bot (Updater/Dispatcher)->>Echo Handler (`echo`): Routes update
    Echo Handler (`echo`)->>Telegram API: Sends "You said: some text" reply
    Telegram API->>User: Displays reply

2. Bot Initialization and Running (Flowchart)

This details the steps in main.py to get the bot running:

Code snippet
graph TD
    A[Start main.py] --> B(Call init_db());
    B --> C{Database Initialized?};
    C -- Yes --> D[Create Updater with API_TOKEN];
    C -- No --> E[Error/Exit];
    D --> F[Get Dispatcher];
    F --> G[Add CommandHandler for /start];
    G --> H[Add MessageHandler for text];
    H --> I[Add Error Handler];
    I --> J(Start Polling updater.start_polling());
    J --> K(Wait for Updates / Idle updater.idle());
    K --> L{Ctrl+C Pressed?};
    L -- Yes --> M[Stop];
    L -- No --> K;

3. /start Command Handling (Process Diagram / Detailed Flowchart)

This zooms in on the start function's logic:

Code snippet
graph TD
    A[Update with /start received] --> B(Dispatcher calls `start` function);
    B --> C[Get user info: id, username from `update.effective_user`];
    C --> D[Log user interaction];
    D --> E(Call `add_user(telegram_id, username)`);
    subgraph Database Interaction
        E --> F[Connect to DB];
        F --> G[Get Cursor];
        G --> H[Execute INSERT OR IGNORE];
        H --> I[Commit Changes];
        I --> J[Close Connection];
    end
    J --> K[Database returns control];
    K --> L[Prepare reply message: "Hello..."];
    L --> M(Send reply via `update.message.reply_text()`);
    M --> N[End /start processing];

4. add_user Database Function (Process Diagram / Flowchart Fragment)

This focuses solely on the database insertion logic:

Code snippet
graph TD
    A[Function `add_user` called with telegram_id, username] --> B(Get current timestamp);
    B --> C(Connect to bot_database.db);
    C --> D[Get cursor object];
    D --> E(Execute SQL: INSERT OR IGNORE INTO users ... VALUES (?, ?, ?));
    E --> F{User already exists?};
    F -- Yes (IGNORE) --> G[Commit transaction];
    F -- No (INSERT) --> G;
    G --> H(Close database connection);
    H --> I[Return control];

Conclusion

Congratulations! You've built a basic Telegram bot using Python and SQLite3. This foundation allows you to:

  • Register users who interact with your bot.
  • Respond to specific commands (/start).
  • Handle general text messages.
  • Persist basic user data.

From here, you can expand your bot's capabilities significantly:

  • Add more commands and functionalities.
  • Query the database to retrieve user information.
  • Implement more complex conversation flows.
  • Integrate with external APIs.
  • Improve error handling and user feedback.

Happy bot building! Feel free to ask if you want to explore specific features further.