Django telegram bot как связать
6 февраля 2018 года команда Telegram анонсировала запуск Telegram Login Widget для внешних сайтов.
Виджет предназначен для авторизации на сайте с помощью Telegram.
Виджет представляет собой кнопку с надписью Log in with Telegram. При нажатии на эту кнопку появляется окно, в которое пользователь должен ввести свой номер телефона. Введенный номер телефона не будет сообщен администратору сайта.
После ввода номера телефона пользователю придет уведомление в Telegram от пользователя Telegram следующего содержания:
Как только пользователь примет запрос авторизации в приложении Telegram, сайт получит информацию об авторизованном пользователе.
Создание бота Telegram
Для реализации системы авторизации необходимо создать бота.
Для этого необходимо написать в Telegram боту @BotFather. Это служебный бот для создания других ботов.
Создание бота происходит путем отправки ему команды /newbot . Бот запросит имя создаваемого бота, как его будут видеть пользователи. Второй вопрос предполагает ввод username создаваемого бота, @examplebot , t.me/examplebot . Username бота всегда должен заканчиваться на bot или Bot . Это требование Telegram. Пусть наш созданный бот называется @TestWidgetBot .
Если введенное имя уже занято, то будет предложено ввести другое. Если имя свободно, то BotFather пришлет токен созданного бота. Токен представляет собой строку вида xxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx и предназначен для авторизации бота.
Подключение домена
Возможно, эти недочеты будут устранены в дальнейшем.
Генерация кода виджета авторизации
В генераторе нужно ввести следующие параметры.
Username бота, без символа @ , например TestWidgetBot .
Размер виджета, Small, Medium или Large.
Выбрать тип авторизации.
При выборе Redirect to URL при успешной авторизации пользователь будет переадресован на страницу с указанным URL. Параметры авторизованного пользователя (username, chat_id, first_name, last_name и пр.) будут переданы в качестве GET-параметров. Я использую именно этот тип авторизации.
При выборе Callback параметры пользователя будут переданы в качестве аргумента JavaScript функции. Параметры представляют собой JSON-объект.
Request Access необходимо установить, если требуется, чтобы бот мог начинать диалог с пользователем.
В моем случае получился такой код:
Сгенерированный код необходимо скопировать и вставить на странице сайта.
Обработка запроса на сервере
При подтверждении пользователем авторизации на сайте, в зависимости от выбранного параметра “тип авторизации”, либо выполнится JavaScript-функция, либо пользователь будет перенаправлен на страницу Callback URL. В качестве GET-параметров на эту страницу будут переданы данные пользователя.
Рассмортрим второй вариант.
Рассмотрим на примере. Предположим что клиент с chat_id 8951599, именем Andrey, фамилией S, авторизовался на сайте в момент времени 1518613843. Тогда после подтверждения авторизации он будет перенаправлен на URL:
Параметр hash служит для проверки данных. На странице документации приведен алгоритм, по которому следует проводить валидацию данных. Я разработал класс для проверки данных по этому алгоритму, он доступен по ссылке:
Использовать класс следует следующим образом:
Переменная окружения BOT_TOKEN должна содержать токен бота.
На странице регистрации можно сохранить данные пользователя, сохранить в сессии идентификатор пользователя. В дальнейшем если пользователь зайдет на сайт, в зависимости от установленной сессии можно произвести те или иные действия.
Заключение
В статье описан общий принцип работы авторичзации пользователя на сайте с использованием Telegram Login Widget. В статье используется технологии Python и Django, однако принцип может быть реализован с применением любых технологий, позволяющий обработать GET-запрос.
Данная заметка это продолжение статьи про написание telegram бота, в ней я постараюсь максимально подробно осветить тему разворачивания (deploy) полноценного, хотя и маленького, Django приложения в production среде на ОС Linux, Ubuntu 14.04 LTS. К концу статьи у нас будет полноценный telegram бот, крутящийся в вебе и принимающий команды от пользователей этого мессенджера.
Чему вы научитесь после прочтения заметки:
- Разворачивать Django приложение (да и любое WSGI приложение) на хостинге Digital Ocean в среде Linux
- Работать с веб-серверами nginx и gunicorn
- Управлять процессами, используя утилиту supervisord
- Настраивать virtualenv с помощью pyenv
- Автоматически запускать веб-приложение даже после перезагрузки сервера
В сентябре 2015 года мы проводили Python митап в Алматы на котором я выступал с докладом на тему веб-разработки на Python. Во время выступления я вкратце описал веб эко-систему Python и сделал краткий обзор популярного инструментария. К сожалению, формат митапа не предусматривал детальный разбор темы, поэтому новичкам в этой области обычно приходится дальше копаться самостоятельно. Сегодня я постараюсь восполнить этот пробел и немного углубиться в "горячую" тему деплоя веб приложений на Python. Несмотря на то, что в статье речь будет идти о Django приложении, описываемые рецепты будут актуальны и для других веб-проектов, разработанных на Python с использованием WSGI-совместимых фреймворков (Flask, Bottle, Pyramid, Falcon, web2py и так далее).
В заметке я буду делать деплой на виртуальном хостинге от Digital Ocean. Если вы зарегистрируетесь по этой ссылке, то после подтверждения платёжных данных, счёт вашего аккаунта сразу пополнится на $10, которые можно потратить на создание маленьких дроплетов (виртуальных серверов) и потренироваться в разворачивании веб проектов на Python. Сразу скажу, что вам необязательно всё делать на удалённой машине и вообще использовать хостинг-провайдер, можно обойтись и локальной виртуалкой, например, используя VirtualBox и Vagrant (но в таком случае невозможно будет установить webhook).
Создание виртуального сервера
Как я ранее уже упоминал, деплой мы будет производить на одном из виртуальных серверов DigitalOcean с его мощным API :)
Создаём дроплет, нажимая на "Create droplet" в правом верхнем углу панели управления:
Выбираем самый минимальный тариф за 5 долларов в месяц с операционной системой Ubuntu 14.04.4 LTS на борту будущей виртуальной машины.
В качестве дата-центра я практически всегда выбираю Frankfurt, так как до него у меня самый лучший пинг. После заполнения всех необходимых полей, нажимаем кнопку "Create". Дроплет создаётся в течение 60 секунд после которых на почту поступает вся необходимая для доступа информация о новой виртуальной машине: IP адрес, логин и пароль.
Настройка сервера
После успешного создания нам необходимо авторизоваться на сервере. Сразу после входа, система попросит установить новый пароль для суперпользователя root.
Далее необходимо завести отдельного sudo пользователя из под которого будем запускать Django приложение.
Заходим под новым юзером django на сервер, и все остальные команды выполняем из под данного юзера.
Устанавливаем необходимый арсенал для настройки виртуального окружения через Pyenv и сборки самой последней версии Python (2.7.11).
После этого ставим сам Pyenv. Подробнее о том что такое Pyenv и как его настроить можно прочитать здесь:
Устанавливаем Python самой последней версии (Python 2.7.11):
Выполнение команды займёт некоторое время (скрипт скачает Python и скомпилирует его из исходников). Устанавливая отдельный интерпретатор питона мы тем самым никак не влияем на работу системного, более того, в последней LTS версии Ubuntu (14.04) используется версия 2.7.6, в которой существует ряд серьёзных уязвимостей, включая баг с SSL, а также отсутствует поддержка TLS 1.2
Клонируем репозиторий с Django проектом:
Далее настраиваем виртуальное окружения Python, используя всё тот же pyenv.
Ставим зависимости через менеджер пакетов pip.
Django приложение, написанное в первой части, претерпело незначительные изменения. В частности я перенёс изменяемые части кода в специальный .env файл, используя библиотеку django-environ. Ознакомиться с изменениями можно по этой ссылке.
Создаём .env файл из шаблона и заполняем необходимые настройки.
В частности необходимо изменить режим DEBUG на False, прописать токен для Telegram бота и указать дополнительный хост через запятую в ALLOWED_HOSTS. В моём случае ALLOWED_HOSTS выглядит вот так:
То есть я завёл дополнительный поддомен на котором и будет крутиться Telegram бот.
Настройка SSL сертификата
В прошлой статье я писал о том, что в случае использования API вызова setWehook, хосту необходимо иметь валидный SSL сертификатом (Telegram позволяет использовать также самоподписанные сертификаты). Сертификат мы будет создавать через бесплатный сервис выдачи SSL сертификатов Let's Encrypt.
Настройка Nginx
Заполняем новый файл telegram_bot.conf следующим содержимым:
Прописываем наш новый конфиг в настройки nginx и перезагружаем его, чтобы изменения вступили в силу:
Что мы только что сделали?
Чтобы проверить успешность наших настроек, можно запустить django приложение через тестовый сервер командой runserver на 8001 порту и зайти на сайт:
URL Not Found это нормальное явление, так как у нас задан всего 1 валидный URL для непосредственной работы с Telegram - /planet/bot/<BOT_TOKEN>/ (не считая настройки Django админки).
Настройка Gunicorn через Supervisor
Пора приступить к настройке production-ready HTTP сервера Gunicorn, который, кстати, полностью написан на языке Python и хорошо зарекомендовал себя в реальном бою (к слову, во всех "живых" проектах я использую именно эту связку: nginx+gunicorn)
Что такое Supervisor?
Supervisor это утилита процесс-менеджер. Она "следит за здоровьем" ваших процессов-демонов и в случае их падения, старается снова их поднять. Если в ходе работы Gunicorn "падает" (системная ошибка, не та фаза луны и так далее), Supervisor старается его снова "поднять", таким образом работоспособность сайта не страдает. К слову, у меня в планах есть идея написать небольшую заметку про эту утилиту, так сказать Supervisor Advanced Usage. Стоит отметить, что все процессы, запущенные в Supervisor должны работать в foreground режиме, чтобы утилита понимала когда что-то идёт не по плану.
Для начала составим конфигурационный файл для запуска Gunicorn внутри Supervisor. Его содержимое выглядит вот так:
Сохраняем файл под именем gunicorn.conf (
/planetpython_telegrambot/gunicorn.conf). К слову, Gunicorn прописан в зависимостях нашего проекта (requirements.txt) и так как мы его уже установили в наше окружение, то узнать путь исполняемого файла можно выполнив команду внутри активированного виртуального окружения (активация происходит автоматически при переходе в директорию веб-приложения из-за наличия там файла .python-version, созданного через pyenv local):
Содержимое конфигурационного файла для supervisord:
Далее выполняем запуск Supervisor демона командой:
Запуск должен пройти без каких либо ошибок. Чтобы узнать статус текущих процессов, запускаем утилиту supervisorctl:
Для получения помощи, можно выполнить команду help. А для получения информации о команде - help . Например:
После успешного запуска supervisor, сайт должен быть доступен онлайн.
Автозапуск веб-приложения при перезагрузке
Доводилось ли вам слышать про так называемые upstart файлы? Именно написанием одного из них мы сейчас и займёмся. К слову, на текущий момент Upstart признана устаревшей и в новых версиях ОС на базе Linux планируется полный переход на systemd.
Файл должен быть помещён в /etc/init/ (в моём случае я дал ему имя telegram_bot.conf). Если ранее все запуски не вызывали проблем, то после рестарта системы, приложение автоматически будет запущено:
Теперь необходимо прописать наш URL на стороне Telegram используя вызов API метода setWebhook:
На этом настройка бота закончена. Посылаем команды нашему боту @PythonPlanetBot и получаем адекватные ответы :)
Помогите пожалуйста никак не могу найти информации о деплое Telegram бота на pythonenywhere.
Файл "urls.py" проекта:
Файл "urls.py" бота:
Файл "views.py" бота:
Для Flask (с ним не работал) есть такой пример:
Буду благодарен за помощь.
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.Подписчики
Добрый день.
Посмотрите для начала статус установленного WebHook, нет ли ошибок с сертификатом безопасности. Это можно сделать из командной строки:
Попробовал реализовать через сертефикат и изменил код:
Попробовал создать сертефикат при помощи acme-tiny (Let's Encrypt certificates):
И получил в логах:
Сервер его вообще не принимает. C рекомендуемым certbot то же самое.
Решил уйти от сертификата к простому токену.
Файл urls.py приложения бота:
Код views.py приложения бота:
При проверке через терминал получаю:
В логах тишина. Немогу понять, что не верно. Особенно если по началу все вроде бы заработало.
Только теперь не знаю как быть. Толи я, что-то не то сделал, то ли телеграм тупит.
Постоянно сробатывает Одна и таже процедура в коде, а именно часть 'Рассказать о боте':
Подскажите пожалуйста, где я туплю. Спасибо.
Что-то не особо помогает.
Похоже что у pythonanywhere какие-то проблемы с передачей обновлений боту или у телеграм. То приходят данные, то нет. Сейчас проверка показывает:
Можете привести пример реализации ответа или подредактировать мое, может я уже туплю на ровном месте.
urls.py приложения бота:
views.py приложения бота:
Большое спасибо за помощь.
На python не делал, поэтому не подскажу, как правильно.
Бросаются в глаза последние строчки из views.py:
Они что, выполняются каждый раз? Если да, то это не правильно. WebHook устанавливается один раз и после этого ничего с ним делать не нужно (пока адрес вашего сервера не изменится или токен бота). Я бы вообще управление вэбхуком из кода убрал, это можно из консоли сделать одной строчкой, когда понадобится.
Спасибо за подсказку.
Да я и не подумал, что код установки webhook можно вообще убрать или вынести.
Здарова, чуваки. Сегодня я расскажу историю одного проекта, который я закончил буквально на днях. Суть его заключалась в следующем: было четыре сайта, с которых нужно было парсить информацию, формировать их в пост, и отправлять через бота в telegram канал. Пообщавшись с заказчиком, я изложил свое видение проекта: для управления постами решили использовать админку Django, парсер и бот, естественно, на Python. Для развертывания будем использовать хостинг Договорившись с заказчиком, мы пожали руки и я приступил к работе.
Часть первая. Модели Django
В общем, тут ничего сложного:
MAGAZIN_CHOICES — это список источников, с которых парсится информация. Их тут пять, но парсить мы будем только четыре из них. (потому что пятый в контексте проекта нормально спарсить не получится, с заказчиком сошлись на том, что он будет его вручную постить)
date_string — это идентификационное поле. В нем будет содержаться эксклюзивная для поста информация, по которой можно будет определить — старый это пост, или новый
base_url — ссылка на источник, с которого были собраны данные. Заказчик попросил для удобства
message_id, chat_id — поля, в которых хранится техническая информация о посте. Чуть позже расскажу, для чего.
datetime_post — время, когда нужно вкинуть пост на канал
magazine_type — ну тут понятно, поле показывающее к какому источнику относится пост
is_posted — поле, которое показывает, находится ли пост уже на канале, или еще нет
date_created — поле, показывающее время создания поста в базе данных, используется для сортировки
Модель Image хранит ссылку на пост и ссылку на изображение.
Часть вторая. Функционал бота
Обратившись в поддержку хостера в поисках каких нибудь штатных средств обхода блокировки мне ответили, что им принципиально пофиг на блокировку, но вот их провайдеру очень даже не пофиг, потому сказали, что ничем помочь не могут.
В голове сразу начали крутиться варианты решения проблемы: сказать клиенту, что нужно заказать другой хостинг? Нет, деньги уже потрачены. Заюзать бесплатные прокси и постоянно их менять? Бред. Купить прокси? Не вариант. Тогда мне в голову пришла следующая идея: можно написать небольшое django приложение, которое будет в роли ретранслятора. Т.е. принимать запросы от моего приложения, перенаправлять их к telegram api, принимать на него ответ и отправлять его моему приложению. Разместить его конечно нужно там, откуда есть доступ к telegram api.
Внимание! Это костыль, и за такое решение у нас в провинции бьют ногами в лицо, поэтому очень не рекомендую повторять это в своих проектах. У меня, благодаря моей врожденной глупости, не осталось выбора. Это был единственный вариант, который не раздувал бюджет. К тому же, посты через бота отправлялись четыре раза в неделю, поэтому этот костыль никак не сыграет на производительности.
В общем, получилось нечто такое:
Немного поясню. Я решил не заморачиваться и для общения с telegram api заюзал библиотеку telepot .
Далее мы отвечаем ответом, который мы получили на запрос sendMessage , благодаря чему мы получили message_id и chat_id — идентификационные данные поста, с помощью которых мы можешь его редактировать.
EditPostView выглядит очень просто. Мы получаем из запроса message_id и chat_id , и используем их для редактирования текста в посте. Ответ пересылаем обратно.
Все это дело я по быстрому залил на heroku и протестировал. Работает идеально:
Допиливаем основное приложение
Пришло время реализовать основной функционал в нашем приложении
В наш Topic добавим три функции: is_post , posted и save
is_post скажет нам, готов ли пост по времени к отправке на канал
posted запостит его на канал
save — это переопределение метода сохранения модели. Переопределяем мы его для того, чтобы в случае, если пост уже на канале — отредактировать его не только в модели но и в телеграмме, отправив соответствующий запрос:
Читайте также: