Esempio n. 1
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]}
Esempio n. 2
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
Esempio n. 3
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]
Esempio n. 4
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
Esempio n. 5
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]
Esempio n. 6
0
    async def _wait_for_game(self, ctx):
        # TODO: Seperate Teams

        embed = discord.Embed(title="Respond with the 🏁 when the game is done")

        msg = await self.village_channel.send(embed=embed)
        start_adding_reactions(msg, "🏁")

        pred = ReactionPredicate.with_emojis(emojis="🏁", message=msg)
        await ctx.bot.wait_for("reaction_add", check=pred)
 
        await msg.delete()
Esempio n. 7
0
async def message_type_reaction(ctx,
                                embed: discord.Embed,
                                emojis: list = None):
    msg: discord.Message = await ctx.send(embed=embed)
    if emojis is None:
        emojis = ["⚠", "💬"]
    start_adding_reactions(msg, emojis)

    pred = ReactionPredicate.with_emojis(emojis, msg)
    await ctx.bot.wait_for("reaction_add", check=pred)
    await msg.delete()
    await ctx.send("Thank-you. Someone will reply shortly, please be patient")
    return pred.result
Esempio n. 8
0
    async def coinhunt(self, ctx):
        """Start a game of coinhunt"""

        game = CoinGame()
        msg = await ctx.send("```\nLoading...\n```")
        try:
            for emoji in EMOJIS:
                await msg.add_reaction(emoji)

        except discord.HTTPException:
            await ctx.send("```/nThere was an error! Please try again./n```")
            return

        while game.stats['moves'] > 0 and game.stats['coins'] != game.stats[
                'max_coins']:
            await msg.edit(content=f"```\n{game.render()}\n```")
            pred = ReactionPredicate.with_emojis(EMOJIS,
                                                 message=msg,
                                                 user=ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=60)
            except asyncio.TimeoutError:
                await msg.clear_reactions()
                break
            emoji = EMOJIS[int(pred.result)]
            if emoji == '❌':
                await msg.clear_reactions()
                await msg.edit(content="```\nGame was cancelled\n```")
                break
            elif emoji == '🔼':
                direction = Direction.up
            elif emoji == '🔽':
                direction = Direction.down
            elif emoji == '▶️':
                direction = Direction.right
            elif emoji == '◀️':
                direction = Direction.left
            game.move_player(direction)
            try:
                await msg.remove_reaction(emoji, ctx.author)
            except discord.HTTPException:
                pass
        score = game.stats['coins'] + game.stats['moves']
        if game.stats['moves'] == 0:
            await msg.edit(
                content=f"```\nUh oh, Game Over. Your score: {score}\n```")
        elif game.stats['coins'] == game.stats['max_coins']:
            await msg.edit(
                content=
                f"```\nCongratulations! You Win. Your score: {score}\n```")
        await msg.clear_reactions()
Esempio n. 9
0
    async def get_confirmation(self, ctx: commands.Context, msg: discord.Message) -> Optional[bool]:
        """Get confirmation from user with reactions"""
        emojis = ["❌", "✅"]
        start_adding_reactions(msg, emojis)

        try:
            reaction, _ = await self.bot.wait_for(
                "reaction_add", timeout=180.0, check=ReactionPredicate.with_emojis(emojis, msg, ctx.author)
            )
        except asyncio.TimeoutError:
            await msg.clear_reactions()
            return
        else:
            await msg.clear_reactions()
            return bool(emojis.index(reaction.emoji))
Esempio n. 10
0
    async def quickcast(self, ctx:commands.Context, bait_type:str):
        """Rolls for a fish - similar to cast, but you do not get to choose the fish to reel in, instead instantly rolling and choosing to keep/release a fish

         - Must be used in a channel registered as a pool"""

        if not await self.IsSpecialized(ctx.guild, ctx.channel.id, POOL_CHANNEL):
            return
        profile = self.config.member(ctx.message.author)

        await profile.currently_fishing.set(True)
        modified_fish_weights = await self.startfishing(ctx, profile, bait_type)

        rarity = choices(FISH_RARITIES, modified_fish_weights)[0]
        rarity_list = self.fishing_rarities.get(rarity)
        curr_fish = rarity_list[randint(0, len(rarity_list) - 1)] if not await profile.bryan_mode() else self.SEA_BASS
        new_fish = curr_fish.ToFishCatch(RARITY_VALUES[rarity])

        embed = Embed(title=f'{ctx.message.author.display_name} cast their rod into the shimmering waves at {ctx.channel}', color=0x7300ff)
        embed.set_footer(text=f'You pulled a {new_fish["name"]} ({new_fish["size"]} inches) out of the water!\nDo you want to keep or release?')
        embed.set_thumbnail(url=curr_fish.image)
        msg = await ctx.send(embed=embed)
        start_adding_reactions(msg, ['🥤', '🐟'])

        pred = ReactionPredicate.with_emojis(['🥤', '🐟'], msg, ctx.author)
        try:
            await ctx.bot.wait_for('reaction_add', check=pred, timeout=15)
        except asyncio.TimeoutError:
            pred.result = 0

        if pred.result == 0:
            if await self.AddFish(ctx.message.author, new_fish):
                embed.set_footer(text=f'{new_fish["name"]} was added to your bucket!')
            else:
                embed.set_footer(text=f'Your bucket was full, so you had to release {new_fish["name"]} :(')
        else:
            embed.set_footer(text=f'You let {new_fish["name"]} swim away...')
        await msg.edit(embed=embed)
        await msg.clear_reactions()

        user_bait = await profile.bait()
        user_bait[bait_type] -= 1
        await profile.bait.set(user_bait)

        await profile.currently_fishing.set(False)
        #if not await profile.mawiam_mode():
        #await profile.nextcast.set(time() + await self.GetSetting(ctx.guild, 'fishing_delay'))

        await self.CheckSchools(ctx)
Esempio n. 11
0
    async def sex_select(self, ctx: commands.Context, embed: Embed,
                         message: discord.Message) -> bool:
        """Requests information from the member about the sex of the
        character being registered.

        Args:
            ctx (commands.Context): Same as `RegisterSession.ctx`
            embed (Embed): Same as `RegisterSession.embed`
            message (discord.Message): Same as `RegisterSession.message`

        Returns:
            bool: Whether the correct information is received or not.

        """
        embed.description = "**Выберите пол персонажа**\n\n"
        await message.edit(embed=embed)
        genders = {"👨": "male", "👩": "female"}
        try:

            for gender in genders.keys():
                await message.add_reaction(gender)
            react, member = await self.ctx.bot.wait_for(
                "reaction_add",
                timeout=60.0,
                check=ReactionPredicate.with_emojis(tuple(genders.keys()),
                                                    message, ctx.author),
            )
            await message.clear_reactions()
            self.char["sex"] = genders[react.emoji]
            embed.add_field(
                name="Пол",
                value=config.humanize.genders[genders[react.emoji]].title(),
                inline=True,
            )
            await message.edit(embed=embed)
            return True
        except asyncio.TimeoutError:
            try:
                await message.clear_reactions()
            except discord.Forbidden:  # cannot remove all reactions
                for gender in genders.keys():
                    await message.remove_reaction(gender, ctx.bot.user)
            except discord.NotFound:
                return False
            await self.cancel(embed, message)
            return False
Esempio n. 12
0
    async def convert(self, ctx, argument):
        try:
            c = await Character._from_json(ctx.bot.get_cog("Adventure").config, ctx.author)
        except Exception:
            log.exception("Error with the new character sheet")
            return
        no_markdown = Item._remove_markdowns(argument)
        lookup = list(i for x, i in c.backpack.items() if no_markdown.lower() in x.lower())
        lookup_m = list(i for x, i in c.backpack.items() if argument.lower() == str(i).lower())
        if len(lookup) == 1:
            return lookup[0]
        elif len(lookup_m) == 1:
            return lookup_m[0]
        elif len(lookup) == 0 and len(lookup_m) == 0:
            raise BadArgument(
                _("`{}` doesn't seem to match any items in your backpack.").format(argument)
            )
        else:
            if len(lookup) > 10:
                raise BadArgument(
                    _("You have too many items matching the name `{}`,"
                      " please be more specific").format(
                        argument
                    )
                )
            items = ""
            for number, item in enumerate(lookup):
                items += f"{number}. {str(item)} (owned {item.owned})\n"

            msg = await ctx.send(
                    _("Multiple items share that name, which one would you like?\n{items}").format(
                        items=box(items, lang="css")
                    )
                )
            emojis = ReactionPredicate.NUMBER_EMOJIS[:len(lookup)]
            start_adding_reactions(msg, emojis)
            pred = ReactionPredicate.with_emojis(emojis, msg, user=ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
            except asyncio.TimeoutError:
                raise BadArgument(_("Alright then."))
            return lookup[pred.result]
Esempio n. 13
0
    async def drop(self, ctx):  # ?drop command

        # locations without picture (labeled)
        marked_list = [
            'shark!', 'yacht!', 'grotto!', 'rig!', 'craggy cliffs!',
            'steamy stacks!', 'pleasant park!', 'sweaty sands!',
            'frenzy farm!', 'dirty docks!', 'holly hedges!', 'weeping woods!',
            'lazy lake!', 'retail row!', 'slurpy swamp!', 'misty meadows!'
        ]

        # before '!' has to correspond with picture in /map/
        unmarked_list = [
            'apres ski! D8', 'box factory! G7', 'compact cars! G4',
            'coral cove! A2', 'crash site! B2', 'fancy view! A4',
            'fn radio! F2', 'hydro 16! D7', 'lockies lighthouse! C1',
            'logjam woodworks! B6', 'orchard! F3', 'pristine point! G1',
            'risky reels! E4'
        ]

        if random.randint(1, 2) == 1:
            the_drop = random.choice(marked_list)
            unmarked = False
        else:
            the_drop = random.choice(unmarked_list)
            drop_filename = the_drop[:-4]
            unmarked = True
            drop_map = f'map/{drop_filename}.png'

        if unmarked == False:
            repeat = await ctx.send(the_drop)

        if unmarked == True:
            await ctx.send(the_drop)
            my_path = os.path.abspath(os.path.dirname(__file__))
            path = os.path.join(my_path, drop_map)
            repeat = await ctx.send(file=discord.File(path))

        start_adding_reactions(repeat, "🔁")
        pred = ReactionPredicate.with_emojis("🔁", repeat)
        await ctx.bot.wait_for("reaction_add", check=pred)
        await ctx.invoke(self.drop)
Esempio n. 14
0
    async def get_user_choice(self, ctx: Context, embed, end, first_player,
                              second_player):
        try:
            msg = await first_player.send(embed=embed)

            react_emojis = ReactionPredicate.NUMBER_EMOJIS[1:end + 1]
            start_adding_reactions(msg, react_emojis)

            pred = ReactionPredicate.with_emojis(react_emojis, msg)
            await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)

            # pred.result is  the index of the number in `emojis`
            return pred.result + 1
        except asyncio.TimeoutError:
            await ctx.send(f"{first_player.name} took too long to respond.")
            raise asyncio.TimeoutError
        except discord.Forbidden:
            await ctx.send(f"{first_player.mention} {second_player.mention}"
                           f" Reason: Unable to DM {first_player.name}."
                           " DMs are required to brawl!")
            raise
Esempio n. 15
0
async def menu(ctx, update=None, timeout=30):
    perms = ctx.channel.permissions_for(ctx.me)
    if not perms.embed_links or not perms.add_reactions:
        raise BMP(embed_links=True, add_reactions=True)
    update = update or Update(ctx.message.created_at)
    message = await ctx.send(embed=update.embed(now=ctx.message.created_at))
    start_adding_reactions(message, reactions, loop=ctx.bot.loop)
    first = True
    while True:
        if first:
            first = False
        else:
            await message.edit(embed=update.embed(now=ctx.message.created_at))
        pred = ReactionPredicate.with_emojis(reactions, message, ctx.author)
        try:
            await ctx.bot.wait_for("reaction_add", check=pred, timeout=timeout)
        except asyncio.TimeoutError:
            with suppress(discord.HTTPException):
                await message.delete()
            return None
        if pred.result == 0:
            upd = update[-1]
            if upd.end.timestamp() >= ctx.message.created_at.timestamp():
                update = upd
        elif pred.result == 1:
            with suppress(discord.HTTPException):
                await message.clear_reactions()
            return update
        elif pred.result == 2:
            with suppress(discord.HTTPException):
                await message.delete()
            return None
        elif pred.result == 3:
            update = update[1]
        with suppress(discord.HTTPException):
            # pylint: disable=E1126
            await message.remove_reaction(reactions[pred.result], ctx.author)
Esempio n. 16
0
    def _give_me_tasks(self) -> list:
        def leave_check(u):
            return u.id == self.member.id

        return [
            asyncio.create_task(
                self.bot.wait_for(
                    "reaction_add",
                    check=ReactionPredicate.with_emojis(
                        "🔁",
                        message=self.messages["bot_challenge"],
                        user=self.member),
                )),
            asyncio.create_task(
                self.bot.wait_for(
                    "message",
                    check=MessagePredicate.same_context(
                        channel=self.channel,
                        user=self.member,
                    ),
                )),
            asyncio.create_task(
                self.bot.wait_for("user_remove", check=leave_check)),
        ]
Esempio n. 17
0
async def get_option_reaction(
    ctx,
    message: str = None,
    embed: discord.Embed = None,
):
    if not embed:
        msg = await ctx.send(
            message,
            delete_after=30,
        )
    else:
        msg = await ctx.send(
            embed=embed,
            delete_after=30,
        )
    emojis = ReactionPredicate.NUMBER_EMOJIS[1:6]
    # Action 1: Do Nothing (still fire event)
    # Action 2: Message
    # Action 3 : Add Role
    # Action 4: Kick
    # Action 5: Ban
    start_adding_reactions(
        msg,
        emojis,
    )

    pred = ReactionPredicate.with_emojis(
        emojis,
        msg,
        ctx.author,
    )
    react = await ctx.bot.wait_for(
        "reaction_add",
        check=pred,
    )
    return await action_to_take_mapping(pred.result)
Esempio n. 18
0
    async def _open_chest(self, ctx: commands.Context, user, chest_type,
                          character):
        if hasattr(user, "display_name"):
            chest_msg = _(
                "{} is opening a treasure chest. What riches lay inside?"
            ).format(escape(user.display_name))
        else:
            chest_msg = _(
                "{user}'s {f} is foraging for treasure. What will it find?"
            ).format(user=escape(ctx.author.display_name),
                     f=(user[:1] + user[1:]))
        open_msg = await ctx.send(box(chest_msg, lang="css"))
        await asyncio.sleep(2)
        item = await self._roll_chest(chest_type, character)
        if chest_type == "pet" and not item:
            await open_msg.edit(content=box(
                _("{c_msg}\nThe {user} found nothing of value.").format(
                    c_msg=chest_msg, user=(user[:1] + user[1:])),
                lang="css",
            ))
            return None
        slot = item.slot[0]
        old_item = getattr(character, item.slot[0], None)
        old_stats = ""

        if old_item:
            old_slot = old_item.slot[0]
            if len(old_item.slot) > 1:
                old_slot = _("two handed")
                att = old_item.att * 2
                cha = old_item.cha * 2
                intel = old_item.int * 2
                luck = old_item.luck * 2
                dex = old_item.dex * 2
            else:
                att = old_item.att
                cha = old_item.cha
                intel = old_item.int
                luck = old_item.luck
                dex = old_item.dex

            old_stats = (_(
                "You currently have {item} [{slot}] equipped | Lvl req {lv} equipped."
            ).format(item=old_item,
                     slot=old_slot,
                     lv=character.equip_level(old_item)) +
                         f" (ATT: {str(att)}, "
                         f"CHA: {str(cha)}, "
                         f"INT: {str(intel)}, "
                         f"DEX: {str(dex)}, "
                         f"LUCK: {str(luck)}) ")
        if len(item.slot) > 1:
            slot = _("two handed")
            att = item.att * 2
            cha = item.cha * 2
            intel = item.int * 2
            luck = item.luck * 2
            dex = item.dex * 2
        else:
            att = item.att
            cha = item.cha
            intel = item.int
            luck = item.luck
            dex = item.dex
        if hasattr(user, "display_name"):
            chest_msg2 = (
                _("{user} found {item} [{slot}] | Lvl req {lv}.").format(
                    user=escape(user.display_name),
                    item=str(item),
                    slot=slot,
                    lv=character.equip_level(item),
                ) + f" (ATT: {str(att)}, "
                f"CHA: {str(cha)}, "
                f"INT: {str(intel)}, "
                f"DEX: {str(dex)}, "
                f"LUCK: {str(luck)}) ")

            await open_msg.edit(content=box(
                _("{c_msg}\n\n{c_msg_2}\n\nDo you want to equip "
                  "this item, put in your backpack, or sell this item?\n\n"
                  "{old_stats}").format(c_msg=chest_msg,
                                        c_msg_2=chest_msg2,
                                        old_stats=old_stats),
                lang="css",
            ))
        else:
            chest_msg2 = (
                _("The {user} found {item} [{slot}] | Lvl req {lv}.").format(
                    user=user,
                    item=str(item),
                    slot=slot,
                    lv=character.equip_level(item)) + f" (ATT: {str(att)}, "
                f"CHA: {str(cha)}, "
                f"INT: {str(intel)}, "
                f"DEX: {str(dex)}, "
                f"LUCK: {str(luck)}), ")
            await open_msg.edit(content=box(
                _("{c_msg}\n{c_msg_2}\nDo you want to equip "
                  "this item, put in your backpack, or sell this item?\n\n{old_stats}"
                  ).format(c_msg=chest_msg,
                           c_msg_2=chest_msg2,
                           old_stats=old_stats),
                lang="css",
            ))

        start_adding_reactions(open_msg, self._treasure_controls.keys())
        if hasattr(user, "id"):
            pred = ReactionPredicate.with_emojis(
                tuple(self._treasure_controls.keys()), open_msg, user)
        else:
            pred = ReactionPredicate.with_emojis(
                tuple(self._treasure_controls.keys()), open_msg, ctx.author)
        try:
            react, user = await self.bot.wait_for("reaction_add",
                                                  check=pred,
                                                  timeout=60)
        except asyncio.TimeoutError:
            await self._clear_react(open_msg)
            await character.add_to_backpack(item)
            await open_msg.edit(content=(box(
                _("{user} put the {item} into their backpack.").format(
                    user=escape(ctx.author.display_name), item=item),
                lang="css",
            )))
            await self.config.user(ctx.author
                                   ).set(await
                                         character.to_json(ctx, self.config))
            return
        await self._clear_react(open_msg)
        if self._treasure_controls[react.emoji] == "sell":
            price = _sell(character, item)
            price = max(price, 0)
            if price > 0:
                try:
                    await bank.deposit_credits(ctx.author, price)
                except BalanceTooHigh as e:
                    await bank.set_balance(ctx.author, e.max_balance)
            currency_name = await bank.get_currency_name(ctx.guild, )
            if str(currency_name).startswith("<"):
                currency_name = "credits"
            await open_msg.edit(content=(box(
                _("{user} sold the {item} for {price} {currency_name}.").
                format(
                    user=escape(ctx.author.display_name),
                    item=item,
                    price=humanize_number(price),
                    currency_name=currency_name,
                ),
                lang="css",
            )))
            await self._clear_react(open_msg)
            character.last_known_currency = await bank.get_balance(ctx.author)
            character.last_currency_check = time.time()
            await self.config.user(ctx.author
                                   ).set(await
                                         character.to_json(ctx, self.config))
        elif self._treasure_controls[react.emoji] == "equip":
            equiplevel = character.equip_level(item)
            if is_dev(ctx.author):
                equiplevel = 0
            if not character.can_equip(item):
                await character.add_to_backpack(item)
                await self.config.user(ctx.author).set(await character.to_json(
                    ctx, self.config))
                return await smart_embed(
                    ctx,
                    f"**{escape(ctx.author.display_name)}**, you need to be level "
                    f"`{equiplevel}` to equip this item. I've put it in your backpack.",
                )
            if not getattr(character, item.slot[0]):
                equip_msg = box(
                    _("{user} equipped {item} ({slot} slot).").format(
                        user=escape(ctx.author.display_name),
                        item=item,
                        slot=slot),
                    lang="css",
                )
            else:
                equip_msg = box(
                    _("{user} equipped {item} ({slot} slot) and put {old_item} into their backpack."
                      ).format(
                          user=escape(ctx.author.display_name),
                          item=item,
                          slot=slot,
                          old_item=getattr(character, item.slot[0]),
                      ),
                    lang="css",
                )
            await open_msg.edit(content=equip_msg)
            character = await character.equip_item(item, False,
                                                   is_dev(ctx.author))
            await self.config.user(ctx.author
                                   ).set(await
                                         character.to_json(ctx, self.config))
        else:
            await character.add_to_backpack(item)
            await open_msg.edit(content=(box(
                _("{user} put the {item} into their backpack.").format(
                    user=escape(ctx.author.display_name), item=item),
                lang="css",
            )))
            await self._clear_react(open_msg)
            await self.config.user(ctx.author
                                   ).set(await
                                         character.to_json(ctx, self.config))
Esempio n. 19
0
    async def command_now(self, ctx: commands.Context):
        """Now playing."""
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        emoji = {
            "prev":
            "\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\N{VARIATION SELECTOR-16}",
            "stop": "\N{BLACK SQUARE FOR STOP}\N{VARIATION SELECTOR-16}",
            "pause":
            "\N{BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR}\N{VARIATION SELECTOR-16}",
            "next":
            "\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\N{VARIATION SELECTOR-16}",
            "close": "\N{CROSS MARK}",
        }
        expected = tuple(emoji.values())
        player = lavalink.get_player(ctx.guild.id)
        player.store("notify_channel", ctx.channel.id)
        if player.current:
            arrow = await self.draw_time(ctx)
            pos = self.format_time(player.position)
            if player.current.is_stream:
                dur = "LIVE"
            else:
                dur = self.format_time(player.current.length)
            song = (await self.get_track_description(
                player.current, self.local_folder_current_path) or "")
            song += _("\n Requested by: **{track.requester}**").format(
                track=player.current)
            song += "\n\n{arrow}`{pos}`/`{dur}`".format(arrow=arrow,
                                                        pos=pos,
                                                        dur=dur)
        else:
            song = _("Nothing.")

        if player.fetch("np_message") is not None:
            with contextlib.suppress(discord.HTTPException):
                await player.fetch("np_message").delete()
        embed = discord.Embed(title=_("Now Playing"), description=song)
        guild_data = await self.config.guild(ctx.guild).all()

        if guild_data[
                "thumbnail"] and player.current and player.current.thumbnail:
            embed.set_thumbnail(url=player.current.thumbnail)
        shuffle = guild_data["shuffle"]
        repeat = guild_data["repeat"]
        autoplay = guild_data["auto_play"]
        text = ""
        text += (
            _("Auto-Play") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if autoplay else "\N{CROSS MARK}"))
        text += (
            (" | " if text else "") + _("Shuffle") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if shuffle else "\N{CROSS MARK}"))
        text += (
            (" | " if text else "") + _("Repeat") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if repeat else "\N{CROSS MARK}"))

        message = await self.send_embed_msg(ctx, embed=embed, footer=text)

        player.store("np_message", message)

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
        if ((dj_enabled or vote_enabled)
                and not await self._can_instaskip(ctx, ctx.author)
                and not await self.is_requester_alone(ctx)):
            return

        if not player.queue and not autoplay:
            expected = (emoji["stop"], emoji["pause"], emoji["close"])
        task: Optional[asyncio.Task]
        if player.current:
            task = start_adding_reactions(message, expected[:5])
        else:
            task = None

        try:
            (r, u) = await self.bot.wait_for(
                "reaction_add",
                check=ReactionPredicate.with_emojis(expected, message,
                                                    ctx.author),
                timeout=30.0,
            )
        except asyncio.TimeoutError:
            return await self._clear_react(message, emoji)
        else:
            if task is not None:
                task.cancel()
        reacts = {v: k for k, v in emoji.items()}
        react = reacts[r.emoji]
        if react == "prev":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_prev)
        elif react == "stop":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_stop)
        elif react == "pause":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_pause)
        elif react == "next":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_skip)
        elif react == "close":
            await message.delete()
Esempio n. 20
0
    async def command_queue(self, ctx: commands.Context, *, page: int = 1):
        """List the songs in the queue."""

        # Check to avoid an IndexError further down in the code.
        if page < 1:
            page = 1

        async def _queue_menu(
            ctx: commands.Context,
            pages: list,
            controls: MutableMapping,
            message: discord.Message,
            page: int,
            timeout: float,
            emoji: str,
        ):
            if message:
                await ctx.send_help(self.command_queue)
                with contextlib.suppress(discord.HTTPException):
                    await message.delete()
                return None

        queue_controls = {
            "\N{LEFTWARDS BLACK ARROW}\N{VARIATION SELECTOR-16}": prev_page,
            "\N{CROSS MARK}": close_menu,
            "\N{BLACK RIGHTWARDS ARROW}\N{VARIATION SELECTOR-16}": next_page,
            "\N{INFORMATION SOURCE}\N{VARIATION SELECTOR-16}": _queue_menu,
        }

        if not self._player_check(ctx):
            return await self.send_embed_msg(
                ctx, title=_("There's nothing in the queue."))
        player = lavalink.get_player(ctx.guild.id)

        if player.current and not player.queue:
            arrow = await self.draw_time(ctx)
            pos = self.format_time(player.position)
            if player.current.is_stream:
                dur = "LIVE"
            else:
                dur = self.format_time(player.current.length)
            song = (await self.get_track_description(
                player.current, self.local_folder_current_path) or "")
            song += _("\n Requested by: **{track.requester}**").format(
                track=player.current)
            song += f"\n\n{arrow}`{pos}`/`{dur}`"
            embed = discord.Embed(title=_("Now Playing"), description=song)
            guild_data = await self.config.guild(ctx.guild).all()
            if guild_data[
                    "thumbnail"] and player.current and player.current.thumbnail:
                embed.set_thumbnail(url=player.current.thumbnail)

            shuffle = guild_data["shuffle"]
            repeat = guild_data["repeat"]
            autoplay = guild_data["auto_play"]
            text = ""
            text += (_("Auto-Play") + ": " + ("\N{WHITE HEAVY CHECK MARK}" if
                                              autoplay else "\N{CROSS MARK}"))
            text += ((" | " if text else "") + _("Shuffle") + ": " +
                     ("\N{WHITE HEAVY CHECK MARK}"
                      if shuffle else "\N{CROSS MARK}"))
            text += (
                (" | " if text else "") + _("Repeat") + ": " +
                ("\N{WHITE HEAVY CHECK MARK}" if repeat else "\N{CROSS MARK}"))
            embed.set_footer(text=text)
            message = await self.send_embed_msg(ctx, embed=embed)
            dj_enabled = self._dj_status_cache.setdefault(
                ctx.guild.id, guild_data["dj_enabled"])
            vote_enabled = guild_data["vote_enabled"]
            if ((dj_enabled or vote_enabled)
                    and not await self._can_instaskip(ctx, ctx.author)
                    and not await self.is_requester_alone(ctx)):
                return

            emoji = {
                "prev":
                "\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\N{VARIATION SELECTOR-16}",
                "stop": "\N{BLACK SQUARE FOR STOP}\N{VARIATION SELECTOR-16}",
                "pause":
                "\N{BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR}\N{VARIATION SELECTOR-16}",
                "next":
                "\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\N{VARIATION SELECTOR-16}",
                "close": "\N{CROSS MARK}",
            }
            expected = tuple(emoji.values())
            if not player.queue and not autoplay:
                expected = (emoji["stop"], emoji["pause"], emoji["close"])
            if player.current:
                task: Optional[asyncio.Task] = start_adding_reactions(
                    message, expected[:5])
            else:
                task: Optional[asyncio.Task] = None

            try:
                (r, u) = await self.bot.wait_for(
                    "reaction_add",
                    check=ReactionPredicate.with_emojis(
                        expected, message, ctx.author),
                    timeout=30.0,
                )
            except asyncio.TimeoutError:
                return await self._clear_react(message, emoji)
            else:
                if task is not None:
                    task.cancel()
            reacts = {v: k for k, v in emoji.items()}
            react = reacts[r.emoji]
            if react == "prev":
                await self._clear_react(message, emoji)
                await ctx.invoke(self.command_prev)
            elif react == "stop":
                await self._clear_react(message, emoji)
                await ctx.invoke(self.command_stop)
            elif react == "pause":
                await self._clear_react(message, emoji)
                await ctx.invoke(self.command_pause)
            elif react == "next":
                await self._clear_react(message, emoji)
                await ctx.invoke(self.command_skip)
            elif react == "close":
                await message.delete()
            return
        elif not player.current and not player.queue:
            return await self.send_embed_msg(
                ctx, title=_("There's nothing in the queue."))

        async with ctx.typing():
            limited_queue = player.queue[:
                                         500]  # TODO: Improve when Toby menu's are merged
            len_queue_pages = math.ceil(len(limited_queue) / 10)
            queue_page_list = []
            async for page_num in AsyncIter(range(1, len_queue_pages + 1)):
                embed = await self._build_queue_page(ctx, limited_queue,
                                                     player, page_num)
                queue_page_list.append(embed)
            if page > len_queue_pages:
                page = len_queue_pages
        return await menu(ctx,
                          queue_page_list,
                          queue_controls,
                          page=(page - 1))
Esempio n. 21
0
    async def coinhunt(self, ctx):
        """
        A Small Minigame where main objective is to collect coins in limited number of moves.

        [@] : Player
        [·] : Visited
        [○] : Coin
        [+] : Power-Ups
        [R] : Reveal-Shard
        """

        game = CoinGame()
        msg = await ctx.send("```\nLoading...\n```")
        try:
            for emoji in EMOJIS:
                await msg.add_reaction(emoji)

        except discord.HTTPException:
            await ctx.send("```/nThere was an error! Please try again./n```")
            return

        while game.stats['moves'] > 0 and game.stats['coins'] != game.stats[
                'max_coins']:
            await msg.edit(content=f"```\n{game.render()}\n```")
            pred = ReactionPredicate.with_emojis(EMOJIS,
                                                 message=msg,
                                                 user=ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred)
            except asyncio.TimeoutError:
                await msg.clear_reactions()
                return
            emoji = EMOJIS[pred.result]
            if emoji == '❌':
                await msg.clear_reactions()
                await msg.edit(content="```\nGame was cancelled\n```")
                return
            elif emoji == '🔼':
                direction = Direction.up
            elif emoji == '🔽':
                direction = Direction.down
            elif emoji == '▶️':
                direction = Direction.right
            elif emoji == '◀️':
                direction = Direction.left
            game.move_player(direction)
            try:
                await msg.remove_reaction(emoji, ctx.author)
            except discord.HTTPException:
                pass
        score = game.stats['coins'] + game.stats['moves']
        if game.stats['moves'] == 0:
            await msg.edit(
                content=f"```\nUh oh, Game Over. Your score: {score}\n```")
            await msg.clear_reactions()
            return
        elif game.stats['coins'] == game.stats['max_coins']:
            await msg.edit(
                content=
                f"```\nCongratulations! You Win. Your score: {score}\n```")
            await msg.clear_reactions()
            return
Esempio n. 22
0
async def menu(
    ctx: commands.Context,
    pages: Union[List[str], List[discord.Embed]],
    controls: dict,
    message: discord.Message = None,
    page: int = 0,
    timeout: float = 30.0,
    **kwargs,
):
    """
    An emoji-based menu
    .. note:: All pages should be of the same type
    .. note:: All functions for handling what a particular emoji does
              should be coroutines (i.e. :code:`async def`). Additionally,
              they must take all of the parameters of this function, in
              addition to a string representing the emoji reacted with.
              This parameter should be the last one, and none of the
              parameters in the handling functions are optional
    Parameters
    ----------
    ctx: commands.Context
        The command context
    pages: `list` of `str` or `discord.Embed`
        The pages of the menu.
    controls: dict
        A mapping of emoji to the function which handles the action for the
        emoji.
    message: discord.Message
        The message representing the menu. Usually :code:`None` when first opening
        the menu
    page: int
        The current page number of the menu
    timeout: float
        The time (in seconds) to wait for a reaction
    Raises
    ------
    RuntimeError
        If either of the notes above are violated
    """
    if not isinstance(pages[0], (discord.Embed, str)):
        raise RuntimeError("Pages must be of type discord.Embed or str")
    if not all(isinstance(x, discord.Embed) for x in pages) and not all(
        isinstance(x, str) for x in pages
    ):
        raise RuntimeError("All pages must be of the same type")
    for key, value in controls.items():
        maybe_coro = value
        if isinstance(value, functools.partial):
            maybe_coro = value.func
        if not asyncio.iscoroutinefunction(maybe_coro):
            raise RuntimeError("Function must be a coroutine")
    current_page = pages[page]

    if not message:
        if isinstance(current_page, discord.Embed):
            message = await ctx.send(embed=current_page, **kwargs)
        else:
            message = await ctx.send(current_page, **kwargs)
        # Don't wait for reactions to be added (GH-1797)
        # noinspection PyAsyncCall
        start_adding_reactions(message, controls.keys())
    else:
        try:
            if isinstance(current_page, discord.Embed):
                await message.edit(embed=current_page, **kwargs)
            else:
                await message.edit(content=current_page, **kwargs)
        except discord.NotFound:
            return

    try:
        predicates = ReactionPredicate.with_emojis(tuple(controls.keys()), message, ctx.author)
        tasks = [
            asyncio.ensure_future(ctx.bot.wait_for("reaction_add", check=predicates)),
            asyncio.ensure_future(ctx.bot.wait_for("reaction_remove", check=predicates)),
        ]
        done, pending = await asyncio.wait(
            tasks, timeout=timeout, return_when=asyncio.FIRST_COMPLETED
        )
        for task in pending:
            task.cancel()

        if len(done) == 0:
            raise asyncio.TimeoutError()
        react, user = done.pop().result()
    except asyncio.TimeoutError:
        if not ctx.me:
            return
        try:
            if message.channel.permissions_for(ctx.me).manage_messages:
                await message.clear_reactions()
            else:
                raise RuntimeError
        except (discord.Forbidden, RuntimeError):  # cannot remove all reactions
            for key in controls:
                try:
                    await message.remove_reaction(key, ctx.bot.user)
                except discord.Forbidden:
                    return
                except discord.HTTPException:
                    pass
        except discord.NotFound:
            return
    else:
        return await controls[react.emoji](
            ctx, pages, controls, message, page, timeout, react.emoji
        )
Esempio n. 23
0
    async def command_now(self, ctx: commands.Context):
        """Now playing."""
        if not self._player_check(ctx):
            return await self.send_embed_msg(ctx, title=_("Nothing playing."))
        expected: Union[Tuple[str, ...]] = (
            "⏮",
            "⏹",
            "⏯",
            "⏭",
            self.get_cross_emoji(ctx),
        )
        emoji = {
            "prev": "⏮",
            "stop": "⏹",
            "pause": "⏯",
            "next": "⏭",
            "close": self.get_cross_emoji(ctx),
        }
        player = lavalink.get_player(ctx.guild.id)
        if player.current:
            arrow = await self.draw_time(ctx)
            pos = self.format_time(player.position)
            if player.current.is_stream:
                dur = "LIVE"
            else:
                dur = self.format_time(player.current.length)
            song = (await self.get_track_description(
                player.current, self.local_folder_current_path) or "")
            song += _("\n Requested by: **{track.requester}**")
            song += "\n\n{arrow}`{pos}`/`{dur}`"
            song = song.format(track=player.current,
                               arrow=arrow,
                               pos=pos,
                               dur=dur)
        else:
            song = _("Nothing.")

        if player.fetch("np_message") is not None:
            with contextlib.suppress(discord.HTTPException):
                await player.fetch("np_message").delete()
        embed = discord.Embed(description=song)
        embed.set_author(
            name=_("Now Playing"),
            icon_url="https://cdn.discordapp.com/emojis/572861527049109515.gif",
        )
        guild_data = await self.config.guild(ctx.guild).all()

        if guild_data[
                "thumbnail"] and player.current and player.current.thumbnail:
            embed.set_thumbnail(url=player.current.thumbnail)
        shuffle = guild_data["shuffle"]
        repeat = guild_data["repeat"]
        autoplay = guild_data["auto_play"]
        text = ""
        text += (
            _("Auto-Play") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if autoplay else "\N{CROSS MARK}"))
        text += (
            (" | " if text else "") + _("Shuffle") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if shuffle else "\N{CROSS MARK}"))
        text += (
            (" | " if text else "") + _("Repeat") + ": " +
            ("\N{WHITE HEAVY CHECK MARK}" if repeat else "\N{CROSS MARK}"))

        message = await self.send_embed_msg(ctx, embed=embed, footer=text)

        player.store("np_message", message)

        dj_enabled = self._dj_status_cache.setdefault(
            ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled())
        vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
        if ((dj_enabled or vote_enabled)
                and not await self._can_instaskip(ctx, ctx.author)
                and not await self.is_requester_alone(ctx)):
            return

        if not player.queue and not autoplay:
            expected = ("⏹", "⏯", "\N{CROSS MARK}")
        task: Optional[asyncio.Task]
        if player.current:
            task = start_adding_reactions(message, expected[:5])
        else:
            task = None

        try:
            (r, u) = await self.bot.wait_for(
                "reaction_add",
                check=ReactionPredicate.with_emojis(expected, message,
                                                    ctx.author),
                timeout=30.0,
            )
        except asyncio.TimeoutError:
            return await self._clear_react(message, emoji)
        else:
            if task is not None:
                task.cancel()
        reacts = {v: k for k, v in emoji.items()}
        react = reacts[r.emoji]
        if react == "prev":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_prev)
        elif react == "stop":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_stop)
        elif react == "pause":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_pause)
        elif react == "next":
            await self._clear_react(message, emoji)
            await ctx.invoke(self.command_skip)
        elif react == "close":
            await message.delete()
Esempio n. 24
0
    async def lfg(self, ctx: commands.Context):
        """Make an LFG request."""
        author = ctx.author
        bot = self.bot
        gamemode1 = bot.get_emoji(658426489636651051)
        gamemode2 = bot.get_emoji(658426504186691598)
        gamemode3 = bot.get_emoji(658426519437443093)
        gamemodeo = bot.get_emoji(658426530715926528)
        rank1 = bot.get_emoji(658431823935832064)
        rank2 = bot.get_emoji(658431824342548510)
        rank3 = bot.get_emoji(658431823746957313)
        rank4 = bot.get_emoji(658431824279896064)
        rank5 = bot.get_emoji(658431824065986562)
        rank6 = bot.get_emoji(658431823931506710)
        rank7 = bot.get_emoji(658431823608545294)
        region1 = bot.get_emoji(658435948513722399)
        region2 = bot.get_emoji(658435948572442635)
        region3 = bot.get_emoji(658435948425641994)
        region4 = bot.get_emoji(658435948492750869)
        region5 = bot.get_emoji(658435948236767236)
        region6 = bot.get_emoji(658435948631162880)
        region7 = bot.get_emoji(658435948211601422)
        region8 = bot.get_emoji(658435948589088787)
        region9 = bot.get_emoji(658435948610191366)
        region10 = bot.get_emoji(658435948983353377)
        platform1 = bot.get_emoji(658438656826015775)
        platform2 = bot.get_emoji(658438656570294314)
        platform3 = bot.get_emoji(658438656872415262)
        platform4 = bot.get_emoji(658438656863895562)
        gamemodes = (gamemode1, gamemode2, gamemode3, gamemodeo)
        gamemodeemoji = {
            "ones": gamemode1,
            "twos": gamemode2,
            "threes": gamemode3,
            "other": gamemodeo
        }
        ranks = (rank1, rank2, rank3, rank4, rank5, rank6, rank7)
        rankemoji = {
            "bronze": rank1,
            "silver": rank2,
            "gold": rank3,
            "platinum": rank4,
            "diamond": rank5,
            "champion": rank6,
            "grandchampion": rank7
        }
        regions = (region1, region2, region3, region4, region5, region6,
                   region7, region8, region9, region10)
        regionemoji = {
            "usw": region1,
            "use": region2,
            "sam": region3,
            "saf": region4,
            "oce": region5,
            "me": region6,
            "jpn": region7,
            "eu": region8,
            "asm": region9,
            "asc": region10
        }
        platforms = (platform1, platform2, platform3, platform4)
        platformemoji = {
            "pc": platform1,
            "xbox": platform2,
            "ps": platform3,
            "switch": platform4
        }
        players = ("1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣")
        playeremoji = {
            "1": "1️⃣",
            "2": "2️⃣",
            "3": "3️⃣",
            "4": "4️⃣",
            "5": "5️⃣",
            "6": "6️⃣",
            "7": "7️⃣"
        }
        try:
            game = await author.send(
                "**You have a maximum of 2 minutes to answer each question, "
                "Please specify what gamemode you are playing.**")
        except discord.Forbidden:
            return await ctx.send(
                "I can't seem to be able to DM you. Do you have DM's closed?")

        message = await ctx.send("Okay, {0}, I've sent you a DM.".format(
            author.mention))
        try:
            task = start_adding_reactions(game, gamemodes[:4], ctx.bot.loop)
            (r, u) = await bot.wait_for("reaction_add",
                                        timeout=120,
                                        check=ReactionPredicate.with_emojis(
                                            gamemodes, game, ctx.author))
            reacts = {v: k for k, v in gamemodeemoji.items()}
            react = reacts[r.emoji]
            if react == "ones":
                gamemode = "1's"
            elif react == "twos":
                gamemode = "2's"
            elif react == "threes":
                gamemode = "3's"
            elif react == "other":
                gamemode = "Other"
        except asyncio.TimeoutError:
            return await author.send("You took too long. Try again.")

        rank = await author.send("**What rank are you in this gamemode?**")
        try:
            task = start_adding_reactions(rank, ranks[:7], ctx.bot.loop)
            (r, u) = await bot.wait_for("reaction_add",
                                        timeout=120,
                                        check=ReactionPredicate.with_emojis(
                                            ranks, rank, ctx.author))
            reacts = {v: k for k, v in rankemoji.items()}
            react = reacts[r.emoji]
            if react == "bronze":
                rank = "Bronze"
            elif react == "silver":
                rank = "Silver"
            elif react == "gold":
                rank = "Gold"
            elif react == "platinum":
                rank = "Platinum"
            elif react == "diamond":
                rank = "Diamond"
            elif react == "champion":
                rank = "Champion"
            elif react == "grandchampion":
                rank = "Grand Champion"
        except asyncio.TimeoutError:
            return await author.send("You took too long. Try again.")

        region = await author.send("**What servers are you playing on?**")
        try:
            task = start_adding_reactions(region, regions[:10], ctx.bot.loop)
            (r, u) = await bot.wait_for("reaction_add",
                                        timeout=120,
                                        check=ReactionPredicate.with_emojis(
                                            regions, region, ctx.author))
            reacts = {v: k for k, v in regionemoji.items()}
            react = reacts[r.emoji]
            if react == "usw":
                region = "US-West"
            elif react == "use":
                region = "US-East"
            elif react == "sam":
                region = "South America"
            elif react == "saf":
                region = "South African"
            elif react == "oce":
                region = "Oceana"
            elif react == "me":
                region = "Middle East"
            elif react == "jpn":
                region = "Japan"
            elif react == "eu":
                region = "Europe"
            elif react == "asm":
                region = "Asia Mainlane"
            elif react == "asc":
                region = "Asia East"
        except asyncio.TimeoutError:
            return await author.send("You took too long. Try again.")

        platform = await author.send("**What platform are you using?**")
        try:
            task = start_adding_reactions(platform, platforms[:4],
                                          ctx.bot.loop)
            (r, u) = await bot.wait_for("reaction_add",
                                        timeout=120,
                                        check=ReactionPredicate.with_emojis(
                                            platforms, platform, ctx.author))
            reacts = {v: k for k, v in platformemoji.items()}
            react = reacts[r.emoji]
            if react == "pc":
                platform = "PC"
            elif react == "xbox":
                platform = "Xbox"
            elif react == "ps":
                platform = "PlayStation"
            elif react == "switch":
                platform = "Nintendo Switch"
        except asyncio.TimeoutError:
            return await author.send("You took too long. Try again.")

        player = await author.send("**How many people are you looking for?**")
        try:
            task = start_adding_reactions(player, players[:7], ctx.bot.loop)
            (r, u) = await bot.wait_for("reaction_add",
                                        timeout=120,
                                        check=ReactionPredicate.with_emojis(
                                            players, player, ctx.author))
            reacts = {v: k for k, v in playeremoji.items()}
            react = reacts[r.emoji]
            if react == "1":
                player = "1"
            elif react == "2":
                player = "2"
            elif react == "3":
                player = "3"
            elif react == "4":
                player = "4"
            elif react == "5":
                player = "5"
            elif react == "6":
                player = "6"
            elif react == "7":
                player = "7"
        except asyncio.TimeoutError:
            return await author.send("You took too long. Try again.")

        embed = discord.Embed(color=await ctx.embed_colour(),
                              timestamp=datetime.now())
        embed.set_author(
            name=f"{ctx.author.name} is looking for a Rocket League group",
            icon_url=author.avatar_url)
        embed.set_footer(text="{0}#{1} ({2})".format(
            author.name, author.discriminator, author.id))
        embed.add_field(name="GameMode:", value=gamemode, inline=True)
        embed.add_field(name="Rank:", value=rank, inline=True)
        embed.add_field(name="Server:", value=region, inline=True)
        embed.add_field(name="Platform:", value=platform, inline=True)
        embed.add_field(name="Looking for:", value=player, inline=True)
        await message.delete()

        try:
            if await self.config.lfg_channel() is None:
                await author.send(
                    "It apprears that this hasn't been set up correctly on this server"
                )
            else:
                channel = self.bot.get_channel(await self.config.lfg_channel())
                please = await channel.send(embed=embed)
                await author.send("**Your LFG request has been made!**")
                await asyncio.sleep(1800)
                await please.delete()
        except discord.Forbidden:
            await author.send("That didn't work for some reason")
Esempio n. 25
0
    async def cast(self, ctx:commands.Context, bait_type:str):
        """Rolls for a fish
          Fish will periodically bite the pole, at which point the message can be reacted to to catch the fish
          After reeling in the rod, you will have the option to keep or release the fish

         - Must be used in a channel registered as a pool"""

        if not await self.IsSpecialized(ctx.guild, ctx.channel.id, POOL_CHANNEL):
            return
        profile = self.config.member(ctx.message.author)

        await profile.currently_fishing.set(True)
        modified_fish_weights = await self.startfishing(ctx, profile, bait_type)

        embed = Embed(title=f'{ctx.message.author.display_name} cast their rod into the shimmering waves at {ctx.channel}', color=0x7300ff)
        embed.set_footer(text='Not even a nibble yet...')
        msg = await ctx.send(embed=embed)
        start_adding_reactions(msg, ['🎣'])

        pred = ReactionPredicate.with_emojis(['🎣'], msg, ctx.author)
        time_left = await self.GetSetting(ctx.guild, 'max_fishing_length')
        min_pause = await self.GetSetting(ctx.guild, 'min_fishing_wait')
        max_pause = await self.GetSetting(ctx.guild, 'max_fishing_wait')
        curr_fish = None
        rarity = None
        while time_left >= 0:
            try:
                timer = time_left if time_left < max_pause else randint(min_pause, max_pause)
                time_left -= timer
                await ctx.bot.wait_for('reaction_add', check=pred, timeout=timer)
            except asyncio.TimeoutError:
                if curr_fish is None:
                    rarity = choices(FISH_RARITIES, modified_fish_weights)[0]
                    rarity_list = self.fishing_rarities.get(rarity)
                    curr_fish = rarity_list[randint(0, len(rarity_list) - 1)] if not await profile.bryan_mode() else self.SEA_BASS
                    embed.set_footer(text=RARITY_DESCRIPTIONS[rarity])
                else:
                    curr_fish = None
                    embed.set_footer(text='The rod drifts in the water')
                await msg.edit(embed=embed)

            if pred.result == 0:
                break

        if curr_fish is None or time_left <= 0:
            embed.set_footer(text='You feel a twist as the line snaps :(')
            await msg.edit(embed=embed)
            await msg.clear_reactions()
        else:
            new_fish = curr_fish.ToFishCatch(RARITY_VALUES[rarity])
            embed.set_footer(text=f'You pulled a {new_fish["name"]} ({new_fish["size"]} inches) out of the water!\nDo you want to keep or release?')
            embed.set_thumbnail(url=curr_fish.image)
            await msg.edit(embed=embed)
            await msg.clear_reactions()

            start_adding_reactions(msg, ['🥤', '🐟'])

            pred = ReactionPredicate.with_emojis(['🥤', '🐟'], msg, ctx.author)
            try:
                await ctx.bot.wait_for("reaction_add", check=pred, timeout=15)
            except asyncio.TimeoutError:
                if await self.AddFish(ctx.message.author, new_fish):
                    embed.set_footer(text=f'Timed out, {new_fish["name"]} was added to your bucket')
                else:
                    embed.set_footer(text=f'Timed out and your bucket was full, so {new_fish["name"]} was released :(')
                await msg.edit(embed=embed)
                await msg.clear_reactions()
            else:
                if pred.result == 0:
                    if await self.AddFish(ctx.message.author, new_fish):
                        embed.set_footer(text=f'{new_fish["name"]} was added to your bucket!')
                    else:
                        embed.set_footer(text=f'Your bucket was full, so you had to release {new_fish["name"]} :(')
                else:
                    embed.set_footer(text=f'You let {new_fish["name"]} swim away...')
                await msg.edit(embed=embed)
                await msg.clear_reactions()

        if randint(0, 100) < 100 * await self.GetSetting(ctx.guild, 'bait_recovery_chance'):
            await ctx.send(f'Your {bait_type} is still on the end of the rod! (+1 {bait_type})')
        else:
            user_bait = await profile.bait()
            user_bait[bait_type] -= 1
            await profile.bait.set(user_bait)

        await profile.currently_fishing.set(False)
        #if not await profile.mawiam_mode():
        #await profile.nextcast.set(time() + await self.GetSetting(ctx.guild, 'fishing_delay'))

        await self.CheckSchools(ctx)
Esempio n. 26
0
 async def open_chest(ctx, user, type):
     if hasattr(user, "display_name"):
         await ctx.send("{} is opening a treasure chest. What riches lay inside?".format(user.display_name))
     else: #this is when a pet is foraging.
         await ctx.send("{} is foraging for treasure. What will it find?".format(user[:1].upper() + user[1:]))
         await asyncio.sleep(2)
     if hasattr(user, "display_name"):
         luckbonus = Userdata.users[str(user.id)]['buffs'].get('luck', {'bonus':0})['bonus']
         roll = random.randint(1,100)-luckbonus
     else:
         luckbonus = 0
         roll = random.randint(1,100)
     if type == "pet":
         if roll <= 1:
             await ctx.send("{} found something precious!".format(user[:1].upper() + user[1:]))
             chance = Treasure.quest
         elif roll <= 11:
             chance = Treasure.unique
         elif roll > 11 and roll <= 50:
             chance = Treasure.rare
         elif roll > 50 and roll <= 75:
             chance = Treasure.common
         else:
             await ctx.send("{} found nothing of value.".format(user[:1].upper() + user[1:]))
             return None
     elif type == "normal":
         if roll <= 5:
             chance = Treasure.unique
         elif roll > 5 and roll <= 25:
             chance = Treasure.rare
         else:
             chance = Treasure.common
     elif type == "rare":
         if roll <= 15:
             chance = Treasure.unique
         elif roll > 15 and roll <= 45:
             chance = Treasure.rare
         else:
             chance = Treasure.common
     elif type == "epic":
         if roll <= 1:
             await ctx.send("This was no ordinary epic chest!")
             chance = Treasure.quest
         elif roll <= 25:
             chance = Treasure.unique
         else:
             chance = Treasure.rare
     elif type == "quest":
         if roll <= 10:
             chance = Treasure.quest
         else:
             chance = Treasure.unique
     itemname = random.choice(list(chance.keys()))
     item = chance[itemname]
     if item['slot'] == ['consumable']:
         item['uses'] = random.randint(1,item['uses'])
         if hasattr(user, "display_name"):
             await ctx.send("```css\n{} found {} ({}x).```".format(user.display_name,itemname,item['uses']))
         else:
             await ctx.send("```css\nYour {} found {} ({}x).```".format(user,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 luckbonus != 0:
             if Userdata.users[str(user.id)]['buffs']['luck']['duration'] <= 1:
                 Userdata.users[str(user.id)]['buffs'].pop('luck')
                 luckbonus = 0
             else:
                 Userdata.users[str(user.id)]['buffs']['luck']['duration'] = Userdata.users[str(user.id)]['buffs']['luck']['duration'] - 1
         await Userdata.save()
         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"]
         if hasattr(user, "display_name"):
             await ctx.send("```css\n{} found a {}. (Attack: {}, Charisma: {} [{}])```".format(user.display_name,itemname,str(att),str(cha),hand))
         else:
             await ctx.send("```css\nYour {} found a {}. (Attack: {}, Charisma: {} [{}])```".format(user,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())
         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 luckbonus != 0:
             if Userdata.users[str(user.id)]['buffs']['luck']['duration'] <= 1:
                 Userdata.users[str(user.id)]['buffs'].pop('luck')
                 luckbonus = 0
             else:
                 Userdata.users[str(user.id)]['buffs']['luck']['duration'] = Userdata.users[str(user.id)]['buffs']['luck']['duration'] - 1
         await Userdata.save()
         if react != None:
             react_emoji = react.emoji
         return {"itemname": itemname,"item":item,"equip":Treasure.controls[react_emoji]}
Esempio n. 27
0
    async def watch2gether(self, ctx, link=None):
        '''
        Create a watch2gether room. If a link is provided then the room will be opened for that resource
        '''
        api_keys = await self.bot.get_shared_api_tokens("watch2gether")
        if api_keys.get("api_key") is None:
            return await ctx.send(
                "The Watch2Gether API key has not been set. Set it with "
                f"`{ctx.prefix}set api watch2gether api_key,<api_key>` command"
            )
        api_key = api_keys["api_key"]

        if link is None:
            running_rooms = await self.db.guild(ctx.guild).rooms()
            if running_rooms:
                now = datetime.utcnow()
                room_strs = []
                i = 1
                for room in running_rooms:
                    created_at = discord.utils.snowflake_time(
                        room["message_id"])
                    expires = await self.db.guild(ctx.guild).expires()
                    if expires:
                        if (now - created_at).total_seconds() > expires:
                            async with self.db.guild(
                                    ctx.guild).rooms() as rooms:
                                rooms.remove(room)
                                running_rooms.remove(room)
                                continue
                    time_delta = human_timedelta(created_at, accuracy=1)
                    string = f"[Room {i}]({room['room_url']}) (Created By - <@{room['author_id']}>, {time_delta})"
                    i = i + 1
                    room_strs.append(string)
                if room_strs:
                    embed_color = await ctx.embed_color()
                    embed = discord.Embed(color=embed_color,
                                          title="Currently running rooms:")
                    embed.description = "\n".join(room_strs)
                    embed.set_footer(
                        text=
                        "Click on any of the URLs above to enter the room.\n"
                        'If you want to create a new room, react with "+" on this message'
                    )
                    message = await ctx.send(embed=embed)

                    emojis = [
                        "\N{HEAVY PLUS SIGN}",
                        "\N{HEAVY MULTIPLICATION X}\N{VARIATION SELECTOR-16}"
                    ]
                    start_adding_reactions(message, emojis)
                    pred = ReactionPredicate.with_emojis(emojis,
                                                         message=message,
                                                         user=ctx.author)
                    try:
                        await self.bot.wait_for("reaction_add",
                                                check=pred,
                                                timeout=60.0)
                    except asyncio.exceptions.TimeoutError:
                        return await message.clear_reactions()
                    else:
                        if pred.result == 1:
                            return await message.delete()

        url = "https://www.watch2gether.com/rooms/create.json"
        data = {"api_key": api_key, "share": link}
        async with self.session.post(url, data=data) as resp:
            jsondata = await resp.json()

        room_key = jsondata["streamkey"]
        room_url = f"https://www.watch2gether.com/rooms/{room_key}"
        async with self.db.guild(ctx.guild).rooms() as rooms:
            rooms.append({
                "room_key": room_key,
                "room_url": room_url,
                "message_id": ctx.message.id,
                "author_id": ctx.author.id
            })

        await ctx.send(f"New Watch2Gether room created: {room_url}")
Esempio n. 28
0
    async def daily(self, ctx):
        """View the daily deals.

        These will come at a lower price than the store, but can only be bought once per day.

        Status guide:
            A: Available to be bought and put in backyard
            B: Already purchased
            S: Available to be bought, but will be put in stash because you either do not have the space for the, or above your level threshold"""
        async with self.lock:
            data = await self.conf.user(ctx.author).all()
        animals = data["animals"]
        animal = data["animal"]

        if animal in ["", "P"]:
            return await ctx.send("Finish starting your evolution first")

        multiplier = data["multiplier"]
        highest = max(list(map(int, animals.keys())))
        e = 6 + math.ceil((multiplier - 1) * 5)

        display = []
        deals = await self.conf.daily()
        for did, deal in deals.items():
            status = ""
            amount = deal["details"]["amount"]
            level = deal["details"]["level"]
            if ctx.author.id in deal["bought"]:
                status = "[B]"
            elif (level > int(highest) - 3
                  and level != 1) or (amount + animals.get(str(level), 0) > e):
                status = "#S "
            else:
                status = " A "

            price = self.utils.get_total_price(level, 0, amount, False) * 0.75

            display.append([
                did,
                status,
                humanize_number(price),
                f"{amount} Level {level} {animal}{'s' if amount != 1 else ''}",
            ])

        message = await ctx.send(
            f"{box(tabulate(display, tablefmt='psql'), lang='css')}Would you like to buy any of these fine animals?  Click the corresponding reaction below."
        )
        emojis = ReactionPredicate.NUMBER_EMOJIS[1:7]
        start_adding_reactions(message, emojis)

        pred = ReactionPredicate.with_emojis(emojis, message, ctx.author)
        try:
            await self.bot.wait_for("reaction_add", check=pred, timeout=60.0)
        except asyncio.TimeoutError:
            return await ctx.send(
                "The vendor grew uncomfortable with you there, and told you to leave and come back later."
            )

        if ctx.author.id in self.inmarket:
            return await ctx.send(
                "Complete your current transaction or evolution first.")
        self.inmarket.append(ctx.author.id)
        buying = pred.result + 1

        deal = deals[str(buying)]
        if ctx.author.id in deal["bought"]:  # ;no
            self.inmarket.remove(ctx.author.id)
            return await ctx.send(
                "You already bought this deal.  You cannot buy daily deals multiple times."
            )

        level = deal["details"]["level"]
        amount = deal["details"]["amount"]

        price = self.utils.get_total_price(level, 0, amount, False) * 0.75
        balance = await bank.get_balance(ctx.author)

        if balance < price:
            self.inmarket.remove(ctx.author.id)
            return await ctx.send(
                f"You need {humanize_number(price - balance)} more credits to buy that deal."
            )

        stashing = 0
        delivering = amount
        if level > int(highest) - 3 and level != 1:
            stashing = amount
            delivering = 0
        elif amount + animals.get(str(level), 0) > e:
            delivering = e - animals[str(level)]
            stashing = amount - delivering

        async with self.lock:
            async with self.conf.user(ctx.author).all() as data:
                data["animals"][str(level)] = animals.get(str(level),
                                                          0) + delivering

                if stashing:
                    current_stash = data["stash"]["animals"].get(str(level), 0)
                    data["stash"]["animals"][str(
                        level)] = current_stash + stashing

                self.cache[ctx.author.id] = data
            async with self.conf.daily(
            ) as data:  # In case someone buys at the same time, we need to re-read the data
                data[str(buying)]["bought"].append(ctx.author.id)

        await bank.withdraw_credits(ctx.author, int(price))
        await ctx.send(
            box(
                (f"[Transaction Complete]\nYou spent {humanize_number(price)} credits to buy {amount} Level {str(level)} {animal}{'s' if amount != 1 else ''}."
                 f"\n\n{delivering} have been added to your backyard, {stashing} have been sent to your stash."
                 ),
                "css",
            ))
        self.inmarket.remove(ctx.author.id)
Esempio n. 29
0
    async def get_playlist_match(
        self,
        context: commands.Context,
        matches: MutableMapping,
        scope: str,
        author: discord.User,
        guild: discord.Guild,
        specified_user: bool = False,
    ) -> Tuple[Optional[Playlist], str, str]:
        """
        Parameters
        ----------
        context: commands.Context
            The context in which this is being called.
        matches: dict
            A dict of the matches found where key is scope and value is matches.
        scope:str
            The custom config scope. A value from :code:`PlaylistScope`.
        author: discord.User
            The user.
        guild: discord.Guild
            The guild.
        specified_user: bool
            Whether or not a user ID was specified via argparse.
        Returns
        -------
        Tuple[Optional[Playlist], str, str]
            Tuple of Playlist or None if none found, original user input and scope.
        Raises
        ------
        `TooManyMatches`
            When more than 10 matches are found or
            When multiple matches are found but none is selected.

        """
        correct_scope_matches: List[Playlist]
        original_input = matches.get("arg")
        lazy_match = False
        if scope is None:
            correct_scope_matches_temp: MutableMapping = matches.get("all")
            lazy_match = True
        else:
            correct_scope_matches_temp: MutableMapping = matches.get(scope)
        guild_to_query = guild.id
        user_to_query = author.id
        correct_scope_matches_user = []
        correct_scope_matches_guild = []
        correct_scope_matches_global = []
        if not correct_scope_matches_temp:
            return None, original_input, scope or PlaylistScope.GUILD.value
        if lazy_match or (scope == PlaylistScope.USER.value):
            correct_scope_matches_user = [
                p for p in matches.get(PlaylistScope.USER.value)
                if user_to_query == p.scope_id
            ]
        if lazy_match or (scope == PlaylistScope.GUILD.value
                          and not correct_scope_matches_user):
            if specified_user:
                correct_scope_matches_guild = [
                    p for p in matches.get(PlaylistScope.GUILD.value) if
                    guild_to_query == p.scope_id and p.author == user_to_query
                ]
            else:
                correct_scope_matches_guild = [
                    p for p in matches.get(PlaylistScope.GUILD.value)
                    if guild_to_query == p.scope_id
                ]
        if lazy_match or (scope == PlaylistScope.GLOBAL.value
                          and not correct_scope_matches_user
                          and not correct_scope_matches_guild):
            if specified_user:
                correct_scope_matches_global = [
                    p for p in matches.get(PlaylistScope.GLOBAL.value)
                    if p.author == user_to_query
                ]
            else:
                correct_scope_matches_global = [
                    p for p in matches.get(PlaylistScope.GLOBAL.value)
                ]

        correct_scope_matches = [
            *correct_scope_matches_global,
            *correct_scope_matches_guild,
            *correct_scope_matches_user,
        ]
        match_count = len(correct_scope_matches)
        if match_count > 1:
            correct_scope_matches2 = [
                p for p in correct_scope_matches
                if p.name == str(original_input).strip()
            ]
            if correct_scope_matches2:
                correct_scope_matches = correct_scope_matches2
            elif original_input.isnumeric():
                arg = int(original_input)
                correct_scope_matches3 = [
                    p for p in correct_scope_matches if p.id == arg
                ]
                if correct_scope_matches3:
                    correct_scope_matches = correct_scope_matches3
        match_count = len(correct_scope_matches)
        # We done all the trimming we can with the info available time to ask the user
        if match_count > 10:
            if original_input.isnumeric():
                arg = int(original_input)
                correct_scope_matches = [
                    p for p in correct_scope_matches if p.id == arg
                ]
            if match_count > 10:
                raise TooManyMatches(
                    _("{match_count} playlists match {original_input}: "
                      "Please try to be more specific, or use the playlist ID."
                      ).format(match_count=match_count,
                               original_input=original_input))
        elif match_count == 1:
            return correct_scope_matches[
                0], original_input, correct_scope_matches[0].scope
        elif match_count == 0:
            return None, original_input, scope or PlaylistScope.GUILD.value

        # TODO : Convert this section to a new paged reaction menu when Toby Menus are Merged
        pos_len = 3
        playlists = f"{'#':{pos_len}}\n"
        number = 0
        correct_scope_matches = sorted(correct_scope_matches,
                                       key=lambda x: x.name.lower())
        async for number, playlist in AsyncIter(
                correct_scope_matches).enumerate(start=1):
            author = self.bot.get_user(
                playlist.author) or playlist.author or _("Unknown")
            line = _("{number}."
                     "    <{playlist.name}>\n"
                     " - Scope:  < {scope} >\n"
                     " - ID:     < {playlist.id} >\n"
                     " - Tracks: < {tracks} >\n"
                     " - Author: < {author} >\n\n").format(
                         number=number,
                         playlist=playlist,
                         scope=self.humanize_scope(playlist.scope),
                         tracks=len(playlist.tracks),
                         author=author,
                     )
            playlists += line

        embed = discord.Embed(
            title=_("{playlists} playlists found, which one would you like?").
            format(playlists=number),
            description=box(playlists, lang="md"),
            colour=await context.embed_colour(),
        )
        msg = await context.send(embed=embed)
        avaliable_emojis = ReactionPredicate.NUMBER_EMOJIS[1:]
        avaliable_emojis.append("🔟")
        emojis = avaliable_emojis[:len(correct_scope_matches)]
        close_emoji = self.get_cross_emoji(context)
        emojis.append(close_emoji)
        start_adding_reactions(msg, emojis)
        pred = ReactionPredicate.with_emojis(emojis, msg, user=context.author)
        try:
            await context.bot.wait_for("reaction_add", check=pred, timeout=60)
        except asyncio.TimeoutError:
            with contextlib.suppress(discord.HTTPException):
                await msg.delete()
            raise TooManyMatches(
                _("Too many matches found and you did not select which one you wanted."
                  ))
        if emojis[pred.result] == close_emoji:
            with contextlib.suppress(discord.HTTPException):
                await msg.delete()
            raise TooManyMatches(
                _("Too many matches found and you did not select which one you wanted."
                  ))
        with contextlib.suppress(discord.HTTPException):
            await msg.delete()
        return (
            correct_scope_matches[pred.result],
            original_input,
            correct_scope_matches[pred.result].scope,
        )
Esempio n. 30
0
 async def open_chest(ctx, user, type):
     if hasattr(user, "display_name"):
         await ctx.send(
             "{} is opening a treasure chest. What riches lay inside?".
             format(user.display_name))
     else:
         await ctx.send(
             "{} is foraging for treasure. What will it find?".format(
                 user[:1].upper() + user[1:]))
         await asyncio.sleep(2)
     roll = random.randint(1, 100)
     if type == "pet":
         if roll <= 5:
             chance = Treasure.unique
         elif roll > 5 and roll <= 25:
             chance = Treasure.rare
         elif roll > 25 and roll <= 75:
             chance = Treasure.common
         else:
             await ctx.send(
                 "{} found nothing of value.".format(user[:1].upper() +
                                                     user[1:]))
             return None
     if type == "normal":
         if roll <= 5:
             chance = Treasure.unique
         elif roll > 5 and roll <= 25:
             chance = Treasure.rare
         else:
             chance = Treasure.common
     if type == "rare":
         if roll <= 15:
             chance = Treasure.unique
         elif roll > 15 and roll <= 45:
             chance = Treasure.rare
         else:
             chance = Treasure.common
     if type == "epic":
         if roll <= 25:
             chance = Treasure.unique
         else:
             chance = Treasure.rare
     itemname = random.choice(list(chance.keys()))
     item = chance[itemname]
     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"]
     if hasattr(user, "display_name"):
         await ctx.send(
             "{} found a {}. (Attack: {}, Charisma: {} [{}])".format(
                 user.display_name, itemname, str(att), str(cha), hand))
     else:
         await ctx.send(
             "Your {} found a {}. (Attack: {}, Charisma: {} [{}])".format(
                 user, 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())
     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, user = await ctx.bot.wait_for("reaction_add", check=pred)
     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)
     return {
         "itemname": itemname,
         "item": item,
         "equip": Treasure.controls[react.emoji]
     }