Files
umb/main.py
T
Галингер Р.С. 0f674f8832 refactor: review fixes and code improvements
- Add shared proxy module (bot/utils/proxy.py) to eliminate duplicate SOCKS5 parsing
- Fix AI client: escape HTML before Markdown→HTML conversion, unify timeouts,
  make health check optional and disabled by default, handle 429 retries
- Fix ai.py: correct forwarded message handling (aiogram 3.x forward_origin),
  pass relevant summaries via extra_system_content
- Fix dialogue.py: only respond to Astra's messages, use system context instead
  of prompt injection, answer on the limit message before phase transition
- Fix voice.py: load Whisper model in thread pool, safe WAV path generation
- Improve database.py: composite indexes, Boolean is_active, upsert file_id cache,
  add context cleanup helper
- Update weather.py and yadisk_download.py to use shared proxy connector
- Update yadisk.py: validate URL before cache clear, add download size limit,
  wrap sync file ops in to_thread
- Reuse S3 client via lru_cache
- Update setup_commands with /aiclear and /aiuser
- Update README, Dockerfile (Python 3.11), docker-compose (mount models)
- Pin dependency versions, remove unused httpx[socks]
- Add basic pytest tests for layout converter and voice normalization
2026-07-07 18:42:10 +07:00

90 lines
2.9 KiB
Python

import asyncio
import logging
from aiogram.exceptions import TelegramNetworkError
from aiohttp import ClientConnectionError
from aiogram import F
from aiogram.types import Message
from aiogram.dispatcher.event.bases import SkipHandler
from bot.bot import dp, bot, setup_proxy
from bot.routers import moderation, layout, weather, ai, voice, yadisk, dialogue
from bot.utils.database import init_db, save_chat_user
from bot.utils.ai_client import start_model_health_check
from bot.utils.logging_config import setup_logging
from bot.setup_commands import setup_bot_commands
from config import PROXY_ENABLED
setup_logging()
logger = logging.getLogger(__name__)
# Router order matters: moderation first so it can delete messages before others process them.
dp.include_router(moderation.router)
dp.include_router(layout.router)
dp.include_router(weather.router)
dp.include_router(ai.router)
dp.include_router(voice.router)
dp.include_router(yadisk.router)
dp.include_router(dialogue.router)
@dp.message(F.text)
async def save_user_info(message: Message):
try:
await save_chat_user(
message.from_user.id,
message.chat.id,
message.from_user.username,
message.from_user.full_name or "",
)
except Exception as exc:
logger.warning("Failed to save chat user: %s", exc)
raise SkipHandler
async def main():
await init_db()
logging.info("База данных инициализирована")
await setup_bot_commands()
health_check_task = asyncio.create_task(start_model_health_check())
try:
if PROXY_ENABLED:
await setup_proxy()
else:
me = await bot.me()
logging.info("Бот запущен без прокси: @%s", me.username)
except TelegramNetworkError:
if PROXY_ENABLED:
logging.error("Не могу соединиться с прокси сервером. Попробуй другой прокси.")
else:
logging.error("Не могу соединиться с Telegram. Проверь интернет-соединение.")
health_check_task.cancel()
return
except ClientConnectionError:
if PROXY_ENABLED:
logging.error("Не могу соединиться с прокси сервером. Попробуй другой прокси.")
else:
logging.error("Не могу соединиться с Telegram. Проверь интернет-соединение.")
health_check_task.cancel()
return
except Exception as exc:
logging.error("Ошибка при запуске бота: %s", exc)
health_check_task.cancel()
return
try:
await dp.start_polling(bot)
finally:
health_check_task.cancel()
try:
await health_check_task
except asyncio.CancelledError:
pass
if __name__ == "__main__":
asyncio.run(main())