407 lines
12 KiB
Markdown
407 lines
12 KiB
Markdown
# API Документация - TG Autoposter
|
||
|
||
## Обзор
|
||
|
||
Это документация по использованию репозиториев и основным компонентам бота для разработчиков.
|
||
|
||
## Репозитории
|
||
|
||
### GroupRepository
|
||
|
||
Работа с группами Telegram.
|
||
|
||
```python
|
||
from app.database import AsyncSessionLocal
|
||
from app.database.repository import GroupRepository
|
||
|
||
async with AsyncSessionLocal() as session:
|
||
repo = GroupRepository(session)
|
||
|
||
# Добавить группу
|
||
group = await repo.add_group(
|
||
chat_id="-1001234567890",
|
||
title="Название группы",
|
||
slow_mode_delay=5 # в секундах
|
||
)
|
||
|
||
# Получить по chat_id
|
||
group = await repo.get_group_by_chat_id("-1001234567890")
|
||
|
||
# Получить все активные
|
||
groups = await repo.get_all_active_groups()
|
||
|
||
# Обновить slow mode
|
||
await repo.update_group_slow_mode(group_id=1, delay=10)
|
||
|
||
# Обновить время последнего сообщения
|
||
await repo.update_last_message_time(group_id=1)
|
||
|
||
# Деактивировать
|
||
await repo.deactivate_group(group_id=1)
|
||
|
||
# Активировать
|
||
await repo.activate_group(group_id=1)
|
||
```
|
||
|
||
### MessageRepository
|
||
|
||
Работа с сообщениями.
|
||
|
||
```python
|
||
from app.database.repository import MessageRepository
|
||
|
||
async with AsyncSessionLocal() as session:
|
||
repo = MessageRepository(session)
|
||
|
||
# Создать сообщение
|
||
msg = await repo.add_message(
|
||
text="<b>Текст сообщения</b>",
|
||
title="Название",
|
||
parse_mode="HTML" # HTML или Markdown
|
||
)
|
||
|
||
# Получить по ID
|
||
msg = await repo.get_message(msg_id=1)
|
||
|
||
# Получить все сообщения
|
||
messages = await repo.get_all_messages(active_only=True)
|
||
|
||
# Обновить
|
||
await repo.update_message(
|
||
message_id=1,
|
||
text="Новый текст",
|
||
title="Новое название"
|
||
)
|
||
|
||
# Деактивировать
|
||
await repo.deactivate_message(message_id=1)
|
||
|
||
# Удалить
|
||
await repo.delete_message(message_id=1)
|
||
```
|
||
|
||
### MessageGroupRepository
|
||
|
||
Связь между сообщениями и группами.
|
||
|
||
```python
|
||
from app.database.repository import MessageGroupRepository
|
||
|
||
async with AsyncSessionLocal() as session:
|
||
repo = MessageGroupRepository(session)
|
||
|
||
# Добавить сообщение в группу
|
||
link = await repo.add_message_to_group(
|
||
message_id=1,
|
||
group_id=1
|
||
)
|
||
|
||
# Получить неотправленные сообщения для отправки
|
||
msg_groups = await repo.get_message_groups_to_send(message_id=1)
|
||
|
||
# Получить неотправленные сообщения для группы
|
||
msg_groups = await repo.get_unsent_messages_for_group(group_id=1)
|
||
|
||
# Отметить как отправленное
|
||
await repo.mark_as_sent(message_group_id=1)
|
||
|
||
# Отметить как ошибка
|
||
await repo.mark_as_sent(
|
||
message_group_id=1,
|
||
error="Бот не имеет прав в группе"
|
||
)
|
||
|
||
# Получить все сообщения для группы
|
||
msg_groups = await repo.get_messages_for_group(group_id=1)
|
||
|
||
# Удалить сообщение из группы
|
||
await repo.remove_message_from_group(
|
||
message_id=1,
|
||
group_id=1
|
||
)
|
||
```
|
||
|
||
## Модели
|
||
|
||
### Group
|
||
|
||
```python
|
||
from app.models import Group
|
||
|
||
# Поля
|
||
group.id # int (первичный ключ)
|
||
group.chat_id # str (уникальный ID группы в Telegram)
|
||
group.title # str (название группы)
|
||
group.slow_mode_delay # int (задержка между сообщениями в сек)
|
||
group.last_message_time # datetime (время последнего отправленного)
|
||
group.is_active # bool (активна ли группа)
|
||
group.created_at # datetime
|
||
group.updated_at # datetime
|
||
|
||
# Связи
|
||
group.messages # List[MessageGroup] (сообщения в этой группе)
|
||
```
|
||
|
||
### Message
|
||
|
||
```python
|
||
from app.models import Message
|
||
|
||
# Поля
|
||
msg.id # int (первичный ключ)
|
||
msg.text # str (текст сообщения)
|
||
msg.title # str (название)
|
||
msg.is_active # bool (активно ли)
|
||
msg.parse_mode # str (HTML, Markdown, None)
|
||
msg.created_at # datetime
|
||
msg.updated_at # datetime
|
||
|
||
# Связи
|
||
msg.groups # List[MessageGroup] (группы для отправки)
|
||
```
|
||
|
||
### MessageGroup
|
||
|
||
```python
|
||
from app.models import MessageGroup
|
||
|
||
# Поля
|
||
mg.id # int (первичный ключ)
|
||
mg.message_id # int (FK на Message)
|
||
mg.group_id # int (FK на Group)
|
||
mg.is_sent # bool (отправлено ли)
|
||
mg.sent_at # datetime (когда отправлено)
|
||
mg.error # str (описание ошибки если была)
|
||
mg.created_at # datetime
|
||
|
||
# Связи
|
||
mg.message # Message (само сообщение)
|
||
mg.group # Group (сама группа)
|
||
```
|
||
|
||
## Обработчики (Handlers)
|
||
|
||
### Команды
|
||
|
||
- **start** - Главное меню
|
||
- **help_command** - Справка
|
||
|
||
### Callback обработчики
|
||
|
||
#### Главное меню
|
||
- `main_menu` - Вернуться в главное меню
|
||
|
||
#### Управление сообщениями
|
||
- `manage_messages` - Меню управления сообщениями
|
||
- `create_message` - Начало создания сообщения
|
||
- `list_messages` - Список всех сообщений
|
||
- `send_msg_<id>` - Отправить сообщение в группы
|
||
- `delete_msg_<id>` - Удалить сообщение
|
||
|
||
#### Управление группами
|
||
- `manage_groups` - Меню управления группами
|
||
- `list_groups` - Список всех групп
|
||
- `group_messages_<id>` - Сообщения для группы
|
||
- `delete_group_<id>` - Удалить группу
|
||
|
||
#### Выбор групп при создании сообщения
|
||
- `select_group_<id>` - Выбрать/отменить выбор группы
|
||
- `done_groups` - Завершить выбор групп
|
||
|
||
## Утилиты
|
||
|
||
### Проверка slow mode
|
||
|
||
```python
|
||
from app.utils import can_send_message
|
||
|
||
# Проверить можно ли отправлять
|
||
can_send, wait_time = await can_send_message(group)
|
||
|
||
if can_send:
|
||
# Отправляем сейчас
|
||
pass
|
||
else:
|
||
# Ждем wait_time секунд
|
||
pass
|
||
```
|
||
|
||
### Клавиатуры
|
||
|
||
```python
|
||
from app.utils.keyboards import (
|
||
get_main_keyboard,
|
||
get_messages_keyboard,
|
||
get_groups_keyboard,
|
||
get_back_keyboard,
|
||
get_message_actions_keyboard,
|
||
get_group_actions_keyboard,
|
||
get_yes_no_keyboard,
|
||
)
|
||
|
||
# Главное меню
|
||
keyboard = get_main_keyboard()
|
||
|
||
# Меню сообщений
|
||
keyboard = get_messages_keyboard()
|
||
|
||
# Меню групп
|
||
keyboard = get_groups_keyboard()
|
||
|
||
# Кнопка назад
|
||
keyboard = get_back_keyboard()
|
||
|
||
# Действия с сообщением
|
||
keyboard = get_message_actions_keyboard(message_id=1)
|
||
|
||
# Действия с группой
|
||
keyboard = get_group_actions_keyboard(group_id=1)
|
||
|
||
# Подтверждение
|
||
keyboard = get_yes_no_keyboard(action="delete_message_1")
|
||
```
|
||
|
||
## Примеры использования
|
||
|
||
### Пример 1: Создание сообщения и отправка в группу
|
||
|
||
```python
|
||
import asyncio
|
||
from app.database import AsyncSessionLocal, init_db
|
||
from app.database.repository import (
|
||
GroupRepository, MessageRepository, MessageGroupRepository
|
||
)
|
||
|
||
async def main():
|
||
await init_db()
|
||
|
||
async with AsyncSessionLocal() as session:
|
||
# Создаем сообщение
|
||
msg_repo = MessageRepository(session)
|
||
msg = await msg_repo.add_message(
|
||
text="Привет, это тестовое сообщение!",
|
||
title="Тест"
|
||
)
|
||
|
||
# Получаем группу
|
||
group_repo = GroupRepository(session)
|
||
groups = await group_repo.get_all_active_groups()
|
||
|
||
if groups:
|
||
# Добавляем сообщение в группу
|
||
mg_repo = MessageGroupRepository(session)
|
||
await mg_repo.add_message_to_group(msg.id, groups[0].id)
|
||
|
||
print(f"✅ Сообщение готово к отправке в {groups[0].title}")
|
||
|
||
asyncio.run(main())
|
||
```
|
||
|
||
### Пример 2: Отправка сообщения с учетом slow mode
|
||
|
||
```python
|
||
from app.utils import can_send_message
|
||
from telegram import Bot
|
||
|
||
async def send_to_group(bot: Bot, message, group):
|
||
# Проверяем slow mode
|
||
can_send, wait_time = await can_send_message(group)
|
||
|
||
if not can_send:
|
||
print(f"⏳ Ожидаем {wait_time} секунд...")
|
||
await asyncio.sleep(wait_time)
|
||
|
||
# Отправляем
|
||
await bot.send_message(
|
||
chat_id=group.chat_id,
|
||
text=message.text,
|
||
parse_mode=message.parse_mode
|
||
)
|
||
|
||
print(f"✅ Отправлено в {group.title}")
|
||
```
|
||
|
||
### Пример 3: Получение статистики
|
||
|
||
```python
|
||
async def get_statistics():
|
||
async with AsyncSessionLocal() as session:
|
||
msg_repo = MessageRepository(session)
|
||
group_repo = GroupRepository(session)
|
||
mg_repo = MessageGroupRepository(session)
|
||
|
||
messages = await msg_repo.get_all_messages()
|
||
groups = await group_repo.get_all_active_groups()
|
||
|
||
print(f"📊 Статистика:")
|
||
print(f" Сообщений: {len(messages)}")
|
||
print(f" Групп: {len(groups)}")
|
||
|
||
# Сообщения по отправкам
|
||
for msg in messages:
|
||
msg_groups = await mg_repo.get_messages_for_group(msg.id)
|
||
sent = sum(1 for mg in msg_groups if mg.is_sent)
|
||
print(f" {msg.title}: {sent}/{len(msg_groups)} групп")
|
||
```
|
||
|
||
## Логирование
|
||
|
||
```python
|
||
import logging
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
logger.debug("Отладочное сообщение")
|
||
logger.info("Информационное сообщение")
|
||
logger.warning("Предупреждение")
|
||
logger.error("Ошибка")
|
||
logger.critical("Критическая ошибка")
|
||
```
|
||
|
||
Логи сохраняются в папку `logs/` с ротацией по дням.
|
||
|
||
## Обработка ошибок
|
||
|
||
```python
|
||
try:
|
||
await bot.send_message(
|
||
chat_id=group.chat_id,
|
||
text=message.text,
|
||
parse_mode=message.parse_mode
|
||
)
|
||
except TelegramError as e:
|
||
logger.error(f"Ошибка Telegram: {e}")
|
||
# Сохраняем ошибку в БД
|
||
await mg_repo.mark_as_sent(mg.id, error=str(e))
|
||
except Exception as e:
|
||
logger.error(f"Неожиданная ошибка: {e}")
|
||
```
|
||
|
||
## Асинхронность
|
||
|
||
Весь код использует async/await. При работе с БД и ботом всегда используйте:
|
||
|
||
```python
|
||
async def my_function():
|
||
async with AsyncSessionLocal() as session:
|
||
# Работа с БД
|
||
pass
|
||
```
|
||
|
||
## Типизация
|
||
|
||
Проект использует type hints для улучшения качества кода:
|
||
|
||
```python
|
||
from typing import List, Optional
|
||
from app.models import Group, Message
|
||
|
||
async def get_active_groups() -> List[Group]:
|
||
"""Получить все активные группы"""
|
||
pass
|
||
|
||
async def find_group(chat_id: str) -> Optional[Group]:
|
||
"""Найти группу по chat_id"""
|
||
pass
|
||
```
|