Bot polling telegram что это
В настоящее время существует достаточно много разных популярных мессенджеров. Достоинством мессенджера Telegram является наличие богатого API, позволяющего взаимодействовать с мессенжером не людям, а программам, то есть писать боты.
Можете изучить полную документацию на Telegram Bot API, но непосредственно этим API мы пользоваться не будем. Но нужно понять, как это устроено внутри.
Самый простой пример тестовой страницы, которую можно загрузить при помощи API:
- Название бота (произвольное текстовое имя),
- Имя пользователя для бота (уникальное, из латинских букв, цифр, символа подчёркивания, должно заканчиваться на bot ).
В ответ вы получите от @BotFather токен.
Дальнейшее описание Telegram Bot API не нужно для выполнения заданий (т.к. мы будем использовать упрощающую разработку ботов библиотеку), но полезно для понимания.
Пример простого запроса getMe для проверки токена, который можно просто ввести в адресную строку браузера, заменив <token> на токен вашего бота:
В ответ вы должны получить небольшой JSON с информацией о вашем боте.
Библиотека pytelegrambotapi (telebot)
Её необходимо установить при помощи pip, в pip она называется pytelegrambotapi. Соответствующая консольная команда может выглядеть, например, так:
Сразу же установите библиотеку requests, она пригодится для выполнения ряда заданий.
Немного более подробно ознакомиться с написанием простейших ботов можно, например, в следующих статьях:
Как сдавать задачи в этом листке
В этих заданиях необходимо разработать бота для Telegram с использованием модуля telebot.
A: Бот, отвечающий односложно
Напишите бота, который на все предложения отвечает односложно. Например, пишет в ответ “Привет!”
B: Приветствие по имени
C: Бот-калькулятор
Напишите бота, который вычисляет значение выражения, которое ему прислали. Например, если написать боту 2 + 2 , он должен ответить 4 .
Для этого нужно использовать функцию eval , вычиcляющую переданное ей выражение в виде строки. Например, eval('2 + 2') вернёт число 4.
Проблема возникает в том, что пользователь может передать некорректное выражение, при вычислении которого функция упадёт. Тогда вам поможет обработка исключений, которая выглядит примерно так:
Подробней про обработку исключений в Python можно прочитать, например, здесь.
Модуль requests для запросов из интернета
Чтобы получить данные с удалённого сайта есть несколько способов, самый простой — библиотека requests. Смотрите документацию на библиотеку, простой пример использования, а также можно сразу же распарсить полученный JSON.
D: Бот-цитатник
E: Конвертер валют
Напишите бота, который мог бы переводить любую сумму любой поддерживаемой валюты в любую другую поддерживаемую валюту. Не забудьте про российский рубль, его курс в этом документе не указан!
F: Цитаты на заданную тему
Для этого у API есть метод quotes (List Quotes), который выдаёт список всех цитат. Этому методу можно передать параметр filter , со значением — слово, по которому осуществляется поиск, и параметр type=tag , чтобы осуществлять поиск по тегам, а не по всем текстам цитат.
Обратите внимание, что если цитат, удовлетворяющих условию, много, то API выдаёт только 25 из них. Чтобы получить больше цитат (они выдаются страницами по 25 штук), нужно задать параметр page , равный номеру страницы.
Всё, что здесь описано, передаётся при помощи параметров GET запроса. Примеры запросов можете посмотреть в документации на API.
Но использовать функцию quotes вы можете только при наличии токена. Для этого нужно зарегистрироваться на сайте и получить бесплатно токен (они называются API keys). Токен — это строка из 32 hex-символов. Токен нужно передавать (см. раздел Authorization в API) при помощи дополнительного параметра “Authorization” в параметрах GET-запроса. Это можно сделать при помощи той же библиотеки requests , посмотрите на пример Custom Headers в документации.
Наконец, вы должны реализовать кэширование запросов. То есть если бот один раз получил список всех цитат на какую-то тему, то можно ожидать, что пользователь захочет получить ещё одну цитату на эту же тему. Чтобы не получать снова цитаты через API, необходимо сохранять все цитаты по этой теме, а при повторном запросе — выдавать одну цитату из сохранённых.
- Получить API key.
- Научиться делать запросы с использованием API key (любые, лишь бы работала авторизация).
- Научиться делать запросы с поиском по тэгу.
- Реализовать загрузку всех цитат с учётом пагинации. До сих пор вам на самом деле не нужен никакой бот, удобней написать простое приложение, которое будет делать необходимые запросы и выдавать результат на стандартный вывод.
- Теперь облачаем это в форму бота, кэшируя полученные цитаты в словаре.
Реализация клавиатуры
Команды, набираемые пользователем, сложно декодировать, да и пользователь может ошибиться в их написании. Поэтому в Телеграме у ботов есть возможность использования клавиатуры для выбора стандартных действий пользователя. Есть два типа клавиатуры: ReplyKeyboardMarkup (более древняя) и InlineKeyboardMarkup (более современная и богатая возможностями), на второй и остановимся.
Теперь нам необходимо сделать обработчики кнопок. Это отдельные функции, которые необходимо зарегистрировать при помощи декоратора callback_query_handler . Эта функция будет получать объект callback_obj , которых хранит информацию о нажатии кнопки. В частности, помимо обычных данных о пользователе, чате и т.д. у этого объекта есть поле data , в котором хранится та самая информация, которая была привязана к кнопке. Пример такого обработчика:
Обратите внимание на вызов метода answer_callback_query . Он сообщает серверу телеграма, что обработка данного callback-запроса завершена. Если этот метод не вызвать, то на кнопке будут изображены часики, а сама кнопка будет недоступна для повторного нажатия.
Есть и другой способ определить, какая кнопка была нажата. Обратите внимание на параметр декоратора: func=lambda call: True . Это лямбда-функция, которая в данном случае всегда возвращает True . Это означает, что данный обработчик будет применяться ко всем callback-запросам. Но если эта функция будет возвращать не всегда True , то так можно установить обработчик для отдельных callback-запросов, а именно, будет вызван тот обработчик, для которого эта функция вернёт True .
Используем это для того, чтобы сделать разные обработчики для разных кнопок.
G: Расписание уроков
Выбор дня недели реализуйте при помощи клавиатуры.
Вот начало вашего расписание
H: Текущая погода
Напишите бота, который выдаёт текущую погоду для одного из городов. Приложение должно предлагать выбор города при помощи кнопки (должно быть минимум 4 города, минимум из трёх разных часовых поясов, обязательно включая Москву). Также должна быть возможность ввести название города вручную (при этом не гарантируется, что погоду для этого города удастся определить).
I: Конвертер валют-2
Бота, конвертирующего валюты, реализуйте при помощи кнопок. Например, должны быть кнопки “Введите сумму”, “Выберите исходную валюту” “, “Выберите валюту, в которую нужно перевести”. Для выбора валюты отображается меню из кнопок, соответствующих валютам. При вводе суммы нужно обрабатывать любые неправильные введённые данные.
J: Бот, который считает
Напишите бота с двумя кнопками: «+1» и «Сброс». По нажатию на первую кнопку выводится последнее выведенное число, увеличенное на 1, а по нажатию на «Сброс» выводится 0.
Для каждого пользователя ряд чисел должен быть собственным.
K: Камень, ножницы, бумага
Напишите бота, который реализует игру «Камень, ножницы, бумага» для двух игроков (двух пользователей). Пользователю отображаются три кнопки. Бот получает результат нажатия кнопок. Когда два пользователя нажали кнопки, бот сообщает каждому из них имя его противника, что выбрал противник и результат игры (выиграл, проиграл, ничья). То есть при получении ответа от одного пользователя бот запоминает его ход, после получения ответа от второго пользователя, бот сообщает обоим пользователям результат игры и всё начинается заново.
Если второй ответ пришёл от того же игрока, то это считается изменением его предыдущего ответа.
L: Игра ним
В игре ним на столе лежит несколько кучек камней (например, содержащих 3, 4 и 5 камней). Двое игроков по очереди берут по одному или несколько камней из одной кучки. Выигрывает тот, кто взял последний камень.
Стратегия при игре в ним: рассмотрим побитовый XOR количества камней в кучках (например, 3 ^ 4 ^ 5 = 2 ). Если эта величина ненулевая, то позиция выигрышная для ходящего игрока. Если же эта величина нулевая, то позиция проигрышная. Выигрышный ход должен быть таким, чтобы XOR размеров кучек стал нулевым.
Реализуйте бота, который играет в ним с человеком (естественно, у каждого игрока своя сессия), при этом выигрывая (если есть такая возможность).
Библиотека sympy для символьных вычислений
Есть отличная библиотека sympy для символьных вычислений. Вот так в ней можно считать производные:
Если добавить кода, то можно сделать ввод и вывод более удобными:
M: Бот, считающий производную
Сделайте бота, который будет считать производную.
N: Бот, считающий интеграл
По аналогии с производной можно и интегралы считать. Подробности письмом.
Если ты совсем не ориентируешься в Python, то отличным началом будет прочтение трех вводных статей, которые я публиковал в «Хакере» этим летом, либо посещение курса «Python для новичков», который я начну вести для читателей «Хакера» уже совсем скоро — 30 ноября.
Чтобы создать бота, нам нужно дать ему название, адрес и получить токен — строку, которая будет однозначно идентифицировать нашего бота для серверов Telegram. Зайдем в Telegram под своим аккаунтом и откроем «отца всех ботов», BotFather.
Жмем кнопку «Запустить» (или отправим / start ), в ответ BotFather пришлет нам список доступных команд:
- / newbot — создать нового бота;
- / mybots — редактировать ваших ботов;
- / setname — сменить имя бота;
- / setdescription — изменить описание бота;
- / setabouttext — изменить информацию о боте;
- / setuserpic — изменить фото аватарки бота;
- / setcommands — изменить список команд бота;
- / deletebot — удалить бота.
Отправим бате‑боту команду / newbot , чтобы создать нового бота. В ответ он попросит ввести имя будущего бота, его можно писать на русском. После ввода имени нужно будет отправить адрес бота, причем он должен заканчиваться на слово bot. Например, xakepbot или xakep_bot . Если адрес будет уже кем‑то занят, BotFather начнет извиняться и просить придумать что‑нибудь другое.
Для взаимодействия с Telegram API есть несколько готовых модулей. Самый простой из них — Telebot. Чтобы установить его, набери
В Linux, возможно, понадобится написать pip3 вместо pip , чтобы указать, что мы хотим работать с третьей версией Python.
Эхо-бот
Для начала реализуем так называемого эхо‑бота. Он будет получать от пользователя текстовое сообщение и возвращать его.
Для начала что такое Webhook, в контексте телеграм ботов есть два варианта взаимодействия с API:
webhook - Это тоже штука для того что бы бот понимал что изменилось, но в данном случае не бот опрашивает телеграм на наличие изменений, а телеграм "шлет" изменения для телеграм бота. Тут есть несколько важных моментов, для того что бы работал webhook у вашего бота должно быть доменное имя с настроенным ssl сертификатом, иначе не секюрно и телеграм откажется взаимодействовать с вашим ботом, и тут когда я начинал "играться" с webhook у меня возник вопрос, а как вообще это настроить для тестов, да и вообще как это настроить? ниже я попытаюсь это описать, а именно как развернуть это локально для разработки и самообучения. Для работы будет использоваться python, flask, ngrok, telebot
1 - Начнем пожалуй с самого кода (я надеюсь вы уже сделали самого бота в телеграм? нуу через BotFather? если нет, тут мануал), когда нам телеграм будет слать запросы мы должны их не только как-то принять, но и обработать, в этом нам поможет flask ну и естественно python, код базовой и довольно тестовой (то есть не для прода) версии ниже, сори что скрин, я не нашел как тут разместить код в удобочитаемом виде:
В самом верху вы видите 4 константы (по хорошему их бы вынести в отдельный какой-то конфиг):
API_TOKEN - Когда вы создадите бот в BotFather, вам будет выдан токен, вот его нужно добавить сюда
APP_HOST = '127.0.0.1' - Эта и следующая переменная для flask, он будет принимать запросы которые идут на порт и интерфейс указанный в этих переменных
APP_PORT = '8444'
Так же я подключил logger что бы удобней было контролировать то, что хочется видеть в в логах.
Помогает flask понять, какой тип запросов обрабатывать, и описывает то, что ему делать
если запрос который пришел был немного не таким как ожидалось)
видете в блоке json_string = flask.request.get_data().decode('utf-8') ? json_string это как раз
тот объект json который мы приняли от телеграм, он "скармливается" в telebot, и потом в хендлерах (как в данном случае start) будет доступен как аргумент функции (правда без пустых значений) в данном случае в виде message
а вот теперь самое интересное, что по доменному имени? и выход есть, ngrok, переходим на их сайт, создаем аккаунт, следуем всем инструкциям и скачиваем бинарный файл (ну или инсталлируем, как удобно, так как у меня мак, я скачал бинарный файл и просто разместил его в /usr/local/bin/ngrok, в итоге он стал доступен просто вызвав ngrok, не забудьте если делаете так же поставить исполняемый бит на файл chmod +x /usr/local/bin/ngrok, что бы у него было право на исполнение ) потом его нужно запустить, и тут все просто, пишем:
и вы увидите что-то на подобие этого:
Что это значит? ngrok сгенерит адрес который отображается в консоли:
А сегодня мы познакомимся с опросами 2.0, точнее, с новой сущностью: викторинами (quiz). Викторина – это именно то, что вы и предположили; тест с одним правильными вариантом ответа и ещё N неправильными.
Поставим себе задачу сделать бота, который умеет:
Задач много, придётся вспомнить, что такое колбэки, инлайн-режим и классы. Но и это не самое главное…
Пятиминутка ненависти к telebot или Привет, aiogram!
Как вы знаете, во всех предыдущих уроках использовалась библиотека pyTelegramBotAPI, именуемая в коде telebot. В 2015-2017 годах, возможно, она ещё была актуальна, но прогресс не стоит на месте. А telebot, увы, стоит. Кривая реализация поллинга, проблемный next_step_handler, медленная поддержка новых версий Bot API и т.д.
В течение 2019 года я постепенно переносил своих ботов на другой фреймворк, который по многим пунктам превосходит pyTelegramBotAPI, и имя ему – aiogram. «Почему?», спросит меня уважаемый читатель. Что ж, приведу следующие аргументы:
- это полноценный фреймворк, т.е. позволяет сделать больше полезных вещей;
- асинхронный, что делает его быстрее в некоторых задачах;
- поддерживается Python 3.7+ и выше, что сподвигнет обновить свой старенький интерпретатор и использовать новые возможности языка;
- множество встроенных «помощников» (синтаксический «сахар»), улучшающих читабельность кода;
- оперативные обновления (поддержка новых опросов появилась в тот же день, что и в самом Bot API);
- русскоязычный чат поддержки и обсуждений, где сидит, в том числе, и сам разработчик фреймворка;
- мой любимый пункт: нормально работающий поллинг.
Прокомментирую последний пункт: в настоящий момент почти все мои боты работают на aiogram-ном поллинге и не падают ежедневно, как в случае с pyTelegramBotAPI.
Введение получилось очень большим, поэтому давайте уже перейдём к делу.
Плацдарм для бота
Напишем элементарного эхо-бота на aiogram с поллингом, чтобы бегло ознакомиться с фреймворком. Прежде всего, добавим нужные импорты (предполагается, что мы используем Virtual Environment, подробнее о нём – в уроке №0):
Теперь создадим объект бота. А за хэндлеры здесь отвечает специальный Диспетчер:
Запрашиваем викторину у пользователя
Сохраняем и предлагаем
В 11-м уроке я использовал библиотеку Vedis для сохранения состояний в файле, чтобы те не сбрасывались после перезагрузки бота. В этот раз мы будем сохранять всё в памяти, а выбор постоянного хранилища останется за читателем, чтобы не навязывать то или иное решение. Разумеется, данные в памяти сотрутся при остановке бота, но для примера так даже лучше.
Наше хранилище будет основано на стандартных питоновских словарях (dict), причём их будет два: первый словарь содержит пары (“id пользователя”, “массив сохранённых викторин”), а второй — пары (“id викторины”, “id автора викторины”). Зачем два словаря? В дальнейшем нам нужно будет по идентификатору викторины получать некоторую информацию о ней. Необходимые нам сведения лежат в первом словаре, но в виде значений, а не ключей. Поэтому нам пришлось бы проходиться по всем возможным парам ключ-значение, чтобы найти нужную викторину.
Помимо определения викторины, нам нужно хранить некоторую дополнительную информацию. Поэтому давайте создадим файл quizzer.py , опишем наш класс Quiz со всеми нужными полями в конструкторе класса (обратите внимание, в конструктор передаются не все поля, т.к. часть из них будет заполнена позднее):
Если вы раньше не сталкивались с подсказками типов (type hints), код вида “chat_id: int = 0” может ввести в замешательство. Здесь chat_id — это имя переменной, далее через двоеточие int — её тип (число), а дальше инициализация числом 0. Python по-прежнему является языком с динамической типизацией, отсюда и название “подсказка типа”. В реальности это влияет только на восприятие кода и предупреждения в полноценных IDE типа PyCharm. Никто не мешает вам написать quiz_id: int = "чемодан" , но зачем так делать? Вернёмся в наш основной файл (я его далее буду называть bot.py ) и импортируем наш класс: from quizzer import Quiz . Также добавим в начале файла под определением бота два пустых словаря:
Теперь будем отлавливать викторины, приходящие в бота. Как только прилетает что-то, похожее на неё, извлекаем информацию и создаём две записи. В первом словаре храним параметры викторины, чтобы потом её воспроизвести, а во втором просто создаём пару викторина-создатель. Идентификаторы, составляющие ключ словаря, конвертируем в строки методом str() :
Начнём разбираться с инлайн-режимом (не забудьте включить его у @BotFather). Когда пользователь вызывает нашего бота через инлайн, показываем все созданные им викторины, плюс кнопку “Создать новую”. Если ничего нет, то только кнопку.
Отправляем викторину и получаем ответы
Начнём с PollAnswer . Когда прилетает событие с новым ответом на викторину, прежде всего достаём её ID, по ней ищем автора во втором словаре. Если находим, то гуляем по всем викторинам этого пользователя и ищем совпадение по ID самой викторины, т.е. в точности обратное действие, только уже в первом словаре. Когда обнаружится нужная викторина, то проверяем, верный ответ или нет (сравниваем с correct_option_id ), и если да, то записываем ID пользователя в список победителей. Если количество победителей при этом достигает двух, то останавливаем викторину.
Код готов. Закинем викторину в группу и попросим друзей правильно ответить, а сами ответим неправильно. После первого правильного ответа:
2 ответа, только один правильный
После второго правильного ответа:
3 ответа, 2 правильных, опрос закрыт
На этом всё! Если у вас возникли вопросы, не стесняйтесь задавать их в нашем чатике, а если вы нашли ошибку/опечатку, либо есть чем дополнить материал, то добро пожаловать на GitHub (ну, или всё так же в чате). Полный код урока можно найти здесь.
Читайте также: