Example #1
0
    async def removal(self, ctx: commands.Context, action: str):
        message = "Would you like to reset the {}?".format(action)
        can_react = ctx.channel.permissions_for(ctx.me).add_reactions
        if not can_react:
            message += " (y/n)"
        question: discord.Message = await ctx.send(message)
        if can_react:
            start_adding_reactions(
                question, ReactionPredicate.YES_OR_NO_EMOJIS
            )
            pred = ReactionPredicate.yes_or_no(question, ctx.author)
            event = "reaction_add"
        else:
            pred = MessagePredicate.yes_or_no(ctx)
            event = "message"
        try:
            await ctx.bot.wait_for(event, check=pred, timeout=20)
        except asyncio.TimeoutError:
            await question.delete()
            await ctx.send("Okay then :D")
        if not pred.result:
            await question.delete()
            return await ctx.send("Canceled!")
        else:
            if can_react:
                with suppress(discord.Forbidden):
                    await question.clear_reactions()
        await self.config.guild(ctx.guild).set_raw(action, value=None)
        await ctx.send("Removed the {}!".format(action))

            pred = ReactionPredicate.yes_or_no(question, ctx.author)
            event = "reaction_add"
Example #2
0
 async def one_from(ctx,user,list): #user needs to be a discord.member object. list is a namestring of a droplist of items here.
     chance = getattr(Treasure, list)
     itemname = random.choice(list(chance.keys()))
     item = chance[itemname]
     if item['slot'] == ['consumable']:
         item['uses'] = random.randint(1,item['uses'])
         await ctx.send("```css\n{} found {} ({}x).```".format(user.display_name,itemname,item['uses']))
         msg = await ctx.send("Do you want to use, put in backpack or sell this item?")
         start_adding_reactions(msg, Treasure.controls.keys())
         if hasattr(user, "id"):
             pred = ReactionPredicate.with_emojis(tuple(Treasure.controls.keys()), msg, user)
         else:
             pred = ReactionPredicate.with_emojis(tuple(Treasure.controls.keys()), msg, ctx.author)
         react = None
         try:
             react, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60)
         except asyncio.TimeoutError:
             await ctx.send("Item claim timed out after one minute. Selling...")
             react_emoji = "💰"
         try:
             await msg.clear_reactions()
         except discord.Forbidden:  # cannot remove all reactions
             for key in Treasure.controls.keys():
                 await msg.remove_reaction(key, ctx.bot.user)
         if react != None:
             react_emoji = react.emoji
         return {"itemname": itemname,"item":item,"equip":Treasure.controls[react_emoji]}
     else:
         if len(item["slot"]) == 2: # two handed weapons add their bonuses twice
             hand = "two handed"
             att = item["att"]*2
             cha = item["cha"]*2
         else:
             if item["slot"][0] == "right" or item["slot"][0] == "left":
                 hand = item["slot"][0] + " handed"
             else:
                 hand = item["slot"][0] + " slot"
             att = item["att"]
             cha = item["cha"]
         await ctx.send("```css\n{} found a {}. (Attack: {}, Charisma: {} [{}])```".format(user.display_name,itemname,str(att),str(cha),hand))
         msg = await ctx.send("Do you want to equip, put in backpack or sell this item?")
         start_adding_reactions(msg, Treasure.controls.keys())
         pred = ReactionPredicate.with_emojis(tuple(Treasure.controls.keys()), msg, user)
         react = None
         try:
             react, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60)
         except asyncio.TimeoutError:
             await ctx.send("Item claim timed out after one minute. Selling...")
             react_emoji = "💰"
         try:
             await msg.clear_reactions()
         except discord.Forbidden:  # cannot remove all reactions
             for key in Treasure.controls.keys():
                 await msg.remove_reaction(key, ctx.bot.user)
         if react != None:
             react_emoji = react.emoji
         return {"itemname": itemname,"item":item,"equip":Treasure.controls[react_emoji]}
Example #3
0
    async def find_wiki_name(self, ctx, wiki_name):
        wikis = await self.get_wikis(ctx)
        match = get_close_matches(wiki_name, wikis.keys(), 1, 0.3)
        if not match:
            # No match found, list of wikis returned instead
            return

        msg = await ctx.send(
            f'I can\'t find a wiki called {wiki_name}. Did you mean`{match[0]}`?'
        )
        start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)

        try:  #waiting for reaction
            pred = ReactionPredicate.yes_or_no(msg, ctx.author)
            await ctx.bot.wait_for("reaction_add", check=pred, timeout=15)
        except asyncio.TimeoutError:
            await ctx.send("You didn\'t react in time, cancelled.")

        try:  # Delete reactions from question message
            if ctx.channel.permissions_for(ctx.me).manage_messages:
                await msg.clear_reactions()
        except:
            pass

        if pred.result is not True:
            return  # User didn't responded with tick

        wiki_name = match[0]
        return wiki_name
Example #4
0
 async def confirm(self, ctx, type: str, cost: int):
     msg = await ctx.send(
         f"Please confirm that you would like to purchase a {type} for {cost}."
     )
     pred = ReactionPredicate.yes_or_no(msg, ctx.author)
     start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
     try:
         await self.bot.wait_for("reaction_add", check=pred, timeout=30)
     except asyncio.TimeoutError:
         await msg.delete()
         await ctx.send(f":x: You took too long to respond.")
     if not pred.result:
         await ctx.send("Okay. No changes have been made.")
     else:
         try:
             await msg.delete()
             await bank.withdraw_credits(ctx.author, cost)
             crooks = await self.config.user(ctx.author).crooks()
             crooks += 1
             await self.config.user(ctx.author).crooks.set(crooks)
             await ctx.send(f"Done. A {type} was successfully purchased for {cost}.")
         except ValueError:
             await ctx.send(
                 f"You do not have enough cash! A crook costs {cost}, you have {await bank.get_balance(ctx.author)}."
             )
Example #5
0
    async def _send_check_out_message(self, ctx, user, match_day, tier):
        embed = discord.Embed(
            title="Check Out",
            description=
            "You are currently checked in as available for the following match day and tier. "
            "Do you wish to take yourself off the availability list? To confirm you want to check out, react with {}"
            .format(ReactionPredicate.YES_OR_NO_EMOJIS[0]),
            colour=discord.Colour.blue())
        embed.add_field(name="Match Day", value=match_day, inline=True)
        embed.add_field(name="Tier", value=tier, inline=True)

        react_msg = await user.send(embed=embed)
        start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS)

        try:
            pred = ReactionPredicate.yes_or_no(react_msg, user)
            await ctx.bot.wait_for("reaction_add",
                                   check=pred,
                                   timeout=verify_timeout)
            if pred.result is True:
                await self._unregister_user(ctx, user, match_day, tier)
                await user.send(
                    "You have been removed from the list. Thank you for updating your availability!"
                )
            else:
                await user.send(
                    "Still checked in. If you wish to check out use the command again."
                )
        except asyncio.TimeoutError:
            await user.send(
                "Sorry, you didn't react quick enough. Please try again.")
Example #6
0
    async def _send_check_in_message(self, ctx, user, match_day, tier):
        embed = discord.Embed(
            title="Check In",
            description=
            "By checking in you are letting GMs know that you are available to play "
            "on the following match day in the following tier. To confirm react with {}"
            .format(ReactionPredicate.YES_OR_NO_EMOJIS[0]),
            colour=discord.Colour.blue())
        embed.add_field(name="Match Day", value=match_day, inline=True)
        embed.add_field(name="Tier", value=tier, inline=True)

        react_msg = await user.send(embed=embed)
        start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS)

        try:
            pred = ReactionPredicate.yes_or_no(react_msg, user)
            await ctx.bot.wait_for("reaction_add",
                                   check=pred,
                                   timeout=verify_timeout)
            if pred.result is True:
                await self._register_user(ctx, user, match_day, tier)
                await user.send(
                    "Thank you for checking in! GMs will now be able to see that you're available."
                )
            else:
                await user.send(
                    "Not checked in. If you wish to check in use the command again."
                )
        except asyncio.TimeoutError:
            await user.send(
                "Sorry, you didn't react quick enough. Please try again.")
Example #7
0
 async def delete_letter(self, ctx: commands.Context, letter_id: str):
     """
     Delete a specific letter.
     """
     letters = await self.config.custom("LetterBox",
                                        ctx.author.id).letterbox()
     if letter_id not in letters:
         await ctx.send("This letter is not in your letterbox.")
         return
     msg = await ctx.send(
         bold(
             "Are you sure you want to delete this letter? This action " +
             underline("cannot be") + " recovered.",
             escape_formatting=False,
         ))
     start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
     pred = ReactionPredicate.yes_or_no(msg, ctx.author)
     try:
         await self.bot.wait_for("reaction_add", check=pred, timeout=60)
     except AsyncTimeoutError:
         return None
     if pred.result:
         await self.config.custom(
             "LetterBox", ctx.author.id).letterbox.clear_raw(letter_id)
         await msg.edit(content="Deleted your letter.")
     else:
         await msg.edit(content="I won't touch it then!")
Example #8
0
 async def _react_prompt(self,
                         ctx,
                         prompt,
                         if_not_msg=None,
                         embed: discord.Embed = None):
     user = ctx.message.author
     if embed:
         embed.description = prompt
         react_msg = await ctx.send(embed=embed)
     else:
         react_msg = await ctx.send(prompt)
     start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS)
     try:
         pred = ReactionPredicate.yes_or_no(react_msg, user)
         await ctx.bot.wait_for("reaction_add",
                                check=pred,
                                timeout=verify_timeout)
         if pred.result:
             return True
         if if_not_msg:
             await ctx.send(if_not_msg)
         return False
     except asyncio.TimeoutError:
         await ctx.send(
             "Sorry {}, you didn't react quick enough. Please try again.".
             format(user.mention))
         return False
Example #9
0
    async def _confirm(ctx: commands.Context) -> bool:
        """Ask "Are you sure?" and get the response as a bool."""
        if ctx.guild is None or ctx.guild.me.permissions_in(
                ctx.channel).add_reactions:
            msg = await ctx.send(_("Are you sure?"))
            # noinspection PyAsyncCall
            task = start_adding_reactions(msg,
                                          ReactionPredicate.YES_OR_NO_EMOJIS)
            pred = ReactionPredicate.yes_or_no(msg, ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
            except asyncio.TimeoutError:
                await ctx.send(_("Response timed out."))
                return False
            else:
                task.cancel()
                agreed = pred.result
            finally:
                await msg.delete()
        else:
            await ctx.send(_("Are you sure? (y/n)"))
            pred = MessagePredicate.yes_or_no(ctx)
            try:
                await ctx.bot.wait_for("message", check=pred, timeout=30)
            except asyncio.TimeoutError:
                await ctx.send(_("Response timed out."))
                return False
            else:
                agreed = pred.result

        if agreed is False:
            await ctx.send(_("Action cancelled."))
        return agreed
Example #10
0
    async def create_tag(
        self, ctx: commands.Context, tag_name: str, tagscript: str, *, global_tag: bool = False
    ):
        kwargs = {"author_id": ctx.author.id}

        if global_tag:
            guild = None
            tag = self.get_tag(None, tag_name, global_priority=True)
        else:
            guild = ctx.guild
            tag = self.get_tag(guild, tag_name, check_global=False)
            kwargs["guild_id"] = guild.id
        self.validate_tag_count(guild)

        if tag:
            tag_prefix = tag.name_prefix
            msg = await ctx.send(
                f"`{tag_name}` is already a registered {tag_prefix.lower()}. Would you like to overwrite it?"
            )
            start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
            pred = ReactionPredicate.yes_or_no(msg, ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
            except asyncio.TimeoutError:
                return await ctx.send(f"{tag_prefix} edit cancelled.")

            if pred.result is False:
                return await ctx.send(f"{tag_prefix} edit cancelled.")
            await ctx.send(await tag.edit_tagscript(tagscript))
            return

        tag = Tag(self, tag_name, tagscript, **kwargs)
        await ctx.send(await tag.initialize())
Example #11
0
    async def _confirm(ctx: commands.Context) -> bool:
        """Ask "Are you sure?" and get the response as a bool."""
        if ctx.guild is None or ctx.guild.me.permissions_in(ctx.channel).add_reactions:
            msg = await ctx.send(_("Are you sure?"))
            # noinspection PyAsyncCall
            task = start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop)
            pred = ReactionPredicate.yes_or_no(msg, ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
            except asyncio.TimeoutError:
                await ctx.send(_("Response timed out."))
                return False
            else:
                task.cancel()
                agreed = pred.result
            finally:
                await msg.delete()
        else:
            await ctx.send(_("Are you sure? (y/n)"))
            pred = MessagePredicate.yes_or_no(ctx)
            try:
                await ctx.bot.wait_for("message", check=pred, timeout=30)
            except asyncio.TimeoutError:
                await ctx.send(_("Response timed out."))
                return False
            else:
                agreed = pred.result

        if agreed is False:
            await ctx.send(_("Action cancelled."))
        return agreed
Example #12
0
    async def _profile_delete(self, ctx: commands.Context):
        """Deletes your profile permanently"""
        try:
            exists_msg = await ctx.author.send(
                "This cannot be undone and you will have to create a new profile, "
                "do you want to continue? (y/n)"
            )
            start_adding_reactions(exists_msg, ReactionPredicate.YES_OR_NO_EMOJIS)
            pred = ReactionPredicate.yes_or_no(exists_msg, ctx.author)
            await self.bot.wait_for("reaction_add", check=pred)
        except discord.Forbidden:
            return await ctx.send(f"I can't DM you, {ctx.author.mention}")

        if pred.result:
            user_group = self.profileConfig.user(ctx.author)
            async with user_group() as user_data:
                user_data.clear()
            account_group = self.config.user(ctx.author)
            async with account_group() as account_data:
                account_data.clear()
            await ctx.author.send(
                f"To created a new one please run `{self._profile_create.qualified_name}`"
            )
        else:
            await ctx.author.send("Your profile hasn't been touched")
Example #13
0
    async def reactrole_delete(
        self,
        ctx: commands.Context,
        message: Union[discord.Message, ObjectConverter],
    ):
        """Delete an entire reaction role for a message."""
        message_data = await self.config.custom("GuildMessage", ctx.guild.id, message.id).all()
        if not message_data["reactroles"]["react_to_roleid"]:
            return await ctx.send("There are no reaction roles set up for that message.")

        msg = await ctx.send(
            "Are you sure you want to remove all reaction roles for that message?"
        )
        start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
        pred = ReactionPredicate.yes_or_no(msg, ctx.author)
        try:
            await self.bot.wait_for("reaction_add", check=pred, timeout=60)
        except asyncio.TimeoutError:
            await ctx.send("Action cancelled.")

        if pred.result:
            await self.config.custom("GuildMessage", ctx.guild.id, message.id).clear()
            await ctx.send("Reaction roles cleared for that message.")
            self._edit_cache(message.id, True)
        else:
            await ctx.send("Action cancelled.")
Example #14
0
 async def einfo(self,
                 ctx,
                 *,
                 emoji: Union[discord.Emoji, discord.PartialEmoji] = None):
     """Get info about emoji"""
     if emoji is None:
         if ctx.channel.permissions_for(ctx.author).add_reactions:
             m = await ctx.send(_("React to this message with your emoji"))
             try:
                 reaction = await ctx.bot.wait_for(
                     "reaction_add",
                     check=ReactionPredicate.same_context(message=m,
                                                          user=ctx.author),
                     timeout=30,
                 )
                 emoji = reaction[0].emoji
             except AsyncTimeoutError:
                 return
             finally:
                 await m.delete(delay=0)
         else:
             await ctx.send_help()
             return
     em = await self.emoji_embed(ctx, emoji)
     await ctx.send(embed=em)
Example #15
0
async def add_reactions_with_cancel(
    ctx: Context,
    msg: discord.Message,
    emojis: Iterable[Union[str, discord.Emoji]],
    timeout: int = 30,
    with_keep: bool = False,
):
    """Add reactions with, for a limited time, author-only cancel."""
    _emojis = [emojis] if isinstance(emojis, str) else list(emojis)
    extra_emojis = []
    cancel = "\N{CROSS MARK}"
    _emojis.append(cancel)
    extra_emojis.append(cancel)
    if with_keep:
        keep = "\N{WHITE HEAVY CHECK MARK}"
        _emojis.append(keep)
        extra_emojis.append(keep)
    start_adding_reactions(msg, _emojis)
    pred = ReactionPredicate.with_emojis(extra_emojis, msg, user=ctx.author)

    try:
        await ctx.bot.wait_for("reaction_add", check=pred, timeout=timeout)
        if pred.result == 0:
            with contextlib.suppress(discord.HTTPException):
                await msg.delete()
                return True
    except asyncio.TimeoutError:
        pass
    with contextlib.suppress(discord.HTTPException):
        for emoji in extra_emojis:
            await msg.clear_reaction(emoji)
    return False
Example #16
0
 async def delete_trigger(self,
                          payload: discord.RawReactionActionEvent) -> None:
     """Enables and disables triggers"""
     member = self.ctx.guild.get_member(payload.user_id)
     if await self.cog.can_edit(member, self.source.selection):
         msg = await self.ctx.send(
             _("Are you sure you want to delete trigger {name}?").format(
                 name=self.source.selection.name))
         start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
         pred = ReactionPredicate.yes_or_no(msg, self.ctx.author)
         await self.ctx.bot.wait_for("reaction_add", check=pred)
         if pred.result:
             await msg.delete()
             self.source.selection.disable()
             done = await self.cog.remove_trigger(
                 payload.guild_id, self.source.selection.name)
             if done:
                 page = await self._source.get_page(self.current_page)
                 kwargs = await self._get_kwargs_from_page(page)
                 await self.message.edit(
                     content=_("This trigger has been deleted."),
                     embed=kwargs["embed"])
                 for t in self.cog.triggers[self.ctx.guild.id]:
                     if t.name == self.source.selection.name:
                         self.cog.triggers[self.ctx.guild.id].remove(t)
Example #17
0
    async def _choose_player(
        self, ctx: commands.Context, players: Tuple[rlapi.Player, ...]
    ) -> rlapi.Player:
        players_len = len(players)
        if players_len > 1:
            description = ""
            for idx, player in enumerate(players, 1):
                description += "\n{}. {} account with username: {}".format(
                    idx, player.platform, player.user_name
                )
            msg = await ctx.send(
                embed=discord.Embed(
                    title="There are multiple accounts with provided name:",
                    description=description,
                )
            )

            emojis = ReactionPredicate.NUMBER_EMOJIS[1 : players_len + 1]
            start_adding_reactions(msg, emojis)
            pred = ReactionPredicate.with_emojis(emojis, msg)

            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=15)
            except asyncio.TimeoutError:
                raise errors.NoChoiceError(
                    "User didn't choose profile he wants to check"
                )
            finally:
                await msg.delete()

            return players[pred.result]
        return players[0]
Example #18
0
 async def manifest(self, ctx: commands.Context) -> None:
     """
     See the current manifest version and optionally re-download it
     """
     version = await self.config.manifest_version()
     if not version:
         version = "Not Downloaded"
     await ctx.send(
         _("Current manifest version is {version}").format(version=version))
     await ctx.trigger_typing()
     msg = await ctx.send(_("Would you like to re-download the manifest?"))
     start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
     pred = ReactionPredicate.yes_or_no(msg, ctx.author)
     try:
         react, user = await self.bot.wait_for("reaction_add",
                                               check=pred,
                                               timeout=15)
     except asyncio.TimeoutError:
         await msg.delete()
     if pred.result:
         try:
             version = await self.get_manifest()
         except Exception:
             return await ctx.send(
                 _("There was an issue downloading the manifest."))
         await msg.delete()
         await ctx.send(f"Manifest {version} was downloaded.")
     else:
         await msg.delete()
Example #19
0
 async def verify_game_results(self, ctx, game, blue_team_wins,
                               orange_team_wins, verifier: discord.Member):
     msg = await ctx.send(
         "{0} Please verify the results:\n**{1}** {2} - {3} **{4}**".format(
             verifier.mention, game.blue.name, blue_team_wins,
             orange_team_wins, game.orange.name))
     start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
     game.scoreReported = True
     pred = ReactionPredicate.yes_or_no(msg, verifier)
     try:
         await ctx.bot.wait_for("reaction_add",
                                check=pred,
                                timeout=verify_timeout)
         if pred.result is True:
             return True
         else:
             game.scoreReported = False
             await ctx.send(
                 ":x: Ladder game result not verified. To report the result you will need to use the `{0}lr` command again."
                 .format(ctx.prefix))
             return False
     except asyncio.TimeoutError:
         game.scoreReported = False
         await ctx.send(
             ":x: Ladder game result not verified in time. To report the result you will need to use the `{0}lr` command again.\n"
             "**If one of the captains is afk, have someone from that team use the command.**"
             .format(ctx.prefix))
         return False
Example #20
0
 async def check_clear_event(self, ctx: commands.Context) -> bool:
     msg = await ctx.send(
         "You already have an event running, would you like to cancel it?")
     start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
     pred = ReactionPredicate.yes_or_no(msg, ctx.author)
     await ctx.bot.wait_for("reaction_add", check=pred)
     return pred.result
Example #21
0
    async def _embed_react_prompt(self,
                                  ctx,
                                  embed,
                                  existing_message=None,
                                  success_embed=None,
                                  reject_embed=None,
                                  clear_after_confirm=True):
        user = ctx.message.author
        if existing_message:
            react_msg = existing_message
            await react_msg.edit(embed=embed)
        else:
            react_msg = await ctx.send(embed=embed)

        start_adding_reactions(react_msg, ReactionPredicate.YES_OR_NO_EMOJIS)
        try:
            pred = ReactionPredicate.yes_or_no(react_msg, user)
            await ctx.bot.wait_for("reaction_add",
                                   check=pred,
                                   timeout=verify_timeout)
            if pred.result:
                await react_msg.edit(embed=success_embed)
                if clear_after_confirm:
                    await react_msg.clear_reactions()
                return True
            if reject_embed:
                await react_msg.edit(embed=reject_embed)
            return False
        except asyncio.TimeoutError:
            await react_msg.edit(embed=reject_embed)
            await ctx.send(
                "Sorry {}, you didn't react quick enough. Please try again.".
                format(user.mention))
            return False
Example #22
0
    async def buy_gem_skin(self, ctx: Context, user: discord.User,
                           config: Config, item_data: dict):
        brawler = item_data["brawler"]
        cost = item_data["cost"]
        skin = item_data["skin"]

        gems = await config.user(user).gems()

        if gems < cost:
            await ctx.send(f"You do not have enough gems! ({gems}/{cost})")
            return False

        msg = await ctx.send(
            f"{user.mention} Buying **{skin} {brawler}**"
            f" skin will cost {emojis['gem']} {cost}. Continue?")
        start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)

        pred = ReactionPredicate.yes_or_no(msg, user)
        await ctx.bot.wait_for("reaction_add", check=pred)
        if pred.result:
            # User responded with tick
            pass
        else:
            # User responded with cross
            await ctx.send("Purchase cancelled.")
            return False

        async with config.user(user).brawlers() as brawlers:
            brawlers[brawler]["skins"].append(skin)

        await config.user(user).gems.set(gems - cost)

        await ctx.send(f"Bought {skin} {brawler} skin!")

        return True
Example #23
0
    async def setup_delete_definition(self, ctx: commands.Context, definition_name:str) -> None:
        """Delete a defined game

        Note that this does delete any files or folders.

        Parameters
        ----------
        definition_name: str
            Name of the game to delete.
        """
        game_defs = await self._conf.game_defs()
        if definition_name not in game_defs.keys():
            return await self._embed_msg(
                ctx,
                title=_("No Such Definition"),
                description=_(f"{name} does not exist."),
                error=True
            )

        # Ask the user if they are really sure about this
        info_msg = _(
                "Are you sure you want to delete?:\n"
                "```\n"
                f"{definition_name}\n"
                "```\n"
                )
        info = await ctx.maybe_send_embed(info_msg)
        start_adding_reactions(info, ReactionPredicate.YES_OR_NO_EMOJIS)
        pred = ReactionPredicate.yes_or_no(info, ctx.author)
        await ctx.bot.wait_for("reaction_add", check=pred)
        # If user said no
        if not pred.result:
            with contextlib.suppress(discord.HTTPException):
                await info.delete()
            return
        else:
            # If an instance is running, shut it down
            if self._locks.get(definition_name, None) is not None:
                async with self._locks[definition_name]:
                    if self._instances.get(definition_name, None) is not None:
                        if self._instances[definition_name].isRunning():
                            self._instances[definition_name].stop()
            # Delete it from the list
            del game_defs[definition_name]
            await self._conf.game_defs.set(game_defs)
            # Delete the channel registrations
            defs_to_channels = await self._conf.defs_to_channels()
            channels_to_defs = await self._conf.channels_to_defs()
            for channel_id in channels_to_defs.keys():
                del channels_to_defs[channel_id]
            await self._conf.channels_to_defs.set(channels_to_defs)
            del defs_to_channels[definition_name]
            await self._conf.defs_to_channels.set(defs_to_channels)
            # Report success
            return await self._embed_msg(
                ctx,
                title=_("Deletion Successful"),
                description=_(f"{definition_name} has been deleted."),
                success=True
            )
Example #24
0
    async def convert(
        self, ctx: Context, argument: str
    ) -> Optional[Union[List[Dict[str, dict]], str]]:
        result: Optional[Union[List[Dict[str, dict]], str]] = []
        team_list = await check_valid_team(argument)
        my_perms = ctx.channel.permissions_for(ctx.guild.me)
        if team_list == []:
            raise BadArgument('Team "{}" not found'.format(argument))
        if len(team_list) == 1:
            result = team_list[0]
        else:
            # This is just some extra stuff to correct the team picker
            msg = _("There's multiple teams with that name, pick one of these:\n")
            new_msg = None
            if my_perms.add_reactions and my_perms.use_external_emojis:
                new_msg = await ctx.send(msg)
                team_emojis = [
                    await EmojiConverter().convert(ctx, "<:" + TEAMS[team]["emoji"] + ">")
                    for team in team_list
                ]
                log.debug(team_emojis)
                log.debug(team_list)
                pred = ReactionPredicate.with_emojis(team_emojis, message=new_msg)
                start_adding_reactions(new_msg, team_emojis)
                try:
                    reaction, user = await ctx.bot.wait_for("reaction_add", check=pred, timeout=60)
                except asyncio.TimeoutError:
                    await new_msg.edit(content=_("I guess not."))
                    return None
                else:
                    result = team_list[pred.result]
                    log.debug(result)
            else:
                for i, team_name in enumerate(team_list):
                    msg += "{}: {}\n".format(i + 1, team_name)

                def msg_check(m):
                    return m.author == ctx.message.author

                try:
                    msg = await ctx.bot.wait_for("message", check=msg_check, timeout=60)
                except asyncio.TimeoutError:
                    await new_msg.edit(content=_("I guess not."))
                    return None

                if msg.content.isdigit():
                    msg = int(msg.content) - 1
                    try:
                        result = team_list[msg]
                    except (IndexError, ValueError, AttributeError):
                        pass
                else:
                    return_team = None
                    for team in team_list:
                        if msg.content.lower() in team.lower():
                            return_team = team
                    result = return_team
            if new_msg:
                await new_msg.delete()
        return result
Example #25
0
	async def find_game_name(self, ctx, game_name):
		games = await self.get_games(ctx)
		match = get_close_matches(game_name, games.keys(), 1, 0.3)
		if not match:
			# No match was found. Returing a list of games.
			return

		# Found a match.
		msg = await ctx.send(f'I can\'t find a game called `{game_name}`.\nDid you mean `{match[0]}`?')
		start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)

		try: # Wait for a reaction on question
			pred = ReactionPredicate.yes_or_no(msg, ctx.author)
			await ctx.bot.wait_for("reaction_add", check=pred, timeout=15)
		except asyncio.TimeoutError:
			await ctx.send("You didn\'t react in time, cancelled.")

		try: # Delete reactions from question message
			if ctx.channel.permissions_for(ctx.me).manage_messages:
				await msg.clear_reactions()
		except:
			pass

		if pred.result is not True:
			return # User didn't responded with tick

		game_name = match[0]
		return game_name
Example #26
0
    async def leave_guilds(self, ctx: commands.Context, guilds: list, message: str):
        data = await self.config.all()
        unwl_guilds = [guild for guild in guilds if guild.id not in data["whitelist"]]
        if not unwl_guilds:
            await ctx.send("There are no servers to leave that aren't whitelisted.")
            return
        name_ids = "\n".join([f"{guild.name} - ({guild.id})" for guild in unwl_guilds][:5])
        guild_preview = name_ids + (
            f"\nand {len(unwl_guilds) - 5} other guilds.." if len(unwl_guilds) > 5 else ""
        )

        msg = await ctx.send(
            f"Are you sure you want me to leave the following {len(unwl_guilds)} guilds?\n"
            + box(guild_preview, "py")
        )
        start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
        pred = ReactionPredicate.yes_or_no(msg, ctx.author)
        try:
            await self.bot.wait_for("reaction_add", check=pred, timeout=60)
        except asyncio.TimeoutError:
            await ctx.send("Action cancelled.")

        if pred.result is True:
            async with ctx.typing():
                for guild in unwl_guilds:
                    await self.notify_guild(guild, message)
                    await guild.leave()
                await self.baron_log("mass_leave", guilds=unwl_guilds, author=ctx.author)
            await ctx.send(f"Done. I left {len(unwl_guilds)} servers.")
        else:
            await ctx.send("Action cancelled.")
Example #27
0
    async def tag_global_add(self, ctx: commands.Context, tag_name: TagName, *,
                             tagscript: TagScriptConverter):
        """
        Add a global tag with TagScript.

        [Tag usage guide](https://phen-cogs.readthedocs.io/en/latest/blocks.html#usage)
        """
        tag = self.get_tag(None, tag_name, check_global=True)
        if tag:
            msg = await ctx.send(
                f"`{tag_name}` is already registered global tag. Would you like to overwrite it?"
            )
            start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)
            pred = ReactionPredicate.yes_or_no(msg, ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
            except asyncio.TimeoutError:
                return await ctx.send("Global tag edit cancelled.")

            if pred.result is False:
                return await ctx.send("Global tag edit cancelled.")
            tag.tagscript = tagscript
            await tag.update_config()
            await ctx.send(f"Global tag `{tag}` edited.")
            return

        tag = Tag(self, tag_name, tagscript, author_id=ctx.author.id)
        self.global_tag_cache[tag_name] = tag
        await tag.update_config()
        await ctx.send(f"Global tag `{tag}` added.")
Example #28
0
async def yes_or_no(ctx, message) -> bool:
    msg = await ctx.send(message)
    start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)

    pred = ReactionPredicate.yes_or_no(msg, ctx.author)
    await ctx.bot.wait_for("reaction_add", check=pred)
    await msg.delete()
    return pred.result
Example #29
0
 async def icon_emoji(self,
                      ctx,
                      *,
                      emoji: Union[discord.Emoji,
                                   discord.PartialEmoji] = None):
     """Change icon of personal role using emoji"""
     role = await self.config.member(ctx.author).role()
     role = ctx.guild.get_role(role)
     if not emoji:
         if ctx.channel.permissions_for(ctx.author).add_reactions:
             m = await ctx.send(_("React to this message with your emoji"))
             try:
                 reaction = await ctx.bot.wait_for(
                     "reaction_add",
                     check=ReactionPredicate.same_context(message=m,
                                                          user=ctx.author),
                     timeout=30,
                 )
                 emoji = reaction[0].emoji
             except AsyncTimeoutError:
                 return
             finally:
                 await m.delete(delay=0)
         else:
             await ctx.send_help()
             return
     try:
         if isinstance(emoji, (discord.Emoji, discord.PartialEmoji)):
             await edit_role_icon(
                 self.bot,
                 role,
                 icon=await emoji.url_as(format="png").read(),
                 reason=get_audit_reason(ctx.author, _("Personal Role")),
             )
         else:
             await edit_role_icon(
                 self.bot,
                 role,
                 unicode_emoji=emoji,
                 reason=get_audit_reason(ctx.author, _("Personal Role")),
             )
     except discord.Forbidden:
         ctx.command.reset_cooldown(ctx)
         await ctx.send(
             chat.error(
                 _("Unable to edit role.\nRole must be lower than my top role"
                   )))
     except discord.InvalidArgument:
         await ctx.send(
             chat.error(
                 _("This image type is unsupported, or link is incorrect")))
     except discord.HTTPException as e:
         ctx.command.reset_cooldown(ctx)
         await ctx.send(chat.error(_("Unable to edit role: {}").format(e)))
     else:
         await ctx.send(
             _("Changed icon of {user}'s personal role").format(
                 user=ctx.message.author.name))
Example #30
0
    async def choose_cog(self, ctx: commands.Context,
                         cogs: List[commands.Cog]) -> Optional[commands.Cog]:
        """Ask user to choose a cog from provided `cogs` list."""
        if len(cogs) == 1:
            return cogs[0]
        cogs = sorted(cogs[:9], key=lambda cog: cog.qualified_name)
        emojis = ReactionPredicate.NUMBER_EMOJIS[1:len(cogs) + 1]
        use_embeds = await ctx.embed_requested()

        lines = []
        if use_embeds:
            for idx, cog in enumerate(cogs, 1):
                cog_name = cog.qualified_name
                short_doc, *_ = cog.format_help_for_context(ctx).partition(
                    "\n\n")

                if len(short_doc) > 70:
                    short_doc = f"{short_doc[:67]}..."

                lines.append(f"{idx}. {bold(cog_name)} - {short_doc}")

            description = "\n".join(lines)
            embed = discord.Embed(
                title="There are multiple categories with provided name:",
                description=description,
            )
            msg = await ctx.send(embed=embed)
        else:
            # all cog names should have the same width since only casing differs
            doc_max_width = 80 - len(cogs[0].qualified_name)

            for idx, cog in enumerate(cogs, 1):
                cog_name = cog.qualified_name
                short_doc, *_ = cog.format_help_for_context(ctx).partition(
                    "\n\n")

                if len(short_doc) > doc_max_width:
                    short_doc = f"{short_doc[: doc_max_width - 3]}..."

                lines.append(f"{idx}. {cog_name}: {short_doc}")

            description = "\n".join(lines)
            msg = await ctx.send(
                f"There are multiple categories with provided name: {box(description)}"
            )

        start_adding_reactions(msg, emojis)
        pred = ReactionPredicate.with_emojis(emojis, msg)
        try:
            await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
        except asyncio.TimeoutError:
            return None
        finally:
            await msg.delete()

        result = cast(int, pred.result)
        return cogs[result]
Example #31
0
    async def clean(self, ctx: commands.Context):
        """
        Dehoist all members in the guild.

        NOTE: If the server owner is hoisted, [botname] cannot change their nickname.
        """
        hoisted_count = await self.get_hoisted_count(ctx)

        guild_config = await self.config.guild(ctx.guild).all()
        nickname = guild_config["nickname"]
        ignored_users = guild_config["ignored_users"]

        if not hoisted_count:
            return await ctx.send("There are no hoisted members.")

        if not ctx.channel.permissions_for(ctx.me).add_reactions:
            return await ctx.send("I cannot add reactions.")

        if not ctx.channel.permissions_for(ctx.me).manage_nicknames:
            return await ctx.send("I do not have permission to edit nicknames."
                                  )

        msg = await ctx.send(
            f"Are you sure you would like to dehoist {hoisted_count} hoisted users? "
            f"This may take a few moments.\nTheir nickname's will be changed to `{nickname}`, "
            f"you can cancel now and change this nickname via `{ctx.clean_prefix}hoist set nickname` "
            "if you wish.")

        pred = ReactionPredicate.yes_or_no(msg, ctx.author)
        start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS)

        try:
            await self.bot.wait_for("reaction_add", check=pred, timeout=30)
        except asyncio.TimeoutError:
            await msg.delete()
            return await ctx.send(f"You took too long to respond.")

        if pred.result:
            await ctx.trigger_typing()
            exceptions = 0
            for m in ctx.guild.members:
                if m.display_name.startswith(
                        HOIST) and not m.bot and m.id not in ignored_users:
                    try:
                        await m.edit(
                            nick=await self.config.guild(ctx.guild).nickname())
                    except discord.Forbidden:
                        # This exception will only occur if an attempt is made to dehoist server owner
                        exceptions += 1
                        await ctx.send(
                            f"I could not change {ctx.guild.owner.name}'s nickname because I cannot edit owner nicknames."
                        )
            await ctx.send(
                f"{hoisted_count - exceptions} users have been dehoisted.")
        else:
            await ctx.send("No changes have been made.")
Example #32
0
    async def _cog_update(self, ctx, cog_name: InstalledCog = None):
        """Update all cogs, or one of your choosing."""
        installed_cogs = set(await self.installed_cogs())

        async with ctx.typing():
            if cog_name is None:
                updated = await self._repo_manager.update_all_repos()

            else:
                try:
                    updated = await self._repo_manager.update_repo(cog_name.repo_name)
                except KeyError:
                    # Thrown if the repo no longer exists
                    updated = {}

            updated_cogs = set(cog for repo in updated for cog in repo.available_cogs)
            installed_and_updated = updated_cogs & installed_cogs

            if installed_and_updated:
                await self._reinstall_requirements(installed_and_updated)
                await self._reinstall_cogs(installed_and_updated)
                await self._reinstall_libraries(installed_and_updated)
                message = _("Cog update completed successfully.")

                cognames = {c.name for c in installed_and_updated}
                message += _("\nUpdated: ") + humanize_list(tuple(map(inline, cognames)))
            else:
                await ctx.send(_("All installed cogs are already up to date."))
                return
        await ctx.send(message)

        cognames &= set(ctx.bot.extensions.keys())  # only reload loaded cogs
        if not cognames:
            return await ctx.send(
                _("None of the updated cogs were previously loaded. Update complete.")
            )
        message = _("Would you like to reload the updated cogs?")
        can_react = ctx.channel.permissions_for(ctx.me).add_reactions
        if not can_react:
            message += " (y/n)"
        query: discord.Message = await ctx.send(message)
        if can_react:
            # noinspection PyAsyncCall
            start_adding_reactions(query, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop)
            pred = ReactionPredicate.yes_or_no(query, ctx.author)
            event = "reaction_add"
        else:
            pred = MessagePredicate.yes_or_no(ctx)
            event = "message"
        try:
            await ctx.bot.wait_for(event, check=pred, timeout=30)
        except asyncio.TimeoutError:
            await query.delete()
            return

        if pred.result is True:
            if can_react:
                with contextlib.suppress(discord.Forbidden):
                    await query.clear_reactions()
            await ctx.invoke(ctx.bot.get_cog("Core").reload, *cognames)
        else:
            if can_react:
                await query.delete()
            else:
                await ctx.send(_("OK then."))