Примеры использования AsyncMaxBot SDK¶
В этом разделе собраны полноценные примеры ботов, демонстрирующие различные возможности AsyncMaxBot SDK версии 1.4.3. Все примеры основаны на реальных файлах из репозитория и показывают лучшие практики использования библиотеки.
1. Эхо-бот (Базовый пример)¶
Самый простой пример бота, который повторяет все сообщения пользователя.
"""
Эхо-бот - исправленный рабочий пример
Демонстрирует базовые возможности библиотеки AsyncMaxBot SDK 1.4.3
"""
import asyncio
from maxbot import Bot, Dispatcher, Context, F
from maxbot.filters import command, text
from maxbot.middleware import LoggingMiddleware, ErrorHandlingMiddleware
# ⚠️ Вставьте ваш токен сюда
TOKEN = "YOUR_TOKEN_HERE"
class EchoBot:
"""Эхо-бот с стандартной архитектурой"""
def __init__(self):
self.bot = Bot(TOKEN)
self.dp = Dispatcher(self.bot)
self.setup_middleware()
self.setup_handlers()
self.stats = {"messages": 0, "users": set()}
def setup_middleware(self):
"""Настройка базового middleware"""
self.dp.include_middleware(LoggingMiddleware())
self.dp.include_middleware(ErrorHandlingMiddleware())
def setup_handlers(self):
"""Настройка обработчиков"""
@self.dp.message_handler(F.command == "start")
async def start_handler(ctx: Context):
await ctx.reply(
f"👋 Привет, {ctx.user.name}! Я эхо-бот.\n"
"📝 Просто напиши что-нибудь, и я повторю это.\n"
"📊 /stats — статистика\n"
"🔄 /echo — режим эхо\n"
"❓ /help — эта справка"
)
@self.dp.message_handler(F.command == "help")
async def help_handler(ctx: Context):
await ctx.reply(
"📚 Справка по эхо-боту:\n\n"
"💬 Просто напишите любое сообщение, и я его повторю\n"
"📊 /stats — показать статистику\n"
"🔄 /echo — включить режим эхо\n"
"❓ /help — эта справка"
)
@self.dp.message_handler(F.command == "stats")
async def stats_handler(ctx: Context):
self.stats["messages"] += 1
self.stats["users"].add(ctx.user_id)
await ctx.reply(
f"📊 Статистика:\n"
f"💬 Сообщений: {self.stats['messages']}\n"
f"👥 Уникальных пользователей: {len(self.stats['users'])}"
)
@self.dp.message_handler(F.command == "echo")
async def echo_mode_handler(ctx: Context):
await ctx.reply("🔄 Режим эхо включен! Напиши что-нибудь.")
@self.dp.message_handler(F.text.contains("привет"))
async def hello_handler(ctx: Context):
emoji = "🦜" if "привет" in ctx.text.lower() else "📢"
await ctx.reply(f"{emoji} {ctx.text}")
@self.dp.message_handler()
async def echo_handler(ctx: Context):
"""
Этот обработчик ловит любое сообщение и отвечает тем же текстом.
Демонстрирует:
- Регистрацию обработчика без фильтров (срабатывает на все).
- Использование `ctx.text` для получения текста.
- Использование `ctx.reply` для ответа.
"""
self.stats["messages"] += 1
self.stats["users"].add(ctx.user_id)
if ctx.text and ctx.text.startswith("/"):
await ctx.reply("❓ Неизвестная команда. Напиши /help")
elif ctx.text:
emoji = "🦜" if "привет" in ctx.text.lower() else "📢"
await ctx.reply(f"{emoji} {ctx.text}")
async def run(self):
"""Запуск бота"""
print("🤖 Эхо-бот запущен!")
async with self.bot:
me = await self.bot.get_me()
print(f"🤖 Бот: {me['name']} (ID: {me['user_id']})")
await self.bot.polling(dispatcher=self.dp)
async def main():
"""Основная функция для запуска бота."""
bot = EchoBot()
try:
await bot.run()
except KeyboardInterrupt:
print("\n🛑 Бот остановлен")
if __name__ == "__main__":
asyncio.run(main())
Что демонстрирует:
- Базовую структуру бота с классами
- Регистрацию обработчиков для команд (F.command
)
- Регистрацию "catch-all" обработчика для любого текста
- Использование middleware для логирования и обработки ошибок
- Простое управление состоянием (статистика)
2. Блэкджек с Inline клавиатурами 🎰¶
Современный пример игры в блэкджек с использованием inline клавиатур, callback обработки и MagicFilter системы.
"""
Блэкджек с Inline клавиатурами - исправленный рабочий пример
Демонстрирует inline клавиатуры, callback обработку и MagicFilter систему
"""
import asyncio
from maxbot import Bot, Dispatcher, Context, F
from maxbot.max_types import InlineKeyboardMarkup, InlineKeyboardButton
import random
TOKEN = "YOUR_TOKEN_HERE"
# Карты и значения
SUITS = ["♠", "♥", "♦", "♣"]
RANKS = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
VALUES = {"A": 11, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "10": 10, "J": 10, "Q": 10, "K": 10}
# Игровое состояние
GAMES = {}
class GameState:
def __init__(self):
self.deck = self._create_deck()
self.player = []
self.dealer = []
self.finished = False
self.result = ""
def _create_deck(self):
deck = []
for suit in SUITS:
for rank in RANKS:
deck.append(f"{rank}{suit}")
random.shuffle(deck)
return deck
def deal_initial(self):
self.player = [self.deck.pop(), self.deck.pop()]
self.dealer = [self.deck.pop(), self.deck.pop()]
def hit(self):
if not self.finished:
self.player.append(self.deck.pop())
if self.get_hand_value(self.player) > 21:
self.finished = True
self.result = "💥 Перебор! Вы проиграли!"
def stand(self):
if not self.finished:
self.finished = True
while self.get_hand_value(self.dealer) < 17:
self.dealer.append(self.deck.pop())
player_value = self.get_hand_value(self.player)
dealer_value = self.get_hand_value(self.dealer)
if dealer_value > 21:
self.result = "🎉 Дилер перебрал! Вы выиграли!"
elif player_value > dealer_value:
self.result = "🎉 Вы выиграли!"
elif player_value < dealer_value:
self.result = "😔 Дилер выиграл!"
else:
self.result = "🤝 Ничья!"
def surrender(self):
if not self.finished:
self.finished = True
self.result = "🏳️ Вы сдались!"
def get_hand_value(self, hand):
value = 0
aces = 0
for card in hand:
rank = card[:-1] # Убираем масть
card_value = VALUES[rank]
if card_value == 11:
aces += 1
else:
value += card_value
for _ in range(aces):
if value + 11 <= 21:
value += 11
else:
value += 1
return value
def get_display_text(self):
player_value = self.get_hand_value(self.player)
dealer_value = self.get_hand_value(self.dealer)
text = f"🎲 **Блэкджек**\n\n"
text += f"👤 **Ваши карты:** {' '.join(self.player)} = {player_value}\n"
if self.finished:
text += f"🤖 **Карты дилера:** {' '.join(self.dealer)} = {dealer_value}\n\n"
text += f"**Результат:** {self.result}"
else:
text += f"🤖 **Карта дилера:** {self.dealer[0]} ?\n\n"
text += "Выберите действие:"
return text
def get_keyboard(finished=False):
if finished:
return InlineKeyboardMarkup(
inline_keyboard=[[InlineKeyboardButton(text="🔄 Сыграть ещё", payload="restart")]]
)
return InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(text="🃏 Взять", payload="hit"),
InlineKeyboardButton(text="✋ Стоп", payload="stand"),
InlineKeyboardButton(text="🏳️ Сдаться", payload="surrender"),
]
]
)
async def main():
async with Bot(token=TOKEN) as bot:
dp = Dispatcher(bot)
@dp.message_handler(F.command == "start")
async def start(ctx: Context):
GAMES[ctx.user_id] = GameState()
game = GAMES[ctx.user_id]
game.deal_initial()
await ctx.reply(
game.get_display_text(),
reply_markup=get_keyboard()
)
@dp.callback_query_handler(F.payload == "hit")
async def hit_handler(ctx: Context):
if ctx.user_id not in GAMES:
await ctx.answer_callback("❌ Игра не найдена. Начните новую игру!")
return
game = GAMES[ctx.user_id]
game.hit()
await ctx.answer_callback("🃏 Карта взята!")
await ctx.edit_message(
game.get_display_text(),
reply_markup=get_keyboard(game.finished)
)
@dp.callback_query_handler(F.payload == "stand")
async def stand_handler(ctx: Context):
if ctx.user_id not in GAMES:
await ctx.answer_callback("❌ Игра не найдена. Начните новую игру!")
return
game = GAMES[ctx.user_id]
game.stand()
await ctx.answer_callback("✋ Остановились!")
await ctx.edit_message(
game.get_display_text(),
reply_markup=get_keyboard(game.finished)
)
@dp.callback_query_handler(F.payload == "surrender")
async def surrender_handler(ctx: Context):
if ctx.user_id not in GAMES:
await ctx.answer_callback("❌ Игра не найдена. Начните новую игру!")
return
game = GAMES[ctx.user_id]
game.surrender()
await ctx.answer_callback("🏳️ Сдались!")
await ctx.edit_message(
game.get_display_text(),
reply_markup=get_keyboard(game.finished)
)
@dp.callback_query_handler(F.payload == "restart")
async def restart_handler(ctx: Context):
GAMES[ctx.user_id] = GameState()
game = GAMES[ctx.user_id]
game.deal_initial()
await ctx.answer_callback("🔄 Новая игра!")
await ctx.edit_message(
game.get_display_text(),
reply_markup=get_keyboard()
)
print("🎰 Блэкджек бот запущен!")
await bot.polling(dispatcher=dp)
if __name__ == "__main__":
asyncio.run(main())
Что демонстрирует:
- Работу с Inline
клавиатурами и Callback
обработчиками
- Использование MagicFilter
(F.payload == "..."
) для фильтрации callback
- Управление состоянием игры для каждого пользователя (GAMES
словарь)
- Редактирование сообщений (ctx.edit_message
)
3. Router система (Модульная архитектура) 🏗️¶
Пример показывает, как использовать роутеры для разделения логики бота на независимые модули (команды, callbacks, события).
"""
Router система - исправленный рабочий пример
Демонстрирует использование роутеров для изоляции логики
"""
import asyncio
from maxbot import Bot, Dispatcher, Router, F, Context
from maxbot.max_types import InlineKeyboardMarkup, InlineKeyboardButton
TOKEN = "YOUR_TOKEN_HERE"
# Создаем роутер для команд
def create_commands_router():
router = Router()
@router.message_handler(F.command == "start")
async def start_command(ctx: Context):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="🎮 Игры", payload="games")],
[InlineKeyboardButton(text="📊 Статистика", payload="stats")],
[InlineKeyboardButton(text="ℹ️ Помощь", payload="help")]
]
)
await ctx.reply(
f"👋 Привет, {ctx.user.name}! Я модульный бот.\n"
"Выберите раздел:",
reply_markup=keyboard
)
@router.message_handler(F.command == "help")
async def help_command(ctx: Context):
await ctx.reply(
"📚 Доступные команды:\n\n"
"🎮 /games — игры\n"
"📊 /stats — статистика\n"
"ℹ️ /help — эта справка\n"
"🔧 /settings — настройки"
)
@router.message_handler(F.command == "settings")
async def settings_command(ctx: Context):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="🔔 Уведомления", payload="notifications")],
[InlineKeyboardButton(text="🌍 Язык", payload="language")],
[InlineKeyboardButton(text="🔙 Назад", payload="back_to_main")]
]
)
await ctx.reply("⚙️ Настройки:", reply_markup=keyboard)
return router
# Создаем роутер для callback
def create_callback_router():
router = Router()
@router.callback_query_handler(F.payload == "games")
async def games_callback(ctx: Context):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="🎰 Блэкджек", payload="blackjack")],
[InlineKeyboardButton(text="🎲 Кости", payload="dice")],
[InlineKeyboardButton(text="🔙 Назад", payload="back_to_main")]
]
)
await ctx.answer_callback("🎮 Выберите игру:")
await ctx.edit_message("🎮 Доступные игры:", reply_markup=keyboard)
@router.callback_query_handler(F.payload == "stats")
async def stats_callback(ctx: Context):
await ctx.answer_callback("📊 Статистика загружается...")
await ctx.edit_message(
"📊 Ваша статистика:\n"
"🎮 Игр сыграно: 15\n"
"🏆 Побед: 8\n"
"📝 Сообщений: 127"
)
@router.callback_query_handler(F.payload == "help")
async def help_callback(ctx: Context):
await ctx.answer_callback("ℹ️ Справка")
await ctx.edit_message(
"ℹ️ Справка по боту:\n\n"
"🎮 Игры — различные мини-игры\n"
"📊 Статистика — ваши достижения\n"
"⚙️ Настройки — персонализация"
)
@router.callback_query_handler(F.payload == "back_to_main")
async def back_to_main_callback(ctx: Context):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="🎮 Игры", payload="games")],
[InlineKeyboardButton(text="📊 Статистика", payload="stats")],
[InlineKeyboardButton(text="ℹ️ Помощь", payload="help")]
]
)
await ctx.answer_callback("🔙 Возвращаемся в главное меню")
await ctx.edit_message(
f"👋 Привет, {ctx.user.name}! Я модульный бот.\n"
"Выберите раздел:",
reply_markup=keyboard
)
return router
# Создаем роутер для событий
def create_events_router():
router = Router()
@router.bot_started_handler()
async def on_bot_started(ctx: Context):
await ctx.reply(
f"🎉 Бот запущен пользователем {ctx.user.name}!\n"
"Используйте /start для начала работы."
)
@router.user_added_handler()
async def on_user_added(ctx: Context):
await ctx.reply(
f"👋 Добро пожаловать, {ctx.user.name}!\n"
"Я модульный бот с различными возможностями.\n"
"Используйте /start для начала работы."
)
@router.chat_member_updated_handler()
async def on_member_updated(ctx: Context):
await ctx.reply(
f"👤 Статус пользователя {ctx.user.name} изменен:\n"
f"📊 {ctx.old_status} → {ctx.new_status}"
)
return router
async def main():
async with Bot(token=TOKEN) as bot:
dp = Dispatcher(bot)
# Подключаем роутеры
commands_router = create_commands_router()
callback_router = create_callback_router()
events_router = create_events_router()
dp.include_router(commands_router)
dp.include_router(callback_router)
dp.include_router(events_router)
print("🔧 Модульный бот запущен!")
await bot.polling(dispatcher=dp)
if __name__ == "__main__":
asyncio.run(main())
Что демонстрирует:
- Разделение обработчиков на логические блоки с помощью Router
- Подключение роутеров к главному диспетчеру (dp.include_router
)
- Обработку системных событий (bot_started
, user_added
, chat_member_updated
)
4. Бот-секретарь с Inline клавиатурами secretary¶
Бот для управления задачами с разными уровнями доступа.
"""
Бот-секретарь - исправленный рабочий пример
Демонстрирует продвинутые возможности библиотеки AsyncMaxBot SDK 1.4.3:
- Inline клавиатуры
- Callback обработка
- MagicFilter система
- Router система
- Middleware
"""
import asyncio
from maxbot import Bot, Dispatcher, Router, F, Context
from maxbot.max_types import InlineKeyboardMarkup, InlineKeyboardButton
TOKEN = "YOUR_TOKEN_HERE"
# База данных задач (in-memory)
TASKS = {
1: {"title": "Подготовить отчет", "status": "в процессе"},
2: {"title": "Заказать пиццу", "status": "новая"},
3: {"title": "Позвонить клиенту", "status": "выполнена"},
}
# --- Роутер для команд ---
commands_router = Router()
@commands_router.message_handler(F.command == "start")
async def start_command(ctx: Context):
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text="📋 Список задач", payload="tasks_list")],
[InlineKeyboardButton(text="➕ Новая задача", payload="new_task")]
]
)
await ctx.reply("👩💼 Бот-секретарь готов к работе. Выберите действие:", reply_markup=keyboard)
# --- Роутер для Callback ---
callback_router = Router()
@callback_router.callback_query_handler(F.payload == "tasks_list")
async def tasks_list_callback(ctx: Context):
if not TASKS:
await ctx.answer_callback("📭 Список задач пуст")
return
response = "📋 **Ваши задачи:**\n\n"
for task_id, task in TASKS.items():
icon = "✅" if task["status"] == "выполнена" else "📝"
response += f"{icon} {task_id}: {task['title']} ({task['status']})\n"
await ctx.answer_callback("📋 Задачи загружены")
await ctx.edit_message(response)
@callback_router.callback_query_handler(F.payload == "new_task")
async def new_task_callback(ctx: Context):
await ctx.answer_callback("➕ Создание задачи")
await ctx.edit_message("📝 Введите название новой задачи:")
# Здесь можно добавить логику для ожидания ответа пользователя
async def main():
async with Bot(token=TOKEN) as bot:
dp = Dispatcher(bot)
dp.include_router(commands_router)
dp.include_router(callback_router)
print("👩💼 Бот-секретарь запущен!")
await bot.polling(dispatcher=dp)
if __name__ == "__main__":
asyncio.run(main())
Что демонстрирует:
- Создание простого CRUD-подобного интерфейса
- Динамическое формирование списка задач
- Более сложную логику взаимодействия через callback
Заключение¶
Эти примеры демонстрируют все основные возможности AsyncMaxBot SDK версии 1.4.3:
- ✅ Базовая архитектура с классами Bot, Dispatcher, Context
- ✅ Фильтры через MagicFilter (F.text
, F.command
, F.payload
)
- ✅ Inline клавиатуры для интерактивного взаимодействия
- ✅ Callback обработка для кнопок
- ✅ Middleware для логирования, троттлинга, обработки ошибок
- ✅ Роутеры для разделения логики
- ✅ Обработка событий (запуск бота, добавление пользователя и т.д.)
Все примеры можно найти в папке examples
репозитория.