# /opt/trueconf_bot/transcription_bot/handlers.py import io import os import asyncio import logging import httpx from ldap3 import Server, Connection, ALL from trueconf import Router, Message from config.config import * from utils import states from utils.menu import MENU_TEXT from utils.texts import ( EMOJI_DIGITS, TRANSCRIPTION_MAIN_MENU_TEXT, transcription_error_bad_extension, TRANSCRIPTION_UPLOADING_TEXT, transcription_success_received, transcription_error_api, transcription_error_system, UNKNOWN_MAIN_CMD_TEXT, ) # 🔌 Импортируем централизованную функцию сбора статистики из main from utils.stats_logger import log_menu_stats logger = logging.getLogger(__name__) router = Router() # ✅ Полный список разрешенных расширений (Аудио, Видео, Проф. форматы) ALLOWED_EXTENSIONS = [ # Аудио '.mp3', '.aac', '.m4a', '.flac', '.ogg', '.oga', '.opus', '.wma', '.aif', '.aiff', '.ac3', '.eac3', '.dts', '.thd', '.au', '.caf', '.wv', '.ape', '.tta', '.wav', # Видео '.mp4', '.m4v', '.mkv', '.mka', '.mk3d', '.avi', '.mov', '.flv', '.webm', '.wmv', '.ts', '.m2ts', '.mpg', '.mpeg', '.vob', # Профессиональные и вещательные '.mxf', '.gxf', '.nucap', # Специфические '.4xm', '.bik', '.smk', '.cak' ] # --- Функция получения Email из Active Directory --- def get_user_email_sync(login: str) -> str: try: server = Server(AD_SERVER, get_info=ALL) conn = Connection(server, user=AD_USER, password=AD_PASSWORD, auto_bind=True) conn.search(search_base=AD_BASE, search_filter=f"(sAMAccountName={login})", attributes=["mail"]) if conn.entries and 'mail' in conn.entries[0] and conn.entries[0].mail.value: return str(conn.entries[0].mail.value) except Exception as e: logger.error(f"Ошибка поиска email в AD: {e}") return DEFAULT_REQUESTER @router.message() async def transcription_handler(msg: Message): user_id = msg.from_user.id # Работаем только если включен режим расшифровки if states.get_state(user_id) != "TRANSCRIPTION_MODE": return # Помечаем сообщение как обработанное msg.handled = True user_login = user_id.split('@')[0] if '@' in user_id else user_id msg_text = getattr(msg.content, "text", "").strip() if hasattr(msg.content, "text") else "" is_attachment = hasattr(msg.type, "name") and msg.type.name == "ATTACHMENT" cmd = msg_text.lower() # 🔄 НОРМАЛИЗАЦИЯ КНОПОК ВК-ЭМОДЗИ for raw_num, emoji_num in EMOJI_DIGITS.items(): if cmd == emoji_num: cmd = raw_num break # --- ВЫХОД (Кнопки 0 и 9 приведены к единому стандарту) --- if cmd in ["0", "9", "/start", "меню"]: log_menu_stats(user_id, "Speech-to-Text", "Выход в главное меню") states.clear_state(user_id) await msg.answer(MENU_TEXT, parse_mode="html") return # --- ОБРАБОТКА ФАЙЛА --- if is_attachment: file_name = getattr(msg.content, "file_name", "").lower() file_id = getattr(msg.content, "file_id", None) # Проверка расширения ext = os.path.splitext(file_name)[1] if ext not in ALLOWED_EXTENSIONS: await msg.answer(transcription_error_bad_extension(ext), parse_mode="html") return await msg.answer(TRANSCRIPTION_UPLOADING_TEXT, parse_mode="html") try: # 1. Добываем почту из AD user_email = await asyncio.to_thread(get_user_email_sync, user_login) # 2. Качаем файл (возвращает bytes) downloaded_file = await states.tc_bot.download_file_by_id(file_id) # 3. Отправка на API async with httpx.AsyncClient(timeout=120.0) as client: files = {'file': (file_name, io.BytesIO(downloaded_file), 'application/octet-stream')} payload = { 'email': user_email, 'generate_summary': 'true' } response = await client.post(TRANSCRIPTION_API_URL, files=files, data=payload) if response.status_code == 200: log_menu_stats(user_id, "Speech-to-Text", f"Отправка встречи на расшифровку ({ext})") await msg.answer(transcription_success_received(user_email), parse_mode="html") else: await msg.answer(transcription_error_api(response.status_code), parse_mode="html") except Exception as e: logger.error(f"Transcription Upload Error: {e}") await msg.answer(transcription_error_system(), parse_mode="html") return # --- ЗАГЛУШКА НА НЕИЗВЕСТНЫЙ ТЕКСТ / СТАНДАРТНАЯ ОШИБКА ВВОДА --- await msg.answer(UNKNOWN_MAIN_CMD_TEXT, parse_mode="html")