Skip to main content

Reusable Telegram bot framework with Clean Architecture

Project description

Bot Framework

Reusable Python library for building Telegram bots with Clean Architecture principles.

Installation

# Basic installation
pip install bot-framework

# With Telegram support
pip install bot-framework[telegram]

# With all optional dependencies
pip install bot-framework[all]

Features

  • Clean Architecture - Layered architecture with import-linter enforcement
  • Telegram Integration - Ready-to-use services for pyTelegramBotAPI
  • Flow Management - Dialog flow stack management with Redis storage
  • Role Management - User roles and permissions
  • Language Management - Multilingual phrase support
  • Request Role Flow - Pre-built flow for role requests

Quick Start

from bot_framework import Button, Keyboard
from bot_framework.app import BotApplication

app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
)

# Use unified message service
message_service = app.message_service

keyboard = Keyboard(rows=[
    [Button(text="Option 1", callback_data="opt1")],
    [Button(text="Option 2", callback_data="opt2")],
])

# Send new message
message_service.send(chat_id=123, text="Choose an option:", keyboard=keyboard)

# Replace existing message
message_service.replace(chat_id=123, message_id=456, text="Updated text")

# Delete message
message_service.delete(chat_id=123, message_id=456)

Message Services

Bot Framework provides a unified TelegramMessageService that combines all message operations:

Method Description
send() Send a new message
send_markdown_as_html() Send markdown converted to HTML
send_document() Send a file
replace() Edit existing message
delete() Delete message
notify_replace() Delete old message and send new one

Using in your handlers

Use IMessageService protocol for dependency injection:

from bot_framework.protocols.i_message_service import IMessageService

class MyHandler:
    def __init__(self, message_service: IMessageService) -> None:
        self.message_service = message_service

    def handle(self, chat_id: int, message_id: int) -> None:
        # Switch between send/replace by changing method name only
        self.message_service.replace(
            chat_id=chat_id,
            message_id=message_id,
            text="Updated!",
        )

Legacy services (still available)

Individual services are still available for backwards compatibility:

message_sender = app.message_sender    # IMessageSender
message_replacer = app.message_replacer  # IMessageReplacer
message_deleter = app.message_deleter   # IMessageDeleter

Bot Commands

Set up bot commands in BotFather using /setcommands. Copy and paste the following:

start - Start the bot
request_role - Request a role
language - Change language

This enables command autocompletion in Telegram when users type /.

Database Migrations

Bot Framework includes built-in database migrations using yoyo-migrations. Migrations are applied automatically when creating a BotApplication instance.

Automatic migrations (default)

from bot_framework.app import BotApplication

# Migrations are applied automatically
app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
)

Disable automatic migrations

app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
    auto_migrate=False,  # Disable automatic migrations
)

Manual migration

from bot_framework.migrations import apply_migrations

# Returns number of applied migrations
applied_count = apply_migrations("postgres://user:pass@localhost/dbname")

Created tables

  • languages - Supported languages (en, ru by default)
  • roles - User roles (user, supervisors by default)
  • users - Bot users
  • phrases - Multilingual phrases
  • user_roles - User-role associations

Configuration

Bot Framework uses JSON files to configure roles, phrases, and languages. The library provides default values, and you can extend them with your own configuration files.

Roles

Roles define user permissions in your bot. The library includes two base roles: user (default for all users) and supervisors (role approvers).

Add custom roles by creating data/roles.json in your project:

{
  "roles": [
    {"name": "admin", "description": "Administrator with full access"},
    {"name": "moderator", "description": "Content moderator"}
  ]
}

Pass the path to BotApplication:

from pathlib import Path
from bot_framework.app import BotApplication

app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
    roles_json_path=Path("data/roles.json"),
)

Roles are synced to the database on startup using INSERT ... ON CONFLICT DO NOTHING, so it's safe to run multiple times.

Using roles in handlers:

class AdminOnlyHandler:
    def __init__(self):
        self.allowed_roles: set[str] | None = {"admin"}

Phrases

Phrases provide multilingual text for your bot. Each phrase has a hierarchical key and translations for each supported language.

Add custom phrases by creating data/phrases.json:

{
  "mybot.greeting": {
    "ru": "Привет! Я ваш помощник.",
    "en": "Hello! I'm your assistant."
  },
  "mybot.help.title": {
    "ru": "Справка",
    "en": "Help"
  },
  "mybot.errors.not_found": {
    "ru": "Не найдено",
    "en": "Not found"
  }
}

Pass the path to BotApplication:

app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
    phrases_json_path=Path("data/phrases.json"),
)

Using phrases:

# Get phrase for user's language
text = app.phrase_provider.get("mybot.greeting", language_code="ru")

Key naming convention: Use dot-separated hierarchical keys like module.context.action (e.g., orders.validation.empty_cart).

Languages

Languages define which translations are available. The library includes English and Russian by default.

Add custom languages by creating data/languages.json:

{
  "languages": [
    {"code": "ru", "name": "Russian", "native_name": "Русский"},
    {"code": "en", "name": "English", "native_name": "English"},
    {"code": "es", "name": "Spanish", "native_name": "Español"}
  ],
  "default_language": "en"
}

Pass the path to BotApplication:

app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
    languages_json_path=Path("data/languages.json"),
)

Full configuration example

from pathlib import Path
from bot_framework.app import BotApplication

app = BotApplication(
    bot_token="YOUR_BOT_TOKEN",
    database_url="postgres://user:pass@localhost/dbname",
    redis_url="redis://localhost:6379/0",
    roles_json_path=Path("data/roles.json"),
    phrases_json_path=Path("data/phrases.json"),
    languages_json_path=Path("data/languages.json"),
)

app.run()

Project structure:

my_bot/
├── data/
│   ├── roles.json
│   ├── phrases.json
│   └── languages.json
├── handlers/
│   └── ...
└── main.py

Optional Dependencies

  • telegram - pyTelegramBotAPI for Telegram bot integration
  • postgres - psycopg and yoyo-migrations for PostgreSQL database support
  • redis - Redis for caching and flow state management
  • all - All optional dependencies

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bot_framework-0.1.6.tar.gz (71.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bot_framework-0.1.6-py3-none-any.whl (93.2 kB view details)

Uploaded Python 3

File details

Details for the file bot_framework-0.1.6.tar.gz.

File metadata

  • Download URL: bot_framework-0.1.6.tar.gz
  • Upload date:
  • Size: 71.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bot_framework-0.1.6.tar.gz
Algorithm Hash digest
SHA256 0eca0a2521db8b42b2a90ab1c5b369383e66aef8230a1546192c14757b371d75
MD5 2702b186d44a3cc7c75dc04ddc4a186b
BLAKE2b-256 1b23f40b455ffbccf005ad01d8e03e9d655b15820fc4355d27677aef23e82d60

See more details on using hashes here.

File details

Details for the file bot_framework-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: bot_framework-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 93.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bot_framework-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 190552a70901cf7842ec9f79813d7a9ed81b2381c905333d389ef9405a588c73
MD5 de6ce858e214cffd90e057598932b3d6
BLAKE2b-256 9e14e50003de1a1295f385872dfc53942af5114398a38d8015a0db8f0df33436

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page