Типичная ситуация выглядит так: есть готовый Telegram-бот на aiogram, и нужно запустить его ещё в Max. Библиотека obabot предлагает другой путь: один код — два мессенджера. Один Код - Два Бота
Max запустили как полноценную альтернативу Telegram для российского рынка, с открытым Bot API. Разработчики оказались перед классической дилеммой: поддерживать двойную кодовую базу или выбрать одну платформу, теряя аудиторию второй.
Типичная ситуация выглядит так: есть готовый Telegram-бот на aiogram, и нужно запустить его ещё в Max. Варианты неприятные: либо дублировать код, либо писать тонну адаптеров вручную, либо мириться с расхождением фич между платформами.
Библиотека obabot предлагает другой путь: один код — два мессенджера, чтобы править всеми.
Что такое obabot?obabot — это асинхронная Python-библиотека с API, совместимым с aiogram 3.x, которая позволяет запускать одного бота сразу на Telegram и Max. Под капотом: для Telegram используется нативный aiogram без какой-либо дополнительной обёртки, а для Max — адаптерный слой, который транслирует события Max-платформы в aiogram-совместимые объекты.
Устанавливается одной командой:
pip install obabot aiogram>=3.0.0 umaxbot>=0.1.7Быстрый стартЦентральная точка входа — функция create_bot(). Она принимает токены нужных платформ и возвращает готовый кортеж (bot, dispatcher, router).
from obabot import create_bot
from obabot.filters import Command
bot, dp, router = create_bot(tg_token="ВАШ_TG_ТОКЕН")
@router.message(Command("start"))
async def start(message):
await message.answer(f"Привет с {message.platform}!")
await dp.start_polling(bot)
Только Maxfrom obabot import create_bot
from obabot.filters import Command
bot, dp, router = create_bot(max_token="ВАШ_MAX_ТОКЕН")
@router.message(Command("start"))
async def start(message):
await message.answer(f"Привет с {message.platform}!")
await dp.start_polling(bot)
Обратите внимание: код обработчика абсолютно идентичен. Разница только в аргументе токена. В каждый объект добавляется атрибут platform для написания платформ-специфичного кода
Обе платформы одновременноfrom obabot import create_bot
from obabot.filters import Command
bot, dp, router = create_bot(
tg_token="ВАШ_TG_ТОКЕН",
max_token="ВАШ_MAX_ТОКЕН"
)
@router.message(Command("start"))
async def start(message):
# Атрибут platform показывает, откуда пришло сообщение
await message.answer(f"Привет с {message.platform}!")
# Polling запускается на обеих платформах параллельно
await dp.start_polling(bot)
Миграция с aiogram за 5 минутЕсли у вас уже есть бот на aiogram 3.x, миграция сводится к замене импортов и инициализации.
До:
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)
После:
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)
Изменилось ровно 2 вещи:
импорты: aiogram → obabot
инициализация: Bot/Dispatcher/Router → create_bot()
всё остальное осталось 100% идентичным
Все сообщения — и из Telegram, и из Max — реализуют единый интерфейс:
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 (Finite State Machine, машина состояний, конечный автомат)FSM работает так же, как в aiogram:
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
@router.message(Command("start", "help")) # Несколько команд
@router.message(F.text.startswith("!")) # Магический фильтр
@router.message(F.photo) # Только фото
@router.callback_query(F.data == "click") # Callback
Тестовый режимДля unit-тестов предусмотрен специальный режим — токены не нужны, сетевых вызовов нет:
bot, dp, router = create_bot(test_mode=True)Тесты покрывают Python 3.10, 3.13, 3.14 и aiogram 3.0.0, 3.24.
Репозиторий: github.com/Korean-DOG/obabot
Итогobabot закрывает конкретную практическую боль: запускать Telegram-бота ещё и в Max без переписывания кода.