vk_chat_bot/tasks.py
Kirill Kirilenko ecfc83d5ad Исправлено добавление в БД левых пользователей, которые VK может вернуть в списке profiles.
При выбрасывании исключения в daily_maintenance_task работа продолжается.
2025-08-29 16:03:25 +03:00

89 lines
2.8 KiB
Python

import datetime
import traceback
from asyncio import sleep
from vkbottle import API
import database
from messages import *
def reset_counters(reset_month: bool):
database.DB.reset_messages_today()
print('Дневные счетчики сброшены.')
if reset_month:
database.DB.reset_messages_month()
print('Месячные счетчики сброшены.')
async def check_birthdays(api: API):
chats = database.DB.get_chats()
for chat in chats:
if chat['active'] == 0:
continue
chat_id = chat['id']
members = await api.messages.get_conversation_members(peer_id=chat_id, extended=False, fields=['bdate'])
today = datetime.datetime.today()
for item in members.items:
user_id = item.member_id
if user_id < 0:
continue
user = database.create_user_if_not_exists(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:
reset_counters(target_datetime.day == 1)
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}) запущен.")