Недавно VK сделал новый мессенджер - Max - который рекламируют как отечественный аналог WeChat. Пока что он немного сыроват, но в нём видно потенциал. Сегодня мы будем писать бота на Python для этого мессенджера.
Создаем аккаунт бота
Для создания аккаунтов ботов есть специальный бот - @MasterBot. Переходим в него и нажимаем "Начать"

Дальше пишем /create, чтобы создать нового бота.
MasterBot предложит нам придумать уникальное имя пользователя для бота, которое должно быть больше 11 символов (да, не меньше) и должно заканчиваться на _bot
или bot
. Я назову своего бота @aiomax_test_bot
.
Дальше пишем имя бота, которое будет отображаться в чатах и вверху диалога с ботом. Оно не должно быть уникальным. Я назову своего "Кликер бот"

Бюрократическая часть окончена! Копируем токен бота, который вам прислал MasterBot и переходим в редактор кода.
Скелет бота
Переходим в командную строку и пишем следующее:
pip install aiomax
В новом Python-файле пишем это:
import aiomax
import logging
Библиотека logging
нам понадобится для проверки, точно ли бот работает и получать от него вывод. Использовать её необязательно.
Далее нам пригодится ранее скопированный токен бота. Добавляем к коду следующее:
bot = aiomax.Bot("TOKEN", default_format="markdown")
Вместо TOKEN
вставляем ваш токен.
default_format="markdown"
устанавливает систему разметки Markdown сообщений по умолчанию. Если её не указать тут, то разметку (жирный, курсивный и все другие шрифты) использовать не получится.
В конец вашего файла пишем это:
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
bot.run()
logging.basicConfig(level=logging.INFO)
настраивает логгер для вывода нужной информации, а bot.run()
запустит бота при запуске Python-файла.
Скелет готов! Приступаем к созданию самого бота.
Эхо-бот
Очень часто первые написанные боты делают эхо-ботами. И мы не будем исключением. Пишем вот этот код до блока if __name__ == "__main__"
:
# Отправка информации о боте при нажатии кнопки "Начать" в мессенджере
@bot.on_bot_start()
async def info(pd: aiomax.BotStartPayload):
await pd.send("Я повторяю за тобой")
# Функция будет выполняться при отправке любого сообщения
@bot.on_message()
async def echo(message: aiomax.Message):
await message.send(message.content)
Давайте разберём код.
Декоратор @bot.on_bot_start()
запускает функцию ниже него, когда кто-то запускает бота в мессенджере и передаёт функции параметр pd
(Payload). У этого pd
есть функция send
, которая отправляет сообщение в чат тому, кто запустил бота.
Декоратор @bot.on_message()
запускает функцию ниже него, когда кто-то отправляет сообщение в любой чат и передает функции параметр message
(отправленное сообщение). У message
есть функция send
, которая отправляет сообщение в тот же чат, в который поступило сообщение, и параметр content
, в котором содержится текст сообщения.
Вместо send
в await message.send(message.content)
можно написать reply
- тогда вы не просто отправите сообщение в тот же чат, а ответите на поступившее сообщение.
Полный код бота, которого мы только что написали:
import aiomax
import logging
bot = aiomax.Bot("TOKEN", default_format="markdown")
# Отправка информации о боте при нажатии кнопки "Начать" в мессенджере
@bot.on_bot_start()
async def info(pd: aiomax.BotStartPayload):
await pd.send("Я повторяю за тобой")
# Функция будет выполняться при отправке любого сообщения
@bot.on_message()
async def echo(message: aiomax.Message):
await message.send(message.content)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
bot.run()
Запускаем Python-файл, пишем боту и видим, что всё работает!

Кликер-бот
А теперь напишем бота с кнопками у сообщений.
Есть глобальный счётчик. При нажатии пользователем на кнопку, этот счётчик будет увеличиваться для всех.
Для начала возьмём старый скелет и добавим туда функции:
import aiomax
import logging
bot = aiomax.Bot("TOKEN", default_format="markdown")
taps = 0
# Создаём клавиатуру
kb = aiomax.buttons.KeyboardBuilder()
button = aiomax.buttons.CallbackButton('Нажми на меня!', 'click')
kb.add(button)
# Отправляем сообщение с информацией о боте при запуске
@bot.on_bot_start()
async def info(pd: aiomax.BotStartPayload):
await pd.send(f"**Жми**!\nТапы: {taps}", keyboard=kb)
# Отправляем сообщение с кнопкой при вводе команды /tap
@bot.on_command('tap')
async def tap_command(ctx: aiomax.CommandContext):
await ctx.reply(f"**Жми!**\nТапы: {taps}", keyboard=kb)
# Обрабатываем нажатие на кнопку в сообщении
@bot.on_button_callback('click')
async def on_tap(callback: aiomax.Callback):
global taps # Делаем taps глобальной переменной, чтобы изменять её по всему боту
taps += 1
await callback.answer(text=f"Жми!\nТапы: **{taps}**")
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
bot.run()
Кроме привычного создания бота, его запуска, и декоратора on_bot_start
, появилось ещё много нового. Давайте рассмотрим поближе.
kb = aiomax.buttons.KeyboardBuilder()
создаёт новую клавиатуру, которую мы будем прикреплять к сообщениям.button = aiomax.buttons.CallbackButton('Нажми на меня!', 'click')
создаёт новую кнопку с текстом Нажми на меня!
и специальным пейлоадом click
, по которому можно проверять, какая именно кнопка нажата.
И наконец, kb.add(button)
добавляет эту кнопку на нашу клавиатуру.
@bot.on_command('tap')
создаёт новую команду с именем tap
.
Наш декоратор on_command
вызовется тогда, когда пользователь отправит боту /tap
.
Вместо message
декоратор on_command
передаёт нам объект CommandsContext
, который отличается от Message
, но точно также имеет функции send
и reply
.
Функция после @bot.on_button_callback('click')
запускается при нажатии кнопки с указанным ожидаемым пейлоадом. Так как пейлоад у нашей кнопки - click
, тут напишем также.
Этот декоратор возвращает объект Callback
, который уже отличается от прошлых on_command
и on_message
. В нём нету ни send
, ни reply
, зато есть функция answer
- она отвечает на нажатие кнопки определенным действием.
В нашем случае мы просто поменяем текст сообщения на новый, который напишем после text=
.
Будьте внимательны - если не указать text=
, а просто написать строку, то текст сообщения не изменится. Вместо этого пользователю отправится уведомление, которые сейчас отображаются только на iPhone.
Запускаем файл, и видим, что бот работает как нужно!

FSM
Если захотелось, чтобы у каждого пользователя был свой отдельный счётчик, то можно использовать FSM.
import aiomax
import logging
from aiomax import fsm
bot = aiomax.Bot("TOKEN", default_format="markdown")
# Создаём клавиатуру
kb = aiomax.buttons.KeyboardBuilder()
button = aiomax.buttons.CallbackButton('Нажми на меня!', 'click')
kb.add(button)
# Отправляем сообщение с информацией о боте при запуске
@bot.on_bot_start()
async def info(pd: aiomax.BotStartPayload, cursor: fsm.FSMCursor):
taps = cursor.get_data()
if not taps:
taps = 0
await pd.send(f"**Жми**!\nТапы: {taps}", keyboard=kb)
# Отправляем сообщение с кнопкой при вводе команды /tap
@bot.on_command('tap')
async def tap_command(ctx: aiomax.CommandContext, cursor: fsm.FSMCursor):
taps = cursor.get_data()
if not taps:
taps = 0
await ctx.reply(f"**Жми!**\nТапы: {taps}", keyboard=kb)
# Обрабатываем нажатие на кнопку в сообщении
@bot.on_button_callback('click')
async def on_tap(callback: aiomax.Callback, cursor: fsm.FSMCursor):
taps = cursor.get_data()
if not taps:
taps = 0
taps += 1
cursor.change_data(taps)
await callback.answer(text=f"Жми!\nТапы: **{taps}**")
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
bot.run()
Можно сразу заметить, что taps
сверху пропало, добавилось from aiomax import fsm
и в каждой функции появились конструкции с cursor
. Давайте рассмотрим.
Чтобы получить курсор пользователя в почти любом декораторе, в списках аргументов вашей функции можно добавить аргумент cursor
- aiomax его увидит и передаст туда курсор.
С помощью курсора можно менять состояние и данные определенного пользователя.
taps = cursor.get_data()
получает данные, которые хранятся у пользователя в текущий момент.if not taps: taps = 0
проверяет, хранятся ли какие-либо данные у пользователя - если нет, то сохраняет в переменной 0
, дабы избежать ошибок.
cursor.change_data(taps)
изменяет текущие хранящиеся данные пользователя на новые - в нашем случае новое количество нажатий.
Заключение
Если вы хотите подробнее ознакомиться с библиотекой aiomax, можете почитать документацию в репозитории проекта.
Обсудить aiomax или задать вопросы можно в чатах aiomax Community в Telegram или самом Max.