У меня есть небольшой пет-проект по созданию нейропсихолога - канала в Телеграмм, публикующего посты по психологии семейных взаимоотношений и саморазвитию человека. Особенностью этого канала является то, что посты для этого канала, как и план выхода постов, составляет нейронная сеть самостоятельно, без вмешательства человека - мною был задан только вектор постов, а дальше уже дело техники. На первом этапе был сформирован CSV-файл с постами до конца лета 2025-го года. В дальнейшем буду по мере возможности развивать функционал так, чтобы посты создавались без прослойки из CSV, а сразу, в одном месте, через API нейросети, добавлю еще какой-то полезный функционал...
Данный пост показывает простейший пример бота, который заполняет базу из CSV-файла и публикует их по расписанию.
Введение
В этой статье я расскажу, как мы создали систему для автоматической публикации постов в Telegram-канал по расписанию. Решение включает:
- Docker-контейнер с PostgreSQL базой данных
- Python-бота для отправки сообщений
- Систему загрузки контента из CSV-файлов
- Поддержку Markdown-разметки в сообщениях
1. Архитектура решения
Наша система состоит из трех основных компонентов:
1.1 База данных (PostgreSQL)
Хранит все посты с их расписанием и статусом отправки.
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
post_date TIMESTAMP WITH TIME ZONE NOT NULL,
message TEXT NOT NULL,
is_sent BOOLEAN DEFAULT FALSE,
sent_at TIMESTAMP WITH TIME ZONE
);
1.2 Telegram-бот
Проверяет базу данных каждые 10 минут и отправляет посты, время публикации которых наступило.
1.3 Админка (Adminer)
Веб-интерфейс для просмотра и управления базой данных.
2. Настройка окружения
2.1 Установка Docker
Для работы системы требуется Docker и Docker Compose.
# Для Ubuntu/Debian
sudo apt update
sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker
2.2 Структура проекта
Создайте следующую структуру файлов:
telegram-post-bot/ ├── docker-compose.yml ├── Dockerfile ├── .env ├── init.sql ├── requirements.txt ├── app/ │ ├── __init__.py │ ├── main.py │ ├── config.py │ ├── database.py │ └── async_utils.py └── data/ └── posts.csv
3. Конфигурационные файлы
3.1 docker-compose.yml
version: '3.8'
services:
db:
image: postgres:16
env_file: .env
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
adminer:
image: adminer:latest
ports:
- "8080:8080"
depends_on:
db:
condition: service_healthy
bot:
build: .
env_file: .env
depends_on:
db:
condition: service_healthy
restart: unless-stopped
volumes:
postgres_data:
3.2 Dockerfile
FROM python:3.11
WORKDIR /app
RUN apt-get update && apt-get install -y tzdata && \
ln -sf /usr/share/zoneinfo/Europe/Moscow /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "-m", "app.main"]
3.3 requirements.txt
python-telegram-bot==20.3
psycopg2-binary==2.9.9
python-dotenv==1.0.0
pandas==2.0.3
python-dateutil==2.8.2
4. Основной код бота
4.1 Отправка сообщений (async_utils.py)
import asyncio
import re
from telegram import Bot
from telegram.constants import ParseMode
import logging
logger = logging.getLogger(__name__)
def escape_markdown(text):
escape_chars = r'\_*[]()~`>#+-=|{}.!'
return re.sub(f'([{re.escape(escape_chars)}])', r'\\\1', text)
async def async_send_message(bot_token, chat_id, text):
bot = Bot(token=bot_token)
try:
await bot.send_message(
chat_id=chat_id,
text=escape_markdown(text),
parse_mode=ParseMode.MARKDOWN_V2,
disable_web_page_preview=True
)
return True
except Exception as e:
logger.error(f"Telegram API error: {str(e)}")
return False
def sync_send_message(bot_token, chat_id, text):
return asyncio.run(async_send_message(bot_token, chat_id, text))
или вариант кода для отправки в формате "html":
async def async_send_message(bot_token, chat_id, text):
bot = Bot(token=bot_token)
try:
# Преобразование Markdown-подобной разметки в HTML
html_text = text
html_text = re.sub(r'\*(.*?)\*', r'\1', html_text) # *жирный* → жирный
html_text = re.sub(r'_(.*?)_', r'\1', html_text) # _курсив_ → курсив
html_text = html_text.replace('\n', '
') # Переносы строк
await bot.send_message(
chat_id=chat_id,
text=html_text,
parse_mode="HTML",
disable_web_page_preview=True
)
return True
except Exception as e:
logger.error(f"Telegram API error: {str(e)}")
return False
4.2 Работа с базой данных (database.py)
import psycopg2
from config import config
def get_connection():
return psycopg2.connect(config.DATABASE_URL)
def get_unsent_post():
with get_connection() as conn:
with conn.cursor() as cursor:
cursor.execute("""
SELECT id, message FROM posts
WHERE is_sent = FALSE AND post_date <= NOW()
ORDER BY post_date ASC
LIMIT 1
""")
return cursor.fetchone()
def mark_post_as_sent(post_id):
with get_connection() as conn:
with conn.cursor() as cursor:
cursor.execute("""
UPDATE posts
SET is_sent = TRUE, sent_at = NOW()
WHERE id = %s
""", (post_id,))
conn.commit()
5. Запуск системы
5.1 Сборка и запуск
# Сборка образов
docker compose build
# Запуск сервисов
docker compose up -d
# Просмотр логов бота
docker compose logs -f bot
5.2 Импорт постов из CSV
Пример CSV-файла (data/posts.csv):
date,message
"2025-06-24 09:00:00","*Почему мы чувствуем одиночество среди людей?*
Социальные связи поверхностны? Попробуйте:
✓ Искренне интересоваться
✓ Найти 1-2 «своих» человека
✓ Не бояться быть уязвимым
_Как вы справляетесь с одиночеством?_"
Команда для импорта:
docker compose exec bot python -m app.main --import-csv /app/data/posts.csv
6. Особенности работы
Форматирование сообщений
Бот поддерживает MarkdownV2 разметку:
*жирный текст*
- жирное начертание_курсив_
- курсивное начертание`моноширинный`
- моноширинный шрифт[текст](URL)
- ссылки
Важные моменты
- Бот должен быть администратором канала
- Для приватных каналов используйте chat_id вместо @username
- Специальные символы в Markdown должны быть экранированы
Результаты
После настройки вы получите:
- Автоматическую публикацию постов по расписанию
- Поддержку форматированного текста
- Веб-интерфейс для управления базой данных
- Масштабируемое решение в Docker-контейнерах
7. Возможные улучшения
- Добавление веб-интерфейса для управления постами
- Интеграция с Google Sheets для редактирования расписания
- Отправка уведомлений об ошибках в Telegram
- Поддержка медиа-вложений (фото, видео)
P.S. Имейте ввиду, что данная задача не оптимизирована по процессам и может быть подкорректирована. Это пример полезного функционала, общее направление действий.
Разработка сайта
Подайте заявку на разработку сайта на базе готового решения от компании 1С-Битрикс или одного из партнеров компании. Максимально подробно опишите, чему будет посвящен сайт, если это интернет-магазин - что он будет продавать, нужна ли мультиязычность, будут ли разные типы цен (розница, опт, крупный опт), будет ли интеграция с 1С, будет ли выгрузка товаров на различные торговые площадки...
Сопровождение сайта
Вы можете подать заявку на сопровождение вашего сайта на базе 1С-Битрикс. Сопровождение включает в себя: проверка актуальности обновлений сайта, проверка актуальности резервной копии, консультации по сайту. Опишите в заявке, какие еще объемы планируются на сопровождении и на какой срок вы планируете заключить договор на сопровождение - мы подберем подходящий вам бюджет на сопровождение
Работы по сайту
Вы можете подать заявку на выполнение определенного объема работ по сайту. Опишите в заявке объем работ. Это может быть разработка какого-то нового функционала, доработки по имеющемуся функционалу, доработки под требования сео-специалистов. На основании заявки вам будет сформирован бюджет работ, а также названы сроки на выполнение тех или иных работ.