init commit
This commit is contained in:
406
docs/API.md
Normal file
406
docs/API.md
Normal file
@@ -0,0 +1,406 @@
|
||||
# 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
|
||||
```
|
||||
Reference in New Issue
Block a user