Первый коммит

This commit is contained in:
2026-02-17 11:24:55 +07:00
commit a06448ca4b
109 changed files with 21165 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
"""
Обработчик команды /emoji для извлечения ID премиум эмодзи
"""
from aiogram import Router
from aiogram.filters import Command
from aiogram.types import Message
from aiogram.utils.keyboard import InlineKeyboardBuilder
from bot.filters.admin import IsAdmin
from configs import settings, COMMANDS
from middleware.loggers import logger
__all__ = ("router",)
router: Router = Router(name="emoji_extractor_router")
# ================= ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ =================
def extract_custom_emojis(message: Message) -> list[dict]:
"""
Извлекает все кастомные эмодзи из сообщения.
Args:
message: Сообщение для анализа
Returns:
Список словарей с информацией об эмодзи
"""
if not message.entities and not message.caption_entities:
return []
# Определяем текст и entities
text = message.text or message.caption
entities = message.entities or message.caption_entities
if not text or not entities:
return []
custom_emojis = []
for entity in entities:
if entity.type == "custom_emoji":
# Извлекаем символ эмодзи
emoji_char = text[entity.offset:entity.offset + entity.length]
custom_emojis.append({
"char": emoji_char,
"id": entity.custom_emoji_id,
"offset": entity.offset
})
return custom_emojis
def format_emoji_html(emoji_char: str, emoji_id: str) -> str:
"""
Форматирует эмодзи в HTML-тег.
Args:
emoji_char: Символ эмодзи (fallback)
emoji_id: ID кастомного эмодзи
Returns:
HTML-строка
"""
return f'<tg-emoji emoji-id="{emoji_id}">{emoji_char}</tg-emoji>'
def escape_html(text: str) -> str:
"""Экранирует HTML символы"""
return (
text.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
)
# ================= КОМАНДА /EMOJI =================
@router.message(
Command(*COMMANDS.get("emoji", ["emoji"]), prefix=settings.PREFIX, ignore_case=True),
IsAdmin()
)
async def emoji_extractor_cmd(message: Message) -> None:
"""
Извлекает кастомные эмодзи из сообщения.
Доступно только администраторам.
Использование: /emoji (в ответ на сообщение)
"""
# Проверяем, что команда в ответ на сообщение
if not message.reply_to_message:
await message.answer(
"❌ <b>Используйте команду в ответ на сообщение</b>\n\n"
"📝 Как использовать:\n"
"1. Ответьте на сообщение с премиум эмодзи\n"
"2. Напишите <code>/emoji</code>\n\n"
"💡 <i>Бот извлечёт все кастомные эмодзи и покажет HTML-код</i>",
parse_mode="HTML"
)
return
replied_message = message.reply_to_message
# Извлекаем кастомные эмодзи
custom_emojis = extract_custom_emojis(replied_message)
if not custom_emojis:
# Нет кастомных эмодзи
await message.answer(
"⚠️ <b>Кастомные эмодзи не найдены</b>\n\n"
"В этом сообщении нет премиум эмодзи.\n\n"
"💡 <i>Попробуйте ответить на сообщение с анимированными эмодзи</i>",
parse_mode="HTML"
)
return
# === ФОРМИРУЕМ ОТВЕТ ===
output = f"✨ <b>НАЙДЕНО ЭМОДЗИ: {len(custom_emojis)}</b>\n\n"
for idx, emoji_data in enumerate(custom_emojis, 1):
emoji_char = emoji_data["char"]
emoji_id = emoji_data["id"]
output += f"<b>{idx}.</b> Эмодзи: {emoji_char}\n"
output += f"📋 <b>ID:</b> <code>{emoji_id}</code>\n\n"
# HTML-код (экранированный для отображения)
html_code = format_emoji_html(emoji_char, emoji_id)
html_escaped = escape_html(html_code)
output += f"📝 <b>HTML-код:</b>\n"
output += f"<code>{html_escaped}</code>\n\n"
# Пример использования
output += f"🎨 <b>Превью:</b> {html_code}\n"
if idx < len(custom_emojis):
output += "\n" + "" * 30 + "\n\n"
output += "💡 <i>Скопируйте HTML-код и используйте в своих сообщениях</i>"
# Создаём клавиатуру
ikb = InlineKeyboardBuilder()
ikb.button(text="✖️ Закрыть", callback_data="emoji_close")
# Отправляем
try:
await message.answer(
text=output,
parse_mode="HTML",
reply_markup=ikb.as_markup()
)
logger.info(
f"Извлечено {len(custom_emojis)} кастомных эмодзи админом {message.from_user.id}",
log_type="EMOJI_EXTRACT"
)
except Exception as e:
logger.error(f"Ошибка отправки эмодзи: {e}", log_type="ERROR")
await message.answer(
"❌ <b>Ошибка извлечения эмодзи</b>\n\n"
"Попробуйте позже или обратитесь к разработчику.",
parse_mode="HTML"
)
# ================= ОБРАБОТЧИК КНОПКИ ЗАКРЫТИЯ =================
@router.callback_query(lambda c: c.data == "emoji_close", IsAdmin())
async def emoji_close_callback(callback) -> None:
"""Закрывает сообщение с эмодзи"""
try:
await callback.message.delete()
await callback.answer("✅ Закрыто")
except Exception as e:
logger.error(f"Ошибка удаления сообщения с эмодзи: {e}", log_type="ERROR")
await callback.answer("Не удалось удалить", show_alert=True)
# ================= ДОПОЛНИТЕЛЬНАЯ КОМАНДА /EMOJIHELP =================
@router.message(
Command(*COMMANDS.get("emojihelp", ["emojihelp"]), prefix=settings.PREFIX, ignore_case=True),
IsAdmin()
)
async def emoji_help_cmd(message: Message) -> None:
"""
Справка по работе с кастомными эмодзи.
"""
text = (
"🎨 <b>РАБОТА С КАСТОМНЫМИ ЭМОДЗИ</b>\n\n"
"📝 <b>Команда /emoji</b>\n"
"Извлекает ID премиум эмодзи из сообщения\n\n"
"🔧 <b>Как использовать:</b>\n"
"1⃣ Ответьте на сообщение с эмодзи\n"
"2⃣ Напишите <code>/emoji</code>\n"
"3⃣ Скопируйте HTML-код\n\n"
"💻 <b>Формат HTML-кода:</b>\n"
"<code>&lt;tg-emoji emoji-id=\"ID\"&gt;fallback&lt;/tg-emoji&gt;</code>\n\n"
"📌 <b>Пример использования в коде:</b>\n"
"<code>text = 'Привет &lt;tg-emoji emoji-id=\"5368324170671202286\"&gt;👍&lt;/tg-emoji&gt;'\n"
"await message.answer(text, parse_mode=\"HTML\")</code>\n\n"
"⚠️ <b>Важно:</b>\n"
"├─ Используйте <code>parse_mode=\"HTML\"</code>\n"
"├─ Пользователи без Premium видят fallback\n"
"└─ Работает только с кастомными эмодзи\n\n"
"💡 <i>Попробуйте отправить эмодзи и ответить командой /emoji</i>"
)
await message.answer(text, parse_mode="HTML")