import datetime import traceback from asyncio import sleep from vkbottle import API, bold from vkbottle_types.codegen.objects import UsersFields from messages import * import vk.vk_database as database from vk.handlers.user import format_rating from vk.utils import * async def cleanup_chats(api: API): # TODO pass async def cleanup_users(api: API): bot_id = get_bot_id(api) for chat in database.DB.get_chats(bot_id): if chat['active'] == 0: continue chat_id = chat['chat_id'] members = await api.messages.get_conversation_members(peer_id=chat_id, extended=False) for user in database.DB.get_top_silent(bot_id, chat_id, threshold_days=14): user_id = user['user_id'] found = False for item in members.items: if item.member_id == user_id: found = True break if not found: 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, api: API): bot_id = get_bot_id(api) 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_id) if len(top_users) == 0: continue message = bold('Итоговая статистика за прошедший месяц') + '\n' message += await format_rating(top_users, api) # noinspection PyArgumentList await api.messages.send(random_id=0, peer_id=chat_id, message=str(message), format_data=message.as_raw_data()) database.DB.reset_messages_month(bot_id) async def check_birthdays(api: API): bot_id = get_bot_id(api) chats = database.DB.get_chats(bot_id) for chat in chats: if chat['active'] == 0: continue chat_id = chat['chat_id'] members = await api.messages.get_conversation_members(peer_id=chat_id, extended=False, fields=[UsersFields.BDATE]) today = datetime.datetime.today() for item in members.items: user_id = item.member_id if user_id < 0: continue user = database.DB.create_user_if_not_exists(bot_id, chat_id, user_id) for profile in members.profiles: if profile.id == user_id: if profile.bdate is None or user['happy_birthday'] == 0: break parts = profile.bdate.split('.') if len(parts) < 2: break day = int(parts[0]) month = int(parts[1]) if day == today.day and month == today.month: message = chat['birthday_message'] or MESSAGE_DEFAULT_BIRTHDAY message = message.format(name=f'@id{user_id} ({profile.first_name} {profile.last_name})') await api.messages.send(random_id=0, peer_id=chat_id, message=message) break 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(api: API): 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(api) except Exception: print(traceback.format_exc()) try: await cleanup_users(api) except Exception: print(traceback.format_exc()) try: await reset_counters(target_datetime.day == 1, api) except Exception: print(traceback.format_exc()) try: await check_birthdays(api) except Exception: print(traceback.format_exc()) target_datetime = target_datetime + datetime.timedelta(days=1) async def startup_task(api: API): me = (await api.groups.get_by_id()).groups[0] print(f"Бот '{me.name}' (id={me.id}) запущен.")