diff --git a/cogs/admin.py b/cogs/admin.py index 6ac1802..7ac10ab 100644 --- a/cogs/admin.py +++ b/cogs/admin.py @@ -21,7 +21,7 @@ class Administration: """Turns on/off the birthday announcements in this server EXAMPLE: !allowbirthdays on - RESULT: Playlists can now be used""" + RESULT: Birthdays will now be announced""" if setting.lower() in ['on', 'yes', 'true']: allowed = True else: diff --git a/cogs/birthday.py b/cogs/birthday.py index ca71d2d..b69ad1a 100644 --- a/cogs/birthday.py +++ b/cogs/birthday.py @@ -1,12 +1,13 @@ import discord import pendulum +import asyncio from pendulum.parsing.exceptions import ParserError from discord.ext import commands from . import utils -class Birthday: +class Birthday: def __init__(self, bot): self.bot = bot self.bot.loop.create_task(self.birthday_task()) @@ -47,20 +48,21 @@ class Birthday: tfilter = {'birthdays_allowed': True} servers = await self.bot.db.actual_load('server_settings', table_filter=tfilter) for s in servers: - server = bot.get_guild(int(s['server_id'])) + server = self.bot.get_guild(int(s['server_id'])) if not server: continue bds = self.get_birthdays_for_server(server, today=True) for bd in bds: # Set our default to either the one set, or the default channel of the server - default_channel_id = servers.get('notifications', {}).get('default') or guild.id + default_channel_id = s.get('notifications', {}).get('default') or server.id # If it is has been overriden by picarto notifications setting, use this - channel_id = servers.get('notifications', {}).get('birthdays') or default_channel_id + channel_id = s.get('notifications', {}).get('birthday') or default_channel_id # Now get the channel based on that ID channel = server.get_channel(int(channel_id)) or server.default_channel try: - await channel.send("It is {}'s birthday today! Wish them a happy birthday! \N{SHORTCAKE}".format(member.mention)) + await channel.send("It is {}'s birthday today! " + "Wish them a happy birthday! \N{SHORTCAKE}".format(bd['member'].mention)) except (discord.Forbidden, discord.HTTPException): pass @@ -92,7 +94,6 @@ class Birthday: except utils.CannotPaginate as e: await ctx.send(str(e)) - @birthday.command(name='add') @utils.custom_perms(send_messages=True) @utils.check_restricted() @@ -150,5 +151,6 @@ class Birthday: self.bot.db.save('server_settings', entry) await ctx.send("All birthday notifications will now go to {}".format(channel.mention)) + def setup(bot): bot.add_cog(Birthday(bot)) diff --git a/cogs/misc.py b/cogs/misc.py index 7781112..82e9017 100644 --- a/cogs/misc.py +++ b/cogs/misc.py @@ -186,7 +186,7 @@ class Miscallaneous: embed.set_author(name=str(self.bot.owner), icon_url=self.bot.owner.avatar_url) # Setup the process statistics - name = "Process stats" + name = "Process statistics" value = "" memory_usage = self.process.memory_full_info().uss / 1024 ** 2 @@ -198,7 +198,7 @@ class Miscallaneous: embed.add_field(name=name, value=value, inline=False) # Setup the user and guild statistics - name = "User/Guild stats" + name = "User/Guild statistics" value = "" value += "Channels: {}".format(len(list(self.bot.get_all_channels()))) diff --git a/cogs/overwatch.py b/cogs/overwatch.py index 8e3fc69..da6142e 100644 --- a/cogs/overwatch.py +++ b/cogs/overwatch.py @@ -89,7 +89,7 @@ class Overwatch: fmt = "\n".join("{}: {}".format(k, r) for k, r in output_data) await ctx.send("Overwatch stats for {}: ```py\n{}```".format(user.name, fmt)) - @ow.command(pass_context=True, name="add") + @ow.command(name="add") @utils.custom_perms(send_messages=True) @utils.check_restricted() async def add(self, ctx, bt: str): @@ -122,7 +122,7 @@ class Overwatch: self.bot.db.save('overwatch', entry) await ctx.send("I have just saved your battletag {}".format(ctx.message.author.mention)) - @ow.command(pass_context=True, name="delete", aliases=['remove']) + @ow.command(name="delete", aliases=['remove']) @utils.custom_perms(send_messages=True) @utils.check_restricted() async def delete(self, ctx): diff --git a/cogs/polls.py b/cogs/polls.py index 4f27e17..3e55c35 100644 --- a/cogs/polls.py +++ b/cogs/polls.py @@ -70,7 +70,7 @@ class Polls: if poll: await poll.remove_other_reaction(reaction, user) - @commands.command(pass_context=True) + @commands.command() @commands.guild_only() @utils.custom_perms(send_messages=True) @utils.check_restricted() diff --git a/cogs/raffle.py b/cogs/raffle.py index 48f7826..5eb0f75 100644 --- a/cogs/raffle.py +++ b/cogs/raffle.py @@ -183,7 +183,7 @@ class Raffle: raffle_count, ctx.prefix) await ctx.send(fmt) - @raffle.command(pass_context=True, name='create', aliases=['start', 'begin', 'add']) + @raffle.command(name='create', aliases=['start', 'begin', 'add']) @commands.guild_only() @utils.custom_perms(kick_members=True) @utils.check_restricted() diff --git a/cogs/stats.py b/cogs/stats.py index d376710..bee0dfa 100644 --- a/cogs/stats.py +++ b/cogs/stats.py @@ -1,344 +1,344 @@ -import discord -from discord.ext import commands - -from . import utils - -import re -import asyncio - - -class Stats: - """Leaderboard/stats related commands""" - - def __init__(self, bot): - self.bot = bot - self.donators = [] - self.bot.loop.create_task(self.donator_task()) - - async def donator_task(self): - while True: - await self.get_donators() - await asyncio.sleep(60) - - async def get_donators(self): - # Set our base URL for the pagination task - url = "https://api.patreon.com/oauth2/api/campaigns/{}/pledges".format(utils.patreon_id) - # Set our headers with our bearer token - headers = {'Authorization': 'Bearer {}'.format(utils.patreon_key)} - # We need the names of all of them, and the names are embeded a bit so lets append while looping - names = [] - # We need to page through, so lets create a loop and break when we find out we're done - while True: - # Simply get data based on the URL - data = await utils.request(url, headers=headers, force_content_type_json=True) - # First check if the data failed to retrieve, if so just return - if data is None: - return - - # Loop through the includes, as that's all we need - for include in data['included']: - # We only carry about the user's - if include['type'] != 'user': - continue - # This check checks the user's connected campaign (should only exist for *our* user) and checks if it - # matches - if include.get('relationshipos', {}).get('campaign', {}).get('data', {}).get('id', {}) == str( - utils.patreon_id): - continue - - # Otherwise the only way this user was included, was if they are a patron, so include them - name = include['attributes']['full_name'] - if name: - names.append(name) - - # Now, lets get our "next" link and request that - url = data['links'].get('next') - # If there is no None, that means there should only be a "first" and our pagination is done - if url is None: - break - - # Now just set the names - self.donators = names - - @commands.command() - @commands.guild_only() - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def serverinfo(self, ctx): - """Provides information about the server - - EXAMPLE: !serverinfo - RESULT: Information about your server!""" - server = ctx.message.guild - # Create our embed that we'll use for the information - embed = discord.Embed(title=server.name, description="Created on: {}".format(server.created_at.date())) - - # Make sure we only set the icon url if it has been set - if server.icon_url != "": - embed.set_thumbnail(url=server.icon_url) - - # Add our fields, these are self-explanatory - embed.add_field(name='Region', value=str(server.region)) - embed.add_field(name='Total Emojis', value=len(server.emojis)) - - # Get the amount of online members - online_members = [m for m in server.members if str(m.status) == 'online'] - embed.add_field(name='Total members', value='{}/{}'.format(len(online_members), server.member_count)) - embed.add_field(name='Roles', value=len(server.roles)) - - # Split channels into voice and text channels - voice_channels = [c for c in server.channels if type(c) is discord.VoiceChannel] - text_channels = [c for c in server.channels if type(c) is discord.TextChannel] - embed.add_field(name='Channels', value='{} text, {} voice'.format(len(text_channels), len(voice_channels))) - embed.add_field(name='Owner', value=server.owner.display_name) - - await ctx.send(embed=embed) - - @commands.group(pass_context=False) - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def command(self): - pass - - @command.command(name="stats") - @commands.guild_only() - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def command_stats(self, ctx, *, command): - """This command can be used to view some usage stats about a specific command - - EXAMPLE: !command stats play - RESULT: The realization that this is the only reason people use me ;-;""" - await ctx.message.channel.trigger_typing() - - cmd = self.bot.get_command(command) - if cmd is None: - await ctx.send("`{}` is not a valid command".format(command)) - return - - command_stats = self.bot.db.load('command_usage', key=cmd.qualified_name) - if command_stats is None: - await ctx.send("That command has never been used! You know I worked hard on that! :c") - return - - total_usage = command_stats['total_usage'] - member_usage = command_stats['member_usage'].get(str(ctx.message.author.id), 0) - server_usage = command_stats['server_usage'].get(str(ctx.message.guild.id), 0) - - try: - data = [("Command Name", cmd.qualified_name), - ("Total Usage", total_usage), - ("Your Usage", member_usage), - ("This Server's Usage", server_usage)] - banner = await utils.create_banner(ctx.message.author, "Command Stats", data) - await ctx.send(file=discord.File(banner, filename='banner.png')) - except (FileNotFoundError, discord.Forbidden): - fmt = "The command {} has been used a total of {} times\n" \ - "{} times on this server\n" \ - "It has been ran by you, {}, {} times".format(cmd.qualified_name, total_usage, server_usage, - ctx.message.author.display_name, member_usage) - - await ctx.send(fmt) - - @command.command(name="leaderboard") - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def command_leaderboard(self, ctx, option="server"): - """This command can be used to print a leaderboard of commands - Provide 'server' to print a leaderboard for this server - Provide 'me' to print a leaderboard for your own usage - - EXAMPLE: !command leaderboard me - RESULT: The realization of how little of a life you have""" - await ctx.message.channel.trigger_typing() - - if re.search('(author|me)', option): - author = ctx.message.author - # First lets get all the command usage - command_stats = self.bot.db.load('command_usage') - # Now use a dictionary comprehension to get just the command name, and usage - # Based on the author's usage of the command - stats = {data['command']: data['member_usage'].get(str(author.id)) for data in command_stats - if data['member_usage'].get(str(author.id), 0) > 0} - # Now sort it by the amount of times used - sorted_stats = sorted(stats.items(), key=lambda x: x[1], reverse=True) - - # Create a string, each command on it's own line, based on the top 5 used commands - # I'm letting it use the length of the sorted_stats[:5] - # As this can include, for example, all 3 if there are only 3 entries - try: - top_5 = [(data[0], data[1]) for data in sorted_stats[:5]] - banner = await utils.create_banner(ctx.message.author, "Your command usage", top_5) - await ctx.send(file=discord.File(banner, filename='banner.png')) - except (FileNotFoundError, discord.Forbidden): - top_5 = "\n".join("{}: {}".format(data[0], data[1]) for data in sorted_stats[:5]) - await ctx.send( - "Your top {} most used commands are:\n```\n{}```".format(len(sorted_stats[:5]), top_5)) - elif re.search('server', option): - # This is exactly the same as above, except server usage instead of member usage - server = ctx.message.guild - command_stats = self.bot.db.load('command_usage') - stats = {data['command']: data['server_usage'].get(str(server.id)) for data in command_stats - if data['server_usage'].get(str(server.id), 0) > 0} - sorted_stats = sorted(stats.items(), key=lambda x: x[1], reverse=True) - try: - top_5 = [(data[0], data[1]) for data in sorted_stats[:5]] - banner = await utils.create_banner(ctx.message.author, "Server command usage", top_5) - await ctx.send(file=discord.File(banner, filename='banner.png')) - except (FileNotFoundError, discord.Forbidden): - top_5 = "\n".join("{}: {}".format(data[0], data[1]) for data in sorted_stats[:5]) - await ctx.send( - "This server's top {} most used commands are:\n```\n{}```".format(len(sorted_stats[:5]), top_5)) - else: - await ctx.send("That is not a valid option, valid options are: `server` or `me`") - - @commands.command() - @commands.guild_only() - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def mostboops(self, ctx): - """Shows the person you have 'booped' the most, as well as how many times - - EXAMPLE: !mostboops - RESULT: You've booped @OtherPerson 351253897120935712093572193057310298 times!""" - boops = self.bot.db.load('boops', key=ctx.message.author.id) - if boops is None: - await ctx.send("You have not booped anyone {} Why the heck not...?".format(ctx.message.author.mention)) - return - - # Just to make this easier, just pay attention to the boops data, now that we have the right entry - boops = boops['boops'] - - # First get a list of the ID's of all members in this server, for use in list comprehension - server_member_ids = [str(member.id) for member in ctx.message.guild.members] - # Then get a sorted list, based on the amount of times they've booped the member - # Reverse needs to be true, as we want it to go from highest to lowest - sorted_boops = sorted(boops.items(), key=lambda x: x[1], reverse=True) - # Then override the same list, checking if the member they've booped is in this server - sorted_boops = [x for x in sorted_boops if x[0] in server_member_ids] - - # Since this is sorted, we just need to get the following information on the first user in the list - most_id, most_boops = sorted_boops[0] - - member = ctx.message.guild.get_member(int(most_id)) - - await ctx.send("{0} you have booped {1} the most amount of times, coming in at {2} times".format( - ctx.message.author.mention, member.display_name, most_boops)) - - @commands.command() - @commands.guild_only() - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def listboops(self, ctx): - """Lists all the users you have booped and the amount of times - - EXAMPLE: !listboops - RESULT: The list of your booped members!""" - await ctx.message.channel.trigger_typing() - - boops = self.bot.db.load('boops', key=ctx.message.author.id) - if boops is None: - await ctx.send("You have not booped anyone {} Why the heck not...?".format(ctx.message.author.mention)) - return - - # Just to make this easier, just pay attention to the boops data, now that we have the right entry - boops = boops['boops'] - - # Same concept as the mostboops method - server_member_ids = [member.id for member in ctx.message.guild.members] - booped_members = {int(m_id): amt for m_id, amt in boops.items() if int(m_id) in server_member_ids} - sorted_booped_members = sorted(booped_members.items(), key=lambda k: k[1], reverse=True) - # Now we only want the first 10 members, so splice this list - sorted_booped_members = sorted_booped_members[:10] - - try: - output = [("{0.display_name}".format(ctx.message.guild.get_member(m_id)), amt) - for m_id, amt in sorted_booped_members] - banner = await utils.create_banner(ctx.message.author, "Your booped victims", output) - await ctx.send(file=discord.File(banner, filename='banner.png')) - except (FileNotFoundError, discord.Forbidden): - output = "\n".join( - "{0.display_name}: {1} times".format(ctx.message.guild.get_member(m_id), amt) for - m_id, amt in sorted_booped_members) - await ctx.send("You have booped:```\n{}```".format(output)) - - @commands.command() - @commands.guild_only() - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def leaderboard(self, ctx): - """Prints a leaderboard of everyone in the server's battling record - - EXAMPLE: !leaderboard - RESULT: A leaderboard of this server's battle records""" - await ctx.message.channel.trigger_typing() - - # Create a list of the ID's of all members in this server, for comparison to the records saved - server_member_ids = [member.id for member in ctx.message.guild.members] - battles = self.bot.db.load('battle_records') - if battles is None or len(battles) == 0: - await ctx.send("No one has battled on this server!") - - battles = [battle for battle in battles if int(battle['member_id']) in server_member_ids] - - # Sort the members based on their rating - sorted_members = sorted(battles, key=lambda k: k['rating'], reverse=True) - - output = [] - for x in sorted_members: - member_id = int(x['member_id']) - rating = x['rating'] - member = ctx.message.guild.get_member(member_id) - output.append("{} (Rating: {})".format(member.display_name, rating)) - - try: - pages = utils.Pages(self.bot, message=ctx.message, entries=output) - await pages.paginate() - except utils.CannotPaginate as e: - await ctx.send(str(e)) - - @commands.command() - @commands.guild_only() - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def battlestats(self, ctx, member: discord.Member = None): - """Prints the battling stats for you, or the user provided - - EXAMPLE: !stats @OtherPerson - RESULT: How good they are at winning a completely luck based game""" - await ctx.message.channel.trigger_typing() - - member = member or ctx.message.author - # Get the different data that we'll display - server_rank = "{}/{}".format(*self.bot.br.get_server_rank(member)) - overall_rank = "{}/{}".format(*self.bot.br.get_rank(member)) - rating = self.bot.br.get_rating(member) - record = self.bot.br.get_record(member) - try: - # Create our banner - title = 'Stats for {}'.format(member.display_name) - fmt = [('Record', record), ('Server Rank', server_rank), ('Overall Rank', overall_rank), ('Rating', rating)] - banner = await utils.create_banner(member, title, fmt) - await ctx.send(file=discord.File(banner, filename='banner.png')) - except (FileNotFoundError, discord.Forbidden): - fmt = 'Stats for {}:\n\tRecord: {}\n\tServer Rank: {}\n\tOverall Rank: {}\n\tRating: {}' - fmt = fmt.format(member.display_name, record, server_rank, overall_rank, rating) - await ctx.send('```\n{}```'.format(fmt)) - - @commands.command(aliases=['donators']) - @utils.custom_perms(send_messages=True) - @utils.check_restricted() - async def patrons(self, ctx): - """Prints a list of all the patrons for Bonfire - - EXAMPLE: !donators - RESULT: A list of the donators""" - try: - pages = utils.Pages(self.bot, message=ctx.message, entries=self.donators) - await pages.paginate() - except utils.CannotPaginate as e: - await ctx.send(str(e)) - - -def setup(bot): - bot.add_cog(Stats(bot)) +import discord +from discord.ext import commands + +from . import utils + +import re +import asyncio + + +class Stats: + """Leaderboard/stats related commands""" + + def __init__(self, bot): + self.bot = bot + self.donators = [] + self.bot.loop.create_task(self.donator_task()) + + async def donator_task(self): + while True: + await self.get_donators() + await asyncio.sleep(60) + + async def get_donators(self): + # Set our base URL for the pagination task + url = "https://api.patreon.com/oauth2/api/campaigns/{}/pledges".format(utils.patreon_id) + # Set our headers with our bearer token + headers = {'Authorization': 'Bearer {}'.format(utils.patreon_key)} + # We need the names of all of them, and the names are embeded a bit so lets append while looping + names = [] + # We need to page through, so lets create a loop and break when we find out we're done + while True: + # Simply get data based on the URL + data = await utils.request(url, headers=headers, force_content_type_json=True) + # First check if the data failed to retrieve, if so just return + if data is None: + return + + # Loop through the includes, as that's all we need + for include in data['included']: + # We only carry about the user's + if include['type'] != 'user': + continue + # This check checks the user's connected campaign (should only exist for *our* user) and checks if it + # matches + if include.get('relationshipos', {}).get('campaign', {}).get('data', {}).get('id', {}) == str( + utils.patreon_id): + continue + + # Otherwise the only way this user was included, was if they are a patron, so include them + name = include['attributes']['full_name'] + if name: + names.append(name) + + # Now, lets get our "next" link and request that + url = data['links'].get('next') + # If there is no None, that means there should only be a "first" and our pagination is done + if url is None: + break + + # Now just set the names + self.donators = names + + @commands.command() + @commands.guild_only() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def serverinfo(self, ctx): + """Provides information about the server + + EXAMPLE: !serverinfo + RESULT: Information about your server!""" + server = ctx.message.guild + # Create our embed that we'll use for the information + embed = discord.Embed(title=server.name, description="Created on: {}".format(server.created_at.date())) + + # Make sure we only set the icon url if it has been set + if server.icon_url != "": + embed.set_thumbnail(url=server.icon_url) + + # Add our fields, these are self-explanatory + embed.add_field(name='Region', value=str(server.region)) + embed.add_field(name='Total Emojis', value=len(server.emojis)) + + # Get the amount of online members + online_members = [m for m in server.members if str(m.status) == 'online'] + embed.add_field(name='Total members', value='{}/{}'.format(len(online_members), server.member_count)) + embed.add_field(name='Roles', value=len(server.roles)) + + # Split channels into voice and text channels + voice_channels = [c for c in server.channels if type(c) is discord.VoiceChannel] + text_channels = [c for c in server.channels if type(c) is discord.TextChannel] + embed.add_field(name='Channels', value='{} text, {} voice'.format(len(text_channels), len(voice_channels))) + embed.add_field(name='Owner', value=server.owner.display_name) + + await ctx.send(embed=embed) + + @commands.group() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def command(self, ctx): + pass + + @command.command(name="stats") + @commands.guild_only() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def command_stats(self, ctx, *, command): + """This command can be used to view some usage stats about a specific command + + EXAMPLE: !command stats play + RESULT: The realization that this is the only reason people use me ;-;""" + await ctx.message.channel.trigger_typing() + + cmd = self.bot.get_command(command) + if cmd is None: + await ctx.send("`{}` is not a valid command".format(command)) + return + + command_stats = self.bot.db.load('command_usage', key=cmd.qualified_name) + if command_stats is None: + await ctx.send("That command has never been used! You know I worked hard on that! :c") + return + + total_usage = command_stats['total_usage'] + member_usage = command_stats['member_usage'].get(str(ctx.message.author.id), 0) + server_usage = command_stats['server_usage'].get(str(ctx.message.guild.id), 0) + + try: + data = [("Command Name", cmd.qualified_name), + ("Total Usage", total_usage), + ("Your Usage", member_usage), + ("This Server's Usage", server_usage)] + banner = await utils.create_banner(ctx.message.author, "Command Stats", data) + await ctx.send(file=discord.File(banner, filename='banner.png')) + except (FileNotFoundError, discord.Forbidden): + fmt = "The command {} has been used a total of {} times\n" \ + "{} times on this server\n" \ + "It has been ran by you, {}, {} times".format(cmd.qualified_name, total_usage, server_usage, + ctx.message.author.display_name, member_usage) + + await ctx.send(fmt) + + @command.command(name="leaderboard") + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def command_leaderboard(self, ctx, option="server"): + """This command can be used to print a leaderboard of commands + Provide 'server' to print a leaderboard for this server + Provide 'me' to print a leaderboard for your own usage + + EXAMPLE: !command leaderboard me + RESULT: The realization of how little of a life you have""" + await ctx.message.channel.trigger_typing() + + if re.search('(author|me)', option): + author = ctx.message.author + # First lets get all the command usage + command_stats = self.bot.db.load('command_usage') + # Now use a dictionary comprehension to get just the command name, and usage + # Based on the author's usage of the command + stats = {data['command']: data['member_usage'].get(str(author.id)) for data in command_stats + if data['member_usage'].get(str(author.id), 0) > 0} + # Now sort it by the amount of times used + sorted_stats = sorted(stats.items(), key=lambda x: x[1], reverse=True) + + # Create a string, each command on it's own line, based on the top 5 used commands + # I'm letting it use the length of the sorted_stats[:5] + # As this can include, for example, all 3 if there are only 3 entries + try: + top_5 = [(data[0], data[1]) for data in sorted_stats[:5]] + banner = await utils.create_banner(ctx.message.author, "Your command usage", top_5) + await ctx.send(file=discord.File(banner, filename='banner.png')) + except (FileNotFoundError, discord.Forbidden): + top_5 = "\n".join("{}: {}".format(data[0], data[1]) for data in sorted_stats[:5]) + await ctx.send( + "Your top {} most used commands are:\n```\n{}```".format(len(sorted_stats[:5]), top_5)) + elif re.search('server', option): + # This is exactly the same as above, except server usage instead of member usage + server = ctx.message.guild + command_stats = self.bot.db.load('command_usage') + stats = {data['command']: data['server_usage'].get(str(server.id)) for data in command_stats + if data['server_usage'].get(str(server.id), 0) > 0} + sorted_stats = sorted(stats.items(), key=lambda x: x[1], reverse=True) + try: + top_5 = [(data[0], data[1]) for data in sorted_stats[:5]] + banner = await utils.create_banner(ctx.message.author, "Server command usage", top_5) + await ctx.send(file=discord.File(banner, filename='banner.png')) + except (FileNotFoundError, discord.Forbidden): + top_5 = "\n".join("{}: {}".format(data[0], data[1]) for data in sorted_stats[:5]) + await ctx.send( + "This server's top {} most used commands are:\n```\n{}```".format(len(sorted_stats[:5]), top_5)) + else: + await ctx.send("That is not a valid option, valid options are: `server` or `me`") + + @commands.command() + @commands.guild_only() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def mostboops(self, ctx): + """Shows the person you have 'booped' the most, as well as how many times + + EXAMPLE: !mostboops + RESULT: You've booped @OtherPerson 351253897120935712093572193057310298 times!""" + boops = self.bot.db.load('boops', key=ctx.message.author.id) + if boops is None: + await ctx.send("You have not booped anyone {} Why the heck not...?".format(ctx.message.author.mention)) + return + + # Just to make this easier, just pay attention to the boops data, now that we have the right entry + boops = boops['boops'] + + # First get a list of the ID's of all members in this server, for use in list comprehension + server_member_ids = [str(member.id) for member in ctx.message.guild.members] + # Then get a sorted list, based on the amount of times they've booped the member + # Reverse needs to be true, as we want it to go from highest to lowest + sorted_boops = sorted(boops.items(), key=lambda x: x[1], reverse=True) + # Then override the same list, checking if the member they've booped is in this server + sorted_boops = [x for x in sorted_boops if x[0] in server_member_ids] + + # Since this is sorted, we just need to get the following information on the first user in the list + most_id, most_boops = sorted_boops[0] + + member = ctx.message.guild.get_member(int(most_id)) + + await ctx.send("{0} you have booped {1} the most amount of times, coming in at {2} times".format( + ctx.message.author.mention, member.display_name, most_boops)) + + @commands.command() + @commands.guild_only() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def listboops(self, ctx): + """Lists all the users you have booped and the amount of times + + EXAMPLE: !listboops + RESULT: The list of your booped members!""" + await ctx.message.channel.trigger_typing() + + boops = self.bot.db.load('boops', key=ctx.message.author.id) + if boops is None: + await ctx.send("You have not booped anyone {} Why the heck not...?".format(ctx.message.author.mention)) + return + + # Just to make this easier, just pay attention to the boops data, now that we have the right entry + boops = boops['boops'] + + # Same concept as the mostboops method + server_member_ids = [member.id for member in ctx.message.guild.members] + booped_members = {int(m_id): amt for m_id, amt in boops.items() if int(m_id) in server_member_ids} + sorted_booped_members = sorted(booped_members.items(), key=lambda k: k[1], reverse=True) + # Now we only want the first 10 members, so splice this list + sorted_booped_members = sorted_booped_members[:10] + + try: + output = [("{0.display_name}".format(ctx.message.guild.get_member(m_id)), amt) + for m_id, amt in sorted_booped_members] + banner = await utils.create_banner(ctx.message.author, "Your booped victims", output) + await ctx.send(file=discord.File(banner, filename='banner.png')) + except (FileNotFoundError, discord.Forbidden): + output = "\n".join( + "{0.display_name}: {1} times".format(ctx.message.guild.get_member(m_id), amt) for + m_id, amt in sorted_booped_members) + await ctx.send("You have booped:```\n{}```".format(output)) + + @commands.command() + @commands.guild_only() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def leaderboard(self, ctx): + """Prints a leaderboard of everyone in the server's battling record + + EXAMPLE: !leaderboard + RESULT: A leaderboard of this server's battle records""" + await ctx.message.channel.trigger_typing() + + # Create a list of the ID's of all members in this server, for comparison to the records saved + server_member_ids = [member.id for member in ctx.message.guild.members] + battles = self.bot.db.load('battle_records') + if battles is None or len(battles) == 0: + await ctx.send("No one has battled on this server!") + + battles = [battle for battle in battles if int(battle['member_id']) in server_member_ids] + + # Sort the members based on their rating + sorted_members = sorted(battles, key=lambda k: k['rating'], reverse=True) + + output = [] + for x in sorted_members: + member_id = int(x['member_id']) + rating = x['rating'] + member = ctx.message.guild.get_member(member_id) + output.append("{} (Rating: {})".format(member.display_name, rating)) + + try: + pages = utils.Pages(self.bot, message=ctx.message, entries=output) + await pages.paginate() + except utils.CannotPaginate as e: + await ctx.send(str(e)) + + @commands.command() + @commands.guild_only() + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def battlestats(self, ctx, member: discord.Member = None): + """Prints the battling stats for you, or the user provided + + EXAMPLE: !stats @OtherPerson + RESULT: How good they are at winning a completely luck based game""" + await ctx.message.channel.trigger_typing() + + member = member or ctx.message.author + # Get the different data that we'll display + server_rank = "{}/{}".format(*self.bot.br.get_server_rank(member)) + overall_rank = "{}/{}".format(*self.bot.br.get_rank(member)) + rating = self.bot.br.get_rating(member) + record = self.bot.br.get_record(member) + try: + # Create our banner + title = 'Stats for {}'.format(member.display_name) + fmt = [('Record', record), ('Server Rank', server_rank), ('Overall Rank', overall_rank), ('Rating', rating)] + banner = await utils.create_banner(member, title, fmt) + await ctx.send(file=discord.File(banner, filename='banner.png')) + except (FileNotFoundError, discord.Forbidden): + fmt = 'Stats for {}:\n\tRecord: {}\n\tServer Rank: {}\n\tOverall Rank: {}\n\tRating: {}' + fmt = fmt.format(member.display_name, record, server_rank, overall_rank, rating) + await ctx.send('```\n{}```'.format(fmt)) + + @commands.command(aliases=['donators']) + @utils.custom_perms(send_messages=True) + @utils.check_restricted() + async def patrons(self, ctx): + """Prints a list of all the patrons for Bonfire + + EXAMPLE: !donators + RESULT: A list of the donators""" + try: + pages = utils.Pages(self.bot, message=ctx.message, entries=self.donators) + await pages.paginate() + except utils.CannotPaginate as e: + await ctx.send(str(e)) + + +def setup(bot): + bot.add_cog(Stats(bot))