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

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

3
configs/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
from .cmd_alias_list import *
from .config import *
from .mapping import *

363
configs/cmd_alias_list.py Normal file
View File

@@ -0,0 +1,363 @@
from typing import Final
# Настройка экспорта в модули
__all__ = ("COMMANDS",)
# Список команд по ключу
COMMANDS: Final[dict[str, list[str]]] = {
"start": [
"start", "старт", "почати", # основные
"ыефке", "cnfhn", "gjxfnb", # раскладка
"st", "on", "вкл", # сокращения
],
"help": [
"help", "помощь", "допомога", # основные
"рудз", "gjvjom", "ljgjvjuf", # раскладка
"h", "хелп", "?", # сокращения
],
"menu": [
"menu", "меню", # основные
"vtym", "vtye", # раскладка
"m", "mn", # сокращения
],
"stats": [
"stats", "статистика", "стат", # основные
"cnfnbcnbrf", "cnfn", "cns", # раскладка
"stat", "st", "s", # сокращения
],
# ==================== ДОБАВЛЕНИЕ ПОСТОЯННЫХ ====================
"addword": [
"addword", "добавитьслово", # основные
"фввцщкв", "lj,fdbnmckjdj", # раскладка
"aw", "addw", "добслово", # сокращения
],
"addlemma": [
"addlemma", "добавитьлемму", # основные
"фввдуььф", "lj,fdbnmktve", # раскладка
"al", "addl", "доблемму", # сокращения
],
"addpart": [
"addpart", "добавитьчасть", # основные
"фввзфке", "lj,fdbnmxfcnm", # раскладка
"ap", "addp", "добчасть", # сокращения
],
# ==================== ДОБАВЛЕНИЕ ВРЕМЕННЫХ ====================
"addtempword": [
"addtempword", "добавитьвремслово", # основные
"фввеуьзцщкв", "lj,fdbnmdhtvckjdj", # раскладка
"atw", "addtw", "темпслово", # сокращения
],
"addtemplemma": [
"addtemplemma", "добавитьвремлемму", # основные
"фввеуьздуььф", "lj,fdbnmdhtvktve", # раскладка
"atl", "addtl", "темплемму", # сокращения
],
# ==================== ДОБАВЛЕНИЕ ИСКЛЮЧЕНИЙ ====================
"addexcept": [
"addexcept", "добавитьисключение", # основные
"фввучсузе", "lj,fdbnmbcrkx", # раскладка
"axc", "addwhite", "искл", # сокращения
],
# ==================== УДАЛЕНИЕ ПОСТОЯННЫХ ====================
"remword": [
"remword", "удалитьслово", # основные
"кутцщкв", "elfkbnmckjdj", # раскладка
"rw", "delword", "dw", "удслово", # сокращения
],
"remlemma": [
"remlemma", "удалитьлемму", # основные
"кутдуььф", "elfkbnmktve", # раскладка
"rl", "dellemma", "dl", "удлемму", # сокращения
],
"rempart": [
"rempart", "удалитьчасть", # основные
"кутзфке", "elfkbnmxfcnm", # раскладка
"rp", "delpart", "dp", "удчасть", # сокращения
],
# ==================== УДАЛЕНИЕ ВРЕМЕННЫХ ====================
"remtempword": [
"remtempword", "удалитьвремслово", # основные
"кутеуьзцщкв", "elfkbnmdhtvckjdj", # раскладка
"rtw", "deltw", "удтемпслово", # сокращения
],
"remtemplemma": [
"remtemplemma", "удалитьвремлемму", # основные
"кутеуьздуььф", "elfkbnmdhtvktve", # раскладка
"rtl", "deltl", "удтемплемму", # сокращения
],
# ==================== УДАЛЕНИЕ ИСКЛЮЧЕНИЙ ====================
"remexcept": [
"remexcept", "удалитьисключение", # основные
"кутучсузе", "elfkbnmbcrkx", # раскладка
"rxc", "remwhite", "удискл", # сокращения
],
# ==================== КОНФЛИКТНЫЕ СЛОВА ====================
"addconflictword": [
"addconflictword", "добавитьконфликт", # основные
"фввсщтакшсецщкв", "lj,fdbnmrjyakbrn", # раскладка
"acw", "addcw", "конфслово", # сокращения
],
"addconflictlemma": [
"addconflictlemma", "добавитьконфлемму", # основные
"фввсщтакшседуььф", "lj,fdbnmrjyaktve", # раскладка
"acl", "addcl", "конфлемму", # сокращения
],
"remconflictword": [
"remconflictword", "удалитьконфликт", # основные
"кутсщтакшсецщкв", "elfkbnmrjyakbrn", # раскладка
"rcw", "delcw", "удконфликт", # сокращения
],
"remconflictlemma": [
"remconflictlemma", "удалитьконфлемму", # основные
"кутсщтakшседуььф", "elfkbnmrjyaktve", # раскладка
"rcl", "delcl", "удконфлемму", # сокращения
],
# ==================== РЕЖИМ АНТИКОНФЛИКТА ====================
"stopconflict": [
"stopconflict", "стопконфликт", # основные
"cnjgsщтakшse", "cnjzrjyakbrn", # раскладка
"sconf", "sc", "стопконф", # сокращения
],
"unstopconflict": [
"unstopconflict", "отменаконфликта", # основные
"eycnjgsщтakшse", "jnvtyf", # раскладка
"usconf", "usc", "откконф", # сокращения
],
"conflictstatus": [
"conflictstatus", "статусконфликта", # основные
"сщтakшseыефnec", "cnfnec", # раскладка
"cstatus", "cs", "статконф", # сокращения
],
# ==================== РЕЖИМ ТИШИНЫ ====================
"silence": [
"silence", "тишина", "мут", # основные
"ышдутсу", "nbibyf", "ven", # раскладка
"sil", "mute", "quiet", "тиш", # сокращения
],
"unsilence": [
"unsilence", "отменатишины", # основные
"eтышдутсу", "jnvtyf", # раскладка
"unsil", "unmute", "откмут", # сокращения
],
"silencestatus": [
"silencestatus", "статустишины", # основные
"ышдутсуыефnec", "cnfnec", # раскладка
"sstatus", "ss", "статтиш", # сокращения
],
"extend_silence": [
"extend_silence", "продлитьтишину", # основные
"уче_ышдутсу", "ghjlkbnmnbibyet", # раскладка
"exsil", "exs", "продтиш", # сокращения
],
# ==================== АДМИНИСТРАТОРЫ ====================
"addadmin": [
"addadmin", "добавитьадмина", # основные
"фввфвьшт", "lj,fdbnmflvbyf", # раскладка
"aa", "addadm", "добадм", # сокращения
],
"remadmin": [
"remadmin", "удалитьадмина", # основные
"кутфвьшт", "elfkbnmflvbyf", # раскладка
"ra", "remadm", "deladmin", "удадм", # сокращения
],
"listadmins": [
"listadmins", "списокадминов", # основные
"дшыефвьшты", "cgbcjrflvbyjd", # раскладка
"admins", "adm", "adminlist", "адм", # сокращения
],
"adminhelp": [
"adminhelp", "помощьадмину", # основные
"фвьштрудз", "gjvjomflvbyt", # раскладка
"admhelp", "ah", "хелпадм", # сокращения
],
"checkadmin": [
"checkadmin", "проверкаадмина", # основные
"сруслфвьшт", "ghjdthrf", # раскладка
"isadmin", "ca", "провадм", # сокращения
],
# ==================== ПРОСМОТР ====================
"list": [
"listwords", "списокслов", # основные
"дшыецщквы", "cgbcjrckjd", # раскладка
"lw", "list", "дшые", "words", "слова", # сокращения
],
"listlemmas": [
"listlemmas", "списоклемм", # основные
"дшыедуььфы", "cgbcjrktv", # раскладка
"ll", "lemmas", "леммы", # сокращения
],
"listparts": [
"listparts", "списокчастей", # основные
"дшыезфкеы", "cgbcjrxfcntq", # раскладка
"lp", "parts", "части", # сокращения
],
"listexcept": [
"listexcept", "списокисключений", # основные
"дшыеучсузе", "cgbcjrbcrkx", # раскладка
"lxc", "except", "white", "искл", # сокращения
],
"listconflict": [
"listconflict", "списокконфликтов", # основные
"дшыесщтakшse", "cgbcjrrjyakbrnjd", # раскладка
"lc", "conflict", "конф", # сокращения
],
# ==================== СТАТИСТИКА ====================
"userstats": [
"userstats", "статистикапользователя", # основные
"ecthыефnы", "cnfnbcnbrf", # раскладка
"ustat", "us", "статюзер", # сокращения
],
"resetstats": [
"resetstats", "сброситьстат", # основные
"кыуеыефnы", "c,hjcbnm", # раскладка
"rstats", "clearstats", "сброс", # сокращения
],
# ==================== ИНФОРМАЦИЯ ====================
"id": [
"id", "айди", "инфо", # основные
"шв", "fqlb", "byaj", # раскладка
"info", "me", "мои", # сокращения
],
"myid": [
"myid", "мойайди", # основные
"ьншв", "vjqfqlb", # раскладка
"mid", "мид", # сокращения
],
"chatid": [
"chatid", "айдичата", # основные
"срфешв", "fqlbxfnf", # раскладка
"cid", "чатид", # сокращения
],
# ==================== РЕПОРТЫ ====================
"report": [
"report", "репорт", "жалоба", # основные
"кузщке", "htgjhn", ";fkj,f", # раскладка
"rep", "r", "жал", # сокращения
],
"reporthelp": [
"reporthelp", "помощьрепорт", # основные
"кузщкерудз", "gjvjomhtgjhn", # раскладка
"rephelp", "rh", "хелпреп", # сокращения
],
"reportstats": [
"reportstats", "статистикарепортов", # основные
"кузщкеыефnы", "cnfnbcnbrf", # раскладка
"rstat", "rs", "статреп", # сокращения
],
"checkreport": [
"checkreport", "проверкарепорта", # основные
"сруслкузщке", "ghjdthrf", # раскладка
"crep", "cr", "провреп", # сокращения
],
"closereport": [
"closereport", "закрытьрепорт", # основные
"сдщыукузщке", "pfrhsnm", # раскладка
"close", "cl", "закреп", # сокращения
],
"banreport": [
"banreport", "забанитьрепорт", # основные
"фтшкузщке", "pf,fybnm", # раскладка
"banrep", "br", "банреп", # сокращения
],
# ==================== ЭМОДЗИ ====================
"emoji": [
"emoji", "эмодзи", # основные
"уьщош", "'vjlpb", # раскладка
"em", "emj", "эм", # сокращения
],
"emojihelp": [
"emojihelp", "помощьэмодзи", # основные
"уьщошрудз", "gjvjom'vjlpb", # раскладка
"emhelp", "emh", "хелпэм", # сокращения
],
# ==================== СИСТЕМНЫЕ ====================
"ping": [
"ping", "пинг", # основные
"зштп", "gbyp", # раскладка
"p", "пн", # сокращения
],
"version": [
"version", "версия", # основные
"дукышщт", "dthcbz", # раскладка
"ver", "v", "вер", # сокращения
],
"reload": [
"reload", "перезагрузка", # основные
"кудщфв", "gthtpfuheprf", # раскладка
"rl", "restart", "рест", # сокращения
],
"logs": [
"logs", "логи", # основные
"дщпы", "kjub", # раскладка
"log", "l", "лог", # сокращения
],
}

224
configs/config.py Normal file
View File

@@ -0,0 +1,224 @@
from pathlib import Path
from urllib.parse import urlparse, ParseResult
from typing import Optional, Any
from secrets import token_urlsafe
from pydantic import field_validator, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
from aiogram.types import ChatAdministratorRights
class _Settings(BaseSettings):
"""Настройки бота с комплексной валидацией"""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
case_sensitive=False,
validate_default=True,
)
# ============== ОСНОВНЫЕ ПАРАМЕТРЫ ==============
# Токены бота
BOT_TOKEN: Optional[str] = None
# Параметры сообщений
PARSE_MODE: str = "HTML"
PREFIX: str = "/!.&?"
# Разрешения и логирование
BOT_EDIT: bool = False
START_INFO_CONSOLE: bool = True
START_INFO_TO_FILE: bool = True
LOG_CONSOLE: bool = True
LOG_FILE: bool = True
LOG_DIR: Path = Path('Logs')
LOG_FILE_INFO: Path = Path('bot_info.log')
LOG_ROTATION: str = '100 MB'
LOG_RETENTION: str = '7 days'
# Вебхук
WEBHOOK: bool = False
SECRET_TOKEN: Optional[str] = ''
WEBHOOK_URL: Optional[str] = None
WEBAPP_HOST: str = "0.0.0.0"
WEBAPP_PORT: int = 3131
LOG_LEVEL: str = "warning"
ACCES_LOG: bool = False
# API ключи
API_KEY: Optional[str] = None
WEB_API_KEY: Optional[str] = None
WEATHER_API_KEY: Optional[str] = None
# Идентификаторы
OWNER_ID: list[int] = [6751720805]
ADMIN_ID: list[int] = []
ADMIN_CHAT_ID: int = 0
# Настройки бота
BOT_NAME: str = "Бот"
BOT_DESCRIPTION: Optional[str] = None
BOT_SHORT_DESCRIPTION: Optional[str] = None
# Права администратора
ANONYMOUS: bool = False
MANAGE_CHAT: bool = True
CHANGE_INFO: bool = True
PROMOTE_MEMBERS: bool = True
RESTRICT_MEMBERS: bool = True
POST_MESSAGE: bool = True
MANAGE_TOPICS: bool = True
INVITE_USER: bool = True
DELETE_MESSAGES: bool = True
MANAGE_VIDEO_CHATS: bool = True
EDIT_MESSAGES: bool = True
PIN_MESSAGE: bool = True
POST_STORIES: bool = True
EDIT_STORIES: bool = True
DELETE_STORIES: bool = True
# Настройки сообщений
DISABLE_NOTIFICATION: bool = False
PROTECT_CONTENT: bool = False
ALLOW_SENDING_WITHOUT_REPLY: bool = True
LINK_PREVIEW_IS_DISABLED: bool = False
LINK_PREVIEW_PREFER_SMALL_MEDIA: bool = False
LINK_PREVIEW_PREFER_LARGE_MEDIA: bool = True
LINK_PREVIEW_SHOW_ABOVE_TEXT: bool = True
SHOW_CAPTION_ABOVE_MEDIA: bool = False
# улучшения
ANTI_SPAM: bool = True
# ================= ВАЛИДАТОРЫ =================
@field_validator('PARSE_MODE')
def validate_parse_mode(cls, v: str) -> str:
allowed_modes: set[str] = {"HTML", "Markdown", "MarkdownV2"}
if v not in allowed_modes:
raise ValueError(f"Недопустимый PARSE_MODE. Допустимые: {', '.join(allowed_modes)}")
return v
@field_validator('PREFIX')
def validate_prefix(cls, v: str) -> str:
cleaned: str = ''.join(dict.fromkeys(v)) # Удаление дубликатов с сохранением порядка
if len(cleaned) < 1:
raise ValueError("PREFIX должен содержать хотя бы один символ")
return cleaned
@field_validator('LOG_DIR', 'LOG_FILE_INFO', 'POSTS_DIR', mode='before')
def validate_paths(cls, v: Any) -> Path:
return Path(v) if isinstance(v, str) else v
@field_validator('WEBHOOK_URL')
def validate_webhook_url(cls, v: Optional[str]) -> Optional[str]:
if v is None:
return v
parsed: ParseResult = urlparse(v)
if not all([parsed.scheme, parsed.netloc]):
raise ValueError("Некорректный URL вебхука")
if parsed.scheme != 'https':
raise ValueError("WEBHOOK_URL должен использовать HTTPS")
return v
@field_validator('BOT_NAME')
def validate_non_empty(cls, v: str) -> str:
if not v.strip():
raise ValueError("Поле не может быть пустым")
return v
@model_validator(mode='after')
def validate_bot_token(self) -> "_Settings":
if not self.BOT_TOKEN:
raise ValueError("Требуется BOT_TOKEN для рабочего режима")
return self
@model_validator(mode='after')
def validate_webhook_config(self) -> "_Settings":
if self.WEBHOOK and not self.WEBHOOK_URL:
raise ValueError("WEBHOOK_URL обязателен при включенном WEBHOOK")
# ✅ Генерация SECRET_TOKEN если не установлен
if self.WEBHOOK and not self.SECRET_TOKEN:
self.SECRET_TOKEN = token_urlsafe(32)
return self
@model_validator(mode='after')
def validate_logging_paths(self) -> "_Settings":
if self.LOG_FILE:
self.LOG_DIR.mkdir(parents=True, exist_ok=True)
# ✅ Создание директории для постов
if not self.POSTS_DIR.exists():
self.POSTS_DIR.mkdir(parents=True, exist_ok=True)
return self
@model_validator(mode='after')
def set_dynamic_descriptions(self) -> "_Settings":
if self.BOT_DESCRIPTION is None:
self.BOT_DESCRIPTION = f"Ваш помощник в удивительные миры! Prod. by:『@verdise』"
if self.BOT_SHORT_DESCRIPTION is None:
self.BOT_SHORT_DESCRIPTION = f"Тех.поддержка: @verdise"
return self
# ================= СВОЙСТВА =================
@property
def rights(self) -> ChatAdministratorRights:
"""Права администратора бота"""
return ChatAdministratorRights(
is_anonymous=self.ANONYMOUS,
can_manage_chat=self.MANAGE_CHAT,
can_delete_messages=self.DELETE_MESSAGES,
can_manage_video_chats=self.MANAGE_VIDEO_CHATS,
can_restrict_members=self.RESTRICT_MEMBERS,
can_promote_members=self.PROMOTE_MEMBERS,
can_change_info=self.CHANGE_INFO,
can_invite_users=self.INVITE_USER,
can_post_stories=self.POST_STORIES,
can_edit_stories=self.EDIT_STORIES,
can_delete_stories=self.DELETE_STORIES,
can_post_messages=self.POST_MESSAGE,
can_edit_messages=self.EDIT_MESSAGES,
can_pin_messages=self.PIN_MESSAGE,
can_manage_topics=self.MANAGE_TOPICS,
)
@property
def active_bot_token(self) -> str:
"""Активный токен бота в зависимости от режима"""
if not self.BOT_TOKEN:
raise ValueError("Активный токен бота отсутствует")
return self.BOT_TOKEN
@property
def log_dir_absolute(self) -> Path:
"""Абсолютный путь к директории логов"""
return self.LOG_DIR.absolute()
@property
def super_admin_ids(self) -> set[int]:
"""Множество ID суперадминов (для банвордов)"""
return set(self.OWNER_ID)
# ✅ Единственный экземпляр настроек
settings = _Settings()
# ✅ ОПЦИОНАЛЬНО: Простые константы для обратной совместимости (без дублирования)
# Используются только для удобства импорта, но ссылаются на settings
BOT_TOKEN = settings.active_bot_token
ADMIN_CHAT_ID = settings.ADMIN_CHAT_ID
SUPER_ADMIN_IDS = settings.super_admin_ids
WORDS_FILE = settings.WORDS_FILE
# Экспорт
__all__ = (
'settings',
'BOT_TOKEN',
'ADMIN_CHAT_ID',
'SUPER_ADMIN_IDS',
'WORDS_FILE',
)

163
configs/mapping.py Normal file
View File

@@ -0,0 +1,163 @@
"""
Словари для нормализации текста и замены символов
"""
from typing import Dict
# Словарь замены латинских букв на кириллические (для обхода фильтров)
LATIN_TO_CYRILLIC: Dict[str, str] = {
'a': 'а', 'A': 'А',
'b': 'б', 'B': 'В',
'c': 'с', 'C': 'С',
'e': 'е', 'E': 'Е',
'h': 'н', 'H': 'Н',
'k': 'к', 'K': 'К',
'm': 'м', 'M': 'М',
'o': 'о', 'O': 'О',
'p': 'р', 'P': 'Р',
't': 'т', 'T': 'Т',
'x': 'х', 'X': 'Х',
'y': 'у', 'Y': 'У'
}
# Словарь замены похожих кириллических букв (украинские, белорусские и т.д.)
CYRILLIC_NORMALIZE: Dict[str, str] = {
'ґ': 'г', 'Ґ': 'Г', # украинское Ґ
'є': 'е', 'Є': 'Е', # украинское Є
'і': 'и', 'І': 'И', # украинское І
'ї': 'и', 'Ї': 'И', # украинское Ї
'ў': 'у', 'Ў': 'У', # белорусское Ў
'ѐ': 'е', 'Ѐ': 'Е', # кириллица с грависом
'ё': 'е', 'Ё': 'Е', # ё -> е для упрощения
}
# Большой словарь Unicode-символов -> кириллица/латиница
UNICODE_MAP: Dict[str, str] = {
# === ЛАТИНСКИЕ БУКВЫ -> КИРИЛЛИЦА ===
'a': 'а', 'A': 'А', 'b': 'б', 'B': 'В', 'c': 'с', 'C': 'С',
'd': 'д', 'D': 'Д', 'e': 'е', 'E': 'Е', 'f': 'ф', 'F': 'Ф',
'g': 'г', 'G': 'Г', 'h': 'н', 'H': 'Н', 'i': 'и', 'I': 'И',
'j': 'ж', 'J': 'Ж', 'k': 'к', 'K': 'К', 'l': 'л', 'L': 'Л',
'm': 'м', 'M': 'М', 'n': 'н', 'N': 'Н', 'o': 'о', 'O': 'О',
'p': 'р', 'P': 'Р', 'q': 'к', 'Q': 'К', 'r': 'р', 'R': 'Р',
's': 'с', 'S': 'С', 't': 'т', 'T': 'Т', 'u': 'у', 'U': 'У',
'v': 'в', 'V': 'В', 'w': 'ш', 'W': 'Ш', 'x': 'х', 'X': 'Х',
'y': 'у', 'Y': 'У', 'z': 'з', 'Z': 'З',
# === SMALL CAPS ===
'': 'а', 'ʙ': 'б', '': 'с', '': 'д', '': 'е', '': 'ф',
'ɢ': 'г', 'ʜ': 'н', 'ɪ': 'и', '': 'ж', '': 'к', 'ʟ': 'л',
'': 'м', 'ɴ': 'н', '': 'о', '': 'р', '': 'к', 'ʀ': 'р',
'': 's', '': 'т', '': 'у', '': 'в', '': 'ш', 'ʏ': 'у', '': 'з',
'': 'г', '': 'л', 'ʍ': 'м', '': 'п', '': 'р', 'ɸ': 'ф', 'ɯ': 'ш',
# === ГРЕЧЕСКИЕ ===
'α': 'а', 'Α': 'А', 'β': 'б', 'Β': 'В', 'γ': 'г', 'Γ': 'Г',
'δ': 'д', 'Δ': 'Д', 'ε': 'е', 'Ε': 'Е', 'ζ': 'з', 'Ζ': 'З',
'η': 'н', 'Η': 'Н', 'θ': 'т', 'Θ': 'Т', 'ι': 'и', 'Ι': 'И',
'κ': 'к', 'Κ': 'К', 'λ': 'л', 'Λ': 'Л', 'μ': 'м', 'Μ': 'М',
'ν': 'н', 'Ν': 'Н', 'ξ': 'кс', 'Ξ': 'КС', 'ο': 'о', 'Ο': 'О',
'π': 'п', 'Π': 'П', 'ρ': 'р', 'Ρ': 'Р', 'σ': 'с', 'Σ': 'С',
'τ': 'т', 'Τ': 'Т', 'υ': 'у', 'Υ': 'У', 'φ': 'ф', 'Φ': 'Ф',
'χ': 'х', 'Χ': 'Х', 'ψ': 'пс', 'Ψ': 'ПС', 'ω': 'о', 'Ω': 'О',
'ύ': 'у', 'ϱ': 'р', 'ς': 'с', 'ϲ': 'с', 'ϕ': 'ф', 'ϰ': 'к',
'ϻ': 'м', 'ϸ': 'ш', 'ϙ': 'к', 'ϝ': 'в', '϶': 'э', 'ʐ': 'з',
'ʒ': 'ж', 'ʂ': 'ш', 'ʈ': 'т', 'ɳ': 'н', 'ɭ': 'л', 'ƙ': 'к',
'ɼ': 'р', 'ʠ': 'к', 'ɩ': 'и', 'ʝ': 'ж', 'ɦ': 'х', 'ɠ': 'г',
'ɗ': 'д', 'ɓ': 'б', 'ɞ': 'е', 'ƒ': 'ф', 'ɧ': 'х', 'ʑ': 'з',
'ɱ': 'м', 'ƴ': 'у', 'ʌ': 'л', 'ƿ': 'р', 'ɾ': 'р', 'ɟ': 'ж',
'ɥ': 'х', 'ɰ': 'м', 'ѕ': 'с', 'ѡ': 'ш',
# === КОПТСКИЕ ===
'': 'а', '': 'А', '': 'б', '': 'Б', '': 'в', '': 'В',
'': 'г', '': 'Г', '': 'д', '': 'Д', '': 'е', '': 'Е',
'': 'ж', '': 'Ж', '': 'з', '': 'З', '': 'к', '': 'К',
'': 'л', '': 'Л', '': 'м', '': 'М', '': 'н', '': 'Н',
'': 'о', '': 'О', '': 'п', '': 'П', '': 'р', '': 'Р',
'': 'с', '': 'С', '': 'т', '': 'Т', '': 'у', '': 'У',
'': 'ф', '': 'Ф', '': 'х', '': 'Х', '': 'ч', '': 'Ч',
'': 'ш', '': 'Ш', '': 'щ', '': 'Щ', '': 'ж', '': 'Ж',
'': 'г', '': 'Г', '': 'л', '': 'Л', '': 'с', '': 'С',
'': 'в', '': 'В', '': 'з', '': 'З', '': 'и', '': 'И',
'': 'н', '': 'Н', '': 'у', '': 'у',
# === КИРИЛЛИЧЕСКИЕ СТИЛИЗОВАННЫЕ ===
'ѧ': 'а', 'ѣ': 'е', 'ґ': 'г', 'Ґ': 'Г', 'є': 'е', 'Є': 'Е',
'ѫ': 'о', 'Ѫ': 'О', 'ӡ': 'з', 'Ӡ': 'З', 'џ': 'дж', 'Џ': 'ДЖ',
'ӣ': 'и', 'Ӣ': 'И', 'ѳ': 'ф', 'Ѳ': 'Ф', '': 'н', 'ҁ': 'ч',
'ѻ': 'о', 'Ѻ': 'О', 'ҵ': 'ц', 'Ҵ': 'Ц', 'ӌ': 'ч', 'Ӌ': 'Ч',
'ѱ': 'пс', 'Ѱ': 'ПС', 'ƀ': 'б', 'ѥ': 'е', 'Ѥ': 'Е',
'': 'я', 'і': 'и', 'І': 'И', 'ї': 'и', 'Ї': 'И',
'ў': 'у', 'Ў': 'У', 'ӷ': 'г', 'Ӷ': 'Г', 'ӄ': 'к', 'Ӄ': 'К',
'ҁ': 'ч', 'Ҁ': 'Ч', 'ӽ': 'х', 'Ӽ': 'Х', 'ҕ': 'г', 'Ҕ': 'Г',
'ѵ': 'в', 'Ѵ': 'В', 'ʯ': 'ч', 'ɜ': 'з',
# === TAI THAM ===
'': 'а', '': 'е', '': 'и', '': 'й', '': 'л', '': 'н',
'': 'о', '': 'п', '': 'с', '': 'х', '': 'в', '': 'ш',
'': 'з', '': 'з', '': 'л', '': 'а', '': 'б', '': 'в',
'': 'д', '': 'е', '': 'и', '': 'й', '': 'о', '': 'п',
'': 'с', '': 'ч', '': 'л', '': 'д', '': 'х', '': 'ж',
'': 'х', '': 'в', '': 'з', '': 'я', '': 'м',
# === СТАРЫЕ ИТАЛИЙСКИЕ ===
'𐌀': 'А', '𐌁': 'В', '𐌂': 'С', '𐌄': 'Е', '𐌅': 'Ф', '𐌉': 'И',
'𐌊': 'К', '𐌋': 'Ж', '𐌑': 'М', '𐌏': 'О', '𐌐': 'Г', '𐌛': 'Р',
'𐌕': 'Т', '𐌖': 'В', '𐌗': 'Х', '𐌟': 'Ж', '𐌍': 'Й', '𐍔': 'У',
'𐌔': 'З', '𐌒': 'К', '𐌓': 'Я', '𐍃': 'С', '𐌴': 'Э', '𐍂': 'Р',
'𐌜': 'Ь', '𐌆': 'Ж', '𐍆': 'Ф', '𐌺': 'К', '𐌡': 'Л', '𐌌': 'М',
'𐌻': 'л', '𐌼': 'м', '𐌽': 'н', '𐌸': 'щ', '𐍅': 'у', '𐍉': 'я',
'𐌵': 'у', '𐋏': 'н', '𐠨': 'в',
# === ДЕВАНАГАРИ И ПРОЧИЕ ===
'𑀐': 'г', '𑀥': 'д', '𑀝': 'с', '𑀡': 'ж', '𑀗': 'с', '𑀱': 'т',
'𑀉': 'л', '𑀌': 'х', '𑀨': 'ь', '': 'б', '': 'з', '': 'щ',
'': 'р', '': 'т', '': 'ж', '': 'о', 'ʆ': 'ж', 'ʠ': 'к',
'': 'к', '': 'е', '': 'е', '': 'ж', '': 'з', '': 'и',
'': 'х', '': 'к', '': 'м', '': 'м', '': 'н', '': 'о',
'': 'к', '': 'р', '': 'с', '': 'т', '': 'у', '': 'ф',
'': 'х', '': 'ч', '': 'ш', '': 'щ', '': 'ы', '': 'ь',
'': 'э', '': 'ю', '': 'я', '': 'а', '': 'б', '': 'в',
'': 'г', '': 'ф', '': 'г', '': 'ж', '': 'ж', '': 'л',
'': 'к', '': 'р', '': 'с', '': 'д', '': 'м', '': 'ж',
'': 'к', '': 'ш', '': 'у', 'ս': 'у', 'Ա': 'ч', 'Կ': 'ч',
'': 'Г', '': 'Б', '': 'К', '': 'Л', '': 'М', '': 'Н',
'': 'О', '': 'Р', '': 'С', '': 'Т', '': 'У', '': 'Ф',
'': 'Ч', '': 'Ш', '': 'Щ', '': 'А', '': 'Д', '': 'Е',
'': 'Ф', '': 'Г', '': 'И', '': 'Ж', '': 'Л', '': 'Р',
'': 'С', '': 'У', '': 'В', '': 'Ш', '': 'З', '': 'Г',
'': 'К', '': 'Х', '': 'В', '': 'Г', 'ᏏᏓ': 'Ы', '': 'Ь',
'ᎰᏫ': 'Ю', '': 'З', '': 'Р', '': 'Б', '': 'Д', '': 'Ж',
# === FULLWIDTH ===
'': 'а', '': 'б', '': 'с', '': 'д', '': 'е', '': 'ф',
'': 'г', '': 'н', '': 'и', '': 'ж', '': 'к', '': 'л',
'': 'м', '': 'н', '': 'о', '': 'р', '': 'к', '': 'р',
'': 'с', '': 'т', '': 'у', '': 'в', '': 'ш', '': 'х',
'': 'у', '': 'з',
# === МАТЕМАТИЧЕСКИЕ ===
'𝐚': 'а', '𝐛': 'б', '𝐜': 'с', '𝐝': 'д', '𝐞': 'е', '𝐟': 'ф',
'𝐠': 'г', '𝐡': 'н', '𝐢': 'и', '𝐣': 'ж', '𝐤': 'к', '𝐥': 'л',
'𝐦': 'м', '𝐧': 'н', '𝐨': 'о', '𝐩': 'р', '𝐪': 'к', '𝐫': 'р',
'𝐬': 'с', '𝐭': 'т', '𝐮': 'у', '𝐯': 'в', '𝐰': 'ш', '𝐱': 'х',
'𝐲': 'у', '𝐳': 'з',
# === CIRCLED ===
'': 'а', '': 'б', '': 'с', '': 'д', '': 'е', '': 'ф',
'': 'г', '': 'н', '': 'и', '': 'ж', '': 'к', '': 'л',
'': 'м', '': 'н', '': 'о', '': 'р', '': 'к', '': 'р',
'': 'с', '': 'т', '': 'у', '': 'в', '': 'ш', '': 'х',
'': 'у', '': 'з',
# === GUJARATI/DEVANAGARI ===
'': 'у', '': 'р', '': 'о', '': 'к', '': 'с', '': 'ч',
'': 'к', '𑀋': 'х', '': 'я', '': 'ы', '': 'з', 'چ': 'б',
'': 'ю', '': 'ь', '': 'а', '': 'к', '': 'р', '': 'с',
'': 'д', '': 'ф', 'ϻ': 'м', '': 'ж', '': 'п', '': 'х',
'Ͷ': 'М', 'Ͳ': 'Т', 'Ϸ': 'Р', 'Ϥ': 'Ч', 'Ͽ': 'Э', 'Ϳ': 'Ж',
'Ɗ': 'Д', 'Ɠ': 'Г', 'Ɍ': 'Р', 'Ʋ': 'У', 'Ɲ': 'Н', 'Ϙ': 'К',
'ϒ': 'У', 'ζ': 'з', 'Ŵ': 'Ш', '': 'Ы', '': 'х',
# === ЦИФРЫ КАК БУКВЫ ===
'0': 'о', '1': 'и', '3': 'з', '4': 'ч', '5': 'с', '7': 'т', '8': 'в',
}