Реализована полнофункциональная система чата с двумя режимами работы: ## Режимы работы: - 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 строк)
15 KiB
Система чата пользователей
Описание
Система чата позволяет пользователям общаться между собой через бота с двумя режимами работы:
- Broadcast (Рассылка) - сообщения пользователей рассылаются всем остальным пользователям
- Forward (Пересылка) - сообщения пользователей пересылаются в указанную группу/канал
Режимы работы
Режим Broadcast (Рассылка всем)
В этом режиме сообщения от одного пользователя автоматически рассылаются всем остальным активным пользователям бота.
Особенности:
- Отправитель не получает копию своего сообщения
- Сообщение доставляется только активным пользователям (is_active=True)
- В базу сохраняется статистика доставки (кому доставлено, кому нет)
- ID отправленных сообщений сохраняются в
forwarded_message_ids(JSONB)
Пример работы:
- Пользователь А отправляет фото с текстом "Привет всем!"
- Бот копирует это сообщение пользователям B, C, D...
- В базу сохраняется:
{telegram_id_B: msg_id_1, telegram_id_C: msg_id_2, ...} - Пользователю А показывается статистика: "✅ Сообщение разослано! 📤 Доставлено: 15, ❌ Не доставлено: 2"
Режим Forward (Пересылка в канал)
В этом режиме сообщения от пользователей пересылаются в указанную группу или канал.
Особенности:
- Бот должен быть администратором канала/группы с правом публикации
- Сохраняется оригинальное авторство сообщения (пересылка, а не копия)
- ID канала хранится в
chat_settings.forward_chat_id - В базу сохраняется ID сообщения в канале
Пример работы:
- Пользователь отправляет видео
- Бот пересылает это видео в канал (сохраняя имя отправителя)
- В базу сохраняется:
{channel: message_id_in_channel} - Пользователю показывается: "✅ Сообщение переслано в канал"
Поддерживаемые типы сообщений
Система поддерживает все основные типы контента:
| Тип | Поле 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 (ответ на сообщение)
Процесс:
- Сообщение помечается как удаленное в БД (
is_deleted=true) - Сохраняется кто удалил (
deleted_by) и когда (deleted_at) - Бот пытается удалить сообщение у всех пользователей, используя
forwarded_message_ids - Показывается статистика: "✅ Удалено у 12 пользователей"
Важно: Удаление возможно только если сообщение было сохранено в БД и есть forwarded_message_ids.
Админские команды
/chat_mode
Переключение режима работы чата.
Интерфейс: Inline-клавиатура с выбором режима.
Пример использования:
/chat_mode
→ Показывается меню выбора режима
→ Нажимаем "📢 Рассылка всем"
→ Режим изменен
/set_forward <chat_id>
Установить ID канала/группы для пересылки.
Как узнать chat_id:
- Добавьте бота в канал/группу
- Напишите любое сообщение в канале
- Перешлите его боту @userinfobot
- Он покажет chat_id (например: -1001234567890)
Пример:
/set_forward -1001234567890
→ ID канала для пересылки установлен!
/ban <user_id> [причина]
Забанить пользователя.
Способы использования:
- Ответить на сообщение:
/ban Спам - Указать ID:
/ban 123456789 Нарушение правил
/unban <user_id>
Разбанить пользователя.
Способы использования:
- Ответить на сообщение:
/unban - Указать 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
Одна строка с глобальными настройками чата:
id = 1 (всегда)
mode = 'broadcast' | 'forward'
forward_chat_id = '-1001234567890' (для режима forward)
global_ban = true | false
Таблица banned_users
История банов пользователей:
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
История всех отправленных сообщений:
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:
// Режим broadcast:
{
"123456789": 12345, // telegram_id: message_id
"987654321": 12346,
"555555555": 12347
}
// Режим forward:
{
"channel": 54321 // ключ "channel", значение - ID сообщения в канале
}
Примеры использования
Настройка режима broadcast
- Админ:
/chat_mode→ выбирает "📢 Рассылка всем" - Пользователь А пишет: "Привет всем!"
- Пользователи B, C, D получают это сообщение
- Пользователь А видит: "✅ Сообщение разослано! 📤 Доставлено: 3"
Настройка режима forward
- Админ создает канал и добавляет бота как админа
- Админ узнает chat_id канала (например: -1001234567890)
- Админ:
/set_forward -1001234567890 - Админ:
/chat_mode→ выбирает "➡️ Пересылка в канал" - Пользователь пишет сообщение → оно появляется в канале
Бан пользователя за спам
- Пользователь отправляет спам
- Админ отвечает на его сообщение:
/ban Спам в чате - Пользователь забанен, попытки отправить сообщение блокируются
- Админ:
/banlist- видит список банов - Админ:
/unban(ответ на сообщение) - разбан
Временное закрытие чата
- Админ:
/global_ban - Все пользователи видят: "❌ Чат временно закрыт администратором"
- Только админы могут писать
- Админ:
/global_ban(повторно) - чат открыт
Удаление неприемлемого контента
- Пользователь отправил неприемлемое фото
- Фото разослано всем (режим broadcast)
- Админ отвечает на это сообщение:
/delete_msg - Бот удаляет фото у всех пользователей, кому оно было отправлено
- В БД сообщение помечается как удаленное
Технические детали
Порядок подключения роутеров
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 и т.д.). Если поставить его раньше, он будет перехватывать команды и сообщения, предназначенные для других обработчиков.
Проверка прав
can_send, reason = await ChatPermissionService.can_send_message(
session,
telegram_id=user.telegram_id,
is_admin=is_admin(user.telegram_id)
)
Логика проверки:
- Если пользователь админ → всегда
can_send=True - Если включен global_ban →
can_send=False - Если пользователь забанен →
can_send=False - Иначе →
can_send=True
Миграция 005
При запуске миграции создаются 3 таблицы и вставляется начальная запись:
INSERT INTO chat_settings (id, mode, global_ban)
VALUES (1, 'broadcast', false);
Эта запись будет использоваться всегда (единственная строка в таблице).
Возможные улучшения
- Фильтрация контента - автоматическая проверка на мат, спам, ссылки
- Лимиты - ограничение количества сообщений в минуту/час
- Ответы на сообщения - возможность отвечать на конкретное сообщение пользователя
- Редактирование - изменение отправленных сообщений
- Реакции - лайки/дизлайки на сообщения
- Каналы - разделение чата на темы/каналы
- История - просмотр истории сообщений через команду
- Поиск - поиск по истории сообщений