- Saved searches
- Use saved searches to filter your results more quickly
- MaxBstr/SimpleSurveyBot
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- Опросы в Telegram-боте с помощью AIOGram с записью в JSON
- Установка библиотек и структура проекта
- Разбор кода для создания опросника
- Utils
- States
- Keyboards
- Handlers
- Подробнее о сохранении в файл
- Заключение
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
simple python telegram bot
MaxBstr/SimpleSurveyBot
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
Бот для проведения опросов.
- Команда /start возвращает описание бота и меню из двух кнопок, “Создать опрос” и “Статистика”
- Опрос — сообщение с вопросом и вариантами ответа в виде InlineKeyboardMarkup
- Команда /start , например, /start 123. Ответ — опрос
- После нажатия на кнопку в опросе текст сообщения должен заменяться на «ответ отправлен». При повторном вызове команды выводится ошибка, что проходить опрос нужно единожды.
- При нажатии на создать опрос — многоуровневый диалог, в котором поступает информация от пользователя — вопрос и варианты ответов. Реализовано с помощью finite state machine (FSM). Вариантов ответа от 2 до 6. После создания опроса пользователь получает ссылку на опрос вида: https://t.me/?start=
- При нажатии на кнопку статистика — меню для выбора опроса с пагинацией с помощью InlineKeyboardMarkup. При нажатии на кнопку — отправить сообщение со статистикой по опросу.
aiogram postgresql tortoise-orm
Опросы в Telegram-боте с помощью AIOGram с записью в JSON
Сегодня мы разберем как сделать опросник в Telegram и запустить сбор данных о пользователях. Чтобы не повторяться, буду иногда обращаться к предыдущим статьям.
Для создания опросника мы воспользуемся библиотекой AIOGram.
Результаты опросов будем сохранять в файл JSON.
Что потребуется для создания опросника:
- Компьютер или ноутбук (для особых извращений можно и телефон)
- Редактор кода (У меня PyCharm)
- Python версии 3.9 и выше
- Соединение с интернетом
Установка библиотек и структура проекта
Установка AIOGram для Windows:
pip3 install aiogram json
Пользоваться будем уже известным шаблоном для разработки бота .
При разработке подобных проектов шаблон сильно упростит вам жизнь.
+---telegram_bot | +---handlers | | +---Users | | | +---__init__.py | | | +---help.py | | | +---audio.py | | | \---start.py | | \---__init__.py | +---states | | +---__init__.py | | \---dowload.py | +---keyboards | | | +---inline | | | |---choice_but_start_test.py | | | \---__init__.py | | \---__init__.py | +---utils | | +---__init__.py | | \---set_bot_commands.py | +---app.py | \---loader.py
Как и в прошлом разборе , мы будем двигаться по всем директориям и рассматривать написанный код.
Разбор кода для создания опросника
from aiogram import Bot, Dispatcher, types from aiogram.contrib.fsm_storage.memory import MemoryStorage token = '52627**************HQvtGZWe_BTVyKi4H1FvT_ezSCy8' bot = Bot(token=token, parse_mode=types.ParseMode.HTML) storage = MemoryStorage() dp = Dispatcher(bot, storage=storage)
Импортируем класс бота, диспетчера и типы, а также класс для хранения информации в оперативной памяти.
Дальше сохраняем в переменную токен (как его получить смотрите тут ), после чего инициализируем бота и диспетчера.
Этот файл будет мотором нашего бота. В дальнейшем мы будем обращаться сюда, чтобы расширять наши возможности.
Как и в прошлом гайде, этот файл будет собирать все хендлеры и инициализировать их, чтобы потом запускать прием от API:
from aiogram import executor from loader import dp import handlers from utils.set_bot_commands import set_default_commands async def on_startup(dispatcher): # Устанавливаем дефолтные команды await set_default_commands(dispatcher) if __name__ == '__main__': executor.start_polling(dp, on_startup=on_startup)
Utils
Set_bot_commands.py
В этом файле мы создаем команды, которые отображаются в меню. Первый аргумент — вызов команды, второй — её описание:
from aiogram import types async def set_default_commands(dp): await dp.bot.set_my_commands( [ types.BotCommand("start", "Запустить бота"), types.BotCommand("help", "Вывести справку"), types.BotCommand("onstarttest", "Пройти первый опрос"), ] )
States
from .on_start_test import CallbackOnStart
Подробнее о пакетах в python: ссылка на статью, ссылка на видео.
Для представления о пакетах этих ссылок хватит.
On_start_test.py
В этом файле будут храниться наши состояния, в которые мы будем сохранять информацию на время опроса. Подробнее можно узнать о машинном состояние по запросу FSM.
У нас будет три состояния для трех этапов опроса:
from aiogram.dispatcher.filters.state import StatesGroup, State class CallbackOnStart(StatesGroup): Q1 = State() Q2 = State() Q3 = State()
Keyboards
Чтобы не захламлять основной файл, будем выносить все кнопки в отдельный пакет. В нашем случае используем генератор для inline кнопок.
Импортируем типы для работы с кнопками. Дальше пишем функцию создания кнопок из массива. У нас будет двумерный массив — каждый массив с городами будет в одной линии у пользователя:
from . import inline choice_but_start_test.py from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton def towers(): list_button_name = [['Москва', 'Санкт Петербург', 'Нижний Новгород', 'Ростов'], ['Новосибирск', 'Екатеринбург', 'Казань', 'Челябинск']] buttons_list = [] for item in list_button_name: l = [] for i in item: l.append(InlineKeyboardButton(text=i, callback_data=i)) buttons_list.append(l) keyboard_inline_buttons = InlineKeyboardMarkup(inline_keyboard=buttons_list) return keyboard_inline_buttons
Почему именно так? Если не прибегать к генератору кнопок, нам бы пришлось каждую кнопку прописывать руками, а это неудобно.
Подробнее о кнопках в AIOGram можно узнать тут .
Функция возвращает массив кнопок для работы с ними.
Handlers
On_start_testing.py
Это лишь пример. Вы всегда можете переделать его под себя, чтобы получать нужные вам данные от пользователей.
Все импорты понятные, но сделаем акцент на библиотеке json. Она нужна для взаимодействия с файлами JSON, в них мы будем сохранять результаты опроса.
import json from aiogram.dispatcher import FSMContext from aiogram.dispatcher.filters import Command from aiogram.types import ReplyKeyboardRemove from keyboards.inline.choice_but_start_test import towers from loader import dp from aiogram import types from states import CallbackOnStart
Реакция на команду
Этот хендлер будет отзываться на команду onstarttest.
Первым делом мы проверяем проходил ли пользователь опрос раньше. Для этого открываем базу данных в JSON-файле и перебираем все элементы в поисках ID пользователя. Если его нет, запускаем тест, переводя пользователя в FSM. Если пользователь уже есть в базе — отправляем сообщение, что он проходил опрос ранее.
@dp.message_handler(Command('onstarttest')) async def on_start_test(message: types.Message): with open('users_test_one.json', encoding='utf-8') as json_file: data = json.load(json_file) for i in data: if int(i) == id: user = False break else: user = True if user: await message.answer("Описание опросника") await message.answer('Вопрос №1\nСколько вам лет?\nНапишите ответ (только число)', reply_markup=ReplyKeyboardRemove()) await CallbackOnStart.Q1.set() else: await message.answer(text="Вы уже проходили тест")
Следующий хендлер срабатывает при состоянии Q1. Впоследствии генерируется набор кнопок. После ответа пользователя, полученные данные сохраняются в FSM кэш. После всех действий бот отправляет новый вопрос и переводит человека в новую фазу состояния:
@dp.message_handler(state=CallbackOnStart.Q1) async def tower(message: types.Message, state: FSMContext): b = towers() answer = message.text await state.update_data(name=answer) await message.answer(text="Вопрос №2\nВ каком городе вы живете?\nВыберите ответ из предложенных", reply_markup=b) await CallbackOnStart.next()
Answer — это данные из скрытого ответа inline кнопки. Data запрашивает все данные, сохранённые в FSM. Дальше мы готовим информацию к сохранению в JSON-файл (под ID пользователя мы добавляем полученные ответы). Когда всё готово, отправляем пользователю его выбранные ответы:
@dp.callback_query_handler(state=CallbackOnStart.Q2) async def end(call: types.Message, state: FSMContext): answer = call.data await state.update_data(full_name=call.from_user.full_name) await state.update_data(repost=answer) data = await state.get_data() user = text = [] for i in data: text.append(f'\n') await call.message.answer(text="Ваши ответы:", reply_markup=ReplyKeyboardRemove()) await call.message.answer('\n'.join(text)) with open('users_test_one.json', encoding='utf-8') as file: data = json.load(file) data.update(user) with open('users_test_one.json', 'w', encoding='utf-8') as outfile: json.dump(data, outfile, indent=4, ensure_ascii=False) await state.finish()
Подробнее о сохранении в файл
Подразумевается, что файл будет создан заранее. В противном случае python выведет ошибку о его отсутствии, поскольку режим чтения файла в автоматическом режиме стоит «r» (подробнее о режимах тут ):
with open('users_test_one.json', encoding='utf-8') as file: data = json.load(file) data.update(user) with open('users_test_one.json', 'w', encoding='utf-8') as outfile: json.dump(data, outfile, indent=4, ensure_ascii=False)
Конструкцией «with open as file» мы сразу присваиваем открытому файлу название и можем удобно с ним работать. Дальше мы скармливаем библиотеке JSON-файл, чтобы она конвертировала его в словарь языка. К старым данным внутри файла добавляются новые с помощью метода «update».
После всех манипуляций мы еще раз открываем файл с пометкой w (открытие файла для записи) и перезаписываем его с дополнениями.
Для корректного сохранения используем библиотеку json и функцию dump. Первый аргумент dump — что записываем, второй — куда записываем (это должен быть уже открытый файл), а третий — размер отступов внутри.
Заключение
Сегодня мы познакомились с новыми возможностями AIOGram и сделали на его базе опросник, который собирает данные пользователей в JSON-файл.
Вы можете применять такой опросник в том числе для своего бизнеса и исследований вашей аудитории, собирая и анализируя ответы пользователей.
При должном желании, можно использовать части кода или идеи в других проектах.