Beispiel #1
0
    def _get_main_menu(self, ctx: SlashContext, guild_data: GuildData, content: dict) -> Embed:
        embed = Embed(
            title="Help | Asteroid Bot",
            timestamp=datetime.datetime.utcnow(),
            color=DiscordColors.EMBED_COLOR,
        )
        embed.add_field(
            name=content["INFORMATION_TEXT"],
            value=content["INFORMATION_CONTENT_TEXT"],
            inline=False,
        )
        embed.set_thumbnail(url=ctx.bot.user.avatar_url)
        embed.set_footer(
            text=content["REQUIRED_BY_TEXT"].format(user=ctx.author),
            icon_url=ctx.author.avatar_url,
        )

        cog_translations = content["PLUGINS"]
        cogs = "".join(
            f"**» {cog_translations[cog_name.upper()]}**\n"
            for cog_name, cog in self.bot.cogs.items()
            if not self._cog_check(guild_data, cog)
        )

        embed.add_field(name=content["PLUGINS_TEXT"], value=cogs)
        return embed
Beispiel #2
0
 async def confirm_equipment(ctx, profile):
     weapon = profile.weapon
     pet = profile.pet
     return await ctx.prompt(embed=Embed(
         ctx=ctx, title='Is this the correct equipment?'
     ).add_field(
         name='⚔️\tWeapon', value=f'```{weapon}```', inline=False
     ).add_field(
         name=
         f'{PET_EMOJIS[pet.internal_name] if pet and pet.internal_name in PET_EMOJIS else "🐣"}\tPet',
         value=f'```{format_pet(pet) if pet else None}```',
         inline=False).add_field(
             name='💎\tPet Item',
             value=f'```{pet.item_name if pet else None}```',
             inline=False).add_field(
                 name='⛑️\tHelmet',
                 value=f'```{profile.armor["helmet"]}```',
                 inline=False).add_field(
                     name='👚\tChestplate',
                     value=f'```{profile.armor["chestplate"]}```',
                     inline=False).add_field(
                         name='👖\tLeggings',
                         value=f'```{profile.armor["leggings"]}```',
                         inline=False).add_field(
                             name='👞\tBoots',
                             value=f'```{profile.armor["boots"]}```',
                             inline=False).add_field(
                                 name='🏺\tTalismans',
                                 value=''.join(
                                     colorize(
                                         f'{amount} {name.capitalize()}',
                                         RARITY_COLORS[name])
                                     for name, amount in
                                     profile.talisman_counts.items())))
Beispiel #3
0
class Fun(commands.Cog):
    """Module focused on fun"""
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def apod(self, ctx, date=None):
        """An astronomy picture of the day from NASA's api. Use `YYYY-MM-DD` for the date or the latest will be pulled."""

        url = (
            f"https://api.nasa.gov/planetary/apod?date={date}&api_key={self.bot.config['nasa']}"
            if date is not None else
            f"https://api.nasa.gov/planetary/apod?api_key={self.bot.config['nasa']}"
        )

        json = await (await self.bot.session.get(url)).json()

        if error := json.get("msg"):
            return await ctx.reply(
                embed=Embed(title="Error", description=error))

        await ctx.reply(embed=Embed(
            title=json.get("title", "None"),
            description=json.get("explanation", "No explanation"),
        ).set_image(url=json.get("url")))
Beispiel #4
0
    async def xkcd(self, ctx, comic=None):
        """Returns the given xkcd comic or the newest one, depending on if `comic` is passed."""

        url = (f"http://xkcd.com/{comic}/info.0.json"
               if comic else "http://xkcd.com/info.0.json")

        async with ctx.bot.session.get(url) as res:
            if res.status == 404:
                return await ctx.reply(embed=Embed(
                    description="Invalid comic."))

            res = await res.json()

            await ctx.reply(embed=Embed(
                title=f"Comic {comic or res['num']}",
                description=res.get("alt", "No alt text"),
            ).set_image(url=res.get("img")))
Beispiel #5
0
    async def _flags(self, ctx: HarleyContext):
        """Returns an explanation of how flags work."""
        embed = Embed(description=(
            "Flags are used via `--flag Args`\n"
            "You can see a list of the commands flag when doing `help command`"
        ))

        await ctx.reply(embed=embed)
Beispiel #6
0
    def _init_embeds(self, ctx: SlashContext, guild_data: GuildData, content: dict):
        translated_commands = None
        guild_language = guild_data.configuration.language
        if guild_language not in ["en-US", "English"]:
            translated_commands = get_content("TRANSLATED_COMMANDS", guild_language)
        commands_data = self._get_commands_data()
        embeds = [self._get_main_menu(ctx, guild_data, content)]
        cog_translations = content["PLUGINS"]

        for cog_name, cog in self.bot.cogs.items():
            if self._cog_check(guild_data, cog, commands_data):
                continue

            embed = Embed(
                title=f"{cog_translations[cog_name.upper()]} | Asteroid Bot",
                description="",
                timestamp=datetime.datetime.utcnow(),
                color=DiscordColors.EMBED_COLOR,
            )
            embed.set_footer(
                text=content["REQUIRED_BY_TEXT"].format(user=ctx.author),
                icon_url=ctx.author.avatar_url,
            )
            embed.set_thumbnail(url=ctx.bot.user.avatar_url)
            embed.custom_id = cog_name
            embed = self._fill_embed_page(embed, commands_data[cog], content, translated_commands)
            embeds.append(embed)

        return embeds
Beispiel #7
0
    async def markdown(self, ctx, *, text):
        """Performs markdown on the given text"""
        code = markdown.markdown(text)
        url = None

        if len(code) > 512:
            url = await self.bot.utils.paste(code, syntax="html")

        await ctx.reply(embed=Embed(description=url or f"```html\n{code}```"))
Beispiel #8
0
    async def rep(self, ctx, player: discord.Member):
        """
        Command to check user's reviewed reputation in this discord server.
        """
        positive_reviewed_reps = []
        positive_unreviewed_reps = []
        negative_reviewed_reps = []
        negative_unreviewed_reps = []

        async for rep in self.reps_db.find({
                'guild_id': ctx.guild.id,
                'reported_discord_id': player.id
        }):
            if rep['type'] is None and rep['positive']:
                positive_unreviewed_reps.append(rep)
            elif rep['type'] is None and not rep['positive']:
                negative_unreviewed_reps.append(rep)
            elif rep['type'] is not None and rep['positive']:
                positive_reviewed_reps.append(rep)
            elif rep['type'] is not None and not rep['positive']:
                negative_reviewed_reps.append(rep)

        embed = Embed(
            ctx=ctx,
            title=f'{player.name} Reputations',
        ).add_field(name='All Positive Reps',
                    value=f'{len(positive_reviewed_reps)}').add_field(
                        name='All Negative Reps',
                        value=f'{len(negative_reviewed_reps)}')

        async for category in self.rep_categories_db.find(
            {'guild_id': ctx.guild.id}):
            category_reps = [
                rep for rep in positive_reviewed_reps + negative_reviewed_reps
                if rep['type'] == category['name']
            ]
            embed.add_field(name=f'{category["name"]}',
                            value=f'{len(category_reps)}')

        await embed.add_field(
            name=f'Unreviewed',
            value=
            f'{len(negative_unreviewed_reps) + len(positive_unreviewed_reps)}'
        ).send()
Beispiel #9
0
    async def stats(self, ctx):
        """
        Displays stats about the bot including number of servers and users.
        """
        server_rankings = sorted(self.bot.guilds,
                                 key=lambda guild: len(guild.members),
                                 reverse=True)[:10]
        server_rankings = f'{"Top Servers".ljust(28)} | Users\n' + '\n'.join([
            f'{guild.name[:28].ljust(28)} | {len(guild.members):,}'
            for guild in server_rankings
        ])

        embed = Embed(
            ctx=ctx,
            title='Discord Stats',
            description=
            f'This command was run on shard {(ctx.guild.shard_id if ctx.guild else 0) + 1} / {self.bot.shard_count}.\n```{server_rankings}```'
        ).add_field(
            name='Servers',
            value=
            f'{self.bot.user.name} is running in {len(self.bot.guilds):,} servers with {sum(len(guild.text_channels) for guild in self.bot.guilds):,} channels.',
            inline=False
        ).add_field(
            name='Users',
            value=
            f'There are currently {sum(len(guild.members) for guild in self.bot.guilds):,} users with access to the bot.',
            inline=False)
        shards = []
        for x in range(self.bot.shard_count):
            shards.append([0, 0, 0])
        for x in self.bot.guilds:
            shards[x.shard_id][0] += 1
            shards[x.shard_id][1] += len(x.text_channels)
            shards[x.shard_id][2] += len(x.members)

        for x in range(self.bot.shard_count):
            embed.add_field(
                name=f'Shard {x + 1}',
                value=
                f'{shards[x][0]:,} servers\n{shards[x][1]:,} channels\n{shards[x][2]:,} members',
                inline=True)

        memory_usage = self.process.memory_full_info().uss / 1024**2
        cpu_usage = self.process.cpu_percent() / psutil.cpu_count()
        embed.add_field(name='Process',
                        value=f'{memory_usage:.2f} MiB\n{cpu_usage:.2f}% CPU',
                        inline=False)

        embed.add_footer(
            text=
            f'This message was delivered in {self.bot.latency * 1000:.0f} milliseconds.'
        )

        await embed.send()
Beispiel #10
0
    async def avatar(self,
                     ctx: HarleyContext,
                     user: Union[discord.Member, discord.User] = None):
        """Returns the users avatar, can be a user or member."""
        user = user or ctx.author

        await ctx.reply(embed=Embed(
            title=f"{user.name}'s avatar",
            description=f'[Url]({user.avatar} "Avatar Link ")',
        ).set_image(url=user.avatar))
Beispiel #11
0
    async def invite(self, ctx: HarleyContext, perms: Optional[int] = None):
        """Returns an invite for the bot."""

        embed = Embed(title="Invite")

        if perms is not None:

            if len(str(perms)) > 30:
                raise commands.BadArgument(
                    "Why is the permissions value over 30 characters long?")

            embed.description = f"[Your Permissions]({discord.utils.oauth_url(ctx.bot.user.id, permissions=discord.Permissions(perms))})"
            return await ctx.reply(embed=embed)

        embed.description = (
            f"[Recommended Permissions]({discord.utils.oauth_url(ctx.bot.user.id, permissions=discord.Permissions(470150358))})\n"
            f"[No Permissions]({discord.utils.oauth_url(ctx.bot.user.id, permissions=discord.Permissions(0))})\n"
            f"[Admin Permissions]({discord.utils.oauth_url(ctx.bot.user.id, permissions=discord.Permissions(8))})"
        )

        await ctx.reply(embed=embed)
Beispiel #12
0
    async def userinfo(
        self,
        ctx: HarleyContext,
        user: Optional[Union[discord.Member, discord.User]] = None,
        *,
        flags: WhoIsFlags,
    ):
        """
        Returns user info, input can be a user not in the guild.
        If the user's name has a space, use quotes around their name.
        """
        user = user or ctx.author

        embed = Embed(
            title=f"Information About {user}",
            description=(
                f"Created At: {user.created_at.strftime(TIME_TEMPLATE)}\n"
                f"Bot: {YES_NO[user.bot]} \n"
                f"ID: {user.id}"),
        )

        if flags.avatar is not False:
            embed.set_thumbnail(url=user.avatar)

        if isinstance(user, discord.Member):

            embed.add_field(
                name="Guild Related Info:",
                value=(f"Joined At: {user.joined_at.strftime(TIME_TEMPLATE)}\n"
                       f"Nickname: {user.nick or 'None'}\n"
                       f"Top Role: {user.top_role.mention}"),
            )

        await ctx.reply(embed=embed)
    async def report(self, ctx, player: discord.Member, proof: str, *, reason: str):
        """
        Report a player.
        """
        imgur_regex = re.compile('https?://imgur.com/(a/)?(\S*)')
        proof_match = imgur_regex.match(proof)
        if proof_match is None:
            return await ctx.send(f'{ctx.author.mention}\nPlease post imgur link or imgur gallery/album link only\n'
                                  f'Example: one image: `sbs report (someone) https://imgur.com/Wb1z8y7 (reason)`\n'
                                  f'Or gallery/album link: `sbs report (someone) https://imgur.com/a/H1AKoI8 (reason)`.')

        report = REPORT.copy()
        report['guild_id'] = ctx.guild.id
        report['reported_discord_id'] = player.id
        report['reported_mojang_uuid'] = None
        report['submitter_discord_id'] = ctx.author.id
        report['submitter_mojang_uuid'] = None
        report['reason'] = reason
        report['proof'] = proof
        report['submitted_timestamp'] = int(time.time())

        confirm_embed = Embed(
            ctx=ctx,
            title='Do you want to report this player?'
        ).add_field(
            name='Reported Discord ID',
            value=f'{report["reported_discord_id"]}'
        ).add_field(
            name='Reported Mojang UUID',
            value=f'{report["reported_mojang_uuid"]}'
        ).add_field().add_field(
            name='Submitter Discord ID',
            value=f'{report["submitter_discord_id"]}'
        ).add_field(
            name='Submitter Mojang UUID',
            value=f'{report["submitter_mojang_uuid"]}'
        ).add_field().add_field(
            name='Reason',
            value=f'{report["reason"]}',
            inline=False
        ).add_field(
            name='Proof',
            value=f'{report["proof"]}',
            inline=False
        )
        confirmed = await ctx.prompt(embed=confirm_embed)
        if not confirmed:
            return await ctx.send(f'{ctx.author.mention}\nReport again if you make a typo!')

        await self.reports_db.insert_one(report)

        await ctx.send(f'{ctx.author.mention}\nYou reported {player.name}!')
Beispiel #14
0
    async def apod(self, ctx, date=None):
        """An astronomy picture of the day from NASA's api. Use `YYYY-MM-DD` for the date or the latest will be pulled."""

        url = (
            f"https://api.nasa.gov/planetary/apod?date={date}&api_key={self.bot.config['nasa']}"
            if date is not None else
            f"https://api.nasa.gov/planetary/apod?api_key={self.bot.config['nasa']}"
        )

        json = await (await self.bot.session.get(url)).json()

        if error := json.get("msg"):
            return await ctx.reply(
                embed=Embed(title="Error", description=error))
Beispiel #15
0
    async def status(self, ctx):
        """
        Check all the skyblock event schedules status.
        """
        embed = Embed(
            ctx=ctx,
            title='Current event schedules status',
            description=
            f'There are currently {len(self.event_schedules)} event schedules. (EST time)'
        )

        for event in self.event_schedules.values():
            estimate = datetime.fromtimestamp(
                event["estimate"] / 1000.0).astimezone(EST).strftime(
                    datetime_fmt).lstrip('0').replace(' 0', ' ')
            embed.add_field(
                name=f'{SKYBLOCK_EVENTS[event["name"]]["name"]} Status',
                value=f'Current estimate > {estimate}\n'
                f'Next schedule > {event["time"].astimezone(EST).strftime(datetime_fmt).lstrip("0").replace(" 0", " ")}\n'
                f'Next schedule type > {event["type"]}',
                inline=False)

        await embed.send()
Beispiel #16
0
 async def confirm_options(ctx, perfect_crit_chance, attack_speed_limit,
                           only_blacksmith, ignored_reforges, selected_pots,
                           selected_buffs, dungeon_item_used,
                           include_dungeon):
     potions_list = [
         f'{name.capitalize()}: {level}' for name, level in selected_pots
         if level != 0
     ]
     embed = Embed(ctx=ctx, title='Are these options correct?').add_field(
         name='Goal',
         value=
         f'```{"Perfect crit chance" if perfect_crit_chance else "Maximum damage"}```'
     ).add_field(
         name='Attack speed limit', value=f'```{attack_speed_limit}%```'
     ).add_field(
         name='Reforges',
         value=
         f'```{"Only blacksmith reforges" if only_blacksmith else "All reforges"}```'
         + '{s}'.format(
             s=f'\n```Ignored reforges: {", ".join(ignored_reforges)}```'
             if ignored_reforges else ""),
         inline=False
     ).add_field(
         name='Potions',
         value=f"```{', '.join(potions_list) if potions_list else 'None'}```"
     ).add_field(
         name='Support items',
         value=
         f"```{', '.join([f'{item.capitalize()}' for item in selected_buffs]) if selected_buffs else 'None'}```"
     )
     if dungeon_item_used:
         embed.add_field(
             name='Dungeon items',
             value=
             f'```{"Dungeon stats" if include_dungeon else "Regular stats"}```',
             inline=False)
     return await ctx.prompt(embed=embed)
Beispiel #17
0
    def twitch(self, ctx, search):
        url = "https://api.twitch.tv/kraken/search/channels"
        params = {'q': search, 'client_id': config.TWITCH_CLIENT_ID}
        r = requests.get(url, params=params)

        if r.status_code != 200:
            raise BotException()

        body = r.json()
        channels = body.get('channels')
        if not channels:
            raise NotFound()

        channel = channels[0]

        embed = Embed({
            'color':
            0x6441a5,
            'title':
            channel['name'],
            'description':
            channel['status'],
            'url':
            channel['url'],
            'thumbnail': {
                'url': channel['logo'],
                'width': 100,
                'height': 100
            },
            'fields': [{
                'name': 'followers',
                'value': channel['followers'],
                'inline': True
            }, {
                'name': 'views',
                'value': channel['views'],
                'inline': True
            }, {
                'name': 'last played game',
                'value': channel['game']
            }]
        })

        return Response(embed=embed)
Beispiel #18
0
    def urban(self, ctx, search):
        url = "http://api.urbandictionary.com/v0/define"
        params = {'term': search}
        r = requests.get(url, params=params)
        if r.status_code != 200:
            raise BotException()

        body = r.json()
        data = body.get('list')
        if not data:
            raise NotFound()

        entry = data[0]

        embed = {
            'thumbnail': {
                'url':
                'https://upload.wikimedia.org/wikipedia/en/b/b7/Urban_dictionary_--_logo.jpg',
                'width': 100,
                'height': 100
            },
            'color':
            0xCC3C32,
            'title':
            entry['word'],
            'description':
            entry['definition'],
            'url':
            entry['permalink'],
            'fields': [
                {
                    'name': 'example',
                    'value': entry['example'],
                    'inline': True
                },
            ]
        }
        embed = Embed(embed)

        return Response(embed=embed)
Beispiel #19
0
    async def send_event_alert(self, event_data):
        """
        Send the event alert 5 mins before starting and schedule tasks to get new estimate time.
        """
        del self.event_schedules[event_data['task_id']]

        event = event_data['name']
        _howlong = round(
            ((event_data['estimate'] - current_milli_time()) / 1000.0) / 60.0)
        _when = datetime.fromtimestamp(
            event_data["estimate"] /
            1000.0).astimezone(EST).strftime(time_fmt).lstrip('0').replace(
                ' 0', ' ')
        embed = Embed(
            title=f'{SKYBLOCK_EVENTS[event]["name"]} Alert',
            description=
            f'The event is starting in {_howlong} minutes at {_when} EST.')

        async for guild in self.guilds_db.find({
                'events.default_enabled': True,
                f'events.{event}.enabled': True,
                'global_blacklisted': False,
                'global_blacklisted_commands': {
                    '$ne': 'events'
                }
        }):
            self.bot.loop.create_task(self._event_alert(guild, event, embed))

        # Calculate time when to get new estimate time. (20 min after event happened)
        time = datetime.fromtimestamp((event_data['estimate'] / 1000.0) + 1200)

        # Schedule new task to get new estimate
        event_data['task_id'] = id(time)
        event_data['type'] = 'get_estimate'
        event_data['time'] = time

        self._schedule_event_task(event_data)
Beispiel #20
0
    async def botinfo(self, ctx):
        delta_uptime = datetime.utcnow() - self.bot.start_time
        hours, remainder = divmod(int(delta_uptime.total_seconds()), 3600)
        minutes, seconds = divmod(remainder, 60)
        days, hours = divmod(hours, 24)

        embed = Embed(
            title="Info about me",
            description=
            (f"I am a bot made by {self.bot.get_user(self.bot.owner_id)} in discord.py! \n"
             ),
        ).add_field(
            name="Stats",
            value=(f"```diff\n"
                   f"+ Guilds: {len(self.bot.guilds)}\n"
                   f"+ Users: {len(self.bot.users)}\n"
                   f"+ Python: {platform.python_version()}\n"
                   f"+ Discord.py: {discord.__version__}\n"
                   f"+ Commands Used: {self.bot.usage}\n"
                   f"+ Uptime: {days}d, {hours}h, {minutes}m, {seconds}s"
                   "```"),
        )

        await ctx.reply(embed=embed)
Beispiel #21
0
    async def serverinfo(self, ctx: HarleyContext, *, flags: GuildInfoFlags):
        """
        Returns info about the server.
        """
        guild = ctx.guild

        embed = Embed(
            title=guild.name,
            description=(f"Owner: {guild.owner} \n"
                         f"Member Count: {guild.member_count} \n"
                         f"Region: {title_format(str(guild.region))} \n"),
        ).set_thumbnail(url=guild.icon)

        if flags.banner is True:
            embed.set_thumbnail(url=guild.banner)

        if flags.features is True:
            embed.add_field(
                name="Features",
                value="\n".join(
                    [title_format(feature) for feature in guild.features]),
            )

        await ctx.reply(embed=embed)
Beispiel #22
0
    async def enable(self, ctx):
        """
        Use this to enable a command!
        """
        disabled_commands = []
        for command in self.bot.walk_commands():
            if not command.enabled and command.qualified_name not in [
                    'disable', 'enable'
            ]:
                disabled_commands.append(command)

        if not disabled_commands:
            return await ctx.send(
                f'{ctx.author.mention}\nThere is no disabled commands to enable!'
            )

        embed = Embed(ctx=ctx,
                      title='Enter a command from the list below to enable!')
        _num = (len(disabled_commands) // 3)
        _left_over = len(disabled_commands) % 3
        _field1 = '\n'.join([
            command.qualified_name
            for command in disabled_commands[:_num + _left_over]
        ]) + '\u200b'
        if _field1:
            embed.add_field(value=f'{_field1}')
        else:
            embed.add_field()
        _field2 = '\n'.join([
            command.qualified_name
            for command in disabled_commands[_num + _left_over:(_num * 2) +
                                             _left_over]
        ]) + '\u200b'
        embed.add_field(value=f'{_field2}')
        _field3 = '\n'.join([
            command.qualified_name
            for command in disabled_commands[(_num * 2) + _left_over:]
        ]) + '\u200b'
        embed.add_field(value=f'{_field3}')
        await embed.send()

        def check(m):
            if m.author.id == ctx.author.id and m.channel.id == ctx.channel.id:
                if m.clean_content.lower() == 'exit':
                    raise SessionTimeout
                if not m.clean_content.isdigit():
                    return True
            return False

        _run = True
        while _run:
            msg = await self.bot.wait_for('message', timeout=60.0, check=check)
            for command in disabled_commands:
                if msg.clean_content.lower() == command.qualified_name:
                    command.enabled = True
                    await ctx.send(
                        f'{ctx.author.mention}\nSuccessfully enable command `{command.qualified_name}`!'
                    )
                    _run = False
                    break
            if _run:
                await ctx.send(
                    f'{ctx.author.mention}\nDid you make a typo? Choose a command from the list.'
                )
Beispiel #23
0
 async def privacy(self, ctx):
     await ctx.reply(embed=Embed(
         title="You can view the privacy policy here.",
         url=
         "https://gist.github.com/ImVaskel/c4bdf888b89e29dd16257264b9f92181",
     ))
Beispiel #24
0
 async def ping(self, ctx, **flags):
     await ctx.reply(embed=Embed(
         description=f"Pong! `{self.bot.latency*1000:.2f} ms`"))
Beispiel #25
0
    async def stats(self, ctx):
        """
        Displays stats about the bot including number of servers and users.
        """
        server_rankings = sorted(self.bot.guilds, key=lambda guild: guild.member_count, reverse=True)[:10]
        #server_rankings2 = f'{"Top Servers".ljust(28)} | Users\n' + '\n'.join(
        #    [f'{guild.name[:28].ljust(28)} | {guild.member_count}' for guild in server_rankings])

        embed = Embed(
            ctx=ctx,
            title='SkyBlock Simplified Bot Stats',
            description=f'This discord server in on shard {(ctx.guild.shard_id if ctx.guild else 0) + 1} / {self.bot.shard_count}.'
        ).add_field(
            name='Top Servers',
            value='\n'.join([f'{guild.name}' for guild in server_rankings]),
            inline=True,
        ).add_field(
            name='Users',
            value='\n'.join([f'{guild.member_count}' for guild in server_rankings]),
            inline=True,
        ).add_field(
            name='\u200b',
            value='\u200b',
            inline=True,
        ).add_field(
            name='Servers',
            value=f'{self.bot.user.name} is running in {len(self.bot.guilds):,} servers with {sum(len(guild.text_channels) for guild in self.bot.guilds):,} channels.',
            inline=False
        ).add_field(
            name='Users',
            value=f'There are currently {sum(guild.member_count for guild in self.bot.guilds):,} users with access to the bot.',
            inline=False
        )

        shards = []
        for x in range(self.bot.shard_count):
            shards.append([0, 0, 0])
        for x in self.bot.guilds:
            shards[x.shard_id][0] += 1
            shards[x.shard_id][1] += len(x.text_channels)
            shards[x.shard_id][2] += x.member_count

        for x in range(self.bot.shard_count):
            embed.add_field(
                name=f'Shard {x + 1}',
                value=f'{shards[x][0]:,} servers\n{shards[x][1]:,} channels\n{shards[x][2]:,} members',
                inline=True
            )

        shard_count = len(shards)
        total_fields = 3 * round((shard_count + 3) / 3)
        remaining_fields = total_fields - shard_count

        # column adjustment
        for x in range(remaining_fields):
            embed.add_field(
                name='\u200b',
                value='\u200b',
                inline=True
            )

        memory_usage = self.process.memory_full_info().uss / 1024 ** 2
        cpu_usage = self.process.cpu_percent() / psutil.cpu_count()
        embed.add_field(
            name='Process',
            value=f'{memory_usage:.2f} MiB\n{cpu_usage:.2f}% CPU',
            inline=True
        ).add_field(
            name='Latency',
            value=f'{self.bot.latency * 1000:.0f} ms',
            inline=True
        ).add_field(
            name='\u200b',
            value='\u200b',
            inline=True
        )

        await embed.send()
Beispiel #26
0
    async def send_optimizer_result(ctx, profile, best_route, include_dungeon):
        weapon = profile.weapon
        best_stats = best_route[0] or {}
        best_equip = best_route[1] or {}
        is_optimized = best_route[0]['is optimized']

        if not best_equip:
            return await ctx.send(
                f'{ctx.author.mention}, Optimization is not possible with the options you chose!\n'
                f'Collect more talismans or raise your combat level before trying again.'
            )

        embed = Embed(
            ctx=ctx,
            title='{s}'.format(
                s='Successful!' if is_optimized else 'Unsuccessful!')
        ).add_footer(
            text='Player\'s stats include pots.\n'
            '{s}'.format(s='Armor/Weapon includes dungeon stats.\n'
                         if include_dungeon else '') +
            'Please make sure your "before" stats are correct before reforging.'
        )

        for equipment in best_equip:
            for rarity in best_equip[equipment]:
                text = colorize(
                    ' + '.join([
                        f'{best_equip[equipment][rarity][reforge]} {reforge.title()}'
                        for reforge in best_equip[equipment][rarity]
                    ]), RARITY_COLORS[rarity])
                embed.add_field(
                    name=f'**{rarity.title()} {equipment.title()}**',
                    value=text,
                    inline=False)

        base_mod = profile.stats.combat_bonus + (profile.stats.archery_bonus if
                                                 weapon.type == 'bow' else 0)

        if include_dungeon:
            normal_mod = emod('base', weapon) + base_mod

            normal_damage_before = damage(
                profile.weapon.stats.get_stat('damage',
                                              dungeon=include_dungeon),
                profile.stats.get_stat('strength', dungeon=include_dungeon),
                profile.stats.get_stat('crit damage', dungeon=include_dungeon),
                normal_mod)

            normal_damage_after = damage(best_stats['damage'],
                                         best_stats['strength'],
                                         best_stats['crit damage'], normal_mod)

            before_damage = f'```Base > {normal_damage_before:,.0f}```'
            after_damage = f'```Base > {normal_damage_after:,.0f}```'
        else:
            zealot_mod = emod('zealots', weapon) + base_mod
            slayer_mod = emod('slayer bosses', weapon) + base_mod

            slayer_mult = 1
            if weapon.internal_name == 'REAPER_SWORD':
                slayer_mult = 3
            elif weapon.internal_name == 'SCORPION_FOIL':
                slayer_mult = 2.5

            zealot_damage_before = damage(
                profile.weapon.stats.get_stat('damage',
                                              dungeon=include_dungeon),
                profile.stats.get_stat('strength', dungeon=include_dungeon),
                profile.stats.get_stat('crit damage', dungeon=include_dungeon),
                zealot_mod)
            slayer_damage_before = damage(
                profile.weapon.stats.get_stat('damage',
                                              dungeon=include_dungeon),
                profile.stats.get_stat('strength', dungeon=include_dungeon),
                profile.stats.get_stat('crit damage', dungeon=include_dungeon),
                slayer_mod)
            slayer_damage_before *= slayer_mult

            zealot_damage_after = damage(best_stats['damage'],
                                         best_stats['strength'],
                                         best_stats['crit damage'], zealot_mod)
            slayer_damage_after = damage(best_stats['damage'],
                                         best_stats['strength'],
                                         best_stats['crit damage'], slayer_mod)
            slayer_damage_after *= slayer_mult

            before_damage = f'```Zealots > {zealot_damage_before:,.0f}\nSlayers > {slayer_damage_before:,.0f}```'
            after_damage = f'```Zealots > {zealot_damage_after:,.0f}\nSlayers > {slayer_damage_after:,.0f}```'

        weapon_damage_before = ''
        weapon_damage_after = ''
        if weapon.internal_name == 'MIDAS_SWORD':
            weapon_damage_before = f'Weapon damage > {profile.weapon.stats.get_stat("damage", dungeon=include_dungeon):.0f}'
            weapon_damage_after = f'Weapon damage > {best_stats["damage"]:.0f}'

        embed.add_field(
            name='**Before**',
            value=
            f'```Strength > {profile.stats.get_stat("strength", dungeon=include_dungeon):.0f}\n'
            f'Crit damage > {profile.stats.get_stat("crit damage", dungeon=include_dungeon):.0f}%\n'
            f'Crit chance > {profile.stats.get_stat("crit chance", dungeon=include_dungeon):.0f}%\n'
            f'Attack speed > {profile.stats.get_stat("attack speed", dungeon=include_dungeon):.0f}%\n'
            f'{weapon_damage_before}```{before_damage}')
        embed.add_field(
            name='**After**',
            value=
            f'```Strength > {best_stats["strength"]:.0f}\nCrit damage > {best_stats["crit damage"]:.0f}%\n'
            f'Crit chance > {best_stats["crit chance"]:.0f}%\nAttack speed > {best_stats["attack speed"]:.0f}%\n'
            f'{weapon_damage_after}```{after_damage}')

        if not is_optimized:
            embed.add_field(
                name='**Warning**',
                value=
                'The bot took too long to optimize your gear so it gave up.\n'
                'This result is the best it could do in the allotted time.',
                inline=False)

        await embed.send()
Beispiel #27
0
 async def emoji(self, ctx: HarleyContext, emoji: discord.PartialEmoji):
     await ctx.reply(embed=Embed(
         title=emoji.name,
         description=(f"Animated: {YES_NO[emoji.animated]} \n"
                      f"ID {emoji.id}\n"),
     ).set_image(url=emoji.url))
Beispiel #28
0
    async def optimizer(self, ctx, player: str = '', profile: str = ''):
        """
        Optimizes your equipments to their best reforges.
        """
        await ctx.send(
            f'{ctx.author.mention}, Welcome to the optimizer!\n'
            f'Please enter `exit` at any given point in the optimizer to exit')

        player = await ask_for_skyblock_profiles(
            ctx,
            player,
            profile,
            session=self.bot.http_session,
            hypixel_api_client=self.bot.hypixel_api_client)
        profile = player.profile

        if player.online:
            raise PlayerOnlineError

        if not profile.enabled_api['skills'] or not profile.enabled_api[
                'inventory']:
            raise APIDisabledError(player.uname, profile.name)

        weapon = await self.prompt_for_weapon(ctx, profile)
        if not weapon:
            raise NoWeaponError

        armor = await self.prompt_for_armor(ctx, profile)
        if not armor:
            raise NoArmorError

        pet = await self.prompt_for_pet(ctx, profile)

        # Check if user selected dungeon items
        dungeon_item_used = False
        if weapon.dungeon:
            dungeon_item_used = True
        if not dungeon_item_used:
            for piece in armor.values():
                if piece is None:
                    continue
                if piece.dungeon:
                    dungeon_item_used = True
                    break

        include_dungeon = False
        if dungeon_item_used:
            include_dungeon = await ctx.prompt(embed=Embed(
                ctx=ctx,
                title="Do you want to use your items' dungeon stats? yes/no"))

        profile.set_weapon(weapon)
        profile.set_armor(armor, dungeon=include_dungeon)
        profile.set_pet(pet, dungeon=include_dungeon)

        profile_confirm = await self.confirm_equipment(ctx, profile)
        if not profile_confirm:
            raise SessionTimeout

        perfect_crit_chance = await ctx.prompt(embed=Embed(
            ctx=ctx, title='What would you like to optimize for?').add_field(
                value='\n\n'.join(f'> {o["emoji"]}\n`{o["name"]}`'
                                  for o in OPTIMIZER_GOALS)),
                                               emoji_list=[('💯', True),
                                                           ('💥', False)])

        attack_speed_limit = await self.prompt_for_attack_speed(ctx)

        only_blacksmith, reforges_set, ignored_reforges = await self.prompt_for_reforges(
            ctx)

        selected_pots = await self.prompt_for_potions(ctx, profile)

        selected_buffs = await self.prompt_for_support_item(ctx, profile)

        option_confirm = await self.confirm_options(
            ctx, perfect_crit_chance, attack_speed_limit, only_blacksmith,
            ignored_reforges, selected_pots, selected_buffs, dungeon_item_used,
            include_dungeon)
        if not option_confirm:
            raise SessionTimeout

        best_route = damage_optimizer(profile,
                                      perfect_crit_chance=perfect_crit_chance,
                                      attack_speed_limit=attack_speed_limit,
                                      only_blacksmith_reforges=only_blacksmith,
                                      include_dungeon=include_dungeon,
                                      reforges_set=reforges_set)

        await self.send_optimizer_result(ctx, profile, best_route,
                                         include_dungeon)
Beispiel #29
0
    async def player(self, ctx, player: str = '', profile: str = ''):
        """
        Displays a player\'s guild, skills, and slayer levels.
        """
        player = await ask_for_skyblock_profiles(ctx, player, profile, session=self.bot.http_session,
                                                 hypixel_api_client=self.bot.hypixel_api_client, auto_set=True,
                                                 get_guild=True)
        profile = player.profile
        guild = player.guild

        api_header = ' '.join(
            f'{key.capitalize()} {"✅" if value else "❌"}' for key, value in profile.enabled_api.items())

        total_xp = 0
        for skill in SKILL_NAMES:
            if skill in COSMETIC_SKILL_NAMES:
                continue
            total_xp += profile.skills_xp.get(skill, 0)

        embed = Embed(
            ctx=ctx,
            title=f'{player.uname} | {profile.name}',
            description=f'```{api_header}```\n'
                        f'```Deaths > {profile.deaths:,}\n'
                        f'Guild > {guild.name if guild else None}\n'
                        f'Money > {profile.bank_balance + profile.purse:,.2f}\n'
                        f'Pet > {format_pet(profile.pet)}```'
        ).add_field(
            name=f'🔰 \tSkills',
            value=f'```Average > {profile.skill_average:.2f}\n'
                  f'Total XP > {total_xp:,.0f}\n'
                  f'{(profile.skill_average / 50 * 100):.2f}% Maxed```',
            inline=False
        ).add_field(
            name=f'🛠️ \tMinions',
            value=f'```Slots > {profile.minion_slots}\n'
                  f'Uniques > {profile.unique_minions}```',
            inline=False
        ).set_thumbnail(
            url=player.get_avatar_url()
        )

        for skill, level in profile.skills.items():
            percent_to_max = 100 * min(1, profile.skills_xp.get(skill, 0) / (
                RUNECRAFTING_LEVEL_REQUIREMENT[-1] if skill == 'runecrafting' else SKILL_LEVEL_REQUIREMENT[-1]))
            embed.add_field(
                name=f'{SKILL_EMOJIS[skill]}\t{skill.capitalize()}',
                value=f'```Level > {level}\n'
                      f'XP > {profile.skills_xp.get(skill, 0):,.0f}\n'
                      f'{percent_to_max:.2f}% Maxed```'
            )
        # So every skill embed field is same size
        left_over_field = 3 - (len(profile.skills) % 3)
        if left_over_field < 3:
            for i in range(0, left_over_field):
                embed.add_field()

        for slayer, level in profile.slayers.items():
            percent_to_max = 100 * min(1, profile.slayers_xp.get(slayer, 0) / SLAYER_LEVEL_REQUIREMENT[slayer][-1])
            embed.add_field(
                name=f'{SKILL_EMOJIS[slayer]}\t{slayer.capitalize()}',
                value=f'```Level > {level}\n'
                      f'XP > {profile.slayers_xp.get(slayer, 0):,.0f}\n'
                      f'{percent_to_max:.2f}% Maxed```'
            )
            
        embed.add_field(
            name=f'{SKILL_EMOJIS["dungeons"]}\tDungeon Stats',
            value=f'```Selected Class > **{profile.dungeons.selected_dungeon_class.capitalize()}**\n'
                  f'Experience > **{Math.round(profile.dungeons.dungeon_types.catacombs.experience)}**```\n'
            inline=False
        )
            
        for d_class, experience in profile.dungeons.player_classes.items():
            percent_to_max = 100 * min(1, profile.dungeons.player_classes.get(d_class, 0) / DUNGEON_SKILL_LEVEL_REQUIREMENT[d_class][-1])
            embed.add_field(
                name=f'{DUNGEON_EMOJIS[d_class]}\t{d_class.capitalize()}',
                value=f'```Level > ?\n'
                      f'Experience > {experience:,.0f} XP\n'
                      f'{percent_to_max:.2f}% Maxed```'
            ).set_footer(
            text=f'Player is currently {"online" if player.online else "offline"} in game.'
        )

        await embed.send()