Простенький бот анкетник под сбор инфы о пользователе в Телеграм (Asyncio, Aiogram 3)

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Нигде не нашел в паблике простенький опросник пользователя в тг на предмет его фамилии имени отчества, номера телефона, и прочей инфы (добавляйте уже сами что хотите). Полезно будет посмотреть как работает машина состояний в 3 версии Aiogram на моем примере.

Устанавливаем: pip install aiogram


bot.py:
Python: Скопировать в буфер обмена
Код:
import asyncio
from aiogram import Bot, Dispatcher
from handlers import questions, different_types


# Запуск бота
async def main():
    bot = Bot(token="сюда забиваем ваш токен из Botfather")
    dp = Dispatcher()

    dp.include_routers(questions.router, different_types.router)

    # Альтернативный вариант регистрации роутеров по одному на строку
    # dp.include_router(questions.router)
    # dp.include_router(different_types.router)

    # Запускаем бота и пропускаем все накопленные входящие
    # Да, этот метод можно вызвать даже если у вас поллинг
    await bot.delete_webhook(drop_pending_updates=True)
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())

keyboards/for_questions.py:
Python: Скопировать в буфер обмена
Код:
from aiogram.types import ReplyKeyboardMarkup
from aiogram.utils.keyboard import ReplyKeyboardBuilder

def get_yes_no_kb() -> ReplyKeyboardMarkup:
    kb = ReplyKeyboardBuilder()
    kb.button(text="Да")
    kb.button(text="Нет")
    kb.adjust(2)
    return kb.as_markup(resize_keyboard=True)

handlers/questions.py:

Python: Скопировать в буфер обмена
Код:
from aiogram import Router, F, Bot
from aiogram.filters import Command, StateFilter
from aiogram.types import Message, ReplyKeyboardRemove
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import default_state, State, StatesGroup
from aiogram.fsm.storage.memory import MemoryStorage
from keyboards.for_questions import get_yes_no_kb

router = Router()  # [1]

# Создаем базу данных пользователей
user_dict: dict[int, dict[str, str | int | bool]] = {}


#Объявляем стэйты
class FSMFillForm(StatesGroup):
    fill_name = State()
    fill_age = State()
    fill_phone = State()

@router.message(Command("start"))  # [2]
async def cmd_start(message: Message):
    await message.answer(
        "Вы готовы вступить в наше движение?",
        reply_markup=get_yes_no_kb()
    )

@router.message(F.text.lower() == "да")
async def answer_anketa_yes(message: Message, state: FSMContext):
    await message.answer(
        "Это здорово! Заполните пожалуйста анкету о себе.",
        reply_markup=ReplyKeyboardRemove()
    )
    await message.answer("Ваше ФИО:")
    #Состояние ожидания ввода ФИО
    await state.set_state(FSMFillForm.fill_name)

@router.message(StateFilter(FSMFillForm.fill_name))
async def anceta_name(message: Message, state: FSMContext):
    #Сохранение введенного имени в хранилище
    await state.update_data(name=message.text)
    await message.answer("Введите Ваш возраст?")
    #Состояние ожидания ввода возраста
    await state.set_state(FSMFillForm.fill_age)

@router.message(StateFilter(FSMFillForm.fill_age))
async def anceta_name(message: Message, state: FSMContext):
    #Сохранение введенного возраста в хранилище
    await state.update_data(age=message.text)
    await message.answer("Теперь введите Ваш личный телефон")
    #Состояние ожидания ввода возраста
    await state.set_state(FSMFillForm.fill_phone)

@router.message(StateFilter(FSMFillForm.fill_phone))
async def anceta_name(message: Message, bot: Bot, state: FSMContext):
    #Сохранение введенного телефона в хранилище
    await state.update_data(phone=message.text)
    await message.answer("Ваши данные сохранены и отправлены администратору")
    user_dict[message.from_user.id] = await state.get_data()
    await state.clear()
    # Отправляем администратору сохраненные данные, chat_id = id администратора бота
    await bot.send_message(chat_id=6483026888, text=f'ФИО: {user_dict[message.from_user.id]["name"]} \n' #ID администратора бота
                              f'Возраст: {user_dict[message.from_user.id]["age"]}\n'
                              f'Телефон: {user_dict[message.from_user.id]["phone"]}\n')

@router.message(F.text.lower() == "нет")
async def answer_no(message: Message):
    await message.answer(
        "Жаль...",
        reply_markup=ReplyKeyboardRemove()
    )

Как это работает:

Юзер попадает на бота и жмет /start, отвечает на вопрос по кнопке ДА:

1714237192378.png



Бот ведет опрос:
1714237361845.png



Нужная инфа прилетает администратору бота:
1714237443768.png




P.S. Очень эффективно альтернативе гугл анкетирования, бота можно расширить и допилить под свои цели. Выставив всякого рода проверки или добавления других типов данных (Фото, файлы).
 
Сверху Снизу