How to write a Telegram news channel if you are not a programmer. Part two

from aiogram import Router, F from aiogram.types import CallbackQuery import datetime #импортируем переменные from variables import CHANNEL_ID, CHAT_ID #импортируем процедуру работы с БД from sql import update_db #импортируем парсер ссылки на новость from parse import parselink #подключаем роутер router = Router() #если новость не нужна - удаляем @router.callback_query(F.data=='gpt_button_delete') async def delete_message(callback: CallbackQuery): try: await callback._bot.delete_message(chat_id=CHAT_ID, message_id=callback.message.message_id) for item in callback.message.entities: if item.type == 'text_link': post = item.url id = parselink(post) await update_db(id,'Del', datetime.datetime.now()) except: for item in callback.message.entities: if item.type == 'text_link': post = item.url id = parselink(post) await update_db(id,"Can't del - more 48H", datetime.datetime.now())

Pay attention to how we extract the link from the message using the familiar procedure parselink() pull news_id. At the object message have their own entities through the collection of which we loop until an object with the type appears text_link.

If we look at the principle of how button click processing works, then through the router decorator we track callbacks, and if the event “gpt_button_delete“start the procedure delete_message(). Everything should be clear to attentive readers of the Aiogram guide.

Now we have a fully working Delete button – the message is deleted, and the deletion status and time of this deletion are entered into the database.

Where would we be without AI?

If you haven’t forgotten yet, then in the first collection of buttons we have a button – “Send to Chat-GPT”.

For our example we will use ChatGPT and their python library openaiwhich must be installed in the project environment in the standard way via the pip utility.

I understand that in Russia there are now certain difficulties with access, registration and payment for OpenAI services. There are plenty of examples online on how to solve this problem. We will assume that you have successfully registered, made payment and received a token.

In the example, I will use the “gpt-4” model – in my opinion, the result of its work is better than that of the “gpt-3.5 turbo”. But each such request costs more and it works significantly slower.

Forming a question (Prompt) for Chat-GPT is a separate and complex topic, one might say it is an entire art. I recommend reading this material. In any case, I advise you to have patience and a budget for experiments – here you will have to experiment for some time. Let’s say our Prompt will look like this (we will insert it into the procedure code later):

As an administrator of a news channel, write a short summary of the news (no more than 100 words)

Let’s create a file in the root of the project gptai.py and add the code to it:

#библиотека для работы с ChatGPT
import openai
#токен добавляем в variables.py, а сюда подгружаем
from variables import GPT_TOKEN

#процедура, которая получает на вход чистый текст новости и возвращает рерайт-версию
def get_GPT(text):
    openai.api_key = GPT_TOKEN
    response = openai.ChatCompletion.create(
    model="gpt-4",
        temperature=0,
        messages=[
            {
                "role": "system",
                "content": "Как администратор новостного канала напиши короткое изложение новости (не больше 100 слов)"
            },
            {
                "role": "user",
                "content": text
            }
        ])
    return response['choices'][0]['message']['content']

It’s quite simple – the procedure get_GPT() receives the text of the article and then feeds it to openai – directing the request to two roles: the user with the text of the article and the “system” with our prompt. The procedure ultimately returns a ChatGPT response.

Returning to the world of aiogram

All that remains is to write a new handler that catches the click of the Send to Chat-GPT button and sends the text to get_GPT(). To file handlers.py add:

handlers.py
from aiogram import Router, F
from aiogram.types import CallbackQuery
import datetime

#импортируем переменные
from variables import CHANNEL_ID, CHAT_ID

#импортируем процедуру работы с БД
from sql import update_db, select_for_db
#импортируем парсер новости и парсер ссылки
from parse import parse, parselink
#импортируем вторую коллекцию кнопок
from entrails.keyboard import second_collection
#импортируем процедуру работы с ChatGPT
from gptai import get_GPT


#подключаем роутер
router = Router()


#Отправляем новость на съедение ChatGPT
@router.callback_query(F.data=='gpt_button_pressed')
async def get_link(callback: CallbackQuery):
    for item in callback.message.entities:
         if item.type == 'text_link': 
            post = item.url#url на новость
            id = parselink(post)#получаем из url id-новости
            text =  parse(post)#чистый текст новости
            title = await select_for_db(id, 'title')#берем заголовок из базы
            brief = get_GPT(text)#получает текст от ChatGpt
            
            #формируем текст сообщения     
            format_text = f'<b>{title[0]}</b>\n{brief}\n<a href="https://habr.com/ru/articles/770428/{post}">Link</a>'
            
            #добавляем в базу статус и время отправки сообщения
            await update_db(id,'Send', datetime.datetime.now())
            #отправляем сообщение
            await callback.message.answer(format_text,
                                            parse_mode="HTML",
                                            disable_web_page_preview=True,
                                            reply_markup=second_collection())
    #пробуем удалить исходное сообщение
    try:
        await callback._bot.delete_message(chat_id=CHAT_ID, message_id=callback.message.message_id)
    except:
        print(f"{callback.message.message_id} can't be deleted")

I provided the code under the spoiler with detailed comments, so I won’t repeat it. The message is generated from previously entered into the database title, link and Chat-GPT response. The attentive reader will notice that in callback.message.answer we added disable_web_page_preview=Tre to disable page preview via link, as well as the second collection with one single button – Send to Channel.

Result of ChatGPT

Result of ChatGPT

Important note about work

Please note that the gpt-4 model is very slow. After clicking on the Send to Chat-GPT button, you will have to wait 30-40 seconds before you receive a return message to the bot. I strongly advise against pressing buttons in several messages at once without waiting for a response – this may cause a crash.

Let’s write another small handler for the Send to Channel button, which will send a copy of the message (without buttons) to the news channel:

@router.callback_query(F.data=='channel_button_pressed')
async def send_tochat(callback: CallbackQuery):
    await callback._bot.copy_message(chat_id=CHANNEL_ID, 
                                     from_chat_id=CHAT_ID, 
                                     message_id=callback.message.message_id)
    try:
        await callback._bot.delete_message(chat_id=CHAT_ID, 
                                       message_id=callback.message.message_id)
    except:
        print(f"{callback.message.message_id} can't be deleted")

As a result, the message in the news channel should look something like this:

I think there is enough material for the second part of our trilogy.

We covered the following topics:

  1. We touched on the topic of regular expressions

  2. Learned the basics of working with databases

  3. Wrote 95% of the bot

  4. Connected to ChatGPT

In the final, third part, we will learn how to run the feed_reader() procedure on a schedule and write another handler in handlers.pywhich will call feed_reader() on command. In addition, we will build a Docker Image bot and try to run it on a remote server.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *