Files
bdbot/handlers/command_handlers.py
T
2026-01-28 12:47:48 +03:00

179 lines
8.0 KiB
Python

"""Handlers for group commands."""
import telebot
from datetime import datetime, timedelta, date
from typing import Dict, List
from sqlalchemy.orm import Session
from database import get_db_session, User, Chat, UserChat
from collections import defaultdict
def register_command_handlers(bot: telebot.TeleBot) -> None:
"""Register all command handlers."""
@bot.message_handler(commands=['stats'], chat_types=['group', 'supergroup'])
def handle_stats(message: telebot.types.Message) -> None:
"""Handle /stats command - show statistics."""
chat_id = message.chat.id
db = get_db_session()
try:
# Check if bot is admin
chat = db.query(Chat).filter(Chat.chat_id == chat_id).first()
if not chat or not chat.bot_is_admin:
bot.reply_to(message, "Мне нужны права администратора для выполнения этой команды.")
return
# Get total members count (exclude bots)
try:
total_members_raw = bot.get_chat_member_count(chat_id)
# Try to subtract all bots (including this bot) using admin list
human_members = total_members_raw
try:
admins = bot.get_chat_administrators(chat_id)
bots_in_admins = sum(1 for m in admins if getattr(m.user, "is_bot", False))
human_members = max(total_members_raw - bots_in_admins, 0)
except Exception:
human_members = total_members_raw
total_members = human_members
except Exception:
total_members = 0
# Get users who shared birthday
users_with_birthday = db.query(User).join(UserChat).filter(
UserChat.chat_id == chat_id
).distinct().count()
users_without_birthday = max(total_members - users_with_birthday, 0)
# Format message
if total_members > 0:
percentage = (users_with_birthday / total_members) * 100
stats_text = (
f"📊 Статистика чата:\n\n"
f"• Всего участников: {total_members}\n"
f"• Поделились днем рождения: {users_with_birthday}\n"
f"• Не поделились: {users_without_birthday}\n"
f"• Процент: {percentage:.1f}%"
)
else:
stats_text = (
f"📊 Статистика чата:\n\n"
f"• Поделились днем рождения: {users_with_birthday}"
)
bot.reply_to(message, stats_text)
finally:
db.close()
@bot.message_handler(commands=['week'], chat_types=['group', 'supergroup'])
def handle_week(message: telebot.types.Message) -> None:
"""Handle /week command - show birthdays for next 7 days."""
chat_id = message.chat.id
db = get_db_session()
try:
# Check if bot is admin
chat = db.query(Chat).filter(Chat.chat_id == chat_id).first()
if not chat or not chat.bot_is_admin:
bot.reply_to(message, "Мне нужны права администратора для выполнения этой команды.")
return
# Get birthdays for next 7 days
today = datetime.now().date()
birthdays = get_birthdays_in_range(db, chat_id, today, days=7)
if not birthdays:
bot.reply_to(message, "На ближайшие 7 дней дней рождений не запланировано.")
return
# Format message
message_text = "🎂 Дни рождения на ближайшие 7 дней:\n\n"
for date_str, names in sorted(birthdays.items()):
names_list = ", ".join(names)
message_text += f"• {date_str}: {names_list}\n"
bot.reply_to(message, message_text)
finally:
db.close()
@bot.message_handler(commands=['month'], chat_types=['group', 'supergroup'])
def handle_month(message: telebot.types.Message) -> None:
"""Handle /month command - show birthdays for next 30 days."""
chat_id = message.chat.id
db = get_db_session()
try:
# Check if bot is admin
chat = db.query(Chat).filter(Chat.chat_id == chat_id).first()
if not chat or not chat.bot_is_admin:
bot.reply_to(message, "Мне нужны права администратора для выполнения этой команды.")
return
# Get birthdays for next 30 days
today = datetime.now().date()
birthdays = get_birthdays_in_range(db, chat_id, today, days=30)
if not birthdays:
bot.reply_to(message, "На ближайшие 30 дней дней рождений не запланировано.")
return
# Format message
message_text = "🎂 Дни рождения на ближайшие 30 дней:\n\n"
for date_str, names in sorted(birthdays.items()):
names_list = ", ".join(names)
message_text += f"• {date_str}: {names_list}\n"
bot.reply_to(message, message_text)
finally:
db.close()
@bot.message_handler(commands=['help'], chat_types=['group', 'supergroup'])
def handle_help(message: telebot.types.Message) -> None:
"""Handle /help command - show help message."""
help_text = (
"📚 Команды бота:\n\n"
"/stats - Показать статистику: сколько человек поделились днем рождения\n"
"/week - Показать дни рождения на ближайшие 7 дней\n"
"/month - Показать дни рождения на ближайшие 30 дней\n"
"/help - Показать это сообщение\n\n"
"Чтобы поделиться своим днем рождения, напиши боту в личку /start\n\n"
"from olly & cursor with <3"
)
bot.reply_to(message, help_text)
def get_birthdays_in_range(db: Session, chat_id: int, start_date: date, days: int) -> Dict[str, List[str]]:
"""Get birthdays in the specified date range for users in the chat."""
birthdays = defaultdict(list)
# Get all users in this chat
users = db.query(User).join(UserChat).filter(
UserChat.chat_id == chat_id
).distinct().all()
end_date = start_date + timedelta(days=days)
for user in users:
# Create birthday date for current year
try:
birthday_this_year = datetime(start_date.year, user.birthday_month, user.birthday_day).date()
except ValueError:
# Invalid date (e.g., Feb 29 in non-leap year)
continue
# Check if birthday falls in range
if start_date <= birthday_this_year < end_date:
date_str = f"{user.birthday_day:02d}.{user.birthday_month:02d}"
birthdays[date_str].append(user.first_name)
else:
# Check next year if we're near year end
try:
birthday_next_year = datetime(start_date.year + 1, user.birthday_month, user.birthday_day).date()
if start_date <= birthday_next_year < end_date:
date_str = f"{user.birthday_day:02d}.{user.birthday_month:02d}"
birthdays[date_str].append(user.first_name)
except ValueError:
pass
return birthdays