Skip to main content

Quick and easy creation of surveys, questionnaires, and forms using aiogram-dialog

Project description

Документация по библиотеке aiogram_dialog_survey

Обзор

Библиотека aiogram_dialog_survey предоставляет инструменты для легкого создания больших интерактивных анкет в Telegram ботах на основе aiogram и aiogram_dialog. Основные возможности:

  • Поддержка различных типов вопросов: текстовый ввод, выбор одного варианта, множественный выбор
  • Генерация диалоговых окон для каждого вопроса. Ощутимо уменьшает кол-во повторяющегося, рутинного кода
  • Кастомизация обработчиков событий. Достаточно написать один обработчик, который будет взаимодействовать с ответами от пользователя

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

Установка

pip install aiogram_dialog_survey

Минимальный пример бота

from aiogram import Bot, Dispatcher, types
from aiogram.filters import CommandStart
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram_dialog import DialogManager, setup_dialogs

from aiogram_dialog_survey import Survey, StartSurvey
from aiogram_dialog_survey.entities.question import WidgetType, Question
from aiogram_dialog_survey.entities.button import Button

# Определяем вопросы анкеты
questions = [
    Question(
        name="name",
        widget_type=WidgetType.TEXT_INPUT,
        text="Как вас зовут?",
        is_required=True
    ),
    Question(
        name="age",
        widget_type=WidgetType.SELECT,
        text="Сколько вам лет?",
        is_required=True,
        buttons=[
            Button(text="До 18", callback="under_18"),
            Button(text="18-25", callback="18_25"),
            Button(text="26-35", callback="26_35"),
            Button(text="Старше 35", callback="over_35"),
        ]
    )
]

# Создаем анкету
survey = Survey(name="user_survey", questions=questions)


async def start_handler(message: types.Message, dialog_manager: DialogManager):
    await dialog_manager.start(survey.state_manager.get_first_state())


async def main():
    bot = Bot(token="YOUR_BOT_TOKEN")
    dp = Dispatcher(storage=MemoryStorage())

    # Регистрируем анкету как диалог
    dp.include_router(survey.to_dialog())
    dp.message.register(start_handler, CommandStart())

    setup_dialogs(dp)
    await dp.start_polling(bot)

Создание анкеты

Определение вопросов

Вопросы определяются с помощью класса Question:

from aiogram_dialog_survey.interface import Question
from aiogram_dialog_survey.entities.question import WidgetType
from aiogram_dialog_survey.entities.button import Button

# Вопросы, их типы и варианты ответов можно хранить в БД или в любом другом удобном месте, чтобы не засорять кодовую базу проекта и сосредоточится на более важных аспектах
questions = [
    Question(
        name="username",  # уникальный идентификатор вопроса
        question_type=WidgetType.TEXT_INPUT,  # тип вопроса
        text="Введите ваше имя:",  # текст вопроса
        is_required=True  # обязательный ли вопрос
    ),
    Question(
        name="hobbies",
        question_type=WidgetType.MULTISELECT,
        text="Выберите ваши увлечения:",
        is_required=False,
        buttons=[
            Button(text="Спорт", callback="sport"),
            Button(text="Музыка", callback="music"),
            Button(text="Кино", callback="movies"),
        ]
    ),
    #
    # еще очень-очень много вопросов
    #
    Question(
        name="height",
        question_type=WidgetType.TEXT_INPUT,
        text="Введите ваш рост:",
        is_required=True
    ),
]

Доступные типы вопросов:

  1. QuestionType.TEXT - текстовый ввод
  2. QuestionType.SELECT - выбор одного варианта из списка
  3. QuestionType.MULTISELECT - множественный выбор

Создание анкеты

from aiogram_dialog_survey import Survey

survey = Survey(
    name="user_survey",  # уникальное имя анкеты
    questions=questions,  # список вопросов
    use_numbering=True  # показывать нумерацию вопросов (по умолчанию True)
)

Подключение анкеты к роутеру

Подключение происходит точно так же, как с обычными aiogram-dialog диалогами

from aiogram import Bot, Dispatcher
from aiogram.fsm.storage.memory import MemoryStorage

bot = Bot(token="YOUR_BOT_TOKEN")
dp = Dispatcher(storage=MemoryStorage())

# Добавляем анкету как диалог
dp.include_router(survey.to_dialog())

Кастомизация

Пользовательские обработчики событий

Вы можете создать собственный обработчик событий, унаследовавшись от IWindowHandler:

from aiogram_dialog_survey.protocols.handler import HandlerProtocol
from aiogram_dialog_survey.entities.action_type import ActionType
from aiogram_dialog import DialogManager


class CustomHandler(HandlerProtocol):
    @staticmethod
    async def process_handler(
        manager: DialogManager,
        question_name: str,
        action_type: ActionType
    ) -> None:
        answer = manager.dialog_data.get(question_name)
        # Кастомная логика обработки событий

    print(f"Пользователь ответил: "
    {answer}
    " на вопрос {question_name}")

    # Использование кастомного обработчика
    survey = Survey(
        name="custom_survey",
        questions=questions,
        handler=CustomHandler
    )

Такой обработчик отлично подойдет, если вы хотите каждый раз, когда пользователь отвечает на вопрос, обрабатывать его и, допустим, записывать в БД ответ пользователя и его прогресс прохождения анкеты.

В process_handler вы так же можете запускать еще subdialog в зависимости от ответа

from aiogram_dialog_survey.protocols.handler import HandlerProtocol
from aiogram_dialog_survey.entities.action_type import ActionType
from aiogram_dialog import DialogManager

from your_module import music_artist_survey


class CustomHandler(HandlerProtocol):
    @staticmethod
    async def process_handler(
        manager: DialogManager,
        question_name: str,
        action_type: ActionType
    ) -> None:
        answer = manager.dialog_data.get(question_name)

    if question_name == 'do_you_like_music' and answer == 'yes':
        manager.start(music_artist_survey.state_manager.get_first_state())

Обработка результатов анкеты

Для обработки результатов анкеты можно использовать callback-функцию on_process_result:

async def survey_result_handler(result, dialog_manager: DialogManager):
    print("Результаты анкеты:", result)
    await dialog_manager.event.answer("Спасибо за заполнение анкеты!")

survey_dialog = survey.to_dialog(on_process_result=survey_result_handler)

Расширенные возможности

Интеграция с существующими диалогами

Вы можете добавить анкету как часть большего диалога, в данном примере, StartSurvey напустить subdialog с анкетой, по завершению которой вы можете получить результат в вашем обработчике on_result:

from aiogram.fsm.state import StatesGroup, State
from aiogram_dialog import Dialog, Window
from aiogram_dialog.widgets.kbd import Button
from aiogram_dialog.widgets.text import Const
from aiogram_dialog_survey import StartSurvey

class MainSG(StatesGroup):
    start = State()
    survey = State()
    finish = State()

main_dialog = Dialog(
    Window(
        Const("Добро пожаловать!"),
        StartSurvey(
            Const("Начать анкету"),
            survey,
            id="start_survey"
        ),
        state=MainSG.start,
    ),
    Window(
        Const("Спасибо за участие!"),
        state=MainSG.finish,
    )
)

async def survey_result_handler(result, dialog_manager: DialogManager):
    print("Результаты анкеты:", result)
    await dialog_manager.switch_to(state=MainSG.finish)

survey_dialog = survey.to_dialog(on_process_result=survey_result_handler)
# Добавляем оба диалога в диспетчер
dp.include_routers(main_dialog, survey_dialog)

Примеры использования

Полный пример бота с анкетой

import logging
from aiogram import Bot, Dispatcher, types
from aiogram.filters import CommandStart
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram_dialog import DialogManager, setup_dialogs

from aiogram_dialog_survey import Survey
from aiogram_dialog_survey.interface import Question
from aiogram_dialog_survey.entities.question import WidgetType
from aiogram_dialog_survey.entities.button import Button

# Настройка логирования
logging.basicConfig(level=logging.INFO)

# Определение вопросов анкеты
questions = [
    Question(
        name="name",
        question_type=WidgetType.TEXT_INPUT,
        text="Как вас зовут?",
        is_required=True
    ),
    Question(
        name="age_group",
        question_type=WidgetType.SELECT,
        text="Ваша возрастная группа?",
        is_required=True,
        buttons=[
            Button(text="До 18", callback="under_18"),
            Button(text="18-25", callback="18_25"),
            Button(text="26-35", callback="26_35"),
            Button(text="36-45", callback="36_45"),
            Button(text="Старше 45", callback="over_45"),
        ]
    ),
    Question(
        name="interests",
        question_type=WidgetType.MULTISELECT,
        text="Какие темы вам интересны? (можно выбрать несколько)",
        is_required=False,
        buttons=[
            Button(text="Технологии", callback="tech"),
            Button(text="Наука", callback="science"),
            Button(text="Искусство", callback="art"),
            Button(text="Спорт", callback="sport"),
        ]
    )
]

# Создание анкеты
survey = Survey(
    name="user_profile",
    questions=questions,
    use_numbering=True
)


async def start_handler(message: types.Message, dialog_manager: DialogManager):
    # метод get_first_state() можно использовать, если вы хотите запустить анкету не с помощью кнопки StartSurvey, как мы это делаем в существующем диалоге, а благодаря dialog_manager
    await dialog_manager.start(survey.state_manager.get_first_state())


async def survey_result_handler(result, dialog_manager: DialogManager):
    await dialog_manager.event.answer(
        "Спасибо за заполнение анкеты! Ваши ответы сохранены."
    )
    logging.info("Сохраняем результаты анкеты: %s", result)


async def main():
    bot = Bot(token="YOUR_BOT_TOKEN")
    dp = Dispatcher(storage=MemoryStorage())

    # Добавляем анкету с обработчиком результатов
    dp.include_router(survey.to_dialog(on_process_result=survey_result_handler))
    dp.message.register(start_handler, CommandStart())

    setup_dialogs(dp)
    await dp.start_polling(bot)


if __name__ == "__main__":
    import asyncio

    asyncio.run(main())

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

aiogram_dialog_survey-0.3.2.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

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

aiogram_dialog_survey-0.3.2-py3-none-any.whl (27.5 kB view details)

Uploaded Python 3

File details

Details for the file aiogram_dialog_survey-0.3.2.tar.gz.

File metadata

  • Download URL: aiogram_dialog_survey-0.3.2.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.10.12 Linux/6.8.0-60-generic

File hashes

Hashes for aiogram_dialog_survey-0.3.2.tar.gz
Algorithm Hash digest
SHA256 ffed8f2cebb0dca1632999cde114a52f19e2df5945936b6bd0d365c34f86b7d6
MD5 948143c03e74c37c14d6a5138d2ab76e
BLAKE2b-256 b56cd414173073ab055d06cbb3a106c9bad2bbfdbb96f1a0b5d8410f97e1bb0f

See more details on using hashes here.

File details

Details for the file aiogram_dialog_survey-0.3.2-py3-none-any.whl.

File metadata

File hashes

Hashes for aiogram_dialog_survey-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e49fc67bddee6a599539ebbcc18df1e1542179faed7a8eec2678c39138264460
MD5 8a40306678201c1d4c47f4d7dc196483
BLAKE2b-256 58aff35e1458d7e4911df037322e0a0b91e9d6c087983ba579a324c468683d0d

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