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)
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
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()
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()
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()
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)
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)
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()
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()
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()
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.' )