Как сделать бота: руководство по вашему первому чат-боту на Python для Telegram

  1. Шаг № 0: немного теории API Telegram Bot
  2. Шаг № 1: Реализация запросов на обменные курсы
  3. Шаг № 2: Создайте бота Telegram с помощью @BotFather
  4. Шаг № 3: Настройка и инициализация бота
  5. Шаг № 4: Напишите обработчик команды / start
  6. Шаг № 5: Создайте обработчик команды / help
  7. Шаг № 6: Добавьте обработчик команды / exchange
  8. Шаг № 7: Напишите встроенный обработчик нажатия кнопки
  9. Шаг № 8: Реализация обработчика кнопки обновления
  10. Шаг № 9: Реализация встроенного режима
  11. Завершение

Часть 3 наша серия чатботов поставляется с пошаговым руководством о том, как сделать бот Telegram. Бот должен уметь показывать курсы валют, показывать разницу между прошлыми и текущими курсами обмена, а также использовать современные встроенные клавиатуры.

Теперь давайте перейдем к поиску и узнаем, как делать ботов Telegram.

Прочитайте больше: 8 вопросов, которые вы должны задать себе, прежде чем создавать чат-бота ,

Шаг № 0: немного теории API Telegram Bot

Я хочу начать это руководство с простого вопроса: вообще, как вы разрабатываете чат-боты Telegram?

Ответ очень прост: вы используете HTTP API как для чтения сообщений, отправленных пользователями, так и для обмена сообщениями. Это требует использования URL, который выглядит следующим образом:

https://api.telegram.org/bot/METHOD_NAME

Токен - это уникальная строка символов, необходимая для аутентификации бота в системе (токен создается при создании бота); а METHOD_NAME (и это видно из его названия) - это метод, например, getUpdates , Отправить сообщение , getChat , так далее.

Токен выглядит примерно так:

123456: ABC-DEF1234ghIkl-zyx57W2v1u123ew11

Для выполнения запросов вы можете использовать как GET, так и POST запросы. Многие методы требуют дополнительных параметров (при использовании Отправить сообщение метод, например, необходимо указать chat_id и текст). Параметры могут быть переданы в виде строки запроса URL, application / x-www-form-urlencoded и application-json (за исключением загрузки файлов). Другое требование - кодировка UTF-8.

После отправки запроса API вы получите ответ JSON. Например, если мы получим данные с помощью метода «getMe», мы получим что-то вроде этого:

ПОЛУЧИТЕ https://api.telegram.org/bot<token>/getMe {ok: true, результат: {id: 231757398, first_name: «Exchange Rate Bot», имя пользователя: «exchangetestbot»}}

Если 'ok' - true, запрос был успешным, и результат будет отображаться в поле 'result'. Если 'ok' равно false, вы увидите сообщение об ошибке в поле 'description'.

Вы можете найти список всех типов данных и методов Telegram Bot API. Вот.

Следующий вопрос: как получать сообщения пользователей?

Есть два способа сделать это.

Первый заключается в том, чтобы вручную отправлять запросы через getUpdates метод. В ответ вы получите массив Обновить объекты. Этот метод действует как технология длительного опроса (вы делаете запрос, обрабатываете данные и затем начинаете снова). Чтобы избежать повторной обработки тех же данных, я рекомендую использовать параметр смещения .

Второй способ - использовать веб-хуки. Вы должны использовать setWebhook метод только один раз. После этого Telegram отправит все обновления по указанному URL, как только они поступят. Единственное ограничение заключается в том, что вам нужен HTTPS, однако самозаверяющие сертификаты также разрешены.

Как выбрать оптимальный метод? getUpdates Метод лучше всего подходит, если:

  1. Вы не хотите / не можете настроить HTTPS во время разработки.
  2. Вы используете язык сценариев, который сложно интегрировать в веб-сервер.
  3. Ваш бот сильно загружен.
  4. Вы время от времени меняете сервер бота.

Метод Webhook является лучшим выбором, если:

  1. Вы кодируете на веб-языках (например, PHP).
  2. Ваш бот малозагружен, и нет смысла регулярно запрашивать обновления вручную.
  3. Ваш бот постоянно интегрирован в веб-сервер.

В этом руководстве я буду использовать метод getUpdates.

Еще один вопрос: как сделать программу бота?

@BotFather используется для создания ботов Telegram. Он также позволяет базовую конфигурацию (описание, фото профиля, встроенная поддержка и т. Д.).

Существует множество библиотек, которые могут упростить работу с Telegram Bot API. Назвать несколько:

По своей сути все эти библиотеки являются оболочками HTTP-запросов. Большая часть из них написана с использованием ООП и отражает все типы данных Telegram Bot API в классах.

В этом уроке по боту Telegram я собираюсь создать чат-бота Python с помощью pyTelegramBotApi библиотека.

Шаг № 1: Реализация запросов на обменные курсы

Давайте напишем скрипт на Python, который будет реализовывать логику для запросов на конкретные курсы валют. Мы собираемся использовать API ПриватБанка. URL: ua/p24api/pubinfo?json&exchange&coursid=5> https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5 ,

Пример ответа:

[{ccy: "EUR", base_ccy: "UAH", купить: "28.70000", продажа: "29.10000"}, {ccy: "RUR", base_ccy: "UAH", купить: "0.39300", продажа: "0.40300" "}, {ccy:" USD ", base_ccy:" UAH ", купить:" 25.40000 ", продажа:" 25.70000 "}]

Давайте создадим файл pb.ру и напишем следующий код:

# - * - кодирование: utf-8 - * - запросы на импорт и импорт импорт json <br> URL = 'https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5' <br> def load_exchange (): return json.loads (запросы.get (URL) .text) def get_exchange (ccy_key): для exc в load_exchange (): если ccy_key == exc ['ccy']: return exc вернуть False def get_exchanges (ccy_pattern): result = [] ccy_pattern = re.escape (ccy_pattern) + '. *' для exc в load_exchange (): если re.match (ccy_pattern, exc ['ccy'], re.IGNORECASE) не является None: result.append (exc) вернуть результат

Мы реализовали три метода:

  • load_exchange: загружает обменные курсы по указанному URL и возвращает в виде dict .
  • get_exchange: возвращает курсы обмена для запрашиваемой валюты.
  • get_exchanges: возвращает список валют в соответствии с шаблоном (требуется при поиске валют во встроенных запросах).

Шаг № 2: Создайте бота Telegram с помощью @BotFather

Связаться с @BotFather бот, чтобы получить список команд чата Telegram. Теперь используйте команду / newbot и дождитесь инструкций для выбора имени и имени пользователя. После успешного создания вашего бота вы получите следующее сообщение:

Готово! Поздравляю с новым ботом. Вы найдете его на telegram.me/ <имя пользователя>. Теперь вы можете добавить описание, раздел и изображение профиля вашего бота, см. / Help список команд. Кстати, когда вы закончите создавать своего крутого бота, обратитесь в нашу службу поддержки ботов, если вы хотите получить более подходящее имя для него. Просто убедитесь, что бот полностью готов к работе, прежде чем сделать это. Используйте этот токен для доступа к HTTP API: <токен> (здесь идет токен бота) Описание API бота см. На этой странице: https://core.telegram.org/bots/api

Давайте настроим настройки бота сразу же. Вы должны указать описание и текст (команды / setdescription и / setabouttext ), фотографию профиля ( / setuserpic ), включить встроенный режим ( / setinline ), добавить подсказки команд ( / setcommands ). Вам нужно будет использовать две команды: / help и / exchange . Давайте опишем их в / setcommand s.

Теперь, когда установка закончена, вы можете приступить к написанию кода. Прежде чем двигаться дальше, я очень рекомендую вам читать об API а также загляните в библиотечную документацию чтобы лучше понять информацию ниже.

Шаг № 3: Настройка и инициализация бота

Начнем с создания файла config.py для настройки:

# - * - кодирование: utf-8 - * - TOKEN = '<бот-токен>' 'TIMEZONE =' Европа / Киев 'TIMEZONE_COMMON_NAME =' Киев '

Здесь мы имеем: токен бота и часовой пояс, в котором он будет работать (это понадобится вам в будущем, чтобы указать время для обновления сообщений. Telegram API не позволяет вам определять часовой пояс пользователя, поэтому обновление время должно отображаться с подсказкой о часовом поясе).

Давайте создадим файл bot.py, импортируем все необходимые библиотеки, файлы конфигурации и ранее созданный файл pb.py. Если некоторые библиотеки отсутствуют, установите их через pip .

# - * - кодирование: utf-8 - * - импорт телебота импорт конфигурации импорта pb импорт даты и времени импорта pytz импорт json импорта traceback P_TIMEZONE = pytz.timezone (config.TIMEZONE) TIMEZONE_COMMON_NAME = config.TIMEZONE_COMMON_NAME

Давайте создадим бота с помощью библиотеки pyTelegramBotAPI. Для этого вы должны передать токен в конструктор:

bot = telebot.TeleBot (config.TOKEN) bot.polling (none_stop = True)

Шаг № 4: Напишите обработчик команды / start

Теперь ваш чат-бот Python инициализируется и постоянно запрашивает метод getUpdates. Параметр none_stop отвечает за продолжение опроса, даже если API возвращает ошибку при выполнении метода.

Затем можно вызывать любые методы Telegram Bot API из переменной бота.

Давайте начнем с написания обработчика команды / start и добавим его перед строкой bot.polling (none_stop = True) :

@ bot.message_handler (commands = ['start']) def start_command (message): bot.send_message (message.chat.id, 'Привет! Я могу показать вам курсы обмена ПриватБанка. \ n' + 'Чтобы узнать курсы обмена нажмите /exchange.\n '+' Чтобы получить помощь, нажмите / help. ')

Как вы видете pyTelegramBotApi использует декораторы Python для инициализации обработчиков для различных команд Telegram. Вы также можете перехватывать сообщения, используя regexp, их тип содержимого и лямбда-функции.

В нашем случае, если условие command = ['start'] истинно, вызывается функция start_command . Объект сообщения (десериализованный Сообщение тип) будет передан в эту функцию. После этого вы просто запускаете send_message в тот же чат с указанным сообщением.

Фу, это было легко, не так ли?

Шаг № 5: Создайте обработчик команды / help

Давайте добавим наш обработчик команд / help с помощью встроенной кнопки, связывающей вашу учетную запись Telegram. Назовем кнопку «Сообщение разработчику».

@ bot.message_handler (commands = ['help']) def help_command (message): клавиатура = telebot.types.InlineKeyboardMarkup () клавиатура.add (telebot.types.InlineKeyboardButton ('Сообщение разработчику), url =' telegram.me / artiomtb ')) bot.send_message (message.chat.id,' 1) Чтобы получить список доступных валют, нажмите /exchange.\n '+' 2) Нажмите на интересующую вас валюту. \ n '+' 3) Вы получите сообщение, содержащее информацию об источнике и целевых валютах, '+' курсы покупки и продажи. \ N '+' 4) Нажмите «Обновить», чтобы получить текущую информацию относительно запроса. '+' Бот также покажет разницу между предыдущим и текущим обменным курсом. \ N '+' 5) Бот поддерживает встроенный режим. Введите @ <имя_пользователя> в любом чате и первые буквы валюты. ', Reply_markup = клавиатура)

Как вы можете видеть в приведенном выше примере, я использовал дополнительный параметр ( reply_markup ) для метода send_message . Метод получил InlineKeyboardMarkup состоящий из одного InlineKeyboardButton с текстом: «Сообщение разработчику» и url = «telegram.me / artiomtb».

Вышесказанное выглядит так:

Шаг № 6: Добавьте обработчик команды / exchange

Обработчик команд / exchange отображает меню выбора валюты и встроенную клавиатуру бота, состоящую из 3 кнопок: USD, EUR и RUR (это валюты, поддерживаемые банковским API).

@ bot.message_handler (commands = ['exchange']) def exchange_command (message): <br> клавиатура = telebot.types.InlineKeyboardMarkup () клавиатура.row (telebot.types.InlineKeyboardButton ('USD', callback_data = 'get- USD ')) keyboard.row (telebot.types.InlineKeyboardButton (' EUR ', callback_data =' get-EUR '), telebot.types.InlineKeyboardButton (' RUR ', callback_data =' get-RUR ')) bot.send_message ( message.chat.id, 'Нажмите на валюту выбора:', reply_markup = клавиатура)

Позвольте мне объяснить, что такое callback-данные в InlineKeyboardButton. Когда пользователь нажмет эту кнопку, вы получите CallbackQuery (его параметр данных будет содержать callback-данные ) в getUpdates . Таким образом, вы будете точно знать, какую кнопку нажал пользователь, и обработать ее соответствующим образом.

Вот как выглядит ответ / exchange :

Шаг № 7: Напишите встроенный обработчик нажатия кнопки

pyTelegramBotAPI предлагает использовать декоратор @ bot.callback_query_handler, который передаст объект CallbackQuery во вложенную функцию.

@ bot.callback_query_handler (func = лямбда-вызов: True) def iq_callback (запрос): data = query.data if data.startswith ('get-'): get_ex_callback (запрос)

Давайте реализуем метод get_ex_callback :

def get_ex_callback (query): bot.answer_callback_query (query.id) send_exchange_result (query.message, query.data [4:])

Метод answer_callback_query необходим для удаления состояния загрузки, которое появляется при нажатии кнопки. Давайте отправим сообщение в send_exchange_query . Вы должны будете передать это Сообщение и код валюты (вы можете получить его из query.data. Если это был, например, get-USD, тогда передайте USD).

Давайте реализуем send_exchange_result :

def send_exchange_result (message, ex_code): bot.send_chat_action (message.chat.id, 'typing') ex = pb.get_exchange (ex_code) bot.send_message (message.chat.id, serialize_ex (ex), reply_markup = get_update_keyboard (ex ), parse_mode = 'HTML')

Это тоже довольно просто.

Давайте сначала отправим в чат состояние набора текста, чтобы бот отображал индикатор «набор текста», в то время как банковский API получает запрос. Теперь давайте вызовем метод get_exchange из файла pb.py, который получит код валюты (например, USD). Вам также придется вызвать два новых метода в send_message : serialize_ex, сериализатор валют и get_update_keyboard (который возвращает клавиатуру кнопкам «Обновить» и «Поделиться»).

def get_update_keyboard (ex): клавиатура = telebot.types.InlineKeyboardMarkup () клавиатура.row (telebot.types.InlineKeyboardButton ('Обновить', callback_data = json.dumps ({'t': 'u', 'e': {' b ': ex [' buy '],' s ': ex [' sale '],' c ': ex [' ccy ']}}). replace (' ',' ')), telebot.types.InlineKeyboardButton ('Share', switch_inline_query = ex ['ccy'])) вернуть клавиатуру

Давайте запишем в get_update_keyboard текущие обменные курсы в callback_data, используя формат JSON. JSON специально сжат, потому что максимально допустимый размер файла составляет 64 байта.

ключ означает тип, а ключ означает обмен. Остальное делается по тому же принципу.

Кнопка «Поделиться» будет иметь параметр switch_inline_query . Нажатие на кнопку предложит пользователю выбрать один из их чатов, открыть этот чат и вставить имя пользователя бота и указанный встроенный запрос в поле ввода.

Далее, давайте представим метод serialize_ex и вспомогательный serialize_exchange_diff, необходимые для отображения разницы между текущим и старым обменными курсами при нажатии кнопки «Обновить».

def serialize_ex (ex_json, diff = None): результат = '<b>' + ex_json ['base_ccy'] + '->' + ex_json ['ccy'] + ': </ b> \ n \ n' + \ 'Buy:' + ex_json ['buy'], если diff: result + = '' + serialize_exchange_diff (diff ['buy_diff']) + '\ n' + \ 'Sell:' + ex_json ['sale'] + \ ' '+ serialize_exchange_diff (diff [' sale_diff ']) +' \ n 'else: result + =' \ nSell: '+ ex_json [' sale '] +' \ n 'вернуть результат def serialize_exchange_diff (diff): result =' ' if diff> 0: result = '(' + str (diff) + '<img draggable = "false" data-mce-resize = "false" data-mce-placeholder = "1" data-wp-emoji = "1 "class =" emoji "alt =" <img draggable = "false" data-mce-resize = "false" data-mce-placeholder = "1" data-wp-emoji = "1" class = "emoji" alt = "<img draggable =" false "data-mce-resize =" false "data-mce-placeholder =" 1 "data-wp-emoji =" 1 "class =" emoji "alt =" <img draggable = "false" data-mce-resize = "false" data-mce-placeholder = "1" data-wp-emoji = "1" class = "emoji" alt = "<img draggable =" false "data-mce-resize =" false "data-mce-placeholder =" 1 "data-wp-emoji =" 1 "class =" emo ji "alt =" ↗️ "src =" https: //sworg/images/core/emoji/2.3/svg/2197.svg ">" src = "https: //sworg/images/core/emoji/2.3/ svg / 2197.svg ">" src = "https: //sworg/images/core/emoji/2.3/svg/2197.svg"> "src =" https: // sworg / images / core / emoji / 72x72 / 2197.png ">" src = "https: //sworg/images/core/emoji/72x72/2197.png">) 'elif diff <0: result =' ('+ str (diff) [1:] + '<img draggable = "false" data-mce-resize = "false" data-mce-placeholder = "1" data-wp-emoji = "1" class = "emoji" alt = "<img draggable =" false " data-mce-resize = "false" data-mce-placeholder = "1" data-wp-emoji = "1" class = "emoji" alt = "<img draggable =" false "data-mce-resize =" false "data-mce-placeholder =" 1 "data-wp-emoji =" 1 "class =" emoji "alt =" <img draggable = "false" data-mce-resize = "false" data-mce-placeholder = " 1 "data-wp-emoji =" 1 "class =" emoji "alt =" <img draggable = "false" data-mce-resize = "false" data-mce-placeholder = "1" data-wp-emoji = "1" class = "emoji" alt = "↘️" src = "https: //sworg/images/core/emoji/2.3/svg/2198.svg"> "src =" https: // sworg / images / ядро / Emoji / 2,3 / SV g / 2198.svg ">" src = "https: //sworg/images/core/emoji/2.3/svg/2198.svg"> "src =" https: // sworg / images / core / emoji / 72x72 / 2198.png ">" src = "https: //sworg/images/core/emoji/72x72/2198.png">) 'вернуть результат

Как видите, метод serialize_ex получает необязательный параметр diff. Именно там вы будете передавать разницу между обменными курсами в формате {'buy_diff': <float> , 'sale_diff': <float> }. Это произойдет во время сериализации, когда вы нажмете кнопку «Обновить». Нам это не понадобится в первый раз, когда обменные курсы отображаются на экране.

Вот как выглядит ответ бота при нажатии на кнопку USD:

Шаг № 8: Реализация обработчика кнопки обновления

Теперь вы готовы реализовать обработчик кнопки «Обновить». После дополнения метода iq_callback это будет выглядеть следующим образом:

@ bot.callback_query_handler (func = лямбда-вызов: True) def iq_callback (запрос): data = query.data if data.startswith ('get-'): get_ex_callback (запрос) else: try: if json.loads (data) [ 't'] == 'u': edit_message_callback (запрос), кроме ValueError: pass

Если данные обратного вызова начинаются с get- ' ( get-USD , get-EUR и т. Д.), Тогда давайте вызовем get_ex_callback, как мы это делали ранее. В противном случае попробуем разобрать JSON и получить его ключ t . Если оно равно 'u', тогда вызовите метод edit_message_callback. Давайте реализуем это:

def edit_message_callback (запрос): data = json.loads (query.data) ['e'] exchange_now = pb.get_exchange (data ['c']) text = serialize_ex (exchange_now, get_exchange_diff (get_ex_from_iq_data (data), exchange_now)) + '\ n' + get_edited_signature () if elif запрос query.message: bot.edit_message_text (text, query.message.chat.id, query.message.message_id, reply_markup = get_update_keyboard (exchange_now), parse_mode = 'HTML'). inline_message_id: bot.edit_message_text (text, inline_message_id = query.inline_message_id, reply_markup = get_update_keyboard (exchange_now), parse_mode = 'HTML')

Как это работает? Очень просто:

  1. Загрузить текущий обменный курс ( exchange_now = pb.get_exchange (data ['c'] ).
  2. Создайте текст для нового сообщения, сериализовав текущий курс обмена с параметром diff , который вы получите с помощью новых методов (о них я напишу ниже). Давайте также добавим подпись редактирования - get_edited_signature .
  3. Вызовите метод edit_message_text, если исходное сообщение является регулярным. Если это ответ на встроенный запрос, передайте другие параметры.

Метод get_ex_from_iq_data анализирует JSON из callback_data:

def get_ex_from_iq_data (exc_json): return {'buy': exc_json ['b'], 'sale': exc_json ['s']}

Метод get_exchange_diff получает старый и текущий обменные курсы и возвращает разницу в формате {'buy_diff': <float> , 'sale_diff': <float> }:

def get_exchange_diff (last, now): return {'sale_diff': float ("%. 6f"% (float (now ['sale']) - float (last ['sale']))), 'buy_diff': float ("% .6f"% (float (сейчас ['buy']) - float (последний ['buy'])))}

get_edited_signature генерирует «обновленный…» текст:

def get_edited_signature (): вернуть '<i> Обновлено "+ \ str (datetime.datetime.now (P_TIMEZONE) .strftime ('% H:% M:% S ')) + \' ('+ TIMEZONE_COMMON_NAME +') < / я>»

Вот как выглядит сообщение при обновлении, если обменные курсы не изменились:

И вот как это выглядит, если обменные курсы изменились:

Шаг № 9: Реализация встроенного режима

Реализация inline означает, что запись имени @ + бота в любом чате активирует поиск введенного текста и предлагает результаты. Нажав на одну из них, бот отправит результат от вашего имени (с пометкой «через бот»).

@ bot.inline_handler (func = лямбда-запрос: True) def query_text (inline_query): bot.answer_inline_query (inline_query.id, get_iq_articles (pb.get_exchanges (inline_query.query)))

Вы реализовали встроенный обработчик запросов.

Библиотека передаст InlineQuery объект в функцию query_text . Внутри вы используете функцию answer_inline_query, которая должна получить inline_query_id и массив объектов (результаты поиска).

Давайте использовать get_exchanges из pb.py для поиска нескольких валют, которые соответствуют поисковому запросу. Давайте передадим этот массив в метод get_iq_articles, который будет возвращать массив из InlineQueryResultArticle :

def get_iq_articles (exchanges): result = [] для exc в обменах: result.append (telebot.types.InlineQueryResultArticle (id = exc ['ccy'], title = exc ['ccy'], input_message_content = telebot.types.InputTextMessageContent (serialize_ex (exc), parse_mode = 'HTML'), reply_markup = get_update_keyboard (exc), description = 'Convert' + exc ['base_ccy'] + '->' + exc ['ccy'], thumb_height = 1)) вернуть результат

Теперь, когда вы введете @exchnagetestbot + пробел в любом чате, вы увидите следующее:

Давайте наберем usd, и результат будет мгновенно отфильтрован:

Давайте нажмем предложенный результат:

Кнопка «Обновить» также работает:

Хорошая работа! Вы успешно внедрили встроенный режим!

Завершение

Поздравляем! Теперь вы знаете, как создать бота для Telegram, реализовать встроенную клавиатуру, обновление сообщений и встроенный режим. Вы можете погладить себя по удивительной спине и поднять тост за нового Botfather.

Рекомендации:

Ранее в Chatbots:

Все, что вы должны знать о диалоговом интерфейсе:

Списки ботов Telegram для вашего вдохновения:

Как выбрать оптимальный метод?
Ua/p24api/pubinfo?
Ua/p24api/pubinfo?
Фу, это было легко, не так ли?