Files
new_lottery_bot/docs/EMOJI_SYSTEM.md
Andrew K. Choi 72f9d40a1a
Some checks failed
continuous-integration/drone/pr Build is failing
Add custom emoji mapping system for premium emoji support
- 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
2026-03-07 10:46:13 +09:00

8.5 KiB
Raw Permalink Blame History

Система управления кастомными эмодзи

Обзор

Система позволяет администраторам регистрировать премиум эмодзи и использовать их в сообщениях бота. Когда админ отправляет эмодзи боту:

  1. Бот получает emoji_id от Telegram API
  2. Сохраняет эмодзи в таблице emoji_mappings
  3. При отправке сообщений в чаты бот автоматически использует emoji_id вместо текста эмодзи

Это обеспечивает, что эмодзи будут выглядеть точно так же, как их отправил админ, даже если это премиум эмодзи.

Команды администратора

1. Добавить новый эмодзи

/add_emoji

Процесс:

  1. Админ запускает команду /add_emoji
  2. Бот просит отправить эмодзи
  3. Админ отправляет эмодзи (например, 🎲)
  4. Бот просит описание (для чего используется)
  5. Админ отправляет描述 (например, "Для лотереи")
  6. Бот сохраняет в БД и подтверждает

2. Просмотр своих эмодзи

/my_emojis

Показывает все эмодзи, добавленные этим админом:

  • Сам эмодзи
  • Описание
  • ID (первые 30 символов)
  • Дату добавления

3. Просмотр всех эмодзи в системе

/all_emojis

Показывает все эмодзи всех админов с информацией об администраторе

4. Удалить эмодзи

/delete_emoji

Админ может удалить только свои эмодзи. Процесс:

  1. Вызвать команду
  2. Выбрать эмодзи из список (кнопки)
  3. Бот удалит из БД

Использование в коде

Простой способ - прямое использование эмодзи

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")

Важные моменты

  1. Parse Mode: Всегда используйте parse_mode="HTML" при работе с эмодзи
  2. Кеширование ID: Система не кеширует, каждый раз обращается к БД. Для оптимизации можно добавить кеширование
  3. Лог использования: last_used_at обновляется автоматически при замене в тексте
  4. Удаление: Удаленный эмодзи больше не будет заменяться в новых сообщениях
  5. Конфликты: Если два админа добавляют один эмодзи - они сохранятся отдельно (разные 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() перед отправкой