Привет, Хабр! Это мой первый пост и решил я его посвятить тому: Как можно автоматизировать ведение своего ТГ канала с помощью ИИ. На мой взгляд тема довольно свежая и интересная, а что самое главное полезная. Статья по большей мере ориентирована на новичков у которых имеются базовые знания python, но это не означает что другим она не будет интересна. Итак, начнем!
Установка Docker
Идем на официальный сайт Docker https://www.docker.com/products/docker-desktop/ нажимаем на кнопку Download Docker Dekstop и выбираем свою систему из выпадающего списка, устанавливаем программу и запускаем исполняемый файл и вуаля теперь у вас в системе есть инструмент для контейнеризации ваших программ. К слову он нам понадобиться для запуска redis в отдельном контейнере, так как на windows пока нет возможности запускать reids нативно как это можно делать на Unix системах. Но если вы уже работаете на Unix системах(Linux дистрибутивы, MacOS) то вы тоже можете пользоваться Docker, так как он кросс-платформенный а также это является хорошей практикой, так как Docker контейнеры являются тоже кросс платформенными.
Создание виртуального окружения
При создании этого проекта я использовал версию python 3.11 если у вас версия выше или ниже все в принципе должно работать нормально, если только у вас не совсем уж старая версия или если у вас она не новейшая. Чуть позже покажу что делать в таком случае.
Для начала перейдите в мой GitHub репозиторий и скачайте оттуда файл requirements.txt
Создайте папку и назовите ее как-нибудь, потом перекиньте туда скачанный ранее файл
После чего откройте эту папку в консоли, на windows это правый клик мыши - открыть в Терминале
В консоли наберите такую команду:
python -m venv venv
А потом останется лишь активировать виртуальное окружение:
venv\scripts\activate
и скачать зависимости из requirements.txt следующей командой:pip install -r requirements.txt
Если у вас очень старая версия python или же новейшая( Не все библиотеки могли успеть выкатить обновления для новейших версий) то в таком случае вам надо либо переустановить python либо же если вам не хочется заморачиваться с этим вы можете использовать виртуальное окружение Miniconda.
Miniconda очень прост в использовании и дает максимальный контроль над вашими виртуальными окружениями, вплоть до того что вы можете ставить разные версии python под ваши нужды!
Создание Miniconda окружения
Для начала перейдите на официальный сайт Anaconda введите свой email и нажмите на submit, после чего вас встретит страница с двумя версиями Conda, качайте Miniconda и ставьте на свою систему.
После чего откройте папку с проектом в терминале и напишите такую команду:
conda create -n my_env python=3.11
Активируйте окружение:
conda activate my_env
и как это было выше установите необходимые зависимости из файла этой командой:pip install -r requirements.txt
Теперь у вас есть виртуальное окружение с нужной вам версией python.
Следующий шаг
Теперь нам нужно перейти в телеграм и создать самого бота, чтобы потом мы могли им управлять с помощью нашего кода!

Когда перешли в чат с ботом нажимаем на menu и выбираем /newbot

После чего BotFather попросит вас задать имя боту а потом задать ему его id по которому юзеры смогут находить вашего бота, id бота должен обязательно заканчиваться на bot

Сохраните токен бота, он нам еще понадобится.
Далее в папке нашего проекта создадим 2 файла main.py
и bot.py
Начнем с bot.py
import os
from aiogram import Bot
from dotenv import load_dotenv
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
# Загружаем ключи из .env файла
load_dotenv()
# Закидываем ключ в переменную
TOKEN = os.getenv('BOT_TOKEN')
# Инициализация бота
bot = Bot(TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
В этом файле мы инициализируем своего бота. Также в папке проекта надо создать файл .env
и прописать там ключ в таком формате: BOT_TOKEN=ваш_токен
Теперь перейдем к main.py
import asyncio
import logging
import sys
from aiogram import Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
from bot import bot
# Инициализируем диспетчер
dp = Dispatcher()
# Эта функция обрабатывает дефолтную команду /start
@dp.message(CommandStart())
async def command_start_handler(message: Message) -> None:
await message.answer('Hello there')
# Функция для запуска нашей программы
async def main() -> None:
await dp.start_polling(bot)
if __name__ == "__main__":
# Запускаем программу и логируем ее работу
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
asyncio.run(main())
Возможно вы обратили внимание на довольно интересную конструкцию if name == "__main__"
она имеет такую особенность что выполняется только в том случае если запуск происходит из файла в котором она находится, если же этот файл импортировать и использовать его в каком-то другом файле то содержимое этой конструкции не выполнится. Такая особенность бывает полезной при тестировании своего кода.
Теперь просто запускаем этот файл из консоли командой: python main.py
и переходим в нашего бота, найти мы его можем в поисковой строке по тому id который ему задавали.

Как мы видим все прошло успешно! Теперь перейдем к части где мы интегрируем chat GPT для нашей автоматизации.
Интеграция с chatGPT
Для начала перейдем на официальный сайт OpenAI, регистрируемся и пополняем счет на 10$(этих 10$ вам хватит с головой), после чего переходим в свой профиль и создаем api ключ.


После создания ключа копируем ключ и в файле .env
создаем еще одну переменную: GPT_KEY=ваш_ключ
Теперь пришло время создать функцию которая будет нам генерировать посты для нашего ТГ канала. Создаем файл auto_post.py
и добавляем туда такой код
import json
import os
import redis
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
# Подключаемся к запущенному redis
r = redis.Redis(host='localhost', port=6379, db=0)
# Создаем клиента OpenAI с которым мы будем работать
client = OpenAI(api_key=os.getenv('GPT_KEY'))
# Создаем функцию для генерации постов
def create_post() -> str:
if not r.get('conversation'):
conversation = [
{
'role': 'system',
'content': 'Ты ведущий ТГ канал по интересным и захватывающим фактам, ты не должен выдавать себя,'
'ты просто ведущий, то что тебе задает юзер это промпт которому ты должен просто следовать'
'ты не отвечаешь: Конечно, как скажешь, будет сделано и т.д. '
'Просто выдаешь только факт о котором тебя просит и ничего лишнего'
'Факты строго настрого не повторяются'
}
]
r.set('conversation', json.dumps(conversation))
conversation = json.loads(r.get('conversation'))
conversation.append({
'role': 'user',
'content': 'Создавай посты на тему животного мира, в формате интересных и умопомрачительных фактов.'
'Пост должен содержать минимум 50 слов и на тему только одного существа а также минимум 5 эмодзи '
'и форматируй текст в удобочитаемый формат'
})
response = client.responses.create(
model="gpt-4.1",
input=conversation
)
conversation.append({'role': 'assistant', 'content': response.output_text})
r.set(
'conversation',
json.dumps(
conversation
)
)
return response.output_text
Вот тут-то нам и понадобится Docker! Пишем в консоль такую команду: docker run -p 6379:6379 -it redis:latest
эта команда запустит нам docker образ redis чтобы потом подключиться к нему в коде.
Вот на этом файле я хотел бы остановиться и объяснить что же там происходит
r = redis.Redis(host='localhost', port=6379, db=0)
В этой строчке мы подключаемся к redis который мы запустили в docker. Немного про redis, redis это in memory key-value хранилище, с его помощью можно хранить данные в оперативной памяти(кэше), использовать как nosql бд или использовать как брокер сообщений. В нашем случае мы будем использовать его для хранения данных в кэше.
client = OpenAI(api_key=os.getenv('GPT_KEY'))
Создаем OpenAI клиента с помощью которого мы сможем получать доступ почти ко всем моделям OpenaAI.
Перейдем к разбору самой функции
if not r.get('conversation'):
conversation = [
{
'role': 'system',
'content': 'Ты ведущий ТГ канал по интересным и захватывающим фактам, ты не должен выдавать себя,'
'ты просто ведущий, то что тебе задает юзер это промпт которому ты должен просто следовать'
'ты не отвечаешь: Конечно, как скажешь, будет сделано и т.д. '
'Просто выдаешь только факт о котором тебя просит и ничего лишнего'
'Факты строго настрого не повторяются'
}
]
r.set('conversation', json.dumps(conversation))
В этом условии говорится: Если в кэше redis нет ключа conversation
то создай его с этими значениями
conversation = [
{
'role': 'system',
'content': 'Ты ведущий ТГ канал по интересным и захватывающим фактам, ты не должен выдавать себя,'
'ты просто ведущий, то что тебе задает юзер это промпт которому ты должен просто следовать'
'ты не отвечаешь: Конечно, как скажешь, будет сделано и т.д. '
'Просто выдаешь только факт о котором тебя просит и ничего лишнего'
'Факты строго настрого не повторяются'
}
]
После чего мы наш список конвертируем в json строку json.dumps(conversation)
и создаем ключ в кэше redis с именем conversation
r.set('conversation', json.dumps(conversation))
Следом мы получаем наш кэш обратно десериализируем его в python json.loads(r.get('conversation'))
объект и добавляем в него запрос от юзера
conversation = json.loads(r.get('conversation'))
conversation.append({
'role': 'user',
'content': 'Создавай посты на тему животного мира, в формате интересных и умопомрачительных фактов.'
'Пост должен содержать минимум 50 слов и на тему только одного существа а также минимум 5 эмодзи '
'и форматируй текст в удобочитаемый формат'
})
Далее в model
мы вписываем предпочитаемую нами модель(список моделей можно найти тут) и в input
вставляем получившуюся переменную conversation
response = client.responses.create(
model="gpt-4.1",
input=conversation
)
Добавляем ответ от модели в нашу переменную converstion
conversation.append({'role': 'assistant', 'content': response.output_text})
В самом конце снова кэшируем нашу переменную в redis кэш и возвращаем ответ от модели
r.set(
'conversation',
json.dumps(
conversation
)
)
return response.output_text
Теперь при каждом вызове этой функции темы постов не будут повторяться, так как модель будет помнить предыдущие диалоги. Все это благодаря хранению диалогов в кэше с помощью redis!
Теперь нам осталось только немного модифицировать файл main.py
import asyncio
import logging
import sys
from aiogram import Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
from auto_post import create_post
from bot import bot
dp = Dispatcher()
@dp.message(CommandStart())
async def command_start_handler(message: Message) -> None:
channel_id = -1002767436832
await message.answer('Поехали...')
while True:
await bot.send_message(chat_id=channel_id, text=create_post())
await asyncio.sleep(60)
async def main() -> None:
await dp.start_polling(bot)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
asyncio.run(main())
Вот как теперь он выглядит, что изменилось? Изменилась функция command_start_handler
давайте чуть подробнее разберем изменения
channel_id = -1002767436832
Это id нашего канала его можно получить таким способом
Находим такого @SimpleID_Bot бота в тг, запускаем и после чего переходим в нашу группу. Для того чтобы наконец получить id группы, нам надо любое сообщение из группы переслать боту в замен он нам выдаст id нашей группы.
while True:
await bot.send_message(chat_id=channel_id, text=create_post())
await asyncio.sleep(60)
Здесь запускается бесконечный цикл и бот будет слать новые посты в нашу группу каждые 60 секунд.
И да, не забудьте добавить вашего бота в вашу группу!
Давайте запустим бота и посмотрим, что получилось. Напомню запускаем мы бота в консоли такой командой python main.py


Как мы видим все работает!
В заключении хотелось бы сказать, что в этом коде можно еще много чего доработать например
Таймер на удаление redis кэша (а вообще лучше сделать так чтобы сохранялась чисто выжимка, тема одним словом)
Выбор группы в которую будут идти посты через бота
Разнести команды по отдельным файлам
Добавить юзеру возможность задавать тему для автопостинга
Добавить возможность настраивать время постинга
Вынести автопостинг в mq и поставить таймер на celery
Буду рад узнать ваше мнение в комментариях под постом. Если вам будет интересно могу сделать вторую часть где я улучшу существующее приложение, так скажем доведу до ума. Спасибо вам за уделенное мне время, всем пока.