Как написать простого бота для Телеграм


Мы уже упоминали, как мы предоставляем бесплатные VPS для студентов, чтобы они учились программировать. Один из наших подопечных Павел сделал простеньких телеграм и ВК ботов для FAQ. Они очень просте, тем не менее, начинающему программисту не помешают комментарии опытных ребят — поэтому публикуем его рассказ — Павел будет рад, если в комментариях ему дадут советы.

Я — студент Новосибирского Государственного Технического Университета, не так давно мы с парочкой моих друзей реализовали площадку для продвижения проектов во всех возможных областях научной деятельности. Мы помогаем «сводить» заинтересованных преподавателей и студентов всех ВУЗов Сибири, чтобы проектная научная деятельность развивалась по территории Сибири и РФ.

Студенты и преподаватели часто обращались ко мне с вопросами и я решил автоматизировать этот процесс, написав ботов для ВК и Телеграм.

На вход они принимают сообщения, а на выходе выдают либо текстовый ответ, либо специальную структуру данных, замаскированное под сообщение: инлайновые или висячие клавиатуры.

Я использовать Python версии 3.6  просто потому, что он самый простой для меня. Кодил в PyCharm Community Edition. Весь код опубликован на GitHub. Удачи!

1. Предварительные приготовления для телеграм-бота

1.1 Получение токена от Bot Father в телеграмме

Первым делом, нам нужно «зарегистрировать» нашего бота в Telegram.

Для этого, в поисковике телеги ищем BotFather

далее, делаем всё также, как показано на скриншотах:

После нажимаем на команду /newbot или же прописываем вручную.

Надо придумать уникальное имя для бота, придумываем и получаем соответствующий токен.

1.2 Переходим в любой редактор кода и создаем файл config.py

Перед созданием данного файла, нам нужно выбрать директорию, в котором будет реализован весь функционал бота. Если вы используете PyCharm Community/Professional Edition, то предлагаю просто создать новый проект, и писать там весь функционал бота.

Если Вы используете любой другой редактор, такой как Sublime Text 3, например, то Вам самостоятельно придётся создать директорию, создать виртуальное окружение, и работать из консоли со всеми предварительными тестами. Во избежание трудностей, предлагаю скачать продукт PyCharm Community Edition от компании JetBrains, с помощью данного продукта можно обойти действия, описанные в предыдущем абзаце, так как данный продукт сделает их самостоятельно, от Вас потребуется только указать путь до интерпритатора Python в конфигурациях PyCharm, с помощью которого и будет работать Ваш бот.

В данном файле (config.py) будет храниться только токен, который нам дал BotFather, поэтому пишем:

token = "Здесь хранится Ваш токен".

1.3 Cоздаём главный файл — bot.py

Делаем cледующие импорты и для соответствующих библиотек, в консоли прописываем закоментированные строчки:

import config
import telebot # pip install telebot
from telebot import types # pip install pyTelegramBotAPI

Далее, нам необходимо использовать наш токен:

bot = telebot.TeleBot(config.token)

Этим действиям мы устанавливаем то, что мы будем накручивать функционал именно для того бота, для которого нам и дал токен BotFather.

2. Разворачиваем функционал

Начнём с того, что для того, чтобы пользователю запустить бота, нам необходимо прописать команды для старта они могут быть разными, например, /start или /go и вообще любыми, какими Вы сочтёте нужными.

Для обработки команд нам потребуется message_handler, с помощью которого и будет реализован весь функционал обработки команд для старта и завершения, если Вы сочтёте нужным добавить завершение. Как только придёт команда /go или /startmessage_handler с соответствующими командами сравнит, совпадают ли строки и если совпадают, то обработает соответствующей функцией.

Каждая функция, как и в примере сейчас, должна принимать один параметр — сообщение от пользователя, которое будет обработано соответствующей функции «в обёртке» декоратора. А также, каждая функция (или связка функций) должна возвращать соответсвующее сообщение от бота.

Итак:

@bot.message_handler(commands=['go', 'start'])  # Обработка команды для старта
def welcome(message):
    sti = open(path+'stiker.tgs', 'rb')
    bot.send_sticker(message.chat.id, sti)
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True)

    item3 = types.KeyboardButton("Приложения")
    item2 = types.KeyboardButton("Мероприятия")
    item1 = types.KeyboardButton('О нас')

    markup.add(item1, item2, item3)

    bot.send_message(message.chat.id,
                     "Добро пожаловать, {0.first_name}!\\n\\nЯ - <b>{1.first_name}</b>, бот команды Projector в НГТУ, "
                     "создан для того, "
                     "чтобы помочь Вам влиться в нашу команду,"
                     "просто узнать что-то о нас или же просто пообщаться и весело провести время.\\n\\n"
                     "<i>Have a nice time</i>".format(
                         message.from_user, bot.get_me()),
                     parse_mode='html', reply_markup=markup)

В этой функции реализовано сразу два действия: отправка приветственного сообщения и создание встроенной клавиатуры — ReplyKeyboardMarkup, которая будет открыта, пока мы не завершим выполнения бота соответсвующей командой. Об этом будет сказано ниже.

Итак, пройдёмся по строчкам:

В строках 20-21: открывается стикер по тому пути к директории, в которой я его сохранил, после чего отправляется.

Строки 22-28: создаем встроенную клавиатуру, добавляя туда три элемента.

Строки 30-37: описано создание и отправка приветственного сообщения

Как вы можете заметить, метод send_message в строке 30, позволяет использовать HTML, для форматирования текста.

Строками ниже, добавим запуск самого бота, который будет хоститься, пока не случится ошибка или же, пока мы Сами его не закроем.

# RUN
if __name__ == "__main__":
    try:
        bot.polling(none_stop=True)
    except ConnectionError as e:
        print('Ошибка соединения: ', e)
    except Exception as r:
        print("Непридвиденная ошибка: ", r)
    finally:
        print("Здесь всё закончилось")

Сделаем первый запуск! Для этого, в PyCharm-е нажмём зеленую кнопку старт в правом верхнем углу или же, можно запустить из консоли командой: python bot.py

Результат первого запуска:

2.1 Обработка нажатия на кнопки и создание inline keyboard

Так любое сообщение — это текст, то мы будем обрабатывать именно текстовые сообщения.

Сделаем следующее и аналогично разберём по строчкам:

@bot.message_handler(content_types=["text"])
def go_send_messages(message):
    if message.chat.type == 'private':
        if message.text == 'Приложения':

            keyboard = types.InlineKeyboardMarkup(row_width=1)
            itemboo = types.InlineKeyboardButton(text="Тыщ на кнопку и ты уже в Google", url="<https://www.google.ru>")
            itemboo1 = types.InlineKeyboardButton('Рандомное число', callback_data='good2')
            itemboo2 = types.InlineKeyboardButton("Калькулятор", callback_data='bad2')
            itemboo3 = types.InlineKeyboardButton("Хочу узнать погоду в моем городе/стране", callback_data='good3')
            itemboo4 = types.InlineKeyboardButton("Как твои дела?", callback_data='bad4')

            keyboard.add(itemboo, itemboo1, itemboo2, itemboo3, itemboo4)

            bot.send_message(message.chat.id,
                             "{0.first_name}, окей, смотри, что у нас есть тут:\\n".format(message.from_user),
                             reply_markup=keyboard)

        elif message.text == "Мероприятия":
            one_markup = types.InlineKeyboardMarkup(row_width=1)
            ite1 = types.InlineKeyboardButton("Ближайшие мероприятия", callback_data="one")
            ite2 = types.InlineKeyboardButton("Проведенные мероприятия", callback_data="two")
            ite3 = types.InlineKeyboardButton("Волонтерство на мероприятие", callback_data="three")
            ite4 = types.InlineKeyboardButton("Действующие проекты в НГТУ", callback_data="fourth")
            ite5 = types.InlineKeyboardButton("Мероприятия Межвузовского центра", callback_data="five")
            one_markup.add(ite1, ite2, ite3, ite4, ite5)
            bot.send_message(message.chat.id, "{0.first_name}, у нас <u>ежемесячно</u> проводится множество "
                                              "мероприятий,\\nмы постарались разбить их на следующие составляющие:".format(
                message.from_user), parse_mode="html", reply_markup=one_markup)

Строка 339 — обработчик любых текстовых сообщений


Строка 341 предназначена для того, чтобы сказать, что если данное сообщение предназначено боту, то сравни эту строку с теми, что здесь обрабатываются и отправь ответ.

Строки 344 — 351 — создаём инлайновую клавиатуру InlineKeyboardMarkup и помещаем в эту клавиатуру 5 элементов, которые также можно будет обработать по установленной callback_data. Элементы данной клавиатуры будут расположены друг под другом, так как в строке 344, мы установили row_width = 1, что обозначает самую широкую грань одной кнопки, поэтому они и будут расположены друг под другом.

Строки 353-355 — отправляют текст, вместе с нашей Inline Keyboard.

В условиях ниже представлены аналогичные представления обработки сообщений.

Итак, сделаем запуск:

2.2 Обработка InlineKeyboardButton

Как было сказано выше, каждый элемент InlineKeyboardButton имеет параметр callback_data, и именно по этим параметрам будет обрабатываться каждая кнопка. Для этого нам потребуется обработчик инлайновой клавиатуры callback_query_handler.

@bot.callback_query_handler(func=lambda call: call.data in ['one', 'two', 'three', 'fourth', 'five'])  # Мероприятия
def callback_inline_one(call):
    try:
        if call.message:
            if call.data == 'one'# Ближайшие мероприятия
                bot.send_message(call.message.chat.id,
                                 "Итак,<b>ближайшие мероприятия</b>:\\n\\n"  # Здесь будут ссылки ещё
                                 "Форум «Байкал»\\n"
                                 "Конкурс «Цифровой ветер»\\n"
                                 "PRONETI", parse_mode="html")
            elif call.data == 'two'# Проведённые мероприятия
                bot.send_message(call.message.chat.id, "Вот список <b>проведённых мероприятий</b>:\\n\\n"
                                                       "МНТК\\n"
                                                       "Семинары по проектной деятельности\\n"
                                                       "Встреча с представителями предприятий", parse_mode="html")
            elif call.data == 'three':

Итак, разберём по строчно:

Строка 269 — объявляем обработчик, который будет обрабатывать каждую из нажатых кнопок с использованием лямбда-функции

Строки 273-278 — В данном блоке if, мы просто обрабатываем сообщение и отправляем сообщение пользователю.

Строки 279-283 — Делают аналогичное действие, что и в предыдущем условном блоке.

и т. д.

Также, в данных блоках можно определить аналогичную инлайновую клавиатуру, только тогда придётся создать ещё один обработчик callback_data, аналогичный обработчику callback_query_handler, показанный на скриншоте выше.

Результат:

Так просто и обрабатываются inline keyboards.

3. Завершаем работу бота

Данная функция будет аналогичной функции обработки команд для старта бота, поэтому Вы сможете легко понять её функционал:

@bot.message_handler(commands=['stop'])  # Обработка команды для выхода
def bye(message):
    bye_Sti = open(path+'byeMorty.tgs', 'rb')

    hideBoard = types.ReplyKeyboardRemove()
    bot.send_message(message.chat.id,
                     "Досвидания, {0.first_name}!\\nМы, команда <b>{1.first_name}</b>, надеемся, что ты хорошо провел(а) время \\n\\n"
                     "Присоединяйся к нашей команде в <a href='<https://vk.com/projector_neti>'>vk</a>\\n"
                     "Наш <a href='<https://instagram.com/projector_neti>'>inst</a>\\n\\n"
                     "Напиши Координатору проектов (<a href='<https://vk.com/nikyats>'>Никите Яцию</a>) и задай интересующие тебя вопросы по <i>проектной деятельности</i>\\n\\n"
                     "Надеемся, что тебе ответят очень скоро \\n\\n"
                     "<u>Don't be ill and have a nice day</u> \\n\\n\\n"
                     "P.S.: Если есть какие-то пожелания или вопросы по боту, то напиши <a href='<https://vk.com/setmyaddresspls>'>мне</a>".format(
                         message.from_user, bot.get_me()), parse_mode='html', reply_markup=hideBoard)
    exit()

Здесь происходит следующее:

  1. Отправляется прощальный стикер.
  2. Закрывается встроенная клавиатура (строка 44).
  3. Отправляется прощальное сообщение.

Так как мы используем bot.polling, с параметром none_stop = True, то пользователь может снова вознообновить общение с ботом при помощи команды /start или /go, обработка которых показано в пункте выше.

Результат:


Добавить комментарий