This commit is contained in:
2026-01-28 11:30:30 +03:00
commit 641b88138d
18 changed files with 1655 additions and 0 deletions

93
handlers/scheduler.py Normal file
View File

@ -0,0 +1,93 @@
"""Scheduler for daily birthday notifications."""
import telebot
from datetime import datetime
from typing import Optional
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
import pytz
from database import get_db_session, User, Chat, UserChat
from messages import format_birthday_greeting
from config import Config
def send_birthday_notifications(bot: telebot.TeleBot) -> None:
"""Send birthday notifications to all chats for users with birthday today."""
db = get_db_session()
try:
today = datetime.now().date()
day = today.day
month = today.month
# Get all users with birthday today
users_with_birthday = db.query(User).filter(
User.birthday_day == day,
User.birthday_month == month
).all()
if not users_with_birthday:
return
# For each user, send greetings to all their chats
for user in users_with_birthday:
# Get all chats where user is a member
user_chats = db.query(Chat).join(UserChat).filter(
UserChat.user_id == user.user_id,
Chat.bot_is_admin == True
).all()
greeting = format_birthday_greeting(user.first_name, user.preference_theme)
for chat in user_chats:
try:
# Check if user is still in chat
member = bot.get_chat_member(chat.chat_id, user.user_id)
if member.status not in ['left', 'kicked']:
bot.send_message(chat.chat_id, greeting)
except telebot.apihelper.ApiTelegramException as e:
# Handle errors: user blocked bot, bot removed from chat, etc.
if e.error_code == 403:
# Bot was blocked or removed from chat
# Update chat status
chat.bot_is_admin = False
db.commit()
elif e.error_code == 400:
# Invalid chat or user
pass
# Silently continue for other errors
except Exception:
# Other errors - continue
pass
finally:
db.close()
def setup_scheduler(bot: telebot.TeleBot) -> BlockingScheduler:
"""Setup and start the scheduler for daily birthday notifications."""
# Parse notification time
time_str: str = Config.NOTIFICATION_TIME
try:
hour, minute = map(int, time_str.split(':'))
except (ValueError, AttributeError):
hour, minute = 9, 0 # Default to 9:00
# Get timezone
timezone_str: str = Config.TIMEZONE
try:
tz = pytz.timezone(timezone_str)
except (pytz.exceptions.UnknownTimeZoneError, AttributeError):
tz = pytz.UTC
# Create scheduler
scheduler = BlockingScheduler(timezone=tz)
# Add daily job
scheduler.add_job(
send_birthday_notifications,
trigger=CronTrigger(hour=hour, minute=minute),
args=[bot],
id='daily_birthday_notifications',
name='Send daily birthday notifications',
replace_existing=True
)
return scheduler