Skip to main content

Universal async bot library for Telegram and Max with aiogram-compatible API

Project description

obabot

Универсальная асинхронная библиотека для ботов Telegram и Max с API, совместимым с aiogram.

Напишите код бота один раз, запустите его на Telegram, Max или на обеих платформах одновременно!

Возможности

  • Минимальные изменения при миграции — меняются только импорты и инициализация
  • API, совместимый с aiogram — используйте знакомые декораторы, фильтры и FSM
  • Поддержка нескольких платформ — работайте на Telegram, Max или на обеих одновременно
  • Нативная производительность для Telegram — без накладных расходов (прямой aiogram)
  • Прозрачные адаптеры для Max — API Max автоматически преобразуется в интерфейс, похожий на aiogram

Установка

pip install obabot

Зависимости для платформ

После установки obabot необходимо установить библиотеки для платформ:

# Для поддержки Telegram
pip install aiogram>=3.0.0

# Для поддержки Max
pip install umaxbot>=0.1.7

# Или обе
pip install aiogram>=3.0.0 umaxbot>=0.1.7

Рекомендуемая версия aiogram: 3.24 (последняя стабильная версия 3.x, используется в тестах)

Быстрый старт

Только Telegram

from obabot import create_bot
from obabot.filters import Command

bot, dp, router = create_bot(tg_token="ВАШ_ТЕЛЕГРАМ_ТОКЕН")

@router.message(Command("start"))
async def start(message):
    await message.answer(f"Привет с {message.platform}!")

await dp.start_polling(bot)

Только Max

from obabot import create_bot
from obabot.filters import Command

# Просто измените аргумент токена!
bot, dp, router = create_bot(max_token="ВАШ_МАКС_ТОКЕН")

@router.message(Command("start"))
async def start(message):
    await message.answer(f"Привет с {message.platform}!")

await dp.start_polling(bot)

Обе платформы (двойной режим)

from obabot import create_bot
from obabot.filters import Command

# Передайте оба токена для режима двух платформ
bot, dp, router = create_bot(
    tg_token="ВАШ_ТЕЛЕГРАМ_ТОКЕН",
    max_token="ВАШ_МАКС_ТОКЕН"
)

@router.message(Command("start"))
async def start(message):
    # message.platform показывает, с какой платформы пришло сообщение
    await message.answer(f"Привет с {message.platform.upper()}!")

# Это запускает polling на ОБЕИХ платформах
await dp.start_polling(bot)

Миграция с aiogram

Миграция существующего бота на aiogram очень проста — просто измените импорты и инициализацию!

До (aiogram)

from aiogram import Bot, Dispatcher, Router
from aiogram.filters import Command
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext

bot = Bot(token="TOKEN")
dp = Dispatcher()
router = Router()
dp.include_router(router)

@router.message(Command("start"))
async def start(message):
    await message.answer("Привет!")

await dp.start_polling(bot)

После (obabot)

from obabot import create_bot
from obabot.filters import Command
from obabot.fsm import State, StatesGroup, FSMContext

bot, dp, router = create_bot(tg_token="TOKEN")

@router.message(Command("start"))
async def start(message):
    await message.answer("Привет!")

await dp.start_polling(bot)

Изменения:

  • ✅ Изменены импорты: aiogramobabot
  • ✅ Изменена инициализация: Bot/Dispatcher/Routercreate_bot()
  • Всё остальное на 100% идентично!

См. examples/aiogram_original.py и examples/aiogram_migrated.py для полного примера миграции.

Справочник API

create_bot()

Основная фабричная функция для создания бота.

def create_bot(
    tg_token: str | None = None,
    max_token: str | None = None,
    fsm_storage: BaseStorage | None = None,
    test_mode: bool | None = None,
) -> tuple[ProxyBot | StubBot, ProxyDispatcher | Dispatcher, ProxyRouter | Router]:
    ...

Аргументы:

  • tg_token - токен Telegram бота (опционально; в тестовом режиме не требуется)
  • max_token - токен Max бота (опционально; в тестовом режиме не требуется)
  • fsm_storage - хранилище для FSM состояний (опционально). Будет использоваться всеми платформами.
  • test_mode - если True, включается тестовый режим (без токенов и сетевых вызовов). Если None, используется переменная окружения TESTING=1.

Возвращает: Кортеж (bot, dispatcher, router)

Режимы:

  • Только tg_token → режим Telegram
  • Только max_token → режим Max
  • Оба токена → режим двух платформ
  • test_mode=True или TESTING=1 → тестовый режим

Обработчики

Используйте те же декораторы, что и в aiogram:

# Вариант 1: Использование router (рекомендуется)
@router.message(Command("start"))
async def cmd_start(message):
    await message.answer("Привет!")

# Вариант 2: Использование dispatcher (тоже работает, как в aiogram)
@dp.message(Command("start"))
async def cmd_start_v2(message):
    await message.answer("Привет!")

# Оба работают с фильтрами
@router.message(F.text)
async def text_handler(message):
    await message.answer(f"Вы сказали: {message.text}")

@router.callback_query(F.data == "button")
async def callback_handler(callback):
    await callback.answer("Кнопка нажата!")
    await callback.message.edit_text("Обновлено!")

Объект Message

Все сообщения имеют эти свойства (как в aiogram):

message.text          # Текст сообщения
message.from_user     # Пользователь, отправивший сообщение
message.chat          # Объект чата
message.message_id    # ID сообщения
message.platform      # "telegram" или "max"

# Методы
await message.answer("Текст ответа")
await message.reply("Ответить на это сообщение")
await message.delete()
await message.edit_text("Новый текст")

FSM (Конечный автомат состояний)

from obabot.fsm import State, StatesGroup, FSMContext

class Form(StatesGroup):
    name = State()
    age = State()

@router.message(Command("start"))
async def start(message, state: FSMContext):
    await state.set_state(Form.name)
    await message.answer("Как тебя зовут?")

@router.message(Form.name)
async def process_name(message, state: FSMContext):
    await state.update_data(name=message.text)
    await state.set_state(Form.age)
    await message.answer("Сколько тебе лет?")

Клавиатуры

from obabot.types import InlineKeyboardMarkup, InlineKeyboardButton

keyboard = InlineKeyboardMarkup(inline_keyboard=[
    [
        InlineKeyboardButton(text="Кнопка 1", callback_data="btn1"),
        InlineKeyboardButton(text="Кнопка 2", callback_data="btn2"),
    ]
])

await message.answer("Выберите:", reply_markup=keyboard)

Фильтры

from obabot.filters import Command, F, StateFilter

@router.message(Command("start", "help"))  # Несколько команд
@router.message(F.text.startswith("!"))     # Магический фильтр
@router.message(F.photo)                   # Сообщения с фото
@router.callback_query(F.data == "click") # Callback data

Архитектура

obabot/
├── obabot/
│   ├── __init__.py          # create_bot, BPlatform
│   ├── factory.py           # Реализация create_bot()
│   ├── proxy/               # Proxy классы для мультиплексирования
│   │   ├── bot.py           # ProxyBot
│   │   ├── dispatcher.py    # ProxyDispatcher
│   │   └── router.py        # ProxyRouter
│   ├── adapters/            # Адаптеры Max → aiogram
│   │   ├── message.py       # MaxMessageAdapter
│   │   ├── max_callback.py  # MaxCallbackQuery
│   │   ├── telegram_callback.py # TelegramCallbackQuery
│   │   ├── user.py          # MaxUserAdapter, MaxChatAdapter
│   │   └── keyboard.py      # Конвертер клавиатур
│   ├── platforms/           # Реализации платформ
│   │   ├── base.py          # BasePlatform ABC
│   │   ├── telegram.py      # TelegramPlatform (нативный aiogram)
│   │   └── max.py           # MaxPlatform (адаптированный)
│   ├── filters.py           # Реэкспортированные фильтры aiogram
│   ├── fsm.py               # Реэкспортированные компоненты FSM
│   └── types.py             # Enum BPlatform, реэкспорты типов
└── examples/
    ├── aiogram_original.py      # Оригинальный бот на aiogram
    ├── aiogram_migrated.py      # Мигрированный на obabot
    ├── telegram_only.py         # Telegram с FSM и клавиатурами
    ├── max_only.py              # Max с FSM и клавиатурами
    └── dual_platform.py         # Обе платформы одновременно
└── tests/
    ├── test_test_mode.py        # Тесты тестового режима
    ├── test_basic.py            # Базовые тесты
    └── ...

Как это работает

  1. Telegram (нативный): Сообщения проходят напрямую к обработчикам aiogram. Добавляется только атрибут message.platform.
  2. Max (адаптированный): Сообщения оборачиваются в MaxMessageAdapter, который предоставляет интерфейс, совместимый с aiogram.
  3. Режим двух платформ: Обе платформы работают параллельно. Каждый обработчик регистрируется на обеих платформах.

Примеры

См. директорию examples/ для полных рабочих примеров:

  • aiogram_original.py - Полный пример бота на оригинальном aiogram 3.x
  • aiogram_migrated.py - Тот же бот, мигрированный на obabot
  • telegram_only.py - Бот для Telegram с FSM и клавиатурами
  • max_only.py - Тот же бот для Max
  • dual_platform.py - Бот для обеих платформ одновременно
  • test_mode_example.py - Пример тестового режима

Тестирование

Библиотека тестируется на разных версиях Python и aiogram:

  • Python: 3.10, 3.13, 3.14
  • aiogram: 3.0.0, 3.24, default (>=3.0.0)
# Установка dev-зависимостей
pip install -e ".[dev]"

# Запуск тестов
pytest

# С покрытием
pytest --cov=obabot --cov-report=html

Лицензия

Proprietary License - см. файл LICENSE для деталей.

Вклад в проект

Вклад приветствуется! Пожалуйста, не стесняйтесь создавать issues и pull requests.

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

obabot-0.2.0.tar.gz (121.6 kB view details)

Uploaded Source

Built Distribution

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

obabot-0.2.0-py3-none-any.whl (78.1 kB view details)

Uploaded Python 3

File details

Details for the file obabot-0.2.0.tar.gz.

File metadata

  • Download URL: obabot-0.2.0.tar.gz
  • Upload date:
  • Size: 121.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for obabot-0.2.0.tar.gz
Algorithm Hash digest
SHA256 88b266eb2a9446874790460e75882c75a860b81b8509dd8330cc45f2b0ee5416
MD5 62d04f1c1973e9c2528575075b6e476d
BLAKE2b-256 a80fb390aacf3fa8a826c549be288dbf66d10c46a801b6a20c2560b19c310044

See more details on using hashes here.

File details

Details for the file obabot-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: obabot-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 78.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for obabot-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 07db3ef1a3e7174010ec360afe63ed6116726ad875d861db522bc0d01804780b
MD5 cffbbaf743a60dccdea000ba135ccf3e
BLAKE2b-256 1f0baffd852c4b6397d26bd753ee496baa970eb8caab1b58f979a2ed1860e623

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