diff --git a/bot.py b/bot.py index 938f815..9c9320b 100644 --- a/bot.py +++ b/bot.py @@ -193,7 +193,7 @@ class DiscordBot(commands.Bot): """ Setup the game status task of the bot. """ - statuses = ["with you!", "with Krypton!", "with humans!"] + statuses = ["with you!", "with neo!", "with humans!", "learning rust!"] await self.change_presence(activity=discord.Game(random.choice(statuses))) @status_task.before_loop diff --git a/cogs/fun/minesweeper.py b/cogs/fun/minesweeper.py new file mode 100644 index 0000000..1f4580d --- /dev/null +++ b/cogs/fun/minesweeper.py @@ -0,0 +1,203 @@ +import random +from itertools import repeat +import discord +from discord.ext import commands +from discord.ext.commands import Context + + +class RowButton(discord.ui.Button): + def __init__(self, ctx, label, custom_id, bombs, board): + super().__init__(label=label, style=discord.ButtonStyle.grey, custom_id=custom_id) + self.ctx = ctx + self.bombs = bombs + self.board = board + + async def callback(self, interaction): + assert self.view is not None + view: MsView = self.view + await interaction.response.defer() + if interaction.user.id != self.ctx.author.id: + return await interaction.followup.send( + "You cannot interact with these buttons.", ephemeral=True + ) + + b_id = self.custom_id + if int(b_id[5:]) in view.moves: + return await interaction.followup.send("That part is already taken.", ephemeral=True) + if int(b_id[5:]) in self.bombs: + await view.RevealBombs(b_id, view.board) + else: + count = [] + rawpos = int(b_id[5:]) + pos = view.GetBoardPos(rawpos) + + def checkpos(count, rawpos, pos): + pos = view.GetBoardPos(rawpos) + if not rawpos - 1 in self.bombs or pos == 0: + count.append(rawpos - 1) + if not rawpos + 1 in self.bombs or pos == 4: + count.append(rawpos + 1) + if not rawpos - 6 in self.bombs or pos == 0: + count.append(rawpos - 6) + if not rawpos - 4 in self.bombs or pos == 4: + count.append(rawpos - 4) + if not rawpos + 6 in self.bombs or pos == 4: + count.append(rawpos + 6) + if not rawpos + 4 in self.bombs or pos == 0: + count.append(rawpos + 4) + if not rawpos - 5 in self.bombs: + count.append(rawpos - 5) + if not rawpos + 5 in self.bombs: + count.append(rawpos + 5) + return count + + count = checkpos(count, rawpos, pos) + number = 8-len(count) + self.label = str(number) if number > 0 else "0" + self.style = discord.ButtonStyle.green + pos = int(b_id[5:]) + view.board[view.GetBoardRow(pos)][ + view.GetBoardPos(pos) + ] = str(number) if number > 0 else "0" + view.moves.append(pos) + if len(view.moves) + len(self.bombs) == 25: + await interaction.edit_original_response(view=view) + await view.EndGame() + + await interaction.edit_original_response(view=view) + + +class MsView(discord.ui.View): + def __init__(self, ctx, options, bombs, board): + super().__init__() + for i, op in enumerate(options): + self.add_item(RowButton(ctx, op, f"block{i}", bombs, board)) + self.board = board + self.bombs = bombs + self.moves = [] + self.ctx = ctx + self.message = None + + async def EndGame(self): + embed = discord.Embed( + title="Minesweeper", + description="Game Ended. You won!", + color=0x00FF00 + ) + embed.set_author(name="Fun", icon_url="https://yes.nighty.works/raw/eW5lLm.webp") + await self.message.edit(embed=embed, view=self) + for button in self.children: + button.disabled = True + pos = int(button.custom_id[5:]) + if pos in self.bombs: + button.label = "💣" + button.style = discord.ButtonStyle.red + self.board[self.GetBoardRow(pos)][self.GetBoardPos(pos)] = "💣" + + def GetBoardRow(self, pos): + if pos in [0, 1, 2, 3, 4]: + return 0 + if pos in [5, 6, 7, 8, 9]: + return 1 + if pos in [10, 11, 12, 13, 14]: + return 2 + if pos in [15, 16, 17, 18, 19]: + return 3 + if pos in [20, 21, 22, 23, 24]: + return 4 + return False + + def GetBoardPos(self, pos): + if pos in [0, 1, 2, 3, 4]: + return pos + if pos in [5, 6, 7, 8, 9]: + for i, num in enumerate(range(5, 10)): + if pos == num: + return i + if pos in [10, 11, 12, 13, 14]: + for i, num in enumerate(range(10, 15)): + if pos == num: + return i + if pos in [15, 16, 17, 18, 19]: + for i, num in enumerate(range(15, 20)): + if pos == num: + return i + if pos in [20, 21, 22, 23, 24]: + for i, num in enumerate(range(20, 25)): + if pos == num: + return i + return False + + async def RevealBombs(self, b_id, board): + bombemo = "💣" + embed = discord.Embed( + title="Minesweeper", + description="💥 BOOM! You hit a bomb! Game Over!", + color=0xE02B2B + ) + embed.set_author(name="Fun", icon_url="https://yes.nighty.works/raw/eW5lLm.webp") + await self.message.edit(embed=embed, view=self) + + for button in self.children: + button.disabled = True + if button.custom_id == b_id: + button.label = bombemo + button.style = discord.ButtonStyle.red + pos = int(b_id[5:]) + self.board[self.GetBoardRow(pos)][self.GetBoardPos(pos)] = bombemo + + for button in self.children: + if int(button.custom_id[5:]) in self.bombs: + button.label = bombemo + button.style = discord.ButtonStyle.red + pos = int(button.custom_id[5:]) + self.board[self.GetBoardRow(pos)][ + self.GetBoardPos(pos) + ] = bombemo + + +class Minesweeper(commands.Cog, name="minesweeper"): + def __init__(self, bot) -> None: + self.bot = bot + + @commands.hybrid_command( + name="minesweeper", + description="Play a buttoned minesweeper mini-game." + ) + async def minesweeper(self, context: Context) -> None: + """ + Play a buttoned minesweeper mini-game. + :param context: The hybrid command context. + """ + board = [["឵឵ "] * 5 for _ in range(5)] # Unicode block character, usually doesnt show up in Discord or github, search up invisible character on google + bombs = 0 + bombpositions = [] + for x in repeat(None, random.randint(4, 11)): + random_index = random.randint(0, 24) + if random_index not in bombpositions and random_index not in [ + 0, 4, 20, 24 + ]: + bombpositions.append(random_index) + bombs += 1 + + def ExtractBlocks(): + new_b = [] + for x in board: + for y in x: + new_b.append(y) + return new_b + + embed = discord.Embed( + title="Minesweeper", + description=f"💣 Total Bombs: `{len(bombpositions)}`\n\nClick the buttons to reveal the grid. Avoid the bombs!", + color=0x7289DA + ) + embed.set_author(name="Fun", icon_url="https://yes.nighty.works/raw/eW5lLm.webp") + + view = MsView(context, ExtractBlocks(), bombpositions, board) + message = await context.send(embed=embed, view=view) + view.message = message + + +async def setup(bot) -> None: + await bot.add_cog(Minesweeper(bot)) diff --git a/cogs/general/help.py b/cogs/general/help.py index 876ffbe..86525a4 100644 --- a/cogs/general/help.py +++ b/cogs/general/help.py @@ -49,6 +49,7 @@ class Help(commands.Cog, name="help"): "coinflip": "fun", "rps": "fun", "8ball": "fun", + "minesweeper": "fun", "kick": "moderation", "ban": "moderation", diff --git a/cogs/moderation/hackban.py b/cogs/moderation/hackban.py index 581a1b3..e210dda 100644 --- a/cogs/moderation/hackban.py +++ b/cogs/moderation/hackban.py @@ -1,11 +1,3 @@ -""" -Copyright © Krypton 2019-Present - https://github.com/kkrypt0nn (https://krypton.ninja) -Description: -🐍 A simple template to start to code your own and personalized Discord bot in Python - -Version: 6.4.0 -""" - import discord from discord import app_commands from discord.ext import commands @@ -42,16 +34,18 @@ class HackBan(commands.Cog, name="hackban"): int(user_id) ) embed = discord.Embed( + title="Ban", description=f"**{user}** (ID: {user_id}) was banned by **{context.author}**!", - color=0xBEBEFE, - ) + color=0x7289DA, + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") embed.add_field(name="Reason:", value=reason) await context.send(embed=embed) except Exception: embed = discord.Embed( + title="Error!", description="An error occurred while trying to ban the user. Make sure ID is an existing ID that belongs to a user.", color=0xE02B2B, - ) + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") await context.send(embed=embed)