Telegram Bot на Python 3

В данной статье мы напишем telegram bot на python, который сможет отвечать на наши сообщения, взаимодействовать с нами, предлагая варианты ответов в виде кнопок и обрабатывать выбранный нами результат, выполняя команды на сервере. Взаимодействовать с Telegram Bot Api мы будем с помощью библиотеки pyTelegramBotAPI (telebot) написанной на Python.

  1. Создание бота
  2. Установка Python и библиотеки pyTelegramBotAPI
  3. Пишем Telegram Bot на Python
  4. Использование прокси в telebot
  5. Ответы бота на сообщения пользователя
  6. Клавиатура в Telegram Bot API
  7. InLine клавиатура
  8. Конечный листинг

Создание бота

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

Обратите внимание на его имя, изображение и знак в виде галочки, говорящий о том, что это действительно отец всех ботов.

Выберите его и в диалоговом окне напишите команду /start и бот в ответном сообщение пришлет список всех доступных команд:

Нас интересует создание нового бота, поэтому выбираем команду /newbot. Команду можно как напечатать самостоятельно, так и выбрать мышью в сообщении и она автоматически отправится:

Первым шагом нам предлагают дать имя новому боту, оно может быть произвольным. Мы назовем его PocketAdmin:

Теперь требуется указать идентификатор бота (username), он должен заканчиваться на _bot и быть уникальным в системе. Мы укажем PocketAdminTech_bot:

На этом создание бота завершено. В последнем сообщении нам пришла ссылка на нашего нового бота t.me/PocketAdminTech_bot и токен (закрашен), необходимый для взаимодействия с API.

Обязательно сохраните токен и храните его в тайне!

Установка Python и библиотеки pyTelegramBotAPI

Скачать Python можно с официального сайта (как установить пакет на Centos 8 можно ознакомиться в данной заметке) и мы не будем заострять внимание на данном вопросе.

Чтобы установить пакет pyTelegramBotAPI воспользуемся pip:

pip install pytelegrambotapi

На этом подготовительная работа завершена, приступаем непосредственно к написанию нашего бота.

Пишем Telegram Bot на Python

Так как наш бот создается в ознакомительных целях и не будет содержать много кода, то писать я его буду сразу на сервере с установленной Centos 8 используя обычный редактор nano. Создадим файл bot.py, открыв его nano:

nano bot.py

Для начала импортируем библиотеку pyTelegramBotAPI:

import telebot

Затем зададим переменную token равную нашему токену, который мы получили от BotFather для взаимодействия с Telegram Bot Api:

token = 'ваш token api'

Объявим бота:

bot = telebot.TeleBot(token)

Далее задается декоратор. Пока наш бот будет обрабатывать только команду start:

@bot.message_handler(commands=['start'])

и в ответ писать нам “Привет!”:

def start_message(message):
    bot.send_message(message.chat.id, 'Привет!')

Чтобы бот постоянно ожидал запрос от пользователя в конце пропишем:

bot.polling()

В итоге мы получим код:

import telebot

token = 'ваш token api'

bot = telebot.TeleBot(token)

@bot.message_handler(commands=['start'])
def start_message(message):
    bot.send_message(message.chat.id, 'Привет!')

bot.polling()

Запустим его:

python bot.py

Затем откроем нашего бота (можно найти по имени) и напишем ему команду /start:

Поздравлю с первыми словами нашего бота PocketAdmin!

Использование прокси в telebot

При запуске скрипта может появиться ошибка следующего вида:

requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))

Чтобы исправить её, можно попробовать подключиться через прокси:

from telebot import apihelper
apihelper.proxy = {
    'https':'socks5://login:password@ip:port'}

где login:password@ip:port – соответствующие данные для подключения к прокси.

Если при использовании прокси возникают ошибки, подобные: Not supported proxy scheme socks5 или Missing dependencies for SOCKS support, то необходимо установить модули:

pip install requests[socks] PySocks

Ответы бота на сообщения пользователя

Аналогично хэндлерам для команд, в telegram bot api есть возможность обрабатывать сообщения от пользователя. Для этого используется тип text. Например, мы можем запрограммировать бота отвечать на определенные фразы или слова пользователя:

@bot.message_handler(content_types=['text'])
def send_text(message):
    if message.text.lower() == 'привет':
        bot.send_message(message.chat.id, 'Ещё раз привет!')
    elif message.text.lower() == 'пока':
        bot.send_message(message.chat.id, 'Пока!')

Думаю тут все понятно. На слово “Привет” бот будет отвечать “Ещё раз привет!”, а на “Пока” – “Пока!”. Весь код нашего telegram bot на python теперь будет выглядеть следующим образом:

import telebot

token = 'ваш token api'

bot = telebot.TeleBot(token)

@bot.message_handler(commands=['start'])
def start_message(message):
    bot.send_message(message.chat.id, 'Привет!')

@bot.message_handler(content_types=['text'])
def send_text(message):
    if message.text.lower() == 'привет':
        bot.send_message(message.chat.id, 'Ещё раз привет!')
    elif message.text.lower() == 'пока':
        bot.send_message(message.chat.id, 'Пока!')

bot.polling()

Перезапустим скрипт и пообщаемся с ботом:

Таким образом мы можем описывать различные диалоги с ботом.

Клавиатура в Telegram Bot на Python

Апи телеграма позволяет использовать свою клавиатуру, а точнее быстрые кнопки, позволяющие пользователю отправлять текст по их нажатию.

Добавим в обработчик команды /start клавиатуру с кнопками “Привет “и “Пока”:

@bot.message_handler(commands=['start'])
def start_message(message):
    keyboard = telebot.types.ReplyKeyboardMarkup(True)
    keyboard.row('Привет', 'Пока')
    bot.send_message(message.chat.id, 'Привет!', reply_markup=keyboard)

И запустим измененный скрипт. Как только мы отправим боту команду /start у нас внизу появится наша клавиатура:

Теперь для отправки сообщений достаточно лишь нажать на соответствующую кнопку. Это очень удобно в мобильной версии телеграма.

InLine клавиатура

На мой взгляд, наиболее интересной является InLine клавиатура. Она позволяет вместе с сообщением отправлять пользователю интерактивные кнопки, например с вариантами ответов, а после их нажатия обрабатывать результат.

Давайте добавим простой вопрос от бота на команду /test:

@bot.message_handler(commands=['test'])
def start_message(message):
    markup = telebot.types.InlineKeyboardMarkup()
    markup.add(telebot.types.InlineKeyboardButton(text='Три', callback_data=3))
    markup.add(telebot.types.InlineKeyboardButton(text='Четыре', callback_data=4))
    markup.add(telebot.types.InlineKeyboardButton(text='Пять', callback_data=5))
    bot.send_message(message.chat.id, text="Какая средняя оценка была у Вас в школе?", reply_markup=markup)

Переменная markup объявляет новую переменную с inline keyboard, а markup.add – создает отдельную кнопку. Основные параметры при создании кнопки – text и callback_data: первый отвечает за текст на кнопке, второй – данные, которые будут переданы боту при выборе пользователем определенного варианта ответа.

Запустим скрипт и напишем /test:

Отлично, бот прислал нам варианты ответов. Но при нажатии на кнопку ничего не произойдет, т.к. мы не описали обработку результатов. Исправим это:

@bot.callback_query_handler(func=lambda call: True)
def query_handler(call):

    bot.answer_callback_query(callback_query_id=call.id, text='Спасибо за честный ответ!')
    answer = ''
    if call.data == '3':
        answer = 'Вы троечник!'
    elif call.data == '4':
        answer = 'Вы хорошист!'
    elif call.data == '5':
        answer = 'Вы отличник!'

    bot.send_message(call.message.chat.id, answer)

bot.answer_callback_quer – это всплывающее окно, которое будет показано пользователю после нажатия кнопки. А в call.data будет передано значение, которое мы указывали при создании клавиатуры в параметре callback_data. Ответим боту, выбрав один из ответов:

Отлично, все работает. Но будет лучше, если после ответа, клавиатура будет исчезать из чата. Это можно сделать добавив в конец функции query_handler следующую строку:

bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id)

Это функция редактирования клавиатуры, вызванная без указания объекта клавиатуры. Теперь после ответа пользователя клавиатура будет убрана ботом:

Конечный листинг телеграм бот на питоне

Мы рассмотрели лишь малую часть возможностей telegram bot api, однако, это очень полезные инструменты по работе с ним. В конце приведем полный листинг получившегося у нас telegram bot на python:

import telebot
from telebot import apihelper

apihelper.proxy = {
    'https':'socks5://login:password@ip:port'}

token = 'ваш token api'

bot = telebot.TeleBot(token)

@bot.message_handler(commands=['start'])
def start_message(message):
    keyboard = telebot.types.ReplyKeyboardMarkup(True)
    keyboard.row('Привет', 'Пока')
    bot.send_message(message.chat.id, 'Привет!', reply_markup=keyboard)

@bot.message_handler(commands=['test'])
def start_message(message):
    markup = telebot.types.InlineKeyboardMarkup()
    markup.add(telebot.types.InlineKeyboardButton(text='Три', callback_data=3))
    markup.add(telebot.types.InlineKeyboardButton(text='Четыре', callback_data=4))
    markup.add(telebot.types.InlineKeyboardButton(text='Пять', callback_data=5))
    bot.send_message(message.chat.id, text="Какая средняя оценка была у Вас в школе?", reply_markup=markup)

@bot.message_handler(content_types=['text'])
def send_text(message):
    if message.text.lower() == 'привет':
        bot.send_message(message.chat.id, 'Ещё раз привет!')
    elif message.text.lower() == 'пока':
        bot.send_message(message.chat.id, 'Пока!')

@bot.callback_query_handler(func=lambda call: True)
def query_handler(call):

    bot.answer_callback_query(callback_query_id=call.id, text='Спасибо за честный ответ!')
    answer = ''
    if call.data == '3':
        answer = 'Вы троечник!'
    elif call.data == '4':
        answer = 'Вы хорошист!'
    elif call.data == '5':
        answer = 'Вы отличник!'

    bot.send_message(call.message.chat.id, answer)
    bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id)

bot.polling()