diff --git a/cogs/admin.py b/cogs/admin.py index 9bc0fbb..49ff777 100644 --- a/cogs/admin.py +++ b/cogs/admin.py @@ -7,7 +7,7 @@ from discord.ext import commands valid_perms = [p for p in dir(discord.Permissions) if isinstance(getattr(discord.Permissions, p), property)] -class Admin: +class Admin(commands.Cog): """These are commands that allow more intuitive configuration, that don't fit into the config command""" @commands.command() diff --git a/cogs/birthday.py b/cogs/birthday.py index 601bd0c..43ddf77 100644 --- a/cogs/birthday.py +++ b/cogs/birthday.py @@ -57,7 +57,7 @@ def parse_string(date): return datetime.date(year, month, day) -class Birthday: +class Birthday(commands.Cog): """Track and announce birthdays""" def __init__(self, bot): @@ -157,7 +157,7 @@ WHERE EXAMPLE: !birthdays RESULT: A printout of the birthdays from everyone on this server""" if member: - date = await self.bot.db.fetchrow("SELECT birthday FROM users WHERE id=$1", member.id) + date = await ctx.bot.db.fetchrow("SELECT birthday FROM users WHERE id=$1", member.id) if date is None or date["birthday"] is None: await ctx.send(f"I do not have {member.display_name}'s birthday saved!") else: @@ -207,9 +207,9 @@ WHERE await ctx.send(f"I have just saved your birthday as {date}") try: - await self.bot.db.execute("INSERT INTO users (id, birthday) VALUES ($1, $2)", ctx.author.id, date) + await ctx.bot.db.execute("INSERT INTO users (id, birthday) VALUES ($1, $2)", ctx.author.id, date) except UniqueViolationError: - await self.bot.db.execute("UPDATE users SET birthday = $1 WHERE id = $2", date, ctx.author.id) + await ctx.bot.db.execute("UPDATE users SET birthday = $1 WHERE id = $2", date, ctx.author.id) @birthday.command(name='remove') @utils.can_run(send_messages=True) @@ -219,7 +219,7 @@ WHERE EXAMPLE: !birthday remove RESULT: I have magically forgotten your birthday""" await ctx.send("I don't know your birthday anymore :(") - await self.bot.db.execute("UPDATE users SET birthday=NULL WHERE id=$1", ctx.author.id) + await ctx.bot.db.execute("UPDATE users SET birthday=NULL WHERE id=$1", ctx.author.id) def setup(bot): diff --git a/cogs/blackjack.py b/cogs/blackjack.py index 0e9b15e..b2a593a 100644 --- a/cogs/blackjack.py +++ b/cogs/blackjack.py @@ -6,14 +6,14 @@ import asyncio import math -class Blackjack: +class Blackjack(commands.Cog): """Pretty self-explanatory""" def __init__(self, bot): self.bot = bot self.games = {} - def __unload(self): + def cog_unload(self): # Simply cancel every task for game in self.games.values(): game.task.cancel() diff --git a/cogs/chess.py b/cogs/chess.py index 0254031..8f2a4b2 100644 --- a/cogs/chess.py +++ b/cogs/chess.py @@ -7,14 +7,12 @@ import re from enum import Enum -class Chess: +class Chess(commands.Cog): """Pretty self-explanatory""" - def __init__(self, bot): - self.bot = bot - # Our format for games is going to be a little different, because we do want to allow multiple games per guild - # Format should be {'server_id': [Game, Game, Game]} - self.games = {} + # Our format for games is going to be a little different, because we do want to allow multiple games per guild + # Format should be {'server_id': [Game, Game, Game]} + games = {} def play(self, player, notation): """Our task to handle a player making their actual move""" @@ -152,7 +150,7 @@ class Chess: elif result is MoveStatus.valid: game = self.get_game(ctx.message.author) link = game.draw_board() - await self.bot.upload(link) + await ctx.bot.upload(link) @commands.command() @checks.can_run(send_messages=True) diff --git a/cogs/config.py b/cogs/config.py index 446e2a4..43d7cb1 100644 --- a/cogs/config.py +++ b/cogs/config.py @@ -26,9 +26,13 @@ class MessageFormatError(ConfigException): # noinspection PyMethodMayBeStatic,PyUnusedLocal -class GuildConfiguration: +class GuildConfiguration(commands.Cog): """Handles configuring the different settings that can be used on the bot""" + keys = { + + } + def _str_to_bool(self, opt, setting): setting = setting.title() if setting.title() not in ["True", "False"]: @@ -596,7 +600,7 @@ WHERE """ return await ctx.bot.db.execute(query, setting, ctx.guild.id) - async def __after_invoke(self, ctx): + async def cog_after_invoke(self, ctx): """Here we will facilitate cleaning up settings, will remove channels/roles that no longer exist, etc.""" pass diff --git a/cogs/events.py b/cogs/events.py index d4431dc..ee18bea 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -1,9 +1,11 @@ -from utils import config import aiohttp import logging import json import discord +from utils import config +from discord.ext import commands + log = logging.getLogger() discord_bots_url = 'https://bots.discord.pw/api/bots/{}/stats' @@ -11,14 +13,14 @@ discordbots_url = "https://discordbots.org/api/bots/{}/stats" carbonitex_url = 'https://www.carbonitex.net/discord/data/botdata.php' -class StatsUpdate: +class StatsUpdate(commands.Cog): """This is used purely to update stats information for the bot sites""" def __init__(self, bot): self.bot = bot self.session = aiohttp.ClientSession() - def __unload(self): + def cog_unload(self): self.bot.loop.create_task(self.session.close()) async def update(self): @@ -59,15 +61,19 @@ class StatsUpdate: async with self.session.post(url, data=payload, headers=headers) as resp: log.info('discordbots.com statistics retruned {} for {}'.format(resp.status, payload)) + @commands.Cog.listener async def on_guild_join(self, _): await self.update() + @commands.Cog.listener async def on_guild_leave(self, _): await self.update() + @commands.Cog.listener async def on_ready(self): await self.update() + @commands.Cog.listener async def on_member_join(self, member): query = """ SELECT @@ -99,6 +105,7 @@ WHERE except (discord.Forbidden, discord.HTTPException, AttributeError): pass + @commands.Cog.listener async def on_member_remove(self, member): query = """ SELECT diff --git a/cogs/hangman.py b/cogs/hangman.py index 74a1b32..6a64534 100644 --- a/cogs/hangman.py +++ b/cogs/hangman.py @@ -64,13 +64,11 @@ class Game: return fmt -class Hangman: +class Hangman(commands.Cog): """Pretty self-explanatory""" - def __init__(self, bot): - self.bot = bot - self.games = {} - self.pending_games = [] + games = {} + pending_games = [] def create(self, word, ctx): # Create a new game, then save it as the server's game @@ -166,7 +164,7 @@ class Hangman: self.pending_games.append(ctx.guild.id) try: - msg = await self.bot.wait_for('message', check=check, timeout=60) + msg = await ctx.bot.wait_for('message', check=check, timeout=60) except asyncio.TimeoutError: self.pending_games.remove(ctx.guild.id) await ctx.send( diff --git a/cogs/images.py b/cogs/images.py index c9bd3c5..7f531af 100644 --- a/cogs/images.py +++ b/cogs/images.py @@ -7,12 +7,9 @@ import math import utils -class Images: +class Images(commands.Cog): """Commands that post images, or look up images""" - def __init__(self, bot): - self.bot = bot - @commands.command(aliases=['rc']) @utils.can_run(send_messages=True) async def cat(self, ctx): diff --git a/cogs/interaction.py b/cogs/interaction.py index 70ef3ee..76e496a 100644 --- a/cogs/interaction.py +++ b/cogs/interaction.py @@ -85,12 +85,10 @@ hugs = \ "*approaches {user} after having gone to the gym for several months and almost crushes them.*"] -class Interaction: +class Interaction(commands.Cog): """Commands that interact with another user""" - def __init__(self, bot): - self.bot = bot - self.battles = defaultdict(list) + battles = defaultdict(list) def get_receivers_battle(self, receiver): for battle in self.battles.get(receiver.guild.id, []): @@ -142,7 +140,7 @@ class Interaction: await ctx.send("Error: Could not find user: {}".format(user)) return - settings = await self.bot.db.fetchrow( + settings = await ctx.bot.db.fetchrow( "SELECT custom_hugs, include_default_hugs FROM guilds WHERE id = $1", ctx.guild.id ) @@ -193,7 +191,7 @@ class Interaction: await ctx.send("Why would you want to battle yourself? Suicide is not the answer") return # Check if the person battled is me - if self.bot.user.id == player2.id: + if ctx.bot.user.id == player2.id: ctx.command.reset_cooldown(ctx) await ctx.send("I always win, don't even try it.") return @@ -214,7 +212,7 @@ class Interaction: f"{ctx.prefix}accept or {ctx.prefix}decline" # Add a call to turn off battling, if the battle is not accepted/declined in 3 minutes part = functools.partial(self.battling_off, battle) - self.bot.loop.call_later(180, part) + ctx.bot.loop.call_later(180, part) await ctx.send(fmt) @commands.command() @@ -238,7 +236,7 @@ class Interaction: return # Lets get the settings - settings = await self.bot.db.fetchrow( + settings = await ctx.bot.db.fetchrow( "SELECT custom_battles, include_default_battles FROM guilds WHERE id = $1", ctx.guild.id ) @@ -278,7 +276,7 @@ FROM ) AS sub WHERE id = any($2) """ - results = await self.bot.db.fetch(query, member_list, [winner.id, loser.id]) + results = await ctx.bot.db.fetch(query, member_list, [winner.id, loser.id]) old_winner = old_loser = None for result in results: @@ -309,7 +307,7 @@ VALUES ($1, $2, $3, $4) """ if old_loser: - await self.bot.db.execute( + await ctx.bot.db.execute( update_query, loser_rating, old_loser['battle_wins'], @@ -317,9 +315,9 @@ VALUES loser.id ) else: - await self.bot.db.execute(insert_query, loser.id, loser_rating, 0, 1) + await ctx.bot.db.execute(insert_query, loser.id, loser_rating, 0, 1) if old_winner: - await self.bot.db.execute( + await ctx.bot.db.execute( update_query, winner_rating, old_winner['battle_wins'] + 1, @@ -327,9 +325,9 @@ VALUES winner.id ) else: - await self.bot.db.execute(insert_query, winner.id, winner_rating, 1, 0) + await ctx.bot.db.execute(insert_query, winner.id, winner_rating, 1, 0) - results = await self.bot.db.fetch(query, member_list, [winner.id, loser.id]) + results = await ctx.bot.db.fetch(query, member_list, [winner.id, loser.id]) new_winner_rank = new_loser_rank = None for result in results: @@ -393,13 +391,13 @@ VALUES ctx.command.reset_cooldown(ctx) await ctx.send("You can't boop yourself! Silly...") return - if boopee.id == self.bot.user.id: + if boopee.id == ctx.bot.user.id: ctx.command.reset_cooldown(ctx) await ctx.send("Why the heck are you booping me? Get away from me >:c") return query = "SELECT amount FROM boops WHERE booper = $1 AND boopee = $2" - amount = await self.bot.db.fetchrow(query, booper.id, boopee.id) + amount = await ctx.bot.db.fetchrow(query, booper.id, boopee.id) if amount is None: amount = 1 replacement_query = "INSERT INTO boops (booper, boopee, amount) VALUES($1, $2, $3)" @@ -408,7 +406,7 @@ VALUES amount = amount['amount'] + 1 await ctx.send(f"{booper.mention} has just booped {boopee.mention}{message}! That's {amount} times now!") - await self.bot.db.execute(replacement_query, booper.id, boopee.id, amount) + await ctx.bot.db.execute(replacement_query, booper.id, boopee.id, amount) class Battle: diff --git a/cogs/links.py b/cogs/links.py index fc8b8be..79dca77 100644 --- a/cogs/links.py +++ b/cogs/links.py @@ -8,13 +8,10 @@ import discord import re -class Links: +class Links(commands.Cog): """This class contains all the commands that make HTTP requests In other words, all commands here rely on other URL's to complete their requests""" - def __init__(self, bot): - self.bot = bot - @commands.command(aliases=['g']) @utils.can_run(send_messages=True) async def google(self, ctx, *, query: str): diff --git a/cogs/misc.py b/cogs/misc.py index 432481e..03ac4c2 100644 --- a/cogs/misc.py +++ b/cogs/misc.py @@ -38,13 +38,10 @@ def _command_signature(cmd): return ' '.join(result) -class Miscallaneous: +class Miscallaneous(commands.Cog): """Core commands, these are the miscallaneous commands that don't fit into other categories'""" - - def __init__(self, bot): - self.bot = bot - self.process = psutil.Process() - self.process.cpu_percent() + process = psutil.Process() + process.cpu_percent() @commands.command() @commands.cooldown(1, 3, commands.cooldowns.BucketType.user) @@ -56,7 +53,7 @@ class Miscallaneous: if command is None: p = await utils.HelpPaginator.from_bot(ctx) else: - entity = self.bot.get_cog(command) or self.bot.get_command(command) + entity = ctx.bot.get_cog(command) or ctx.bot.get_command(command) if entity is None: clean = command.replace('@', '@\u200b') @@ -74,7 +71,7 @@ class Miscallaneous: chunks = [] if entity: - entity = self.bot.get_cog(entity) or self.bot.get_command(entity) + entity = ctx.bot.get_cog(entity) or ctx.bot.get_command(entity) if entity is None: fmt = "Hello! Here is a list of the sections of commands that I have " \ "(there are a lot of commands so just start with the sections...I know, I'm pretty great)\n" @@ -88,7 +85,7 @@ class Miscallaneous: chunks.append(fmt) - cogs = sorted(self.bot.cogs.values(), key=lambda c: c.__class__.__name__) + cogs = sorted(ctx.bot.cogs.values(), key=lambda c: c.__class__.__name__) for cog in cogs: tmp = "**{}**\n".format(cog.__class__.__name__) if cog.__doc__: @@ -102,14 +99,14 @@ class Miscallaneous: tmp += "\n{}".format(entity.help) chunks.append(tmp) else: - cmds = sorted(ctx.bot.get_cog_commands(entity.__class__.__name__), key=lambda c: c.name) + cmds = sorted(entity.get_commands(), key=lambda c: c.name) fmt = "Here are a list of commands under the section {}\n".format(entity.__class__.__name__) fmt += "Type `{}help command` to get more help on a specific command\n\n".format(ctx.prefix) chunks.append(fmt) for command in cmds: - for subcommand in utils.get_all_subcommands(command): + for subcommand in command.walk_commands(): tmp = "**{}**\n\t{}\n".format(subcommand.qualified_name, subcommand.short_doc) if len(chunks[len(chunks) - 1] + tmp) > 2000: chunks.append(tmp) @@ -144,7 +141,7 @@ class Miscallaneous: """Returns the latency between the server websocket, and between reading messages""" msg_latency = datetime.datetime.utcnow() - ctx.message.created_at fmt = "Message latency {0:.2f} seconds".format(msg_latency.seconds + msg_latency.microseconds / 1000000) - fmt += "\nWebsocket latency {0:.2f} seconds".format(self.bot.latency) + fmt += "\nWebsocket latency {0:.2f} seconds".format(ctx.bot.latency) await ctx.send(fmt) @commands.command(aliases=["coin"]) @@ -231,8 +228,8 @@ class Miscallaneous: # Set the owner embed = discord.Embed(**opts) - if hasattr(self.bot, 'owner'): - embed.set_author(name=str(self.bot.owner), icon_url=self.bot.owner.avatar_url) + if hasattr(ctx.bot, 'owner'): + embed.set_author(name=str(ctx.bot.owner), icon_url=ctx.bot.owner.avatar_url) # Setup the process statistics name = "Process statistics" @@ -242,17 +239,17 @@ class Miscallaneous: cpu_usage = self.process.cpu_percent() / psutil.cpu_count() value += 'Memory: {:.2f} MiB'.format(memory_usage) value += '\nCPU: {}%'.format(cpu_usage) - if hasattr(self.bot, 'uptime'): - value += "\nUptime: {}".format((pendulum.now(tz="UTC") - self.bot.uptime).in_words()) + if hasattr(ctx.bot, 'uptime'): + value += "\nUptime: {}".format((pendulum.now(tz="UTC") - ctx.bot.uptime).in_words()) embed.add_field(name=name, value=value, inline=False) # Setup the user and guild statistics name = "User/Guild statistics" value = "" - value += "Channels: {}".format(len(list(self.bot.get_all_channels()))) - value += "\nUsers: {}".format(len(self.bot.users)) - value += "\nServers: {}".format(len(self.bot.guilds)) + value += "Channels: {}".format(len(list(ctx.bot.get_all_channels()))) + value += "\nUsers: {}".format(len(ctx.bot.users)) + value += "\nServers: {}".format(len(ctx.bot.guilds)) embed.add_field(name=name, value=value, inline=False) # The game statistics @@ -261,10 +258,10 @@ class Miscallaneous: # Lets make this one a list and join it at the end value = [] - hm = self.bot.get_cog('Hangman') - ttt = self.bot.get_cog('TicTacToe') - bj = self.bot.get_cog('Blackjack') - interaction = self.bot.get_cog('Interaction') + hm = ctx.bot.get_cog('Hangman') + ttt = ctx.bot.get_cog('TicTacToe') + bj = ctx.bot.get_cog('Blackjack') + interaction = ctx.bot.get_cog('Interaction') if hm: value.append("Hangman games: {}".format(len(hm.games))) @@ -274,7 +271,7 @@ class Miscallaneous: value.append("Blackjack games: {}".format(len(bj.games))) if interaction: count_battles = 0 - for battles in self.bot.get_cog('Interaction').battles.values(): + for battles in ctx.bot.get_cog('Interaction').battles.values(): count_battles += len(battles) value.append("Battles running: {}".format(len(bj.games))) embed.add_field(name=name, value="\n".join(value), inline=False) @@ -288,8 +285,8 @@ class Miscallaneous: EXAMPLE: !uptime RESULT: A BAJILLION DAYS""" - if hasattr(self.bot, 'uptime'): - await ctx.send("Uptime: ```\n{}```".format((pendulum.now(tz="UTC") - self.bot.uptime).in_words())) + if hasattr(ctx.bot, 'uptime'): + await ctx.send("Uptime: ```\n{}```".format((pendulum.now(tz="UTC") - ctx.bot.uptime).in_words())) else: await ctx.send("I've just restarted and not quite ready yet...gimme time I'm not a morning pony :c") @@ -314,7 +311,7 @@ class Miscallaneous: perms.connect = True perms.attach_files = True perms.add_reactions = True - app_info = await self.bot.application_info() + app_info = await ctx.bot.application_info() await ctx.send("Use this URL to add me to a server that you'd like!\n<{}>" .format(discord.utils.oauth_url(app_info.id, perms))) diff --git a/cogs/mod.py b/cogs/mod.py index ecc4171..02453e7 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -6,12 +6,9 @@ import discord import asyncio -class Moderation: +class Moderation(commands.Cog): """Moderation commands, things that help control a server...but not the settings of the server""" - def __init__(self, bot): - self.bot = bot - @commands.command() @commands.guild_only() @utils.can_run(kick_members=True) @@ -40,7 +37,7 @@ class Moderation: # Lets only accept an int for this method, in order to ensure only an ID is provided # Due to that though, we need to ensure a string is passed as the member's ID try: - await self.bot.http.unban(member_id, ctx.guild.id) + await ctx.bot.http.unban(member_id, ctx.guild.id) await ctx.send("\N{OK HAND SIGN}") except discord.Forbidden: await ctx.send("But I can't, muh permissions >:c") @@ -61,7 +58,7 @@ class Moderation: # Lets first check if a user ID was provided, as that will be the easiest case to ban if member.isdigit(): try: - await self.bot.http.ban(member, ctx.guild.id, reason=reason) + await ctx.bot.http.ban(member, ctx.guild.id, reason=reason) await ctx.send("\N{OK HAND SIGN}") except discord.Forbidden: await ctx.send("But I can't, muh permissions >:c") diff --git a/cogs/osu.py b/cogs/osu.py index 3c79b28..b2fe66a 100644 --- a/cogs/osu.py +++ b/cogs/osu.py @@ -10,7 +10,7 @@ BASE_URL = 'https://osu.ppy.sh/api/' MAX_RETRIES = 5 -class Osu: +class Osu(commands.Cog): """View OSU stats""" def __init__(self, bot): @@ -107,7 +107,7 @@ class Osu: "id": author.id, "osu": user.username } - await self.bot.db.upsert("users", update) + await ctx.bot.db.upsert("users", update) @osu.command(name='score', aliases=['scores']) @utils.can_run(send_messages=True) @@ -180,7 +180,7 @@ class Osu: entries.append(entry) try: - pages = utils.DetailedPages(self.bot, message=ctx.message, entries=entries) + pages = utils.DetailedPages(ctx.bot, message=ctx.message, entries=entries) await pages.paginate() except utils.CannotPaginate as e: await ctx.send(str(e)) diff --git a/cogs/overwatch.py b/cogs/overwatch.py index 788bd1b..3b3764e 100644 --- a/cogs/overwatch.py +++ b/cogs/overwatch.py @@ -16,12 +16,9 @@ check_o_stats = ['wins'] log = logging.getLogger() -class Overwatch: +class Overwatch(commands.Cog): """Class for viewing Overwatch stats""" - def __init__(self, bot): - self.bot = bot - @commands.group() async def ow(self, ctx): """Command used to lookup information on your own user, or on another's @@ -39,7 +36,7 @@ class Overwatch: EXAMPLE: !ow stats @OtherPerson Junkrat RESULT: Whether or not you should unfriend this person because they're a dirty rat""" user = user or ctx.message.author - bt = self.bot.db.load('overwatch', key=str(user.id), pluck='battletag') + bt = ctx.bot.db.load('overwatch', key=str(user.id), pluck='battletag') if bt is None: await ctx.send("I do not have this user's battletag saved!") @@ -119,7 +116,7 @@ class Overwatch: 'battletag': bt } - await self.bot.db.save('overwatch', entry) + await ctx.bot.db.save('overwatch', entry) await ctx.send("I have just saved your battletag {}".format(ctx.message.author.mention)) @ow.command(name="delete", aliases=['remove']) @@ -133,7 +130,7 @@ class Overwatch: 'member_id': str(ctx.message.author.id), 'battletag': None } - await self.bot.db.save('overwatch', entry) + await ctx.bot.db.save('overwatch', entry) await ctx.send("I no longer have your battletag saved {}".format(ctx.message.author.mention)) diff --git a/cogs/owner.py b/cogs/owner.py index 4172991..741bb9b 100644 --- a/cogs/owner.py +++ b/cogs/owner.py @@ -16,16 +16,13 @@ def get_syntax_error(e): return '```py\n{0.text}{1:>{0.offset}}\n{2}: {0}```'.format(e, '^', type(e).__name__) -class Owner: +class Owner(commands.Cog): """Commands that can only be used by the owner of the bot, bot management commands""" + _last_result = None + sessions = set() - def __init__(self, bot): - self.bot = bot - self._last_result = None - self.sessions = set() - - async def __local_check(self, ctx): - return await self.bot.is_owner(ctx.author) + async def cog_check(self, ctx): + return await ctx.bot.is_owner(ctx.author) @staticmethod def cleanup_code(content): @@ -43,7 +40,7 @@ class Owner: variables = { 'ctx': ctx, - 'bot': self.bot, + 'bot': ctx.bot, 'message': msg, 'guild': msg.guild, 'server': msg.guild, @@ -69,7 +66,7 @@ class Owner: while True: try: - response = await self.bot.wait_for('message', check=check, timeout=10.0 * 60.0) + response = await ctx.bot.wait_for('message', check=check, timeout=10.0 * 60.0) except asyncio.TimeoutError: await ctx.send('Exiting REPL session.') self.sessions.remove(msg.channel.id) @@ -134,7 +131,7 @@ class Owner: @commands.command() async def sendtochannel(self, ctx, cid: int, *, message): """Sends a message to a provided channel, by ID""" - channel = self.bot.get_channel(cid) + channel = ctx.bot.get_channel(cid) await channel.send(message) try: await ctx.message.delete() @@ -144,7 +141,7 @@ class Owner: @commands.command() async def debug(self, ctx, *, body: str): env = { - 'bot': self.bot, + 'bot': ctx.bot, 'ctx': ctx, 'channel': ctx.message.channel, 'author': ctx.message.author, @@ -202,19 +199,19 @@ class Owner: """Shuts the bot down""" fmt = 'Shutting down, I will miss you {0.author.name}' await ctx.send(fmt.format(ctx.message)) - await self.bot.logout() - await self.bot.close() + await ctx.bot.logout() + await ctx.bot.close() @commands.command() async def name(self, ctx, new_nick: str): """Changes the bot's name""" - await self.bot.user.edit(username=new_nick) + await ctx.bot.user.edit(username=new_nick) await ctx.send('Changed username to ' + new_nick) @commands.command() async def status(self, ctx, *, status: str): """Changes the bot's 'playing' status""" - await self.bot.change_presence(activity=discord.Game(name=status, type=0)) + await ctx.bot.change_presence(activity=discord.Game(name=status, type=0)) await ctx.send("Just changed my status to '{}'!".format(status)) @commands.command() @@ -228,7 +225,7 @@ class Owner: # This try catch will catch errors such as syntax errors in the module we are loading try: - self.bot.load_extension(module) + ctx.bot.load_extension(module) await ctx.send("I have just loaded the {} module".format(module)) except Exception as error: fmt = 'An error occurred while processing this request: ```py\n{}: {}\n```' @@ -243,7 +240,7 @@ class Owner: if not module.startswith("cogs"): module = "cogs.{}".format(module) - self.bot.unload_extension(module) + ctx.bot.unload_extension(module) await ctx.send("I have just unloaded the {} module".format(module)) @commands.command() @@ -254,11 +251,11 @@ class Owner: module = module.lower() if not module.startswith("cogs"): module = "cogs.{}".format(module) - self.bot.unload_extension(module) + ctx.bot.unload_extension(module) # This try block will catch errors such as syntax errors in the module we are loading try: - self.bot.load_extension(module) + ctx.bot.load_extension(module) await ctx.send("I have just reloaded the {} module".format(module)) except Exception as error: fmt = 'An error occurred while processing this request: ```py\n{}: {}\n```' diff --git a/cogs/picarto.py b/cogs/picarto.py index aa773e3..64e6899 100644 --- a/cogs/picarto.py +++ b/cogs/picarto.py @@ -1,9 +1,10 @@ import asyncio import discord import traceback - import utils +from discord.ext import commands + BASE_URL = 'https://api.picarto.tv/v1' @@ -21,7 +22,7 @@ def produce_embed(*channels): return discord.Embed(title="Channels that have gone online!", description=description.strip()) -class Picarto: +class Picarto(commands.Cog): """Pretty self-explanatory""" def __init__(self, bot): diff --git a/cogs/polls.py b/cogs/polls.py index a89385f..348e928 100644 --- a/cogs/polls.py +++ b/cogs/polls.py @@ -1,4 +1,5 @@ from discord.ext import commands + import utils @@ -35,7 +36,7 @@ class Poll: await self.message.remove_reaction(r, member) -class Polls: +class Polls(commands.Cog): """Create custom polls that can be tracked through reactions""" def __init__(self, bot): @@ -65,6 +66,7 @@ class Polls: if p.message.id == message.id: return p + @commands.Cog.listener async def on_reaction_add(self, reaction, user): if user.id == self.bot.user.id: return diff --git a/cogs/raffle.py b/cogs/raffle.py index b9ebc06..aa068f4 100644 --- a/cogs/raffle.py +++ b/cogs/raffle.py @@ -9,12 +9,9 @@ import asyncio import random -class Raffle: +class Raffle(commands.Cog): """Used to hold custom raffles""" - - def __init__(self, bot): - self.bot = bot - self.raffles = defaultdict(list) + raffles = defaultdict(list) def create_raffle(self, ctx, title, num): raffle = GuildRaffle(ctx, title, num) @@ -83,7 +80,7 @@ class Raffle: check = lambda m: m.author == author and m.channel == channel try: - msg = await self.bot.wait_for('message', check=check, timeout=120) + msg = await ctx.bot.wait_for('message', check=check, timeout=120) except asyncio.TimeoutError: await ctx.send("You took too long! >:c") return @@ -103,7 +100,7 @@ class Raffle: return False try: - msg = await self.bot.wait_for('message', timeout=120, check=check) + msg = await ctx.bot.wait_for('message', timeout=120, check=check) except asyncio.TimeoutError: await ctx.send("You took too long! >:c") return diff --git a/cogs/roles.py b/cogs/roles.py index 20992ed..2c742de 100644 --- a/cogs/roles.py +++ b/cogs/roles.py @@ -7,12 +7,9 @@ import re import asyncio -class Roles: +class Roles(commands.Cog): """Class to handle management of roles on the server""" - def __init__(self, bot): - self.bot = bot - @commands.command(aliases=['color']) @commands.guild_only() @utils.can_run(send_messages=True) @@ -125,7 +122,7 @@ class Roles: if len(members) == 0: await ctx.send("Please provide the list of members you want to remove a role from") try: - msg = await self.bot.wait_for('message', check=check, timeout=60) + msg = await ctx.bot.wait_for('message', check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -141,7 +138,7 @@ class Roles: "Here is a list of this server's roles:" "```\n{}```".format("\n".join([r.name for r in server_roles]))) try: - msg = await self.bot.wait_for('message', check=check, timeout=60) + msg = await ctx.bot.wait_for('message', check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -188,7 +185,7 @@ class Roles: if len(members) == 0: await ctx.send("Please provide the list of members you want to add a role to") try: - msg = await self.bot.wait_for('message', check=check, timeout=60) + msg = await ctx.bot.wait_for('message', check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -202,7 +199,7 @@ class Roles: "Here is a list of this server's roles:" "```\n{}```".format("\n".join([r.name for r in server_roles]))) try: - msg = await self.bot.wait_for('message', check=check, timeout=60) + msg = await ctx.bot.wait_for('message', check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -253,7 +250,7 @@ class Roles: return False try: - msg = await self.bot.wait_for('message', timeout=60, check=check) + msg = await ctx.bot.wait_for('message', timeout=60, check=check) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -309,7 +306,7 @@ class Roles: await ctx.send( "Alright! I'm ready to create a new role, please respond with the name of the role you want to create") try: - msg = await self.bot.wait_for('message', timeout=60.0, check=author_check) + msg = await ctx.bot.wait_for('message', timeout=60.0, check=author_check) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -324,7 +321,7 @@ class Roles: # For this we're going to give a couple extra minutes before we timeout # as it might take a bit to figure out which permissions they want try: - msg = await self.bot.wait_for('message', timeout=180.0, check=num_seperated_check) + msg = await ctx.bot.wait_for('message', timeout=180.0, check=num_seperated_check) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -335,7 +332,7 @@ class Roles: # Check if this role should be in a separate section on the sidebard, i.e. hoisted await ctx.send("Do you want this role to be in a separate section on the sidebar? (yes or no)") try: - msg = await self.bot.wait_for('message', timeout=60.0, check=yes_no_check) + msg = await ctx.bot.wait_for('message', timeout=60.0, check=yes_no_check) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -344,7 +341,7 @@ class Roles: # Check if this role should be able to be mentioned await ctx.send("Do you want this role to be mentionable? (yes or no)") try: - msg = await self.bot.wait_for('message', timeout=60.0, check=yes_no_check) + msg = await ctx.bot.wait_for('message', timeout=60.0, check=yes_no_check) except asyncio.TimeoutError: await ctx.send("You took too long. I'm impatient, don't make me wait") return @@ -368,7 +365,7 @@ class Roles: await ctx.send("We did it! You just created the new role {}\nIf you want to add this role" " to some people, mention them now".format(role.name)) try: - msg = await self.bot.wait_for('message', timeout=60.0, check=members_check) + msg = await ctx.bot.wait_for('message', timeout=60.0, check=members_check) except asyncio.TimeoutError: # There's no need to mention the users, so don't send a failure message if they didn't, just return return diff --git a/cogs/roulette.py b/cogs/roulette.py index 3ba4355..8c5b8e8 100644 --- a/cogs/roulette.py +++ b/cogs/roulette.py @@ -8,12 +8,9 @@ from discord.ext import commands import utils -class Roulette: +class Roulette(commands.Cog): """A fun game that ends in someone getting kicked!""" - - def __init__(self, bot): - self.bot = bot - self.roulettes = [] + roulettes = [] def get_game(self, server): for x in self.roulettes: diff --git a/cogs/spades.py b/cogs/spades.py index cf6272e..63061f4 100644 --- a/cogs/spades.py +++ b/cogs/spades.py @@ -413,7 +413,7 @@ class Game: self.players.append(p) -class Spades: +class Spades(commands.Cog): def __init__(self, bot): self.bot = bot self.pending_game = None @@ -446,7 +446,7 @@ class Spades: g.join(author) self.pending_game = g - def __unload(self): + def cog_unload(self): # Simply cancel every task for _, task in self.games: task.cancel() diff --git a/cogs/spotify.py b/cogs/spotify.py index 9be4c52..75891c5 100644 --- a/cogs/spotify.py +++ b/cogs/spotify.py @@ -8,7 +8,7 @@ from base64 import urlsafe_b64encode import utils -class Spotify: +class Spotify(commands.Cog): """Pretty self-explanatory""" def __init__(self, bot): diff --git a/cogs/stats.py b/cogs/stats.py index 0c805d2..68bdf0d 100644 --- a/cogs/stats.py +++ b/cogs/stats.py @@ -6,7 +6,7 @@ import datetime from discord.ext import commands -class Stats: +class Stats(commands.Cog): """Leaderboard/stats related commands""" def __init__(self, bot): @@ -177,7 +177,7 @@ ORDER BY LIMIT 1 """ members = [m.id for m in ctx.guild.members] - most = await self.bot.db.fetchrow(query, ctx.author.id, members) + most = await ctx.bot.db.fetchrow(query, ctx.author.id, members) if most is None or len(most) == 0: await ctx.send(f"You have not booped anyone in this server {ctx.author.mention}") @@ -212,7 +212,7 @@ LIMIT 10 """ members = [m.id for m in ctx.guild.members] - most = await self.bot.db.fetch(query, ctx.author.id, members) + most = await ctx.bot.db.fetch(query, ctx.author.id, members) if len(most) != 0: embed = discord.Embed(title="Your booped victims", colour=ctx.author.colour) @@ -244,7 +244,7 @@ ORDER BY battle_rating DESC """ - results = await self.bot.db.fetch(query, [m.id for m in ctx.guild.members]) + results = await ctx.bot.db.fetch(query, [m.id for m in ctx.guild.members]) if len(results) == 0: await ctx.send("No one has battled on this server!") @@ -291,7 +291,7 @@ WHERE id = $2 member_list = [m.id for m in ctx.guild.members] result = await ctx.bot.db.fetch(query, member_list, member.id) server_rank = result["rank"] - # overall_rank = "{}/{}".format(*self.bot.br.get_rank(member)) + # overall_rank = "{}/{}".format(*ctx.bot.br.get_rank(member)) rating = result["battle_rating"] record = f"{result['battle_wins']} - {result['battle_losses']}" diff --git a/cogs/tags.py b/cogs/tags.py index 0edbaea..3cbdddc 100644 --- a/cogs/tags.py +++ b/cogs/tags.py @@ -6,12 +6,9 @@ import utils import asyncio -class Tags: +class Tags(commands.Cog): """This class contains all the commands for custom tags""" - def __init__(self, bot): - self.bot = bot - @commands.command() @commands.guild_only() @utils.can_run(send_messages=True) @@ -20,7 +17,7 @@ class Tags: EXAMPLE: !tags RESULT: All tags setup on this server""" - tags = await self.bot.db.fetch("SELECT trigger FROM tags WHERE guild=$1", ctx.guild.id) + tags = await ctx.bot.db.fetch("SELECT trigger FROM tags WHERE guild=$1", ctx.guild.id) if len(tags) > 0: entries = [t['trigger'] for t in tags] @@ -37,7 +34,7 @@ class Tags: EXAMPLE: !mytags RESULT: All your tags setup on this server""" - tags = await self.bot.db.fetch( + tags = await ctx.bot.db.fetch( "SELECT trigger FROM tags WHERE guild=$1 AND creator=$2", ctx.guild.id, ctx.author.id @@ -59,7 +56,7 @@ class Tags: EXAMPLE: !tag butts RESULT: Whatever you setup for the butts tag!!""" - tag = await self.bot.db.fetchrow( + tag = await ctx.bot.db.fetchrow( "SELECT id, result FROM tags WHERE guild=$1 AND trigger=$2", ctx.guild.id, tag.lower().strip() @@ -67,7 +64,7 @@ class Tags: if tag: await ctx.send("\u200B{}".format(tag['result'])) - await self.bot.db.execute("UPDATE tags SET uses = uses + 1 WHERE id = $1", tag['id']) + await ctx.bot.db.execute("UPDATE tags SET uses = uses + 1 WHERE id = $1", tag['id']) else: await ctx.send("There is no tag called {}".format(tag)) @@ -86,7 +83,7 @@ class Tags: my_msg = await ctx.send("Ready to setup a new tag! What do you want the trigger for the tag to be?") try: - msg = await self.bot.wait_for("message", check=check, timeout=60) + msg = await ctx.bot.wait_for("message", check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long!") return @@ -102,7 +99,7 @@ class Tags: "Current forbidden tag triggers are: \n{}".format("\n".join(forbidden_tags))) return - tag = await self.bot.db.fetchrow( + tag = await ctx.bot.db.fetchrow( "SELECT result FROM tags WHERE guild=$1 AND trigger=$2", ctx.guild.id, trigger.lower().strip() @@ -122,7 +119,7 @@ class Tags: trigger)) try: - msg = await self.bot.wait_for("message", check=check, timeout=60) + msg = await ctx.bot.wait_for("message", check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long!") return @@ -135,7 +132,7 @@ class Tags: pass await ctx.send("I have just setup a new tag for this server! You can call your tag with {}".format(trigger)) - await self.bot.db.execute( + await ctx.bot.db.execute( "INSERT INTO tags(guild, creator, trigger, result) VALUES ($1, $2, $3, $4)", ctx.guild.id, ctx.author.id, @@ -153,7 +150,7 @@ class Tags: def check(m): return m.channel == ctx.message.channel and m.author == ctx.message.author and len(m.content) > 0 - tag = await self.bot.db.fetchrow( + tag = await ctx.bot.db.fetchrow( "SELECT id, trigger FROM tags WHERE guild=$1 AND creator=$2 AND trigger=$3", ctx.guild.id, ctx.author.id, @@ -163,7 +160,7 @@ class Tags: if tag: my_msg = await ctx.send(f"Alright, what do you want the new result for the tag {tag} to be") try: - msg = await self.bot.wait_for("message", check=check, timeout=60) + msg = await ctx.bot.wait_for("message", check=check, timeout=60) except asyncio.TimeoutError: await ctx.send("You took too long!") return @@ -177,7 +174,7 @@ class Tags: pass await ctx.send(f"Alright, the tag {trigger} has been updated") - await self.bot.db.execute("UPDATE tags SET result=$1 WHERE id=$2", new_result, tag['id']) + await ctx.bot.db.execute("UPDATE tags SET result=$1 WHERE id=$2", new_result, tag['id']) else: await ctx.send(f"You do not have a tag called {trigger} on this server!") @@ -191,7 +188,7 @@ class Tags: EXAMPLE: !tag delete stupid_tag RESULT: Deletes that stupid tag""" - tag = await self.bot.db.fetchrow( + tag = await ctx.bot.db.fetchrow( "SELECT id FROM tags WHERE guild=$1 AND creator=$2 AND trigger=$3", ctx.guild.id, ctx.author.id, @@ -200,7 +197,7 @@ class Tags: if tag: await ctx.send(f"I have just deleted the tag {trigger}") - await self.bot.db.execute("DELETE FROM tags WHERE id=$1", tag['id']) + await ctx.bot.db.execute("DELETE FROM tags WHERE id=$1", tag['id']) else: await ctx.send(f"You do not own a tag called {trigger} on this server!") @@ -210,7 +207,7 @@ class Tags: async def info_tag(self, ctx, *, trigger: str): """Shows some information a bout the tag given""" - tag = await self.bot.db.fetchrow( + tag = await ctx.bot.db.fetchrow( "SELECT creator, uses, trigger FROM tags WHERE guild=$1 AND trigger=$2", ctx.guild.id, trigger diff --git a/cogs/tictactoe.py b/cogs/tictactoe.py index ee4bb58..09206f5 100644 --- a/cogs/tictactoe.py +++ b/cogs/tictactoe.py @@ -97,12 +97,9 @@ class Board: return "```\n{}```".format(_board) -class TicTacToe: +class TicTacToe(commands.Cog): """Pretty self-explanatory""" - - def __init__(self, bot): - self.bot = bot - self.boards = {} + boards = {} def create(self, server_id, player1, player2): self.boards[server_id] = Board(player1, player2) @@ -193,7 +190,7 @@ class TicTacToe: await ctx.send("{} has won this game of TicTacToe, better luck next time {}".format(winner.display_name, loser.display_name)) # Handle updating ratings based on the winner and loser - await utils.update_records('tictactoe', self.bot.db, winner, loser) + await utils.update_records('tictactoe', ctx.bot.db, winner, loser) # This game has ended, delete it so another one can be made del self.boards[ctx.message.guild.id] else: diff --git a/cogs/tutorial.py b/cogs/tutorial.py index db6a62b..e7dc0fa 100644 --- a/cogs/tutorial.py +++ b/cogs/tutorial.py @@ -4,11 +4,8 @@ import utils import discord -class Tutorial: - - def __init__(self, bot): - self.bot = bot +class Tutorial(commands.Cog): @commands.command() # @utils.can_run(send_messages=True) async def tutorial(self, ctx, *, cmd_or_cog = None): @@ -18,17 +15,17 @@ class Tutorial: # The list of commands we need to run through commands = [] if cmd_or_cog: - cmd = self.bot.get_command(cmd_or_cog.lower()) + cmd = ctx.bot.get_command(cmd_or_cog.lower()) # This should be a cog if cmd is None: - cog = self.bot.get_cog(cmd_or_cog.title()) + cog = ctx.bot.get_cog(cmd_or_cog.title()) if cog is None: await ctx.send("Could not find a command or a cog for {}".format(cmd_or_cog)) return commands = set([ c - for c in self.bot.walk_commands() + for c in ctx.bot.walk_commands() if c.cog_name == cmd_or_cog.title() ]) # Specific command @@ -36,7 +33,7 @@ class Tutorial: commands = [cmd] # Use all commands else: - commands = set(self.bot.walk_commands()) + commands = set(ctx.bot.walk_commands()) # Loop through all the commands that we want to use for command in commands: