auto-sync: 2026-04-15 01:00:01

This commit is contained in:
Stream
2026-04-15 01:00:01 +03:00
parent 2925fd8e0c
commit ebfbe7ffcd
11 changed files with 591 additions and 0 deletions

121
tasks/bytik/bot.py Normal file
View File

@@ -0,0 +1,121 @@
import asyncio
import logging
import os
from logging.handlers import RotatingFileHandler
from aiogram import Bot, Dispatcher, types
from aiogram.filters import Command
from aiogram.types import BotCommand
from config import BOT_TOKEN, ALLOWED_CHAT_ID
from prompts import SYSTEM_PROMPT
from llm import ask_llm
from chat_history import load_history, add_message
from scheduler import BytikScheduler
LOG_DIR = "logs"
os.makedirs(LOG_DIR, exist_ok=True)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[
RotatingFileHandler(
os.path.join(LOG_DIR, "bytik.log"),
maxBytes=5*1024*1024,
backupCount=3,
encoding="utf-8",
),
logging.StreamHandler(),
],
)
logger = logging.getLogger(__name__)
bot = Bot(token=BOT_TOKEN)
dp = Dispatcher()
scheduler = None
def is_allowed_chat(chat_id: int) -> bool:
return chat_id == ALLOWED_CHAT_ID
@dp.message(Command("start"))
async def cmd_start(message: types.Message):
if not is_allowed_chat(message.chat.id):
logger.warning(f"Попытка /start из неразрешённого чата: {message.chat.id}")
return
await message.answer("Привет, Егор! 👋 Я Байтик, твой робот-помощник! Спрашивай меня о чём угодно! 🤖")
@dp.message(Command("clear"))
async def cmd_clear(message: types.Message):
if not is_allowed_chat(message.chat.id):
return
from chat_history import clear_history
clear_history(message.from_user.id)
await message.answer("История наших разговоров очищена! 🧹")
@dp.message()
async def handle_message(message: types.Message):
if not message.text:
return
if not is_allowed_chat(message.chat.id):
logger.debug(f"Игнорирую сообщение из чата {message.chat.id}")
return
user_message = message.text.strip()
logger.info(f"Сообщение от user {message.from_user.id}: {user_message[:100]}")
typing_msg = await message.answer("Думаю... 🤔")
history = load_history(message.from_user.id)
messages_for_llm = [{"role": "system", "content": SYSTEM_PROMPT}] + history
messages_for_llm.append({"role": "user", "content": user_message})
add_message(message.from_user.id, "user", user_message)
answer = await ask_llm(messages_for_llm)
add_message(message.from_user.id, "assistant", answer)
try:
await typing_msg.edit_text(answer)
except Exception:
await message.answer(answer)
@dp.my_chat_member()
async def handle_bot_status_change(update: types.ChatMemberUpdated):
chat_id = update.chat.id
new_status = update.new_chat_member.status
if new_status == "member" and chat_id != ALLOWED_CHAT_ID:
logger.warning(f"Бот добавлен в неразрешённый чат {chat_id}. Покидаю.")
await bot.leave_chat(chat_id)
elif new_status == "left":
logger.info(f"Бот удалён из чата {chat_id}")
async def set_commands():
commands = [
BotCommand(command="start", description="Начать общение"),
BotCommand(command="clear", description="Очистить историю диалога"),
]
await bot.set_my_commands(commands)
async def main():
global scheduler
await set_commands()
scheduler = BytikScheduler(bot)
scheduler.start()
logger.info(f"Бот запущен. Whitelist chat_id: {ALLOWED_CHAT_ID}")
await dp.start_polling(bot)
async def on_shutdown():
if scheduler:
scheduler.shutdown()
await bot.session.close()
if __name__ == "__main__":
try:
asyncio.run(main())
except (KeyboardInterrupt, SystemExit):
logger.info("Бот остановлен")