import datetime import traceback from asyncio import sleep from aiogram import Bot from aiogram.exceptions import TelegramBadRequest from aiogram.types import ChatMemberBanned, ChatMemberLeft from aiogram.utils.formatting import Bold import tg.tg_database as database from tg.handlers.user import format_rating async def is_user_in_chat(bot: Bot, chat_id: int, user_id: int) -> bool: found = True try: info = await bot.get_chat_member(chat_id, user_id) if isinstance(info, ChatMemberLeft) or isinstance(info, ChatMemberBanned): found = False except TelegramBadRequest: found = False except Exception: pass return found async def cleanup_chats(bot: Bot): for chat in database.DB.get_chats(bot.id): chat_id = chat['chat_id'] if chat_id > 0: # TODO continue if not await is_user_in_chat(bot, chat_id, bot.id): database.DB.chat_delete(bot.id, chat_id) print(f"Чат (bot_id={bot.id}, chat_id={chat_id}) удален.") async def cleanup_users(bot: Bot): for chat in database.DB.get_chats(bot.id): if chat['active'] == 0: continue chat_id = chat['chat_id'] for user in database.DB.get_top_silent(bot_id=bot.id, chat_id=chat_id, threshold_days=14): user_id = user['user_id'] if not await is_user_in_chat(bot, chat_id, user_id): database.DB.delete_user(bot.id, chat_id, user_id) print(f'Из чата (bot_id={bot.id}, chat_id={chat_id}) удален пользователь (id={user_id})') async def reset_counters(reset_month: bool, bot: Bot): database.DB.reset_messages_today(bot.id) if not reset_month: return for chat in database.DB.get_chats(bot.id): if chat['active'] == 0: continue chat_id = chat['chat_id'] top_users = database.DB.get_top_messages_month(bot.id, chat['chat_id']) if len(top_users) == 0: continue message = Bold('Итоговая статистика за прошедший месяц') + '\n' message += await format_rating(chat_id, top_users, bot) await bot.send_message(chat_id=chat_id, **message.as_kwargs()) database.DB.reset_messages_month(bot.id) async def wait_until(target_time: datetime.datetime): now = datetime.datetime.now(target_time.tzinfo) if now >= target_time: return delay_seconds = (target_time - now).total_seconds() await sleep(delay_seconds) async def daily_maintenance_task(bot: Bot): tz = datetime.timezone(datetime.timedelta(hours=3), name="MSK") target_time = datetime.time(6, 0, 0, tzinfo=tz) now = datetime.datetime.now(tz) if now.hour > target_time.hour or now.hour == target_time.hour and now.minute > target_time.minute: target_date = now.date() + datetime.timedelta(days=1) else: target_date = now.date() target_datetime = datetime.datetime.combine(target_date, target_time) while True: await wait_until(target_datetime) try: await cleanup_chats(bot) except Exception: print(traceback.format_exc()) try: await cleanup_users(bot) except Exception: print(traceback.format_exc()) try: await reset_counters(target_datetime.day == 1, bot) except Exception: print(traceback.format_exc()) target_datetime = target_datetime + datetime.timedelta(days=1) async def startup_task(bot: Bot): me = await bot.get_me() print(f"Бот '{me.full_name}' (id={me.id}) запущен.")