|
| 1 | +"""Обработчики команд казино для групп.""" |
| 2 | + |
| 3 | +import asyncio |
| 4 | +import logging |
| 5 | +import re |
| 6 | + |
| 7 | +from aiogram import F, Router |
| 8 | +from aiogram.enums import DiceEmoji |
| 9 | +from aiogram.filters import Command |
| 10 | +from aiogram.types import Message |
| 11 | +from stp_database import Employee, MainRequestsRepo |
| 12 | + |
| 13 | +from tgbot.dialogs.events.common.game.casino import ( |
| 14 | + calculate_simple_multiplier, |
| 15 | + calculate_slots_multiplier, |
| 16 | + format_result, |
| 17 | +) |
| 18 | +from tgbot.filters.group_casino import IsGroupCasinoAllowed |
| 19 | + |
| 20 | +logger = logging.getLogger(__name__) |
| 21 | + |
| 22 | +group_casino_router = Router() |
| 23 | +group_casino_router.message.filter(F.chat.type.in_(("group", "supergroup"))) |
| 24 | + |
| 25 | + |
| 26 | +def parse_casino_command(message_text: str) -> int: |
| 27 | + """Извлечь ставку из команды казино. |
| 28 | +
|
| 29 | + Args: |
| 30 | + message_text: Текст команды (например, "/slots 50" или "/dice") |
| 31 | +
|
| 32 | + Returns: |
| 33 | + Размер ставки (минимум 10) |
| 34 | + """ |
| 35 | + # Паттерн для извлечения числа из команды |
| 36 | + match = re.search(r"/(?:slots|dice|darts|bowling)\s+(\d+)", message_text) |
| 37 | + if match: |
| 38 | + bet_amount = int(match.group(1)) |
| 39 | + return max(10, bet_amount) # Минимальная ставка 10 |
| 40 | + return 10 # Ставка по умолчанию |
| 41 | + |
| 42 | + |
| 43 | +async def process_casino_game( |
| 44 | + message: Message, |
| 45 | + user: Employee, |
| 46 | + stp_repo: MainRequestsRepo, |
| 47 | + game_type: str, |
| 48 | + dice_emoji: DiceEmoji, |
| 49 | + bet_amount: int, |
| 50 | +) -> None: |
| 51 | + """Обработать игру в казино. |
| 52 | +
|
| 53 | + Args: |
| 54 | + message: Сообщение от пользователя |
| 55 | + user: Экземпляр пользователя с моделью Employee |
| 56 | + stp_repo: Репозиторий операций с базой STP |
| 57 | + game_type: Тип игры (slots, dice, darts, bowling) |
| 58 | + dice_emoji: Emoji для dice API |
| 59 | + bet_amount: Размер ставки |
| 60 | + """ |
| 61 | + try: |
| 62 | + # Проверяем баланс |
| 63 | + user_balance = await stp_repo.transaction.get_user_balance(user.user_id) |
| 64 | + |
| 65 | + if user_balance < bet_amount: |
| 66 | + await message.reply( |
| 67 | + f"❌ Недостаточно баллов для игры!\n" |
| 68 | + f"💰 Твой баланс: {user_balance} баллов\n" |
| 69 | + f"🎲 Нужно для ставки: {bet_amount} баллов" |
| 70 | + ) |
| 71 | + return |
| 72 | + |
| 73 | + # Отправляем dice и ждем результата |
| 74 | + dice_message = await message.reply_dice(emoji=dice_emoji) |
| 75 | + dice_value = dice_message.dice.value |
| 76 | + |
| 77 | + # Ждем анимацию (3 секунды) |
| 78 | + await asyncio.sleep(3) |
| 79 | + |
| 80 | + # Рассчитываем выигрыш |
| 81 | + if game_type == "slots": |
| 82 | + multiplier = calculate_slots_multiplier(dice_value) |
| 83 | + else: |
| 84 | + multiplier = calculate_simple_multiplier(dice_value) |
| 85 | + |
| 86 | + # Вычисляем чистый выигрыш/проигрыш |
| 87 | + if multiplier > 0: |
| 88 | + gross_win = int(bet_amount * multiplier) |
| 89 | + net_win = gross_win - bet_amount |
| 90 | + else: |
| 91 | + net_win = -bet_amount |
| 92 | + |
| 93 | + # Обновляем баланс |
| 94 | + if net_win > 0: |
| 95 | + await stp_repo.transaction.add_transaction( |
| 96 | + user_id=user.user_id, |
| 97 | + transaction_type="earn", |
| 98 | + source_type="casino", |
| 99 | + amount=net_win, |
| 100 | + comment=f"Выигрыш в {game_type}: {dice_value} (ставка {bet_amount})", |
| 101 | + ) |
| 102 | + elif net_win < 0: |
| 103 | + await stp_repo.transaction.add_transaction( |
| 104 | + user_id=user.user_id, |
| 105 | + transaction_type="spend", |
| 106 | + source_type="casino", |
| 107 | + amount=abs(net_win), |
| 108 | + comment=f"Проигрыш в {game_type}: {dice_value} (ставка {bet_amount})", |
| 109 | + ) |
| 110 | + |
| 111 | + # Получаем новый баланс |
| 112 | + new_balance = await stp_repo.transaction.get_user_balance(user.user_id) |
| 113 | + |
| 114 | + # Формируем сообщение о результате используя общую функцию |
| 115 | + result_data = format_result(game_type, dice_value, multiplier, net_win) |
| 116 | + |
| 117 | + # Дополняем информацией о ставке и балансе для групповых команд |
| 118 | + message_parts = [ |
| 119 | + f"{result_data['result_icon']} <b>{result_data['result_title']}</b>", |
| 120 | + result_data["result_message"], |
| 121 | + ] |
| 122 | + |
| 123 | + # Информация о ставке и выигрыше |
| 124 | + if net_win > 0: |
| 125 | + message_parts.append(f"\n💰 <b>Выиграно:</b> +{net_win} баллов") |
| 126 | + elif net_win < 0: |
| 127 | + message_parts.append(f"\n💸 <b>Проиграно:</b> {abs(net_win)} баллов") |
| 128 | + |
| 129 | + message_parts.append(f"\n🎯 <b>Ставка:</b> {bet_amount} баллов") |
| 130 | + message_parts.append(f"\n\n💳 <b>Баланс:</b> {new_balance} баллов") |
| 131 | + |
| 132 | + result_message = "\n".join(message_parts) |
| 133 | + |
| 134 | + await dice_message.reply(result_message) |
| 135 | + |
| 136 | + # Логируем игру |
| 137 | + user_name = ( |
| 138 | + user.fullname |
| 139 | + if user |
| 140 | + else f"@{message.from_user.username}" |
| 141 | + if message.from_user.username |
| 142 | + else message.from_user.full_name |
| 143 | + ) |
| 144 | + logger.info( |
| 145 | + f"[Casino/{game_type}] {user_name} ({user.user_id}) играл с ставкой {bet_amount}, " |
| 146 | + f"результат {dice_value}, выигрыш {net_win}" |
| 147 | + ) |
| 148 | + |
| 149 | + except Exception as e: |
| 150 | + logger.error(f"Ошибка в казино {game_type}: {e}") |
| 151 | + await message.reply("🚨 Произошла ошибка при игре в казино. Попробуй позже.") |
| 152 | + |
| 153 | + |
| 154 | +@group_casino_router.message(Command("slots"), IsGroupCasinoAllowed()) |
| 155 | +async def slots_cmd(message: Message, user: Employee, stp_repo: MainRequestsRepo): |
| 156 | + """Обработчик команды /slots для групп. |
| 157 | +
|
| 158 | + Args: |
| 159 | + message: Сообщение от пользователя |
| 160 | + user: Экземпляр пользователя с моделью Employee |
| 161 | + stp_repo: Репозиторий операций с базой STP |
| 162 | + """ |
| 163 | + bet_amount = parse_casino_command(message.text) |
| 164 | + await process_casino_game( |
| 165 | + message, user, stp_repo, "slots", DiceEmoji.SLOT_MACHINE, bet_amount |
| 166 | + ) |
| 167 | + |
| 168 | + |
| 169 | +@group_casino_router.message(Command("dice"), IsGroupCasinoAllowed()) |
| 170 | +async def dice_cmd(message: Message, user: Employee, stp_repo: MainRequestsRepo): |
| 171 | + """Обработчик команды /dice для групп. |
| 172 | +
|
| 173 | + Args: |
| 174 | + message: Сообщение от пользователя |
| 175 | + user: Экземпляр пользователя с моделью Employee |
| 176 | + stp_repo: Репозиторий операций с базой STP |
| 177 | + """ |
| 178 | + bet_amount = parse_casino_command(message.text) |
| 179 | + await process_casino_game( |
| 180 | + message, user, stp_repo, "dice", DiceEmoji.DICE, bet_amount |
| 181 | + ) |
| 182 | + |
| 183 | + |
| 184 | +@group_casino_router.message(Command("darts"), IsGroupCasinoAllowed()) |
| 185 | +async def darts_cmd(message: Message, user: Employee, stp_repo: MainRequestsRepo): |
| 186 | + """Обработчик команды /darts для групп. |
| 187 | +
|
| 188 | + Args: |
| 189 | + message: Сообщение от пользователя |
| 190 | + user: Экземпляр пользователя с моделью Employee |
| 191 | + stp_repo: Репозиторий операций с базой STP |
| 192 | + """ |
| 193 | + bet_amount = parse_casino_command(message.text) |
| 194 | + await process_casino_game( |
| 195 | + message, user, stp_repo, "darts", DiceEmoji.DART, bet_amount |
| 196 | + ) |
| 197 | + |
| 198 | + |
| 199 | +@group_casino_router.message(Command("bowling"), IsGroupCasinoAllowed()) |
| 200 | +async def bowling_cmd(message: Message, user: Employee, stp_repo: MainRequestsRepo): |
| 201 | + """Обработчик команды /bowling для групп. |
| 202 | +
|
| 203 | + Args: |
| 204 | + message: Сообщение от пользователя |
| 205 | + user: Экземпляр пользователя с моделью Employee |
| 206 | + stp_repo: Репозиторий операций с базой STP |
| 207 | + """ |
| 208 | + bet_amount = parse_casino_command(message.text) |
| 209 | + await process_casino_game( |
| 210 | + message, user, stp_repo, "bowling", DiceEmoji.BOWLING, bet_amount |
| 211 | + ) |
0 commit comments