Stabilize staff concurrency and premium emoji; enable verified Drone deployment
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2026-09-13 19:48:41 +09:00
parent 733298bf06
commit cb35bb12e3
86 changed files with 2993 additions and 2455 deletions

View File

@@ -1,4 +1,5 @@
"""Админские обработчики для управления счетами и верификации"""
from src.utils.errors import public_error
from aiogram import Router, F, Bot
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.filters import Command
@@ -12,7 +13,7 @@ from src.core.registration_services import AccountService, WinnerNotificationSer
from src.core.services import UserService, LotteryService, ParticipationService
from src.core.models import User, Winner, Account, Participation
from src.core.config import ADMIN_IDS
from src.core.permissions import admin_only
from src.core.access import staff_only
router = Router()
@@ -24,7 +25,7 @@ class AddAccountStates(StatesGroup):
@router.message(CaseInsensitiveCommand("cancel"))
@admin_only
@staff_only
async def cancel_command(message: Message, state: FSMContext):
"""Отменить текущую операцию и сбросить состояние (регистронезависимо)"""
await state.clear()
@@ -32,7 +33,7 @@ async def cancel_command(message: Message, state: FSMContext):
@router.message(CaseInsensitiveCommand("add_account"))
@admin_only
@staff_only
async def add_account_command(message: Message, state: FSMContext):
"""
Добавить счет пользователю по клубной карте (регистронезависимо)
@@ -107,7 +108,7 @@ async def process_single_account(message: Message, club_card: str, account_numbe
)
text += "📨 Владельцу отправлено уведомление\n\n"
except Exception as e:
text += f"⚠️ Не удалось отправить уведомление: {str(e)}\n\n"
text += f"⚠️ Не удалось отправить уведомление: {public_error(e)}\n\n"
# Предлагаем добавить в розыгрыш
await show_lottery_selection(message, text, state)
@@ -116,11 +117,11 @@ async def process_single_account(message: Message, club_card: str, account_numbe
await message.answer(f"❌ Ошибка: {str(e)}")
await state.clear()
except Exception as e:
await message.answer(f"❌ Произошла ошибка: {str(e)}")
await message.answer(f"❌ Произошла ошибка: {public_error(e)}")
await state.clear()
@router.message(AddAccountStates.waiting_for_data)
@router.message(AddAccountStates.waiting_for_data, F.text)
async def process_accounts_data(message: Message, state: FSMContext):
"""Обработка данных счетов (один или несколько)"""
if message.text.strip().lower() == '/cancel':
@@ -220,7 +221,7 @@ async def process_accounts_data(message: Message, state: FSMContext):
except ValueError as e:
errors.append(f"Счет {account_number} (карта {club_card}): {str(e)}")
except Exception as e:
errors.append(f"Счет {account_number}: {str(e)}")
errors.append(f"Счет {account_number}: {public_error(e)}")
i += 1
@@ -383,36 +384,10 @@ async def add_accounts_to_lottery(callback: CallbackQuery, state: FSMContext):
await state.clear()
return
for acc in accounts:
try:
# Добавляем участие через account_id
# Проверяем, не участвует ли уже
existing = await session.execute(
select(Participation).where(
and_(
Participation.lottery_id == lottery_id,
Participation.account_id == acc['account_id']
)
)
)
if existing.scalar_one_or_none():
errors.append(f"{acc['account_number']}: уже участвует")
continue
# Создаем участие
participation = Participation(
lottery_id=lottery_id,
account_id=acc['account_id'],
account_number=acc['account_number']
)
session.add(participation)
success_count += 1
except Exception as e:
errors.append(f"{acc['account_number']}: {str(e)}")
await session.commit()
from .account_services import AccountParticipationService
result = await AccountParticipationService.add_accounts_bulk(session, lottery_id, [a['account_number'] for a in accounts])
success_count = result['added']
errors = result['errors']
text = f"📊 **Добавление в розыгрыш '{lottery.title}'**\n\n"
@@ -436,7 +411,7 @@ async def skip_lottery_add(callback: CallbackQuery, state: FSMContext):
@router.message(CaseInsensitiveCommand("remove_account"))
@admin_only
@staff_only
async def remove_account_command(message: Message):
"""
Деактивировать счет(а) (регистронезависимо)
@@ -502,11 +477,11 @@ async def remove_account_command(message: Message):
await message.answer("\n\n".join(response_parts), parse_mode="Markdown")
except Exception as e:
await message.answer(f"❌ Критическая ошибка: {str(e)}")
await message.answer(f"❌ Критическая ошибка: {public_error(e)}")
@router.message(CaseInsensitiveCommand("verify_winner"))
@admin_only
@staff_only
async def verify_winner_command(message: Message):
"""
Подтвердить выигрыш по коду верификации (регистронезависимо)
@@ -585,7 +560,7 @@ async def verify_winner_command(message: Message):
)
text += "\n📨 Победителю отправлено уведомление"
except Exception as e:
text += f"\n⚠️ Не удалось отправить уведомление: {str(e)}"
text += f"\n⚠️ Не удалось отправить уведомление: {public_error(e)}"
if winner.account_number:
text += f"💳 Счет: {winner.account_number}\n"
@@ -593,11 +568,11 @@ async def verify_winner_command(message: Message):
await message.answer(text)
except Exception as e:
await message.answer(f"❌ Ошибка: {str(e)}")
await message.answer(f"❌ Ошибка: {public_error(e)}")
@router.message(CaseInsensitiveCommand("winner_status"))
@admin_only
@staff_only
async def winner_status_command(message: Message):
"""
Показать статус всех победителей розыгрыша (регистронезависимо)
@@ -666,11 +641,11 @@ async def winner_status_command(message: Message):
await message.answer(text)
except Exception as e:
await message.answer(f"❌ Ошибка: {str(e)}")
await message.answer(f"❌ Ошибка: {public_error(e)}")
@router.message(CaseInsensitiveCommand("user_info"))
@admin_only
@staff_only
async def user_info_command(message: Message):
"""
Показать информацию о пользователе (регистронезависимо)
@@ -741,7 +716,7 @@ async def user_info_command(message: Message):
await message.answer(text)
except Exception as e:
await message.answer(f"❌ Ошибка: {str(e)}")
await message.answer(f"❌ Ошибка: {public_error(e)}")
@router.callback_query(F.data == "view_my_accounts")
@@ -807,6 +782,6 @@ async def view_my_accounts_callback(callback: CallbackQuery):
except Exception as e:
# Не используем callback.answer в except - может быть timeout
try:
await callback.message.answer(f"❌ Ошибка: {str(e)}")
await callback.message.answer(f"❌ Ошибка: {public_error(e)}")
except:
pass # Игнорируем если не получилось отправить