Some checks failed
continuous-integration/drone/pr Build is failing
- Create emoji_mappings table to store emoji->emoji_id mappings - Add EmojiMappingService for managing emoji registration and replacement - Add admin emoji handlers (/add_emoji, /my_emojis, /delete_emoji, /all_emojis) - Create emoji message helper for automatic emoji processing - Add Alembic migration for emoji_mappings table - Integrate emoji router into main dispatcher - Add comprehensive documentation (EMOJI_SYSTEM.md) - Fix migration chain issue with merge_migration Features: - Admins can register premium emojis via /add_emoji command - Automatic emoji->emoji_id replacement before sending messages - Per-admin unique constraint on emoji registration - Track last used timestamp for analytics - Bulk operations support
8.5 KiB
8.5 KiB
Система управления кастомными эмодзи
Обзор
Система позволяет администраторам регистрировать премиум эмодзи и использовать их в сообщениях бота. Когда админ отправляет эмодзи боту:
- Бот получает
emoji_idот Telegram API - Сохраняет эмодзи в таблице
emoji_mappings - При отправке сообщений в чаты бот автоматически использует
emoji_idвместо текста эмодзи
Это обеспечивает, что эмодзи будут выглядеть точно так же, как их отправил админ, даже если это премиум эмодзи.
Команды администратора
1. Добавить новый эмодзи
/add_emoji
Процесс:
- Админ запускает команду
/add_emoji - Бот просит отправить эмодзи
- Админ отправляет эмодзи (например, 🎲)
- Бот просит описание (для чего используется)
- Админ отправляет描述 (например, "Для лотереи")
- Бот сохраняет в БД и подтверждает
2. Просмотр своих эмодзи
/my_emojis
Показывает все эмодзи, добавленные этим админом:
- Сам эмодзи
- Описание
- ID (первые 30 символов)
- Дату добавления
3. Просмотр всех эмодзи в системе
/all_emojis
Показывает все эмодзи всех админов с информацией об администраторе
4. Удалить эмодзи
/delete_emoji
Админ может удалить только свои эмодзи. Процесс:
- Вызвать команду
- Выбрать эмодзи из список (кнопки)
- Бот удалит из БД
Использование в коде
Простой способ - прямое использование эмодзи
from aiogram.types import Message
async def handler(message: Message):
await message.answer(
text="🎲 Добро пожаловать на лотерею! 🏆",
parse_mode="HTML"
)
С обработкой эмодзи
from sqlalchemy.ext.asyncio import AsyncSession
from src.core.emoji_message_helper import get_emoji_aware_text
from aiogram.types import Message
async def handler(message: Message, session: AsyncSession):
# Текст с эмодзи
original_text = "🎲 Выиграли! 🏆"
# Обработаны текст (эмодзи заменены на ID для корректного отображения)
processed_text = await get_emoji_aware_text(session, original_text)
await message.answer(processed_text, parse_mode="HTML")
Работа с EmojiMessageHelper
from sqlalchemy.ext.asyncio import AsyncSession
from src.core.emoji_message_helper import EmojiMessageHelper
async def handler(message: Message, session: AsyncSession):
helper = EmojiMessageHelper(session)
# Обработка перед отправкой
text = "🎲 Лотерея начинается! 💎"
processed = await helper.process_text_before_send(text)
await message.answer(processed, parse_mode="HTML")
Структура БД
Таблица emoji_mappings
| Колонка | Тип | Описание |
|---|---|---|
id |
Integer | Primary Key |
emoji_text |
String(10) | Сам эмодзи (например, 🎲) |
emoji_id |
String(255) | telegram_emoji_id от API (уникален) |
admin_id |
Integer | FK на user (администратор) |
description |
String(255) | Описание назначения эмодзи |
created_at |
DateTime | Дата добавления |
last_used_at |
DateTime | Последнее использование |
Уникальные ограничения
emoji_id— уникален во всей системе(emoji_text, admin_id)— один админ не может добавить один эмодзи дважды
API сервиса EmojiMappingService
Регистрация эмодзи
from sqlalchemy.ext.asyncio import AsyncSession
from src.core.emoji_mapping_service import EmojiMappingService
async with async_session_maker() as session:
service = EmojiMappingService(session)
emoji = await service.register_emoji(
emoji_text="🎲",
emoji_id="telegram_emoji_id_here",
admin_id=12345,
description="Для лотереи"
)
Получение эмодзи
# По тексту
emoji = await service.get_emoji_by_text("🎲")
# По emoji_id
emoji = await service.get_emoji_by_id("telegram_emoji_id")
# Все эмодзи админа
emojis = await service.get_all_emoji_by_admin(admin_id=12345)
# Все эмодзи
all_emojis = await service.get_all_emojis()
Замена эмодзи в тексте
# Текст → с заменой эмодзи на ID
processed = await service.replace_emojis_in_text(
"🎲 Выиграли! 🏆"
)
# Обратно - ID → эмодзи
original = await service.restore_emojis_in_text(processed)
Получить словарь маппинга
# {emoji_text: emoji_id}
mapping = await service.get_emoji_mapping_dict()
# {'🎲': 'telegram_emoji_id_1', '🏆': 'telegram_emoji_id_2', ...}
Примеры использования в разных рутерах
В регистрации
async def registration_complete(message: Message, session: AsyncSession):
text = "✅ Регистрация завершена! 🎉"
text = await get_emoji_aware_text(session, text)
await message.answer(text, parse_mode="HTML")
В админ-панели
async def lottery_created(callback: CallbackQuery, session: AsyncSession):
text = "🎰 Новый розыгрыш создан! 🏆"
text = await get_emoji_aware_text(session, text)
await callback.message.edit_text(text, parse_mode="HTML")
В чатовой рассылке
async def broadcast_message(message: Message, session: AsyncSession):
text = f"📢 Сообщение от админа: {message.text}\n\n💎 Удачи!"
text = await get_emoji_aware_text(session, text)
for user_id in target_users:
await bot.send_message(user_id, text, parse_mode="HTML")
Важные моменты
- Parse Mode: Всегда используйте
parse_mode="HTML"при работе с эмодзи - Кеширование ID: Система не кеширует, каждый раз обращается к БД. Для оптимизации можно добавить кеширование
- Лог использования:
last_used_atобновляется автоматически при замене в тексте - Удаление: Удаленный эмодзи больше не будет заменяться в новых сообщениях
- Конфликты: Если два админа добавляют один эмодзи - они сохранятся отдельно (разные admin_id)
Миграция
Таблица создана миграцией:
migrations/versions/20260307_0100_add_emoji_mappings.py
Применить миграцию:
alembic upgrade head
Trouble Shooting
Эмодзи не отображается корректно
- Проверьте что используете
parse_mode="HTML" - Убедитесь что эмодзи зарегистрирован с помощью
/my_emojis
Ошибка "Can't parse entities"
- Это означает что есть конфликт форматирования
- Убедитесь что используете HTML теги (
<b>,<i>, и т.д.), а не Markdown (**,__)
Эмодзи не заменяется
- Проверьте что был зарегистрирован с помощью
/add_emoji - Убедитесь что используете функцию
get_emoji_aware_text()перед отправкой