auto-sync: 2026-04-15 01:00:01
This commit is contained in:
121
tasks/bytik/bot.py
Normal file
121
tasks/bytik/bot.py
Normal 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("Бот остановлен")
|
||||
Reference in New Issue
Block a user