Простой Telegram-бот на Flask с информированием о погоде
- четверг, 2 апреля 2020 г. в 00:18:06
Всем привет, в этой статье я расскажу как сделать простейшего телеграмм бота на Python для отправки текущей погоды в Москве.
Статья расчитана на новичков в Python, которые бы хотели узнать больше о том, как взаимодействовать с внешними сервисами по API.
Технологии и API:
На этом этапе нам нужно создать бота и получить к нему доступы. Для этого запускаем бота @botfather в Telegram командой ниже.
/start
Создаем нового бота согласно инструкциям из сообщения от бота.
!
Бот создан, но если ему написать какое-нибудь сообщение, он никак на него не отреагирует. Исправим это.
Flask — фреймворк для создания веб-приложений на языке программирования Python, использующий набор инструментов Werkzeug, а также шаблонизатор Jinja2. Относится к категории так называемых микрофреймворков — минималистичных каркасов веб-приложений, сознательно предоставляющих лишь самые базовые возможности.
Поддерживается установка посредством пакетного менеджера PyPI, версия 1.0 совместима с Python 2.7, Python 3.3 и выше.
Для изоляции зависимостей пакетов Python создадим папку проекта и виртуальное окружение. Для этого в терминале выполним команды ниже. Подробнее о виртуальных окружениях.
$ mkdir weather_bot
$ cd weather_bot
$ python3 -m venv venv
После завершения установки и активации виртуального окружения установим Flask.
(venv)$ pip install Flask
Подробнее на странице Installation.
В директории weather_bot
создадим файл app.py
с содержимым.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
Запустим полученное приложение.
(venv)$ export FLASK_APP=app.py
(venv)$ flask run
* Running on http://127.0.0.1:5000/
Перейдем по адресу http://127.0.0.1:5000/ и убедимся, что отображается текст "Hello, World!".
Подробнее на странице Quickstart.
Ngrok — это сервис, позволяющий создавать туннели на локальный компьютер пользователя.
$ ./ngrok http 5000
Для того, чтобы Telegram пересылал сообщения на наш сервер, нужно передать сообщить ему адрес сервера. У нас уже создан туннель, поэтому его передадим адрес в Telegram. Это делается с помощью метода POST setWebhook. Подробнее на странице документации.
$ curl --location --request POST 'https://api.telegram.org/bot{token}/setWebhook' \
--header 'Content-Type: application/json' \
--data-raw '{
"url": "{url}"
}'
где {token} — токен вида 840446984:AAFuVTW-FYP5tJVu8mqhc9y4E0j1fr2lCD0, который нам прислал BotFather,
{url} — адрес вида https://32515a83.ngrok.io, который отобразился в консоли ngrok. Обратите внимание на протокол. Он должен быть https, иначе Telegram не примет url.
Подробнее о cURL на странице wiki.
Если получен ответ "ok": true, то все в порядке.
{
"ok": true,
"result": true,
"description": "Webhook was set"
}
Проверим, что сообщения доходят до нашего локального сервера. Для этого в файле app.py
обновим код.
from flask import Flask, request
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def receive_update():
if request.method == "POST":
print(request.json)
return {"ok": True}
Перезапустим Flask. Для этого остановим сервер из терминала комбинацией клавиш Ctrl+C и повторно запустим сервер.
(venv)$ flask run
Отправим нашему боту сообщение с произвольным текстом. В консоли должно отобразиться тело запроса из Telegram. Это признак того, что все в порядке.
!
Мы научились получать сообщения от пользователей, но еще не умеем их отправлять. Для проверки отправки сообщений будем отвечать текстом "pong" на все сообщения.
Для отправки сообщений пользователям в API Telegram используется метод sendMessage. Подробнее на странице документации.
Запросы будем делать с помощью библиотеки requests, которой нет в списке стандартных, поэтому установим ее. Для этого в терминале с активированным виртуальным окружением выполним команду нижу.
(venv)$ pip install requests
Добавим строку импорта requests
сразу за строкой from flask import Flask, request
в app.py
.
import requests
Для отправки сообщений нам нужно знать id чата. Его можно вытащить из тела Telegram-запроса.
chat_id = request.json["message"]["chat"]["id"]
Напишем функцию для отправки сообщений, в которую будем передавать id чата и текст сообщения.
def send_message(chat_id, text):
method = "sendMessage"
token = "840446984:AAFuVTW-FYP5tJVu8mqhc9y4E0j1fr2lCD0"
url = f"https://api.telegram.org/bot{token}/{method}"
data = {"chat_id": chat_id, "text": text}
requests.post(url, data=data)
Подробнее о библиотеке requests
на странице.
Добавим вызов функции send_message()
из receive_update()
.
send_message(chat_id, "pong")
Вот так выглядит код в файле app.py
from flask import Flask, request
import requests
app = Flask(__name__)
def send_message(chat_id, text):
method = "sendMessage"
token = "840446984:AAFuVTW-FYP5tJVu8mqhc9y4E0j1fr2lCD0"
url = f"https://api.telegram.org/bot{token}/{method}"
data = {"chat_id": chat_id, "text": text}
requests.post(url, data=data)
@app.route("/", methods=["GET", "POST"])
def receive_update():
if request.method == "POST":
print(request.json)
chat_id = request.json["message"]["chat"]["id"]
send_message(chat_id, "pong")
return {"ok": True}
Используем метод current
Weatherstack API для получения информации о погоде.
Передадим 2 обязательных Query Params: access_key — секретный ключ вида 86a3fe972756lk34a6a042bll348b1e3, который можно получить после регистрации, и query — город, по которому получаем информацию о погоде, в нашем случае — Moscow.
Подробнее на странице документации.
Добавим функцию для получения текущей температуры в Москве после строки app = Flask(__name__)
.
def get_weather():
params = {"access_key": "86a3fe972756lk34a6a042bll348b1e3", "query": "Moscow"}
api_result = requests.get('http://api.weatherstack.com/current', params)
api_response = api_result.json()
return f"Сейчас в Москве {api_response['current']['temperature']} градусов"
Внутри функции receive_update()
вместо сообщения с текстом "pong" передадим погоду.
weather = get_weather()
send_message(chat_id, weather)
Код всего Flask-приложения состоит из 3 функций: получения сообщений из Telegram, отправка сообщений в Telegram и получение информации о погоде из Weatherstack.
from flask import Flask, request
import requests
app = Flask(__name__)
def get_weather():
params = {"access_key": "86a3fe972756lk34a6a042bll348b1e3", "query": "Moscow"}
api_result = requests.get('http://api.weatherstack.com/current', params)
api_response = api_result.json()
return f"Сейчас в Москве {api_response['current']['temperature']} градусов"
def send_message(chat_id, text):
method = "sendMessage"
token = "840446984:AAFuVTW-FYP5tJVu8mqhc9y4E0j1fr2lCD0"
url = f"https://api.telegram.org/bot{token}/{method}"
data = {"chat_id": chat_id, "text": text}
requests.post(url, data=data)
@app.route("/", methods=["GET", "POST"])
def receive_update():
if request.method == "POST":
print(request.json)
chat_id = request.json["message"]["chat"]["id"]
weather = get_weather()
send_message(chat_id, weather)
return {"ok": True}
Вот и всё! Таким несложным образом мы научили наш бот информировать нас о погоде в Москве.