Как стать автором
Обновить

Создание телеграм бота на Django + pyTelegramBotApi

Уровень сложностиПростой

Задался я вопросом создания бота в телеграм для беседы, который бы напоминал нам о др всех её участников. И я столкнулся с такой проблемой, что хотелось поиграться с админкой django, но нет нормальных туториалов по использованию ботов именно вместе с django. Был вариант, который я нашел, с реализацией через core команды по типу manage.py runserver и тд, но зачем для простенького бота такие заморочки. Даже думал попробовать использовать Flask, ведь его много где использовали и он мне даже показался очень удобным по началу для моей задачи. А потом просто все заработало и я понял, что это проще, чем кажется. Собственно, сегодня разберем бота на Django и pyTelegramBotApi.

Стэк технологий, которые потребуются

Во-первых, хотелось бы разобрать то, на чем это все стоит. Итак, давайте по порядку:

  • Django любой версии, но от 4 версии есть свои приколы с доменами, поэтому с ними могут возникать ошибки в работе, которые крайне легко фиксятся

  • pyTelegramBotApi я использовал просто потому, что уже работал с ним и по факту нет разницы на чем писать, хоть на самой апишке телеграма, там все предельно просто, ютуб в помощь, но заморачиваться с этим я не хотел.

  • botFather для создания самого бота

  • Библиотеки python по-типу requests для пары фишечных функций

  • ngrok, но о нем чуть попозже

Пару слов о том, какую библиотеку использовать для бота. Не важно на чем вы пишете: aiogram, telebot или сама апи телеграма. Готовые библиотеки просто упрощают ваше взаимодействие с api, ведь без них вы бы писали руками кучу запросов, а покопавшись в их документациях, можно найти, что они используют всё те же запросы, просто автоматизируют их за вас.

Какую роль играет django

В своем боте я хотел попробовать использование вэбхуков, поэтому django мне помог с этим полностью. Собственно большую часть работы с бд и моделями django тоже мне заменил, так что мне даже не пришлось продумывать очень сильно этот момент. Но для простых и маленьких ботов без хранения данных, насколько стало понятно, легче делать бота на скриптах. Поэтому в основном django осуществлял работу принятия запросов с вэбхука. А вот тут как раз для теста на локальном компьютере нам поможет ngrok. Он нам создаст наш личный url, который будет отображаться в браузере и мы сможем повесить на него уже вэбхук, ведь на localhost это сделать не получится. На этой ноте я думаю можно перейти к созданию.

Написание бота

Итак, первое, что нам нужно сделать, это создать виртуальное окружение, чтобы не убить наш компьютер и было легко закинуть все на сервер в будущем. Виртуальное окружение поможет нам сохранить все библиотеки внутри проекта, а в будущем выгрузить в txt нужную информацию, чтобы установить уже на сервер.

Пропишем в консоли

python -m venv venv

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

pip install Django
pip install pyTelegramBotAPI

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

django-admin startproject mybot

Внутри нашей папки создается проект с базовыми настройками django. После этого мы переходим внутрь созданной папки и так же создаем приложение нашего бота с представлениями и т.п.

cd mybot
django-admin startapp bot

Внутри нашего проекта создается приложение, где есть базовые файлы django.

Итак, почти все готово для запуска нашего бота. Нам нужно добавить созданное приложение в INSTALLED_APPS внутри settings.py нашего проекта, чтобы код был следующим:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bot',
]

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

Добавим в urls.py нашего проекта следующее:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('bot.urls')),
]

Данный код будет делать редирект на приложение, когда мы попадем на главную страницу. И меняем urls.py внутри приложения, чтобы уже обрабатывать запросы.

from django.contrib import admin
from django.urls import path
from . import views
from django.views.decorators.csrf import csrf_exempt


urlpatterns = [
    path('', csrf_exempt(views.index), name='index'),
]

Итак, переходим к написанию представлений:

bot = telebot.TeleBot(settings.BOT_TOKEN)


def index(request):
    if request.method == "POST":
        update = telebot.types.Update.de_json(request.body.decode('utf-8'))
        bot.process_new_updates([update])

    return HttpResponse('<h1>Ты подключился!</h1>')

Здесь я создаю экземпляр класса TeleBot с токеном, который беру из переменной окружения внутри settings.py. Это нам нужно для запуска на сервере, поэтому для работы на локальной машине лучше не забивать этим голову. фунция index принимает в себя запрос и проверяет его метод. Т.к. сервера телеграма посылают именно POST запросы вместе с принятием сообщений от пользователя, нам нужно их отследить. Дальше мы берем тело запроса и создаем экземпляр класса Update, что уже передаем в обработчик новых событий. Я также вывожу надпись о успешном подключении, если отправлю GET запрос, просто для проверки работоспособности.

Основная часть по подготовке бота на самом деле уже завешилась. Дальше нам предстоит уже написание функций обработчиков команд и сообщений, что уже можно сделать исходя из докуменатции к библиотеке pyTelegramBotApi и вашей фантазии. Для примера я приведу вам свой обработчик /start:

@bot.message_handler(commands=['start'])
def start(message: telebot.types.Message):
    name = ''
    if message.from_user.last_name is None:
        name = f'{message.from_user.first_name}'
    else:
        name = f'{message.from_user.first_name} {message.from_user.last_name}'
    bot.send_message(message.chat.id, f'Привет! {name}\n'
                                      f'Я бот, который будет спамить вам беседу :)\n\n'
                                      f'Чтобы узнать больше команд, напишите /help')

Позже я узнал о том, что можно взять полное имя, а не обрабатывать его отдельно, но переделывать уже было лень, оставил это на следующую версию бота. Но теперь встал вопрос, как же нам получать эти запросы на локальной машине. Тут то нам и пригодится ngrok.

Регистрируемся на их сайте и далее идем в консоль. Запускаем локальный сервер django:

python manage.py runserver

А также открываем второй терминал и запускаем ngrok:

ngrok http 8000

Тем самым мы создадим туннель на наш локальный хост и сможем зайти на отображаемую страницу с успешным подключением.

Будьте внимательны к версии ngrok, ведь для разных ОС разные приложения. Т.к. мне так же было лень настраивать себе url, поэтому я колхозным способом до сих пор держу туннель через ngrok. И я как раз столкнулся с ошибкой в его работе, когда скачал не для той версии linux.

Собственно итоговый вариант того, как выглядит проект моего бота:

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

Для django от 4 версии нужно добавить доверенный хост, о чем вам скажет сама django, когда вы попытаетесь подключиться к ней со стороннего url. Этого бояться не стоит, а фиксится одной строчкой в settings.py. Нагуглить легко по ошибке.

В заключение

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

Конечно же, данный проект не сказать, что доведен до совершенства, ведь я бы еще хотел запихнуть это все в docker и использовать их на сервере. А так же сделать url, а не колхозно использовать ngrok. Но это все не особо мне нужно было в поставленной задаче, ведь самое первое зачем я это делал для удобства с др и просто потренироваться.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.