Публикуем посты блога на канале telegram используя Django
У вас есть блог на Django и вы хотите , чтобы информация о посте автоматически появлялась бы на вашем телеграм канале. Или у вас на сайте прием заявок или иных событий и вы хотите , чтобы информация об этих заявках и событиях мгновенно появлялась у вас на телеграм-канале.
Это легко реализовать с помощью стандартных средств python, с использованием телеграм бота , который будет посылать сообщения в телеграм-канал.
И в этой статье я пошагово расскажу как это сделать.
Исходники проекта лежат на Github, а внизу будет пошаговое объяснение
Создание бота в телеграм
Нам нужно создать бота в телеграм. Для этого мы ищем по имени BotFather бота @BotFather в телеграм
Заходим в этот бот и создаем нашего бота. Для этого вы должны ввести команду /newbot . Дальше вам предложать выбрать имя для вашего бота , после того как вы введете имя будет предложено выбрать username для вашего бота , который должен быть уникальным и окончиваться на _bot.
Создание нового канала в телеграм
Создать канал очень легко. В телеграме кликаем по ссылке "Создать канал" и вводим название канала и описание
Канал мы должны сделать публичным и выбрать уникальное имя для ссылки.
Поздравляю! Канал мы создали. Теперь нам нужно созданного бота сделать администратором созданного канала , чтобы он мог туда публиковать сообщения.
Назначаем бота администратором для созданного канала
Добавляем нашего бота администратором
Нажмите ОК и тем самым вы приглашаете на канал и назначаете бота администраторм.
Далее , мы указываем боту разрешения. Тут мы задаем минимальные разрешения , позволяя ему только управлять сообщениями.
Отправляем первое сообщение на наш канал с помощью бота
Обычно , чтобы отправить сообщение через бот используют разные библиотеки , которые создают бота. Таких библиотек для python огромное количество , как синхронных и асинхронных. Но для такой простой задачи мы не будем их использовать. Их можно будет использовать для полноценных ботов , которые решают сложные задачи и в следующих статьях я это планирую сделать.
Тут будем использовать API Telegram и сделаем это с помощью стандартных библиотек Python.
# Используем стандартную библиотеку urllib.request
# для того , чтобы делать запросы.
# Можно использовать сторонние библиотеки requests или httpx
import urllib.request
import json
# Тут будет ваш токен, который вы получили при создании бота
BOT_TOKEN = "Ваш токен"
# Тут нужно указать название канала в ссылке,которое начинается с @
# Тут я указал для примера созданный канал
CHAT_ID = "@blog_publications"
def send_telegram_message():
# Используется метод sendMessage API Telegram
# Обратите внимание , что мы тут используем BOT_TOKEN
api_url = f'https://api.telegram.org/bot{BOT_TOKEN}/sendMessage'
#Указаваем в параметрах CHAT_ID и само сообщение
input_data = json.dumps(
{
'chat_id': CHAT_ID,
'text': "Первое привественное сообщение в блоге",
}
).encode()
try:
req = urllib.request.Request(
url=api_url,
data=input_data,
headers={'Content-Type': 'application/json'}
)
with urllib.request.urlopen(req) as response:
#Тут выводим ответ
print(response.read().decode('utf-8'))
except Exception as e:
print(e)
if __name__ == "__main__":
send_telegram_message()
Запускаем скрипт и видим , что запрос прошел успешно и вернулся ответ от Telegram
Смотрим на канал и видим , что там появилось первое сообщение , которое мы отправили с помощью бота
Используем переменные окружения
Хорошей практикой является хранение секретных(чувствительных) данных в переменных окружения. Поэтому в корне нашего Django проекта создадим файл .env . В этом файле мы будем хранить токен доступа к телеграм боту , название нашего канала , а также другие переменные.
Файл .env будет выглядет следующим образом:
BOT_TOKEN=7029945146:AqF-0vlfCTSPl8Ip9ui3xRQ
SECRET_KEY=django-insecure-%4)m0$c&8!hmzcymad+cxz1gi(2ofynsw7*7w(8
CHAT_ID=@blog_publications
Вы должны сюда поместить ваши данные. И этот файл не должен быть в репозитории GIT
Теперь вы должны установить библиотеку python-dotenv
pip install python-dotenv
Теперь в файле settings.py вашего Django проекта мы можем читать переменные окружение следующим образом:
from dotenv import load_dotenv
load_dotenv()
BOT_TOKEN = os.getenv('BOT_TOKEN')
CHAT_ID = os.getenv('CHAT_ID')
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('SECRET_KEY')
Тут мы загружаем с помощью этой фкункции load_dotenv переменные окружения из файла .env
А дальше они доступны через os.getenv()
Создаем функцию отправки информации о посте в телеграм канал
Создадим html шаблон сообщения , которая отправляется в телеграм
Файл post_telegram_message.html
{{ post.title }}
{{ post.content|truncatewords:30 }}
Дата создания:{{ post.created_at|date:'SHORT_DATE_FORMAT' }}
Создадим файл posts/telegram_utils.py и добавим метод получения содержимого шаблона с подставленными переменными.
Для этого будем использовать метод render_to_string , которая подставит необходимые переменные в шаблон post_telegram_message.html и вернет строку
from django.template.loader import render_to_string
def get_html_message_from_template(post) -> str:
return render_to_string('post_telegram_message.html', {
'post': post
})
Теперь создадим функцию отправки сообщения на телеграм канал с помощью телеграмм бота
import urllib.request
import json
from django.conf import settings
def send_telegram_message(chat_id: str, post):
api_url = f'https://api.telegram.org/bot{settings.BOT_TOKEN}/sendMessage'
input_data = json.dumps(
{
'chat_id': chat_id,
'text': get_html_message_from_template(post=post),
'parse_mode': "HTML"
}
).encode()
try:
req = urllib.request.Request(
url=api_url,
data=input_data,
headers={'Content-Type': 'application/json'}
)
with urllib.request.urlopen(req) as response:
print(response.read().decode('utf-8'))
except Exception as e:
print(e)
Эту функцию отправки мы уже можем использовать где-угодно в нашем Django приложении. И во вьюхах , и в консольных коммандах и в отложенных задач , которые выполняют системы очередей, такие как Celery. Все зависит от ваших целей и потребностей
Я решил создать кнопку при редактировании поста в админке и при нажатии котороый происходит отправка в телеграм канал
Добавляем возможность в админке публиковать сообщение в телеграм канале
from django.contrib import admin
from django.http import HttpResponseRedirect
from django.conf import settings
from posts.telegram_utils import send_telegram_message
from posts.models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
change_form_template = "post_change_form.html"
list_display = ('title', 'created_at', 'is_published')
def response_change(self, request, post_obj):
if "publish-telegram" in request.POST:
send_telegram_message(
chat_id=settings.CHAT_ID,
post=post_obj
)
post_obj.is_published = True
post_obj.save()
self.message_user(request, "Опубликовано сообщение об этом посте в телеграм канале")
return HttpResponseRedirect(request.path_info)
return super().response_change(request, post_obj)
Наглядно это будет выглядеть следующим образом:
Заключение
При написании данной статьи я использовал эту англоязычную статью. Но в этой статье используется библиотека python-telegram-bot, но для данной задачи я считаю использование таких библиотек излишним , так как можно обойтись стандартными средствами. И еще в этой статье используется python-telegram-bot версии 12.2.0 , которая сейчас является устаревшей. Сейчас рекомендуется использовать версию 20 версии и выше , где используется асинхронный подход. Хотя , можно использовать ее используя асинхронные вьюхи , которая нам любезно предоставляет Django. Но в этой статье я использую синхронный подход.
В своей статье я отправку реализовал при редактировании поста в django admin. Добавил кнопку при нажатии которой происходит отправка сообщения в телеграм-канал. Но вы можете использовать функцию отправки сообщения в любом месте
Исходный код опубликован на Github