Telegram bot server

Introduction#

BotServer: DI wiring, command handlers (/start, /help, /stop, /status, /placement_year, /stats, /noticestats, /web; admin /userstats), registration, subscriptions, admin commands. Polling lifecycle, HTML/Markdown replies, and how tokens stay out of logs.

Project structure#

The Telegram Bot Server resides in the servers package and integrates with services and clients for database, notifications, and Telegram API communication. The main entry point orchestrates server startup and daemon mode.

Core components#

  • BotServer: Implements the Telegram bot server with DI support, command handlers, lifecycle management, and admin command integration.
  • DatabaseService: Provides MongoDB operations for notices, jobs, placement offers, users, policies, and official placement data.
  • NotificationService: Aggregates multiple notification channels and orchestrates sending unsent notices.
  • TelegramService: Wraps Telegram Bot API interactions, message formatting, and broadcasting to users.
  • AdminTelegramService: Handles administrative commands with authentication and operational controls.
  • PlacementStatsCalculatorService: Computes detailed placement statistics from placement offers.
  • DBClient: Manages MongoDB connection and exposes collections.
  • TelegramClient: Low-level Telegram API client with retry logic and rate-limit handling.
  • Settings and Logging: Centralized configuration and logging setup with daemon mode support.

Architecture overview#

The Telegram Bot Server follows a service-oriented architecture with dependency injection. The BotServer initializes services, registers command handlers, and manages the asynchronous lifecycle. Services encapsulate domain logic and integrate with clients for external APIs and databases.

Detailed component analysis#

BotServer: dependency injection and lifecycle#

  • Dependency Injection: BotServer accepts Settings, DatabaseService, NotificationService, AdminTelegramService, and PlacementStatsCalculatorService instances. Daemon mode is configurable too.
  • Command Handlers Registration: setup_handlers registers /start, /help, /stop, /status, /placement_year, /stats, /noticestats, /web, and admin /userstats. Admin scrape/broadcast/log/kill commands are registered when AdminTelegramService is provided.
  • Asynchronous Lifecycle:
  • run_async builds the Application, sets up logging, initializes and starts the application, and keeps the loop running while self.running is True.
  • run blocks and catches KeyboardInterrupt to trigger graceful shutdown.
  • shutdown stops the updater, application, and performs cleanup.
  • Factory Function: create_bot_server constructs DBClient, DatabaseService, TelegramService, NotificationService, AdminTelegramService, and PlacementStatsCalculatorService, then returns a BotServer instance.

Command handler system#

  • /start: Registers or reactivates a user via DatabaseService and responds with HTML-formatted welcome message including commands and helpful links.
  • /help: Responds with Markdown-formatted help text listing available commands.
  • /stop: Deactivates a user via DatabaseService and informs the user.
  • /status: Retrieves user data from DatabaseService and formats a status message indicating subscription state and placement year.
  • /placement_year: Inline keyboard of configured years. Callback writes set_user_placement_year.
  • /stats: Calculates placement statistics via PlacementStatsCalculatorService and replies with Markdown-formatted statistics.
  • /noticestats: Retrieves notice statistics from DatabaseService and replies with Markdown-formatted stats.
  • /userstats: Retrieves user statistics from DatabaseService and replies with Markdown-formatted stats (admin-only via AdminTelegramService).
  • /web: Replies with HTML-formatted links to JIIT suite tools.

User registration and management workflows#

  • Registration: On /start, BotServer calls DatabaseService.add_user with user identity and chat metadata. Responses vary depending on whether the user is newly registered, reactivated, or already active.
  • Subscription Management: /stop triggers DatabaseService.deactivate_user to mark the user as inactive. /status retrieves user data and indicates active/inactive state.
  • Placement year: /placement_year stores a preference used by /stats and /noticestats.
  • User Statistics: /userstats is admin-only (ADMIN_TELEGRAM_USER_IDS) and uses DatabaseService.get_users_stats.

Subscription handling#

  • Deactivation: /stop calls DatabaseService.deactivate_user and informs the user accordingly.
  • Status Checking: /status fetches user data and formats a readable status message, including registration date and user ID when available.

Admin command processing#

  • Authentication: AdminTelegramService verifies that the chat ID matches the configured admin chat ID.
  • /users: Lists all users with status and identifiers.
  • /boo: Broadcasts messages either to all users or a specific user.
  • /fu or /scrapyyy: Triggers a legacy update workflow executed in a thread to avoid blocking the event loop.
  • /kill: Stops the scheduler daemon.
  • /logs: Reads and returns the last lines of the specified log file, HTML-escaped and truncated to fit Telegram limits.

Asynchronous bot lifecycle#

  • Initialization: create_bot_server constructs dependencies and returns a BotServer instance.
  • Polling Mode: run_async initializes and starts the Application, then starts polling with drop_pending_updates to avoid replaying old updates.
  • Graceful Shutdown: run catches KeyboardInterrupt and calls shutdown to stop the updater and application cleanly.

Message formatting with HTML and Markdown#

  • HTML: Used for /start welcome message, /web links, and status messages. TelegramService.convert_markdown_to_html transforms Markdown to HTML for Telegram.
  • Markdown: Used for /help and statistics commands. TelegramService.convert_markdown_to_telegram adapts Markdown for Telegram’s MarkdownV2.
  • Long Messages: TelegramService.split_long_message splits messages exceeding 4000 characters and sends them sequentially with delays.

Integration with DatabaseService and NotificationService#

  • DatabaseService: Provides user management, notice operations, job operations, placement offers, and statistics retrieval. Used by BotServer for user registration/status and by AdminTelegramService for user listing and stats.
  • NotificationService: Orchestrates sending unsent notices to Telegram and Web Push channels. It fetches unsent notices from DatabaseService and broadcasts via TelegramService.

Security considerations for bot token management#

  • Token Storage: BotServer reads TELEGRAM_BOT_TOKEN from Settings. TelegramClient validates presence of bot token before sending messages.
  • Admin Authentication: AdminTelegramService compares the incoming chat ID with the configured admin chat ID to restrict sensitive commands.
  • Daemon Mode: safe_print suppresses stdout in daemon mode and logs to files instead.

Dependency analysis#

The BotServer depends on DatabaseService, NotificationService, AdminTelegramService, and PlacementStatsCalculatorService. DatabaseService depends on DBClient. NotificationService depends on TelegramService. TelegramService depends on TelegramClient. The main entry point creates the BotServer and runs it, optionally in daemon mode.

Performance considerations#

  • Rate Limiting: TelegramService applies small delays between broadcasts to Telegram users to avoid rate limits.
  • Message chunking: TelegramService.split_long_message keeps messages under Telegram’s character limit.
  • Asynchronous Polling: BotServer uses asynchronous polling to keep the event loop responsive.
  • Daemon Mode: Reduces console output overhead in production environments.

[No sources needed since this section provides general guidance]

Troubleshooting guide#

  • Bot not starting: Ensure TELEGRAM_BOT_TOKEN is configured; create_bot_server raises if token is missing.
  • Database connectivity: Verify MONGO_CONNECTION_STR; DBClient.connect tests the connection and logs errors.
  • Admin commands failing: Confirm admin chat ID matches the configured TELEGRAM_CHAT_ID; AdminTelegramService enforces authentication.
  • Logs: Use /logs admin command to retrieve recent log entries; logs are written to files configured by Settings.

Conclusion#

BotServer is DI, command handlers, and an async polling loop. It talks to DatabaseService and NotificationService. Daemon mode is how you leave it running without a terminal attached.