import re from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton from telegram.ext import ContextTypes from asgiref.sync import sync_to_async from webapp.models import BindingRequest, Client, Invoice from draw.models import DrawResult from bot.state import BINDING_PENDING from bot.models import BotConfig @sync_to_async def get_client_by_telegram_id(telegram_id: int): try: return Client.objects.get(telegram_id=str(telegram_id)) except Client.DoesNotExist: return None @sync_to_async def get_invoices_for_client(client): return list(Invoice.objects.filter(client_club_card_number=client.club_card_number)) @sync_to_async def get_draws_for_client(client): return list( DrawResult.objects.filter(participant__invoice__client_club_card_number=client.club_card_number) .select_related('lottery', 'prize', 'participant__invoice') ) @sync_to_async def create_binding_request(telegram_chat_id, client_card): return BindingRequest.objects.create( telegram_chat_id=str(telegram_chat_id), client_card=client_card ) async def whoami(update: Update, context: ContextTypes.DEFAULT_TYPE): if not update.message: return chat_id = update.message.chat_id client = await get_client_by_telegram_id(chat_id) if not client: await update.message.reply_text( "❌ Пользователь не найден. Возможно, Вы ещё не привязали свою клубную карту." ) return invoices = await get_invoices_for_client(client) draws = await get_draws_for_client(client) message_text = f"👤 *Профиль клиента:*\n" \ f"• *Имя:* {client.name}\n" \ f"• *Клубная карта:* {client.club_card_number}\n\n" message_text += "💳 *Счета:*\n" if invoices: show_all = len(invoices) > 5 displayed_invoices = invoices[:5] if show_all else invoices for inv in displayed_invoices: message_text += f" • ID {inv.id} (*{inv.sum}*)\n" else: message_text += " _Нет счетов_\n" message_text += "\n🎉 *Розыгрыши и выигранные призы:*\n" if draws: for draw in draws: lottery_name = draw.lottery.name if draw.lottery else "неизвестно" invoice_info = getattr(draw.participant.invoice, 'id', 'неизвестно') if draw.participant else 'неизвестно' prize_info = getattr(draw.prize, 'reward', 'неизвестно') message_text += f" • Лотерея: *{lottery_name}*\n Счет: _{invoice_info}_\n Выигрыш: *{prize_info}*\n\n" else: message_text += " _Нет результатов розыгрышей_\n" reply_markup = None if invoices and len(invoices) > 5: reply_markup = InlineKeyboardMarkup([ [InlineKeyboardButton("Показать все счета", callback_data="show_all_invoices")] ]) await update.message.reply_text(message_text, parse_mode="Markdown", reply_markup=reply_markup) async def handle_client_card(update: Update, context: ContextTypes.DEFAULT_TYPE): if not update.message: return telegram_chat_id = update.message.chat_id client = await get_client_by_telegram_id(telegram_chat_id) if client: await update.message.reply_text("✅ Вы уже привязаны!") return BINDING_PENDING.add(telegram_chat_id) await update.message.reply_text("Введите номер вашей клубной карты (КК):") await send_event_message("binding_started", update, context) async def process_binding_input(update: Update, context: ContextTypes.DEFAULT_TYPE): if not update.message or not update.message.text: return client_card = update.message.text.strip() telegram_chat_id = update.message.chat_id if not re.fullmatch(r'\d{3,}', client_card): await update.message.reply_text("❌ Неверный формат клиентской карты. Пожалуйста, введите минимум 3 цифры.") return await create_binding_request(telegram_chat_id, client_card) BINDING_PENDING.discard(telegram_chat_id) await update.message.reply_text("✅ Заявка отправлена. После подтверждения вы сможете участвовать в чате.") async def show_all_invoices_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): query = update.callback_query await query.answer() chat_id = query.message.chat_id client = await get_client_by_telegram_id(chat_id) if not client: await query.edit_message_text("❌ Пользователь не найден. Возможно, Вы ещё не привязали свою клубную карту.") return invoices = await get_invoices_for_client(client) message_text = "💳 *Все счета:*\n" if invoices: for inv in invoices: message_text += f" • ID {inv.ext_id} (*{inv.sum}*)\n" else: message_text += " _Нет счетов_\n" await query.edit_message_text(message_text, parse_mode="Markdown") async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): if not update.message: return bot_config = await sync_to_async(BotConfig.objects.filter(is_active=True).first)() if bot_config and bot_config.active_welcome: await update.message.reply_text(bot_config.active_welcome.welcome_message) else: await update.message.reply_text("Привет! Бот работает.")