Initial commit: TrueConf Chatbot КЛЕВЕР
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# /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")
|
||||
Reference in New Issue
Block a user