| """
|
| Fun cog: Games, trivia, memes, and entertainment commands.
|
| Enhanced with rich emoji decorations, beautiful formatting, and multi-language support.
|
| """
|
|
|
| import html
|
| import random
|
|
|
| import aiohttp
|
| import discord
|
| from discord.ext import commands
|
|
|
| from bot.cogs.ai_suite import ImperialMotaz
|
| from bot.theme import (
|
| fancy_header, NEON_CYAN, NEON_PINK, NEON_PURPLE, NEON_LIME, NEON_ORANGE, NEON_BLUE,
|
| panel_divider, gaming_embed, success_embed, error_embed, info_embed,
|
| double_line, triple_line, shimmer, pick_neon_color
|
| )
|
| from bot.i18n import get_cmd_desc
|
| from bot.emojis import (
|
| ui, E_GAMEHUB, E_ARROW_PINK, E_ARROW_GREEN, E_ARROW_PURPLE, E_STAR,
|
| E_TROPHY, E_FIRE, E_SPARKLE, E_DIZZY, E_BOOM, E_ZAP, E_DIAMOND, E_CROWN, E_GEM
|
| )
|
| from bot.utils.shared import fetch_gaming_news, fetch_free_games, store_icon, FreeGameClaimView
|
|
|
|
|
| TRIVIA_BANK: dict[str, dict[str, list[dict[str, object]]]] = {
|
| "en": {
|
| "gaming": [
|
| {"q": "Which studio created The Witcher 3?", "c": ["CD Projekt Red", "Rockstar", "Ubisoft", "Bethesda"], "a": 0},
|
| {"q": "What is the default block in Minecraft?", "c": ["Stone", "Dirt", "Grass Block", "Sand"], "a": 2},
|
| {"q": "In which game would you find Master Chief?", "c": ["Halo", "Destiny", "Call of Duty", "Gears of War"], "a": 0},
|
| {"q": "What year was Fortnite released?", "c": ["2015", "2017", "2018", "2019"], "a": 1},
|
| {"q": "Which company makes the PlayStation?", "c": ["Microsoft", "Nintendo", "Sony", "Sega"], "a": 2},
|
| ],
|
| "movies": [
|
| {"q": "Who directed Inception?", "c": ["Christopher Nolan", "James Cameron", "Denis Villeneuve", "Ridley Scott"], "a": 0},
|
| {"q": "In the MCU, who is Peter Parker?", "c": ["Iron Man", "Spider-Man", "Doctor Strange", "Hawkeye"], "a": 1},
|
| {"q": "What is the highest-grossing film of all time?", "c": ["Avengers: Endgame", "Avatar", "Titanic", "Star Wars"], "a": 1},
|
| {"q": "Who played the Joker in The Dark Knight?", "c": ["Joaquin Phoenix", "Jack Nicholson", "Heath Ledger", "Jared Leto"], "a": 2},
|
| ],
|
| "series": [
|
| {"q": "Which series features Walter White?", "c": ["Narcos", "Breaking Bad", "Dark", "Sherlock"], "a": 1},
|
| {"q": "In Game of Thrones, what is Jon Snow's house at first?", "c": ["Lannister", "Baratheon", "Stark", "Targaryen"], "a": 2},
|
| {"q": "What is the name of the coffee shop in Friends?", "c": ["Central Park", "Central Perk", "Coffee House", "The Brew"], "a": 1},
|
| {"q": "How many seasons does Stranger Things have?", "c": ["3", "4", "5", "6"], "a": 2},
|
| ],
|
| },
|
| "ar": {
|
| "gaming": [
|
| {"q": "ุฃู ุดุฑูุฉ ุทูุฑุช ูุนุจุฉ The Witcher 3ุ", "c": ["CD Projekt Red", "Rockstar", "Ubisoft", "Bethesda"], "a": 0},
|
| {"q": "ู
ุง ูู ุงูุจููู ุงูุงูุชุฑุงุถู ูู Minecraftุ", "c": ["Stone", "Dirt", "Grass Block", "Sand"], "a": 2},
|
| {"q": "ูู ุฃู ูุนุจุฉ ุชุฌุฏ Master Chiefุ", "c": ["Halo", "Destiny", "Call of Duty", "Gears of War"], "a": 0},
|
| {"q": "ู
ุชู ุตุฏุฑุช Fortniteุ", "c": ["2015", "2017", "2018", "2019"], "a": 1},
|
| ],
|
| "movies": [
|
| {"q": "ู
ู ู
ุฎุฑุฌ ูููู
Inceptionุ", "c": ["ูุฑูุณุชููุฑ ูููุงู", "ุฌูู
ุณ ูุงู
ูุฑูู", "ุฏูููุณ ูููููู", "ุฑูุฏูู ุณููุช"], "a": 0},
|
| {"q": "ูู ุนุงูู
ู
ุงุฑููุ ุจูุชุฑ ุจุงุฑูุฑ ููุ", "c": ["Iron Man", "Spider-Man", "Doctor Strange", "Hawkeye"], "a": 1},
|
| {"q": "ู
ุง ูู ุฃุนูู ูููู
ุฅูุฑุงุฏุงุช ูู ุงูุชุงุฑูุฎุ", "c": ["Avengers: Endgame", "Avatar", "Titanic", "Star Wars"], "a": 1},
|
| ],
|
| "series": [
|
| {"q": "ุฃู ู
ุณูุณู ูุธูุฑ ููู Walter Whiteุ", "c": ["Narcos", "Breaking Bad", "Dark", "Sherlock"], "a": 1},
|
| {"q": "ูู Game of Thronesุ ุฌูู ุณูู ูุงู ุถู
ู ุฃู ุจูุช ุจุงูุจุฏุงูุฉุ", "c": ["Lannister", "Baratheon", "Stark", "Targaryen"], "a": 2},
|
| ],
|
| },
|
| }
|
|
|
|
|
| class TriviaAnswerButton(discord.ui.Button["TriviaView"]):
|
| def __init__(self, label: str, index: int) -> None:
|
| super().__init__(label=label[:80], style=discord.ButtonStyle.secondary)
|
| self.index = index
|
|
|
| async def callback(self, interaction: discord.Interaction) -> None:
|
| await self.view.on_answer(interaction, self.index)
|
|
|
|
|
| class FreeGameClaimView(discord.ui.View):
|
| def __init__(self, url: str) -> None:
|
| super().__init__(timeout=None)
|
| self.add_item(
|
| discord.ui.Button(
|
| label=f"{ui('gift')} Claim Your Prize {ui('gift')}",
|
| style=discord.ButtonStyle.link,
|
| url=url,
|
| )
|
| )
|
|
|
|
|
| class TriviaView(discord.ui.View):
|
| def __init__(self, owner_id: int, correct_index: int, lang: str, cog: "Fun", guild_id: int | None) -> None:
|
| super().__init__(timeout=None)
|
| self.owner_id = owner_id
|
| self.correct_index = correct_index
|
| self.lang = lang
|
| self.answered = False
|
| self.cog = cog
|
| self.guild_id = guild_id
|
|
|
| async def on_answer(self, interaction: discord.Interaction, picked_index: int) -> None:
|
| if interaction.user.id != self.owner_id:
|
| msg = "โ ูุฐุง ุงูุณุคุงู ูุตุงุญุจ ุงูุฃู
ุฑ ููุท." if self.lang == "ar" else "โ This question is for the command author only."
|
| await interaction.response.send_message(msg, ephemeral=True)
|
| return
|
| if self.answered:
|
| msg = "โ ๏ธ ุชู
ุช ุงูุฅุฌุงุจุฉ ุจุงููุนู." if self.lang == "ar" else "โ ๏ธ Already answered."
|
| await interaction.response.send_message(msg, ephemeral=True)
|
| return
|
|
|
| self.answered = True
|
| is_correct = picked_index == self.correct_index
|
| for idx, child in enumerate(self.children):
|
| if isinstance(child, discord.ui.Button):
|
| child.disabled = True
|
| if idx == self.correct_index:
|
| child.style = discord.ButtonStyle.success
|
| elif idx == picked_index and not is_correct:
|
| child.style = discord.ButtonStyle.danger
|
|
|
| if is_correct:
|
| msg = f"โ
ุฅุฌุงุจุฉ ุตุญูุญุฉ! {E_STAR}" if self.lang == "ar" else f"โ
Correct answer! {E_STAR}"
|
| else:
|
| msg = "โ ุฅุฌุงุจุฉ ุฎุงุทุฆุฉ." if self.lang == "ar" else "โ Wrong answer."
|
|
|
| await interaction.response.edit_message(view=self)
|
| if is_correct and interaction.guild and self.guild_id:
|
| reward = random.randint(20, 45)
|
| await self.cog.bot.db.execute(
|
| "INSERT INTO user_balance(guild_id, user_id, wallet, bank) VALUES (?, ?, ?, 0) "
|
| "ON CONFLICT(guild_id, user_id) DO UPDATE SET wallet = wallet + excluded.wallet",
|
| self.guild_id,
|
| interaction.user.id,
|
| reward,
|
| )
|
| if self.lang == "ar":
|
| msg += f" ๐ฐ **+{reward}** ุนู
ูุฉ!"
|
| else:
|
| msg += f" ๐ฐ **+{reward}** coins!"
|
| await interaction.followup.send(msg, ephemeral=True)
|
|
|
|
|
| GAME_HUB_GAMES = [
|
| {"id": "chess", "name": "Chess", "emoji": "โ๏ธ", "description": "Strategic board game"},
|
| {"id": "checkers", "name": "Checkers", "emoji": "๐ด", "description": "Classic draughts game"},
|
| {"id": "connect4", "name": "Connect 4", "emoji": "๐ด", "description": "Drop and connect"},
|
| {"id": "othello", "name": "Othello", "emoji": "โช", "description": "Reversi strategy"},
|
| {"id": "tictactoe", "name": "TicTacToe", "emoji": "โ", "description": "X and O battle"},
|
| {"id": "rps", "name": "Rock Paper Scissors", "emoji": "โ๏ธ", "description": "Quick decision game"},
|
| {"id": "trivia", "name": "Trivia Challenge", "emoji": "๐ง ", "description": "Knowledge contest"},
|
| {"id": "guess", "name": "Number Guess", "emoji": "๐ข", "description": "Guess 1-10"},
|
| ]
|
|
|
|
|
| class GameHubSelect(discord.ui.Select):
|
| def __init__(self, cog: "Fun", invitee_id: int | None, lang: str = "en") -> None:
|
| self.cog = cog
|
| self.invitee_id = invitee_id
|
| self.lang = lang
|
|
|
| options = []
|
| for game in GAME_HUB_GAMES:
|
| if lang == "ar":
|
| desc = game["description"]
|
| else:
|
| desc = game["description"]
|
| options.append(
|
| discord.SelectOption(
|
| label=game["name"],
|
| value=game["id"],
|
| description=desc,
|
| emoji=game["emoji"]
|
| )
|
| )
|
| super().__init__(
|
| placeholder="๐ฎ Choose a game",
|
| min_values=1,
|
| max_values=1,
|
| options=options,
|
| custom_id="gamehub_select",
|
| )
|
|
|
| async def callback(self, interaction: discord.Interaction) -> None:
|
| if not interaction.guild:
|
| await interaction.response.send_message("Server only.", ephemeral=True)
|
| return
|
|
|
| guild = interaction.guild
|
| game_id = self.values[0]
|
| invitee = guild.get_member(self.invitee_id) if self.invitee_id else None
|
| guild_id = guild.id
|
| lang = await self.cog.bot.get_guild_language(guild_id)
|
|
|
| category = discord.utils.get(guild.categories, name="๐น๏ธ Game Rooms")
|
| if category is None:
|
| category = await guild.create_category("๐น๏ธ Game Rooms", reason="GameHub temporary rooms")
|
|
|
| overwrites = {
|
| guild.default_role: discord.PermissionOverwrite(view_channel=False),
|
| interaction.user: discord.PermissionOverwrite(view_channel=True, send_messages=True, read_message_history=True),
|
| }
|
| if invitee:
|
| overwrites[invitee] = discord.PermissionOverwrite(view_channel=True, send_messages=True, read_message_history=True)
|
| if guild.me:
|
| overwrites[guild.me] = discord.PermissionOverwrite(view_channel=True, send_messages=True, manage_channels=True)
|
|
|
| room = await guild.create_text_channel(
|
| name=f"game-{game_id}-{interaction.user.name[:8].lower()}",
|
| category=category,
|
| overwrites=overwrites,
|
| reason=f"GameHub room for {interaction.user}",
|
| )
|
|
|
| board_cog = self.cog.bot.get_cog("BoardGames")
|
| try:
|
| if game_id == "tictactoe":
|
| view = TicTacToeView(interaction.user, invitee)
|
| first = interaction.user.mention
|
| second = invitee.mention if invitee else "๐ค Bot"
|
| if lang == "ar":
|
| msg = await room.send(f"โ ุชูู ุชุงู ุชู: {first} (X) ุถุฏ {second} (O)\n๐ฎ ุงูุฏูุฑ: {interaction.user.mention}", view=view)
|
| else:
|
| msg = await room.send(f"โ TicTacToe: {first} (X) vs {second} (O)\n๐ฎ Turn: {interaction.user.mention}", view=view)
|
| if invitee is None:
|
| await view._maybe_bot(msg)
|
| elif game_id == "trivia":
|
|
|
| item = random.choice(TRIVIA_BANK.get(lang, TRIVIA_BANK["en"])["gaming"])
|
| view = TriviaView(owner_id=interaction.user.id, correct_index=int(item["a"]), lang=lang, cog=self.cog, guild_id=guild_id)
|
| for idx, choice in enumerate(item["c"]):
|
| view.add_item(TriviaAnswerButton(str(choice), idx))
|
|
|
| if lang == "ar":
|
| q_title = "๐ง ุณุคุงู ุชุฑุงฺคูุง!"
|
| else:
|
| q_title = "๐ง Trivia Time!"
|
|
|
| embed = discord.Embed(
|
| title=q_title,
|
| description=f"{panel_divider('blue')}\nโ {str(item['q'])}\n{panel_divider('blue')}",
|
| color=NEON_CYAN,
|
| )
|
| await room.send(embed=embed, view=view)
|
| elif game_id == "rps":
|
|
|
| if lang == "ar":
|
| await room.send(f"โ๏ธ ุญุฌุฑ ูุฑูุฉ ู
ูุต!\nุงุณุชุฎุฏู
`rps rock/paper/scissors` ููุนุจ!")
|
| else:
|
| await room.send(f"โ๏ธ Rock Paper Scissors!\nUse `rps rock/paper/scissors` to play!")
|
| elif game_id == "guess":
|
|
|
| secret = random.randint(1, 10)
|
| if lang == "ar":
|
| await room.send(f"๐ข ุฎู
ู ุงูุฑูู
ู
ู 1 ุฅูู 10!\nุงุณุชุฎุฏู
`/guess <ุฑูู
>` ููุนุจ!")
|
| else:
|
| await room.send(f"๐ข Guess a number from 1 to 10!\nUse `/guess <number>` to play!")
|
| elif board_cog and game_id in {"chess", "checkers", "connect4", "othello"}:
|
| fake_ctx = type("_Ctx", (), {"guild": guild, "channel": room, "author": interaction.user, "reply": room.send})
|
| opponent = invitee
|
| ok = await board_cog.start_game_session(fake_ctx, game_id, opponent)
|
| if not ok:
|
| if lang == "ar":
|
| await room.send("โ ๏ธ ุชุนุฐุฑ ุชุดุบูู ุงููุนุจุฉ. ุงุฎุชุฑ ูุนุจุฉ ุฃุฎุฑู.")
|
| else:
|
| await room.send("โ ๏ธ Could not initialize selected board game. Choose another one.")
|
| else:
|
| game_name = next((g["name"] for g in GAME_HUB_GAMES if g["id"] == game_id), game_id.title())
|
| if lang == "ar":
|
| await room.send(f"๐ฎ **{game_name}** ุงูุบุฑูุฉ ุฌุงูุฒุฉ. ุงูุนุจ ุงูุขู! {E_FIRE}")
|
| else:
|
| await room.send(f"๐ฎ **{game_name}** room is ready. Play now! {E_FIRE}")
|
| except Exception:
|
| if lang == "ar":
|
| await room.send("โ ๏ธ ุชุนุฐุฑ ุชุดุบูู ูุฐู ุงููุนุจุฉ. ุฌุฑุจ ุฅูุดุงุก ุบุฑูุฉ ุฃุฎุฑู.")
|
| else:
|
| await room.send("โ ๏ธ Could not start this game. Try creating another room.")
|
|
|
| if lang == "ar":
|
| invite_text = (
|
| f"๐ฎ **{game_id.title()}** ุงูุบุฑูุฉ ุฌุงูุฒุฉ!\n"
|
| f"{panel_divider('purple')}\n"
|
| f"๐ค **ุงูู
ุถูู:** {interaction.user.mention}"
|
| )
|
| close_text = "๐ ุฃุบูู ุงูุบุฑูุฉ ุนูุฏ ุงูุงูุชูุงุก ๐"
|
| else:
|
| invite_text = (
|
| f"๐ฎ **{game_id.title()}** Room Ready!\n"
|
| f"{panel_divider('purple')}\n"
|
| f"๐ค **Host:** {interaction.user.mention}"
|
| )
|
| close_text = "๐ Close the room when done ๐"
|
|
|
| if invitee:
|
| if lang == "ar":
|
| invite_text += f"\n๐ฏ **ู
ุฏุนู:** {invitee.mention}"
|
| else:
|
| invite_text += f"\n๐ฏ **Invited:** {invitee.mention}"
|
| invite_text += f"\n\n{close_text}"
|
| await room.send(invite_text, view=RoomControlView(interaction.user.id))
|
|
|
| if lang == "ar":
|
| response_msg = f"โ
ุชู
ุฅูุดุงุก ุงูุบุฑูุฉ: {room.mention} ๐ฎ"
|
| if invitee:
|
| response_msg += f" | ุชู
ุช ุฏุนูุฉ {invitee.mention}"
|
| else:
|
| response_msg = f"โ
Room created: {room.mention} ๐ฎ"
|
| if invitee:
|
| response_msg += f" | Invited {invitee.mention}"
|
| await interaction.response.send_message(response_msg, ephemeral=True)
|
|
|
|
|
| class GameHubView(discord.ui.View):
|
| def __init__(self, cog: "Fun", invitee_id: int | None = None, lang: str = "en") -> None:
|
| super().__init__(timeout=None)
|
| self.add_item(GameHubSelect(cog, invitee_id, lang))
|
|
|
|
|
| class RoomControlView(discord.ui.View):
|
| def __init__(self, owner_id: int) -> None:
|
| super().__init__(timeout=None)
|
| self.owner_id = owner_id
|
|
|
| @discord.ui.button(label="End Game & Close Room", style=discord.ButtonStyle.danger, emoji=ui("lock"), custom_id="room_close")
|
| async def close_room(self, interaction: discord.Interaction, _: discord.ui.Button) -> None:
|
| if not isinstance(interaction.channel, discord.TextChannel):
|
| await interaction.response.send_message("Text channel only.", ephemeral=True)
|
| return
|
| if interaction.user.id != self.owner_id and not interaction.user.guild_permissions.manage_channels:
|
| await interaction.response.send_message("โ Only room owner or admins can close this room.", ephemeral=True)
|
| return
|
| await interaction.response.send_message("๐ Closing room...", ephemeral=True)
|
| try:
|
| await interaction.channel.delete(reason=f"Game room closed by {interaction.user}")
|
| except Exception:
|
| pass
|
|
|
| @discord.ui.button(label="Invite Friend", style=discord.ButtonStyle.success, emoji=ui("plus"), custom_id="room_invite")
|
| async def invite_friend(self, interaction: discord.Interaction, _: discord.ui.Button) -> None:
|
| if interaction.user.id != self.owner_id:
|
| await interaction.response.send_message("โ Only room owner can invite.", ephemeral=True)
|
| return
|
| await interaction.response.send_message("โ Use `/gamehub @user` to invite someone to a new game room!", ephemeral=True)
|
|
|
|
|
| class TicTacToeButton(discord.ui.Button["TicTacToeView"]):
|
| def __init__(self, index: int) -> None:
|
| super().__init__(label=" ", style=discord.ButtonStyle.secondary, row=index // 3)
|
| self.index = index
|
|
|
| async def callback(self, interaction: discord.Interaction) -> None:
|
| if self.view:
|
| await self.view.play(interaction, self.index)
|
|
|
|
|
| class TicTacToeView(discord.ui.View):
|
| def __init__(self, player_x: discord.Member, player_o: discord.Member | None) -> None:
|
| super().__init__(timeout=None)
|
| self.player_x = player_x
|
| self.player_o = player_o
|
| self.turn_x = True
|
| self.board = ["" for _ in range(9)]
|
| for i in range(9):
|
| self.add_item(TicTacToeButton(i))
|
|
|
| def _check(self, mark: str) -> bool:
|
| lines = [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)]
|
| return any(self.board[a]==self.board[b]==self.board[c]==mark for a,b,c in lines)
|
|
|
| def _free(self) -> list[int]:
|
| return [i for i,v in enumerate(self.board) if not v]
|
|
|
| async def _maybe_bot(self, message: discord.Message) -> None:
|
| if self.player_o is not None or not self._free() or not self.turn_x:
|
| return
|
| move = random.choice(self._free())
|
| self.board[move] = "O"
|
| btn = self.children[move]
|
| if isinstance(btn, discord.ui.Button):
|
| btn.label = "O"
|
| btn.style = discord.ButtonStyle.danger
|
| btn.disabled = True
|
| self.turn_x = True
|
| if self._check("O"):
|
| for child in self.children:
|
| if isinstance(child, discord.ui.Button):
|
| child.disabled = True
|
| await message.edit(content=f"๐ค Bot won TicTacToe! {E_BOOM}", view=self)
|
| return
|
| if not self._free():
|
| await message.edit(content="๐ค TicTacToe draw!", view=self)
|
| return
|
| await message.edit(content=f"โ Turn: {self.player_x.mention}", view=self)
|
|
|
| async def play(self, interaction: discord.Interaction, index: int) -> None:
|
| if self.board[index]:
|
| await interaction.response.send_message("This cell is already used.", ephemeral=True)
|
| return
|
| current = self.player_x if self.turn_x else self.player_o
|
| if self.turn_x and interaction.user.id != self.player_x.id:
|
| await interaction.response.send_message("It is X player's turn.", ephemeral=True)
|
| return
|
| if not self.turn_x and self.player_o and interaction.user.id != self.player_o.id:
|
| await interaction.response.send_message("It is O player's turn.", ephemeral=True)
|
| return
|
| mark = "X" if self.turn_x else "O"
|
| self.board[index] = mark
|
| btn = self.children[index]
|
| if isinstance(btn, discord.ui.Button):
|
| btn.label = mark
|
| btn.style = discord.ButtonStyle.success if mark == "X" else discord.ButtonStyle.danger
|
| btn.disabled = True
|
|
|
| if self._check(mark):
|
| for child in self.children:
|
| if isinstance(child, discord.ui.Button):
|
| child.disabled = True
|
| winner = interaction.user.mention if self.player_o else (self.player_x.mention if mark == "X" else "๐ค Bot")
|
| await interaction.response.edit_message(content=f"๐ TicTacToe Winner: {winner}! {E_TROPHY}", view=self)
|
| return
|
|
|
| if not self._free():
|
| await interaction.response.edit_message(content="๐ค TicTacToe draw!", view=self)
|
| return
|
|
|
| self.turn_x = not self.turn_x
|
| nxt = self.player_x.mention if self.turn_x else (self.player_o.mention if self.player_o else "๐ค Bot")
|
| await interaction.response.edit_message(content=f"๐ฎ Turn: {nxt}", view=self)
|
| if not self.turn_x and self.player_o is None and interaction.message:
|
| await self._maybe_bot(interaction.message)
|
|
|
|
|
| class Fun(commands.Cog):
|
| """Games and entertainment with beautiful panels and multi-language support."""
|
|
|
| def __init__(self, bot: commands.Bot) -> None:
|
| self.bot = bot
|
|
|
| async def cog_load(self) -> None:
|
| self.bot.add_view(GameHubView(self))
|
|
|
| async def _fetch_trivia_api(self) -> dict[str, object] | None:
|
| url = "https://opentdb.com/api.php?amount=50"
|
| async with aiohttp.ClientSession() as session:
|
| async with session.get(url, timeout=15) as response:
|
| data = await response.json(content_type=None)
|
| results = data.get("results") if isinstance(data, dict) else None
|
| if not isinstance(results, list) or not results:
|
| return None
|
| item = random.choice(results)
|
| question = html.unescape(str(item.get("question", "")).strip())
|
| correct = html.unescape(str(item.get("correct_answer", "")).strip())
|
| wrong = [html.unescape(str(c).strip()) for c in item.get("incorrect_answers", []) if str(c).strip()]
|
| if not question or not correct or not wrong:
|
| return None
|
| choices = wrong[:]
|
| choices.append(correct)
|
| random.shuffle(choices)
|
| answer_index = choices.index(correct)
|
| return {"q": question, "c": choices[:4], "a": answer_index}
|
|
|
| @commands.hybrid_command(name="8ball", description=get_cmd_desc("commands.tools.8ball_desc"))
|
| async def eightball(self, ctx: commands.Context, *, question: str) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| if lang == "ar":
|
| answers = [
|
| "ูุนู
! โ
", "ูุง โ", "ุฑุจู
ุง ๐ค", "ุจุงูุชุฃููุฏ! ๐ฏ",
|
| "ููุณ ุงูุขู โฐ", "ุงุณุฃู ูุงุญูุงู ๐ฎ", "100% ูุนู
! ๐ฅ", "ุบูุฑ ูุงุถุญ ๐ซ๏ธ"
|
| ]
|
| embed = discord.Embed(
|
| title="๐ฑ ุงููุฑุฉ ุงูุณุญุฑูุฉ",
|
| description=(
|
| f"{panel_divider('pink')}\n"
|
| f"โ **ุงูุณุคุงู:** {question}\n"
|
| f"๐ฑ **ุงูุฌูุงุจ:** {random.choice(answers)}\n"
|
| f"{panel_divider('pink')}"
|
| ),
|
| color=NEON_PINK,
|
| )
|
| else:
|
| answers = [
|
| "Yes! โ
", "No โ", "Maybe ๐ค", "Definitely! ๐ฏ",
|
| "Not now โฐ", "Ask later ๐ฎ", "100% Yes! ๐ฅ", "Unclear ๐ซ๏ธ"
|
| ]
|
| embed = discord.Embed(
|
| title="๐ฑ Magic 8 Ball",
|
| description=(
|
| f"{panel_divider('pink')}\n"
|
| f"โ **Question:** {question}\n"
|
| f"๐ฑ **Answer:** {random.choice(answers)}\n"
|
| f"{panel_divider('pink')}"
|
| ),
|
| color=NEON_PINK,
|
| )
|
| await ctx.reply(embed=embed)
|
|
|
| @commands.hybrid_command(name="meme", description=get_cmd_desc("commands.tools.meme_desc"))
|
| async def meme(self, ctx: commands.Context) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| url = "https://meme-api.com/gimme"
|
| try:
|
| async with aiohttp.ClientSession() as session:
|
| async with session.get(url, timeout=10) as response:
|
| data = await response.json()
|
| except Exception:
|
| if lang == "ar":
|
| await ctx.reply("โ ๏ธ ุชุนุฐุฑ ุชุญู
ูู ุงูู
ูู
ุงูุขู. ุฌุฑุจ ู
ุฑุฉ ุฃุฎุฑู! ๐")
|
| else:
|
| await ctx.reply("โ ๏ธ Could not load meme right now. Try again in a minute! ๐")
|
| return
|
|
|
| embed = discord.Embed(
|
| title=f"๐ {data.get('title', 'Random Meme')}",
|
| color=NEON_CYAN,
|
| url=data.get("postLink")
|
| )
|
| if data.get("url"):
|
| embed.set_image(url=data["url"])
|
| embed.set_footer(text=f"๐ {data.get('ups', 0)} | r/{data.get('subreddit', 'meme')}")
|
| await ctx.reply(embed=embed)
|
|
|
| @commands.hybrid_command(name="trivia", description=get_cmd_desc("commands.tools.trivia_desc"), hidden=True, with_app_command=False)
|
| async def trivia(self, ctx: commands.Context, category: str = "", source: str = "local") -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| normalized_source = source.strip().lower() or "local"
|
| if normalized_source not in {"local", "api"}:
|
| if lang == "ar":
|
| await ctx.reply("โ ุงูู
ุตุฏุฑ ูุฌุจ ุฃู ูููู `local` ุฃู `api`")
|
| else:
|
| await ctx.reply("โ Source must be `local` or `api`")
|
| return
|
|
|
| normalized = category.strip().lower()
|
| item: dict[str, object] | None = None
|
| if lang == "ar":
|
| topic_text = "ุงูุฃูุนุงุจ โข ุงูุฃููุงู
โข ุงูู
ุณูุณูุงุช"
|
| else:
|
| topic_text = "Gaming โข Movies โข Series"
|
|
|
| if normalized_source == "api":
|
| try:
|
| item = await self._fetch_trivia_api()
|
| topic_text = "OpenTDB (50 questions pool)"
|
| except Exception:
|
| item = None
|
|
|
| if item is None:
|
| aliases = {
|
| "gaming": "gaming", "games": "gaming", "game": "gaming", "ููู
ุฒ": "gaming", "ุงูุนุงุจ": "gaming",
|
| "movies": "movies", "movie": "movies", "ุงููุงู
": "movies", "ุฃููุงู
": "movies",
|
| "series": "series", "show": "series", "shows": "series", "ู
ุณูุณูุงุช": "series",
|
| }
|
| normalized = aliases.get(normalized, normalized) if normalized else random.choice(["gaming", "movies", "series"])
|
| if normalized not in {"gaming", "movies", "series"}:
|
| if lang == "ar":
|
| await ctx.reply("โ ูุณู
ุบูุฑ ู
ุฏุนูู
. ุงุณุชุฎุฏู
: gaming ุฃู movies ุฃู series")
|
| else:
|
| await ctx.reply("โ Unsupported category. Use: gaming, movies, or series")
|
| return
|
|
|
|
|
| trivia_bank = TRIVIA_BANK.get(lang, TRIVIA_BANK["en"])
|
| if normalized not in trivia_bank:
|
| trivia_bank = TRIVIA_BANK["en"]
|
| item = random.choice(trivia_bank[normalized])
|
|
|
| view = TriviaView(owner_id=ctx.author.id, correct_index=int(item["a"]), lang=lang, cog=self, guild_id=guild_id)
|
| for idx, choice in enumerate(item["c"]):
|
| view.add_item(TriviaAnswerButton(str(choice), idx))
|
|
|
| if lang == "ar":
|
| title = "๐ง ุณุคุงู ุชุฑุงฺคูุง!"
|
| cat_label = "๐ ุงููุณู
"
|
| topics_label = "๐ ุงูู
ูุงุถูุน"
|
| else:
|
| title = "๐ง Trivia Time!"
|
| cat_label = "๐ Category"
|
| topics_label = "๐ Topics"
|
|
|
| embed = discord.Embed(
|
| title=title,
|
| description=f"{panel_divider('blue')}\nโ {str(item['q'])}\n{panel_divider('blue')}",
|
| color=NEON_CYAN,
|
| )
|
| cat_value = normalized.title() if normalized else ("General" if normalized_source == "api" else "Random")
|
| embed.add_field(name=cat_label, value=cat_value, inline=True)
|
| embed.add_field(name=topics_label, value=topic_text, inline=True)
|
| await ctx.reply(embed=embed, view=view)
|
|
|
| async def _fetch_gaming_news(self) -> list[dict[str, str]]:
|
| return await fetch_gaming_news()
|
|
|
| async def _fetch_free_games(self) -> list[dict[str, str]]:
|
| return await fetch_free_games()
|
|
|
| @staticmethod
|
| def _store_icon(platform: str) -> str:
|
| return store_icon(platform)
|
|
|
| def _free_game_embed(self, item: dict[str, str]) -> tuple[discord.Embed, discord.ui.View]:
|
| title = item["title"][:120]
|
| link = item["link"]
|
| embed = ImperialMotaz.craft_embed(
|
| title=f"[FREE GAME] | {title}",
|
| description=(
|
| f"**{item.get('description', 'Limited-time free game offer!')}**\n\n"
|
| "Claim it now from the official store page before it expires."
|
| ),
|
| color=NEON_PINK,
|
| footer="Free Games Tracker",
|
| )
|
| embed.url = link
|
| embed.add_field(name="Platform", value=f"ใ {item.get('platform', 'Unknown')} ใ", inline=True)
|
| embed.add_field(name="Type", value=f"ใ {item.get('game_type', 'Game')} ใ", inline=True)
|
| embed.add_field(name="Original Price", value=f"ใ {item.get('original_price', 'N/A')} ใ", inline=True)
|
| embed.add_field(name="Ends On", value=f"ใ {item.get('end_date', 'N/A')} ใ", inline=True)
|
| embed.add_field(name="Link", value=f"[Open Giveaway]({link})", inline=False)
|
| if item.get("image"):
|
| embed.set_image(url=item["image"])
|
| embed.set_thumbnail(url=self._store_icon(item.get("platform", "")))
|
| return embed, FreeGameClaimView(link)
|
|
|
| @commands.hybrid_command(name="gaming_news", description=get_cmd_desc("commands.tools.gaming_news_desc"))
|
| async def gaming_news(self, ctx: commands.Context) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| try:
|
| items = await self._fetch_gaming_news()
|
| except Exception:
|
| if lang == "ar":
|
| await ctx.reply("โ ุชุนุฐุฑ ุฌูุจ ุฃุฎุจุงุฑ ุงูุฃูุนุงุจ ุงูุขู.")
|
| else:
|
| await ctx.reply("โ Could not fetch gaming news right now.")
|
| return
|
|
|
| if not items:
|
| if lang == "ar":
|
| await ctx.reply("ูุง ุชูุฌุฏ ุฃุฎุจุงุฑ ู
ุชุงุญุฉ ุงูุขู.")
|
| else:
|
| await ctx.reply("No gaming news available right now.")
|
| return
|
|
|
| if lang == "ar":
|
| title = "๐น๏ธ ุขุฎุฑ ุฃุฎุจุงุฑ ุงูุฃูุนุงุจ ุนุงูู
ููุง"
|
| else:
|
| title = "๐น๏ธ Latest Gaming News Worldwide"
|
|
|
| embed = discord.Embed(
|
| title=title,
|
| description=f"{panel_divider('green')}",
|
| color=NEON_CYAN,
|
| )
|
| for item in items:
|
| date_hint = f"\n๐๏ธ {item['pub_date'][:16]}" if item.get("pub_date") else ""
|
| if lang == "ar":
|
| embed.add_field(name=item["title"][:256], value=f"๐ฐ [ุงูุฑุฃ ุงูู
ูุงู]({item['link']}){date_hint}", inline=False)
|
| else:
|
| embed.add_field(name=item["title"][:256], value=f"๐ฐ [Read Article]({item['link']}){date_hint}", inline=False)
|
| await ctx.reply(embed=embed)
|
|
|
| @commands.hybrid_command(name="freegames", description=get_cmd_desc("commands.tools.freegames_desc"), with_app_command=False)
|
| async def freegames(self, ctx: commands.Context) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| try:
|
| items = await self._fetch_free_games()
|
| except Exception:
|
| if lang == "ar":
|
| await ctx.reply("โ ุชุนุฐุฑ ุฌูุจ ุงูุนุฑูุถ ุงูุขู.")
|
| else:
|
| await ctx.reply("โ Could not fetch free game offers right now.")
|
| return
|
|
|
| if not items:
|
| if lang == "ar":
|
| await ctx.reply("ูุง ุชูุฌุฏ ุนุฑูุถ ู
ุฌุงููุฉ ูุดุทุฉ ุงูุขู.")
|
| else:
|
| await ctx.reply("No active free game offers right now.")
|
| return
|
|
|
| for item in items:
|
| embed, view = self._free_game_embed(item)
|
| await ctx.reply(embed=embed, view=view)
|
|
|
| @commands.hybrid_command(name="free_games", description=get_cmd_desc("commands.tools.free_games_desc"))
|
| async def free_games(self, ctx: commands.Context) -> None:
|
| await self.freegames(ctx)
|
|
|
| @commands.hybrid_group(name="gamehub", fallback="panel", description="Interactive game hub with temporary private rooms")
|
| async def gamehub(self, ctx: commands.Context, invite: discord.Member | None = None) -> None:
|
| if not ctx.guild:
|
| await ctx.reply("Server only.")
|
| return
|
|
|
| guild_id = ctx.guild.id
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| if invite and invite.bot:
|
| if lang == "ar":
|
| await ctx.reply("โ ุงุฏุนู ุนุถูุงู ุญููููุงูุ ููุณ ุจูุช.")
|
| else:
|
| await ctx.reply("โ Invite a real member, not a bot.")
|
| return
|
| if invite and invite.id == ctx.author.id:
|
| if lang == "ar":
|
| await ctx.reply("โ ุงุฏุนู ุนุถูุงู ุขุฎุฑ.")
|
| else:
|
| await ctx.reply("โ Invite another member.")
|
| return
|
|
|
| games_list = " โข ".join([f"{g['emoji']} {g['name']}" for g in GAME_HUB_GAMES])
|
|
|
| if lang == "ar":
|
| title = "๐ฎ ู
ุฑูุฒ ุงูุฃูุนุงุจ"
|
| desc = (
|
| f"{panel_divider('pink')}\n"
|
| f"๐น๏ธ ุงุฎุชุฑ ูุนุจุฉ ุฃุฏูุงู ูุฅูุดุงุก **ุบุฑูุฉ ุฎุงุตุฉ**.\n"
|
| f"๐ฅ ุงุฏุนู ุตุฏููุงู ุฃู ุงูุนุจ ุถุฏ ุงูุจูุช.\n"
|
| f"๐๏ธ ุงูุบุฑูุฉ ุชูุญุฐู ุชููุงุฆูุงู ุนูุฏ ุฅุบูุงููุง.\n"
|
| f"{panel_divider('pink')}\n\n"
|
| f"**ุงูุฃูุนุงุจ:** {games_list}"
|
| )
|
| invited_label = "๐ฏ ุงูุนุถู ุงูู
ุฏุนู"
|
| else:
|
| title = "๐ฎ Game Hub"
|
| desc = (
|
| f"{panel_divider('pink')}\n"
|
| f"๐น๏ธ Select a game below to create a **private room**.\n"
|
| f"๐ฅ Invite a friend or play solo vs the bot.\n"
|
| f"๐๏ธ The room auto-deletes when you close it.\n"
|
| f"{panel_divider('pink')}\n\n"
|
| f"**Games:** {games_list}"
|
| )
|
| invited_label = "๐ฏ Invited Member"
|
|
|
| embed = discord.Embed(
|
| title=title,
|
| description=desc,
|
| color=NEON_CYAN,
|
| )
|
| if invite:
|
| embed.add_field(name=invited_label, value=invite.mention, inline=False)
|
| await ctx.reply(embed=embed, view=GameHubView(self, invite.id if invite else None, lang))
|
|
|
| @gamehub.command(name="xo", description="TicTacToe vs member or bot")
|
| async def gamehub_xo(self, ctx: commands.Context, opponent: discord.Member | None = None) -> None:
|
| await self.xo(ctx, opponent=opponent)
|
|
|
| @gamehub.command(name="mario", description="Mario/Pac-Man arcade challenge")
|
| async def gamehub_mario(self, ctx: commands.Context) -> None:
|
| await self.mario(ctx)
|
|
|
| @gamehub.command(name="dice", description="Roll dice")
|
| async def gamehub_dice(self, ctx: commands.Context, sides: int = 6) -> None:
|
| await self.dice(ctx, sides=sides)
|
|
|
| @gamehub.command(name="slots", description="Slot machine game")
|
| async def gamehub_slots(self, ctx: commands.Context, bet: int = 50) -> None:
|
| await self.slots(ctx, bet=bet)
|
|
|
| @gamehub.command(name="trivia", description="Gaming/Movies/Series trivia")
|
| async def gamehub_trivia(self, ctx: commands.Context, category: str = "gaming", difficulty: str = "medium") -> None:
|
| await self.trivia(ctx, category=category)
|
|
|
| @commands.hybrid_command(name="xo", description=get_cmd_desc("commands.tools.xo_desc"), hidden=True, with_app_command=False)
|
| async def xo(self, ctx: commands.Context, opponent: discord.Member | None = None) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| if opponent and opponent.bot:
|
| opponent = None
|
| view = TicTacToeView(ctx.author, opponent)
|
| second = opponent.mention if opponent else "๐ค Bot"
|
|
|
| if lang == "ar":
|
| msg = await ctx.reply(
|
| f"โ ุชูู ุชุงู ุชู: {ctx.author.mention} (X) ุถุฏ {second} (O)\n"
|
| f"๐ฎ ุงูุฏูุฑ: {ctx.author.mention}",
|
| view=view
|
| )
|
| else:
|
| msg = await ctx.reply(
|
| f"โ TicTacToe: {ctx.author.mention} (X) vs {second} (O)\n"
|
| f"๐ฎ Turn: {ctx.author.mention}",
|
| view=view
|
| )
|
| if opponent is None:
|
| await view._maybe_bot(msg)
|
|
|
| @commands.hybrid_command(name="choose", hidden=True, with_app_command=False, description=get_cmd_desc("commands.tools.choose_desc"))
|
| async def choose(self, ctx: commands.Context, *, options: str) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| parts = [p.strip() for p in options.split(",") if p.strip()]
|
| if len(parts) < 2:
|
| if lang == "ar":
|
| await ctx.reply("โ ุฃุฏุฎู ุฎูุงุฑูู ุนูู ุงูุฃูู ู
ูุตูููู ุจููุงุตู.")
|
| else:
|
| await ctx.reply("โ Provide at least 2 options separated by commas.")
|
| return
|
|
|
| choice = random.choice(parts)
|
|
|
| if lang == "ar":
|
| embed = discord.Embed(
|
| title="๐ฒ ุงุฎุชูุงุฑ ุนุดูุงุฆู",
|
| description=(
|
| f"{panel_divider('purple')}\n"
|
| f"๐ ุงูุฎูุงุฑุงุช: {', '.join(parts)}\n"
|
| f"๐ฏ **ุงูู
ุฎุชุงุฑ:** {choice}\n"
|
| f"{panel_divider('purple')}"
|
| ),
|
| color=NEON_PINK,
|
| )
|
| else:
|
| embed = discord.Embed(
|
| title="๐ฒ Random Choice",
|
| description=(
|
| f"{panel_divider('purple')}\n"
|
| f"๐ Options: {', '.join(parts)}\n"
|
| f"๐ฏ **Selected:** {choice}\n"
|
| f"{panel_divider('purple')}"
|
| ),
|
| color=NEON_PINK,
|
| )
|
| await ctx.reply(embed=embed)
|
|
|
| @commands.hybrid_command(name="mario", description=get_cmd_desc("commands.tools.mario_desc"), hidden=True, with_app_command=False)
|
| async def mario(self, ctx: commands.Context) -> None:
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| coins = random.randint(5, 120)
|
| level = random.randint(1, 8)
|
|
|
| if lang == "ar":
|
| embed = discord.Embed(
|
| title="๐ ุชุญุฏู ุงูุขุฑููุฏ",
|
| description=(
|
| f"{panel_divider('orange')}\n"
|
| f"๐ {ctx.author.mention} ุฌู
ุน **{coins}** ุนู
ูุฉ!\n"
|
| f"โ
ุชุฌุงูุฒ ุงูู
ุฑุญูุฉ **{level}**!\n"
|
| f"{panel_divider('orange')}"
|
| ),
|
| color=NEON_ORANGE,
|
| )
|
| embed.add_field(name="๐ ู
ูุงูุฃุฉ", value="ุชู
ูุชุญ combo ุจุงู ู
ุงู! <:animatedarrowyellow:1477261257592668271>", inline=False)
|
| else:
|
| embed = discord.Embed(
|
| title="๐ Arcade Challenge",
|
| description=(
|
| f"{panel_divider('orange')}\n"
|
| f"๐ {ctx.author.mention} collected **{coins}** coins!\n"
|
| f"โ
Cleared level **{level}**!\n"
|
| f"{panel_divider('orange')}"
|
| ),
|
| color=NEON_ORANGE,
|
| )
|
| embed.add_field(name="๐ Bonus", value="Pac-Man combo unlocked! <:animatedarrowyellow:1477261257592668271>", inline=False)
|
| embed.set_thumbnail(url="https://upload.wikimedia.org/wikipedia/en/a/a9/MarioNSMBUDeluxe.png")
|
| await ctx.reply(embed=embed)
|
|
|
| @commands.hybrid_command(name="dice", description=get_cmd_desc("commands.tools.dice_desc"), hidden=True, with_app_command=False)
|
| async def dice(self, ctx: commands.Context, sides: int = 6) -> None:
|
| """Roll a dice with specified sides."""
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| sides = max(2, min(sides, 100))
|
| result = random.randint(1, sides)
|
|
|
| if lang == "ar":
|
| embed = gaming_embed(
|
| "๐ฒ ุฑู
ู ุงููุฑุฏ",
|
| f"๐ฒ ุฑู
ูุช ูุฑุฏ ุจู **{sides}** ุฃูุฌู\n๐ฏ ุงููุชูุฌุฉ: **{result}**"
|
| )
|
| else:
|
| embed = gaming_embed(
|
| "๐ฒ Dice Roll",
|
| f"๐ฒ Rolled a **{sides}**-sided dice\n๐ฏ Result: **{result}**"
|
| )
|
| await ctx.reply(embed=embed)
|
|
|
| @commands.hybrid_command(name="slots", description=get_cmd_desc("commands.tools.slots_desc"), hidden=True, with_app_command=False)
|
| async def slots(self, ctx: commands.Context, bet: int = 10) -> None:
|
| """Play a slot machine game."""
|
| guild_id = ctx.guild.id if ctx.guild else None
|
| lang = await self.bot.get_guild_language(guild_id)
|
|
|
| bet = max(10, bet)
|
|
|
|
|
| row = await self.bot.db.fetchone(
|
| "SELECT wallet FROM user_balance WHERE guild_id = ? AND user_id = ?",
|
| guild_id,
|
| ctx.author.id,
|
| )
|
| wallet = row[0] if row else 0
|
|
|
| if wallet < bet:
|
| if lang == "ar":
|
| await ctx.reply(f"โ ููุณ ูุฏูู ุฑุตูุฏ ูุงูู. ู
ุญูุธุชู: **{wallet}** ุนู
ูุฉ")
|
| else:
|
| await ctx.reply(f"โ Insufficient balance. Your wallet: **{wallet}** coins")
|
| return
|
|
|
|
|
| symbols = ["๐", "๐", "๐", "๐", "โ
", "๐", "7๏ธโฃ"]
|
| weights = [25, 20, 18, 15, 12, 7, 3]
|
|
|
|
|
| results = random.choices(symbols, weights=weights, k=3)
|
|
|
|
|
| if results[0] == results[1] == results[2]:
|
|
|
| if results[0] == "7๏ธโฃ":
|
| multiplier = 10
|
| elif results[0] == "๐":
|
| multiplier = 7
|
| elif results[0] == "โ
":
|
| multiplier = 5
|
| else:
|
| multiplier = 3
|
| winnings = bet * multiplier
|
| elif results[0] == results[1] or results[1] == results[2] or results[0] == results[2]:
|
| winnings = bet * 2
|
| else:
|
| winnings = 0
|
|
|
|
|
| if winnings > 0:
|
| await self._add_coins(guild_id, ctx.author.id, winnings - bet)
|
| else:
|
| await self._add_coins(guild_id, ctx.author.id, -bet)
|
|
|
|
|
| slot_display = " | ".join(results)
|
|
|
| if winnings >= bet * 5:
|
| result_text = f"๐ฐ **{'ุฌุงุฆุฒุฉ ูุจุฑู!' if lang == 'ar' else 'JACKPOT!'}** {E_FIRE}"
|
| elif winnings > 0:
|
| result_text = f"โ
**{'ูุฒุช!' if lang == 'ar' else 'You won!'}**"
|
| else:
|
| result_text = f"โ **{'ุญุธ ุฃููุฑ' if lang == 'ar' else 'Better luck next time'}**"
|
|
|
| if lang == "ar":
|
| embed = gaming_embed(
|
| "๐ฐ ู
ุงูููุฉ ุงููู
ุงุฑ",
|
| f"โโโโโโโโโ\nโ {slot_display} โ\nโโโโโโโโโ\n\n{result_text}\n๐ฐ **ุงูุฑุงุจุญ:** {winnings} ุนู
ูุฉ"
|
| )
|
| else:
|
| embed = gaming_embed(
|
| "๐ฐ Slot Machine",
|
| f"โโโโโโโโโ\nโ {slot_display} โ\nโโโโโโโโโ\n\n{result_text}\n๐ฐ **Won:** {winnings} coins"
|
| )
|
| await ctx.reply(embed=embed)
|
|
|
| async def _add_coins(self, guild_id: int, user_id: int, amount: int) -> None:
|
| """Helper to add/remove coins from user balance."""
|
| if amount == 0:
|
| return
|
| await self.bot.db.execute(
|
| "INSERT INTO user_balance(guild_id, user_id, wallet, bank) VALUES (?, ?, ?, 0) "
|
| "ON CONFLICT(guild_id, user_id) DO UPDATE SET wallet = wallet + ?",
|
| guild_id,
|
| user_id,
|
| amount if amount > 0 else 0,
|
| amount,
|
| )
|
|
|
|
|
| async def setup(bot: commands.Bot) -> None:
|
| await bot.add_cog(Fun(bot))
|
|
|