From 712577e694d4f84c3925707aa8ff735a09485bba Mon Sep 17 00:00:00 2001 From: "Andrew K. Choi" Date: Mon, 17 Nov 2025 08:32:11 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=B0=D1=80=D1=81=D0=B8=D0=BD=D0=B3?= =?UTF-8?q?=20=D1=81=D1=87=D0=B5=D1=82=D0=BE=D0=B2=20=D0=B8=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=83=D0=B2=D0=B5?= =?UTF-8?q?=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B1=D0=B5=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8F=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Исправления: 1. Парсинг счетов (parse_accounts_from_message): - Исправлено дублирование счетов при формате 'КАРТА СЧЕТ' - Добавлены негативные lookbehind для корректного разбора - Теперь '2521 11-22-33-44-55-66-77' парсится только 1 раз 2. Уведомления победителям: - Создан новый модуль src/utils/notifications.py - Добавлена функция notify_winners_async() - Уведомления отправляются автоматически после розыгрыша - Поддержка счетов и обычных пользователей - Включает кнопки подтверждения для победителей по счетам --- .bot.pid | 2 +- src/handlers/admin_panel.py | 13 ++++ src/utils/account_utils.py | 18 ++--- src/utils/notifications.py | 138 ++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 src/utils/notifications.py diff --git a/.bot.pid b/.bot.pid index 1807423..0ba2bb9 100644 --- a/.bot.pid +++ b/.bot.pid @@ -1 +1 @@ -822376 +832585 diff --git a/src/handlers/admin_panel.py b/src/handlers/admin_panel.py index 670aa5a..ae73e16 100644 --- a/src/handlers/admin_panel.py +++ b/src/handlers/admin_panel.py @@ -1,6 +1,7 @@ """ Расширенная админ-панель для управления розыгрышами """ +import logging from aiogram import Router, F from aiogram.types import ( CallbackQuery, Message, InlineKeyboardButton, InlineKeyboardMarkup @@ -17,6 +18,8 @@ from ..core.services import UserService, LotteryService, ParticipationService from ..core.config import ADMIN_IDS from ..core.models import User, Lottery, Participation, Account +logger = logging.getLogger(__name__) + # Состояния для админки class AdminStates(StatesGroup): @@ -2620,6 +2623,14 @@ async def conduct_lottery_draw(callback: CallbackQuery): winners_dict = await LotteryService.conduct_draw(session, lottery_id) if winners_dict: + # Отправляем уведомления победителям + from ..utils.notifications import notify_winners_async + try: + await notify_winners_async(callback.bot, session, lottery_id) + logger.info(f"Уведомления отправлены для розыгрыша {lottery_id}") + except Exception as e: + logger.error(f"Ошибка при отправке уведомлений: {e}") + # Получаем победителей из базы winners = await LotteryService.get_winners(session, lottery_id) text = f"🎉 Розыгрыш '{lottery.title}' завершён!\n\n" @@ -2633,6 +2644,8 @@ async def conduct_lottery_draw(callback: CallbackQuery): else: text += f"{winner.place} место: ID {winner.user_id}\n" + text += "\n✅ Уведомления отправлены победителям" + await callback.message.edit_text( text, reply_markup=InlineKeyboardMarkup(inline_keyboard=[ diff --git a/src/utils/account_utils.py b/src/utils/account_utils.py index d2f4e01..e61974c 100644 --- a/src/utils/account_utils.py +++ b/src/utils/account_utils.py @@ -113,9 +113,11 @@ def parse_accounts_from_message(text: str) -> List[str]: return [] accounts = [] + found_accounts_only = set() # Для отслеживания уже найденных счетов # Паттерн 1: номер карты (4 цифры) + пробел + счет (7 пар цифр) - pattern_with_card = r'\b(\d{4})\s+(\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2})\b' + # Используем негативный lookbehind чтобы не ловить цифры перед картой + pattern_with_card = r'(? List[str]: full_account = f"{card} {formatted}" if full_account not in accounts: accounts.append(full_account) + found_accounts_only.add(formatted) # Запоминаем этот счет - # Паттерн 2: только счет (7 пар цифр) - для обратной совместимости - pattern_only_account = r'\b\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}\b' + # Паттерн 2: только счет (7 пар цифр) БЕЗ карты перед ним + # Негативный lookbehind для проверки что перед счетом нет "4 цифры + пробел" + pattern_only_account = r'(?