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 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())))
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")))
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")))
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)
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
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}```"))
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 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 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))
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)
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}!')
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))
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)
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)
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)
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)
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)
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 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.' )
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", ))
async def ping(self, ctx, **flags): await ctx.reply(embed=Embed( description=f"Pong! `{self.bot.latency*1000:.2f} ms`"))
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 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 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))
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)
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()