Some checks reported errors
continuous-integration/drone/push Build encountered an error
Реализована полнофункциональная система чата с двумя режимами работы: ## Режимы работы: - Broadcast: рассылка сообщений всем пользователям - Forward: пересылка сообщений в указанную группу/канал ## Функционал: - Поддержка всех типов сообщений: text, photo, video, document, animation, sticker, voice - Система банов: личные баны пользователей и глобальный бан чата - Модерация: удаление сообщений с отслеживанием в БД - История сообщений с сохранением ID пересланных сообщений ## Структура БД (миграция 005): - chat_settings: настройки чата (режим, ID канала, глобальный бан) - banned_users: история банов с причинами и информацией о модераторе - chat_messages: история сообщений с типами, файлами и картой доставки (JSONB) ## Сервисы: - ChatSettingsService: управление настройками чата - BanService: управление банами пользователей - ChatMessageService: работа с историей сообщений - ChatPermissionService: проверка прав на отправку сообщений ## Обработчики: - chat_handlers.py: обработка сообщений пользователей (7 типов контента) - admin_chat_handlers.py: админские команды управления чатом ## Админские команды: - /chat_mode - переключение режима (broadcast/forward) - /set_forward <chat_id> - установка ID канала для пересылки - /ban <user_id> [причина] - бан пользователя - /unban <user_id> - разбан пользователя - /banlist - список забаненных - /global_ban - включение/выключение глобального бана - /delete_msg - удаление сообщения (ответ на сообщение) - /chat_stats - статистика чата ## Документация: - docs/CHAT_SYSTEM.md: полное описание системы с примерами использования Изменено файлов: 7 (2 modified, 5 new) - main.py: подключены chat_router и admin_chat_router - src/core/models.py: добавлены модели ChatSettings, BannedUser, ChatMessage - migrations/versions/005_add_chat_system.py: миграция создания таблиц - src/core/chat_services.py: сервисный слой для чата (267 строк) - src/handlers/chat_handlers.py: обработчики сообщений (447 строк) - src/handlers/admin_chat_handlers.py: админские команды (369 строк) - docs/CHAT_SYSTEM.md: документация (390 строк)
356 lines
15 KiB
Markdown
356 lines
15 KiB
Markdown
# Система чата пользователей
|
||
|
||
## Описание
|
||
|
||
Система чата позволяет пользователям общаться между собой через бота с двумя режимами работы:
|
||
- **Broadcast (Рассылка)** - сообщения пользователей рассылаются всем остальным пользователям
|
||
- **Forward (Пересылка)** - сообщения пользователей пересылаются в указанную группу/канал
|
||
|
||
## Режимы работы
|
||
|
||
### Режим Broadcast (Рассылка всем)
|
||
|
||
В этом режиме сообщения от одного пользователя автоматически рассылаются всем остальным активным пользователям бота.
|
||
|
||
**Особенности:**
|
||
- Отправитель не получает копию своего сообщения
|
||
- Сообщение доставляется только активным пользователям (is_active=True)
|
||
- В базу сохраняется статистика доставки (кому доставлено, кому нет)
|
||
- ID отправленных сообщений сохраняются в `forwarded_message_ids` (JSONB)
|
||
|
||
**Пример работы:**
|
||
1. Пользователь А отправляет фото с текстом "Привет всем!"
|
||
2. Бот копирует это сообщение пользователям B, C, D...
|
||
3. В базу сохраняется: `{telegram_id_B: msg_id_1, telegram_id_C: msg_id_2, ...}`
|
||
4. Пользователю А показывается статистика: "✅ Сообщение разослано! 📤 Доставлено: 15, ❌ Не доставлено: 2"
|
||
|
||
### Режим Forward (Пересылка в канал)
|
||
|
||
В этом режиме сообщения от пользователей пересылаются в указанную группу или канал.
|
||
|
||
**Особенности:**
|
||
- Бот должен быть администратором канала/группы с правом публикации
|
||
- Сохраняется оригинальное авторство сообщения (пересылка, а не копия)
|
||
- ID канала хранится в `chat_settings.forward_chat_id`
|
||
- В базу сохраняется ID сообщения в канале
|
||
|
||
**Пример работы:**
|
||
1. Пользователь отправляет видео
|
||
2. Бот пересылает это видео в канал (сохраняя имя отправителя)
|
||
3. В базу сохраняется: `{channel: message_id_in_channel}`
|
||
4. Пользователю показывается: "✅ Сообщение переслано в канал"
|
||
|
||
## Поддерживаемые типы сообщений
|
||
|
||
Система поддерживает все основные типы контента:
|
||
|
||
| Тип | Поле `message_type` | Поле `file_id` | Описание |
|
||
|-----|---------------------|----------------|----------|
|
||
| Текст | `text` | NULL | Обычное текстовое сообщение |
|
||
| Фото | `photo` | file_id | Изображение (сохраняется самое большое) |
|
||
| Видео | `video` | file_id | Видео файл |
|
||
| Документ | `document` | file_id | Файл любого типа |
|
||
| GIF | `animation` | file_id | Анимированное изображение |
|
||
| Стикер | `sticker` | file_id | Стикер из набора |
|
||
| Голосовое | `voice` | file_id | Голосовое сообщение |
|
||
|
||
**Примечание:** Для всех типов кроме `text` и `sticker` может быть указан `caption` (подпись), который сохраняется в поле `text`.
|
||
|
||
## Система банов
|
||
|
||
### Личный бан пользователя
|
||
|
||
Администратор может забанить конкретного пользователя:
|
||
|
||
```
|
||
/ban 123456789 Спам в чате
|
||
/ban (ответ на сообщение) Нарушение правил
|
||
```
|
||
|
||
**Эффекты:**
|
||
- Пользователь не может отправлять сообщения
|
||
- При попытке отправки получает: "❌ Вы заблокированы и не можете отправлять сообщения"
|
||
- Запись добавляется в таблицу `banned_users` с `is_active=true`
|
||
|
||
**Разблокировка:**
|
||
```
|
||
/unban 123456789
|
||
/unban (ответ на сообщение)
|
||
```
|
||
|
||
### Глобальный бан чата
|
||
|
||
Администратор может временно закрыть весь чат:
|
||
|
||
```
|
||
/global_ban
|
||
```
|
||
|
||
**Эффекты:**
|
||
- Все пользователи (кроме админов) не могут писать
|
||
- При попытке отправки: "❌ Чат временно закрыт администратором"
|
||
- Флаг `chat_settings.global_ban` устанавливается в `true`
|
||
|
||
**Открытие чата:**
|
||
```
|
||
/global_ban (повторно - переключение)
|
||
```
|
||
|
||
## Модерация сообщений
|
||
|
||
### Удаление сообщений
|
||
|
||
Администратор может удалить сообщение из всех чатов:
|
||
|
||
```
|
||
/delete_msg (ответ на сообщение)
|
||
```
|
||
|
||
**Процесс:**
|
||
1. Сообщение помечается как удаленное в БД (`is_deleted=true`)
|
||
2. Сохраняется кто удалил (`deleted_by`) и когда (`deleted_at`)
|
||
3. Бот пытается удалить сообщение у всех пользователей, используя `forwarded_message_ids`
|
||
4. Показывается статистика: "✅ Удалено у 12 пользователей"
|
||
|
||
**Важно:** Удаление возможно только если сообщение было сохранено в БД и есть `forwarded_message_ids`.
|
||
|
||
## Админские команды
|
||
|
||
### /chat_mode
|
||
Переключение режима работы чата.
|
||
|
||
**Интерфейс:** Inline-клавиатура с выбором режима.
|
||
|
||
**Пример использования:**
|
||
```
|
||
/chat_mode
|
||
→ Показывается меню выбора режима
|
||
→ Нажимаем "📢 Рассылка всем"
|
||
→ Режим изменен
|
||
```
|
||
|
||
### /set_forward <chat_id>
|
||
Установить ID канала/группы для пересылки.
|
||
|
||
**Как узнать chat_id:**
|
||
1. Добавьте бота в канал/группу
|
||
2. Напишите любое сообщение в канале
|
||
3. Перешлите его боту @userinfobot
|
||
4. Он покажет chat_id (например: -1001234567890)
|
||
|
||
**Пример:**
|
||
```
|
||
/set_forward -1001234567890
|
||
→ ID канала для пересылки установлен!
|
||
```
|
||
|
||
### /ban <user_id> [причина]
|
||
Забанить пользователя.
|
||
|
||
**Способы использования:**
|
||
1. Ответить на сообщение: `/ban Спам`
|
||
2. Указать ID: `/ban 123456789 Нарушение правил`
|
||
|
||
### /unban <user_id>
|
||
Разбанить пользователя.
|
||
|
||
**Способы использования:**
|
||
1. Ответить на сообщение: `/unban`
|
||
2. Указать ID: `/unban 123456789`
|
||
|
||
### /banlist
|
||
Показать список всех забаненных пользователей.
|
||
|
||
**Формат вывода:**
|
||
```
|
||
🚫 Забаненные пользователи
|
||
|
||
👤 Иван Иванов (123456789)
|
||
🔨 Забанил: Админ
|
||
📝 Причина: Спам
|
||
📅 Дата: 15.01.2025 14:30
|
||
|
||
👤 Петр Петров (987654321)
|
||
🔨 Забанил: Админ
|
||
📅 Дата: 14.01.2025 12:00
|
||
```
|
||
|
||
### /global_ban
|
||
Включить/выключить глобальный бан чата (переключатель).
|
||
|
||
**Статусы:**
|
||
- 🔇 Включен - только админы могут писать
|
||
- 🔊 Выключен - все могут писать
|
||
|
||
### /delete_msg
|
||
Удалить сообщение (ответ на сообщение).
|
||
|
||
**Требует:** Ответить на сообщение, которое нужно удалить.
|
||
|
||
### /chat_stats
|
||
Показать статистику чата.
|
||
|
||
**Информация:**
|
||
- Текущий режим работы
|
||
- Статус глобального бана
|
||
- Количество забаненных пользователей
|
||
- Количество сообщений за последнее время
|
||
- ID канала (если установлен)
|
||
|
||
## База данных
|
||
|
||
### Таблица chat_settings
|
||
|
||
Одна строка с глобальными настройками чата:
|
||
|
||
```sql
|
||
id = 1 (всегда)
|
||
mode = 'broadcast' | 'forward'
|
||
forward_chat_id = '-1001234567890' (для режима forward)
|
||
global_ban = true | false
|
||
```
|
||
|
||
### Таблица banned_users
|
||
|
||
История банов пользователей:
|
||
|
||
```sql
|
||
id - уникальный ID бана
|
||
user_id - FK на users.id
|
||
telegram_id - Telegram ID пользователя
|
||
banned_by - FK на users.id (кто забанил)
|
||
reason - текстовая причина (nullable)
|
||
banned_at - timestamp бана
|
||
is_active - true/false (активен ли бан)
|
||
```
|
||
|
||
**Примечание:** При разбане `is_active` меняется на `false`, но запись не удаляется (история).
|
||
|
||
### Таблица chat_messages
|
||
|
||
История всех отправленных сообщений:
|
||
|
||
```sql
|
||
id - уникальный ID сообщения
|
||
user_id - FK на users.id (отправитель)
|
||
telegram_message_id - ID сообщения в Telegram
|
||
message_type - text/photo/video/document/animation/sticker/voice
|
||
text - текст или caption (nullable)
|
||
file_id - file_id медиа (nullable)
|
||
forwarded_message_ids - JSONB с картой доставки
|
||
is_deleted - помечено ли как удаленное
|
||
deleted_by - FK на users.id (кто удалил, nullable)
|
||
deleted_at - timestamp удаления (nullable)
|
||
created_at - timestamp отправки
|
||
```
|
||
|
||
**Формат forwarded_message_ids:**
|
||
```json
|
||
// Режим broadcast:
|
||
{
|
||
"123456789": 12345, // telegram_id: message_id
|
||
"987654321": 12346,
|
||
"555555555": 12347
|
||
}
|
||
|
||
// Режим forward:
|
||
{
|
||
"channel": 54321 // ключ "channel", значение - ID сообщения в канале
|
||
}
|
||
```
|
||
|
||
## Примеры использования
|
||
|
||
### Настройка режима broadcast
|
||
|
||
1. Админ: `/chat_mode` → выбирает "📢 Рассылка всем"
|
||
2. Пользователь А пишет: "Привет всем!"
|
||
3. Пользователи B, C, D получают это сообщение
|
||
4. Пользователь А видит: "✅ Сообщение разослано! 📤 Доставлено: 3"
|
||
|
||
### Настройка режима forward
|
||
|
||
1. Админ создает канал и добавляет бота как админа
|
||
2. Админ узнает chat_id канала (например: -1001234567890)
|
||
3. Админ: `/set_forward -1001234567890`
|
||
4. Админ: `/chat_mode` → выбирает "➡️ Пересылка в канал"
|
||
5. Пользователь пишет сообщение → оно появляется в канале
|
||
|
||
### Бан пользователя за спам
|
||
|
||
1. Пользователь отправляет спам
|
||
2. Админ отвечает на его сообщение: `/ban Спам в чате`
|
||
3. Пользователь забанен, попытки отправить сообщение блокируются
|
||
4. Админ: `/banlist` - видит список банов
|
||
5. Админ: `/unban` (ответ на сообщение) - разбан
|
||
|
||
### Временное закрытие чата
|
||
|
||
1. Админ: `/global_ban`
|
||
2. Все пользователи видят: "❌ Чат временно закрыт администратором"
|
||
3. Только админы могут писать
|
||
4. Админ: `/global_ban` (повторно) - чат открыт
|
||
|
||
### Удаление неприемлемого контента
|
||
|
||
1. Пользователь отправил неприемлемое фото
|
||
2. Фото разослано всем (режим broadcast)
|
||
3. Админ отвечает на это сообщение: `/delete_msg`
|
||
4. Бот удаляет фото у всех пользователей, кому оно было отправлено
|
||
5. В БД сообщение помечается как удаленное
|
||
|
||
## Технические детали
|
||
|
||
### Порядок подключения роутеров
|
||
|
||
```python
|
||
dp.include_router(registration_router) # Первым
|
||
dp.include_router(admin_account_router)
|
||
dp.include_router(admin_chat_router) # До chat_router!
|
||
dp.include_router(redraw_router)
|
||
dp.include_router(account_router)
|
||
dp.include_router(chat_router) # ПОСЛЕДНИМ (ловит все сообщения)
|
||
dp.include_router(router)
|
||
dp.include_router(admin_router)
|
||
```
|
||
|
||
**Важно:** `chat_router` должен быть последним, так как он ловит ВСЕ типы сообщений (text, photo, video и т.д.). Если поставить его раньше, он будет перехватывать команды и сообщения, предназначенные для других обработчиков.
|
||
|
||
### Проверка прав
|
||
|
||
```python
|
||
can_send, reason = await ChatPermissionService.can_send_message(
|
||
session,
|
||
telegram_id=user.telegram_id,
|
||
is_admin=is_admin(user.telegram_id)
|
||
)
|
||
```
|
||
|
||
**Логика проверки:**
|
||
1. Если пользователь админ → всегда `can_send=True`
|
||
2. Если включен global_ban → `can_send=False`
|
||
3. Если пользователь забанен → `can_send=False`
|
||
4. Иначе → `can_send=True`
|
||
|
||
### Миграция 005
|
||
|
||
При запуске миграции создаются 3 таблицы и вставляется начальная запись:
|
||
|
||
```sql
|
||
INSERT INTO chat_settings (id, mode, global_ban)
|
||
VALUES (1, 'broadcast', false);
|
||
```
|
||
|
||
Эта запись будет использоваться всегда (единственная строка в таблице).
|
||
|
||
## Возможные улучшения
|
||
|
||
1. **Фильтрация контента** - автоматическая проверка на мат, спам, ссылки
|
||
2. **Лимиты** - ограничение количества сообщений в минуту/час
|
||
3. **Ответы на сообщения** - возможность отвечать на конкретное сообщение пользователя
|
||
4. **Редактирование** - изменение отправленных сообщений
|
||
5. **Реакции** - лайки/дизлайки на сообщения
|
||
6. **Каналы** - разделение чата на темы/каналы
|
||
7. **История** - просмотр истории сообщений через команду
|
||
8. **Поиск** - поиск по истории сообщений
|