async def commits(self, ctx): await ctx.send("Getting commits") paginator = await self.commits_() interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author) await interface.send_to(ctx)
async def caseslist(self, ctx, detailed: bool = False): """Lists all cases. run "g!cases True" to get a more detailed list. Note this increases the amount of pages you will need to scroll through""" es = discord.utils.escape_markdown paginator = PaginatorEmbedInterface( self.bot, commands.Paginator(max_size=750, prefix="", suffix="")) # prefix + suffix = "" because it stops it breaking markdown (for the box design) data = config.read("./data/core.json").get(str(ctx.guild.id)) things = ['warns', 'mutes', 'kicks', 'bans', 'unbans'] msgs = [] for case_type in things: for case_id, case_data in data[case_type].items(): case_data["ctx"] = ctx case_data["case_id"] = case_id case = await entry_helper.Case.from_dict(case_data) msg = f"```md\n# Case action: {case_type.replace('s', '')}\n# Case ID: {case.id}\n# Case Target: {es(str(case.target))}" if detailed: msg += f"\n# Moderator: {es(str(case.author))}\n# Reason: {es(case.reason[:300])}" if len(msg) >= 1600: msg = msg[:1590] + '...' msg += '```' # await paginator.add_line(msg, empty=True) n = case.id msgs.append((int(n), msg)) for _, content in sorted(msgs): await paginator.add_line(content, empty=True) await paginator.send_to(ctx.channel)
async def lyrics(self, ctx, *, query: typing.Union[Member, str] = None): lyrics = None query = ctx.author if not query else query if type(query) == discord.Member: for activity in query.activities: if type(activity) == discord.Spotify: lyrics = await self.bot.ksoft.lyrics_search( f'{", ".join(activity.artists)} {activity.title}') if not lyrics: raise commands.BadArgument( 'That member isn\'t listening to Spotify!') elif type(query) == discord.User: raise commands.BadArgument('Missing search query') else: lyrics = await self.bot.ksoft.lyrics_search(query) if len(lyrics.results) < 1: return await ctx.error('No lyrics found') lyrics: ksoftapi.LyricsSearchResp = lyrics.results[0] paginator = WrappedPaginator(prefix='', suffix='', max_size=1000) for line in lyrics.lyrics.split('\n'): paginator.add_line(line) embed = discord.Embed(color=ctx.author.color, title=f'{lyrics.name} by {lyrics.artist}', url=lyrics.url) footer = { 'text': 'Powered by KSoft.Si API', 'icon_url': 'https://cdn.ksoft.si/images/Logo128.png' } interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed, _footer=footer) await interface.send_to(ctx)
async def send_pages(self): destination = self.get_destination() interface = PaginatorEmbedInterface(self.context.bot, self.paginator, owner=self.context.author) await interface.send_to(destination)
async def lyrics(self, ctx, *, query: str = None): lyrics = None if not query: return await ctx.error('Missing search query') else: lyrics = await self.bot.ksoft.lyrics_search(query) if not lyrics or len(lyrics.results) < 1: return await ctx.error('No lyrics found') lyrics = lyrics.results[0] paginator = WrappedPaginator(prefix='', suffix='', max_size=1000) for line in lyrics.lyrics.split('\n'): paginator.add_line(line) embed = discord.Embed(color=ctx.author.color, title=f'{lyrics.name} by {lyrics.artist}', url=lyrics.url) embed.set_thumbnail(url=lyrics.album_art) footer = { 'text': 'Powered by KSoft.Si API', 'icon_url': 'https://cdn.ksoft.si/images/Logo128.png' } interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed, _footer=footer) await interface.send_to(ctx)
async def role(self, ctx, *, role: Role = None): if not role: role = ctx.author.top_role embed = discord.Embed(colour=role.color if role.color != discord.Color.default() else ctx.author.color, timestamp=datetime.datetime.now(datetime.timezone.utc)) embed.add_field(name="» Name", value=role.name, inline=False) embed.add_field(name="» ID", value=role.id, inline=False) embed.add_field(name="» Mention", value=f'`{role.mention}`', inline=False) rgbcolor = role.color.to_rgb() hexcolor = rgb2hex(role.color.r, role.color.g, role.color.b).replace('##', '#') embed.add_field(name="» Hoisted?", value='Yes' if role.hoist else 'No') embed.add_field(name="» Mentionable?", value='Yes' if role.mentionable else 'No') embed.add_field(name="» Color", value=f'RGB: {rgbcolor}\nHEX: {hexcolor}') perms = [] if not role.permissions.administrator: for perm, value in role.permissions: if value and perm in permissions: perms.append(permissions[perm]) if perms: embed.add_field(name="» Key Permissions", value=', '.join(perms), inline=False) else: embed.add_field(name="» Permissions", value='Administrator', inline=False) await ctx.send(embed=embed) is_cached = len(ctx.guild.members) / ctx.guild.member_count if role.members and is_cached > 0.98: paginator = WrappedPaginator(prefix='', suffix='', max_size=250) for member in role.members: paginator.add_line(member.mention) membed = discord.Embed( colour=role.color if role.color != discord.Color.default() else ctx.author.color, timestamp=datetime.datetime.now(datetime.timezone.utc), title=f'Members [{len(role.members):,d}]' ) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=membed) await interface.send_to(ctx)
async def mcsteams(self, ctx): async with aiohttp.ClientSession() as s: async with s.get(f'https://minecraftsaturdays.net/api/roster/{self.season}/{self.week}') as r: p = await r.text() p = json.loads(p) teams = p['teams'] t = [] for team in teams: team["score"] = 0 for x in team["players"]: team["score"] += x["score"] players = [f'[{x["name"]}]({x.get("link", "https://minecraftsaturdays.net/")})\nтнР Points: {x["score"]}' for x in team["players"]] players = "\n".join(players) t.append({ 'text': f'**Team {teams.index(team) + 1}:**\n{players}\n\nЁЯПЕ Wins: {team["players"][0]["wins"]}\nтнР Total Points: {team["score"]}\n', 'score': team["score"] }) t = sorted(t, key=lambda t: t["score"]) t.reverse() paginator = WrappedPaginator(prefix='**Minecraft Saturdays Teams**', suffix='', max_size=650) for team in t: paginator.add_line(team["text"]) embed = discord.Embed(colour=ctx.author.color, timestamp=datetime.datetime.utcnow()) footer = {'text': 'https://minecraftsaturdays.net/', 'icon_url': 'https://cdn.discordapp.com/icons/618826436299456533/6dfe2d224d8d919cac6bd71dcf7b0955.png'} interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed, _footer=footer) await interface.send_to(ctx)
async def update(self, ctx, *, version: str = None): """Updates the module to the latest (or provided) version.""" proc = psutil.Process() with proc.oneshot(): command = proc.name() if not command.lower().startswith("py"): return await ctx.send( f"Unable to automatically update: process name does not start with `py`," f" so unable to invoke pip.") else: run = command.lower() + " -m pip install guildmanager-v2" + ( " --upgrade" if not version else f"=={version}") paginator = PaginatorEmbedInterface( self.bot, commands.Paginator("```bash", "```", 1600)) async with ctx.channel.typing(): with ShellReader(run, 120) as reader: async for line in reader: if paginator.closed: return else: await paginator.add_line(line) await paginator.add_line( f"[status] return code {reader.close_code}") return await paginator.send_to(ctx.channel)
async def nmcnames(self, ctx, name: str): async with aiohttp.ClientSession() as s: async with s.get(f'https://namemc.com/{name}') as r: content = await r.text() namecount, names, dates = await getnames(content, name) if type(namecount) == dict: data = namecount embed = discord.Embed(title=f'Name information for {name}', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) if 'when' in data: embed.add_field(name='Availability Status', value=data['when'], inline=False) if 'searches' in data: embed.add_field(name='Searches', value=data['searches'], inline=False) if 'toa' in data and data['toa'] != 'tomorrow': date = dateutil.parser.parse(data['toa']) date = datetime.datetime.strftime(date, '%d/%m/%Y @ %I:%M:%S %p') embed.add_field(name='Time of Availability', value=date, inline=False) if 'remain' in data and data['remain'] != 'an eternity': embed.add_field(name='Time Remaining', value=data['remain'], inline=False) await ctx.send(embed=embed) if namecount and names and dates: yeet = True else: raise commands.CommandError( 'I was unable to parse the list of names for that user') namelist = [] reqname = name paginator = WrappedPaginator(prefix='', suffix='', max_size=2000) for i, v in enumerate(namecount): count = namecount[i] namemd = names[i] name = discord.utils.escape_markdown(names[i]) name = f"[{name}](https://namemc.com/name/{name} 'Click here to go to the NameMC page for {namemd}')" try: date = dateutil.parser.parse(dates[i]) date = datetime.datetime.strftime(date, '%d/%m/%Y @ %I:%M:%S %p') except IndexError: date = 'First Name' paginator.add_line(f'**{count}** {name} {date}') embed = discord.Embed(title=f'Name history for {reqname}', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx)
async def send_cog_help(self, cog): paginator = commands.Paginator(prefix="", suffix="") commands_ = await self.filter_commands(cog.get_commands(), sort=True) commands_ = [self.get_command_signature(i) for i in commands_] for i in commands_: paginator.add_line(i) interface = PaginatorEmbedInterface( self.context.bot, paginator, owner=self.context.author) await interface.send_to(self.context)
async def skiermod(self, ctx, *, mod: str = None): if mod is None: return await ctx.error("You need to provide a mod name") route = Route( 'GET', f'/mods' ) try: mods = await self.bot.http.sk1er.request(route) except Exception: return await ctx.error(f'Failed to fetch mods') names = {} for m in mods: names[mods[m]['display'].lower()] = m for mod_id in mods[m]['mod_ids']: names[mod_id.lower()] = m if mod.lower() not in names: return await ctx.error(f'Unknown mod.') else: mod = mods[names[mod.lower()]] route = Route( 'GET', f'/mods_analytics' ) try: analytics = await self.bot.http.sk1er.request(route) analytics = analytics.get(mod['mod_ids'][0], {}) except Exception: return await ctx.error(f'Failed to fetch mod analytics') embed = discord.Embed( title=mod['display'], colour=ctx.author.color, url=f"https://sk1er.club/mods/{mod['mod_ids'][0]}", description=mod['short'], timestamp=datetime.datetime.utcnow() ) embed.add_field(name="Versions", value='\n'.join([f'**{k}**: {v}' for k, v in mod['latest'].items()]), inline=False) embed.add_field(name="Creator", value=f'''**__{mod['vendor']['name']}__** [Website]({mod['vendor']['website']}) [Twitter]({mod['vendor']['twitter']}) [YouTube]({mod['vendor']['youtube']}) ''', inline=False) if analytics: embed.add_field(name="Analytics", value=f"Total: {analytics['total']:,d}, Online: {analytics['online']:,d}, Last Day: {analytics['day']:,d}, Last Week: {analytics['week']:,d}", inline=False) await ctx.send(embed=embed) paginator = WrappedPaginator(prefix='', suffix='', max_size=490) for mcv in mod['changelog']: paginator.add_line(f'**__{mcv}__**') for v in mod['changelog'][mcv]: changelog = mod["changelog"][mcv][v][0] time = datetime.datetime.utcfromtimestamp(changelog["time"] / 1000).strftime('%d/%m/%Y @ %I:%M:%S %p') paginator.add_line(f'**{v}**: {changelog["text"]} ({time})') paginator.add_line('-----------------') embed = discord.Embed(color=ctx.author.color, title='Changelogs', timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx)
async def cfstatus(self, ctx): colors = { 'none': ctx.author.color, 'minor': discord.Color.gold(), 'major': discord.Color.orange(), 'critical': discord.Color.red(), 'maintenance': discord.Color.blue() } emoji = { 'operational': '<:operational:685538400639385649>', 'degraded_performance': '<:degraded_performance:685538400228343808>', 'partial_outage': '<:partial_outage:685538400555499675>', 'major_outage': '<:major_outage:685538400639385706>', 'under_maintenance': '<:maintenance:685538400337395743>' } sroute = Route('GET', '/summary.json') iroute = Route('GET', '/incidents.json') try: summary = await self.bot.http.cfstatus.request(sroute) incidents = await self.bot.http.cfstatus.request(iroute) except Exception: return await ctx.error(f'Failed to fetch Cloudflare status') # Cloudflare is a special little snowflake with a shit ton of compontents, too many for the embed description paginator = WrappedPaginator(prefix='', suffix='', max_size=1980) groups = {} for c in [c for c in summary['components'] if c['group_id']]: if c['status'] == 'operational': continue if c['group_id'] not in groups: groups[c['group_id']] = [c] else: groups[c['group_id']].append(c) for c in [c for c in summary['components'] if not c['group_id']]: paginator.add_line( f'├{emoji[c["status"]]} **{c["name"]}**: {c["status"].replace("_", " ").title()}' ) for s in groups.get(c['id'], []): paginator.add_line( f'├─{emoji[s["status"]]} **{s["name"]}**: {s["status"].replace("_", " ").title()}' ) embed = discord.Embed(color=colors[str( summary['status']['indicator'])], title=summary['status']['description'], timestamp=datetime.datetime.utcnow()) incident = incidents['incidents'][0] embed.add_field( name='Latest Incident', value= f'[{incident["name"]}]({incident["shortlink"]})\nStatus: **{incident["status"].capitalize()}**' ) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx)
async def paginate(self, *words, destination=None): embed = discord.Embed(color=discord.Colour.blurple()) pg = WrappedPaginator(prefix="", suffix="", max_size=2048) for line in words: pg.add_line(line) inf = PaginatorEmbedInterface(self.bot, pg, owner=self.author, embed=embed) await inf.send_to(destination or self)
async def send_pages(self): destination = self.get_destination() interface = PaginatorEmbedInterface( self.context.bot, self.paginator, owner=self.context.author, embed=discord.Embed( title=f"{self.context.bot.user.name}'s Help Command", color=0x40aeff)) await interface.send_to(destination)
async def reminders(self, ctx): mine = sorted(self.reminders.get(ctx.author.id, []), key=lambda r: r['for']) if not mine: return await ctx.error('You have no reminders.') paginator = WrappedPaginator(prefix='', suffix='', max_size=1980) for i, r in enumerate(mine): forwhen = datetime.datetime.fromtimestamp(r['for'], datetime.timezone.utc).strftime('%b %-d %Y @ %I:%M %p') delta = humanfriendly.format_timespan(datetime.datetime.fromtimestamp(r['for'], datetime.timezone.utc) - datetime.datetime.now(datetime.timezone.utc), max_units=2) paginator.add_line(f'[{i + 1}] {r["reminder"]} - {forwhen} ({delta})') interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author) return await interface.send_to(ctx)
async def servers(self, ctx): """Lists servers.""" paginator = PaginatorEmbedInterface( self.bot, commands.Paginator(prefix="```md", max_size=500)) for number, guild in enumerate(ctx.bot.guilds, start=1): dot = '\u200B.' backtick = '\u200B`' await paginator.add_line( discord.utils.escape_markdown( f'{number}. {guild.name.replace(".", dot).replace("`", backtick)}\n' )) await paginator.send_to(ctx.channel)
async def info(self, ctx, video: str): if findvideo(video): video = findvideo(video) videoinfo = await self.loop.run_in_executor(None, func=functools.partial( self.video_info, video)) try: videoinfo = videoinfo['items'][0] except (KeyError, IndexError): return await ctx.error( f'Couldn\'t find a video. Please provide a valid YouTube video URL' ) title = videoinfo['snippet']['title'] vid = videoinfo['id'] author = videoinfo['snippet']['channelTitle'] authorid = videoinfo['snippet']['channelId'] published = videoinfo['snippet']['publishedAt'].replace( 'T', ' ').split('.')[0] duration = videoinfo['contentDetails']['duration'].replace( 'PT', '').replace('H', ' Hrs ').replace('M', ' Mins ').replace('S', 'Secs') description = videoinfo['snippet']['description'] paginator = WrappedPaginator( prefix='```\nDescription (Use controls to change page)\n', suffix='```', max_size=1895) for line in description.split('\n'): paginator.add_line(line) views = format( int(videoinfo.get('statistics', {}).get('viewCount', 0)), ',d') likes = format( int(videoinfo.get('statistics', {}).get('likeCount', 0)), ',d') dislikes = format( int(videoinfo.get('statistics', {}).get('dislikeCount', 0)), ',d') comments = format( int(videoinfo.get('statistics', {}).get('commentCount', 0)), ',d') embed = discord.Embed(title=f"Video info for {video}", color=ctx.author.color, timestamp=datetime.datetime.utcnow()) embed.add_field( name=videoinfo["snippet"]["title"], value= f"» Link: [{title}](https://youtu.be/{vid} 'Click here to watch the video')\n» Author: [{author}](https://youtube.com/channel/{authorid} 'Click here to checkout {author} channel')\n» Published: {published}\n» Views: {views}\n» Likes: {likes}\n» Dislikes: {dislikes}\n» Comments: {comments}", inline=False) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) return await interface.send_to(ctx)
async def gm_root(self, ctx: commands.Context): """Shows a nice list of your bot's servers.""" group_commands = sum([ 1 for n in self.bot.walk_commands() if isinstance(n, commands.Group) ]) e = discord.Embed(title=f"You have: {len(self.bot.guilds)} guilds.") e.add_field( name="All Statistics:", value=f"**Guilds:** {len(self.bot.guilds)}\n" f"**Channels:** {len(list(self.bot.get_all_channels()))}\n" f"**Users:** {len(self.bot.users)}\n" f"**Emojis:** {len(set(self.bot.emojis))}\n" f"**Cached Messages:** {len(self.bot.cached_messages)}\n" f"**Average Ping:** `{round(self.average_latency, 3)}ms`\n" f"\n" f"**Loaded Cogs:** {len(self.bot.cogs)}\n" f"**Loaded Extensions:** {len(self.bot.extensions)}\n" f"\n" f"**Total single commands:** {len(self.bot.commands)}\n" f"**Total group commands:** {group_commands}\n" f"**Total sub commands:** {sum([1 for n in self.bot.walk_commands() if n.parent])}" ) e.add_field(name="Cog Info", value=f"**Loaded:** {nt(self.loaded)}\n" f"**Sampled Pings:** {ic(self.sampled_pings)}\n" f"**Version:** {__version__}") owners = [x.owner for x in self.bot.guilds] v = "" sorted_ = sorted(set(owners), key=lambda x: percent(owners.count(x), len(owners)), reverse=True) for n, user in enumerate(list(sorted_)[:10], start=1): v += f"{n}. {user} ({percent(owners.count(user), len(owners))}%)\n" e.add_field( name= "Guild owners, sorted by number of servers they own that uses the bot:", value=v) paginator = PaginatorEmbedInterface(self.bot, commands.Paginator("", "", max_size=1990), embed=e) for n, guild in enumerate(self.bot.guilds): await paginator.add_line( f"{ic(n)}. {guild} (`{guild.id}`): {guild.member_count}") await paginator.send_to(ctx.channel)
async def info(self, ctx, *, guild: DynamicGuild()): """Force get information on a guild. this includes debug information.""" owner, mention = guild.owner, guild.owner.mention text_channels = len(guild.text_channels) voice_channels = len(guild.text_channels) roles, totalroles = [ (role.name, role.permissions) for role in reversed(guild.roles) ], len(guild.roles) bots, humans = len([u for u in guild.members if u.bot ]), len([u for u in guild.members if not u.bot]) def get_siplified_ratio(): x = bots y = humans def get_hcf(): if x > y: smaller = y else: smaller = x for i in range(smaller, 0, -1): if (x % i == 0) and (y % i == 0): hcf = i break else: raise ArithmeticError( f"Unable to find HCF for {x} and {y} (smallest {smaller})" ) return hcf hcf = get_hcf() return f"{x / hcf}:{y / hcf}" bot_to_human_ratio = '{}:{} ({})'.format(bots, humans, get_siplified_ratio()) default_perms = guild.default_role.permissions.value invites = len(await guild.invites( )) if guild.me.guild_permissions.manage_guild else 'Not Available' fmt = f"Owner: {owner} ({owner.mention})\nText channels: {text_channels}\nVoice Channels: {voice_channels}\n" \ f"Roles: {totalroles}\nBTHR: {bot_to_human_ratio}\n`@everyone` role permissions: {default_perms}\nInvites: " \ f"{invites}" await ctx.send(fmt) paginator = PaginatorEmbedInterface(self.bot, commands.Paginator(max_size=500)) for name, value in roles: await paginator.add_line(f"@{name}: {value}") await paginator.send_to(ctx.channel) return await ctx.message.add_reaction('\U00002705')
async def commandsusage(self, ctx): counter = 0 lists = [f"Total {self.bot.command_counter} commands invoked"] for i, (n, v) in enumerate(self.bot.commandsusages.most_common()): counter += 1 lists.append(f"`{counter}. {n:<20} {v}`") paginator = commands.Paginator(max_size=1800, prefix="", suffix="") for i in lists: paginator.add_line(i) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author) return await interface.send_to(ctx)
async def cases_for(self, ctx, *, target: typing.Union[discord.User, int] = None): """Gets cases the target was... the target. e.g: ?cases for bob == target: bob""" async with ctx.channel.typing(): data = read("./data/core.json") if isinstance(target, int): try: target = await self.bot.fetch_user(target) except discord.NotFound: await ctx.send("target not found.") target = None target = target if target else ctx.author paginator = PaginatorEmbedInterface( self.bot, commands.Paginator(max_size=1000)) await paginator.add_line("[start]") unchecked = 0 if data.get(str(ctx.guild.id)): for _type in data[str(ctx.guild.id)].keys(): if _type not in [ 'warns', 'mutes', 'unmutes', 'kicks', 'bans', 'unbans' ]: continue for _case in data[str(ctx.guild.id)][_type].keys(): data[str(ctx.guild.id)][_type][_case]['ctx'] = ctx case = await entry_helper.Case.from_dict(data[str( ctx.guild.id)][_type][_case]) if isinstance(case.target, (discord.Member, discord.User)): if case.target.id == target.id: await paginator.add_line( f"Case {_case}: {_type.replace('s', '', 1)}\n" ) else: _target = self.bot.get_user(target) if _target is None: try: _target = await self.bot.fetch_user( case.target) except discord.NotFound: unchecked += 1 continue if _target == target: await paginator.add_line( f"Case {_case}: {_type.replace('s', '', 1)}\n" )
async def modlogs(self, ctx, user: UserWithFallback = None): """PFXmodlogs <user>""" if not user: user = ctx.author try: if type(user) == discord.User or type(user) == discord.Member: mlogs = self.modlogs[ctx.guild.id][user.id] elif type(user) == int: mlogs = self.modlogs[ctx.guild.id][user] except KeyError: return await ctx.send(f'<a:fireFailed:603214400748257302> No logs found.') paginator = WrappedPaginator(prefix='', suffix='') for log in mlogs: paginator.add_line(f'**Case ID**: {log["caseid"]}\n**Type**: {log["type"].capitalize()}\n**User**: {user}\n**Reason**: {log["reason"]}\n**Date**: {log["date"]}\n**-----------------**') embed = discord.Embed(color=discord.Color(15105570), timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx)
async def modlogs(self, ctx, user: UserWithFallback = None): if not user: user = ctx.author mlogs = await self.bot.db.fetch( 'SELECT * FROM modlogs WHERE uid=$1 AND gid=$2', user.id, ctx.guild.id ) if not mlogs: return await ctx.error('No modlogs found') paginator = WrappedPaginator(prefix='', suffix='') for log in mlogs: paginator.add_line(f'**Case ID**: {log["caseid"]}\n' f'**Type**: {log["type"].capitalize()}\n' f'**User**: {user}\n' f'**Reason**: {log["reason"]}\n' f'**Date**: {log["date"]}\n' f'**-----------------**') embed = discord.Embed(color=discord.Color(15105570), timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx)
async def reactionroles(self, ctx, *, message: int = None): """Lists reaction roles. To create/remove reaction roles, run `g!help rr` to get the subcommands""" data = config.read("./data/reactions.json") if str(ctx.guild.id) not in data.keys(): return await ctx.send(embed=discord.Embed( title="Reaction Roles:", description= "This guild has no reaction roles set up! Try `{0.prefix}{0.command.qualified_name} create`." .format(ctx), color=0xfdae55, timestamp=datetime.datetime.utcnow())) else: roles = [] for message_id in data[str(ctx.guild.id)].keys(): if int(message.id) == message or message is None: for role, emoji in message_id.items(): if role == "channelid": continue _role = ctx.guild.get_role(int(role)) if _role: _role = _role.mention else: _role = role roles.append( (_role, discord.utils.get(self.bot.emojis, id=emoji))) content = PaginatorEmbedInterface( self.bot, commands.Paginator(max_size=1900, prefix="", suffix="")) count = 0 for role, emote in roles: await content.add_line(f"{count}. {role}L {str(emote)}") count += 1 await content.send_to(ctx.channel)
async def modboard(self, ctx, *, sort_by_action: str = 'warns'): """Shows the moderation leaderboard""" types = ['warns', 'mutes', 'unmutes', 'kicks', 'bans', 'unbans', 'all'] sort_by_action = sort_by_action.lower() if sort_by_action not in types: esc = '\n• ' return await ctx.send( f"No valid type to sort by. Please use one of the following:\n• {esc.join(types)}" ) else: async with ctx.channel.typing(): # aesthetics don't complain data = read('./data/core.json') guild = data.get(str(ctx.guild.id)) paginator = PaginatorEmbedInterface( self.bot, commands.Paginator(max_size=1000, prefix='', suffix='')) # paginator = commands.Paginator(max_size=2000) key = guild.get(sort_by_action) authors = {} if key: # print(key) for _case in key.keys(): # print(_case) _case = key[_case] _case['type'] = sort_by_action _case['ctx'] = ctx try: case = await Case.from_dict(_case) except (KeyError, Exception): await ctx.send( f"Error while creating case - skipping...", delete_after=10) await asyncio.sleep(2) if authors.get(case.author): authors[case.author] += 1 else: authors[case.author] = 1
async def test_paginator_interface(): bot = commands.Bot('?') with open(__file__, 'rb') as file: paginator = FilePaginator(file, max_size=200) interface = PaginatorInterface(bot, paginator) assert interface.pages == paginator.pages assert interface.page_count == len(paginator.pages) assert interface.page_size > 200 assert interface.page_size < interface.max_page_size send_kwargs = interface.send_kwargs assert isinstance(send_kwargs, dict) assert 'content' in send_kwargs content = send_kwargs['content'] assert isinstance(content, str) assert len(content) <= interface.page_size assert interface.display_page == 0 # pages have been closed, so adding a line should make a new page old_page_count = interface.page_count await interface.add_line('a' * 150) assert interface.page_count > old_page_count # push the page to the end (rounded into bounds) interface.display_page = 999 old_display_page = interface.display_page assert interface.pages == paginator.pages # page closed, so create new page await interface.add_line('b' * 150) # ensure page has followed tail assert interface.display_page > old_display_page # testing with embed interface embed_interface = PaginatorEmbedInterface(bot, paginator) assert embed_interface.pages[0] == interface.pages[0] send_kwargs = embed_interface.send_kwargs assert isinstance(send_kwargs, dict) assert 'embed' in send_kwargs embed = send_kwargs['embed'] assert isinstance(embed, discord.Embed) description = embed.description assert content.startswith(description) # check for raise on too large page size with pytest.raises(ValueError): PaginatorInterface(None, commands.Paginator(max_size=2000)) # check for raise on not-paginator with pytest.raises(TypeError): PaginatorInterface(None, 4) paginator = commands.Paginator(max_size=100) for _ in range(100): paginator.add_line("test text") # test interfacing with utils.mock_ctx(bot) as ctx: interface = PaginatorInterface(bot, paginator) assert not interface.closed await interface.send_to(ctx) await asyncio.sleep(0.1) await interface.add_line("test text") assert interface.page_count > 1 assert not interface.closed interface.message.id = utils.sentinel() current_page = interface.display_page payload = { 'message_id': interface.message.id, 'user_id': ctx.author.id, 'channel_id': ctx.channel.id, 'guild_id': ctx.guild.id } # push right button emoji = discord.PartialEmoji( animated=False, name="\N{BLACK RIGHT-POINTING TRIANGLE}", id=None ) bot.dispatch( 'raw_reaction_add', discord.RawReactionActionEvent(payload, emoji, 'REACTION_ADD') if discord.version_info >= (1, 3) else discord.RawReactionActionEvent(payload, emoji) ) await asyncio.sleep(0.1) assert interface.display_page > current_page assert not interface.closed current_page = interface.display_page # push left button emoji = discord.PartialEmoji( animated=False, name="\N{BLACK LEFT-POINTING TRIANGLE}", id=None ) bot.dispatch( 'raw_reaction_add', discord.RawReactionActionEvent(payload, emoji, 'REACTION_ADD') if discord.version_info >= (1, 3) else discord.RawReactionActionEvent(payload, emoji) ) await asyncio.sleep(0.1) assert interface.display_page < current_page assert not interface.closed # push last page button emoji = discord.PartialEmoji( animated=False, name="\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}", id=None ) bot.dispatch( 'raw_reaction_add', discord.RawReactionActionEvent(payload, emoji, 'REACTION_ADD') if discord.version_info >= (1, 3) else discord.RawReactionActionEvent(payload, emoji) ) await asyncio.sleep(0.1) assert interface.display_page == interface.page_count - 1 assert not interface.closed # push first page button emoji = discord.PartialEmoji( animated=False, name="\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}", id=None ) bot.dispatch( 'raw_reaction_add', discord.RawReactionActionEvent(payload, emoji, 'REACTION_ADD') if discord.version_info >= (1, 3) else discord.RawReactionActionEvent(payload, emoji) ) await asyncio.sleep(0.1) assert interface.display_page == 0 assert not interface.closed # push close button emoji = discord.PartialEmoji( animated=False, name="\N{BLACK SQUARE FOR STOP}", id=None ) bot.dispatch( 'raw_reaction_add', discord.RawReactionActionEvent(payload, emoji, 'REACTION_ADD') if discord.version_info >= (1, 3) else discord.RawReactionActionEvent(payload, emoji) ) await asyncio.sleep(0.1) assert interface.closed ctx.send.coro.return_value.delete.assert_called_once() # test resend, no delete with utils.mock_ctx(bot) as ctx: interface = PaginatorInterface(bot, paginator) assert not interface.closed await interface.send_to(ctx) await asyncio.sleep(0.1) await interface.add_line("test text") assert interface.page_count > 1 assert not interface.closed # resend await interface.send_to(ctx) await asyncio.sleep(0.1) await interface.add_line("test text") ctx.send.coro.return_value.delete.assert_not_called() interface.task.cancel() await asyncio.sleep(0.1) assert interface.closed # test resend, delete with utils.mock_ctx(bot) as ctx: interface = PaginatorInterface(bot, paginator, delete_message=True) assert not interface.closed await interface.send_to(ctx) await asyncio.sleep(0.1) await interface.add_line("test text") assert interface.page_count > 1 assert not interface.closed # resend await interface.send_to(ctx) await asyncio.sleep(0.1) await interface.add_line("test text") ctx.send.coro.return_value.delete.assert_called_once() interface.task.cancel() await asyncio.sleep(0.1) assert interface.closed
async def skiermod(self, ctx, *, mod: str = None): if mod is None: return await ctx.error("You need to provide a mod name") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get(f'https://api.sk1er.club/mods') as resp: if resp.status != 200: return await ctx.error('Sk1er\'s API responded incorrectly' ) mods = await resp.json() names = {} for m in mods: names[mods[m]['display'].lower()] = m for mod_id in mods[m]['mod_ids']: names[mod_id.lower()] = m if mod.lower() not in names: return await ctx.error(f'Unknown mod.') else: mod = mods[names[mod.lower()]] async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://api.sk1er.club/mods_analytics') as resp: if resp.status != 200: return await ctx.error('Sk1er\'s API responded incorrectly' ) analytics = await resp.json() analytics = analytics.get(mod['mod_ids'][0], {}) embed = discord.Embed( title=mod['display'], colour=ctx.author.color, url=f"https://sk1er.club/mods/{mod['mod_ids'][0]}", description=mod['short'], timestamp=datetime.datetime.utcnow()) embed.add_field(name="Versions", value='\n'.join([ f'**{k}**: {v}' for k, v in mod['latest'].items() ]), inline=False) embed.add_field( name="Creator", value= f"**__{mod['vendor']['name']}__**\n[Website]({mod['vendor']['website']})" f"\n[Twitter]({mod['vendor']['twitter']})" f"\n[YouTube]({mod['vendor']['youtube']})", inline=False) if analytics: embed.add_field( name="Analytics", value= f"Total: {analytics['total']:,d}, Online: {analytics['online']:,d}, Last Day: {analytics['day']:,d}, Last Week: {analytics['week']:,d}", inline=False) await ctx.send(embed=embed) paginator = WrappedPaginator(prefix='', suffix='', max_size=490) for mcv in mod['changelog']: paginator.add_line(f'**__{mcv}__**') for v in mod['changelog'][mcv]: changelog = mod["changelog"][mcv][v][0] time = datetime.datetime.utcfromtimestamp( changelog["time"] / 1000).strftime('%d/%m/%Y @ %I:%M:%S %p') paginator.add_line(f'**{v}**: {changelog["text"]} ({time})') paginator.add_line('-----------------') embed = discord.Embed(color=ctx.author.color, title='Changelogs', timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx)
def test_paginator_interface(self): bot = commands.Bot('?') with open(__file__, 'rb') as fp: paginator = FilePaginator(fp, max_size=200) interface = PaginatorInterface(bot, paginator) self.assertEqual(interface.pages, paginator.pages) self.assertEqual(interface.page_count, len(paginator.pages)) self.assertGreater(interface.page_size, 200) self.assertLess(interface.page_size, interface.max_page_size) send_kwargs = interface.send_kwargs self.assertIsInstance(send_kwargs, dict) self.assertIn('content', send_kwargs) content = send_kwargs['content'] self.assertIsInstance(content, str) self.assertLessEqual(len(content), interface.page_size) self.assertEqual(interface.display_page, 0) # pages have been closed, so adding a line should make a new page old_page_count = interface.page_count bot.loop.run_until_complete(interface.add_line('a' * 150)) self.assertGreater(interface.page_count, old_page_count) # push the page to the end (rounded into bounds) interface.display_page = 999 old_display_page = interface.display_page self.assertEqual(interface.pages, paginator.pages) # page closed, so create new page bot.loop.run_until_complete(interface.add_line('b' * 150)) # ensure page has followed tail self.assertGreater(interface.display_page, old_display_page) # testing with embed interface embed_interface = PaginatorEmbedInterface(bot, paginator) self.assertEqual(embed_interface.pages[0], interface.pages[0]) send_kwargs = embed_interface.send_kwargs self.assertIsInstance(send_kwargs, dict) self.assertIn('embed', send_kwargs) embed = send_kwargs['embed'] self.assertIsInstance(embed, discord.Embed) description = embed.description self.assertTrue(content.startswith(description)) # check for raise on too large page size raised = False try: PaginatorInterface(None, commands.Paginator(max_size=2000)) except ValueError: raised = True self.assertTrue(raised) # check for raise on not-paginator raised = False try: PaginatorInterface(None, 4) except TypeError: raised = True self.assertTrue(raised) bot.loop.run_until_complete(bot.close())
async def tictactoe(self, ctx, otherUser: typing.Optional[discord.Member] = None, player_1_symbol: str = "x", player_2_symbol: str = "o"): """Play a game of tictactoe! Leave "OtherUser" Blank to play against me!""" if ctx.author == self.bot.user: return await ctx.send("Some f****d up shit just happened and this command just ran away it was that broken." " Please tell my dev that somehow ctx.author is self.bot.") winner = None otherUser = otherUser or self.bot.user if player_1_symbol[:1] == player_2_symbol[:1]: await ctx.send("Symbols can't be the same. Randomising.") player_2_symbol = random.choice(list(string.punctuation)) if (otherUser.bot or otherUser == ctx.author) and otherUser != self.bot.user: return await ctx.send("You can't challenge them. Either they are a bot or they are you.") default = ' ' board = { "1": default, "2": default, "3": default, "4": default, "5": default, "6": default, "7": default, "8": default, "9": default } display = "```\n+---+---+---+\n| {o} | {tw} | {th} |\n| {fo} | {fi} | {si} |\n| {se} | {ei} | {ni} |" \ "\n+---+---+---+\n```".format(o=board['1'], tw=board['2'], th=board['3'], fo=board['4'], fi=board['5'], si=board['6'], se=board['7'], ei=board['8'], ni=board['9']) first = random.choice([ctx.author, otherUser]) second = [ctx.author, otherUser] second.remove(first) # gets the user not chosen to go first. second = second[0] cctx = ctx.author.mention _ctx = copy.copy(ctx) _ctx.author = otherUser if otherUser != self.bot.user: confirmed = await self.get_response(_ctx, toSend=f"{otherUser.mention}: {cctx} has challenged" f" you you to a game of tictactoe!\nDo you accept?\n*reply " f"with yes or no within 2 minutes!*", del_after=True, y_n=True, timeout=120) else: confirmed = True if not confirmed: return await ctx.send(f"Match cancelled - opponent did not accept, or didn't respond in time.") else: e = discord.Embed(title="Board:", description=display, color=discord.Color.dark_orange()) if otherUser == self.bot.user: om = False else: om = otherUser.is_on_mobile() if not any([ctx.author.is_on_mobile, om]): ind = '' e.add_field(name="how to play?", value=f"To play:\n1) Wait until it is your turn\n2) When prompted," f" say the digit of the box you want to change (e.g: if i " f"wanted to change top right, it would be `3`. " f"Bottom right would be 9, bottom left 7, etc)\n3) wait for " f"the dodgey maths to do its magic\n4) other player's turn.", inline=False) else: ind = '```\n+-+-+-+\n|1|2|3|\n|4|5|6|\n|7|8|9|\n+-+-+-+\n```\n\n' player_1_symbol = player_1_symbol[:1] player_2_symbol = player_2_symbol[:1] players = { first: player_1_symbol, second: player_2_symbol } e.add_field(name="index:", value=f"{ind}Player 1's " f"symbol: `{player_1_symbol}`\nPlayer 2's symbol: `{player_2_symbol}`\nPlayer 1: {first}\nPlayer 2: {second}", inline=False) status = await ctx.send(embed=e) turn = await ctx.send(f"{first.mention} is going first!") playing = first idle = second log = f"{first} went first." while True: await turn.edit(content=f"{playing.mention} is playing.") can = [x for x, y in board.items() if y == ' '] if len(can) == 0: self.bot.winner = None break # finished, no more spots. _ctx = ctx _ctx.author = playing log += f"\n{playing} is now playing" if playing.id != self.bot.user.id: where = await self.get_response(_ctx, toSend=f"Available spots: {', '.join(can)} ({len(can)})", del_after=True, timeout=60) else: where = str(random.choice([1, 2, 3, 4, 5, 6, 7, 8, 9])) if where is False: return await turn.edit(content=f"The game timed out. {idle.mention} wins!") else: if not where.isdigit() and where[:1] not in board.keys(): await turn.edit(content=f"{playing.mention}: that's not a valid option! try again!") await asyncio.sleep(1) continue else: where = where[:1] if board[where] != " " and board[where] == players[idle]: log += f"\n{playing.mention} tried to claim {where}, but failed." await turn.edit(content=f"{playing.mention}: That position is already claimed! Try again") await asyncio.sleep(1) continue elif board[where] != " ": # you're welcome Minion await turn.edit(content="You already claimed that one!") continue else: board[where] = players[playing] log += f"\n{playing} claimed {where}." display = "```\n+---+---+---+\n| {o} | {tw} | {th} |\n| {fo} | {fi} | {si} |\n| {se} | {ei} | {ni} |" \ "\n+---+---+---+\n```".format(o=board['1'], tw=board['2'], th=board['3'], fo=board['4'], fi=board['5'], si=board['6'], se=board['7'], ei=board['8'], ni=board['9']) e.description = display await status.edit(embed=e) await asyncio.sleep(1) _p = playing if self.haswon(board, players[_p]): self.bot.winner = _p break elif self.haswon(board, players[idle]): self.bot.winner = idle break playing = idle idle = _p paginator = PaginatorEmbedInterface(self.bot, commands.Paginator(prefix='', suffix='')) await paginator.add_line( f"Overview:\n{f'**{self.bot.winner.mention} Won!**' if self.bot.winner else '**Draw!**'}\n\nLog:\n") for line in log.splitlines(keepends=False): await paginator.add_line(line) await paginator.add_line(f"**{self.bot.winner.mention} wins!**" if self.bot.winner else '**Draw!**') await paginator.send_to(ctx.channel) await turn.delete() e = discord.Embed( title="Game Over. Overview:", description="```\n+---+---+---+\n| {o} | {tw} | {th} |\n| {fo} | {fi} | {si} |\n| {se} | {ei} | {ni} |" "\n+---+---+---+\n```".format(o=board['1'], tw=board['2'], th=board['3'], fo=board['4'], fi=board['5'], si=board['6'], se=board['7'], ei=board['8'], ni=board['9']), ) await status.edit(embed=e)
async def hypixel(self, ctx, arg1: str = None, arg2: str = None): if arg1 is None: msg = await ctx.send("I need an IGN, `key` or `watchdog`", delete_after=5) return arg1 = arg1.lower() if arg2: arg2 = arg2.lower() if arg1.lower() == "watchdog": async with aiohttp.ClientSession() as session: async with session.get( f'https://api.hypixel.net/watchdogstats?key={hypixelkey}' ) as resp: watchdog = await resp.json() color = ctx.author.color embed = discord.Embed(title="Watchdog Stats", colour=color, timestamp=datetime.datetime.utcnow()) embed.set_thumbnail( url="https://hypixel.net/attachments/cerbtrimmed-png.245674/") embed.set_footer( text= "Want more integrations? Use the suggest command to suggest some" ) embed.add_field(name="Watchdog Bans in the last minute", value=watchdog['watchdog_lastMinute'], inline=False) embed.add_field(name="Staff bans in the last day", value=format(watchdog['staff_rollingDaily'], ',d'), inline=False) embed.add_field(name="Watchdog bans in the last day", value=format(watchdog['watchdog_rollingDaily'], ',d'), inline=False) embed.add_field(name="Staff Total Bans", value=format(watchdog['staff_total'], ',d'), inline=False) embed.add_field(name="Watchdog Total Bans", value=format(watchdog['watchdog_total'], ',d'), inline=False) await ctx.send(embed=embed) return if arg1.lower() == "key": lastmin = "0" async with aiohttp.ClientSession() as session: async with session.get( f'https://api.hypixel.net/key?key={hypixelkey}' ) as resp: key = await resp.json() lastmin = key.get('record', {}).get('queriesInPastMin', 0) color = ctx.author.color embed = discord.Embed(title="My API Key Stats", colour=color, timestamp=datetime.datetime.utcnow()) embed.set_footer( text= "Want more integrations? Use the suggest command to suggest some" ) embed.add_field( name="Owner", value="GamingGeeek (4686e7b58815485d8bc4a45445abb984)", inline=False) embed.add_field(name="Total Requests", value=format(key['record']['totalQueries'], ',d'), inline=False) embed.add_field(name="Requests in the past minute", value=lastmin, inline=False) await ctx.send(embed=embed) return if arg1.lower() == 'leaderboard': if arg2 is None: return #Make available leaderboards embed elif arg2.lower() == 'level': msg = await ctx.send(f"Generating Network Level leaderboard..." ) headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/LEVEL' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Level', 'Karma', 'Kills', 'Wins' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] level = player['Level'] paginator.add_line(f'[{pos}] {name} - {level}') except Exception as e: pass embed = discord.Embed(title='Network Level Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'karma': msg = await ctx.send(f"Generating Karma leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/KARMA' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Karma', 'Level', 'Kills', 'Wins' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] karma = player['Karma'] paginator.add_line(f'[{pos}] {name} - {karma}') except Exception as e: pass embed = discord.Embed(title='Karma Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'coins': msg = await ctx.send(f"Generating Coins leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/COINS' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Coins', 'Karma', 'Kills', 'Wins' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] coins = player['Coins'] paginator.add_line(f'[{pos}] {name} - {coins}') except Exception as e: pass embed = discord.Embed(title='Coins Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'kills': msg = await ctx.send(f"Generating Total Kills leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/TOTAL_KILLS' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Kills', 'Level', 'Wins', 'Quests' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] kills = player['Kills'] paginator.add_line(f'[{pos}] {name} - {kills}') except Exception as e: pass embed = discord.Embed(title='Total Kills Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'wins': msg = await ctx.send(f"Generating Total Wins leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/TOTAL_WINS' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Wins', 'Level', 'Kills', 'Quests' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] wins = player['Wins'] paginator.add_line(f'[{pos}] {name} - {wins}') except Exception as e: pass embed = discord.Embed(title='Total Wins Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'glevel': msg = await ctx.send(f"Generating Guild Level leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/GUILD_LEVEL' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Level', 'Wins', 'Exp', 'Legacy', 'Created' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] level = player['Level'] paginator.add_line(f'[{pos}] {name} - {level}') except Exception as e: pass embed = discord.Embed(title='Guild Level Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'gexperience': msg = await ctx.send( f"Generating Guild Experience leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/GUILD_LEVEL' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Level', 'Wins', 'Exp', 'Legacy', 'Created' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] exp = player['Exp'] paginator.add_line(f'[{pos}] {name} - {exp}') except Exception as e: pass embed = discord.Embed(title='Guild Experience Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) elif arg2.lower() == 'gwins': msg = await ctx.send(f"Generating Guild Wins leaderboard...") headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://sk1er.club/leaderboards/newdata/GUILD_WINS' ) as resp: content = await resp.read() lbjson = table2json(content, [ 'Position', 'Change', 'Name', 'Wins', 'Level', 'Exp', 'Legacy', 'Created' ]) paginator = WrappedPaginator( prefix='```vbs\n-------------------------------------', suffix='-------------------------------------\n```', max_size=420) for player in lbjson: try: pos = player['Position'] name = player['Name'] wins = player['Wins'] paginator.add_line(f'[{pos}] {name} - {wins}') except Exception as e: pass embed = discord.Embed(title='Guild Wins Leaderboard', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await msg.delete() return await interface.send_to(ctx) else: return await ctx.send('Unknown leaderboard.') elif arg1 == 'skyblock': if not arg2 or arg2 == 'news': async with aiohttp.ClientSession() as session: async with session.get( f'https://api.hypixel.net/skyblock/news?key={hypixelkey}' ) as resp: sbnews = await resp.json() paginator = WrappedPaginator(prefix='', suffix='', max_size=250) for entry in sbnews['items']: paginator.add_line( f'[{entry["title"]}]({entry["link"]})\n{entry["text"]}\n' ) embed = discord.Embed(color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) return await interface.send_to(ctx) if arg2 is None: cleaned = discord.utils.escape_mentions( discord.utils.escape_markdown(arg1)) msg = await ctx.send( f"Requesting info about {cleaned} from the Hypixel API!") channel = ctx.message.channel color = ctx.author.color async with channel.typing(): try: player = hypixel.Player(arg1) except hypixel.PlayerNotFoundException: raise commands.ArgumentParsingError( 'Couldn\'t find that player...') except AttributeError: raise commands.ArgumentParsingError( 'Couldn\'t find that player...') p = player.JSON headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } tributes = p.get('tourney', {}).get('total_tributes', 0) # TOURNAMENT TRIBUTES level = str(player.getLevel()).split('.')[0] lastlogin = p.get('lastLogin', 0) lastlogout = p.get('lastLogout', 1) if lastlogin > lastlogout: status = "Online!" else: status = "Offline!" tag = None async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://api.sk1er.club/guild/player/{player.UUID}' ) as resp: guild = await resp.json() if guild['success']: guild = guild['guild'] tag = guild['tag'] if 'tag' in guild else None if tag: tagcolor = guild[ 'tagColor'] if 'tagColor' in guild else 'GRAY' if tagcolor == 'GRAY' or tagcolor == 'GREY': tag = f'§7[{tag}]' elif tagcolor == 'GOLD': tag = f'§6[{tag}]' elif tagcolor == 'DARK_GREEN': tag = f'§2[{tag}]' elif tagcolor == 'YELLOW': tag = f'§e[{tag}]' elif tagcolor == 'DARK_AQUA': tag = f'§3[{tag}]' if not tag: tag = f'§7[{tag}]' async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://api.sk1er.club/player/{arg1}') as resp: apiplayer = await resp.json() if apiplayer['success']: try: nametag = apiplayer['player']['playerdisplay'].replace( '§0YOUTUBE', '§fYOUTUBE' ) if 'playerdisplay' in apiplayer else apiplayer[ 'player']['display'].replace( '§0YOUTUBE', '§fYOUTUBE') except Exception: displayname = p['displayname'] nametag = f'§f{displayname}' if tag: nametag = f'{nametag} {tag}' if nametag: parsedtxt = mcfont.parse(nametag) width = mcfont.get_width(parsedtxt) img = Image.new('RGBA', (width + 25, 42)) mcfont.render((5, 0), parsedtxt, img) buf = BytesIO() img.save(buf, format='PNG') buf.seek(0) customtag = discord.File(buf, 'imaginereadingthefilename.png') if arg2 is None: msg = await ctx.send( f"Retrieving {discord.utils.escape_mentions(discord.utils.escape_markdown(p['displayname']))}'s info..." ) uuid = player.UUID embed = discord.Embed( title= f"{discord.utils.escape_markdown(p['displayname'])}'s Info", colour=color, timestamp=datetime.datetime.utcnow()) if nametag: embed.set_image( url=f'attachment://imaginereadingthefilename.png') embed.set_thumbnail( url=f"https://crafatar.com/avatars/{uuid}?overlay=true" ) embed.set_footer( text= "Want more integrations? Use the suggest command to suggest some" ) embed.add_field(name="Online Status", value=status, inline=True) language = p.get('userLanguage', 'Not Set') embed.add_field(name="Language", value=language, inline=True) channel = p.get('channel', 'ALL') embed.add_field(name="Chat Channel", value=channel, inline=True) embed.add_field(name="Level", value=level, inline=True) embed.add_field(name="Karma", value=format(p.get('karma', 0), ',d'), inline=True) if 'twitter' not in self.bot.configs[ctx.guild.id].get( 'mod.linkfilter'): twitter = p.get('socialMedia', {}).get('TWITTER', 'Not Set') else: twitter = 'Hidden' if 'youtube' not in self.bot.configs[ctx.guild.id].get( 'mod.linkfilter'): yt = p.get('socialMedia', {}).get('links', {}).get('YOUTUBE', 'Not Set') else: yt = 'Hidden' insta = p.get('socialMedia', {}).get('INSTAGRAM', 'Not Set') if 'twitch' not in self.bot.configs[ctx.guild.id].get( 'mod.linkfilter'): twitch = p.get('socialMedia', {}).get('TWITCH', 'Not Set') else: twitch = 'Hidden' beam = p.get('socialMedia', {}).get('BEAM', 'Not Set') if 'discord' not in self.bot.configs[ctx.guild.id].get( 'mod.linkfilter'): dscrd = p.get('socialMedia', {}).get('links', {}).get('DISCORD', 'Not Set') else: dscrd = 'Hidden' embed.add_field( name="Social Media", value= f"Twitter: {twitter}\nYouTube: {yt}\nInstagram: {insta}\nTwitch: {twitch}\nBeam: {beam}\nDiscord: {dscrd}", inline=False) if tributes != 0: embed.add_field(name="Tournament Tributes", value=tributes, inline=False) if customtag: await msg.delete() await ctx.send(embed=embed, file=customtag) else: await msg.edit(content=None, embed=embed) elif arg2 == 'friends': headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://api.sk1er.club/friends/{arg1}') as resp: friends = await resp.json() paginator = WrappedPaginator( prefix= f'-----------------------------------------------------\n Friends ({len(friends)}) >>', suffix='-----------------------------------------------------', max_size=512) for uuid in friends: friend = friends[uuid] try: name = re.sub(remcolor, '', friend['display'], 0, re.IGNORECASE) time = str( datetime.datetime.utcfromtimestamp(friend['time'] / 1000)).split('.')[0] except TypeError: raise commands.ArgumentParsingError( 'Couldn\'t find that persons friends. Check the name and try again' ) return paginator.add_line( discord.utils.escape_markdown(f'{name} added on {time}')) embed = discord.Embed(color=ctx.author.color, timestamp=datetime.datetime.utcnow()) interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=embed) await interface.send_to(ctx) elif arg2 == 'guild': uuid = await self.nameToUUID(arg1) headers = { 'USER-AGENT': 'Fire (Python 3.7.2 / aiohttp 3.3.2) | Fire Discord Bot', 'CONTENT-TYPE': 'application/json' } async with aiohttp.ClientSession(headers=headers) as session: async with session.get( f'https://api.sk1er.club/guild/player/{uuid}') as resp: guild = await resp.json() if guild['success'] != True: raise commands.ArgumentParsingError( 'Couldn\'t find a guild. Maybe they aren\'t in one...') guild = guild['guild'] embed = discord.Embed(colour=ctx.author.color, timestamp=datetime.datetime.utcnow()) embed.set_footer( text= "Want more integrations? Use the suggest command to suggest some" ) gtagcolor = guild.get('tagColor', 'GRAY').lower().replace('_', ' ').capitalize() gtag = guild.get('tag', '') if gtag: gtag = f'[{gtag}] ({gtagcolor})' desc = guild.get('description', 'No Description Set.') embed.add_field( name=f"{arg1}'s guild", value= f"{guild['name']} {gtag}\n{desc}\n\nLevel: {guild['level_calc']}" ) embed.add_field(name="Joinable?", value=guild.get('joinable', 'False'), inline=False) embed.add_field(name="Publicly Listed?", value=guild.get('publiclyListed', 'False'), inline=False) embed.add_field(name="Legacy Rank", value=format(guild.get('legacyRanking', -1), ',d'), inline=False) games = [] for game in guild.get('preferredGames', ['this is a placeholder']): games.append(picklegames.get(game, 'Preferred Games not set.')) embed.add_field(name="Preferred Games", value=', '.join(games) if games else 'Preferred Games not set.', inline=False) ranks = [] for rank in guild.get('ranks', { 'name': 'No custom ranks', 'tag': '' }): name = rank['name'] if not rank.get('tag', ''): tag = '' else: tag = rank['tag'] tag = f'[{tag}]' ranks.append(f'{name} {tag}') embed.add_field( name="Ranks", value='\n'.join(ranks) if ranks else 'No custom ranks', inline=False) await ctx.send(embed=embed) gname = guild['name'] paginatorembed = discord.Embed( title=f'{gname}\'s Members ({len(guild["members"])})', color=ctx.author.color, timestamp=datetime.datetime.utcnow()) ranktags = {} for rank in ranks: ranktags[rank.split(' ')[0]] = rank.split(' ')[1] paginator = WrappedPaginator(prefix='', suffix='', max_size=380) for member in guild['members']: name = re.sub( remcolor, '', member.get('displayname', member.get('name', 'Unknown Player')), 0, re.IGNORECASE) joined = str( datetime.datetime.utcfromtimestamp(member['joined'] / 1000)).split('.')[0] try: ranktag = ranktags[member['rank']] except KeyError: ranktag = '' if ranktag != '': paginator.add_line(f'{name} {ranktag} joined on {joined}') else: paginator.add_line(f'{name} joined on {joined}') interface = PaginatorEmbedInterface(ctx.bot, paginator, owner=ctx.author, _embed=paginatorembed) await interface.send_to(ctx)