vkbottle-dialog
Декларативные диалоги для VK-ботов поверх vkbottle — порт aiogram-dialog на VK.
Что это
В обычном vkbottle-боте многошаговые сценарии (анкеты, меню, мастера) собираются вручную: свой FSM,
свои клавиатуры, свои проверки "а что если пользователь написал не то". vkbottle-dialog берёт эту
рутину на себя — так же, как aiogram-dialog делает это для aiogram/Telegram:
- Window — экран (текст + клавиатура + приём ввода), Dialog — набор окон на одном FSM-стейте.
- Навигация между окнами (
SwitchTo,Back,Next), между диалогами (Start,Cancel,done()с результатом родителю). - Виджеты клавиатур:
Select/Radio/Multiselect/Toggle/Checkbox, группировкаGroup/Row/Column, пагинацияScrollingGroup. - Приём текстового ввода:
TextInput(с валидацией черезtype_factory),MessageInput. - Хранение состояния диалога:
MemoryStorage(для разработки) илиRedisStorage(для прод).
Quickstart
import os
from vkbottle import Bot
from vkbottle_dialog import Dialog, StartMode, Window, setup_dialogs
from vkbottle_dialog.fsm import State, StatesGroup
from vkbottle_dialog.integration import NotInDialog
from vkbottle_dialog.storage import MemoryStorage
from vkbottle_dialog.widgets.kbd import Cancel, SwitchTo
from vkbottle_dialog.widgets.text import Const
class MenuSG(StatesGroup):
main = State()
info = State()
dialog = Dialog(
Window(
Const("Главное меню. Выберите пункт:"),
SwitchTo(Const("О боте"), id="to_info", state=MenuSG.info),
Cancel(Const("Закрыть")),
state=MenuSG.main,
),
Window(
Const("Это демонстрационный бот на vkbottle-dialog."),
SwitchTo(Const("Назад"), id="to_main", state=MenuSG.main),
state=MenuSG.info,
),
)
bot = Bot(os.environ["VK_TOKEN"])
setup_dialogs(bot, dialog, storage=MemoryStorage())
@bot.on.message(NotInDialog(), text="/start")
async def start(message, dialog_manager):
await dialog_manager.start(MenuSG.main, mode=StartMode.RESET_STACK)
if __name__ == "__main__":
bot.run_forever()
Больше примеров — в examples/: menu.py, survey.py (анкета с валидацией ввода),
pagination.py (список на 30 позиций), nested.py (вложенные диалоги с возвратом результата),
chat.py (работа в беседах).
Обязательно
(а) Правило NotInDialog() / InDialog() для ВСЕХ соседних @bot.on.message-хендлеров.
vkbottle не блокирует события между views: DialogView, который подключает setup_dialogs, —
это всего лишь один из views в labeler.views(), он выполняется наравне с остальными хендлерами, а
не "перехватывает" их. Если рядом с диалогом зарегистрирован обычный @bot.on.message(text="/start")
без NotInDialog(), он сработает поверх активного диалога так, будто диалога нет — сообщение
пользователя внутри диалога может случайно попасть не туда, а повторный /start пересоздаст диалог
поверх уже открытого окна. Каждый хендлер, который должен видеть/не видеть активный диалог,
обязан использовать NotInDialog() (сработает, только если у пользователя нет активного
диалога) или InDialog() (сработает, только если диалог активен) — см. dialog_manager в
сигнатуре хендлера, который эти правила инжектят.
(б) В настройках сообщества обязательно включить событие message_event и Long Poll API.
Инлайн-клавиатуры диалогов кликаются через message_event (callback-кнопки) — без этого события
нажатия на кнопки будут молча теряться. Long Poll API должен быть включён и настроен на версию API,
поддерживающую message_event (VK API ≥ 5.103).
Соответствие aiogram-dialog → vkbottle-dialog
| aiogram-dialog | vkbottle-dialog (v0.2) | Статус |
|---|---|---|
Dialog, Window, DialogManager |
Dialog, Window, DialogManager |
✅ |
Const, Format, Case, Multi, Or |
Const, Format, Case, Multi, Or |
✅ |
Button, Url, SwitchTo, Back, Next, Cancel, Start |
то же самое | ✅ |
Group, Row, Column |
Group, Row, Column |
✅ |
Select, Radio, Multiselect, Toggle, Checkbox |
то же самое | ✅ |
ScrollingGroup + пейджеры (NumberedPager, FirstPage/PrevPage/CurrentPage/NextPage/LastPage, SwitchPage) |
то же самое | ✅ |
MessageInput, TextInput |
MessageInput, TextInput |
✅ |
Calendar |
Calendar (COMPACT, WIDE) + TimeSelect |
✅ |
Counter |
Counter |
✅ |
ListGroup |
List (постраничный вывод page_size) |
✅ |
Text + ScrollingGroup |
ScrollingText |
✅ |
Медиа-виджеты (StaticMedia) |
StaticMedia + MediaResolver (кэш загрузок) |
✅ |
ListGroup, SubManager |
— | 🗺️ роадмап |
DynamicMedia |
— | 🗺️ роадмап |
| Карусель (media group) | — | 🗺️ роадмап |
StartMode.NEW_STACK |
— | 🗺️ роадмап (пока NotImplementedError) |
AccessSettings |
— | 🗺️ роадмап |
| Jinja-шаблоны для текста | — | 🗺️ роадмап |
Мульти-инстанс (несколько setup_dialogs в процессе) |
— | 🗺️ роадмап (сейчас один setup_dialogs на процесс) |
Календарь и лимиты VK
Calendar (v0.2): два режима верстки —
CalendarLayout.COMPACT(по умолчанию): 6 дней на страницу (по 3 в строке), пагинация; подходит для беседы (≤10 кнопок).CalendarLayout.WIDE: весь месяц за раз (до 35 кнопок), ≤ 5 дней в строке; работает только в личных сообщениях (в беседе упадёт сDialogConfigError).
TimeSelect (v0.2): выбор часа/минуты по слотам, постранично, укладывается в лимит 10 кнопок.
Медиа в диалогах (v0.2): StaticMedia + MediaResolver (кэширование attachment-строк за сессию). При отсутствии доступа к медиа вложение деградирует без ошибки; перед продом проверьте доступ кросс-peer (группа ↔ личные сообщения) ручным смоуком.
Ограничения v0.2
- Single-instance. На процесс можно вызвать
setup_dialogs()один раз —InDialog()/NotInDialog()резолвятся late-binding к последнему активному сетапу. StartMode.NEW_STACKне реализован —manager.start(..., mode=StartMode.NEW_STACK)кидаетNotImplementedError. ИспользуйтеStartMode.NORMALилиStartMode.RESET_STACK.TextKeyboardFactoryработает только в личных сообщениях. В беседах нижняя (не-инлайн) клавиатура общая на весь чат, поэтому рендер диалога с текстовой клавиатурой в беседе — ошибка конфигурации (DialogConfigError). То же верно дляCalendarLayout.WIDE— в беседе используйте толькоCOMPACT.- 24-часовое окно редактирования сообщений VK. Диалог обновляет своё окно, редактируя одно и то
же сообщение; когда VK перестаёт разрешать правку (окно устарело), пользователь при клике по
устаревшей клавиатуре увидит снекбар «Окно устарело, начните заново» вместо тихого зависания
(настраивается через
stale_snackbar=вsetup_dialogs). - Лимит инлайн-клавиатуры VK — 10 кнопок (и до 6 строк, не больше 5 кнопок в строке) — учитывайте
при проектировании окон с большим числом виджетов; для длинных списков используйте
ScrollingGroup.
VK-расширения
Помимо API aiogram-dialog, доступны VK-специфичные возможности:
Button(..., color=ButtonColor.POSITIVE)— цвет инлайн-кнопки (PRIMARY/SECONDARY/NEGATIVE/POSITIVE).Button(..., snackbar="Текст")— показать всплывающее уведомление сразу при клике, без ручного вызоваmanager.answer().manager.answer(snackbar=..., open_link=...)— ответ наmessage_event(снекбар и/или открытие ссылки на клиенте); доступно только для событий кнопок, не для обычных сообщений.
Установка
pip install vkbottle-dialog
Для хранения состояния диалогов в Redis (прод-режим, вместо MemoryStorage):
pip install vkbottle-dialog[redis]
from redis.asyncio import Redis
from vkbottle_dialog.storage import RedisStorage
storage = RedisStorage(Redis.from_url("redis://localhost"))
setup_dialogs(bot, dialog, storage=storage)
English
vkbottle-dialog is a declarative dialog/window framework for VK bots built on top of
vkbottle — a VK port of
aiogram-dialog. It provides Dialog/Window
abstractions, navigation widgets, keyboard widgets (Select, Radio, Multiselect, Toggle,
Checkbox, ScrollingGroup), text input handling (TextInput, MessageInput) and pluggable
storage (MemoryStorage, RedisStorage).
Must read before using: because vkbottle does not block events between views, every neighboring
@bot.on.message handler must use the NotInDialog() / InDialog() rules so it doesn't fire on top
of an active dialog. Your community must also have the message_event event and Long Poll API
enabled, or button clicks will be silently dropped.
See the RU section above for the full feature-parity table with aiogram-dialog, v0.1 limitations
(single-instance, no StartMode.NEW_STACK, text-keyboard degradation only in DMs, VK's 24h message
edit window, 10-button inline limit) and installation instructions
(pip install vkbottle-dialog[redis] for Redis-backed storage). Runnable examples live in
examples/.
License: Apache-2.0.
Release files for vkbottle-dialog 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vkbottle_dialog-0.2.0.tar.gz | 183.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vkbottle_dialog-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 247.4 kB
Release files / vkbottle_dialog-0.2.0.tar.gz
| Download URL | vkbottle_dialog-0.2.0.tar.gz |
|---|---|
| Size | 183.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9b5294d939db5258a5b5198c6c376df308135f05ad9cbc9a18067e96ffce1d31
|
|
BLAKE2b-256 checksum How to use checksums |
f6f19978c6c345106ff406dad385709cc716bae3131a708fffdd1aea0e5957c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.15
|
Release files / vkbottle_dialog-0.2.0-py3-none-any.whl
| Download URL | vkbottle_dialog-0.2.0-py3-none-any.whl |
|---|---|
| Size | 64.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
62b88861d45db34adee6321357a953d5b56dc89a0da0cc0f50893e96b62ac9b1
|
|
BLAKE2b-256 checksum How to use checksums |
294758845fdd7603eed4a5d8aacf085c97a086540b6946a2790c2d4dce1fccb9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.15
|