83 lines
2.7 KiB
Python
83 lines
2.7 KiB
Python
"""Telegram-бот: текстовые и голосовые сообщения → LLM → ответ."""
|
||
import asyncio
|
||
import logging
|
||
import tempfile
|
||
from pathlib import Path
|
||
|
||
from aiogram import Bot, Dispatcher, F, Router
|
||
from aiogram.types import Message
|
||
|
||
import config
|
||
from config import get_gitea_username
|
||
from llm_handler import process_message
|
||
from transcribe import transcribe_audio
|
||
|
||
logging.basicConfig(level=logging.INFO)
|
||
logger = logging.getLogger(__name__)
|
||
|
||
config.validate()
|
||
|
||
bot = Bot(token=config.TELEGRAM_BOT_TOKEN)
|
||
dp = Dispatcher()
|
||
router = Router()
|
||
dp.include_router(router)
|
||
|
||
|
||
@router.message(F.text)
|
||
async def on_text(message: Message) -> None:
|
||
text = (message.text or "").strip()
|
||
if not text:
|
||
return
|
||
gitea_username = get_gitea_username(
|
||
message.from_user.username if message.from_user else None,
|
||
message.from_user.id if message.from_user else None,
|
||
)
|
||
try:
|
||
reply = await asyncio.wait_for(process_message(text, gitea_username), timeout=60.0)
|
||
await message.answer(reply or "Готово.")
|
||
except asyncio.TimeoutError:
|
||
await message.answer("Таймаут. Попробуй короче или позже.")
|
||
except Exception as e:
|
||
logger.exception("Handler error")
|
||
await message.answer(f"Ошибка: {e!s}")
|
||
|
||
|
||
@router.message(F.voice)
|
||
async def on_voice(message: Message) -> None:
|
||
if not message.voice:
|
||
return
|
||
gitea_username = get_gitea_username(
|
||
message.from_user.username if message.from_user else None,
|
||
message.from_user.id if message.from_user else None,
|
||
)
|
||
tmp = None
|
||
try:
|
||
file = await message.bot.get_file(message.voice.file_id)
|
||
tmp = tempfile.NamedTemporaryFile(suffix=".ogg", delete=False)
|
||
tmp.close()
|
||
await message.bot.download_file(file.file_path, tmp.name)
|
||
text = await asyncio.to_thread(transcribe_audio, tmp.name)
|
||
Path(tmp.name).unlink(missing_ok=True)
|
||
tmp = None
|
||
if not (text or "").strip():
|
||
await message.answer("Не удалось распознать речь.")
|
||
return
|
||
reply = await asyncio.wait_for(process_message(text.strip(), gitea_username), timeout=60.0)
|
||
await message.answer(reply or "Готово.")
|
||
except asyncio.TimeoutError:
|
||
await message.answer("Таймаут. Попробуй короче или позже.")
|
||
except Exception as e:
|
||
logger.exception("Voice handler error")
|
||
await message.answer(f"Ошибка: {e!s}")
|
||
finally:
|
||
if tmp is not None and getattr(tmp, "name", None):
|
||
Path(tmp.name).unlink(missing_ok=True)
|
||
|
||
|
||
async def main() -> None:
|
||
await dp.start_polling(bot)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(main())
|