diff --git a/Discord/Harmonbot.py b/Discord/Harmonbot.py index 691e0890d4..876f9dc26c 100644 --- a/Discord/Harmonbot.py +++ b/Discord/Harmonbot.py @@ -46,7 +46,7 @@ async def on_ready(): # asyncio.ensure_future(client.cogs["Audio"].start_player(client.get_channel(voice_channel[1]))) text_channel = client.get_channel(voice_channel[1]) if text_channel: - client.cogs["Audio"].players[text_channel.server.id] = audio_player.AudioPlayer(client, text_channel) + client.cogs["Audio"].players[text_channel.guild.id] = audio_player.AudioPlayer(client, text_channel) await client.join_voice_channel(client.get_channel(voice_channel[0])) ''' for folder in os.listdir("data/server_data"): @@ -56,12 +56,12 @@ async def on_ready(): with open("data/server_data/{}/settings.json".format(folder), 'w') as settings_file: json.dump(data, settings_file, indent = 4) ''' - for server in client.servers: - utilities.create_folder("data/server_data/{}".format(server.id)) - utilities.create_file("server_data/{}/settings".format(server.id), content = {"anti-spam": False, "respond_to_bots": False}) - if server.name: - clean_name = re.sub(r"[\|/\\:\?\*\"<>]", "", server.name) # | / \ : ? * " < > - utilities.create_file("server_data/{}/{}".format(server.id, clean_name)) + for guild in client.guilds: + utilities.create_folder("data/server_data/{}".format(guild.id)) + utilities.create_file("server_data/{}/settings".format(guild.id), content = {"anti-spam": False, "respond_to_bots": False}) + if guild.name: + clean_name = re.sub(r"[\|/\\:\?\*\"<>]", "", guild.name) # | / \ : ? * " < > + utilities.create_file("server_data/{}/{}".format(guild.id, clean_name)) # TODO: DM if joined new server # TODO: DM if left server await clients.random_game_status() @@ -87,26 +87,26 @@ async def on_resumed(): print("Discord Harmonbot: resumed") @client.event - async def on_command(command, ctx): + async def on_command(ctx): with open("data/stats.json", 'r') as stats_file: stats = json.load(stats_file) stats["commands_executed"] += 1 - stats["commands_usage"][command.name] = stats["commands_usage"].get(command.name, 0) + 1 + stats["commands_usage"][ctx.command.name] = stats["commands_usage"].get(ctx.command.name, 0) + 1 with open("data/stats.json", 'w') as stats_file: json.dump(stats, stats_file, indent = 4) - utilities.create_folder("data/user_data/{}".format(ctx.message.author.id)) - utilities.create_file("user_data/{}/stats".format(ctx.message.author.id), content = {"commands_executed": 0, "points": 0, "respects_paid": 0}) + utilities.create_folder("data/user_data/{}".format(ctx.author.id)) + utilities.create_file("user_data/{}/stats".format(ctx.author.id), content = {"commands_executed": 0, "points": 0, "respects_paid": 0}) # TODO: Transfer respects paid data? - clean_name = re.sub(r"[\|/\\:\?\*\"<>]", "", ctx.message.author.name) # | / \ : ? * " < > - utilities.create_file("user_data/{}/{}".format(ctx.message.author.id, clean_name)) - with open("data/user_data/{}/stats.json".format(ctx.message.author.id), "r") as stats_file: + clean_name = re.sub(r"[\|/\\:\?\*\"<>]", "", ctx.author.name) # | / \ : ? * " < > + utilities.create_file("user_data/{}/{}".format(ctx.author.id, clean_name)) + with open("data/user_data/{}/stats.json".format(ctx.author.id), "r") as stats_file: stats = json.load(stats_file) stats["commands_executed"] += 1 stats["points"] += 1 - with open("data/user_data/{}/stats.json".format(ctx.message.author.id), 'w') as stats_file: + with open("data/user_data/{}/stats.json".format(ctx.author.id), 'w') as stats_file: json.dump(stats, stats_file, indent = 4) - @client.command(pass_context = True) + @client.command() @checks.is_owner() async def load(ctx, cog : str): '''Loads a cog''' @@ -119,7 +119,7 @@ async def load(ctx, cog : str): await client.embed_reply(":thumbsup::skin-tone-2: Loaded `{}` cog :gear:".format(cog)) await client.delete_message(ctx.message) - @client.command(pass_context = True) + @client.command() @checks.is_owner() async def unload(ctx, cog : str): '''Unloads a cog''' @@ -132,7 +132,7 @@ async def unload(ctx, cog : str): await client.embed_reply(":ok_hand::skin-tone-2: Unloaded `{}` cog :gear:".format(cog)) await client.delete_message(ctx.message) - @client.command(pass_context = True) + @client.command() @checks.is_owner() async def reload(ctx, cog : str): '''Reloads a cog''' @@ -157,13 +157,13 @@ async def reload(ctx, cog : str): async def on_message(message): # Log message - source = "Direct Message" if message.channel.is_private else "#{0.channel.name} ({0.channel.id}) [{0.server.name} ({0.server.id})]".format(message) - logging.chat_logger.info("{0.timestamp}: [{0.id}] {0.author.display_name} ({0.author.name}) ({0.author.id}) in {1}: {0.content} {0.embeds}".format(message, source)) + source = "Direct Message" if isinstance(message.channel, discord.DMChannel) else "#{0.channel.name} ({0.channel.id}) [{0.guild.name} ({0.guild.id})]".format(message) + logging.chat_logger.info("{0.created_at}: [{0.id}] {0.author.display_name} ({0.author.name}) ({0.author.id}) in {1}: {0.content} {0.embeds}".format(message, source)) # Server specific settings - if message.server is not None: + if message.guild is not None: try: - with open("data/server_data/{}/settings.json".format(message.server.id), 'r') as settings_file: + with open("data/server_data/{}/settings.json".format(message.guild.id), 'r') as settings_file: data = json.load(settings_file) except FileNotFoundError: # TODO: Handle/Fix, create new file with default settings @@ -172,9 +172,9 @@ async def on_message(message): global mention_spammers if message.author.id in mention_spammers: # TODO: Handle across different servers - if message.server.me.permissions_in(message.channel).kick_members: + if message.guild.me.permissions_in(message.channel).kick_members: # TODO: Check hierarchy, if able to kick - await client.send_message(message.author, "You were kicked from {} for spamming mentions".format(message.server)) + await client.send_message(message.author, "You were kicked from {} for spamming mentions".format(message.guild)) await client.kick(message.author) await client.send_message(message.channel, "{} has been kicked for spamming mentions".format(message.author)) else: @@ -188,10 +188,11 @@ async def on_message(message): return # Commands - await client.process_commands(message) + ctx = await client.get_context(message, cls = clients.Context) + await client.invoke(ctx) # Forward DMs - if message.channel.is_private and message.channel.user.id != clients.owner_id: + if isinstance(message.channel, discord.DMChannel) and message.channel.user.id != clients.owner_id: me = discord.utils.get(client.get_all_members(), id = clients.owner_id) if message.author == client.user: try: @@ -245,7 +246,7 @@ async def on_message(message): await client.send_message(message.channel, "Prefixes: {}".format(' '.join(['`"{}"`'.format(prefix) for prefix in prefixes]))) # help DM - elif message.content.lower() == "help" and message.channel.is_private: + elif message.content.lower() == "help" and isinstance(message.channel, discord.DMChannel): await clients.embed_reply(message, "Please see {}help".format(prefixes[0])) # :8ball: @@ -272,7 +273,7 @@ async def on_message(message): # Chatbot elif message.raw_mentions and client.user.id == message.raw_mentions[0] and message.clean_content.startswith('@'): # Handle @Harmonbot help - bot_name = message.channel.me.display_name if message.channel.is_private else message.server.me.display_name + bot_name = message.channel.me.display_name if isinstance(message.channel, discord.DMChannel) else message.guild.me.display_name if ' '.join(message.clean_content.split()[:2]).lower() == '@' + bot_name.lower() + " help": await clients.embed_reply(message, "Please see {}help".format(prefixes[0])) return @@ -293,10 +294,10 @@ async def on_error(event_method, *args, **kwargs): if type is discord.errors.Forbidden: for arg in args: if isinstance(arg, commands.context.Context): - print("Missing Permissions for #{0.channel.name} in {0.server.name}".format(arg.message)) + print("Missing Permissions for #{0.channel.name} in {0.guild.name}".format(arg.message)) return elif isinstance(arg, discord.Message): - print("Missing Permissions for #{0.channel.name} in {0.server.name}".format(arg)) + print("Missing Permissions for #{0.channel.name} in {0.guild.name}".format(arg)) return print('Ignoring exception in {}'.format(event_method), file = sys.stderr) traceback.print_exc() @@ -309,13 +310,13 @@ async def on_command_error(error, ctx): if isinstance(error, (errors.LichessUserNotFound)): return # handled with local error handler if isinstance(error, commands.errors.CommandInvokeError) and isinstance(error.original, youtube_dl.utils.DownloadError): return # handled with local error handler embed = discord.Embed(color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) if isinstance(error, (errors.NotServerOwner, errors.MissingPermissions)): # errors.NotOwner? embed.description = ":no_entry: You don't have permission to do that" elif isinstance(error, errors.MissingCapability): if "embed_links" in error.permissions: - await ctx.bot.send_message(ctx.message.channel, "I don't have permission to do that here\nI need the permission(s): " + ', '.join(error.permissions)) + await ctx.bot.send_message(ctx.channel, "I don't have permission to do that here\nI need the permission(s): " + ', '.join(error.permissions)) return embed.description = "I don't have permission to do that here\nI need the permission(s): " + ', '.join(error.permissions) elif isinstance(error, errors.PermittedVoiceNotConnected): @@ -335,7 +336,7 @@ async def on_command_error(error, ctx): if embed.description: await ctx.bot.send_message(ctx.message.channel, embed = embed) # check embed links permission elif isinstance(error, commands.errors.CommandInvokeError) and isinstance(error.original, (discord.errors.Forbidden)): - print("Missing Permissions for #{0.channel.name} in {0.server.name}".format(ctx.message)) + print("Missing Permissions for #{0.channel.name} in {0.guild.name}".format(ctx.message)) else: print("Ignoring exception in command {}".format(ctx.command), file = sys.stderr) traceback.print_exception(type(error), error, error.__traceback__, file = sys.stderr) diff --git a/Discord/clients.py b/Discord/clients.py index ef3acafce3..1d346a583b 100644 --- a/Discord/clients.py +++ b/Discord/clients.py @@ -26,9 +26,9 @@ version = "0.35.16" changelog = "https://discord.gg/a2rbZPu" stream_url = "https://www.twitch.tv/harmonbot" -owner_id = "115691005197549570" -listener_id = "180994984038760448" -cache_channel_id = "254051856219635713" +owner_id = 115691005197549570 +listener_id = 180994984038760448 +cache_channel_id = 254051856219635713 user_agent = "Discord Bot" fake_ip = "nice try" fake_location = "Fort Yukon, Alaska" @@ -83,172 +83,58 @@ class Bot(commands.Bot): - def reply(self, content, *args, **kwargs): - author = commands.bot._get_variable('_internal_author') - destination = commands.bot._get_variable('_internal_channel') - fmt = '{0.display_name}: {1}'.format(author, str(content)) # , -> : - extensions = ('delete_after',) - params = {k: kwargs.pop(k, None) for k in extensions} - coro = self.send_message(destination, fmt, *args, **kwargs) - return self._augmented_msg(coro, embed = kwargs.get("embed"), **params) # embed - - def embed_reply(self, content, *args, title = discord.Embed.Empty, title_url = discord.Embed.Empty, image_url = None, thumbnail_url = None, footer_text = discord.Embed.Empty, footer_icon_url = discord.Embed.Empty, timestamp = discord.Embed.Empty, fields = [], **kwargs): - author = commands.bot._get_variable('_internal_author') - destination = commands.bot._get_variable('_internal_channel') - embed = discord.Embed(description = str(content) if content else None, title = title, url = title_url, timestamp = timestamp, color = bot_color) - embed.set_author(name = author.display_name, icon_url = author.avatar_url or author.default_avatar_url) + def send_embed(self, destination, description = None, *, title = discord.Embed.Empty, title_url = discord.Embed.Empty, + author_name = "", author_url = discord.Embed.Empty, author_icon_url = discord.Embed.Empty, + image_url = None, thumbnail_url = None, footer_text = discord.Embed.Empty, footer_icon_url = discord.Embed.Empty, + timestamp = discord.Embed.Empty, fields = []): + embed = discord.Embed(title = title, url = title_url, timestamp = timestamp, color = bot_color) + embed.description = str(description) if description else discord.Embed.Empty + if author_name: embed.set_author(name = author_name, url = author_url, icon_url = author_icon_url) if image_url: embed.set_image(url = image_url) if thumbnail_url: embed.set_thumbnail(url = thumbnail_url) embed.set_footer(text = footer_text, icon_url = footer_icon_url) for field_name, field_value in fields: embed.add_field(name = field_name, value = field_value) - extensions = ('delete_after',) - params = {k: kwargs.pop(k, None) for k in extensions} - coro = self.send_message(destination, embed = embed, *args, **kwargs) - if destination.is_private or getattr(destination.permissions_for(destination.server.me), "embed_links", None): - return self._augmented_msg(coro, embed = embed, **params) - elif not (title or title_url or image_url or thumbnail_url or footer_text or timestamp): - fmt = '{0.display_name}: {1}'.format(author, str(content)) - coro = self.send_message(destination, fmt, *args, **kwargs) - return self._augmented_msg(coro, **params) - else: - permissions = ["embed_links"] - raise errors.MissingCapability(permissions) - - def say(self, *args, **kwargs): - destination = commands.bot._get_variable('_internal_channel') - extensions = ('delete_after',) - params = {k: kwargs.pop(k, None) for k in extensions} - coro = self.send_message(destination, *args, **kwargs) - return self._augmented_msg(coro, embed = kwargs.get("embed"), **params) # embed + return self.send_message(destination, embed = embed) - def embed_say(self, *args, title = discord.Embed.Empty, title_url = discord.Embed.Empty, image_url = None, thumbnail_url = None, footer_text = discord.Embed.Empty, footer_icon_url = discord.Embed.Empty, timestamp = discord.Embed.Empty, fields = [], **kwargs): - destination = commands.bot._get_variable('_internal_channel') - embed = discord.Embed(description = str(args[0]) if args[0] else None, title = title, url = title_url, timestamp = timestamp, color = bot_color) - # TODO: add author_name and author_icon_url - if image_url: embed.set_image(url = image_url) - if thumbnail_url: embed.set_thumbnail(url = thumbnail_url) - embed.set_footer(text = footer_text, icon_url = footer_icon_url) - for field_name, field_value in fields: - embed.add_field(name = field_name, value = field_value) - extensions = ('delete_after',) - params = {k: kwargs.pop(k, None) for k in extensions} - coro = self.send_message(destination, embed = embed, *args[1:], **kwargs) - return self._augmented_msg(coro, embed = embed, **params) + async def attempt_delete_message(self, message): + try: + await self.delete_message(message) + except (discord.errors.Forbidden, discord.errors.NotFound): + pass - def whisper(self, *args, **kwargs): - destination = commands.bot._get_variable('_internal_author') - extensions = ('delete_after',) - params = {k: kwargs.pop(k, None) for k in extensions} - coro = self.send_message(destination, *args, **kwargs) - return self._augmented_msg(coro, embed = kwargs.get("embed"), **params) # embed + # TODO: Case-Insenstivie commands + subcommands + +class Context(commands.Context): - def embed_whisper(self, *args, **kwargs): - destination = commands.bot._get_variable('_internal_author') - embed = discord.Embed(description = args[0], color = bot_color) - extensions = ('delete_after',) - params = {k: kwargs.pop(k, None) for k in extensions} - coro = self.send_message(destination, embed = embed, *args[1:], **kwargs) - return self._augmented_msg(coro, embed = embed, **params) + def embed_reply(self, *args, **kwargs): + return self.embed_say(*args, author_name = self.author.display_name, author_icon_url = self.author.avatar_url or self.author.default_avatar_url, **kwargs) - def send_embed(self, destination, content, title = discord.Embed.Empty, title_url = discord.Embed.Empty, image_url = None, thumbnail_url = None, footer_text = discord.Embed.Empty, footer_icon_url = discord.Embed.Empty, timestamp = discord.Embed.Empty, fields = []): - embed = discord.Embed(description = str(content) if content else None, title = title, url = title_url, timestamp = timestamp, color = bot_color) + def embed_say(self, description = None, *, title = discord.Embed.Empty, title_url = discord.Embed.Empty, + author_name = "", author_url = discord.Embed.Empty, author_icon_url = discord.Embed.Empty, + image_url = None, thumbnail_url = None, footer_text = discord.Embed.Empty, footer_icon_url = discord.Embed.Empty, + timestamp = discord.Embed.Empty, fields = [], **kwargs): + embed = discord.Embed(title = title, url = title_url, timestamp = timestamp, color = bot_color) + embed.description = str(description) if description else discord.Embed.Empty + if author_name: embed.set_author(name = author_name, url = author_url, icon_url = author_icon_url) if image_url: embed.set_image(url = image_url) if thumbnail_url: embed.set_thumbnail(url = thumbnail_url) embed.set_footer(text = footer_text, icon_url = footer_icon_url) for field_name, field_value in fields: embed.add_field(name = field_name, value = field_value) - return self.send_message(destination, embed = embed) - - async def _augmented_msg(self, coro, **kwargs): - msg = await coro - delete_after = kwargs.get('delete_after') - if delete_after is not None: - async def delete(): - await asyncio.sleep(delete_after) - await self.delete_message(msg) - - discord.compat.create_task(delete(), loop=self.loop) - # return embed - embed = kwargs.get("embed") - return msg, embed + if isinstance(self.channel, discord.DMChannel) or getattr(self.channel.permissions_for(self.channel.guild.me), "embed_links", None): + return self.send(embed = embed, **kwargs) + elif not (title or title_url or image_url or thumbnail_url or footer_text or footer_icon_url or timestamp or fields): + return self.reply(description) + # TODO: Check for everyone/here mentions + else: + raise errors.MissingCapability(["embed_links"]) - async def attempt_delete_message(self, message): - try: - await self.delete_message(message) - except discord.errors.Forbidden: - pass - except discord.errors.NotFound: - pass + def reply(self, content, *args, **kwargs): + return self.send("{0.display_name}: {1}".format(self.author, str(content)), **kwargs) - async def process_commands(self, message): - _internal_channel = message.channel - _internal_author = message.author - view = StringView(message.content) - if self._skip_check(message.author, self.user): - return - prefix = await self._get_prefix(message) - invoked_prefix = prefix - if not isinstance(prefix, (tuple, list)): - if not view.skip_string(prefix): - return - else: - invoked_prefix = discord.utils.find(view.skip_string, prefix) - if invoked_prefix is None: - return - invoker = view.get_word().lower() # case-insensitive commands - tmp = {'bot': self, 'invoked_with': invoker, 'message': message, 'view': view, 'prefix': invoked_prefix} - ctx = Context(**tmp) - del tmp - if invoker in self.commands: - command = self.commands[invoker] - self.dispatch('command', command, ctx) - try: - await command.invoke(ctx) - except CommandError as e: - ctx.command.dispatch_error(e, ctx) - else: - self.dispatch('command_completion', command, ctx) - elif invoker: - exc = CommandNotFound('Command "{}" is not found'.format(invoker)) - self.dispatch('command_error', exc, ctx) - -# Make Subcommands Case-Insensitive - -class Group(commands.GroupMixin, commands.Command): - - def __init__(self, **attrs): - self.invoke_without_command = attrs.pop('invoke_without_command', False) - super().__init__(**attrs) - - async def invoke(self, ctx): - early_invoke = not self.invoke_without_command - if early_invoke: - await self.prepare(ctx) - view = ctx.view - previous = view.index - view.skip_ws() - trigger = view.get_word().lower() # case-insensitive subcommands - if trigger: - ctx.subcommand_passed = trigger - ctx.invoked_subcommand = self.commands.get(trigger, None) - if early_invoke: - injected = commands.core.inject_context(ctx, self.callback) - await injected(*ctx.args, **ctx.kwargs) - if trigger and ctx.invoked_subcommand: - ctx.invoked_with = trigger - await ctx.invoked_subcommand.invoke(ctx) - elif not early_invoke: - # undo the trigger parsing - view.index = previous - view.previous = previous - await super().invoke(ctx) - -def group(name=None, **attrs): - return commands.command(name=name, cls=Group, **attrs) - -commands.Group = Group -commands.group = group + def whisper(self, *args, **kwargs): + return self.author.send(*args, **kwargs) # Create Folders @@ -265,10 +151,10 @@ def group(name=None, **attrs): def get_prefix(bot, message): with open("data/prefixes.json", 'r') as prefixes_file: all_prefixes = json.load(prefixes_file) - if message.channel.is_private: + if isinstance(message.channel, discord.DMChannel): prefixes = all_prefixes.get(message.channel.id, None) else: - prefixes = all_prefixes.get(message.server.id, None) + prefixes = all_prefixes.get(message.guild.id, None) return prefixes if prefixes else '!' @@ -284,7 +170,7 @@ def get_prefix(bot, message): async def _update_discord_bots_stats(): async with aiohttp_session.post("https://bots.discord.pw/api/bots/{}/stats".format(client.user.id), headers = {"authorization": credentials.discord_bots_api_token, "content-type": "application/json"}, - data = json.dumps({"server_count": len(client.servers)})) as resp: + data = json.dumps({"server_count": len(client.guilds)})) as resp: # Change to check for 200? if resp.status in (500, 502, 504, 522): return "Error: {}".format(resp.status) @@ -307,10 +193,10 @@ async def on_server_remove(server): await _update_discord_bots_stats() @client.listen() -async def on_command(command, ctx): +async def on_command(ctx): global session_commands_executed, session_commands_usage session_commands_executed += 1 - session_commands_usage[command.name] = session_commands_usage.get(command.name, 0) + 1 + session_commands_usage[ctx.command.name] = session_commands_usage.get(ctx.command.name, 0) + 1 # Download FFMPEG @@ -344,7 +230,7 @@ async def random_game_status(): "music", "Google Ultron", "not enough space here to", "the meaning of life is", "with the NSA", "with neural networks", "with RSS Bot", "with Data", "with Harmon", " "] - me = discord.utils.find(lambda s: s != None, client.servers).me + me = discord.utils.find(lambda s: s != None, client.guilds).me if not me: return elif not me.game: @@ -355,7 +241,7 @@ async def random_game_status(): await client.change_presence(game = updated_game) async def set_streaming_status(client): - me = discord.utils.get(client.servers).me + me = discord.utils.get(client.guilds).me if not me: return elif not me.game: diff --git a/Discord/cogs/audio.py b/Discord/cogs/audio.py index d1ac445b18..c49e0cfaac 100644 --- a/Discord/cogs/audio.py +++ b/Discord/cogs/audio.py @@ -26,7 +26,7 @@ def __init__(self, bot): self.bot.add_command(command) self.audio.add_command(command) - @commands.group(aliases = ["yt", "youtube", "soundcloud", "voice", "stream", "play", "playlist", "spotify", "budio", "music", "download"], description = "Supports [these sites](https://rg3.github.io/youtube-dl/supportedsites.html) and Spotify", pass_context = True, invoke_without_command = True, no_pm = True) + @commands.group(aliases = ["yt", "youtube", "soundcloud", "voice", "stream", "play", "playlist", "spotify", "budio", "music", "download"], description = "Supports [these sites](https://rg3.github.io/youtube-dl/supportedsites.html) and Spotify", invoke_without_command = True, no_pm = True) @checks.is_voice_connected() @checks.not_forbidden() async def audio(self, ctx, *, song : str = ""): #elif options[0] == "full": @@ -36,20 +36,21 @@ async def audio(self, ctx, *, song : str = ""): #elif options[0] == "full": For cleanup of audio commands, the Manage Messages permission is required ''' if not song: - await self.bot.embed_reply(":grey_question: What would you like to play?") + await ctx.embed_reply(":grey_question: What would you like to play?") return if "playlist" in song: - await self.players[ctx.message.server.id].add_playlist(song, ctx.message.author, ctx.message.timestamp) + await self.players[ctx.guild.id].add_playlist(song, ctx.author, ctx.message.created_at) return if "spotify" in song: song = await self.spotify_to_youtube(song) if not song: - await self.bot.embed_reply(":warning: Error") + await ctx.embed_reply(":warning: Error") return - response, embed = await self.bot.embed_reply(":cd: Loading..") + response = await ctx.embed_reply(":cd: Loading..") + embed = response.embeds[0] stream = ctx.invoked_with == "stream" try: - title, url = await self.players[ctx.message.server.id].add_song(song, ctx.message.author, ctx.message.timestamp, stream = stream) + title, url = await self.players[ctx.guild.id].add_song(song, ctx.author, ctx.message.created_at, stream = stream) except Exception as e: embed.description = ":warning: Error loading `{}`\n`{}: {}`".format(song, type(e).__name__, e) if len(embed.description) > 2048: embed.description = embed.description[:2044] + "...`" @@ -61,65 +62,65 @@ async def audio(self, ctx, *, song : str = ""): #elif options[0] == "full": await self.bot.edit_message(response, embed = embed) await self.bot.attempt_delete_message(ctx.message) - @commands.command(aliases = ["summon", "move"], pass_context = True, no_pm = True) + @commands.command(aliases = ["summon", "move"], no_pm = True) @checks.is_permitted() async def join(self, ctx, *channel : str): '''Get me to join a voice channel''' # TODO: Permit all when not in voice channel? - if ctx.message.server.id not in self.players: - self.players[ctx.message.server.id] = audio_player.AudioPlayer(self.bot, ctx.message.channel) + if ctx.guild.id not in self.players: + self.players[ctx.guild.id] = audio_player.AudioPlayer(self.bot, ctx.channel) try: - moved = await self.players[ctx.message.server.id].join_channel(ctx.message.author, channel) + moved = await self.players[ctx.guild.id].join_channel(ctx.author, channel) except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: Voice channel not found", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: Voice channel not found", footer_text = "In response to: {}".format(ctx.message.content)) except concurrent.futures._base.TimeoutError: - await self.bot.embed_reply(":no_entry: Error joining the voice channel\nPlease check that I'm permitted to join", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: Error joining the voice channel\nPlease check that I'm permitted to join", footer_text = "In response to: {}".format(ctx.message.content)) else: - await self.bot.embed_reply(":arrow_right_hook: I've moved to the voice channel" if moved else ":headphones: I've joined the voice channel") + await ctx.embed_reply(":arrow_right_hook: I've moved to the voice channel" if moved else ":headphones: I've joined the voice channel") await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def leave(self, ctx): '''Tell me to leave the voice channel''' - if (await self.players[ctx.message.server.id].leave_channel()): - await self.bot.embed_reply(":door: I've left the voice channel") - del self.players[ctx.message.server.id] + if (await self.players[ctx.guild.id].leave_channel()): + await ctx.embed_reply(":door: I've left the voice channel") + del self.players[ctx.guild.id] await self.bot.attempt_delete_message(ctx.message) - ## await self.bot.embed_reply("The leave command is currently disabled right now, due to an issue/bug with Discord.") + ## await ctx.embed_reply("The leave command is currently disabled right now, due to an issue/bug with Discord.") - @commands.command(pass_context = True, aliases = ["stop"], no_pm = True) + @commands.command(aliases = ["stop"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def pause(self, ctx): '''Pause the current song''' try: - self.players[ctx.message.server.id].pause() + self.players[ctx.guild.id].pause() except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There is no song to pause") + await ctx.embed_reply(":no_entry: There is no song to pause") except errors.AudioAlreadyDone: - await self.bot.embed_reply(":no_entry: The song is already paused") + await ctx.embed_reply(":no_entry: The song is already paused") else: - await self.bot.embed_reply(":pause_button: Paused song") + await ctx.embed_reply(":pause_button: Paused song") await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, aliases = ["start"], no_pm = True) + @commands.command(aliases = ["start"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def resume(self, ctx): '''Resume the current song''' try: - self.players[ctx.message.server.id].resume() + self.players[ctx.guild.id].resume() except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There is no song to resume") + await ctx.embed_reply(":no_entry: There is no song to resume") except errors.AudioAlreadyDone: - await self.bot.embed_reply(":no_entry: The song is already playing") + await ctx.embed_reply(":no_entry: The song is already playing") else: - await self.bot.embed_reply(":play_pause: Resumed song") + await ctx.embed_reply(":play_pause: Resumed song") await self.bot.attempt_delete_message(ctx.message) - @commands.group(pass_context = True, aliases = ["next", "remove"], no_pm = True, invoke_without_command = True) + @commands.group(aliases = ["next", "remove"], no_pm = True, invoke_without_command = True) @checks.not_forbidden() @checks.is_voice_connected() async def skip(self, ctx, *, number : int = 0): @@ -130,38 +131,38 @@ async def skip(self, ctx, *, number : int = 0): Otherwise, a majority vote of the people in the voice channel is required ''' # TODO: Implement override permission - player = self.players[ctx.message.server.id] - if ctx.message.author.id in (ctx.message.server.owner.id, clients.owner_id) or checks.is_permitted_check(ctx): + player = self.players[ctx.guild.id] + if ctx.author.id in (ctx.guild.owner.id, clients.owner_id) or checks.is_permitted_check(ctx): if number: try: song = await player.skip_specific(number) except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There's not that many songs in the queue", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: There's not that many songs in the queue", footer_text = "In response to: {}".format(ctx.message.content)) else: - await self.bot.embed_reply(":put_litter_in_its_place: Skipped #{} in the queue: `{}`".format(number, song["info"]["title"])) + await ctx.embed_reply(":put_litter_in_its_place: Skipped #{} in the queue: `{}`".format(number, song["info"]["title"])) del song else: try: player.skip() except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There is no song to skip") + await ctx.embed_reply(":no_entry: There is no song to skip") else: - await self.bot.embed_reply(":next_track: Song skipped") + await ctx.embed_reply(":next_track: Song skipped") # TODO: Include title of skipped song - elif ctx.message.author in self.bot.voice_client_in(ctx.message.server).channel.voice_members: + elif ctx.author in self.bot.voice_client_in(ctx.guild).channel.voice_members: try: - vote = player.vote_skip(ctx.message.author) + vote = player.vote_skip(ctx.author) except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There is no song to skip") + await ctx.embed_reply(":no_entry: There is no song to skip") except errors.AudioAlreadyDone: - await self.bot.embed_reply(":no_entry: You've already voted to skip. Skips: {}/{}".format(len(player.skip_votes), player.skip_votes_required)) + await ctx.embed_reply(":no_entry: You've already voted to skip. Skips: {}/{}".format(len(player.skip_votes), player.skip_votes_required)) else: - await self.bot.embed_reply(":white_check_mark: You voted to skip the current song\n{}".format("Skips: {}/{}".format(vote, player.skip_votes_required) if vote else ":next_track: Song skipped")) + await ctx.embed_reply(":white_check_mark: You voted to skip the current song\n{}".format("Skips: {}/{}".format(vote, player.skip_votes_required) if vote else ":next_track: Song skipped")) else: - await self.bot.embed_reply(":no_entry: You're not even listening!", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: You're not even listening!", footer_text = "In response to: {}".format(ctx.message.content)) await self.bot.attempt_delete_message(ctx.message) - @skip.command(name = "to", pass_context = True, no_pm = True) + @skip.command(name = "to", no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def skip_to(self, ctx, number : int): @@ -170,27 +171,28 @@ async def skip_to(self, ctx, number : int): Skips every song before number ''' try: - songs = await self.players[ctx.message.server.id].skip_to_song(number) + songs = await self.players[ctx.guild.id].skip_to_song(number) except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There aren't that many songs in the queue", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: There aren't that many songs in the queue", footer_text = "In response to: {}".format(ctx.message.content)) else: - await self.bot.embed_reply(":put_litter_in_its_place: Skipped to #{} in the queue".format(number)) + await ctx.embed_reply(":put_litter_in_its_place: Skipped to #{} in the queue".format(number)) del songs await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, aliases = ["repeat"], no_pm = True) + @commands.command(aliases = ["repeat"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def replay(self, ctx): '''Repeat the current song''' # TODO: Add restart alias? - response, embed = await self.bot.embed_reply(":repeat_one: Restarting song..") - replayed = await self.players[ctx.message.server.id].replay() + response = await ctx.embed_reply(":repeat_one: Restarting song..") + embed = response.embeds[0] + replayed = await self.players[ctx.guild.id].replay() embed.description = ":repeat_one: Restarted song" if replayed else ":no_entry: There is nothing to replay" await self.bot.edit_message(response, embed = embed) await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def insert(self, ctx, position_number : int, *, song : str): @@ -198,11 +200,12 @@ async def insert(self, ctx, position_number : int, *, song : str): if "spotify" in song: song = await self.spotify_to_youtube(song) if not song: - await self.bot.embed_reply(":warning: Error") + await ctx.embed_reply(":warning: Error") return - response, embed = await self.bot.embed_reply(":cd: Loading..") + response = await ctx.embed_reply(":cd: Loading..") + embed = response.embeds[0] try: - title = await self.players[ctx.message.server.id].insert_song(song, ctx.message.author, ctx.message.timestamp, position_number) + title = await self.players[ctx.guild.id].insert_song(song, ctx.author, ctx.message.created_at, position_number) except Exception as e: embed.description = ":warning: Error loading `{}`\n`{}: {}`".format(song, type(e).__name__, e) if len(embed.description) > 2048: embed.description = embed.description[:2044] + "...`" @@ -212,27 +215,28 @@ async def insert(self, ctx, position_number : int, *, song : str): await self.bot.edit_message(response, embed = embed) await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, aliases = ["clear"], no_pm = True) + @commands.command(aliases = ["clear"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def empty(self, ctx): '''Empty the queue''' - await self.players[ctx.message.server.id].empty_queue() - await self.bot.embed_reply(":wastebasket: Emptied queue") + await self.players[ctx.guild.id].empty_queue() + await ctx.embed_reply(":wastebasket: Emptied queue") await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def shuffle(self, ctx): '''Shuffle the queue''' - response, embed = await self.bot.embed_reply(":twisted_rightwards_arrows: Shuffling..") - await self.players[ctx.message.server.id].shuffle_queue() + response = await ctx.embed_reply(":twisted_rightwards_arrows: Shuffling..") + embed = response.embeds[0] + await self.players[ctx.guild.id].shuffle_queue() embed.description = ":twisted_rightwards_arrows: Shuffled songs" await self.bot.edit_message(response, embed = embed) await self.bot.attempt_delete_message(ctx.message) - @audio.command(name = "random", aliases = ["top"], pass_context = True, no_pm = True) + @audio.command(name = "random", aliases = ["top"], no_pm = True) @checks.not_forbidden() @checks.is_voice_connected() async def audio_random(self, ctx): @@ -241,9 +245,10 @@ async def audio_random(self, ctx): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() song = random.choice([video["id"] for video in data["items"]]) - response, embed = await self.bot.embed_reply(":cd: Loading..") + response = await ctx.embed_reply(":cd: Loading..") + embed = response.embeds[0] try: - title, url = await self.players[ctx.message.server.id].add_song(song, ctx.message.author, ctx.message.timestamp) + title, url = await self.players[ctx.guild.id].add_song(song, ctx.author, ctx.message.created_at) except Exception as e: embed.description = ":warning: Error loading `{}`\n`{}: {}`".format(song, type(e).__name__, e) else: @@ -256,7 +261,7 @@ async def audio_random(self, ctx): embed.description = ":warning: Error loading `{}`".format(song) await self.bot.edit_message(response, embed = embed) - @commands.group(pass_context = True, no_pm = True, invoke_without_command = True) + @commands.group(no_pm = True, invoke_without_command = True) @checks.is_permitted() @checks.is_voice_connected() async def radio(self, ctx): @@ -264,54 +269,54 @@ async def radio(self, ctx): Radio station based on the current song No input to turn on/off ''' - if self.players[ctx.message.server.id].radio_flag: - self.players[ctx.message.server.id].radio_off() - await self.bot.embed_reply(":stop_sign: Turned radio off") - elif (await self.players[ctx.message.server.id].radio_on(ctx.message.author, ctx.message.timestamp)) is False: - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first", footer_text = "In response to: {}".format(ctx.message.content)) + if self.players[ctx.guild.id].radio_flag: + self.players[ctx.guild.id].radio_off() + await ctx.embed_reply(":stop_sign: Turned radio off") + elif (await self.players[ctx.guild.id].radio_on(ctx.author, ctx.message.created_at)) is False: + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first", footer_text = "In response to: {}".format(ctx.message.content)) await self.bot.attempt_delete_message(ctx.message) - @radio.command(name = "on", pass_context = True, aliases = ["start"], no_pm = True) + @radio.command(name = "on", aliases = ["start"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def radio_on(self, ctx): '''Turn radio on''' - if self.players[ctx.message.server.id].radio_flag: - await self.bot.embed_reply(":no_entry: Radio is already on") - elif (await self.players[ctx.message.server.id].radio_on(ctx.message.author, ctx.message.timestamp)) is False: - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first", footer_text = "In response to: {}".format(ctx.message.content)) + if self.players[ctx.guild.id].radio_flag: + await ctx.embed_reply(":no_entry: Radio is already on") + elif (await self.players[ctx.guild.id].radio_on(ctx.author, ctx.message.created_at)) is False: + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first", footer_text = "In response to: {}".format(ctx.message.content)) await self.bot.attempt_delete_message(ctx.message) - @radio.command(name = "off", pass_context = True, aliases = ["stop"], no_pm = True) + @radio.command(name = "off", aliases = ["stop"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def radio_off(self, ctx): '''Turn radio off''' - if self.players[ctx.message.server.id].radio_flag: - self.players[ctx.message.server.id].radio_off() - await self.bot.embed_reply(":stop_sign: Turned radio off") + if self.players[ctx.guild.id].radio_flag: + self.players[ctx.guild.id].radio_off() + await ctx.embed_reply(":stop_sign: Turned radio off") await self.bot.attempt_delete_message(ctx.message) else: - await self.bot.embed_reply(":no_entry: Radio is already off") + await ctx.embed_reply(":no_entry: Radio is already off") - @commands.command(aliases = ["set_text"], pass_context = True, no_pm = True) + @commands.command(aliases = ["set_text"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def settext(self, ctx): '''Set text channel for messages''' - self.players[ctx.message.server.id].text_channel = ctx.message.channel - await self.bot.embed_reply(":writing_hand::skin-tone-2: Changed text channel") + self.players[ctx.guild.id].text_channel = ctx.channel + await ctx.embed_reply(":writing_hand::skin-tone-2: Changed text channel") await self.bot.attempt_delete_message(ctx.message) - @commands.group(pass_context = True, no_pm = True, invoke_without_command = True) + @commands.group(no_pm = True, invoke_without_command = True) @checks.is_permitted() @checks.is_voice_connected() async def tts(self, ctx, *, message : str): '''Text to speech''' - if not (await self.players[ctx.message.server.id].play_tts(message, ctx.message.author, timestamp = ctx.message.timestamp)): - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first") + if not (await self.players[ctx.guild.id].play_tts(message, ctx.author, timestamp = ctx.message.created_at)): + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first") - @tts.command(name = "options", pass_context = True, no_pm = True) + @tts.command(name = "options", no_pm = True) @checks.not_forbidden() @checks.is_voice_connected() async def tts_options(self, ctx, amplitude: int, pitch: int, speed: int, word_gap: int, voice: str, *, message : str): @@ -331,96 +336,96 @@ async def tts_options(self, ctx, amplitude: int, pitch: int, speed: int, word_ga if amplitude > 1000: amplitude = 1000 if speed > 9000: speed = 9000 if word_gap > 1000: word_gap = 1000 - if not (await self.players[ctx.message.server.id].play_tts(message, ctx.message.author, timestamp = ctx.message.timestamp, amplitude = amplitude, pitch = pitch, speed = speed, word_gap = word_gap, voice = voice)): - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first") + if not (await self.players[ctx.guild.id].play_tts(message, ctx.author, timestamp = ctx.message.created_at, amplitude = amplitude, pitch = pitch, speed = speed, word_gap = word_gap, voice = voice)): + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first") - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def file(self, ctx, *, filename : str = ""): '''Play an audio file''' - if not (await self.players[ctx.message.server.id].play_file(filename, ctx.message.author, ctx.message.timestamp)): - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first") + if not (await self.players[ctx.guild.id].play_file(filename, ctx.author, ctx.message.created_at)): + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first") - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.not_forbidden() @checks.is_voice_connected() async def files(self, ctx): '''List existing audio files''' - await self.bot.embed_reply(self.players[ctx.message.server.id].list_files()) + await ctx.embed_reply(self.players[ctx.guild.id].list_files()) - @commands.group(pass_context = True, no_pm = True, invoke_without_command = True) + @commands.group(no_pm = True, invoke_without_command = True) @checks.is_permitted() @checks.is_voice_connected() async def library(self, ctx): '''Start/stop playing songs from my library''' - if self.players[ctx.message.server.id].library_flag: - self.players[ctx.message.server.id].stop_library() - await self.bot.embed_reply(":stop_sign: Stopped playing songs from my library") - elif not (await self.players[ctx.message.server.id].play_library(ctx.message.author, ctx.message.timestamp)): - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first", footer_text = "In response to: {}".format(ctx.message.content)) + if self.players[ctx.guild.id].library_flag: + self.players[ctx.guild.id].stop_library() + await ctx.embed_reply(":stop_sign: Stopped playing songs from my library") + elif not (await self.players[ctx.guild.id].play_library(ctx.author, ctx.message.created_at)): + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first", footer_text = "In response to: {}".format(ctx.message.content)) await self.bot.attempt_delete_message(ctx.message) - @library.command(name = "play", aliases = ["start"], pass_context = True, no_pm = True) + @library.command(name = "play", aliases = ["start"], no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def library_play(self, ctx): '''Start playing songs from my library''' - if self.players[ctx.message.server.id].library_flag: - await self.bot.embed_reply(":no_entry: I'm already playing songs from my library") - elif not (await self.players[ctx.message.server.id].play_library(ctx.message.author, ctx.message.timestamp)): - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first") + if self.players[ctx.guild.id].library_flag: + await ctx.embed_reply(":no_entry: I'm already playing songs from my library") + elif not (await self.players[ctx.guild.id].play_library(ctx.author, ctx.message.created_at)): + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first") - @library.command(name = "stop", pass_context = True, no_pm = True) + @library.command(name = "stop", no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def library_stop(self, ctx): '''Stop playing songs from my library''' - if self.players[ctx.message.server.id].library_flag: - self.players[ctx.message.server.id].stop_library() - await self.bot.embed_reply(":stop_sign: Stopped playing songs from my library") + if self.players[ctx.guild.id].library_flag: + self.players[ctx.guild.id].stop_library() + await ctx.embed_reply(":stop_sign: Stopped playing songs from my library") else: - await self.bot.embed_reply(":no_entry: Not currently playing songs from my library", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: Not currently playing songs from my library", footer_text = "In response to: {}".format(ctx.message.content)) await self.bot.attempt_delete_message(ctx.message) - @library.command(name = "song", pass_context = True, no_pm = True) + @library.command(name = "song", no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def library_song(self, ctx, *, filename : str = ""): '''Play a song from my library''' - if not (await self.players[ctx.message.server.id].play_from_library(filename, ctx.message.author, ctx.message.timestamp)): - await self.bot.embed_reply(":warning: Something else is already playing\nPlease stop it first") + if not (await self.players[ctx.guild.id].play_from_library(filename, ctx.author, ctx.message.created_at)): + await ctx.embed_reply(":warning: Something else is already playing\nPlease stop it first") - @library.command(name = "files", pass_context = True, no_pm = True) # enable for DMs? + @library.command(name = "files", no_pm = True) # enable for DMs? @checks.not_forbidden() @checks.is_voice_connected() async def library_files(self, ctx): '''List song files in the library''' - if not ctx.message.channel.is_private: - await self.bot.embed_reply("Check your DMs") + if not isinstance(ctx.channel, discord.DMChannel): + await ctx.embed_reply("Check your DMs") output = "```" - for filename in self.players[ctx.message.server.id].library_files: + for filename in self.players[ctx.guild.id].library_files: if len(output) + len(filename) > 1997: # 2000 - 3 await self.bot.whisper(output[:-2] + "```") output = "```" + filename + ", " else: output += filename + ", " - @library.command(name = "search", pass_context = True, no_pm = True) + @library.command(name = "search", no_pm = True) @checks.not_forbidden() @checks.is_voice_connected() async def library_search(self, ctx, *, search : str): '''Search songs in the library''' - results = [filename for filename in self.players[ctx.message.server.id].library_files if search.lower() in filename.lower()] + results = [filename for filename in self.players[ctx.guild.id].library_files if search.lower() in filename.lower()] if not results: - await self.bot.embed_reply(":no_entry: No songs matching that search found") + await ctx.embed_reply(":no_entry: No songs matching that search found") return try: - await self.bot.embed_reply("```\n{}\n```".format(", ".join(results))) + await ctx.embed_reply("```\n{}\n```".format(", ".join(results))) except discord.errors.HTTPException: - await self.bot.embed_reply(":no_entry: Too many results\nTry a more specific search") + await ctx.embed_reply(":no_entry: Too many results\nTry a more specific search") - @commands.group(pass_context = True, no_pm = True, invoke_without_command = True) + @commands.group(no_pm = True, invoke_without_command = True) @checks.is_permitted() @checks.is_voice_connected() async def volume(self, ctx, *, volume_setting : float = None): @@ -430,21 +435,21 @@ async def volume(self, ctx, *, volume_setting : float = None): ''' if volume_setting is None: try: - await self.bot.embed_reply(":sound: Current volume: {:g}".format(self.players[ctx.message.server.id].get_volume())) + await ctx.embed_reply(":sound: Current volume: {:g}".format(self.players[ctx.guild.id].get_volume())) except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: There's nothing playing right now", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: There's nothing playing right now", footer_text = "In response to: {}".format(ctx.message.content)) else: try: - self.players[ctx.message.server.id].set_volume(volume_setting) + self.players[ctx.guild.id].set_volume(volume_setting) except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: Couldn't change volume\nThere's nothing playing right now", footer_text = "In response to: {}".format(ctx.message.content)) + await ctx.embed_reply(":no_entry: Couldn't change volume\nThere's nothing playing right now", footer_text = "In response to: {}".format(ctx.message.content)) else: if volume_setting > 2000: volume_setting = 2000 elif volume_setting < 0: volume_setting = 0 - await self.bot.embed_reply(":sound: Set volume to {:g}".format(volume_setting)) + await ctx.embed_reply(":sound: Set volume to {:g}".format(volume_setting)) await self.bot.attempt_delete_message(ctx.message) - @volume.command(name = "default", pass_context = True, no_pm = True) + @volume.command(name = "default", no_pm = True) @checks.is_permitted() @checks.is_voice_connected() async def volume_default(self, ctx, *, volume_setting : float = None): @@ -453,90 +458,90 @@ async def volume_default(self, ctx, *, volume_setting : float = None): volume_setting: 0 - 2000 ''' if volume_setting is None: - await self.bot.embed_reply(":sound: Current default volume: {:g}".format(self.players[ctx.message.server.id].default_volume)) + await ctx.embed_reply(":sound: Current default volume: {:g}".format(self.players[ctx.guild.id].default_volume)) else: if volume_setting > 2000: volume_setting = 2000 elif volume_setting < 0: volume_setting = 0 - self.players[ctx.message.server.id].default_volume = volume_setting - await self.bot.embed_reply(":sound: Set default volume to {:g}".format(volume_setting)) + self.players[ctx.guild.id].default_volume = volume_setting + await ctx.embed_reply(":sound: Set default volume to {:g}".format(volume_setting)) await self.bot.attempt_delete_message(ctx.message) - @commands.group(aliases = ["current"], pass_context = True, no_pm = True, invoke_without_command = True) + @commands.group(aliases = ["current"], no_pm = True, invoke_without_command = True) @checks.is_voice_connected() @checks.not_forbidden() async def playing(self, ctx): '''See the currently playing song''' try: - embed = self.players[ctx.message.server.id].current_embed() + embed = self.players[ctx.guild.id].current_embed() except errors.AudioNotPlaying: - await self.bot.embed_reply(":speaker: There is no song currently playing") + await ctx.embed_reply(":speaker: There is no song currently playing") else: - embed.set_author(name = ctx.message.author.display_name, icon_url = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url) + embed.set_author(name = ctx.author.display_name, icon_url = ctx.author.avatar_url or ctx.author.default_avatar_url) await self.bot.say(embed = embed) await self.bot.attempt_delete_message(ctx.message) - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.is_voice_connected() @checks.not_forbidden() async def queue(self, ctx): '''See the current queue''' - embed = self.players[ctx.message.server.id].queue_embed() - embed.set_author(name = ctx.message.author.display_name, icon_url = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url) + embed = self.players[ctx.guild.id].queue_embed() + embed.set_author(name = ctx.author.display_name, icon_url = ctx.author.avatar_url or ctx.author.default_avatar_url) await self.bot.say(embed = embed) await self.bot.attempt_delete_message(ctx.message) # Voice Input - @commands.group(pass_context = True, invoke_without_command = True, hidden = True) + @commands.group(invoke_without_command = True, hidden = True) @checks.is_voice_connected() @checks.is_permitted() async def listen(self, ctx): - if self.players[ctx.message.server.id].listener: - await self.players[ctx.message.server.id].stop_listening() - elif not (await self.players[ctx.message.server.id].start_listening()): - await self.bot.embed_reply(":warning: Something else is already playing. Please stop it first.") + if self.players[ctx.guild.id].listener: + await self.players[ctx.guild.id].stop_listening() + elif not (await self.players[ctx.guild.id].start_listening()): + await ctx.embed_reply(":warning: Something else is already playing. Please stop it first.") - @listen.command(name = "start", aliases = ["on"], pass_context = True) + @listen.command(name = "start", aliases = ["on"]) @checks.is_voice_connected() @checks.is_permitted() async def listen_start(self, ctx): - if self.players[ctx.message.server.id].listener: - await self.bot.embed_reply(":no_entry: I'm already listening") - elif not (await self.players[ctx.message.server.id].start_listening()): - await self.bot.embed_reply(":warning: Something else is already playing. Please stop it first.") + if self.players[ctx.guild.id].listener: + await ctx.embed_reply(":no_entry: I'm already listening") + elif not (await self.players[ctx.guild.id].start_listening()): + await ctx.embed_reply(":warning: Something else is already playing. Please stop it first.") - @listen.command(name = "stop", aliases = ["off"], pass_context = True) + @listen.command(name = "stop", aliases = ["off"]) @checks.is_voice_connected() @checks.is_permitted() async def listen_stop(self, ctx): - if self.players[ctx.message.server.id].listener: - await self.players[ctx.message.server.id].stop_listening() + if self.players[ctx.guild.id].listener: + await self.players[ctx.guild.id].stop_listening() else: - await self.bot.embed_reply(":no_entry: I'm not listening") + await ctx.embed_reply(":no_entry: I'm not listening") - @listen.command(name = "once", pass_context = True) + @listen.command(name = "once") @checks.is_voice_connected() @checks.is_permitted() async def listen_once(self, ctx): - if self.players[ctx.message.server.id].listener: - await self.bot.embed_reply(":no_entry: I'm already listening") - elif (await self.players[ctx.message.server.id].listen_once()) is False: - await self.bot.embed_reply(":warning: Something else is already playing. Please stop it first.") + if self.players[ctx.guild.id].listener: + await ctx.embed_reply(":no_entry: I'm already listening") + elif (await self.players[ctx.guild.id].listen_once()) is False: + await ctx.embed_reply(":warning: Something else is already playing. Please stop it first.") - @listen.command(name = "finish", pass_context = True) + @listen.command(name = "finish") @checks.is_voice_connected() @checks.is_permitted() async def listen_finish(self, ctx): - if self.players[ctx.message.server.id].listener: - await self.players[ctx.message.server.id].finish_listening() + if self.players[ctx.guild.id].listener: + await self.players[ctx.guild.id].finish_listening() else: - await self.bot.embed_reply(":no_entry: I'm not listening") + await ctx.embed_reply(":no_entry: I'm not listening") - @listen.command(name = "process", pass_context = True) + @listen.command(name = "process") @checks.is_voice_connected() @checks.is_permitted() async def listen_process(self, ctx): - await self.players[ctx.message.server.id].process_listen() + await self.players[ctx.guild.id].process_listen() # Utility diff --git a/Discord/cogs/discord.py b/Discord/cogs/discord.py index 34d20b3641..556c96489b 100644 --- a/Discord/cogs/discord.py +++ b/Discord/cogs/discord.py @@ -21,7 +21,7 @@ def __init__(self, bot): # Do Stuff - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.has_permissions_and_capability(manage_roles = True) async def addrole(self, ctx, member : str, *, role : str): # member : discord.Member ''' @@ -32,14 +32,14 @@ async def addrole(self, ctx, member : str, *, role : str): # member : discord.Me if not member: await self.bot.embed_reply(":no_entry: Member not found") return - role = discord.utils.find(lambda r: utilities.remove_symbols(r.name).startswith(role), ctx.message.server.roles) + role = discord.utils.find(lambda r: utilities.remove_symbols(r.name).startswith(role), ctx.guild.roles) if not role: await self.bot.embed_reply(":no_entry: Role not found") return await self.bot.add_roles(member, role) await self.bot.embed_reply("I gave the role, {0}, to {1}".format(role, member)) - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.has_permissions_and_capability(manage_channels = True) async def channel(self, ctx, *options : str): ''' @@ -49,68 +49,68 @@ async def channel(self, ctx, *options : str): ''' if options: if options[0] == "voice": - await self.bot.create_channel(ctx.message.server, options[1], type = "voice") + await self.bot.create_channel(ctx.guild, options[1], type = "voice") elif options[0] == "text": - await self.bot.create_channel(ctx.message.server, options[1], type = "text") + await self.bot.create_channel(ctx.guild, options[1], type = "text") else: - await self.bot.create_channel(ctx.message.server, options[0], type = "text") + await self.bot.create_channel(ctx.guild, options[0], type = "text") - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.has_permissions_and_capability(manage_roles = True) async def createrole(self, ctx, *, name : str = ""): '''Creates a role''' - await self.bot.create_role(ctx.message.server, name = name) + await self.bot.create_role(ctx.guild, name = name) - @commands.group(pass_context = True, aliases = ["purge", "clean"], invoke_without_command = True) + @commands.group(aliases = ["purge", "clean"], invoke_without_command = True) @checks.dm_or_has_permissions_and_capability(manage_messages = True) async def delete(self, ctx, number : int, *, user : str = ""): ''' Delete messages If used in a DM, delete deletes of Harmonbot's messages ''' - if ctx.message.channel.is_private: + if isinstance(ctx.channel, discord.DMChannel): await self.bot.delete_number(ctx, number, check = lambda m: m.author == self.bot.user, delete_command = False) elif not user: await self.bot.attempt_delete_message(ctx.message) - await self.bot.purge_from(ctx.message.channel, limit = number) + await self.bot.purge_from(ctx.channel, limit = number) elif user: await self.delete_number(ctx, number, check = lambda m: m.author.name == user) - @delete.command(name = "attachments", aliases = ["images"], pass_context = True) + @delete.command(name = "attachments", aliases = ["images"]) @checks.has_permissions_and_capability(manage_messages = True) async def delete_attachments(self, ctx, number : int): '''Deletes the most recent messages with attachments''' await self.delete_number(ctx, number, check = lambda m: m.attachments) - @delete.command(name = "contains", pass_context = True) + @delete.command(name = "contains") @checks.has_permissions_and_capability(manage_messages = True) async def delete_contains(self, ctx, string : str, number : int): '''Deletes the most recent messages with in them''' await self.delete_number(ctx, number, check = lambda m: string in m.content) - @delete.command(name = "embeds", pass_context = True) + @delete.command(name = "embeds") @checks.has_permissions_and_capability(manage_messages = True) async def delete_embeds(self, ctx, number: int): '''Deletes the most recent messages with embeds''' await self.delete_number(ctx, number, check = lambda m: m.embeds) - @delete.command(name = "time", pass_context = True) + @delete.command(name = "time") @checks.has_permissions_and_capability(manage_messages = True) async def delete_time(self, ctx, minutes : int): '''Deletes messages in the past minutes''' await self.bot.attempt_delete_message(ctx.message) - await self.bot.purge_from(ctx.message.channel, limit = clients.delete_limit, after = datetime.datetime.utcnow() - datetime.timedelta(minutes = minutes)) + await self.bot.purge_from(ctx.channel, limit = clients.delete_limit, after = datetime.datetime.utcnow() - datetime.timedelta(minutes = minutes)) # TODO: delete mentions, invites? async def delete_number(self, ctx, number, check, delete_command = True): if number <= 0: - await self.bot.embed_reply(":no_entry: Syntax error") + await ctx.embed_reply(":no_entry: Syntax error") return to_delete = [] count = 0 if delete_command: await self.bot.attempt_delete_message(ctx.message) - async for message in self.bot.logs_from(ctx.message.channel, limit = clients.delete_limit): + async for message in self.bot.logs_from(ctx.channel, limit = clients.delete_limit): if check(message): to_delete.append(message) count += 1 @@ -125,7 +125,7 @@ async def delete_number(self, ctx, number, check, delete_command = True): elif len(to_delete) > 1: await self.bot.delete_messages(to_delete) - @commands.command(aliases = ["mycolour", "my_color", "my_colour"], pass_context = True, no_pm = True) + @commands.command(aliases = ["mycolour", "my_color", "my_colour"], no_pm = True) @checks.not_forbidden() async def mycolor(self, ctx, color : str = ""): ''' @@ -134,54 +134,54 @@ async def mycolor(self, ctx, color : str = ""): ''' # TODO: Rework if not color: - color_value = ctx.message.author.color.value - await self.bot.embed_reply("#{}".format(conversions.inttohex(color_value))) + color_value = ctx.author.color.value + await ctx.embed_reply("#{}".format(conversions.inttohex(color_value))) return # check color try: color_value = int(color.strip('#'), 16) except ValueError: - await self.bot.embed_reply(":no_entry: Please enter a valid hex color") + await ctx.embed_reply(":no_entry: Please enter a valid hex color") return - role_to_change = discord.utils.get(ctx.message.server.roles, name = ctx.message.author.name) + role_to_change = discord.utils.get(ctx.guild.roles, name = ctx.author.name) if not role_to_change: - new_role = await self.bot.create_role(ctx.message.server, name = ctx.message.author.name, hoist = False) - await self.bot.add_roles(ctx.message.author, new_role) + new_role = await self.bot.create_role(ctx.guild, name = ctx.author.name, hoist = False) + await self.bot.add_roles(ctx.author, new_role) new_colour = new_role.colour new_colour.value = color_value - await self.bot.edit_role(ctx.message.server, new_role, name = ctx.message.author.name, colour = new_colour) - await self.bot.embed_reply("Created your role with the color, {}".format(color)) + await self.bot.edit_role(ctx.guild, new_role, name = ctx.author.name, colour = new_colour) + await ctx.embed_reply("Created your role with the color, {}".format(color)) else: new_colour = role_to_change.colour new_colour.value = color_value - await self.bot.edit_role(ctx.message.server, role_to_change, colour = new_colour) + await self.bot.edit_role(ctx.guild, role_to_change, colour = new_colour) await self.bot.embed_reply("Changed your role color to {}".format(color)) - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.has_permissions_and_capability(manage_messages = True) async def pin(self, ctx, message_id : int): '''Pin message by message ID''' - message = await self.bot.get_message(ctx.message.channel, str(message_id)) + message = await self.bot.get_message(ctx.channel, str(message_id)) await self.bot.pin_message(message) await self.bot.embed_reply(":pushpin: Pinned message") - @pin.command(name = "first", pass_context = True) + @pin.command(name = "first") @checks.has_permissions_and_capability(manage_messages = True) async def pin_first(self, ctx): '''Pin first message''' - message = await self.bot.logs_from(ctx.message.channel, after = ctx.message.channel, limit = 1).iterate() + message = await self.bot.logs_from(ctx.channel, after = ctx.channel, limit = 1).iterate() await self.bot.pin_message(message) await self.bot.embed_reply(":pushpin: Pinned first message in this channel") - @commands.command(pass_context = True) + @commands.command() @checks.has_permissions_and_capability(manage_messages = True) async def unpin(self, ctx, message_id : int): '''Unpin message by message ID''' - message = await self.bot.get_message(ctx.message.channel, str(message_id)) + message = await self.bot.get_message(ctx.channel, str(message_id)) await self.bot.unpin_message(message) await self.bot.embed_reply(":wastebasket: Unpinned message") - @commands.command(aliases = ["rolecolour", "role_color", "role_colour"], pass_context = True, no_pm = True) + @commands.command(aliases = ["rolecolour", "role_color", "role_colour"], no_pm = True) @checks.not_forbidden() async def rolecolor(self, ctx, role : str, *color : str): ''' @@ -191,7 +191,7 @@ async def rolecolor(self, ctx, role : str, *color : str): ''' if not color: selected_role = None - for _role in ctx.message.server.roles: + for _role in ctx.guild.roles: if _role.name.startswith((' ').join(role.split('_'))): selected_role = _role break @@ -201,8 +201,8 @@ async def rolecolor(self, ctx, role : str, *color : str): color = selected_role.colour color_value = color.value await self.bot.embed_reply(conversions.inttohex(color_value)) - elif ctx.message.channel.permissions_for(ctx.message.author).manage_roles or ctx.message.author.id == clients.owner_id: - for _role in ctx.message.server.roles: + elif ctx.channel.permissions_for(ctx.author).manage_roles or ctx.author.id == clients.owner_id: + for _role in ctx.guild.roles: if _role.name.startswith((' ').join(role.split('_'))): role_to_change = _role break @@ -211,31 +211,31 @@ async def rolecolor(self, ctx, role : str, *color : str): return new_colour = role_to_change.colour new_colour.value = conversions.hextoint(color[0]) - await self.bot.edit_role(ctx.message.server, role_to_change, colour = new_colour) + await self.bot.edit_role(ctx.guild, role_to_change, colour = new_colour) - @commands.command(pass_context = True, hidden = True) + @commands.command(hidden = True) @checks.is_owner() async def roleposition(self, ctx, role : str, position : int): '''WIP''' - for _role in ctx.message.server.roles: + for _role in ctx.guild.roles: if _role.name.startswith((' ').join(role.split('_'))): selected_role = _role break - await self.bot.move_role(ctx.message.server, selected_role, position) + await self.bot.move_role(ctx.guild, selected_role, position) - @commands.command(pass_context = True, no_pm = True) + @commands.command(no_pm = True) @checks.not_forbidden() async def tempchannel(self, ctx, *options : str): ''' Create temporary voice and text channels options: allow ''' - temp_voice_channel = discord.utils.get(ctx.message.server.channels, name = ctx.message.author.display_name + "'s Temp Channel") - temp_text_channel = discord.utils.get(ctx.message.server.channels, name = ctx.message.author.display_name.lower() + "s_temp_channel") + temp_voice_channel = discord.utils.get(ctx.guild.channels, name = ctx.author.display_name + "'s Temp Channel") + temp_text_channel = discord.utils.get(ctx.guild.channels, name = ctx.author.display_name.lower() + "s_temp_channel") if temp_voice_channel and options and options[0] == "allow": - to_allow = discord.utils.get(ctx.message.server.members, name = options[1]) + to_allow = discord.utils.get(ctx.guild.members, name = options[1]) if not to_allow: - await self.bot.embed_reply(":no_entry: User not found") + await ctx.embed_reply(":no_entry: User not found") voice_channel_permissions = discord.Permissions.none() voice_channel_permissions.connect = True voice_channel_permissions.speak = True @@ -244,45 +244,45 @@ async def tempchannel(self, ctx, *options : str): text_channel_permissions = discord.Permissions.text() text_channel_permissions.manage_messages = False await self.bot.edit_channel_permissions(temp_text_channel, to_allow, allow = text_channel_permissions) - await self.bot.embed_reply("You have allowed " + to_allow.display_name + " to join your temporary voice and text channel") + await ctx.embed_reply("You have allowed " + to_allow.display_name + " to join your temporary voice and text channel") return if temp_voice_channel: - await self.bot.embed_reply(":no_entry: You already have a temporary voice and text channel") + await ctx.embed_reply(":no_entry: You already have a temporary voice and text channel") return - temp_voice_channel = await self.bot.create_channel(ctx.message.server, ctx.message.author.display_name + "'s Temp Channel", type = discord.ChannelType.voice) - temp_text_channel = await self.bot.create_channel(ctx.message.server, ctx.message.author.display_name + "s_Temp_Channel", type = discord.ChannelType.text) - await self.bot.edit_channel_permissions(temp_voice_channel, ctx.message.server.me, allow = discord.Permissions.all()) - await self.bot.edit_channel_permissions(temp_text_channel, ctx.message.server.me, allow = discord.Permissions.all()) - await self.bot.edit_channel_permissions(temp_voice_channel, ctx.message.author.roles[0], deny = discord.Permissions.all()) - await self.bot.edit_channel_permissions(temp_text_channel, ctx.message.author.roles[0], deny = discord.Permissions.all()) - await self.bot.edit_channel_permissions(temp_voice_channel, ctx.message.author, allow = discord.Permissions.all()) - await self.bot.edit_channel_permissions(temp_text_channel, ctx.message.author, allow = discord.Permissions.all()) + temp_voice_channel = await self.bot.create_channel(ctx.guild, ctx.author.display_name + "'s Temp Channel", type = discord.ChannelType.voice) + temp_text_channel = await self.bot.create_channel(ctx.guild, ctx.author.display_name + "s_Temp_Channel", type = discord.ChannelType.text) + await self.bot.edit_channel_permissions(temp_voice_channel, ctx.me, allow = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_text_channel, ctx.me, allow = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_voice_channel, ctx.author.roles[0], deny = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_text_channel, ctx.author.roles[0], deny = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_voice_channel, ctx.author, allow = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_text_channel, ctx.author, allow = discord.Permissions.all()) try: - await self.bot.move_member(ctx.message.author, temp_voice_channel) + await self.bot.move_member(ctx.author, temp_voice_channel) except discord.errors.Forbidden: - await self.bot.embed_reply(":no_entry: I can't move you to the new temporary voice channel") - await self.bot.embed_reply("Temporary voice and text channel created") + await ctx.embed_reply(":no_entry: I can't move you to the new temporary voice channel") + await ctx.embed_reply("Temporary voice and text channel created") while True: await asyncio.sleep(15) - temp_voice_channel = discord.utils.get(ctx.message.server.channels, id = temp_voice_channel.id) + temp_voice_channel = discord.utils.get(ctx.guild.channels, id = temp_voice_channel.id) if len(temp_voice_channel.voice_members) == 0: - await self.bot.edit_channel_permissions(temp_voice_channel, ctx.message.server.me, allow = discord.Permissions.all()) - await self.bot.edit_channel_permissions(temp_text_channel, ctx.message.server.me, allow = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_voice_channel, ctx.me, allow = discord.Permissions.all()) + await self.bot.edit_channel_permissions(temp_text_channel, ctx.me, allow = discord.Permissions.all()) await self.bot.delete_channel(temp_voice_channel) await self.bot.delete_channel(temp_text_channel) return - @commands.command(hidden = True, pass_context = True, no_pm = True) + @commands.command(hidden = True, no_pm = True) @checks.is_owner() async def userlimit(self, ctx, limit : int): '''WIP''' - if ctx.message.author.voice_channel: - voice_channel = ctx.message.author.voice_channel + if ctx.author.voice_channel: + voice_channel = ctx.author.voice_channel await self.bot.edit_channel(voice_channel, user_limit = limit) # Get Attributes - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def avatar(self, ctx, *, name : str = ""): ''' @@ -290,10 +290,10 @@ async def avatar(self, ctx, *, name : str = ""): Your own or someone else's avatar ''' if not name: - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url await self.bot.embed_reply(None, title = "Your avatar", image_url = avatar) return - if not ctx.message.server: + if not ctx.guild: await self.bot.embed_reply(":no_entry: Please use that command in a server") return user = await utilities.get_user(ctx, name) @@ -303,7 +303,7 @@ async def avatar(self, ctx, *, name : str = ""): avatar = user.avatar_url or user.default_avatar_url await self.bot.embed_reply(None, title = "{}'s avatar".format(user), image_url = avatar) - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def discriminator(self, ctx, *, name : str = ""): ''' @@ -311,13 +311,13 @@ async def discriminator(self, ctx, *, name : str = ""): Your own or someone else's discriminator ''' if not name: - await self.bot.embed_reply("Your discriminator: #" + ctx.message.author.discriminator) + await self.bot.embed_reply("Your discriminator: #" + ctx.author.discriminator) return - if not ctx.message.server: + if not ctx.guild: await self.bot.embed_reply(":no_entry: Please use that command in a server") return flag = True - for member in ctx.message.server.members: + for member in ctx.guild.members: if member.name == name: embed = discord.Embed(description = name + "'s discriminator: #" + member.discriminator, color = clients.bot_color) avatar = member.default_avatar_url if not member.avatar else member.avatar_url @@ -327,37 +327,37 @@ async def discriminator(self, ctx, *, name : str = ""): if flag and name: await self.bot.embed_reply(name + " was not found on this server") - @commands.command(aliases = ["role_id"], pass_context = True, no_pm = True) + @commands.command(aliases = ["role_id"], no_pm = True) @checks.not_forbidden() async def roleid(self, ctx, *, name : str): '''Get the ID of a role''' - for role in ctx.message.server.roles: + for role in ctx.guild.roles: if utilities.remove_symbols(role.name).startswith(name): await self.bot.embed_reply(role.id) - @commands.command(aliases = ["role_positions"], pass_context = True, hidden = True) + @commands.command(aliases = ["role_positions"], hidden = True) @checks.is_owner() async def rolepositions(self, ctx): '''WIP''' - await self.bot.embed_reply(', '.join([role.name + ": " + str(role.position) for role in ctx.message.server.roles[1:]])) + await self.bot.embed_reply(', '.join([role.name + ": " + str(role.position) for role in ctx.guild.roles[1:]])) - @commands.command(aliases = ["server_icon"], pass_context = True, no_pm = True) + @commands.command(aliases = ["server_icon"], no_pm = True) @checks.not_forbidden() async def servericon(self, ctx): '''See a bigger version of the server icon''' - if not ctx.message.server.icon: + if not ctx.guild.icon: await self.bot.embed_reply(":no_entry: This server doesn't have an icon") return - await self.bot.embed_reply("This server's icon:", image_url = ctx.message.server.icon_url) + await self.bot.embed_reply("This server's icon:", image_url = ctx.guild.icon_url) - @commands.command(aliases = ["serverinformation", "server_info", "server_information"], pass_context = True, no_pm = True) + @commands.command(aliases = ["serverinformation", "server_info", "server_information"], no_pm = True) @checks.not_forbidden() async def serverinfo(self, ctx): '''Information about a server''' - server = ctx.message.server + server = ctx.guild embed = discord.Embed(title = server.name, url = server.icon_url, timestamp = server.created_at, color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.set_thumbnail(url = server.icon_url) embed.add_field(name = "Owner", value = server.owner.mention) embed.add_field(name = "ID", value = server.id) @@ -383,18 +383,18 @@ async def serverinfo(self, ctx): embed.set_footer(text = "Created") await self.bot.say(embed = embed) - @commands.command(aliases = ["server_owner"], pass_context = True, no_pm = True) + @commands.command(aliases = ["server_owner"], no_pm = True) @checks.not_forbidden() async def serverowner(self, ctx): '''The owner of the server''' - owner = ctx.message.server.owner + owner = ctx.guild.owner await self.bot.embed_reply("The owner of this server is {}".format(owner.mention), footer_text = str(owner), footer_icon_url = owner.avatar_url or owner.default_avatar_url) - @commands.command(aliases = ["user_info"], pass_context = True) + @commands.command(aliases = ["user_info"]) @checks.not_forbidden() async def userinfo(self, ctx): '''Information about a user''' - user = ctx.message.author + user = ctx.author avatar = user.avatar_url or user.default_avatar_url await self.bot.embed_reply(None, title = str(user), title_url = avatar, thumbnail_url = avatar, footer_text = "Created", timestamp = user.created_at, fields = [("User", user.mention), ("ID", user.id), ("Bot", user.bot)]) # member info, status, game, roles, color, etc. @@ -403,7 +403,7 @@ async def userinfo(self, ctx): @commands.command(aliases = ["id_to_name"]) @checks.not_forbidden() - async def idtoname(self, id : str): + async def idtoname(self, ctx, id : str): '''Convert user id to name''' user = await self.bot.get_user_info(id) if not user: @@ -414,7 +414,7 @@ async def idtoname(self, id : str): # Include mention? await self.bot.reply("", embed = embed) - @commands.command(aliases = ["usertoid", "usernametoid", "name_to_id", "user_to_id", "username_to_id"], no_pm = True, pass_context = True) + @commands.command(aliases = ["usertoid", "usernametoid", "name_to_id", "user_to_id", "username_to_id"], no_pm = True) @checks.not_forbidden() async def nametoid(self, ctx, *, name : str): '''Convert username to id''' @@ -429,13 +429,13 @@ async def nametoid(self, ctx, *, name : str): # Checks - @commands.command(aliases = ["here"], pass_context = True) + @commands.command(aliases = ["here"]) @checks.not_forbidden() async def everyone(self, ctx): ''' Check if you can mention everyone/here For the channel you execute the command in ''' - able = "" if ctx.message.author.permissions_in(ctx.message.channel).mention_everyone else "not " - await self.bot.embed_reply("You are {}able to mention everyone/here in this channel".format(able)) + able = "" if ctx.author.permissions_in(ctx.channel).mention_everyone else "not " + await ctx.embed_reply("You are {}able to mention everyone/here in this channel".format(able)) diff --git a/Discord/cogs/games.py b/Discord/cogs/games.py index caa3bae1b4..b2a5141657 100644 --- a/Discord/cogs/games.py +++ b/Discord/cogs/games.py @@ -24,7 +24,7 @@ # from modules import gofish from modules import maze from modules import utilities -from modules import war +# from modules import war from utilities import checks def setup(bot): @@ -58,7 +58,7 @@ def __init__(self, bot): @commands.group(aliases = ["rpg"], invoke_without_command = True, hidden = True) @checks.not_forbidden() - async def adventure(self): + async def adventure(self, ctx): '''WIP''' pass @@ -69,32 +69,32 @@ def get_adventure_player(self, user_id): self.adventure_players[user_id] = player return player - @adventure.group(name = "stats", aliases = ["stat", "levels", "level", "lvls", "lvl"], pass_context = True, invoke_without_command = True) + @adventure.group(name = "stats", aliases = ["stat", "levels", "level", "lvls", "lvl"], invoke_without_command = True) @checks.not_forbidden() async def adventure_stats(self, ctx): '''Stats''' - player = self.get_adventure_player(ctx.message.author.id) - await self.bot.embed_reply("\n:fishing_pole_and_fish: Fishing xp: {} (Level {})" + player = self.get_adventure_player(ctx.author.id) + await ctx.embed_reply("\n:fishing_pole_and_fish: Fishing xp: {} (Level {})" "\n:herb: Foraging xp: {} (Level {})" "\n:pick: Mining xp: {} (Level {})" "\n:evergreen_tree: Woodcutting xp: {} (Level {})".format(player.fishing_xp, player.fishing_lvl, player.foraging_xp, player.foraging_lvl, player.mining_xp, player.mining_lvl, player.woodcutting_xp, player.woodcutting_lvl)) # time started/played - @adventure_stats.command(name = "woodcutting", aliases = ["wc"], pass_context = True) + @adventure_stats.command(name = "woodcutting", aliases = ["wc"]) @checks.not_forbidden() async def stats_woodcutting(self, ctx): '''Woodcutting stats''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) woodcutting_xp = player.woodcutting_xp - await self.bot.embed_reply("\n:evergreen_tree: Woodcutting xp: {}\n{}\n{} xp to next level".format(woodcutting_xp, self.level_bar(woodcutting_xp), adventure.xp_left_to_next_lvl(woodcutting_xp))) + await ctx.embed_reply("\n:evergreen_tree: Woodcutting xp: {}\n{}\n{} xp to next level".format(woodcutting_xp, self.level_bar(woodcutting_xp), adventure.xp_left_to_next_lvl(woodcutting_xp))) - @adventure_stats.command(name = "foraging", aliases = ["forage", "gather", "gathering"], pass_context = True) + @adventure_stats.command(name = "foraging", aliases = ["forage", "gather", "gathering"]) @checks.not_forbidden() async def stats_foraging(self, ctx): '''Foraging stats''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) foraging_xp = player.foraging_xp - await self.bot.embed_reply("\n:herb: Foraging xp: {}\n{}\n{} xp to next level".format(foraging_xp, self.level_bar(foraging_xp), adventure.xp_left_to_next_lvl(foraging_xp))) + await ctx.embed_reply("\n:herb: Foraging xp: {}\n{}\n{} xp to next level".format(foraging_xp, self.level_bar(foraging_xp), adventure.xp_left_to_next_lvl(foraging_xp))) def level_bar(self, xp): lvl = adventure.xp_to_lvl(xp) @@ -105,92 +105,92 @@ def level_bar(self, xp): bar = chr(9632) * shaded + chr(9633) * (10 - shaded) return "Level {0} ({3} xp) [{2}] Level {1} ({4} xp)".format(lvl, lvl + 1, bar, previous_xp, next_xp) - @adventure.command(name = "inventory", pass_context = True) + @adventure.command(name = "inventory") @checks.not_forbidden() async def adventure_inventory(self, ctx, *, item : str = ""): '''Inventory''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) inventory = player.inventory if item in inventory: - await self.bot.embed_reply("{}: {}".format(item, inventory[item])) + await ctx.embed_reply("{}: {}".format(item, inventory[item])) else: - await self.bot.embed_reply(", ".join(["{}: {}".format(item, amount) for item, amount in sorted(inventory.items())])) + await ctx.embed_reply(", ".join(["{}: {}".format(item, amount) for item, amount in sorted(inventory.items())])) - @adventure.command(name = "examine", pass_context = True) + @adventure.command(name = "examine") @checks.not_forbidden() async def adventure_examine(self, ctx, *, item : str): '''Examine items''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) inventory = player.inventory if item in inventory: if item in adventure.examine_messages: - await self.bot.embed_reply("{}".format(adventure.examine_messages[item])) + await ctx.embed_reply("{}".format(adventure.examine_messages[item])) else: - await self.bot.embed_reply("{}".format(item)) + await ctx.embed_reply("{}".format(item)) else: - await self.bot.embed_reply(":no_entry: You don't have that item") + await ctx.embed_reply(":no_entry: You don't have that item") - @adventure.group(name = "forage", aliases = ["gather"], pass_context = True, invoke_without_command = True) + @adventure.group(name = "forage", aliases = ["gather"], invoke_without_command = True) @checks.not_forbidden() async def adventure_forage(self, ctx, *, item : str = ""): '''Foraging''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) started = player.start_foraging(item) if started == "foraging": stopped = player.stop_foraging() output = "\n:herb: You were foraging {0[0]} for {0[1]:.2f} min. and received {0[2]} {0[0]} and xp. While you were foraging, you also found {0[3]} {1}".format(stopped, adventure.forageables[stopped[0]][0]) if stopped[4]: output += " and {0[4]} {1}!".format(stopped, adventure.forageables[stopped[0]][1]) - await self.bot.embed_reply(output) + await ctx.embed_reply(output) if item: started = player.start_foraging(item) else: return if started is True: - await self.bot.embed_reply("\n:herb: You have started foraging for {}".format(item)) + await ctx.embed_reply("\n:herb: You have started foraging for {}".format(item)) # active? elif started is False: - await self.bot.embed_reply(":no_entry: That item type doesn't exist") + await ctx.embed_reply(":no_entry: That item type doesn't exist") else: - await self.bot.embed_reply(":no_entry: You're currently {}! You can't start/stop foraging right now".format(started)) + await ctx.embed_reply(":no_entry: You're currently {}! You can't start/stop foraging right now".format(started)) - @adventure_forage.command(name = "start", aliases = ["on"], pass_context = True) + @adventure_forage.command(name = "start", aliases = ["on"]) @checks.not_forbidden() async def forage_start(self, ctx, *, item : str): '''Start foraging''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) started = player.start_foraging(item) if started is True: - await self.bot.embed_reply("\n:herb: You have started foraging for {}".format(item)) + await ctx.embed_reply("\n:herb: You have started foraging for {}".format(item)) # active? elif started is False: - await self.bot.embed_reply(":no_entry: That item type doesn't exist") + await ctx.embed_reply(":no_entry: That item type doesn't exist") else: - await self.bot.embed_reply(":no_entry: You're currently {}! You can't start foraging right now".format(started)) + await ctx.embed_reply(":no_entry: You're currently {}! You can't start foraging right now".format(started)) - @adventure_forage.command(name = "stop", aliases = ["off"], pass_context = True) + @adventure_forage.command(name = "stop", aliases = ["off"]) @checks.not_forbidden() async def forage_stop(self, ctx): '''Stop foraging''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) stopped = player.stop_foraging() if stopped[0]: output = "\n:herb: You were foraging {0[0]} for {0[1]:.2f} min. and received {0[2]} {0[0]} and xp. While you were foraging, you also found {0[3]} {1}".format(stopped, adventure.forageables[stopped[0]][0]) if stopped[4]: output += " and {0[4]} {1}!".format(stopped, adventure.forageables[stopped[0]][1]) - await self.bot.embed_reply(output) + await ctx.embed_reply(output) elif stopped[1]: - await self.bot.embed_reply(":no_entry: You're currently {}! You aren't foraging right now") + await ctx.embed_reply(":no_entry: You're currently {}! You aren't foraging right now") else: - await self.bot.embed_reply(":no_entry: You aren't foraging") + await ctx.embed_reply(":no_entry: You aren't foraging") @adventure_forage.command(name = "items", aliases = ["item", "type", "types"]) @checks.not_forbidden() - async def forage_items(self): + async def forage_items(self, ctx): '''Forageable items''' - await self.bot.embed_reply(", ".join(adventure.forageables.keys())) + await ctx.embed_reply(", ".join(adventure.forageables.keys())) - @adventure.command(name = "create", aliases = ["make", "craft"], pass_context = True) + @adventure.command(name = "create", aliases = ["make", "craft"]) @checks.not_forbidden() async def adventure_create(self, ctx, *items : str): ''' @@ -198,54 +198,54 @@ async def adventure_create(self, ctx, *items : str): items: items to use to attempt to create something else Use quotes for spaces in item names ''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) created = player.create_item(items) if created is None: - await self.bot.embed_reply("You don't have those items") + await ctx.embed_reply("You don't have those items") elif created is False: - await self.bot.embed_reply("You were unable to create anything with those items") + await ctx.embed_reply("You were unable to create anything with those items") else: - await self.bot.embed_reply("You have created {}".format(created)) + await ctx.embed_reply("You have created {}".format(created)) - @adventure.group(name = "chop", aliases = ["woodcutting", "wc"], pass_context = True, invoke_without_command = True) + @adventure.group(name = "chop", aliases = ["woodcutting", "wc"], invoke_without_command = True) @checks.not_forbidden() async def adventure_woodcutting(self, ctx, *, wood_type : str = ""): '''Woodcutting''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) started = player.start_woodcutting(wood_type) if started == "woodcutting": stopped = player.stop_woodcutting() - await self.bot.embed_reply("\n:evergreen_tree: You were chopping {0[0]} for {0[1]:.2f} min. and received {0[2]} {0[0]} and {0[3]} xp".format(stopped)) + await ctx.embed_reply("\n:evergreen_tree: You were chopping {0[0]} for {0[1]:.2f} min. and received {0[2]} {0[0]} and {0[3]} xp".format(stopped)) if wood_type: started = player.start_woodcutting(wood_type) else: return if started is True: - await self.bot.embed_reply("\n:evergreen_tree: You have started chopping {} trees".format(wood_type)) + await ctx.embed_reply("\n:evergreen_tree: You have started chopping {} trees".format(wood_type)) await self.woodcutting_active(ctx, wood_type) elif started is False: - await self.bot.embed_reply(":no_entry: That wood type doesn't exist") + await ctx.embed_reply(":no_entry: That wood type doesn't exist") else: - await self.bot.embed_reply(":no_entry: You're currently {}! You can't start/stop woodcutting right now".format(started)) + await ctx.embed_reply(":no_entry: You're currently {}! You can't start/stop woodcutting right now".format(started)) - @adventure_woodcutting.command(name = "start", aliases = ["on"], pass_context = True) + @adventure_woodcutting.command(name = "start", aliases = ["on"]) @checks.not_forbidden() async def woodcutting_start(self, ctx, *, wood_type : str): '''Start chopping wood''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) started = player.start_woodcutting(wood_type) if started is True: - await self.bot.embed_reply("\n:evergreen_tree: You have started chopping {} trees".format(wood_type)) + await ctx.embed_reply("\n:evergreen_tree: You have started chopping {} trees".format(wood_type)) await self.woodcutting_active(ctx, wood_type) elif started is False: - await self.bot.embed_reply(":no_entry: That wood type doesn't exist") + await ctx.embed_reply(":no_entry: That wood type doesn't exist") else: - await self.bot.embed_reply(":no_entry: You're currently {}! You can't start woodcutting right now".format(started)) + await ctx.embed_reply(":no_entry: You're currently {}! You can't start woodcutting right now".format(started)) async def woodcutting_active(self, ctx, wood_type): - player = self.get_adventure_player(ctx.message.author.id) - ask_message, embed = await self.bot.embed_reply("\n:grey_question: Would you like to chop {} trees actively? Yes/No".format(wood_type)) - message = await self.bot.wait_for_message(timeout = 60, author = ctx.message.author, check = lambda m: m.content.lower() in ('y', "yes", 'n', "no")) + player = self.get_adventure_player(ctx.author.id) + ask_message = await ctx.embed_reply("\n:grey_question: Would you like to chop {} trees actively? Yes/No".format(wood_type)) + message = await self.bot.wait_for_message(timeout = 60, author = ctx.author, check = lambda m: m.content.lower() in ('y', "yes", 'n', "no")) await self.bot.delete_message(ask_message) if not message or message.content.lower() in ('n', "no"): if message: @@ -253,59 +253,59 @@ async def woodcutting_active(self, ctx, wood_type): return rate = player.wood_rate(wood_type) * player.woodcutting_rate if rate == 0: - await self.bot.embed_reply(":no_entry: You can't chop this wood yet") + await ctx.embed_reply(":no_entry: You can't chop this wood yet") return time = int(60 / rate) chopped_message = None while message: - chopping, embed = await self.bot.embed_reply("\n:evergreen_tree: Chopping.. (this could take up to {} sec.)".format(time)) + chopping = await ctx.embed_reply("\n:evergreen_tree: Chopping.. (this could take up to {} sec.)".format(time)) await asyncio.sleep(random.randint(1, time)) await self.bot.delete_message(message) await self.bot.delete_message(chopping) prompt = random.choice(["chop", "whack", "swing", "cut"]) - prompt_message, embed = await self.bot.embed_reply('Reply with "{}" in the next 10 sec. to continue'.format(prompt)) - message = await self.bot.wait_for_message(timeout = 10, author = ctx.message.author, content = prompt) + prompt_message = await ctx.embed_reply('Reply with "{}" in the next 10 sec. to continue'.format(prompt)) + message = await self.bot.wait_for_message(timeout = 10, author = ctx.author, content = prompt) if message: chopped = player.chop_once(wood_type) if chopped_message: await self.bot.delete_message(chopped_message) - chopped_message, embed = await self.bot.embed_reply("\n:evergreen_tree: You chopped a {0} tree. You now have {1[0]} {0} and {1[1]} woodcutting xp".format(wood_type, chopped)) + chopped_message = await ctx.embed_reply("\n:evergreen_tree: You chopped a {0} tree. You now have {1[0]} {0} and {1[1]} woodcutting xp".format(wood_type, chopped)) else: - await self.bot.embed_reply("\n:stop_sign: You have stopped actively chopping {}".format(wood_type)) + await ctx.embed_reply("\n:stop_sign: You have stopped actively chopping {}".format(wood_type)) await self.bot.delete_message(prompt_message) - @adventure_woodcutting.command(name = "stop", aliases = ["off"], pass_context = True) + @adventure_woodcutting.command(name = "stop", aliases = ["off"]) @checks.not_forbidden() async def woodcutting_stop(self, ctx): '''Stop chopping wood''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) stopped = player.stop_woodcutting() if stopped[0]: - await self.bot.embed_reply("\n:evergreen_tree: You were chopping {0[0]} for {0[1]:.2f} min. and received {0[2]} {0[0]} and {0[3]} xp".format(stopped)) + await ctx.embed_reply("\n:evergreen_tree: You were chopping {0[0]} for {0[1]:.2f} min. and received {0[2]} {0[0]} and {0[3]} xp".format(stopped)) elif stopped[1]: - await self.bot.embed_reply(":no_entry: You're currently {}! You aren't woodcutting right now") + await ctx.embed_reply(":no_entry: You're currently {}! You aren't woodcutting right now") else: - await self.bot.embed_reply(":no_entry: You aren't woodcutting") + await ctx.embed_reply(":no_entry: You aren't woodcutting") @adventure_woodcutting.command(name = "types", aliases = ["type", "item", "items"]) @checks.not_forbidden() - async def woodcutting_types(self): + async def woodcutting_types(self, ctx): '''Types of wood''' - await self.bot.embed_reply(", ".join(adventure.wood_types)) + await ctx.embed_reply(", ".join(adventure.wood_types)) - @adventure_woodcutting.command(name = "rate", aliases = ["rates"], pass_context = True) + @adventure_woodcutting.command(name = "rate", aliases = ["rates"]) @checks.not_forbidden() async def woodcutting_rate(self, ctx, *, wood_type : str): '''Rate of chopping certain wood''' - player = self.get_adventure_player(ctx.message.author.id) + player = self.get_adventure_player(ctx.author.id) if wood_type in adventure.wood_types: - await self.bot.embed_reply("You will get {:.2f} {}/min. at your current level".format(player.wood_rate(wood_type) * player.woodcutting_rate, wood_type)) + await ctx.embed_reply("You will get {:.2f} {}/min. at your current level".format(player.wood_rate(wood_type) * player.woodcutting_rate, wood_type)) else: - await self.bot.embed_reply(":no_entry: That wood type doesn't exist") + await ctx.embed_reply(":no_entry: That wood type doesn't exist") # Not Adventure - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def blackjack(self, ctx): ''' @@ -321,16 +321,17 @@ async def blackjack(self, ctx): player_string = self.cards_to_string(player.cards) dealer_total = self.blackjack_total(dealer.cards) player_total = self.blackjack_total(player.cards) - response, embed = await self.bot.embed_reply("Dealer: {} (?)\n{}: {} ({})\n".format(dealer_string, ctx.message.author.display_name, player_string, player_total), title = "Blackjack", footer_text = "Hit or Stay?") + response = await ctx.embed_reply("Dealer: {} (?)\n{}: {} ({})\n".format(dealer_string, ctx.author.display_name, player_string, player_total), title = "Blackjack", footer_text = "Hit or Stay?") + embed = response.embeds[0] await self.bot.attempt_delete_message(ctx.message) while True: - action = await self.bot.wait_for_message(author = ctx.message.author, check = lambda msg: msg.content.lower().strip('!') in ("hit", "stay")) + action = await self.bot.wait_for_message(author = ctx.author, check = lambda msg: msg.content.lower().strip('!') in ("hit", "stay")) await self.bot.attempt_delete_message(action) if action.content.lower().strip('!') == "hit": player.add(deck.deal()) player_string = self.cards_to_string(player.cards) player_total = self.blackjack_total(player.cards) - embed.description = "Dealer: {} (?)\n{}: {} ({})\n".format(dealer_string, ctx.message.author.display_name, player_string, player_total) + embed.description = "Dealer: {} (?)\n{}: {} ({})\n".format(dealer_string, ctx.author.display_name, player_string, player_total) await self.bot.edit_message(response, embed = embed) if player_total > 21: embed.description += ":boom: You have busted" @@ -338,7 +339,7 @@ async def blackjack(self, ctx): break else: dealer_string = self.cards_to_string(dealer.cards) - embed.description = "Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.message.author.display_name, player_string, player_total) + embed.description = "Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.author.display_name, player_string, player_total) if dealer_total > 21: embed.description += ":boom: The dealer busted" embed.set_footer(text = "You win!") @@ -354,7 +355,7 @@ async def blackjack(self, ctx): dealer.add(deck.deal()) dealer_string = self.cards_to_string(dealer.cards) dealer_total = self.blackjack_total(dealer.cards) - embed.description = "Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.message.author.display_name, player_string, player_total) + embed.description = "Dealer: {} ({})\n{}: {} ({})\n".format(dealer_string, dealer_total, ctx.author.display_name, player_string, player_total) await self.bot.edit_message(response, embed = embed) if dealer_total > 21: embed.description += ":boom: The dealer busted" @@ -375,7 +376,7 @@ def blackjack_total(self, cards): if pydealer.tools.find_card(cards, term = "Ace", limit = 1) and total <= 11: total += 10 return total - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def chess(self, ctx): ''' @@ -386,7 +387,7 @@ async def chess(self, ctx): white e2e4 ''' - await self.bot.embed_reply("See {}help chess".format(ctx.prefix)) + await ctx.embed_reply("See {}help chess".format(ctx.prefix)) ''' else: @@ -396,12 +397,12 @@ async def chess(self, ctx): try: self._chess_board.push_uci(move) except ValueError: - await self.bot.embed_reply(":no_entry: Invalid move") + await ctx.embed_reply(":no_entry: Invalid move") return await self._update_chess_board_embed() ''' - @chess.command(name = "play", aliases = ["start"], pass_context = True) + @chess.command(name = "play", aliases = ["start"]) @checks.not_forbidden() async def chess_play(self, ctx, *, opponent : str = ""): ''' @@ -409,53 +410,53 @@ async def chess_play(self, ctx, *, opponent : str = ""): You can play me as well ''' # check if already playing a match in this channel - if self.get_chess_match(ctx.message.channel, ctx.message.author): - await self.bot.embed_reply(":no_entry: You're already playing a chess match here") + if self.get_chess_match(ctx.channel, ctx.author): + await ctx.embed_reply(":no_entry: You're already playing a chess match here") return # prompt for opponent if not opponent: - await self.bot.embed_reply("Who would you like to play?") - message = await self.bot.wait_for_message(author = ctx.message.author, channel = ctx.message.channel) + await ctx.embed_reply("Who would you like to play?") + message = await self.bot.wait_for_message(author = ctx.author, channel = ctx.channel) opponent = message.content color = None if opponent.lower() in ("harmonbot", "you"): opponent = self.bot.user elif opponent.lower() in ("myself", "me"): - opponent = ctx.message.author + opponent = ctx.author color = 'w' else: opponent = await utilities.get_user(ctx, opponent) if not opponent: - await self.bot.embed_reply(":no_entry: Opponent not found") + await ctx.embed_reply(":no_entry: Opponent not found") return # check if opponent already playing a match in this channel - if opponent != self.bot.user and self.get_chess_match(ctx.message.channel, opponent): - await self.bot.embed_reply(":no_entry: Your chosen opponent is playing a chess match here") + if opponent != self.bot.user and self.get_chess_match(ctx.channel, opponent): + await ctx.embed_reply(":no_entry: Your chosen opponent is playing a chess match here") return # prompt for color - if opponent == ctx.message.author: + if opponent == ctx.author: color = 'w' if not color: - await self.bot.embed_reply("Would you like to play white, black, or random?") - message = await self.bot.wait_for_message(author = ctx.message.author, channel = ctx.message.channel, check = lambda msg: msg.content.lower() in ("white", "black", "random", 'w', 'b', 'r')) + await ctx.embed_reply("Would you like to play white, black, or random?") + message = await self.bot.wait_for_message(author = ctx.author, channel = ctx.channel, check = lambda msg: msg.content.lower() in ("white", "black", "random", 'w', 'b', 'r')) color = message.content.lower() if color in ("random", 'r'): color = random.choice(('w', 'b')) if color in ("white", 'w'): - white_player = ctx.message.author + white_player = ctx.author black_player = opponent elif color in ("black", 'b'): white_player = opponent - black_player = ctx.message.author + black_player = ctx.author # prompt opponent - if opponent != self.bot.user and opponent != ctx.message.author: - await self.bot.say("{}: {} has challenged you to a chess match\nWould you like to accept? Yes/No".format(opponent.mention, ctx.message.author)) - message = await self.bot.wait_for_message(author = opponent, channel = ctx.message.channel, check = lambda msg: msg.content.lower() in ("yes", "no", 'y', 'n'), timeout = 300) + if opponent != self.bot.user and opponent != ctx.author: + await self.bot.say("{}: {} has challenged you to a chess match\nWould you like to accept? Yes/No".format(opponent.mention, ctx.author)) + message = await self.bot.wait_for_message(author = opponent, channel = ctx.channel, check = lambda msg: msg.content.lower() in ("yes", "no", 'y', 'n'), timeout = 300) if not message or message.content.lower() in ("no", 'n'): - await self.bot.say("{}: {} has declined your challenge".format(ctx.message.author.mention, opponent)) + await self.bot.say("{}: {} has declined your challenge".format(ctx.author.mention, opponent)) return match = chess_match() - match.initialize(self.bot, ctx.message.channel, white_player, black_player) + match.initialize(self.bot, ctx.channel, white_player, black_player) self.chess_matches.append(match) def get_chess_match(self, text_channel, player): @@ -464,102 +465,102 @@ def get_chess_match(self, text_channel, player): #dm #check mate, etc. - @chess.group(name = "board", aliases = ["match"], pass_context = True, invoke_without_command = True) + @chess.group(name = "board", aliases = ["match"], invoke_without_command = True) async def chess_board(self, ctx): '''Current match/board''' - match = self.get_chess_match(ctx.message.channel, ctx.message.author) + match = self.get_chess_match(ctx.channel, ctx.author) if not match: - await self.bot.embed_reply(":no_entry: Chess match not found") + await ctx.embed_reply(":no_entry: Chess match not found") return await match.new_match_embed() - @chess_board.command(name = "text", pass_context = True) + @chess_board.command(name = "text") async def chess_board_text(self, ctx): '''Text version of the current board''' - match = self.get_chess_match(ctx.message.channel, ctx.message.author) + match = self.get_chess_match(ctx.channel, ctx.author) if not match: - await self.bot.embed_reply(":no_entry: Chess match not found") + await ctx.embed_reply(":no_entry: Chess match not found") return await self.bot.reply(clients.code_block.format(match)) - @chess.command(name = "fen", pass_context = True) + @chess.command(name = "fen") async def chess_fen(self, ctx): '''FEN of the current board''' - match = self.get_chess_match(ctx.message.channel, ctx.message.author) + match = self.get_chess_match(ctx.channel, ctx.author) if not match: - await self.bot.embed_reply(":no_entry: Chess match not found") + await ctx.embed_reply(":no_entry: Chess match not found") return - await self.bot.embed_reply(match.fen()) + await ctx.embed_reply(match.fen()) - @chess.command(name = "pgn", pass_context = True, hidden = True) + @chess.command(name = "pgn", hidden = True) async def chess_pgn(self, ctx): '''PGN of the current game''' - match = self.get_chess_match(ctx.message.channel, ctx.message.author) + match = self.get_chess_match(ctx.channel, ctx.author) if not match: - await self.bot.embed_reply(":no_entry: Chess match not found") + await ctx.embed_reply(":no_entry: Chess match not found") return - await self.bot.embed_reply(chess.pgn.Game.from_board(match)) + await ctx.embed_reply(chess.pgn.Game.from_board(match)) - @chess.command(name = "turn", pass_context = True, hidden = True) + @chess.command(name = "turn", hidden = True) async def chess_turn(self, ctx): '''Who's turn it is to move''' - match = self.get_chess_match(ctx.message.channel, ctx.message.author) + match = self.get_chess_match(ctx.channel, ctx.author) if not match: - await self.bot.embed_reply(":no_entry: Chess match not found") + await ctx.embed_reply(":no_entry: Chess match not found") return if match.turn: - await self.bot.embed_reply("It's white's turn to move") + await ctx.embed_reply("It's white's turn to move") else: - await self.bot.embed_reply("It's black's turn to move") + await ctx.embed_reply("It's black's turn to move") """ - @chess.command(name = "reset", pass_context = True) + @chess.command(name = "reset") async def chess_reset(self, ctx): '''Reset the board''' self._chess_board.reset() - await self.bot.embed_reply("The board has been reset") + await ctx.embed_reply("The board has been reset") """ """ - @chess.command(name = "undo", pass_context = True) + @chess.command(name = "undo") async def chess_undo(self, ctx): '''Undo the previous move''' try: self._chess_board.pop() await self._display_chess_board(ctx, message = "The previous move was undone") except IndexError: - await self.bot.embed_reply(":no_entry: There are no more moves to undo") + await ctx.embed_reply(":no_entry: There are no more moves to undo") """ - @chess.command(name = "previous", aliases = ["last"], pass_context = True, hidden = True) + @chess.command(name = "previous", aliases = ["last"], hidden = True) async def chess_previous(self, ctx): '''Previous move''' - match = self.get_chess_match(ctx.message.channel, ctx.message.author) + match = self.get_chess_match(ctx.channel, ctx.author) if not match: - await self.bot.embed_reply(":no_entry: Chess match not found") + await ctx.embed_reply(":no_entry: Chess match not found") return try: - await self.bot.embed_reply(match.peek()) + await ctx.embed_reply(match.peek()) except IndexError: - await self.bot.embed_reply(":no_entry: There was no previous move") + await ctx.embed_reply(":no_entry: There was no previous move") """ - @chess.command(name = "(╯°□°)╯︵", pass_context = True, hidden = True) + @chess.command(name = "(╯°□°)╯︵", hidden = True) async def chess_flip(self, ctx): '''Flip the table over''' self._chess_board.clear() - await self.bot.say(ctx.message.author.name + " flipped the table over in anger!") + await self.bot.say(ctx.author.name + " flipped the table over in anger!") """ @commands.command(aliases = ["talk", "ask"]) @checks.not_forbidden() - async def cleverbot(self, *, message : str): + async def cleverbot(self, ctx, *, message : str): ''' Talk to Cleverbot Uses [Cleverbot](http://www.cleverbot.com/)'s [API](https://www.cleverbot.com/api/) ''' response = await self.cleverbot_get_reply(message) - await self.bot.embed_reply(response) + await ctx.embed_reply(response) async def cleverbot_get_reply(self, message): # TODO: Include user-specific conversation state @@ -571,55 +572,57 @@ async def cleverbot_get_reply(self, message): @commands.command(name = "8ball", aliases = ["eightball", "\U0001f3b1"]) @checks.not_forbidden() - async def eightball(self): + async def eightball(self, ctx): ''' Ask 8ball a yes or no question Also triggers on :8ball: without prefix ''' - await self.bot.embed_reply(":8ball: {}".format(self._eightball())) + await ctx.embed_reply(":8ball: {}".format(self._eightball())) def _eightball(self): responses = ["It is certain", "It is decidedly so", "Without a doubt", "Yes, definitely", "You may rely on it", "As I see it, yes", "Most likely", "Outlook good", "Yes", "Signs point to yes", "Reply hazy try again", "Ask again later", "Better not tell you now", "Cannot predict now", "Concentrate and ask again", "Don't count on it", "My reply is no", "My sources say no", "Outlook not so good", "Very doubtful"] return(random.choice(responses)) - @commands.group(hidden = True, pass_context = True) + @commands.group(hidden = True) @checks.not_forbidden() async def gofish(self, ctx): '''WIP''' return - @gofish.command(hidden = True, name = "start", pass_context = True, no_pm = True) + @gofish.command(hidden = True, name = "start", no_pm = True) @checks.is_owner() async def gofish_start(self, ctx, *players : str): '''WIP''' - self.gofish_channel = ctx.message.channel - if ctx.message.server: - for member in ctx.message.server.members: + self.gofish_channel = ctx.channel + if ctx.guild: + for member in ctx.guild.members: if member.name in players: self.gofish_players.append(member) break else: - await self.bot.embed_reply(":no_entry: Please use that command in a server") + await ctx.embed_reply(":no_entry: Please use that command in a server") pass gofish.start(len(players)) gofish_players_string = "" for player in self.gofish_players: gofish_players_string += player.name + " and " - await self.bot.embed_reply("{} has started a game of Go Fish between {}!".format(message.author.display_name, gofish_players_string[:-5])) + await ctx.embed_reply("{} has started a game of Go Fish between {}!".format(message.author.display_name, gofish_players_string[:-5])) - @gofish.command(hidden = True, name = "hand", pass_context = True) + @gofish.command(hidden = True, name = "hand") + @commands.is_owner() async def gofish_hand(self, ctx): '''WIP''' - if ctx.message.author in gofish_players: - await self.bot.whisper("Your hand: " + gofish.hand(gofish_players.index(ctx.message.author) + 1)) + if ctx.author in gofish_players: + await self.bot.whisper("Your hand: " + gofish.hand(gofish_players.index(ctx.author) + 1)) - @gofish.command(hidden = True, name = "ask", pass_context = True) + @gofish.command(hidden = True, name = "ask") + @commands.is_owner() async def gofish_ask(self, ctx): '''WIP''' - if ctx.message.author in gofish_players: + if ctx.author in gofish_players: pass - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def guess(self, ctx, *options : str): ''' @@ -632,42 +635,42 @@ async def guess(self, ctx, *options : str): if len(options) >= 1 and utilities.is_digit_gtz(options[0]): max_value = int(options[0]) else: - await self.bot.embed_reply("What range of numbers would you like to guess to? 1 to _") - max_value = await self.bot.wait_for_message(timeout = clients.wait_time, author = ctx.message.author, check = utilities.message_is_digit_gtz) + await ctx.embed_reply("What range of numbers would you like to guess to? 1 to _") + max_value = await self.bot.wait_for_message(timeout = clients.wait_time, author = ctx.author, check = utilities.message_is_digit_gtz) if max_value is None: max_value = 10 else: max_value = int(max_value.content) answer = random.randint(1, max_value) if not tries: - await self.bot.embed_reply("How many tries would you like?") - tries = await self.bot.wait_for_message(timeout = clients.wait_time, author = ctx.message.author, check = utilities.message_is_digit_gtz) + await ctx.embed_reply("How many tries would you like?") + tries = await self.bot.wait_for_message(timeout = clients.wait_time, author = ctx.author, check = utilities.message_is_digit_gtz) if tries is None: tries = 1 else: tries = int(tries.content) - await self.bot.embed_reply("Guess a number between 1 to {}".format(max_value)) + await ctx.embed_reply("Guess a number between 1 to {}".format(max_value)) while tries != 0: - guess = await self.bot.wait_for_message(timeout = clients.wait_time, author = ctx.message.author, check = utilities.message_is_digit_gtz) + guess = await self.bot.wait_for_message(timeout = clients.wait_time, author = ctx.author, check = utilities.message_is_digit_gtz) if guess is None: - await self.bot.embed_reply("Sorry, you took too long\nIt was {}".format(answer)) + await ctx.embed_reply("Sorry, you took too long\nIt was {}".format(answer)) return if int(guess.content) == answer: - await self.bot.embed_reply("You are right!") + await ctx.embed_reply("You are right!") return elif tries != 1 and int(guess.content) > answer: - await self.bot.embed_reply("It's less than " + guess.content) + await ctx.embed_reply("It's less than " + guess.content) tries -= 1 elif tries != 1 and int(guess.content) < answer: - await self.bot.embed_reply("It's greater than " + guess.content) + await ctx.embed_reply("It's greater than " + guess.content) tries -= 1 else: - await self.bot.embed_reply("Sorry, it was actually {}".format(answer)) + await ctx.embed_reply("Sorry, it was actually {}".format(answer)) return @commands.group(aliases = ["hrmp"], hidden = True) @checks.not_forbidden() - async def harmonopoly(self): + async def harmonopoly(self, ctx): ''' WIP Harmonopoly is a game based on The Centipede Game where every player chooses a number. @@ -676,7 +679,7 @@ async def harmonopoly(self): ''' pass - @commands.group(invoke_without_command = True, pass_context = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def jeopardy(self, ctx, row_number : int, value : int): ''' @@ -685,16 +688,16 @@ async def jeopardy(self, ctx, row_number : int, value : int): Based on Jeopardy ''' if not self.jeopardy_active: - await self.bot.embed_reply(":no_entry: There's not a jeopardy game currently in progress") + await ctx.embed_reply(":no_entry: There's not a jeopardy game currently in progress") return if self.jeopardy_question_active: - await self.bot.embed_reply(":no_entry: There's already a jeopardy question in play") + await ctx.embed_reply(":no_entry: There's already a jeopardy question in play") return if row_number < 1 or row_number > 6: - await self.bot.embed_reply(":no_entry: That's not a valid row number") + await ctx.embed_reply(":no_entry: That's not a valid row number") return if value not in [200, 400, 600, 800, 1000]: - await self.bot.embed_reply(":no_entry: That's not a valid value") + await ctx.embed_reply(":no_entry: That's not a valid value") return value_index = ["200", "400", "600", "800", "1000"].index(str(value)) if not self.jeopardy_board[row_number - 1][value_index + 1]: @@ -744,10 +747,10 @@ async def jeopardy_wait_for_answer(self): #jeopardy stats - @jeopardy.command(name = "start", pass_context = True) + @jeopardy.command(name = "start") async def jeopardy_start(self, ctx): if self.jeopardy_active: - await self.bot.embed_reply(":no_entry: There's already a jeopardy game in progress") + await ctx.embed_reply(":no_entry: There's already a jeopardy game in progress") return self.jeopardy_active = True categories = [] @@ -769,7 +772,7 @@ async def jeopardy_start(self, ctx): self.jeopardy_board_output += category_title.ljust(self.jeopardy_max_width) + " 200 400 600 800 1000\n" await self.bot.embed_say(clients.code_block.format(self.jeopardy_board_output)) - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def maze(self, ctx): ''' @@ -777,9 +780,9 @@ async def maze(self, ctx): [w, a, s, d] to move Also see mazer ''' - await self.bot.embed_reply("See {}help maze".format(ctx.prefix)) + await ctx.embed_reply("See {}help maze".format(ctx.prefix)) - @maze.command(name = "start", aliases = ["begin"], pass_context = True) + @maze.command(name = "start", aliases = ["begin"]) @checks.not_forbidden() async def maze_start(self, ctx, width : int = 5, height : int = 5, random_start : bool = False, random_end : bool = False): ''' @@ -787,12 +790,12 @@ async def maze_start(self, ctx, width : int = 5, height : int = 5, random_start width: 2 - 100 height: 2 - 100 ''' - if ctx.message.channel.id in self.mazes: - await self.bot.embed_reply(":no_entry: There's already a maze game going on") + if ctx.channel.id in self.mazes: + await ctx.embed_reply(":no_entry: There's already a maze game going on") return - self.mazes[ctx.message.channel.id] = maze.Maze(width, height, random_start = random_start, random_end = random_end) - maze_instance = self.mazes[ctx.message.channel.id] - maze_message, embed = await self.bot.embed_reply(clients.code_block.format(maze_instance.print_visible())) + self.mazes[ctx.channel.id] = maze.Maze(width, height, random_start = random_start, random_end = random_end) + maze_instance = self.mazes[ctx.channel.id] + maze_message = await ctx.embed_reply(clients.code_block.format(maze_instance.print_visible())) ''' maze_print = "" for r in maze_instance.test_print(): @@ -805,42 +808,42 @@ async def maze_start(self, ctx, width : int = 5, height : int = 5, random_start # await self.bot.reply(clients.code_block.format(repr(maze_instance))) convert_move = {'w' : 'n', 'a' : 'w', 's' : 's', 'd' : 'e'} while not maze_instance.reached_end(): - move = await self.bot.wait_for_message(check = lambda message: message.content.lower() in ['w', 'a', 's', 'd'] and message.channel == ctx.message.channel) # author = ctx.message.author + move = await self.bot.wait_for_message(check = lambda message: message.content.lower() in ['w', 'a', 's', 'd'] and message.channel == ctx.channel) # author = ctx.author moved = maze_instance.move(convert_move[move.content.lower()]) response = clients.code_block.format(maze_instance.print_visible()) if not moved: response += "\n:no_entry: You can't go that way" - new_maze_message, embed = await self.bot.embed_reply(response) + new_maze_message = await ctx.embed_reply(response) try: await self.bot.delete_message(move) await self.bot.delete_message(maze_message) except discord.errors.Forbidden: pass maze_message = new_maze_message - await self.bot.embed_reply("Congratulations! You reached the end of the maze in {} moves".format(maze_instance.move_counter)) - del self.mazes[ctx.message.channel.id] + await ctx.embed_reply("Congratulations! You reached the end of the maze in {} moves".format(maze_instance.move_counter)) + del self.mazes[ctx.channel.id] - @maze.command(name = "current", pass_context = True) + @maze.command(name = "current") @checks.not_forbidden() async def maze_current(self, ctx): '''Current maze game''' - if ctx.message.channel.id in self.mazes: - await self.bot.embed_reply(clients.code_block.format(self.mazes[ctx.message.channel.id].print_visible())) + if ctx.channel.id in self.mazes: + await ctx.embed_reply(clients.code_block.format(self.mazes[ctx.channel.id].print_visible())) else: - await self.bot.embed_reply(":no_entry: There's no maze game currently going on") + await ctx.embed_reply(":no_entry: There's no maze game currently going on") # add maze print, position? @commands.group() @checks.not_forbidden() - async def poker(self): + async def poker(self, ctx): '''WIP''' ... - @poker.command(name = "start", pass_context = True) + @poker.command(name = "start") async def poker_start(self, ctx): if self.poker_status not in (None, "started"): - await self.bot.embed_reply("There's already a round of poker in progress") + await ctx.embed_reply("There's already a round of poker in progress") elif self.poker_status is None: self.poker_status = "started" self.poker_players = [] @@ -849,7 +852,7 @@ async def poker_start(self, ctx): self.poker_deck = pydealer.Deck() self.poker_deck.shuffle() self.poker_pot = 0 - await self.bot.embed_say("{0} has started a round of poker\n`{1}poker join` to join\n`{1}poker start` again to start".format(ctx.message.author.display_name, ctx.prefix)) + await self.bot.embed_say("{0} has started a round of poker\n`{1}poker join` to join\n`{1}poker start` again to start".format(ctx.author.display_name, ctx.prefix)) else: self.poker_status = "pre-flop" await self.bot.embed_say("The poker round has started\nPlayers: {}".format(" ".join([player.mention for player in self.poker_players]))) @@ -899,67 +902,67 @@ async def poker_start(self, ctx): type = evaluator.class_to_string(evaluator.get_rank_class(best_hand_value)) await self.bot.embed_say("{} is the winner with a {}".format(player.mention, type)) - @poker.command(name = "join", pass_context = True) + @poker.command(name = "join") async def poker_join(self, ctx): if self.poker_status == "started": - self.poker_players.append(ctx.message.author) - self.poker_hands[ctx.message.author.id] = self.poker_deck.deal(2) - await self.bot.embed_say("{} has joined the poker match".format(ctx.message.author.display_name)) + self.poker_players.append(ctx.author) + self.poker_hands[ctx.author.id] = self.poker_deck.deal(2) + await self.bot.embed_say("{} has joined the poker match".format(ctx.author.display_name)) elif self.poker_status is None: - await self.bot.embed_reply("There's not currently a round of poker going on\nUse `{}poker start` to start one".format(ctx.prefix)) + await ctx.embed_reply("There's not currently a round of poker going on\nUse `{}poker start` to start one".format(ctx.prefix)) else: - await self.bot.embed_reply(":no_entry: The current round of poker already started") + await ctx.embed_reply(":no_entry: The current round of poker already started") - @poker.command(name = "raise", pass_context = True) + @poker.command(name = "raise") async def poker_raise(self, ctx, points : int): - if self.poker_turn and self.poker_turn.id == ctx.message.author.id: + if self.poker_turn and self.poker_turn.id == ctx.author.id: if points > self.poker_current_bet: self.poker_bets[self.poker_turn.id] = points self.poker_current_bet = points - await self.bot.embed_reply("{} has raised to {}".format(ctx.message.author.display_name, points)) + await ctx.embed_reply("{} has raised to {}".format(ctx.author.display_name, points)) self.poker_turn = None elif points == self.poker_current_bet: self.poker_bets[self.poker_turn.id] = points - await self.bot.embed_say("{} has called".format(ctx.message.author.display_name)) + await self.bot.embed_say("{} has called".format(ctx.author.display_name)) self.poker_turn = None else: - await self.bot.embed_reply("The current bet is more than that") + await ctx.embed_reply("The current bet is more than that") else: - await self.bot.embed_reply(":no_entry: You can't do that right now") + await ctx.embed_reply(":no_entry: You can't do that right now") - @poker.command(name = "call", pass_context = True) + @poker.command(name = "call") async def poker_call(self, ctx): - if self.poker_turn and self.poker_turn.id == ctx.message.author.id: + if self.poker_turn and self.poker_turn.id == ctx.author.id: if self.poker_current_bet == 0 or (self.poker_turn.id in self.poker_bets and self.poker_bets[self.poker_turn.id] == self.poker_current_bet): - await self.bot.embed_reply("You can't call\nYou have checked instead") - await self.bot.embed_say("{} has checked".format(ctx.message.author.display_name)) + await ctx.embed_reply("You can't call\nYou have checked instead") + await self.bot.embed_say("{} has checked".format(ctx.author.display_name)) else: self.poker_bets[self.poker_turn.id] = self.poker_current_bet - await self.bot.embed_say("{} has called".format(ctx.message.author.display_name)) + await self.bot.embed_say("{} has called".format(ctx.author.display_name)) self.poker_turn = None else: - await self.bot.embed_reply(":no_entry: You can't do that right now") + await ctx.embed_reply(":no_entry: You can't do that right now") - @poker.command(name = "check", pass_context = True) + @poker.command(name = "check") async def poker_check(self, ctx): - if self.poker_turn and self.poker_turn.id == ctx.message.author.id: + if self.poker_turn and self.poker_turn.id == ctx.author.id: if self.poker_current_bet != 0 and (self.poker_turn.id not in self.poker_bets or self.poker_bets[self.poker_turn.id] < self.poker_current_bet): - await self.bot.embed_reply(":no_entry: You can't check") + await ctx.embed_reply(":no_entry: You can't check") else: self.poker_bets[self.poker_turn.id] = self.poker_current_bet - await self.bot.embed_say("{} has checked".format(ctx.message.author.display_name)) + await self.bot.embed_say("{} has checked".format(ctx.author.display_name)) self.poker_turn = None else: - await self.bot.embed_reply(":no_entry: You can't do that right now.") + await ctx.embed_reply(":no_entry: You can't do that right now.") - @poker.command(name = "fold", pass_context = True) + @poker.command(name = "fold") async def poker_fold(self, ctx): - if self.poker_turn and self.poker_turn.id == ctx.message.author.id: + if self.poker_turn and self.poker_turn.id == ctx.author.id: self.poker_bets[self.poker_turn.id] = -1 self.poker_folded.append(self.poker_turn) self.poker_turn = None else: - await self.bot.embed_reply(":no_entry: You can't do that right now") + await ctx.embed_reply(":no_entry: You can't do that right now") async def poker_betting(self): self.poker_status = "betting" @@ -979,14 +982,14 @@ async def poker_betting(self): self.poker_pot += bet self.poker_status = None - @commands.command(aliases = ["rtg", "reactiontime", "reactiontimegame", "reaction_time_game"], pass_context = True) + @commands.command(aliases = ["rtg", "reactiontime", "reactiontimegame", "reaction_time_game"]) @checks.not_forbidden() async def reaction_time(self, ctx): '''Reaction time game''' response, embed = await self.bot.say("Please choose 10 reactions") while len(response.reactions) < 10: await self.bot.wait_for_reaction(message = response) - response = await self.bot.get_message(ctx.message.channel, response.id) + response = await self.bot.get_message(ctx.channel, response.id) reactions = response.reactions reaction = random.choice(reactions) await self.bot.edit_message(response, "Please wait..") @@ -1007,53 +1010,53 @@ async def reaction_time(self, ctx): @commands.command(aliases = ["rockpaperscissors", "rock-paper-scissors", "rock_paper_scissors"]) @checks.not_forbidden() - async def rps(self, object : str): + async def rps(self, ctx, object : str): '''Rock paper scissors''' if object.lower() not in ('r', 'p', 's', "rock", "paper", "scissors"): - await self.bot.embed_reply(":no_entry: That's not a valid object") + await ctx.embed_reply(":no_entry: That's not a valid object") return value = random.choice(("rock", "paper", "scissors")) short_shape = object[0].lower() resolution = {'r': {'s': "crushes"}, 'p': {'r': "covers"}, 's': {'p': "cuts"}} - emotes = {'r': ":fist::skin-tone-2:", 'p': ":raised_hand::skin-tone-2:", 's': ":v::skin-tone-2:"} + emotes = {'r': ":fist:", 'p': ":raised_hand:", 's': ":v:"} if value[0] == short_shape: - await self.bot.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) + await ctx.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) elif short_shape in resolution[value[0]]: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[value[0]], resolution[value[0]][short_shape], emotes[short_shape])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[value[0]], resolution[value[0]][short_shape], emotes[short_shape])) else: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[short_shape], resolution[short_shape][value[0]], emotes[value[0]])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[short_shape], resolution[short_shape][value[0]], emotes[value[0]])) @commands.command(aliases = ["rockpaperscissorslizardspock", "rock-paper-scissors-lizard-spock"]) @checks.not_forbidden() - async def rpsls(self, object : str): + async def rpsls(self, ctx, object : str): ''' RPS lizard Spock https://upload.wikimedia.org/wikipedia/commons/f/fe/Rock_Paper_Scissors_Lizard_Spock_en.svg ''' if object.lower() not in ('r', 'p', 's', 'l', "rock", "paper", "scissors", "lizard", "spock"): - await self.bot.embed_reply(":no_entry: That's not a valid object") + await ctx.embed_reply(":no_entry: That's not a valid object") else: value = random.choice(("rock", "paper", "scissors", "lizard", "Spock")) short_shape = 'S' if object[0] == 'S' and object.lower() != "scissors" or object.lower() == "spock" else object[0].lower() resolution = {'r': {'s': "crushes", 'l': "crushes"}, 'p': {'r': "covers", 'S': "disproves"}, 's': {'p': "cuts", 'l': "decapitates"}, 'l': {'p': "eats", 'S': "poisons"}, 'S': {'r': "vaporizes", 's': "smashes"}} - emotes = {'r': ":fist::skin-tone-2:", 'p': ":raised_hand::skin-tone-2:", 's': ":v::skin-tone-2:", 'l': ":lizard:", 'S': ":vulcan::skin-tone-2:"} + emotes = {'r': ":fist:", 'p': ":raised_hand:", 's': ":v:", 'l': ":lizard:", 'S': ":vulcan:"} if value[0] == short_shape: - await self.bot.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) + await ctx.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) elif short_shape in resolution[value[0]]: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[value[0]], resolution[value[0]][short_shape], emotes[short_shape])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[value[0]], resolution[value[0]][short_shape], emotes[short_shape])) else: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[short_shape], resolution[short_shape][value[0]], emotes[value[0]])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[short_shape], resolution[short_shape][value[0]], emotes[value[0]])) @commands.command(aliases = ["rockpaperscissorslizardspockspidermanbatmanwizardglock", "rock-paper-scissors-lizard-spock-spiderman-batman-wizard-glock"]) @checks.not_forbidden() - async def rpslssbwg(self, object : str): + async def rpslssbwg(self, ctx, object : str): ''' RPSLS Spider-Man Batman wizard Glock http://i.imgur.com/m9C2UTP.jpg ''' object = object.lower().replace('-', "") if object not in ("rock", "paper", "scissors", "lizard", "spock", "spiderman", "batman", "wizard", "glock"): - await self.bot.embed_reply(":no_entry: That's not a valid object") + await ctx.embed_reply(":no_entry: That's not a valid object") else: value = random.choice(("rock", "paper", "scissors", "lizard", "Spock", "Spider-Man", "Batman", "wizard", "Glock")) resolution = {"rock": {"scissors": "crushes", "lizard": "crushes", "spiderman": "knocks out", "wizard": "interrupts"}, @@ -1065,39 +1068,39 @@ async def rpslssbwg(self, object : str): "batman": {"rock": "explodes", "scissors": "dismantles", "spiderman": "scares", "spock": "hangs"}, "wizard": {"paper": "burns", "lizard": "transforms", "batman": "stuns", "glock": "melts"}, "glock": {"rock": "breaks", "scissors": "dents", "batman": "kills parents of", "spock": "shoots"}} - emotes = {"rock": ":fist::skin-tone-2:", "paper": ":raised_hand::skin-tone-2:", "scissors": ":v::skin-tone-2:", "lizard": ":lizard:", "spock": ":vulcan::skin-tone-2:", "spiderman": ":spider:", "batman": ":bat:", "wizard": ":tophat:", "glock": ":gun:"} + emotes = {"rock": ":fist:", "paper": ":raised_hand:", "scissors": ":v:", "lizard": ":lizard:", "spock": ":vulcan:", "spiderman": ":spider:", "batman": ":bat:", "wizard": ":tophat:", "glock": ":gun:"} standard_value = value.lower().replace('-', "") if standard_value == object: - await self.bot.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) + await ctx.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) elif object in resolution[standard_value]: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[standard_value], resolution[standard_value][object], emotes[object])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[standard_value], resolution[standard_value][object], emotes[object])) else: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[object], resolution[object][standard_value], emotes[standard_value])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[object], resolution[object][standard_value], emotes[standard_value])) @commands.command(aliases = ["cockroachfootnuke", "cockroach-foot-nuke"]) @checks.not_forbidden() - async def cfn(self, object : str): + async def cfn(self, ctx, object : str): ''' Cockroach foot nuke https://www.youtube.com/watch?v=wRi2j8k0vjo ''' if object.lower() not in ('c', 'f', 'n', "cockroach", "foot", "nuke"): - await self.bot.embed_reply(":no_entry: That's not a valid object") + await ctx.embed_reply(":no_entry: That's not a valid object") else: value = random.choice(("cockroach", "foot", "nuke")) short_shape = object[0].lower() resolution = {'c': {'n': "survives"}, 'f': {'c': "squashes"}, 'n': {'f': "blows up"}} emotes = {'c': ":bug:", 'f': ":footprints:", 'n': ":bomb:"} if value[0] == short_shape: - await self.bot.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) + await ctx.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) elif short_shape in resolution[value[0]]: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[value[0]], resolution[value[0]][short_shape], emotes[short_shape])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[value[0]], resolution[value[0]][short_shape], emotes[short_shape])) else: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[short_shape], resolution[short_shape][value[0]], emotes[value[0]])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[short_shape], resolution[short_shape][value[0]], emotes[value[0]])) @commands.command(aliases = ["extremerps", "rps-101", "rps101"]) @checks.not_forbidden() - async def erps(self, object : str): + async def erps(self, ctx, object : str): ''' Extreme rock paper scissors http://www.umop.com/rps101.htm @@ -1108,7 +1111,7 @@ async def erps(self, object : str): object = object.lower().replace('.', "").replace("video game", "game") # dynamite: outwits gun # tornado: sweeps away -> blows away, fills pit, ruins camera - emotes = {"dynamite": ":boom:", "tornado": ":cloud_tornado:", "quicksand": "quicksand", "pit": ":black_circle:", "chain": ":chains:", "gun": ":gun:", "law": ":scales:", "whip": "whip", "sword": ":crossed_swords:", "rock": ":fist::skin-tone-2:", "death": ":skull:", "wall": "wall", "sun": ":sunny:", "camera": ":camera:", "fire": ":fire:", "chainsaw": "chainsaw", "school": ":school:", "scissors": ":scissors:", "poison": "poison", "cage": "cage", "axe": "axe", "peace": ":peace:", "computer": ":computer:", "castle": ":european_castle:", "snake": ":snake:", "blood": "blood", "porcupine": "porcupine", "vulture": "vulture", "monkey": ":monkey:", "king": "king", "queen": "queen", "prince": "prince", "princess": "princess", "police": ":police_car:", "woman": ":woman::skin-tone-2:", "baby": ":baby::skin-tone-2:", "man": ":man::skin-tone-2:", "home": ":homes:", "train": ":train:", "car": ":red_car:", "noise": "noise", "bicycle": ":bicyclist::skin-tone-2:", "tree": ":evergreen_tree:", "turnip": "turnip", "duck": ":duck:", "wolf": ":wolf:", "cat": ":cat:", "bird": ":bird:", "fish": ":fish:", "spider": ":spider:", "cockroach": "cockroach", "brain": "brain", "community": "community", "cross": ":cross:", "money": ":moneybag:", "vampire": "vampire", "sponge": "sponge", "church": ":church:", "butter": "butter", "book": ":book:", "paper": ":raised_hand::skin-tone-2:", "cloud": ":cloud:", "airplane": ":airplane:", "moon": ":full_moon:", "grass": "grass", "film": ":film_frames:", "toilet": ":toilet:", "air": "air", "planet": "planet", "guitar": ":guitar:", "bowl": "bowl", "cup": "cup", "beer": ":beer:", "rain": ":cloud_rain:", "water": ":potable_water:", "tv": ":tv:", "rainbow": ":rainbow:", "ufo": "ufo", "alien": ":alien:", "prayer": ":pray::skin-tone-2:", "mountain": ":mountain:", "satan": "satan", "dragon": ":dragon:", "diamond": "diamond", "platinum": "platinum", "gold": "gold", "devil": "devil", "fence": "fence", "game": ":video_game:", "math": "math", "robot": ":robot:", "heart": ":heart:", "electricity": ":zap:", "lightning": ":cloud_lightning:", "medusa": "medusa", "power": ":electric_plug:", "laser": "laser", "nuke": ":bomb:", "sky": "sky", "tank": "tank", "helicopter": ":helicopter:"} + emotes = {"dynamite": ":boom:", "tornado": ":cloud_tornado:", "quicksand": "quicksand", "pit": ":black_circle:", "chain": ":chains:", "gun": ":gun:", "law": ":scales:", "whip": "whip", "sword": ":crossed_swords:", "rock": ":fist:", "death": ":skull:", "wall": "wall", "sun": ":sunny:", "camera": ":camera:", "fire": ":fire:", "chainsaw": "chainsaw", "school": ":school:", "scissors": ":scissors:", "poison": "poison", "cage": "cage", "axe": "axe", "peace": ":peace:", "computer": ":computer:", "castle": ":european_castle:", "snake": ":snake:", "blood": "blood", "porcupine": "porcupine", "vulture": "vulture", "monkey": ":monkey:", "king": "king", "queen": "queen", "prince": "prince", "princess": "princess", "police": ":police_car:", "woman": ":woman:", "baby": ":baby:", "man": ":man:", "home": ":homes:", "train": ":train:", "car": ":red_car:", "noise": "noise", "bicycle": ":bicyclist:", "tree": ":evergreen_tree:", "turnip": "turnip", "duck": ":duck:", "wolf": ":wolf:", "cat": ":cat:", "bird": ":bird:", "fish": ":fish:", "spider": ":spider:", "cockroach": "cockroach", "brain": "brain", "community": "community", "cross": ":cross:", "money": ":moneybag:", "vampire": "vampire", "sponge": "sponge", "church": ":church:", "butter": "butter", "book": ":book:", "paper": ":raised_hand:", "cloud": ":cloud:", "airplane": ":airplane:", "moon": ":full_moon:", "grass": "grass", "film": ":film_frames:", "toilet": ":toilet:", "air": "air", "planet": "planet", "guitar": ":guitar:", "bowl": "bowl", "cup": "cup", "beer": ":beer:", "rain": ":cloud_rain:", "water": ":potable_water:", "tv": ":tv:", "rainbow": ":rainbow:", "ufo": "ufo", "alien": ":alien:", "prayer": ":pray:", "mountain": ":mountain:", "satan": "satan", "dragon": ":dragon:", "diamond": "diamond", "platinum": "platinum", "gold": "gold", "devil": "devil", "fence": "fence", "game": ":video_game:", "math": "math", "robot": ":robot:", "heart": ":heart:", "electricity": ":zap:", "lightning": ":cloud_lightning:", "medusa": "medusa", "power": ":electric_plug:", "laser": "laser", "nuke": ":bomb:", "sky": "sky", "tank": "tank", "helicopter": ":helicopter:"} ''' for _object in emotes: if _object == emotes[_object]: @@ -1120,15 +1123,15 @@ async def erps(self, object : str): resolution = json.load(erps_file) value = random.choice(list(emotes.keys())) if object not in emotes: - await self.bot.embed_reply(":no_entry: That's not a valid object") + await ctx.embed_reply(":no_entry: That's not a valid object") else: standard_value = value.lower().replace('.', "").replace("video game", "game") if standard_value == object: - await self.bot.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) + await ctx.embed_reply("\nI chose `{}`\nIt's a draw :confused:".format(value)) elif object in resolution[standard_value]: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[standard_value], resolution[standard_value][object], emotes[object])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou lose :slight_frown:".format(value, emotes[standard_value], resolution[standard_value][object], emotes[object])) elif standard_value in resolution[object]: - await self.bot.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[object], resolution[object][standard_value], emotes[standard_value])) + await ctx.embed_reply("\nI chose `{}`\n{} {} {}\nYou win! :tada:".format(value, emotes[object], resolution[object][standard_value], emotes[standard_value])) async def generate_erps_dict(self): async with clients.aiohttp_session.get("http://www.umop.com/rps101/alloutcomes.htm") as resp: @@ -1153,29 +1156,29 @@ async def generate_erps_dict(self): @commands.group(hidden = True) @checks.not_forbidden() - async def taboo(self): + async def taboo(self, ctx): '''WIP''' return - @taboo.command(hidden = True, name = "start", pass_context = True, no_pm = True) + @taboo.command(hidden = True, name = "start", no_pm = True) async def taboo_start(self, ctx, player : str): '''WIP''' - self.taboo_players.append(ctx.message.author) - for member in self.message.server.members: + self.taboo_players.append(ctx.author) + for member in self.message.guild.members: if member.name == player: self.taboo_players.append(member) break - await self.bot.embed_reply(" has started a game of Taboo with " + taboo_players[1].mention) + await ctx.embed_reply(" has started a game of Taboo with " + taboo_players[1].mention) await self.bot.whisper("You have started a game of Taboo with " + taboo_players[1].name) - await self.bot.send_message(taboo_players[1], ctx.message.author.name + " has started a game of Taboo with you.") + await self.bot.send_message(taboo_players[1], ctx.author.name + " has started a game of Taboo with you.") @taboo.command(hidden = True, name = "nextround") # no_pm = True ? - async def taboo_nextround(self): + async def taboo_nextround(self, ctx): '''WIP''' - if message.server: + if message.guild: pass - @commands.group(invoke_without_command = True, pass_context = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def trivia(self, ctx, *options : str): ''' @@ -1195,7 +1198,7 @@ async def trivia(self, ctx, *options : str): bet_message, embed = await self.bot.embed_say(None, title = string.capwords(data["category"]["title"]), footer_text = "You have {} seconds left to bet".format(self.bet_countdown)) bet_countdown_task = self.bot.loop.create_task(self._bet_countdown(bet_message, embed)) while self.bet_countdown: - message = await self.bot.wait_for_message(timeout = self.bet_countdown, channel = ctx.message.channel, check = lambda m: m.content.isdigit()) + message = await self.bot.wait_for_message(timeout = self.bet_countdown, channel = ctx.channel, check = lambda m: m.content.isdigit()) if message: if int(message.content) <= self.trivia_stats[message.author.id][2]: # check if new player bets[message.author] = int(message.content) @@ -1211,7 +1214,7 @@ async def trivia(self, ctx, *options : str): answer_message, embed = await self.bot.embed_say(data["question"], title = string.capwords(data["category"]["title"]), footer_text = "You have {} seconds left to answer".format(self.trivia_countdown)) countdown_task = self.bot.loop.create_task(self._trivia_countdown(answer_message, embed)) while self.trivia_countdown: - message = await self.bot.wait_for_message(timeout = self.trivia_countdown, channel = ctx.message.channel) + message = await self.bot.wait_for_message(timeout = self.trivia_countdown, channel = ctx.channel) if message and not message.content.startswith(('!', '>')): responses[message.author] = message.content while not countdown_task.done(): @@ -1270,7 +1273,7 @@ async def trivia(self, ctx, *options : str): await self.bot.embed_say(trivia_bets_output) self.trivia_active = False else: - await self.bot.embed_reply("There is already an ongoing game of trivia\nOther options: score money") + await ctx.embed_reply("There is already an ongoing game of trivia\nOther options: score money") async def _bet_countdown(self, bet_message, embed): while self.bet_countdown: @@ -1291,26 +1294,27 @@ async def _trivia_countdown(self, answer_message, embed): # if answer == data["q_correct_option"]: # await self.bot.say("The answer was " + str(data["q_correct_option"]) + ". " + data["q_options_" + str(data["q_correct_option"])] + "\n" + correct_players_output) - @trivia.command(name = "score", aliases = ["points", "rank", "level"], pass_context = True) + @trivia.command(name = "score", aliases = ["points", "rank", "level"]) async def trivia_score(self, ctx): '''Trivia score''' - correct = self.trivia_stats[ctx.message.author.id][0] - incorrect = self.trivia_stats[ctx.message.author.id][1] + correct = self.trivia_stats[ctx.author.id][0] + incorrect = self.trivia_stats[ctx.author.id][1] correct_percentage = correct / (correct + incorrect) * 100 - await self.bot.embed_reply("You have answered {}/{} ({:.2f}%) correctly.".format(correct, correct + incorrect, correct_percentage)) + await ctx.embed_reply("You have answered {}/{} ({:.2f}%) correctly.".format(correct, correct + incorrect, correct_percentage)) - @trivia.command(name = "money", aliases = ["cash"], pass_context = True) + @trivia.command(name = "money", aliases = ["cash"]) async def trivia_money(self, ctx): '''Trivia money''' - cash = self.trivia_stats[ctx.message.author.id][2] - await self.bot.embed_reply("You have $" + utilities.add_commas(cash)) + cash = self.trivia_stats[ctx.author.id][2] + await ctx.embed_reply("You have $" + utilities.add_commas(cash)) - @trivia.command(name = "scores", aliases = ["scoreboard", "top", "ranks", "levels"], pass_context = True) + @trivia.command(name = "scores", aliases = ["scoreboard", "top", "ranks", "levels"]) async def trivia_scores(self, ctx, number : int = 10): '''Trivia scores''' if number > 15: number = 15 top_scores = sorted(self.trivia_stats.items(), key = lambda p: p[1][0], reverse = True)[:number] - response, embed = await self.bot.embed_reply(None, title = "Trivia Top {}".format(number)) + response = await ctx.embed_reply(title = "Trivia Top {}".format(number)) + embed = response.embeds[0] for user in top_scores: user_info = await self.bot.get_user_info(user[0]) correct = user[1][0] @@ -1319,7 +1323,7 @@ async def trivia_scores(self, ctx, number : int = 10): embed.add_field(name = user_info, value = "{}/{} correct ({:.2f}%)\n".format(correct, correct + incorrect, correct_percentage)) await self.bot.edit_message(response, embed = embed) - @commands.group(pass_context = True) + @commands.group() @checks.not_forbidden() async def war(self, ctx): ''' @@ -1328,48 +1332,51 @@ async def war(self, ctx): ''' return - @war.command(name = "start", pass_context = True, no_pm = True) + @war.command(name = "start", no_pm = True) @checks.is_owner() async def war_start(self, ctx, *players : str): '''Start a game of War''' self.war_players = [] - for member in ctx.message.server.members: + for member in ctx.guild.members: if member.name in players: self.war_players.append(member) break war.start(len(players)) - self.war_channel = ctx.message.channel + self.war_channel = ctx.channel war_players_string = "" for player in self.war_players: war_players_string += player.name + " and " - await self.bot.embed_reply("{} has started a game of War between {}!".format(ctx.message.author.display_name, war_players_string[:-5])) + await ctx.embed_reply("{} has started a game of War between {}!".format(ctx.author.display_name, war_players_string[:-5])) - @war.command(name = "hand", pass_context = True) + @war.command(name = "hand") + @commands.is_owner() async def war_hand(self, ctx): '''See your current hand''' - if ctx.message.author in self.war_players: - await self.bot.whisper("Your hand: " + war.hand(self.war_players.index(ctx.message.author) + 1)) + if ctx.author in self.war_players: + await self.bot.whisper("Your hand: " + war.hand(self.war_players.index(ctx.author) + 1)) - @war.command(name = "left", pass_context = True) + @war.command(name = "left") + @commands.is_owner() async def war_left(self, ctx): '''See how many cards you have left''' - if ctx.message.author in self.war_players: - await self.bot.embed_reply("You have {} cards left".format(war.card_count(self.war_players.index(ctx.message.author) + 1))) + if ctx.author in self.war_players: + await ctx.embed_reply("You have {} cards left".format(war.card_count(self.war_players.index(ctx.author) + 1))) - @war.command(name = "play", pass_context = True) + @war.command(name = "play") + @commands.is_owner() async def war_play(self, ctx, *card : str): '''Play a card''' - if ctx.message.author in self.war_players: + if ctx.author in self.war_players: player_number = self.war_players.index(message.author) + 1 winner, cardsplayed, tiedplayers = war.play(player_number, ' '.join(card)) if winner == -1: - await self.bot.embed_reply(":no_entry: You have already chosen your card for this battle") + await ctx.embed_reply(":no_entry: You have already chosen your card for this battle") elif winner == -3: - await self.bot.embed_reply(":no_entry: You are not in this battle") + await ctx.embed_reply(":no_entry: You are not in this battle") elif winner == -4: - await self.bot.embed_reply(":no_entry: Card not found in your hand") + await ctx.embed_reply(":no_entry: Card not found in your hand") else: - await self.bot.embed_reply("You chose the {} of {}".format(cardsplayed[player_number - 1].value, cardsplayed[player_number - 1].suit)) + await ctx.embed_reply("You chose the {} of {}".format(cardsplayed[player_number - 1].value, cardsplayed[player_number - 1].suit)) await self.bot.whisper("Your hand: " + war.hand(player_number)) if winner > 0: winner_name = self.war_players[winner - 1].name diff --git a/Discord/cogs/meta.py b/Discord/cogs/meta.py index 9a3dec4aa0..d4b92e82cb 100644 --- a/Discord/cogs/meta.py +++ b/Discord/cogs/meta.py @@ -32,7 +32,7 @@ def __init__(self, bot): utilities.create_file("stats", content = {"uptime" : 0, "restarts" : 0, "cogs_reloaded" : 0, "commands_executed" : 0, "commands_usage": {}, "reaction_responses": 0}) self.command_not_found = "No command called `{}` found" - @commands.group(aliases = ["commands"], hidden = True, pass_context = True, invoke_without_command = True) + @commands.group(aliases = ["commands"], hidden = True, invoke_without_command = True) @checks.dm_or_has_capability("embed_links") async def help(self, ctx, *commands : str): ''' @@ -41,8 +41,8 @@ async def help(self, ctx, *commands : str): ''' if len(commands) == 0: embed = discord.Embed(title = "Categories", color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.description = " ".join("__{}__".format(category) for category in sorted(self.bot.cogs, key = str.lower)) embed.add_field(name = "For more info:", value = "`{0}{1} [category]`\n`{0}{1} [command]`\n`{0}{1} [command] [subcommand]`".format(ctx.prefix, ctx.invoked_with)) embed.add_field(name = "Also see:", value = "`{0}about`\n`{0}{1} other`".format(ctx.prefix, ctx.invoked_with)) # stats? @@ -66,56 +66,56 @@ def repl(obj): close_matches = difflib.get_close_matches(name, self.bot.commands.keys(), n = 1) if close_matches: output += "\nDid you mean `{}`?".format(close_matches[0]) - await self.bot.embed_reply(output) + await ctx.embed_reply(output) return embeds = self.bot.formatter.format_help_for(ctx, command) else: name = _mention_pattern.sub(repl, commands[0]) command = self.bot.commands.get(name) if command is None: - await self.bot.embed_reply(self.command_not_found.format(name)) + await ctx.embed_reply(self.command_not_found.format(name)) return for key in commands[1:]: try: key = _mention_pattern.sub(repl, key) command = command.commands.get(key) if command is None: - await self.bot.embed_reply(self.command_not_found.format(key)) + await ctx.embed_reply(self.command_not_found.format(key)) return except AttributeError: - await self.bot.embed_reply("`{}` command has no subcommands".format(command.name)) + await ctx.embed_reply("`{}` command has no subcommands".format(command.name)) return embeds = self.bot.formatter.format_help_for(ctx, command) if len(embeds) > 1: - destination = ctx.message.author - if not ctx.message.channel.is_private: - await self.bot.embed_reply("Check your DMs") + destination = ctx.author + if not isinstance(ctx.channel, discord.DMChannel): + await ctx.embed_reply("Check your DMs") else: - destination = ctx.message.channel + destination = ctx.channel for embed in embeds: - if destination == ctx.message.channel: - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + if destination == ctx.channel: + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) await self.bot.send_message(destination, embed = embed) - @help.command(name = "all", pass_context = True) + @help.command(name = "all") async def help_all(self, ctx): '''All commands''' embeds = self.bot.formatter.format_help_for(ctx, self.bot) for embed in embeds: await self.bot.whisper(embed = embed) - if not ctx.message.channel.is_private: - await self.bot.embed_reply("Check your DMs") + if not isinstance(ctx.channel, discord.DMChannel): + await ctx.embed_reply("Check your DMs") - @help.command(name = "other", pass_context = True) + @help.command(name = "other") async def help_other(self, ctx): '''Additional commands and information''' # TODO: Update # TODO: Add last updated date? embed = discord.Embed(title = "Commands not in {}help".format(ctx.prefix), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.description = "See `{}help` for the main commands".format(ctx.prefix) embed.add_field(name = "Conversion Commands", value = "see `{}conversions`".format(ctx.prefix), inline = False) embed.add_field(name = "In Progress", value = "gofish redditsearch roleposition rolepositions taboo userlimit webmtogif whatis", inline = False) @@ -124,7 +124,7 @@ async def help_other(self, ctx): embed.add_field(name = "No Prefix", value = "@Harmonbot :8ball: (exactly: f|F) (anywhere in message: getprefix)", inline = False) await self.bot.say(embed = embed) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def allcommands(self, ctx): '''All the commands''' @@ -139,7 +139,7 @@ async def allcommands(self, ctx): @commands.command() @checks.is_owner() - async def benchmark(self): + async def benchmark(self, ctx): '''Benchmark''' process = psutil.Process() memory = process.memory_info().rss / 2 ** 20 @@ -153,60 +153,60 @@ async def benchmark(self): embed.set_field_at(1, name = "CPU", value = "{}%".format(cpu)) await self.bot.edit_message(message, embed = embed) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def disable(self, ctx, command : str): '''Disable a command''' self.bot.commands[command].enabled = False - await self.bot.embed_reply("`{}{}` has been disabled".format(ctx.prefix, command)) + await ctx.embed_reply("`{}{}` has been disabled".format(ctx.prefix, command)) await self.bot.delete_message(ctx.message) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def enable(self, ctx, command : str): '''Enable a command''' self.bot.commands[command].enabled = True - await self.bot.embed_reply("`{}{}` has been enabled".format(ctx.prefix, command)) + await ctx.embed_reply("`{}{}` has been enabled".format(ctx.prefix, command)) await self.bot.delete_message(ctx.message) - @commands.command(pass_context = True) + @commands.command() async def points(self, ctx): '''WIP''' - with open("data/user_data/{}/stats.json".format(ctx.message.author.id), "r") as stats_file: + with open("data/user_data/{}/stats.json".format(ctx.author.id), "r") as stats_file: stats = json.load(stats_file) - await self.bot.embed_reply("You have {} points".format(stats["points"])) + await ctx.embed_reply("You have {} points".format(stats["points"])) - @commands.command(aliases = ["server_setting"], pass_context = True) + @commands.command(aliases = ["server_setting"]) @checks.is_server_owner() async def server_settings(self, ctx, setting : str, on_off : bool): '''WIP''' - with open("data/server_data/{}/settings.json".format(ctx.message.server.id), 'r') as settings_file: + with open("data/server_data/{}/settings.json".format(ctx.guild.id), 'r') as settings_file: data = json.load(settings_file) if setting in data: data[setting] = on_off else: - await self.bot.embed_reply("Setting not found") + await ctx.embed_reply("Setting not found") return - with open("data/server_data/{}/settings.json".format(ctx.message.server.id), 'w') as settings_file: + with open("data/server_data/{}/settings.json".format(ctx.guild.id), 'w') as settings_file: json.dump(data, settings_file, indent = 4) - await self.bot.embed_reply("{} set to {}".format(setting, on_off)) + await ctx.embed_reply("{} set to {}".format(setting, on_off)) @commands.command() @checks.is_owner() - async def servers(self): + async def servers(self, ctx): '''Every server I'm in''' - for server in self.bot.servers: + for guild in self.bot.guilds: embed = discord.Embed(color = clients.bot_color) - embed.description = "```Name: " + server.name + "\n" - embed.description += "ID: " + server.id + "\n" - embed.description += "Owner: {0} ({0.id})".format(server.owner) + "\n" - embed.description += "Server Region: {}".format(server.region) + "\n" - embed.description += "Members: {}".format(server.member_count) + "\n" - embed.description += "Created at: {}".format(server.created_at) + "\n```" - embed.set_thumbnail(url = server.icon_url) - await self.bot.whisper(embed = embed) - - @commands.command(aliases = ["setprefixes"], pass_context = True) + embed.description = "```Name: " + guild.name + "\n" + embed.description += "ID: " + guild.id + "\n" + embed.description += "Owner: {0} ({0.id})".format(guild.owner) + "\n" + embed.description += "Server Region: {}".format(guild.region) + "\n" + embed.description += "Members: {}".format(guild.member_count) + "\n" + embed.description += "Created at: {}".format(guild.created_at) + "\n```" + embed.set_thumbnail(url = guild.icon_url) + await ctx.whisper(embed = embed) + + @commands.command(aliases = ["setprefixes"]) @checks.is_permitted() async def setprefix(self, ctx, *prefixes : str): ''' @@ -219,31 +219,32 @@ async def setprefix(self, ctx, *prefixes : str): prefixes = ['!'] with open("data/prefixes.json", "r") as prefixes_file: all_prefixes = json.load(prefixes_file) - if ctx.message.channel.is_private: - all_prefixes[ctx.message.channel.id] = prefixes + if isinstance(ctx.channel, discord.DMChannel): + all_prefixes[ctx.channel.id] = prefixes else: - all_prefixes[ctx.message.server.id] = prefixes + all_prefixes[ctx.guild.id] = prefixes with open("data/prefixes.json", "w") as prefixes_file: json.dump(all_prefixes, prefixes_file, indent = 4) - await self.bot.embed_reply("Prefix(es) set: {}".format(' '.join(['`"{}"`'.format(prefix) for prefix in prefixes]))) + await ctx.embed_reply("Prefix(es) set: {}".format(' '.join(['`"{}"`'.format(prefix) for prefix in prefixes]))) - @commands.command(pass_context = True, hidden = True) + @commands.command(hidden = True) @checks.not_forbidden() async def type(self, ctx): '''Sends typing status''' - await self.bot.send_typing(ctx.message.channel) + # TODO: Add seconds option + await ctx.trigger_typing() # Public Info - @commands.command(aliases = ["info"], pass_context = True) + @commands.command(aliases = ["info"]) async def about(self, ctx): '''About me''' from clients import application_info changes = os.popen(r'git show -s HEAD~3..HEAD --format="[`%h`](https://github.com/Harmon758/Harmonbot/commit/%H) %s (%cr)"').read().strip() embed = discord.Embed(title = "About Me", color = clients.bot_color) embed.description = "[Changelog (Harmonbot Server)]({})\n[Invite Link]({})".format(clients.changelog, discord.utils.oauth_url(application_info.id)) - # avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - # embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + # avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + # embed.set_author(name = ctx.author.display_name, icon_url = avatar) avatar = self.bot.user.avatar_url or self.bot.user.default_avatar_url # embed.set_thumbnail(url = avatar) embed.set_author(name = "Harmonbot (Discord ID: {})".format(self.bot.user.id), icon_url = avatar) @@ -258,23 +259,23 @@ async def about(self, ctx): await self.bot.say("Changelog (Harmonbot Server): {}".format(clients.changelog)) @commands.command() - async def changelog(self): + async def changelog(self, ctx): '''Link to changelog''' await self.bot.reply(clients.changelog) - @commands.command(pass_context = True) + @commands.command() async def conversions(self, ctx): '''All conversion commands''' - await self.bot.embed_reply("**Temperature Unit Conversions**: {0}[c, f, k, r, de]__to__[c, f, k, r, de, n, re, ro]\n" + await ctx.embed_reply("**Temperature Unit Conversions**: {0}[c, f, k, r, de]__to__[c, f, k, r, de, n, re, ro]\n" "**Weight Unit Conversions**: {0}__to__\nunits: [amu, me, bagc, bagpc, barge, kt, ct, clove, crith, da, drt, drav, ev, gamma, gr, gv, longcwt, cwt, shcwt, kg, kip, mark, mite, mitem, ozt, ozav, oz, dwt, pwt, point, lb, lbav, lbm, lbt, quarterimp, quarterinf, quarterlinf, q, sap, sheet, slug, st, atl, ats, longtn, ton, shtn, t, wey, g]".format(ctx.prefix), title = "Conversion Commands") @commands.command(aliases = ["oauth"]) - async def invite(self): + async def invite(self, ctx): '''Link to invite me to a server''' from clients import application_info - await self.bot.embed_reply(discord.utils.oauth_url(application_info.id)) + await ctx.embed_reply(discord.utils.oauth_url(application_info.id)) - @commands.command(pass_context = True) + @commands.command() async def stats(self, ctx): '''Bot stats''' from clients import session_commands_executed, session_commands_usage @@ -284,7 +285,7 @@ async def stats(self, ctx): now = datetime.datetime.utcnow() uptime = now - clients.online_time uptime = utilities.duration_to_letter_format(utilities.secs_to_duration(int(uptime.total_seconds()))) - total_members = sum(len(s.members) for s in self.bot.servers) + total_members = sum(len(g.members) for g in self.bot.guilds) total_members_online = sum(1 for m in self.bot.get_all_members() if m.status != discord.Status.offline) unique_members = set(self.bot.get_all_members()) unique_members_online = sum(1 for m in unique_members if m.status != discord.Status.offline) @@ -298,8 +299,8 @@ async def stats(self, ctx): playing_in_voice_count = sum(player.current is not None and player.current["stream"].is_playing() for player in self.bot.cogs["Audio"].players.values()) embed = discord.Embed(description = "__**Stats**__ :bar_chart:", color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) # url? + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) # url? embed.add_field(name = "Uptime", value = uptime) embed.add_field(name = "Total Recorded Uptime", value = total_uptime) ## since 2016-04-17, fixed 2016-05-10 embed.add_field(name = "Recorded Restarts", value = "{:,}".format(stats["restarts"])) ## since 2016-04-17, fixed 2016-05-10 @@ -309,7 +310,7 @@ async def stats(self, ctx): # since 2016-06-10 (cog commands) embed.add_field(name = "Cogs Reloaded", value = "{:,}".format(stats["cogs_reloaded"])) ## since 2016-06-10 - implemented cog reloading # TODO: cogs reloaded this session - embed.add_field(name = "Servers", value = len(self.bot.servers)) + embed.add_field(name = "Servers", value = len(self.bot.guilds)) embed.add_field(name = "Channels", value = "{} text\n{} voice (playing in {}/{})".format(text_count, voice_count, playing_in_voice_count, in_voice_count)) embed.add_field(name = "Members", value = "{:,} total\n({:,} online)\n{:,} unique\n({:,} online)".format(total_members, total_members_online, len(unique_members), unique_members_online)) @@ -322,56 +323,56 @@ async def stats(self, ctx): await self.bot.send_message(ctx.message.channel, embed = embed) @commands.command() - async def uptime(self): + async def uptime(self, ctx): '''Bot uptime''' now = datetime.datetime.utcnow() uptime = now - clients.online_time - await self.bot.embed_reply(utilities.secs_to_letter_format(uptime.total_seconds())) + await ctx.embed_reply(utilities.secs_to_letter_format(uptime.total_seconds())) @commands.command() - async def version(self): + async def version(self, ctx): '''Bot version''' - await self.bot.embed_reply("I am Harmonbot `v{}`".format(clients.version)) + await ctx.embed_reply("I am Harmonbot `v{}`".format(clients.version)) # Update Bot Stuff - @commands.command(aliases = ["change_nickname"], pass_context = True) + @commands.command(aliases = ["change_nickname"]) @checks.is_owner() async def changenickname(self, ctx, *, nickname : str): '''Update my nickname''' - await self.bot.change_nickname(ctx.message.server.me, nickname) + await self.bot.change_nickname(ctx.me, nickname) @commands.command(aliases = ["setavatar", "update_avatar", "set_avatar"]) @checks.is_owner() - async def updateavatar(self, filename : str): + async def updateavatar(self, ctx, filename : str): '''Update my avatar''' if not os.path.isfile("data/avatars/{}".format(filename)): - await self.bot.embed_reply(":no_entry: Avatar not found") + await ctx.embed_reply(":no_entry: Avatar not found") return with open("data/avatars/{}".format(filename), "rb") as avatar_file: await self.bot.edit_profile(avatar = avatar_file.read()) - await self.bot.embed_reply("Updated avatar") + await ctx.embed_reply("Updated avatar") @commands.command(aliases = ["random_game"], hidden = True) @checks.not_forbidden() - async def randomgame(self): + async def randomgame(self, ctx): '''Update to a random playing/game status message''' await clients.random_game_status() - # await self.bot.embed_reply("I changed to a random game status") + # await ctx.embed_reply("I changed to a random game status") - @commands.command(aliases = ["updateplaying", "updategame", "changeplaying", "changegame", "setplaying", "set_game", "update_playing", "update_game", "change_playing", "change_game", "set_playing"], pass_context = True) + @commands.command(aliases = ["updateplaying", "updategame", "changeplaying", "changegame", "setplaying", "set_game", "update_playing", "update_game", "change_playing", "change_game", "set_playing"]) @checks.is_owner() async def setgame(self, ctx, *, name : str): '''Set my playing/game status message''' - updated_game = ctx.message.server.me.game + updated_game = ctx.me.game if not updated_game: updated_game = discord.Game(name = name) else: updated_game.name = name await self.bot.change_status(game = updated_game) - await self.bot.embed_reply("Game updated") + await ctx.embed_reply("Game updated") - @commands.command(aliases = ["set_streaming"], pass_context = True) + @commands.command(aliases = ["set_streaming"]) @checks.is_owner() async def setstreaming(self, ctx, option : str, *url : str): '''Set my streaming status''' @@ -380,67 +381,67 @@ async def setstreaming(self, ctx, option : str, *url : str): await clients.set_streaming_status() return else: - updated_game = ctx.message.server.me.game + updated_game = ctx.me.game if not updated_game: updated_game = discord.Game(url = url[0], type = 1) else: updated_game.url = url[0] updated_game.type = 1 else: - updated_game = ctx.message.server.me.game + updated_game = ctx.me.game updated_game.type = 0 await self.bot.change_status(game = updated_game) - @commands.command(aliases = ["clearplaying", "clear_game", "clear_playing"], pass_context = True) + @commands.command(aliases = ["clearplaying", "clear_game", "clear_playing"]) @checks.is_owner() async def cleargame(self, ctx): '''Clear my playing/game status message''' - updated_game = ctx.message.server.me.game + updated_game = ctx.me.game if updated_game and updated_game.name: updated_game.name = None await self.bot.change_status(game = updated_game) - await self.bot.embed_reply("Game status cleared") + await ctx.embed_reply("Game status cleared") else: - await self.bot.embed_reply(":no_entry: There is no game status to clear") + await ctx.embed_reply(":no_entry: There is no game status to clear") - @commands.command(aliases = ["clear_streaming"], pass_context = True) + @commands.command(aliases = ["clear_streaming"]) @checks.is_owner() async def clearstreaming(self, ctx, *option : str): '''Clear my streaming status''' - updated_game = ctx.message.server.me.game + updated_game = ctx.me.game if updated_game and (updated_game.url or updated_game.type): updated_game.url = None if option and option[0] == "url": await self.bot.change_status(game = updated_game) - await self.bot.embed_reply("Streaming url cleared") + await ctx.embed_reply("Streaming url cleared") return updated_game.type = 0 await self.bot.change_status(game = updated_game) - await self.bot.embed_reply("Streaming status and url cleared") + await ctx.embed_reply("Streaming status and url cleared") else: - await self.bot.embed_reply(":no_entry: There is no streaming status or url to clear") + await ctx.embed_reply(":no_entry: There is no streaming status or url to clear") @commands.command(hidden = True) @checks.is_owner() - async def update_discord_bots_stats(self): + async def update_discord_bots_stats(self, ctx): '''Update stats on https://bots.discord.pw''' response = await clients._update_discord_bots_stats() await self.bot.reply(response) # Restart/Shutdown - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def restart(self, ctx): '''Restart me''' await self.bot.embed_say(":ok_hand::skin-tone-2: Restarting...") print("Shutting down Discord Harmonbot...") - await clients.restart_tasks(ctx.message.channel.id) + await clients.restart_tasks(ctx.channel.id) await self.bot.logout() @commands.command(aliases = ["crash", "panic"]) @checks.is_owner() - async def shutdown(self): + async def shutdown(self, ctx): '''Shut me down''' await self.bot.embed_say(":scream: Shutting down.") print("Forcing Shutdown...") @@ -452,23 +453,23 @@ async def shutdown(self): @commands.command(hidden = True) @checks.not_forbidden() - async def test(self): + async def test(self, ctx): '''Basic test command''' await self.bot.say("Hello, World!") @commands.group(aliases = ["code_block"], invoke_without_command = True) @checks.not_forbidden() - async def codeblock(self, *, input : str): + async def codeblock(self, ctx, *, input : str): '''Wrap your message in a code block''' - await self.bot.embed_reply(clients.code_block.format(input)) + await ctx.embed_reply(clients.code_block.format(input)) @codeblock.command(name = "python", aliases = ["py"]) @checks.not_forbidden() - async def codeblock_python(self, *, input : str): + async def codeblock_python(self, ctx, *, input : str): '''Wrap your message in a Python code block''' - await self.bot.embed_reply(clients.py_code_block.format(input)) + await ctx.embed_reply(clients.py_code_block.format(input)) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def do(self, ctx, times : int, *, command): '''Repeats a command a specified number of times''' @@ -479,17 +480,17 @@ async def do(self, ctx, times : int, *, command): @commands.group(aliases = ["say"], invoke_without_command = True) @checks.is_owner() - async def echo(self, *, message): + async def echo(self, ctx, *, message): '''Echoes the message''' await self.bot.say(message) @echo.command(name = "embed") @checks.is_owner() - async def echo_embed(self, *, message): + async def echo_embed(self, ctx, *, message): '''Echoes the message in an embed''' await self.bot.embed_say(message) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def eval(self, ctx, *, code : str): code = code.strip('`') @@ -501,7 +502,7 @@ async def eval(self, ctx, *, code : str): except Exception as e: await self.bot.reply(clients.py_code_block.format("{}: {}".format(type(e).__name__, e))) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def exec(self, ctx, *, code : str): code = code.strip('`') @@ -510,36 +511,36 @@ async def exec(self, ctx, *, code : str): except Exception as e: await self.bot.reply(clients.py_code_block.format("{}: {}".format(type(e).__name__, e))) return - await self.bot.embed_reply("Successfully executed") + await ctx.embed_reply("Successfully executed") @commands.command(aliases = ["deletetest"]) @checks.is_owner() - async def delete_test(self): + async def delete_test(self, ctx): '''Sends 100 messages''' for i in range(1, 101): await self.bot.say(str(i)) - @commands.command(aliases = ["logsfromtest"], pass_context = True) + @commands.command(aliases = ["globalratelimittest"]) @checks.is_owner() - async def logs_from_test(self, ctx): - '''Used to test global rate limits''' + async def global_ratelimit_test(self, ctx): + '''Used to test global ratelimits''' for i in range(1, 101): async for message in self.bot.logs_from(ctx.message.channel): pass - print("logs_from_test {}".format(i)) + print("global ratelimit test {}".format(i)) @commands.command(aliases = ["repeattext"]) @checks.is_owner() - async def repeat_text(self, number : int, *, text): + async def repeat_text(self, ctx, number : int, *, text): '''Repeat text''' for _ in range(number): await self.bot.say(text) - @commands.command(pass_context = True) + @commands.command() @checks.is_owner() async def repl(self, ctx): variables = {"self" : self, "ctx" : ctx, "last" : None} - await self.bot.embed_reply("Enter code to execute or evaluate\n`exit` or `quit` to exit") + await ctx.embed_reply("Enter code to execute or evaluate\n`exit` or `quit` to exit") while True: message = await self.bot.wait_for_message(author = ctx.message.author, channel = ctx.message.channel, check = lambda m: m.content.startswith('`')) if message.content.startswith("```py") and message.content.endswith("```"): @@ -547,7 +548,7 @@ async def repl(self, ctx): else: code = message.content.strip("` \n") if code in ("quit", "exit", "quit()", "exit()"): - await self.bot.embed_reply('Exiting repl') + await ctx.embed_reply('Exiting repl') return function = exec if '\n' not in code: @@ -579,7 +580,7 @@ async def repl(self, ctx): @commands.command(aliases = ["github"]) @checks.not_forbidden() - async def source(self, command : str = None): + async def source(self, ctx, command : str = None): ''' Displays my full source code or for a specific command To display the source code of a subcommand you have to separate it by @@ -588,7 +589,7 @@ async def source(self, command : str = None): ''' source_url = "https://github.com/Harmon758/Harmonbot" if command is None: - await self.bot.embed_reply(source_url) + await ctx.embed_reply(source_url) return code_path = command.split('.') obj = self.bot @@ -596,10 +597,10 @@ async def source(self, command : str = None): try: obj = obj.get_command(cmd) if obj is None: - await self.bot.embed_reply("Could not find the command " + cmd) + await ctx.embed_reply("Could not find the command " + cmd) return except AttributeError: - await self.bot.embed_reply("{0.name} command has no subcommands".format(obj)) + await ctx.embed_reply("{0.name} command has no subcommands".format(obj)) return # since we found the command we're looking for, presumably anyway, let's # try to access the code itself @@ -612,5 +613,5 @@ async def source(self, command : str = None): ## location = obj.callback.__module__.replace('.', '/') + ".py" ## source_url = "https://github.com/Rapptz/discord.py" final_url = '<{}/blob/master/Discord/{}#L{}-L{}>'.format(source_url, location, firstlineno, firstlineno + len(lines) - 1) - await self.bot.embed_reply(final_url) + await ctx.embed_reply(final_url) diff --git a/Discord/cogs/misc.py b/Discord/cogs/misc.py index 45887fe4e9..62c5ccf45b 100644 --- a/Discord/cogs/misc.py +++ b/Discord/cogs/misc.py @@ -19,7 +19,7 @@ def __init__(self, bot): @commands.command(aliases = ["emotify"]) @checks.not_forbidden() - async def emojify(self, *, text : str): + async def emojify(self, ctx, *, text : str): '''Emojify text''' output = "" for character in text: @@ -30,13 +30,13 @@ async def emojify(self, *, text : str): else: output += character try: - await self.bot.embed_reply(output) + await ctx.embed_reply(output) except discord.errors.HTTPException: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") @commands.command() @checks.not_forbidden() - async def fancify(self, *, text : str): + async def fancify(self, ctx, *, text : str): '''Fancify text''' output = "" for character in text: @@ -48,11 +48,11 @@ async def fancify(self, *, text : str): output += chr(ord(character) + 120744) else: output += character - await self.bot.embed_reply(output) + await ctx.embed_reply(output) @commands.command(aliases = ["full-width", "full_width"]) @checks.not_forbidden() - async def fullwidth(self, *, text : str): + async def fullwidth(self, ctx, *, text : str): '''Make text fullwidth''' output = "" for character in text: @@ -60,24 +60,25 @@ async def fullwidth(self, *, text : str): output += chr(ord(character) + 65248) else: output += character - await self.bot.embed_reply(output) + await ctx.embed_reply(output) @commands.command() @checks.not_forbidden() - async def fingers(self, *, text : str): + async def fingers(self, ctx, *, text : str): '''Add fingers''' - await self.bot.embed_reply(":point_right::skin-tone-2: {} :point_left::skin-tone-2:".format(text)) + await ctx.embed_reply(":point_right::skin-tone-2: {} :point_left::skin-tone-2:".format(text)) @commands.command() @checks.not_forbidden() - async def loading_bar(self): + async def loading_bar(self, ctx): ''' A loading bar Currently does nothing.. or does it? ''' counter = 0 bar = chr(9633) * 10 - loading_message, embed = await self.bot.embed_reply("Loading: [" + bar + "]") + loading_message = await ctx.embed_reply("Loading: [" + bar + "]") + embed = loading_message.embeds[0] while counter <= 10: counter += 1 bar = chr(9632) + bar[:-1] #9608 @@ -86,40 +87,40 @@ async def loading_bar(self): await self.bot.edit_message(loading_message, embed = embed) @commands.command() - async def ping(self): + async def ping(self, ctx): '''Basic ping - pong command''' - await self.bot.embed_reply("pong") + await ctx.embed_reply("pong") - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def poke(self, ctx, *, user : str): '''Poke someone''' to_poke = await utilities.get_user(ctx, user) if not to_poke: - await self.bot.embed_reply(":no_entry: User not found") + await ctx.embed_reply(":no_entry: User not found") elif to_poke == self.bot.user: - await self.bot.embed_reply("!poke {}".format(ctx.message.author.mention)) + await ctx.embed_reply("!poke {}".format(ctx.author.mention)) else: - utilities.create_folder("data/user_data/{}".format(ctx.message.author.id)) - utilities.create_file("user_data/{}/pokes".format(ctx.message.author.id)) - with open("data/user_data/{}/pokes.json".format(ctx.message.author.id), 'r') as pokes_file: + utilities.create_folder("data/user_data/{}".format(ctx.author.id)) + utilities.create_file("user_data/{}/pokes".format(ctx.author.id)) + with open("data/user_data/{}/pokes.json".format(ctx.author.id), 'r') as pokes_file: pokes_data = json.load(pokes_file) pokes_data[to_poke.id] = pokes_data.get(to_poke.id, 0) + 1 - with open("data/user_data/{}/pokes.json".format(ctx.message.author.id), 'w') as pokes_file: + with open("data/user_data/{}/pokes.json".format(ctx.author.id), 'w') as pokes_file: json.dump(pokes_data, pokes_file, indent = 4) embed = discord.Embed(color = clients.bot_color) - embed.set_author(name = ctx.message.author, icon_url = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url) + embed.set_author(name = ctx.author, icon_url = ctx.author.avatar_url or ctx.author.default_avatar_url) embed.description = "Poked you for the {} time!".format(clients.inflect_engine.ordinal(pokes_data[to_poke.id])) await self.bot.send_message(to_poke, embed = embed) - await self.bot.embed_reply("You have poked {} for the {} time!".format(to_poke.mention, clients.inflect_engine.ordinal(pokes_data[to_poke.id])), footer_text = "In response to: {}".format(ctx.message.clean_content)) + await ctx.embed_reply("You have poked {} for the {} time!".format(to_poke.mention, clients.inflect_engine.ordinal(pokes_data[to_poke.id])), footer_text = "In response to: {}".format(ctx.message.clean_content)) await self.bot.attempt_delete_message(ctx.message) def emote_wrapper(name, emote = None): if emote is None: emote = name @commands.command(name = name, help = name.capitalize() + " emote") @checks.not_forbidden() - async def emote_command(self): - await self.bot.embed_reply(":{}:".format(emote)) + async def emote_command(self, ctx): + await ctx.embed_reply(":{}:".format(emote)) return emote_command for emote in ("fish", "frog", "turtle", "gun", "tomato", "cucumber", "eggplant", "lizard", "minidisc", "horse"): diff --git a/Discord/cogs/permissions.py b/Discord/cogs/permissions.py index 2c2f236f17..fe7b9e5b66 100644 --- a/Discord/cogs/permissions.py +++ b/Discord/cogs/permissions.py @@ -15,112 +15,112 @@ class Permissions: def __init__(self, bot): self.bot = bot - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.is_permitted() async def setpermission(self, ctx): '''Set a permission''' - await self.bot.embed_reply(":no_entry: Invalid input\nSee {}help setpermission".format(ctx.prefix)) + await ctx.embed_reply(":no_entry: Invalid input\nSee {}help setpermission".format(ctx.prefix)) - @setpermission.command(name = "everyone", pass_context = True) + @setpermission.command(name = "everyone") @checks.is_permitted() async def setpermission_everyone(self, ctx, permission : str, setting : bool = None): - if permission not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(permission))) + if permission not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(permission))) command = self.bot.commands[permission].name - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) permissions_data.setdefault("everyone", {}) permissions_data["everyone"][command] = setting - with open("data/permissions/{}.json".format(ctx.message.server.id), "w") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "w") as permissions_file: json.dump(permissions_data, permissions_file, indent = 4) - await self.bot.embed_reply("Permission updated\n{} set to {} for everyone".format(permission, setting)) + await ctx.embed_reply("Permission updated\n{} set to {} for everyone".format(permission, setting)) - @setpermission.command(name = "role", pass_context = True) + @setpermission.command(name = "role") @checks.is_permitted() async def setpermission_role(self, ctx, role : str, permission : str, setting : bool = None): - if permission not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(permission))) + if permission not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(permission))) command = self.bot.commands[permission].name - matches = [_role for _role in ctx.message.server.roles if _role.name == role] - if len(matches) > 1: return (await self.bot.embed_reply("Error: multiple roles with the name, {}".format(role))) - elif len(matches) == 0: return (await self.bot.embed_reply('Error: role with name, "{}", not found'.format(role))) + matches = [_role for _role in ctx.guild.roles if _role.name == role] + if len(matches) > 1: return (await ctx.embed_reply("Error: multiple roles with the name, {}".format(role))) + elif len(matches) == 0: return (await ctx.embed_reply('Error: role with name, "{}", not found'.format(role))) else: _role = matches[0] - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) permissions_data.setdefault("roles", {}) permissions_data["roles"].setdefault(_role.id, {"name" : _role.name}) permissions_data["roles"][_role.id][command] = setting - with open("data/permissions/{}.json".format(ctx.message.server.id), "w") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "w") as permissions_file: json.dump(permissions_data, permissions_file, indent = 4) - await self.bot.embed_reply("Permission updated\n{} set to {} for the {} role".format(permission, setting, _role.name)) + await ctx.embed_reply("Permission updated\n{} set to {} for the {} role".format(permission, setting, _role.name)) - @setpermission.command(name = "user", pass_context = True) + @setpermission.command(name = "user") @checks.is_permitted() async def setpermission_user(self, ctx, user : str, permission : str, setting : bool = None): - if permission not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(permission))) + if permission not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(permission))) command = self.bot.commands[permission].name _user = await utilities.get_user(ctx, user) - if not _user: return (await self.bot.embed_reply("Error: user not found")) - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + if not _user: return (await ctx.embed_reply("Error: user not found")) + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) permissions_data.setdefault("users", {}) permissions_data["users"].setdefault(_user.id, {"name" : _user.name}) permissions_data["users"][_user.id][command] = setting - with open("data/permissions/{}.json".format(ctx.message.server.id), "w") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "w") as permissions_file: json.dump(permissions_data, permissions_file, indent = 4) - await self.bot.embed_reply("Permission updated\n{} set to {} for {}".format(permission, setting, _user)) + await ctx.embed_reply("Permission updated\n{} set to {} for {}".format(permission, setting, _user)) - @commands.group(invoke_without_command = True, pass_context = True) + @commands.group(invoke_without_command = True) @checks.is_permitted() async def getpermission(self, ctx, *options : str): '''Get a permission''' if len(options) == 2: - if options[1] not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(options[1]))) + if options[1] not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(options[1]))) command = self.bot.commands[options[1]].name user = await utilities.get_user(ctx, options[0]) - if not user: return (await self.bot.embed_reply("Error: user not found")) + if not user: return (await ctx.embed_reply("Error: user not found")) setting = utilities.get_permission(ctx, command, id = user.id) - await self.bot.embed_reply("{} is set to {} for {}".format(options[1], setting, user)) + await ctx.embed_reply("{} is set to {} for {}".format(options[1], setting, user)) else: - await self.bot.embed_reply(":no_entry: Invalid input\ngetpermission everyone|role|user or ") #options + await ctx.embed_reply(":no_entry: Invalid input\ngetpermission everyone|role|user or ") #options - @getpermission.command(name = "everyone", pass_context = True) + @getpermission.command(name = "everyone") @checks.is_permitted() async def getpermission_everyone(self, ctx, permission : str): - if permission not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(permission))) + if permission not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(permission))) command = self.bot.commands[permission].name setting = utilities.get_permission(ctx, command, type = "everyone") - await self.bot.embed_reply("{} is set to {} for everyone".format(permission, setting)) + await ctx.embed_reply("{} is set to {} for everyone".format(permission, setting)) - @getpermission.command(name = "role", pass_context = True) + @getpermission.command(name = "role") @checks.is_permitted() async def getpermission_role(self, ctx, role : str, permission : str): - if permission not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(permission))) + if permission not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(permission))) command = self.bot.commands[permission].name - matches = [_role for _role in ctx.message.server.roles if _role.name == role] - if len(matches) > 1: return (await self.bot.embed_reply("Error: multiple roles with the name, {}".format(role))) - elif len(matches) == 0: return (await self.bot.embed_reply('Error: role with name, "{}", not found'.format(role))) + matches = [_role for _role in ctx.guild.roles if _role.name == role] + if len(matches) > 1: return (await ctx.embed_reply("Error: multiple roles with the name, {}".format(role))) + elif len(matches) == 0: return (await ctx.embed_reply('Error: role with name, "{}", not found'.format(role))) else: _role = matches[0] setting = utilities.get_permission(ctx, command, type = "role", id = _role.id) - await self.bot.embed_reply("{} is set to {} for the {} role".format(permission, setting, _role.name)) + await ctx.embed_reply("{} is set to {} for the {} role".format(permission, setting, _role.name)) - @getpermission.command(name = "user", pass_context = True) + @getpermission.command(name = "user") @checks.is_permitted() async def getpermission_user(self, ctx, user : str, permission : str): - if permission not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(permission))) + if permission not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(permission))) command = self.bot.commands[permission].name _user = await utilities.get_user(ctx, user) - if not _user: return (await self.bot.embed_reply("Error: user not found")) + if not _user: return (await ctx.embed_reply("Error: user not found")) setting = utilities.get_permission(ctx, command, id = _user.id) - await self.bot.embed_reply("{} is set to {} for {}".format(permission, setting, _user)) + await ctx.embed_reply("{} is set to {} for {}".format(permission, setting, _user)) - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.is_permitted() async def getpermissions(self, ctx): - await self.bot.embed_reply(":no_entry: Invalid input\nSee {}help getpermissions".format(ctx.prefix)) + await ctx.embed_reply(":no_entry: Invalid input\nSee {}help getpermissions".format(ctx.prefix)) - @getpermissions.command(name = "everyone", pass_context = True) + @getpermissions.command(name = "everyone") @checks.is_permitted() async def getpermissions_everyone(self, ctx): - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) everyone_settings = permissions_data.get("everyone", {}) output = "__Permissions for everyone__\n" @@ -128,14 +128,14 @@ async def getpermissions_everyone(self, ctx): output += "{}: {}\n".format(permission, str(setting)) await self.bot.say(output) - @getpermissions.command(name = "role", pass_context = True) + @getpermissions.command(name = "role") @checks.is_permitted() async def getpermissions_role(self, ctx, role : str): - matches = [_role for _role in ctx.message.server.roles if _role.name == role] - if len(matches) > 1: return (await self.bot.embed_reply("Error: multiple roles with the name, {}".format(role))) - elif len(matches) == 0: return (await self.bot.embed_reply('Error: role with name, "{}", not found'.format(role))) + matches = [_role for _role in ctx.guild.roles if _role.name == role] + if len(matches) > 1: return (await ctx.embed_reply("Error: multiple roles with the name, {}".format(role))) + elif len(matches) == 0: return (await ctx.embed_reply('Error: role with name, "{}", not found'.format(role))) else: _role = matches[0] - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) role_settings = permissions_data.get("roles", {}).get(_role.id, {}) output = "__Permissions for {}__\n".format(_role.name) @@ -144,12 +144,12 @@ async def getpermissions_role(self, ctx, role : str): output += "{}: {}\n".format(permission, str(setting)) await self.bot.say(output) - @getpermissions.command(name = "user", pass_context = True) + @getpermissions.command(name = "user") @checks.is_permitted() async def getpermissions_user(self, ctx, user : str): _user = await utilities.get_user(ctx, user) - if not _user: return (await self.bot.embed_reply("Error: user not found")) - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + if not _user: return (await ctx.embed_reply("Error: user not found")) + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) user_settings = permissions_data.get("users", {}).get(_user.id, {}) output = "__Permissions for {}__\n".format(_user.name) @@ -158,11 +158,11 @@ async def getpermissions_user(self, ctx, user : str): output += "{}: {}\n".format(permission, str(setting)) await self.bot.say(output) - @getpermissions.command(name = "command", pass_context = True) + @getpermissions.command(name = "command") @checks.is_permitted() async def getpermissions_command(self, ctx, command : str): - if command not in self.bot.commands: return (await self.bot.embed_reply("Error: {} is not a command".format(command))) - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + if command not in self.bot.commands: return (await ctx.embed_reply("Error: {} is not a command".format(command))) + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) output = "__Permissions for {}__\n".format(command) permissions_data.pop("name", None) diff --git a/Discord/cogs/random.py b/Discord/cogs/random.py index 53acc691aa..d5fd07e42c 100644 --- a/Discord/cogs/random.py +++ b/Discord/cogs/random.py @@ -58,14 +58,14 @@ def __unload(self): @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def random(self): + async def random(self, ctx): ''' Random things All random subcommands are also commands ''' - await self.bot.embed_reply(":grey_question: Random what?") + await ctx.embed_reply(":grey_question: Random what?") - @random.command(pass_context = True) + @random.command() @checks.not_forbidden() async def color(self, ctx): '''Information on a random color''' @@ -75,51 +75,51 @@ async def color(self, ctx): @random.command() @checks.not_forbidden() - async def giphy(self): + async def giphy(self, ctx): '''Random gif from giphy''' url = "http://api.giphy.com/v1/gifs/random?api_key={}".format(credentials.giphy_public_beta_api_key) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() - await self.bot.embed_reply(None, image_url = data["data"]["image_url"]) + await ctx.embed_reply(image_url = data["data"]["image_url"]) @random.command() @checks.not_forbidden() - async def map(self): + async def map(self, ctx): '''See map of random location''' latitude = random.uniform(-90, 90) longitude = random.uniform(-180, 180) map_url = "https://maps.googleapis.com/maps/api/staticmap?center={},{}&zoom=13&size=640x640".format(latitude, longitude) - await self.bot.embed_reply("[:map:]({})".format(map_url), image_url = map_url) + await ctx.embed_reply("[:map:]({})".format(map_url), image_url = map_url) @random.command() @checks.not_forbidden() - async def streetview(self): + async def streetview(self, ctx): '''Generate street view of a random location''' latitude = random.uniform(-90, 90) longitude = random.uniform(-180, 180) image_url = "https://maps.googleapis.com/maps/api/streetview?size=400x400&location={},{}".format(latitude, longitude) - await self.bot.embed_reply(None, image_url = image_url) + await ctx.embed_reply(image_url = image_url) @random.command() @checks.not_forbidden() - async def uesp(self): + async def uesp(self, ctx): ''' Random UESP page [UESP](http://uesp.net/wiki/Main_Page) ''' cog = self.bot.get_cog("Search") if cog: await cog.process_uesp(None, random = True) - else: await self.bot.embed_reply(None, title = "Random UESP page", title_url = "http://uesp.net/wiki/Special:Random") # necessary? + else: await ctx.embed_reply(title = "Random UESP page", title_url = "http://uesp.net/wiki/Special:Random") # necessary? @random.command(aliases = ["wiki"]) @checks.not_forbidden() - async def wikipedia(self): + async def wikipedia(self, ctx): '''Random Wikipedia article''' cog = self.bot.get_cog("Search") if cog: await cog.process_wikipedia(None, random = True) - else: await self.bot.embed_reply(None, title = "Random Wikipedia article", title_url = "https://wikipedia.org/wiki/Special:Random") # necessary? + else: await ctx.embed_reply(title = "Random Wikipedia article", title_url = "https://wikipedia.org/wiki/Special:Random") # necessary? - @random.command(pass_context = True) + @random.command() @checks.not_forbidden() async def xkcd(self, ctx): '''Random xkcd''' @@ -132,11 +132,11 @@ async def xkcd(self, ctx): @commands.command() @checks.not_forbidden() - async def card(self): + async def card(self, ctx): '''Random playing card''' - await self.bot.embed_reply(":{}: {}".format(random.choice(pydealer.const.SUITS).lower(), random.choice(pydealer.const.VALUES))) + await ctx.embed_reply(":{}: {}".format(random.choice(pydealer.const.SUITS).lower(), random.choice(pydealer.const.VALUES))) - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def cat(self, ctx, *, category : str = ""): ''' @@ -150,34 +150,34 @@ async def cat(self, ctx, *, category : str = ""): try: categories = xml.etree.ElementTree.fromstring(data).findall(".//name") except xml.etree.ElementTree.ParseError: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") else: - await self.bot.embed_reply('\n'.join(sorted(category.text for category in categories))) + await ctx.embed_reply('\n'.join(sorted(category.text for category in categories))) elif category: async with clients.aiohttp_session.get("http://thecatapi.com/api/images/get?format=xml&results_per_page=1&category={}".format(category)) as resp: data = await resp.text() try: url = xml.etree.ElementTree.fromstring(data).find(".//url") except xml.etree.ElementTree.ParseError: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return if url is not None: - await self.bot.embed_reply("[:cat:]({})".format(url.text), image_url = url.text) + await ctx.embed_reply("[:cat:]({})".format(url.text), image_url = url.text) else: - await self.bot.embed_reply(":no_entry: Error: Category not found") + await ctx.embed_reply(":no_entry: Error: Category not found") else: async with clients.aiohttp_session.get("http://thecatapi.com/api/images/get?format=xml&results_per_page=1") as resp: data = await resp.text() try: url = xml.etree.ElementTree.fromstring(data).find(".//url").text except xml.etree.ElementTree.ParseError: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") else: - await self.bot.embed_reply("[:cat:]({})".format(url), image_url = url) + await ctx.embed_reply("[:cat:]({})".format(url), image_url = url) @commands.command(aliases = ["die", "roll"]) @checks.not_forbidden() - async def dice(self, *, input : str = '6'): + async def dice(self, ctx, *, input : str = '6'): ''' Roll dice Inputs: Examples: @@ -197,57 +197,57 @@ async def dice(self, *, input : str = '6'): try: result = await asyncio.wait_for(future, 10.0, loop = self.bot.loop) if type(result) is int: - await self.bot.embed_reply(result) + await ctx.embed_reply(result) else: - await self.bot.embed_reply(", ".join(str(roll) for roll in result)) + await ctx.embed_reply(", ".join(str(roll) for roll in result)) except discord.errors.HTTPException: - await self.bot.embed_reply(":no_entry: Output too long") + await ctx.embed_reply(":no_entry: Output too long") except pyparsing.ParseException: - await self.bot.embed_reply(":no_entry: Invalid input") + await ctx.embed_reply(":no_entry: Invalid input") except (concurrent.futures.TimeoutError, multiprocessing.context.TimeoutError): - await self.bot.embed_reply(":no_entry: Execution exceeded time limit") + await ctx.embed_reply(":no_entry: Execution exceeded time limit") - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def command(self, ctx): '''Random command''' - await self.bot.embed_reply("{}{}".format(ctx.prefix, random.choice(tuple(set(command.name for command in self.bot.commands.values()))))) + await ctx.embed_reply("{}{}".format(ctx.prefix, random.choice(tuple(set(command.name for command in self.bot.commands.values()))))) @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def date(self): + async def date(self, ctx): '''Random date''' - await self.bot.embed_reply(datetime.date.fromordinal(random.randint(1, 365)).strftime("%B %d")) + await ctx.embed_reply(datetime.date.fromordinal(random.randint(1, 365)).strftime("%B %d")) @commands.command() @checks.not_forbidden() - async def day(self): + async def day(self, ctx): '''Random day of week''' - await self.bot.embed_reply(random.choice(calendar.day_name)) + await ctx.embed_reply(random.choice(calendar.day_name)) @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def fact(self): + async def fact(self, ctx): '''Random fact''' url = "http://mentalfloss.com/api/1.0/views/amazing_facts.json?limit=1&bypass={}".format(random.random()) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() - await self.bot.embed_reply(BeautifulSoup(data[0]["nid"]).text) + await ctx.embed_reply(BeautifulSoup(data[0]["nid"]).text) - @fact.command(name = "cat", aliases = ["cats"], pass_context = True) + @fact.command(name = "cat", aliases = ["cats"]) @checks.not_forbidden() async def fact_cat(self, ctx): '''Random fact about cats''' async with clients.aiohttp_session.get("http://catfacts-api.appspot.com/api/facts") as resp: data = await resp.json() if data["success"]: - await self.bot.embed_reply(data["facts"][0]) + await ctx.embed_reply(data["facts"][0]) else: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") @fact.command(name = "date") @checks.not_forbidden() - async def fact_date(self, date : str): + async def fact_date(self, ctx, date : str): ''' Random fact about a date Format: month/date @@ -255,111 +255,111 @@ async def fact_date(self, date : str): ''' async with clients.aiohttp_session.get("http://numbersapi.com/{}/date".format(date)) as resp: if resp.status == 404: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = await resp.text() - await self.bot.embed_reply(data) + await ctx.embed_reply(data) @fact.command(name = "math") @checks.not_forbidden() - async def fact_math(self, number : int): + async def fact_math(self, ctx, number : int): '''Random math fact about a number''' async with clients.aiohttp_session.get("http://numbersapi.com/{}/math".format(number)) as resp: data = await resp.text() - await self.bot.embed_reply(data) + await ctx.embed_reply(data) @fact.command(name = "number") @checks.not_forbidden() - async def fact_number(self, number : int): + async def fact_number(self, ctx, number : int): '''Random fact about a number''' async with clients.aiohttp_session.get("http://numbersapi.com/{}".format(number)) as resp: data = await resp.text() - await self.bot.embed_reply(data) + await ctx.embed_reply(data) @fact.command(name = "year") @checks.not_forbidden() - async def fact_year(self, year : int): + async def fact_year(self, ctx, year : int): '''Random fact about a year''' async with clients.aiohttp_session.get("http://numbersapi.com/{}/year".format(year)) as resp: data = await resp.text() - await self.bot.embed_reply(data) + await ctx.embed_reply(data) @commands.command() @checks.not_forbidden() - async def idea(self): + async def idea(self, ctx): '''Random idea''' async with clients.aiohttp_session.get("http://itsthisforthat.com/api.php?json") as resp: data = await resp.json() - await self.bot.embed_reply("{0[this]} for {0[that]}".format(data)) + await ctx.embed_reply("{0[this]} for {0[that]}".format(data)) @commands.command() @checks.not_forbidden() - async def insult(self): + async def insult(self, ctx): '''Random insult''' async with clients.aiohttp_session.get("http://quandyfactory.com/insult/json") as resp: data = await resp.json() - await self.bot.embed_say(data["insult"]) + await ctx.embed_say(data["insult"]) @commands.command() @checks.not_forbidden() - async def joke(self): + async def joke(self, ctx): '''Random joke''' # Sources: # https://github.com/KiaFathi/tambalAPI # https://www.kaggle.com/abhinavmoudgil95/short-jokes (https://github.com/amoudgl/short-jokes-dataset) - await self.bot.embed_reply(random.choice(self.jokes)) + await ctx.embed_reply(random.choice(self.jokes)) @commands.command() @checks.not_forbidden() - async def letter(self): + async def letter(self, ctx): '''Random letter''' - await self.bot.embed_reply(random.choice(string.ascii_uppercase)) + await ctx.embed_reply(random.choice(string.ascii_uppercase)) @commands.command() @checks.not_forbidden() - async def location(self): + async def location(self, ctx): '''Random location''' - await self.bot.embed_reply("{}, {}".format(random.uniform(-90, 90), random.uniform(-180, 180))) + await ctx.embed_reply("{}, {}".format(random.uniform(-90, 90), random.uniform(-180, 180))) @commands.group(aliases = ["rng"], invoke_without_command = True) @checks.not_forbidden() - async def number(self, number : int = 10): + async def number(self, ctx, number : int = 10): ''' Random number Default range is 1 to 10 ''' - await self.bot.embed_reply(random.randint(1, number)) + await ctx.embed_reply(random.randint(1, number)) @commands.command(aliases = ["why"]) @checks.not_forbidden() - async def question(self): + async def question(self, ctx): '''Random question''' async with clients.aiohttp_session.get("http://xkcd.com/why.txt") as resp: data = await resp.text() questions = data.split('\n') - await self.bot.embed_reply("{}?".format(random.choice(questions).capitalize())) + await ctx.embed_reply("{}?".format(random.choice(questions).capitalize())) @commands.command() @checks.not_forbidden() - async def quote(self): + async def quote(self, ctx): '''Random quote''' async with clients.aiohttp_session.get("http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=en") as resp: try: data = await resp.json() except: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return - await self.bot.embed_reply(data["quoteText"], footer_text = data["quoteAuthor"]) # quoteLink? + await ctx.embed_reply(data["quoteText"], footer_text = data["quoteAuthor"]) # quoteLink? @commands.command() @checks.not_forbidden() - async def time(self): + async def time(self, ctx): '''Random time''' - await self.bot.embed_reply("{:02d}:{:02d}".format(random.randint(0, 23), random.randint(0, 59))) + await ctx.embed_reply("{:02d}:{:02d}".format(random.randint(0, 23), random.randint(0, 59))) @commands.command() @checks.not_forbidden() - async def word(self): + async def word(self, ctx): '''Random word''' - await self.bot.embed_reply(clients.wordnik_words_api.getRandomWord().word.capitalize()) + await ctx.embed_reply(self.bot.wordnik_words_api.getRandomWord().word.capitalize()) diff --git a/Discord/cogs/reactions.py b/Discord/cogs/reactions.py index fa7772438b..73dfa09fe3 100644 --- a/Discord/cogs/reactions.py +++ b/Discord/cogs/reactions.py @@ -37,18 +37,19 @@ def __unload(self): for command, parent_name in self.reaction_commands: utilities.remove_as_subcommand(self, parent_name, "reactions") - @commands.command(aliases = ["guessreactions", "guessreaction"], pass_context = True) + @commands.command(aliases = ["guessreactions", "guessreaction"]) @checks.not_forbidden() async def guessr(self, ctx): ''' Guessing game With reactions ''' - guess_message, embed = await self.bot.embed_reply("Guess a number between 1 to 10") + guess_message = await ctx.embed_reply("Guess a number between 1 to 10") + embed = guess_message.embeds[0] answer = random.randint(1, 10) for number_emote in sorted(self.numbers.keys()): await self.bot.add_reaction(guess_message, number_emote) - self.reaction_messages[guess_message.id] = lambda reaction, user: self.guessr_processr(ctx.message.author, answer, embed, reaction, user) + self.reaction_messages[guess_message.id] = lambda reaction, user: self.guessr_processr(ctx.author, answer, embed, reaction, user) async def guessr_processr(self, player, answer, embed, reaction, user): if user == player and reaction.emoji in self.numbers: @@ -60,7 +61,7 @@ async def guessr_processr(self, player, answer, embed, reaction, user): embed.description = "{}: Guess a number between 1 to 10. No, it's not {}".format(player.display_name, self.numbers[reaction.emoji]) await self.bot.edit_message(reaction.message, embed = embed) - @commands.command(pass_context = True, invoke_without_command = True) + @commands.command(invoke_without_command = True) @checks.not_forbidden() async def newsr(self, ctx, source : str): ''' @@ -71,7 +72,7 @@ async def newsr(self, ctx, source : str): async with clients.aiohttp_session.get("https://newsapi.org/v1/articles?source={}&apiKey={}".format(source, credentials.news_api_key)) as resp: data = await resp.json() if data["status"] != "ok": - await self.bot.embed_reply(":no_entry: Error: {}".format(data["message"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["message"])) return response, embed = await self.bot.reply("React with a number from 1 to 10 to view each news article") numbers = {'\N{KEYCAP TEN}': 10} @@ -80,7 +81,7 @@ async def newsr(self, ctx, source : str): for number_emote in sorted(numbers.keys()): await self.bot.add_reaction(response, number_emote) while True: - emoji_response = await self.bot.wait_for_reaction(user = ctx.message.author, message = response, emoji = numbers.keys()) + emoji_response = await self.bot.wait_for_reaction(user = ctx.author, message = response, emoji = numbers.keys()) reaction = emoji_response.reaction number = numbers[reaction.emoji] article = data["articles"][number - 1] @@ -92,12 +93,12 @@ async def newsr(self, ctx, source : str): # output += "\n<{}>".format(article["url"]) output += "\n{}".format(article["url"]) output += "\nSelect a different number for another article" - await self.bot.edit_message(response, "{}: {}".format(ctx.message.author.display_name, output)) + await self.bot.edit_message(response, "{}: {}".format(ctx.author.display_name, output)) # TODO: urband # TODO: rtg - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def mazer(self, ctx, width : int = 5, height : int = 5, random_start : bool = False, random_end : bool = False): ''' @@ -108,11 +109,11 @@ async def mazer(self, ctx, width : int = 5, height : int = 5, random_start : boo React with an arrow key to move ''' maze_instance = maze.Maze(width, height, random_start = random_start, random_end = random_end) - maze_message, embed = await self.bot.embed_reply(clients.code_block.format(maze_instance.print_visible()), footer_text = "Your current position: {}, {}".format(maze_instance.column + 1, maze_instance.row + 1)) + maze_message = await ctx.embed_reply(clients.code_block.format(maze_instance.print_visible()), footer_text = "Your current position: {}, {}".format(maze_instance.column + 1, maze_instance.row + 1)) self.mazes[maze_message.id] = maze_instance for emote in tuple(self.arrows.keys()) + ("\N{PRINTER}",): await self.bot.add_reaction(maze_message, emote) - self.reaction_messages[maze_message.id] = lambda reaction, user: self.mazer_processr(ctx.message.author, reaction, user) + self.reaction_messages[maze_message.id] = lambda reaction, user: self.mazer_processr(ctx.author, reaction, user) async def mazer_processr(self, player, reaction, user): if user == player and reaction.emoji in tuple(self.arrows.keys()) + ("\N{PRINTER}",): @@ -137,16 +138,16 @@ async def mazer_processr(self, player, reaction, user): embed.description = "{}\n:no_entry: You can't go that way".format(clients.code_block.format(maze_instance.print_visible())) await self.bot.edit_message(reaction.message, embed = embed) - @commands.command(aliases = ["player"], no_pm = True, pass_context = True) + @commands.command(aliases = ["player"], no_pm = True) @checks.not_forbidden() async def playingr(self, ctx): '''Audio player''' try: - embed = self.bot.cogs["Audio"].players[ctx.message.server.id].current_embed() + embed = self.bot.cogs["Audio"].players[ctx.guild.id].current_embed() except errors.AudioNotPlaying: - player_message, embed = await self.bot.embed_reply(":speaker: There is no song currently playing") + player_message = await ctx.embed_reply(":speaker: There is no song currently playing") else: - embed.set_author(name = ctx.message.author.display_name, icon_url = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url) + embed.set_author(name = ctx.author.display_name, icon_url = ctx.author.avatar_url or ctx.author.default_avatar_url) player_message, embed = await self.bot.say(embed = embed) await self.bot.attempt_delete_message(ctx.message) for control_emote in self.controls.keys(): @@ -159,31 +160,31 @@ async def playingr(self, ctx): async def playingr_processr(self, ctx, reaction, user): if reaction.emoji in self.controls: if self.controls[reaction.emoji] == "pause_resume": - if utilities.get_permission(ctx, "pause", id = user.id) or user == ctx.message.server.owner or user.id == clients.owner_id: + if utilities.get_permission(ctx, "pause", id = user.id) or user == ctx.guild.owner or user.id == clients.owner_id: embed = discord.Embed(color = clients.bot_color).set_author(name = user.display_name, icon_url = user.avatar_url or user.default_avatar_url) try: - self.bot.cogs["Audio"].players[ctx.message.server.id].pause() + self.bot.cogs["Audio"].players[ctx.guild.id].pause() except errors.AudioNotPlaying: embed.description = ":no_entry: There is no song to pause" except errors.AudioAlreadyDone: - self.bot.cogs["Audio"].players[ctx.message.server.id].resume() + self.bot.cogs["Audio"].players[ctx.guild.id].resume() embed.description = ":play_pause: Resumed song" else: embed.description = ":pause_button: Paused song" - await self.bot.send_message(ctx.message.channel, embed = embed) + await self.bot.send_message(ctx.channel, embed = embed) await self.bot.attempt_delete_message(ctx.message) elif self.controls[reaction.emoji] in ("skip", "replay", "shuffle", "radio"): - if utilities.get_permission(ctx, self.controls[reaction.emoji], id = user.id) or user.id in (ctx.message.server.owner.id, clients.owner_id): + if utilities.get_permission(ctx, self.controls[reaction.emoji], id = user.id) or user.id in (ctx.guild.owner.id, clients.owner_id): message = copy.copy(ctx.message) message.content = "{}{}".format(ctx.prefix, self.controls[reaction.emoji]) await self.bot.process_commands(message) # Timestamp for radio elif self.controls[reaction.emoji] in ("volume_down", "volume_up"): - if utilities.get_permission(ctx, "volume", id = user.id) or user.id in (ctx.message.server.owner, clients.owner_id): + if utilities.get_permission(ctx, "volume", id = user.id) or user.id in (ctx.guild.owner, clients.owner_id): try: - current_volume = self.bot.cogs["Audio"].players[ctx.message.server.id].get_volume() + current_volume = self.bot.cogs["Audio"].players[ctx.guild.id].get_volume() except errors.AudioNotPlaying: - await self.bot.embed_reply(":no_entry: Couldn't change volume\nThere's nothing playing right now") + await ctx.embed_reply(":no_entry: Couldn't change volume\nThere's nothing playing right now") if self.controls[reaction.emoji] == "volume_down": set_volume = current_volume - 10 elif self.controls[reaction.emoji] == "volume_up": set_volume = current_volume + 10 message = copy.copy(ctx.message) diff --git a/Discord/cogs/resources.py b/Discord/cogs/resources.py index 6c0660b497..f70d15ac0d 100644 --- a/Discord/cogs/resources.py +++ b/Discord/cogs/resources.py @@ -34,22 +34,22 @@ def __init__(self, bot): @commands.command(aliases = ["antonyms"]) @checks.not_forbidden() - async def antonym(self, word : str): + async def antonym(self, ctx, word : str): '''Antonyms of a word''' antonyms = clients.wordnik_word_api.getRelatedWords(word, relationshipTypes = "antonym", useCanonical = "true", limitPerRelationshipType = 100) if not antonyms: - await self.bot.embed_reply(":no_entry: Word or antonyms not found") + await ctx.embed_reply(":no_entry: Word or antonyms not found") return - await self.bot.embed_reply(', '.join(antonyms[0].words), title = "Antonyms of {}".format(word.capitalize())) + await ctx.embed_reply(', '.join(antonyms[0].words), title = "Antonyms of {}".format(word.capitalize())) @commands.group(aliases = ["blizzard"], invoke_without_command = True) @checks.not_forbidden() - async def battlenet(self): + async def battlenet(self, ctx): '''Battle.net''' ... @battlenet.command(name = "run", aliases = ["launch"]) - async def battlenet_run(self, *, game : str): + async def battlenet_run(self, ctx, *, game : str): ''' Generate a Battle.net link to launch a game You must have the Battle.net launcher open for the link to work @@ -62,11 +62,11 @@ async def battlenet_run(self, *, game : str): elif lower_game in ("heroes of the storm", "hots"): abbrev = "Hero" elif lower_game in ("overwatch"): abbrev = "Pro" else: - await self.bot.embed_reply(":no_entry: Game not found") + await ctx.embed_reply(":no_entry: Game not found") return - await self.bot.embed_reply("[Launch {}](battlenet://{})".format(game, abbrev)) + await ctx.embed_reply("[Launch {}](battlenet://{})".format(game, abbrev)) - @commands.group(aliases = ["colour"], pass_context = True, invoke_without_command = True) + @commands.group(aliases = ["colour"], invoke_without_command = True) @checks.not_forbidden() async def color(self, ctx, *, color : str): ''' @@ -84,12 +84,12 @@ async def process_color(self, ctx, url): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if not data: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = data[0] embed = discord.Embed(title = data["title"].capitalize(), description = "#{}".format(data["hex"]), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.add_field(name = "RGB", value = "{0[red]}, {0[green]}, {0[blue]}".format(data["rgb"])) embed.add_field(name = "HSV", value = "{0[hue]}°, {0[saturation]}%, {0[value]}%".format(data["hsv"])) embed.set_image(url = data["imageUrl"]) @@ -97,17 +97,17 @@ async def process_color(self, ctx, url): @commands.command() @checks.not_forbidden() - async def define(self, word : str): + async def define(self, ctx, word : str): '''Define a word''' definition = clients.wordnik_word_api.getDefinitions(word, limit = 1) # useCanonical = True ? if not definition: - await self.bot.embed_reply(":no_entry: Definition not found") + await ctx.embed_reply(":no_entry: Definition not found") return - await self.bot.embed_reply(definition[0].text, title = definition[0].word.capitalize(), footer_text = definition[0].attributionText) + await ctx.embed_reply(definition[0].text, title = definition[0].word.capitalize(), footer_text = definition[0].attributionText) @commands.command() @checks.not_forbidden() - async def dotabuff(self, account : str): + async def dotabuff(self, ctx, account : str): '''Get Dotabuff link''' try: url = "https://www.dotabuff.com/players/{}".format(int(account) - 76561197960265728) @@ -116,44 +116,44 @@ async def dotabuff(self, account : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() url = "https://www.dotabuff.com/players/{}".format(int(data["response"]["steamid"]) - 76561197960265728) - await self.bot.embed_reply(None, title = "{}'s Dotabuff profile".format(account), title_url = url) + await ctx.embed_reply(title = "{}'s Dotabuff profile".format(account), title_url = url) @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def giphy(self, *, search : str): + async def giphy(self, ctx, *, search : str): '''Find an image on giphy''' url = "http://api.giphy.com/v1/gifs/search?api_key={}&q={}&limit=1".format(credentials.giphy_public_beta_api_key, search) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() - await self.bot.embed_reply(None, image_url = data["data"][0]["images"]["original"]["url"]) + await ctx.embed_reply(image_url = data["data"][0]["images"]["original"]["url"]) @giphy.command(name = "trending") - async def giphy_trending(self): + async def giphy_trending(self, ctx): '''Trending gif''' url = "http://api.giphy.com/v1/gifs/trending?api_key={}".format(credentials.giphy_public_beta_api_key) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() - await self.bot.embed_reply(None, image_url = data["data"][0]["images"]["original"]["url"]) + await ctx.embed_reply(image_url = data["data"][0]["images"]["original"]["url"]) @commands.command(aliases = ["imagesearch", "googleimages"]) @checks.not_forbidden() - async def googleimage(self, *, search : str): + async def googleimage(self, ctx, *, search : str): '''Google image search something''' url = "https://www.googleapis.com/customsearch/v1?key={}&cx={}&searchType=image&q={}".format(credentials.google_apikey, credentials.google_cse_cx, search.replace(' ', '+')) async with clients.aiohttp_session.get(url) as resp: if resp.status == 403: - await self.bot.embed_reply(":no_entry: Daily limit exceeded") + await ctx.embed_reply(":no_entry: Daily limit exceeded") return data = await resp.json() if "items" not in data: - await self.bot.embed_reply(":no_entry: No images with that search found") + await ctx.embed_reply(":no_entry: No images with that search found") return - await self.bot.embed_reply(None, image_url = data["items"][0]["link"], title = "Image of {}".format(search), title_url = data["items"][0]["link"]) + await ctx.embed_reply(image_url = data["items"][0]["link"], title = "Image of {}".format(search), title_url = data["items"][0]["link"]) # handle 403 daily limit exceeded error @commands.command() @checks.not_forbidden() - async def haveibeenpwned(self, name : str): + async def haveibeenpwned(self, ctx, name : str): '''Check if your account has been breached''' url = "https://haveibeenpwned.com/api/v2/breachedaccount/{0}?truncateResponse=true".format(name) async with clients.aiohttp_session.get(url) as resp: @@ -177,62 +177,62 @@ async def haveibeenpwned(self, name : str): for pastedaccount in data: pastedaccounts += pastedaccount["Source"] + " (" + pastedaccount["Id"] + "), " pastedaccounts = pastedaccounts[:-2] - await self.bot.embed_reply("Breached accounts: {}\nPastes: {}".format(breachedaccounts, pastedaccounts)) + await ctx.embed_reply("Breached accounts: {}\nPastes: {}".format(breachedaccounts, pastedaccounts)) @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def horoscope(self, sign : str): + async def horoscope(self, ctx, sign : str): '''Horoscope''' - await self.process_horoscope(sign, "today") + await self.process_horoscope(ctx, sign, "today") @horoscope.command(name = "signs", aliases = ["sun_signs", "sunsigns"]) @checks.not_forbidden() - async def horoscope_signs(self): + async def horoscope_signs(self, ctx): '''Sun signs''' async with clients.aiohttp_session.get("http://sandipbgt.com/theastrologer/api/sunsigns") as resp: data = await resp.json() - await self.bot.embed_reply(", ".join(data)) + await ctx.embed_reply(", ".join(data)) @horoscope.command(name = "today") @checks.not_forbidden() - async def horoscope_today(self, sign): + async def horoscope_today(self, ctx, sign): '''Today's horoscope''' - await self.process_horoscope(sign, "today") + await self.process_horoscope(ctx, sign, "today") @horoscope.command(name = "tomorrow") @checks.not_forbidden() - async def horoscope_tomorrow(self, sign): + async def horoscope_tomorrow(self, ctx, sign): '''Tomorrow's horoscope''' - await self.process_horoscope(sign, "tomorrow") + await self.process_horoscope(ctx, sign, "tomorrow") @horoscope.command(name = "yesterday") @checks.not_forbidden() - async def horoscope_yesterday(self, sign): + async def horoscope_yesterday(self, ctx, sign): '''Yesterday's horoscope''' - await self.process_horoscope(sign, "yesterday") + await self.process_horoscope(ctx, sign, "yesterday") - async def process_horoscope(self, sign, day): + async def process_horoscope(self, ctx, sign, day): if len(sign) == 1: sign = unicodedata.name(sign).lower() async with clients.aiohttp_session.get("http://sandipbgt.com/theastrologer/api/horoscope/{}/{}/".format(sign, day)) as resp: if resp.status == 404: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = await resp.json() date = [int(d) for d in data["date"].split('-')] - await self.bot.embed_reply(data["horoscope"].replace(data["credit"], ""), title = data["sunsign"], fields = sorted((k.capitalize(), v) for k, v in data["meta"].items()), footer_text = data["credit"], timestamp = datetime.datetime(date[0], date[1], date[2])) + await ctx.embed_reply(data["horoscope"].replace(data["credit"], ""), title = data["sunsign"], fields = sorted((k.capitalize(), v) for k, v in data["meta"].items()), footer_text = data["credit"], timestamp = datetime.datetime(date[0], date[1], date[2])) @commands.command(aliases = ["imagerecog", "imager", "image_recognition"]) @checks.not_forbidden() - async def imagerecognition(self, image_url : str): + async def imagerecognition(self, ctx, image_url : str): '''Image recognition''' try: response = clients.clarifai_general_model.predict_by_url(image_url) except clarifai.rest.ApiError as e: - await self.bot.embed_reply(":no_entry: Error: `{}`".format(e.response.json()["outputs"][0]["status"]["details"])) + await ctx.embed_reply(":no_entry: Error: `{}`".format(e.response.json()["outputs"][0]["status"]["details"])) return if response["status"]["description"] != "Ok": - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return names = {} for concept in response["outputs"][0]["data"]["concepts"]: @@ -241,26 +241,26 @@ async def imagerecognition(self, image_url : str): for name, value in sorted(names.items(), key = lambda i: i[1], reverse = True): output += "**{}**: {:.2f}%, ".format(name, value) output = output[:-2] - await self.bot.embed_reply(output) + await ctx.embed_reply(output) @commands.command() @checks.not_forbidden() - async def nsfw(self, image_url : str): + async def nsfw(self, ctx, image_url : str): '''NSFW recognition''' try: response = clients.clarifai_nsfw_model.predict_by_url(image_url) except clarifai.rest.ApiError as e: - await self.bot.embed_reply(":no_entry: Error: `{}`".format(e.response.json()["outputs"][0]["status"]["details"])) + await ctx.embed_reply(":no_entry: Error: `{}`".format(e.response.json()["outputs"][0]["status"]["details"])) return if response["status"]["description"] != "Ok": - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return percentages = {} for concept in response["outputs"][0]["data"]["concepts"]: percentages[concept["name"]] = concept["value"] * 100 - await self.bot.embed_reply("NSFW: {:.2f}%".format(percentages["nsfw"])) + await ctx.embed_reply("NSFW: {:.2f}%".format(percentages["nsfw"])) - @commands.command(aliases = ["movie"], pass_context = True) + @commands.command(aliases = ["movie"]) @checks.not_forbidden() async def imdb(self, ctx, *search : str): '''IMDb Information''' @@ -268,11 +268,11 @@ async def imdb(self, ctx, *search : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if data["Response"] == "False": - await self.bot.embed_reply(":no_entry: Error: {}".format(data["Error"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["Error"])) return embed = discord.Embed(title = data["Title"], url = "http://www.imdb.com/title/{}".format(data["imdbID"]), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.description = "{0[Year]} {0[Type]}".format(data) embed.add_field(name = "IMDb Rating", value = data["imdbRating"]) embed.add_field(name = "Runtime", value = data["Runtime"]) @@ -288,13 +288,13 @@ async def imdb(self, ctx, *search : str): if data["Poster"] != "N/A": embed.set_thumbnail(url = data["Poster"]) await self.bot.say(embed = embed) - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def imgur(self, ctx): '''Imgur''' - await self.bot.embed_reply("See {}help imgur".format(ctx.prefix)) + await ctx.embed_reply("See {}help imgur".format(ctx.prefix)) - @imgur.command(name = "upload", pass_context = True) + @imgur.command(name = "upload") @checks.not_forbidden() async def imgur_upload(self, ctx, url : str = ""): '''Upload images to imgur''' @@ -303,21 +303,21 @@ async def imgur_upload(self, ctx, url : str = ""): if ctx.message.attachments: await self._imgur_upload(ctx.message.attachments[0]["url"]) if not (url or ctx.message.attachments): - await self.bot.embed_reply(":no_entry: Please input an image and/or url") + await ctx.embed_reply(":no_entry: Please input an image and/or url") async def _imgur_upload(self, url): try: - await self.bot.embed_reply(clients.imgur_client.upload_from_url(url)["link"]) + await ctx.embed_reply(clients.imgur_client.upload_from_url(url)["link"]) except imgurpython.helpers.error.ImgurClientError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @commands.group() @checks.not_forbidden() - async def lichess(self): + async def lichess(self, ctx): '''WIP''' return - @lichess.group(name = "user", pass_context = True) + @lichess.group(name = "user") async def lichess_user(self, ctx): '''WIP''' if len(ctx.message.content.split()) == 2: @@ -330,13 +330,13 @@ async def lichess_user(self, ctx): raise errors.LichessUserNotFound @lichess_user.command(name = "bullet") - async def lichess_user_bullet(self, username : str): + async def lichess_user_bullet(self, ctx, username : str): '''WIP''' data = self.lichess_user_data await self.bot.embed_reply(":zap: Bullet | **Games**: {0[games]}, **Rating**: {0[rating]}{prov}±{0[rd]}, {chart} {0[prog]}".format(data["perfs"]["bullet"], prov = "?" if data["perfs"]["bullet"]["prov"] else "", chart = ":chart_with_upwards_trend:" if data["perfs"]["bullet"]["prog"] >= 0 else ":chart_with_downwards_trend:"), title = data["username"]) @lichess_user.command(name = "blitz") - async def lichess_user_blitz(self, username : str): + async def lichess_user_blitz(self, ctx, username : str): '''WIP''' data = self.lichess_user_data await self.bot.embed_reply(":fire: Blitz | **Games**: {0[games]}, **Rating**: {0[rating]}{prov}±{0[rd]}, {chart} {0[prog]}".format(data["perfs"]["blitz"], prov = "?" if data["perfs"]["blitz"]["prov"] else "", chart = ":chart_with_upwards_trend:" if data["perfs"]["blitz"]["prog"] >= 0 else ":chart_with_downwards_trend:"), title = data["username"]) @@ -346,13 +346,13 @@ async def lichess_user_error(self, error, ctx): if isinstance(error, errors.LichessUserNotFound): await self.bot.embed_reply(":no_entry: User not found") - @lichess_user.command(name = "all", pass_context = True) + @lichess_user.command(name = "all") async def lichess_user_all(self, ctx, username : str): '''WIP''' data = self.lichess_user_data embed = discord.Embed(title = data["username"], url = data["url"], color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.description = "Online: {}\n".format(data["online"]) embed.description += "Member since {}\n".format(datetime.datetime.utcfromtimestamp(data["createdAt"] / 1000.0).strftime("%b %#d, %Y")) # embed.add_field(name = "Games", value = "Played: {0[all]}\nRated: {0[rated]}\nWins: {0[win]}\nLosses: {0[loss]}\nDraws: {0[draw]}\nBookmarks: {0[bookmark]}\nAI: {0[ai]}".format(data["count"])) @@ -369,19 +369,19 @@ async def lichess_user_all(self, ctx, username : str): await self.bot.say(embed = embed) @lichess.group(name = "tournaments") - async def lichess_tournaments(self): + async def lichess_tournaments(self, ctx): '''WIP''' url = "https://en.lichess.org/api/tournament" async with clients.aiohttp_session.get(url) as resp: self.lichess_tournaments_data = await resp.json() - @lichess_tournaments.command(name = "current", aliases = ["started"], pass_context = True) + @lichess_tournaments.command(name = "current", aliases = ["started"]) async def lichess_tournaments_current(self, ctx): '''WIP''' data = self.lichess_tournaments_data["started"] embed = discord.Embed(title = "Current Lichess Tournaments", color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) for tournament in data: value = "{:g}+{} {} {rated}".format(tournament["clock"]["limit"] / 60, tournament["clock"]["increment"], tournament["perf"]["name"], rated = "Rated" if tournament["rated"] else "Casual") value += "\nEnds in: {:g}m".format((datetime.datetime.utcfromtimestamp(tournament["finishesAt"] / 1000.0) - datetime.datetime.utcnow()).total_seconds() // 60) @@ -390,41 +390,41 @@ async def lichess_tournaments_current(self, ctx): await self.bot.say(embed = embed) @lichess.command(name = "tournament") - async def lichess_tournament(self): + async def lichess_tournament(self, ctx): '''WIP''' pass @commands.command() @checks.not_forbidden() - async def longurl(self, url : str): + async def longurl(self, ctx, url : str): '''Expand a short goo.gl url''' url = "https://www.googleapis.com/urlshortener/v1/url?shortUrl={}&key={}".format(url, credentials.google_apikey) async with clients.aiohttp_session.get(url) as resp: if resp.status == 400: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = await resp.json() - await self.bot.embed_reply(data["longUrl"]) + await ctx.embed_reply(data["longUrl"]) @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def map(self, *, location : str): + async def map(self, ctx, *, location : str): '''See map of location''' map_url = "https://maps.googleapis.com/maps/api/staticmap?center={}&zoom=13&size=640x640".format(location.replace(' ', '+')) - await self.bot.embed_reply("[:map:]({})".format(map_url), image_url = map_url) + await ctx.embed_reply("[:map:]({})".format(map_url), image_url = map_url) @map.command(name = "options") @checks.not_forbidden() - async def map_options(self, zoom : int, maptype : str, *, location : str): + async def map_options(self, ctx, zoom : int, maptype : str, *, location : str): ''' More customized map of a location Zoom: 0 - 21+ (Default: 13) Map Types: roadmap, satellite, hybrid, terrain (Default: roadmap) ''' map_url = "https://maps.googleapis.com/maps/api/staticmap?center={}&zoom={}&maptype={}&size=640x640".format(location.replace(' ', '+'), zoom, maptype) - await self.bot.embed_reply("[:map:]({})".format(map_url), image_url = map_url) + await ctx.embed_reply("[:map:]({})".format(map_url), image_url = map_url) - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def news(self, ctx, source : str): ''' @@ -434,10 +434,10 @@ async def news(self, ctx, source : str): async with clients.aiohttp_session.get("https://newsapi.org/v1/articles?source={}&apiKey={}".format(source, credentials.news_api_key)) as resp: data = await resp.json() if data["status"] != "ok": - await self.bot.embed_reply(":no_entry: Error: {}".format(data["message"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["message"])) return ''' - paginator = commands.formatter.Paginator(prefix = "{}:".format(ctx.message.author.display_name), suffix = "") + paginator = commands.formatter.Paginator(prefix = "{}:".format(ctx.author.display_name), suffix = "") for article in data["articles"]: paginator.add_line("**{}** ({})".format(article["title"], article["publishedAt"].replace('T', " ").replace('Z', ""))) paginator.add_line("{}".format(article["description"])) @@ -453,7 +453,7 @@ async def news(self, ctx, source : str): for number_emote in sorted(numbers.keys()): await self.bot.add_reaction(response, number_emote) while True: - emoji_response = await self.bot.wait_for_reaction(user = ctx.message.author, message = response, emoji = numbers.keys()) + emoji_response = await self.bot.wait_for_reaction(user = ctx.author, message = response, emoji = numbers.keys()) reaction = emoji_response.reaction number = numbers[reaction.emoji] article = data["articles"][number - 1] @@ -465,11 +465,11 @@ async def news(self, ctx, source : str): # output += "\n<{}>".format(article["url"]) output += "\n{}".format(article["url"]) output += "\nSelect a different number for another article" - await self.bot.edit_message(response, "{}: {}".format(ctx.message.author.display_name, output)) + await self.bot.edit_message(response, "{}: {}".format(ctx.author.display_name, output)) @news.command(name = "sources") @checks.not_forbidden() - async def news_sources(self): + async def news_sources(self, ctx): ''' News sources https://newsapi.org/sources @@ -477,14 +477,14 @@ async def news_sources(self): async with clients.aiohttp_session.get("https://newsapi.org/v1/sources") as resp: data = await resp.json() if data["status"] != "ok": - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return # for source in data["sources"]: await self.bot.reply("\n{}".format(", ".join([source["id"] for source in data["sources"]]))) @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def oeis(self, *, search : str): + async def oeis(self, ctx, *, search : str): ''' The On-Line Encyclopedia of Integer Sequences Does not accept spaces for search by sequence @@ -493,15 +493,15 @@ async def oeis(self, *, search : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if data["results"]: - await self.bot.embed_reply(data["results"][0]["data"], title = data["results"][0]["name"]) + await ctx.embed_reply(data["results"][0]["data"], title = data["results"][0]["name"]) elif data["count"]: - await self.bot.embed_reply(":no_entry: Too many sequences found") + await ctx.embed_reply(":no_entry: Too many sequences found") else: - await self.bot.embed_reply(":no_entry: Sequence not found") + await ctx.embed_reply(":no_entry: Sequence not found") @oeis.command(name = "graph") @checks.not_forbidden() - async def oeis_graph(self, *, search : str): + async def oeis_graph(self, ctx, *, search : str): ''' The On-Line Encyclopedia of Integer Sequences Does not accept spaces for search by sequence @@ -511,15 +511,15 @@ async def oeis_graph(self, *, search : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if data["results"]: - await self.bot.embed_reply(None, image_url = "https://oeis.org/A{:06d}/graph?png=1".format(data["results"][0]["number"])) + await ctx.embed_reply(image_url = "https://oeis.org/A{:06d}/graph?png=1".format(data["results"][0]["number"])) elif data["count"]: - await self.bot.embed_reply(":no_entry: Too many sequences found") + await ctx.embed_reply(":no_entry: Too many sequences found") else: - await self.bot.embed_reply(":no_entry: Sequence not found") + await ctx.embed_reply(":no_entry: Sequence not found") @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def overwatch(self): + async def overwatch(self, ctx): ''' WIP Note: battletags are case sensitive @@ -532,7 +532,7 @@ async def overwatch(self): ''' pass - @overwatch.group(name = "stats", pass_context = True, invoke_without_command = True) + @overwatch.group(name = "stats", invoke_without_command = True) async def overwatch_stats(self, ctx, battletag : str): ''' Overwatch user statistics @@ -548,8 +548,8 @@ async def overwatch_stats(self, ctx, battletag : str): if data[region]: stats = data[region]["stats"]["quickplay"] embed = discord.Embed(title = battletag, color = clients.bot_color) - avatar = ctx.message.author.default_avatar_url if not ctx.message.author.avatar else ctx.message.author.avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.set_thumbnail(url = stats["overall_stats"]["avatar"]) embed.add_field(name = "Level", value = stats["overall_stats"]["level"]) embed.add_field(name = "Prestige", value = stats["overall_stats"]["prestige"]) @@ -561,7 +561,7 @@ async def overwatch_stats(self, ctx, battletag : str): ''' await self.bot.say(embed = embed) - @overwatch_stats.command(name = "quickplay", aliases = ["qp"], pass_context = True) + @overwatch_stats.command(name = "quickplay", aliases = ["qp"]) async def overwatch_stats_quickplay(self, ctx, battletag : str): ''' Overwatch user quickplay statistics @@ -577,8 +577,8 @@ async def overwatch_stats_quickplay(self, ctx, battletag : str): if data[region]: stats = data[region]["stats"]["quickplay"] embed = discord.Embed(title = "{} ({})".format(battletag, region.upper()), color = clients.bot_color) - avatar = ctx.message.author.default_avatar_url if not ctx.message.author.avatar else ctx.message.author.avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.set_thumbnail(url = stats["overall_stats"]["avatar"]) embed.add_field(name = "Level", value = stats["overall_stats"]["level"]) embed.add_field(name = "Prestige", value = stats["overall_stats"]["prestige"]) @@ -594,7 +594,7 @@ async def overwatch_stats_quickplay(self, ctx, battletag : str): embed.add_field(name = "Deaths", value = "{:,g} total\n{:,g} average".format(stats["game_stats"]["deaths"], stats["average_stats"]["deaths_avg"])) await self.bot.say(embed = embed) - @overwatch_stats.command(name = "competitive", aliases = ["comp"], pass_context = True) + @overwatch_stats.command(name = "competitive", aliases = ["comp"]) async def overwatch_stats_competitive(self, ctx, battletag : str): ''' Overwatch user quickplay statistics @@ -610,8 +610,8 @@ async def overwatch_stats_competitive(self, ctx, battletag : str): if data[region]: stats = data[region]["stats"]["competitive"] embed = discord.Embed(title = "{} ({})".format(battletag, region.upper()), color = clients.bot_color) - avatar = ctx.message.author.default_avatar_url if not ctx.message.author.avatar else ctx.message.author.avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.set_thumbnail(url = stats["overall_stats"]["avatar"]) embed.add_field(name = "Level", value = stats["overall_stats"]["level"]) embed.add_field(name = "Prestige", value = stats["overall_stats"]["prestige"]) @@ -628,7 +628,7 @@ async def overwatch_stats_competitive(self, ctx, battletag : str): await self.bot.say(embed = embed) @overwatch.command(name = "heroes", hidden = True) - async def overwatch_heroes(self, battletag : str, number : str): + async def overwatch_heroes(self, ctx, battletag : str, number : str): ''' Overwatch user hero statistics Note: battletags are case sensitive @@ -646,19 +646,19 @@ async def overwatch_heroes(self, battletag : str, number : str): #plural await self.bot.embed_reply('\n'.join(output)) - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def phone(self, ctx, *, phone : str): # add reactions version '''Get phone specifications''' async with clients.aiohttp_session.get("https://fonoapi.freshpixl.com/v1/getdevice?device={}&position=0&token={}".format(phone.replace(' ', '+'), credentials.fonoapi_token)) as resp: data = await resp.json() if "status" in data and data["status"] == "error": - await self.bot.embed_reply(":no_entry: Error: {}".format(data["message"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["message"])) return data = data[0] embed = discord.Embed(title = data["DeviceName"], color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) # Brand if "Brand" in data: embed.add_field(name = "Brand", value = data["Brand"]) # Network (network_c?) @@ -771,7 +771,7 @@ async def phone(self, ctx, *, phone : str): # add reactions version @commands.command(aliases = ["audiodefine", "pronounce"]) @checks.not_forbidden() - async def pronunciation(self, word : str): + async def pronunciation(self, ctx, word : str): '''Pronunciation of a word''' pronunciation = clients.wordnik_word_api.getTextPronunciations(word, limit = 1) description = pronunciation[0].raw.strip("()") if pronunciation else "Audio File Link" @@ -779,27 +779,27 @@ async def pronunciation(self, word : str): if audio_file: description = "[{}]({})".format(description, audio_file[0].fileUrl) elif not pronunciation: - await self.bot.embed_reply(":no_entry: Word or pronunciation not found") + await ctx.embed_reply(":no_entry: Word or pronunciation not found") return - await self.bot.embed_reply(description, title = "Pronunciation of {}".format(word.capitalize())) + await ctx.embed_reply(description, title = "Pronunciation of {}".format(word.capitalize())) @commands.command(hidden = True) @checks.not_forbidden() - async def redditsearch(self): + async def redditsearch(self, ctx): '''WIP''' return @commands.command(aliases = ["rhymes"]) @checks.not_forbidden() - async def rhyme(self, word : str): + async def rhyme(self, ctx, word : str): '''Rhymes of a word''' rhymes = clients.wordnik_word_api.getRelatedWords(word, relationshipTypes = "rhyme", limitPerRelationshipType = 100) if not rhymes: - await self.bot.embed_reply(":no_entry: Word or rhymes not found") + await ctx.embed_reply(":no_entry: Word or rhymes not found") return - await self.bot.embed_reply(', '.join(rhymes[0].words), title = "Words that rhyme with {}".format(word.capitalize())) + await ctx.embed_reply(', '.join(rhymes[0].words), title = "Words that rhyme with {}".format(word.capitalize())) - @commands.group(aliases = ["realmofthemadgod"], pass_context = True, invoke_without_command = True) + @commands.group(aliases = ["realmofthemadgod"], invoke_without_command = True) @checks.not_forbidden() async def rotmg(self, ctx, player : str): '''Realm of the Mad God player information''' @@ -808,11 +808,11 @@ async def rotmg(self, ctx, player : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if "error" in data: - await self.bot.embed_reply("Error: " + data["error"]) + await ctx.embed_reply("Error: " + data["error"]) return embed = discord.Embed(title = data["player"], url = "https://www.realmeye.com/player/{}".format(player), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) if data["donator"] == "true": embed.description = "Donator" embed.add_field(name = "Characters", value = data["chars"]) embed.add_field(name = "Total Fame", value = "{:,}".format(data["fame"])) @@ -831,7 +831,7 @@ async def rotmg(self, ctx, player : str): embed.add_field(name = "Description", value = "{}\n{}\n{}".format(data["desc1"], data["desc2"], data["desc3"])) await self.bot.say(embed = embed) - @rotmg.command(name = "characters", pass_context = True) + @rotmg.command(name = "characters") @checks.not_forbidden() async def rotmg_characters(self, ctx, player : str): '''Realm of the Mad God player characters information''' @@ -840,11 +840,11 @@ async def rotmg_characters(self, ctx, player : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if "error" in data: - await self.bot.embed_reply("Error: " + data["error"]) + await ctx.embed_reply("Error: " + data["error"]) return embed = discord.Embed(title = "{}'s Characters".format(data["player"]), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) for character in data["characters"]: value = "Fame: {0[fame]:,}, Exp: {0[exp]:,}, Rank: {0[place]:,}, Class Quests Completed: {0[cqc]}, Stats Maxed: {0[stats_maxed]}".format(character) value += "\nHP: {0[hp]}, MP: {0[mp]}, Attack: {0[attack]}, Defense: {0[defense]}, Speed: {0[speed]}, Vitality: {0[vitality]}, Wisdom: {0[wisdom]}, Dexterity: {0[dexterity]}".format(character["stats"]) @@ -859,13 +859,13 @@ async def rotmg_characters(self, ctx, player : str): @commands.group(aliases = ["rs"], invoke_without_command = True) @checks.not_forbidden() - async def runescape(self): + async def runescape(self, ctx): '''Runescape''' ... @runescape.command(name = "ge", aliases = ["grandexchange"]) @checks.not_forbidden() - async def runescape_ge(self, *, item): + async def runescape_ge(self, ctx, *, item): '''Runescape GE''' # http://services.runescape.com/m=rswiki/en/Grand_Exchange_APIs # http://forums.zybez.net/runescape-2007-prices/api/?info @@ -941,7 +941,7 @@ async def runescape_ge(self, *, item): } ''' - @runescape.command(name = "monster", aliases = ["bestiary"], pass_context = True) + @runescape.command(name = "monster", aliases = ["bestiary"]) @checks.not_forbidden() async def runescape_monster(self, ctx, *, monster : str): '''Runescape bestiary''' @@ -955,8 +955,8 @@ async def runescape_monster(self, ctx, *, monster : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() embed = discord.Embed(title = data["name"], description = data["description"], color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.add_field(name = "Level", value = data["level"]) embed.add_field(name = "Weakness", value = data["weakness"]) embed.add_field(name = "XP/Kill", value = data["xp"]) @@ -966,7 +966,7 @@ async def runescape_monster(self, ctx, *, monster : str): await self.bot.say(embed = embed) # add other? - http://runescape.wikia.com/wiki/RuneScape_Bestiary#beastData - @runescape.command(name = "stats", aliases = ["levels"], pass_context = True) + @runescape.command(name = "stats", aliases = ["levels"]) @checks.not_forbidden() async def runescape_stats(self, ctx, *, username : str): '''Runescape stats''' @@ -981,8 +981,8 @@ async def runescape_stats(self, ctx, *, username : str): for stat in stats_names: stats[stat] = next(data) embed = discord.Embed(title = username, url = "http://services.runescape.com/m=hiscore/compare?user1={}".format(username.replace(' ', '+')), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) output = ["`{}`".format(name) for name in stats_names] embed.add_field(name = "Skill", value = '\n'.join(output)) @@ -999,7 +999,7 @@ async def runescape_stats(self, ctx, *, username : str): @runescape.command(name = "zybez") @checks.not_forbidden() - async def runescape_zybez(self, *, item): + async def runescape_zybez(self, ctx, *, item): '''Runescape Zybez average price''' url = "http://forums.zybez.net/runescape-2007-prices/api/item/{}".format(item.replace(' ', '+')) async with clients.aiohttp_session.get(url) as resp: @@ -1012,10 +1012,10 @@ async def runescape_zybez(self, *, item): @commands.command() @checks.not_forbidden() - async def shorturl(self, url : str): + async def shorturl(self, ctx, url : str): '''Generate a short goo.gl url for your link''' short_url = await self._shorturl(url) - await self.bot.embed_reply(short_url) + await ctx.embed_reply(short_url) async def _shorturl(self, url): async with clients.aiohttp_session.post("https://www.googleapis.com/urlshortener/v1/url?key={}".format(credentials.google_apikey), headers = {'Content-Type': 'application/json'}, data = '{"longUrl": "' + url +'"}') as resp: @@ -1024,7 +1024,7 @@ async def _shorturl(self, url): @commands.command() @checks.not_forbidden() - async def spellcheck(self, *, words : str): + async def spellcheck(self, ctx, *, words : str): '''Spell check words''' async with clients.aiohttp_session.post("https://api.cognitive.microsoft.com/bing/v5.0/spellcheck?Text=" + words.replace(' ', '+'), headers = {"Ocp-Apim-Subscription-Key" : credentials.bing_spell_check_key}) as resp: data = await resp.json() @@ -1036,9 +1036,9 @@ async def spellcheck(self, *, words : str): suggestion = correction["suggestions"][0]["suggestion"] corrected = corrected[:offset] + suggestion + corrected[offset + len(correction["token"]):] offset += (len(suggestion) - len(correction["token"])) - correction["offset"] - await self.bot.embed_reply(corrected) + await ctx.embed_reply(corrected) - @commands.command(aliases = ["spotify_info"], pass_context = True) + @commands.command(aliases = ["spotify_info"]) @checks.not_forbidden() async def spotifyinfo(self, ctx, url : str): '''Information about a Spotify track''' @@ -1059,22 +1059,22 @@ async def spotifyinfo(self, ctx, url : str): @commands.command(aliases = ["sptoyt", "spotify_to_youtube", "sp_to_yt"]) @checks.not_forbidden() - async def spotifytoyoutube(self, url : str): + async def spotifytoyoutube(self, ctx, url : str): '''Find a Spotify track on Youtube''' link = await self.bot.cogs["Audio"].spotify_to_youtube(url) if link: await self.bot.reply(link) else: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def steam(self): + async def steam(self, ctx): '''Steam Information''' return @steam.command(name = "appid") - async def steam_appid(self, *, app : str): + async def steam_appid(self, ctx, *, app : str): '''Get the AppID''' async with clients.aiohttp_session.get("http://api.steampowered.com/ISteamApps/GetAppList/v0002/") as resp: data = await resp.json() @@ -1084,10 +1084,10 @@ async def steam_appid(self, *, app : str): if _app["name"].lower() == app.lower(): appid = _app["appid"] break - await self.bot.embed_reply(appid) + await ctx.embed_reply(appid) @steam.command(name = "gamecount", aliases = ["game_count"]) - async def steam_gamecount(self, vanity_name : str): + async def steam_gamecount(self, ctx, vanity_name : str): '''Find how many games someone has''' url = "http://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key={0}&vanityurl={1}".format(credentials.steam_apikey, vanity_name) async with clients.aiohttp_session.get(url) as resp: @@ -1097,39 +1097,39 @@ async def steam_gamecount(self, vanity_name : str): async with clients.aiohttp_session.get(url) as resp: data = await resp.json() gamecount = data["response"]["game_count"] - await self.bot.embed_reply("{} has {} games".format(vanity_name, gamecount)) + await ctx.embed_reply("{} has {} games".format(vanity_name, gamecount)) @steam.command(name = "gameinfo", aliases = ["game_info"]) - async def steam_gameinfo(self, *, game : str): + async def steam_gameinfo(self, ctx, *, game : str): '''Information about a game''' async with clients.aiohttp_session.get("http://api.steampowered.com/ISteamApps/GetAppList/v0002/") as resp: data = await resp.json() app = discord.utils.find(lambda app: app["name"].lower() == game.lower(), data["applist"]["apps"]) if not app: - await self.bot.embed_reply(":no_entry: Game not found") + await ctx.embed_reply(":no_entry: Game not found") return appid = str(app["appid"]) url = "http://store.steampowered.com/api/appdetails/?appids={}".format(appid) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() data = data[appid]["data"] - await self.bot.embed_reply(data["short_description"], title = data["name"], title_url = data["website"], fields = (("Release Date", data["release_date"]["date"]), ("Free", "Yes" if data["is_free"] else "No"), ("App ID", data["steam_appid"])), image_url = data["header_image"]) + await ctx.embed_reply(data["short_description"], title = data["name"], title_url = data["website"], fields = (("Release Date", data["release_date"]["date"]), ("Free", "Yes" if data["is_free"] else "No"), ("App ID", data["steam_appid"])), image_url = data["header_image"]) @steam.command(name = "run", aliases = ["launch"]) - async def steam_run(self, *, game : str): + async def steam_run(self, ctx, *, game : str): '''Generate a steam link to launch a game''' async with clients.aiohttp_session.get("http://api.steampowered.com/ISteamApps/GetAppList/v0002/") as resp: data = await resp.json() app = discord.utils.find(lambda app: app["name"].lower() == game.lower(), data["applist"]["apps"]) if not app: - await self.bot.embed_reply(":no_entry: Game not found") + await ctx.embed_reply(":no_entry: Game not found") return appid = app["appid"] - await self.bot.embed_reply("[Launch {}](steam://run/{})".format(game, appid)) + await ctx.embed_reply("[Launch {}](steam://run/{})".format(game, appid)) @commands.command() @checks.not_forbidden() - async def strawpoll(self, question : str, *options : str): + async def strawpoll(self, ctx, question : str, *options : str): ''' Generate a strawpoll link Use qoutes for spaces in the question or options @@ -1140,74 +1140,74 @@ async def strawpoll(self, question : str, *options : str): @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def streetview(self, *, location : str): + async def streetview(self, ctx, *, location : str): '''Generate street view of a location''' image_url = "https://maps.googleapis.com/maps/api/streetview?size=400x400&location={}".format(location.replace(' ', '+')) - await self.bot.embed_reply(None, image_url = image_url) + await ctx.embed_reply(image_url = image_url) @commands.command(aliases = ["synonyms"]) @checks.not_forbidden() - async def synonym(self, word : str): + async def synonym(self, ctx, word : str): '''Synonyms of a word''' synonyms = clients.wordnik_word_api.getRelatedWords(word, relationshipTypes = "synonym", useCanonical = "true", limitPerRelationshipType = 100) if not synonyms: - await self.bot.embed_reply(":no_entry: Word or synonyms not found") + await ctx.embed_reply(":no_entry: Word or synonyms not found") return - await self.bot.embed_reply(', '.join(synonyms[0].words), title = "Synonyms of {}".format(word.capitalize())) + await ctx.embed_reply(', '.join(synonyms[0].words), title = "Synonyms of {}".format(word.capitalize())) @commands.group(description = "[Language Codes](https://tech.yandex.com/translate/doc/dg/concepts/api-overview-docpage/#languages)\n" "Powered by [Yandex.Translate](http://translate.yandex.com/)", invoke_without_command = True) @checks.not_forbidden() - async def translate(self, *, text : str): + async def translate(self, ctx, *, text : str): '''Translate to English''' # TODO: From and to language code options? - await self.process_translate(text, "en") + await self.process_translate(ctx, text, "en") @translate.command(name = "from") @checks.not_forbidden() - async def translate_from(self, from_language_code : str, to_language_code : str, *, text : str): + async def translate_from(self, ctx, from_language_code : str, to_language_code : str, *, text : str): ''' Translate from a specific language to another [Language Codes](https://tech.yandex.com/translate/doc/dg/concepts/api-overview-docpage/#languages) Powered by [Yandex.Translate](http://translate.yandex.com/) ''' # TODO: Default to_language_code? - await self.process_translate(text, to_language_code, from_language_code) + await self.process_translate(ctx, text, to_language_code, from_language_code) @translate.command(name = "languages", aliases = ["codes", "language_codes"]) @checks.not_forbidden() - async def translate_languages(self, language_code : str = "en"): + async def translate_languages(self, ctx, language_code : str = "en"): '''Language Codes''' async with clients.aiohttp_session.get("https://translate.yandex.net/api/v1.5/tr.json/getLangs?ui={}&key={}".format(language_code, credentials.yandex_translate_api_key)) as resp: data = await resp.json() if "langs" not in data: - await self.bot.embed_reply(":no_entry: Error: Invalid Language Code") + await ctx.embed_reply(":no_entry: Error: Invalid Language Code") return - await self.bot.embed_reply(", ".join(sorted("{} ({})".format(language, code) for code, language in data["langs"].items()))) + await ctx.embed_reply(", ".join(sorted("{} ({})".format(language, code) for code, language in data["langs"].items()))) @translate.command(name = "to") @checks.not_forbidden() - async def translate_to(self, language_code : str, *, text : str): + async def translate_to(self, ctx, language_code : str, *, text : str): ''' Translate to a specific language [Language Codes](https://tech.yandex.com/translate/doc/dg/concepts/api-overview-docpage/#languages) Powered by [Yandex.Translate](http://translate.yandex.com/) ''' - await self.process_translate(text, language_code) + await self.process_translate(ctx, text, language_code) - async def process_translate(self, text, to_language_code, from_language_code = None): + async def process_translate(self, ctx, text, to_language_code, from_language_code = None): url = "https://translate.yandex.net/api/v1.5/tr.json/translate?key={}&lang={}&text={}&options=1".format(credentials.yandex_translate_api_key, to_language_code if not from_language_code else "{}-{}".format(from_language_code, to_language_code), text.replace(' ', '+')) async with clients.aiohttp_session.get(url) as resp: if resp.status == 400: # Bad Request - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = await resp.json() if data["code"] != 200: - await self.bot.embed_reply(":no_entry: Error: {}".format(data["message"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["message"])) return - await self.bot.embed_reply(data["text"][0], footer_text = "{}Powered by Yandex.Translate".format("Detected Language Code: {} | ".format(data["detected"]["lang"]) if not from_language_code else "")) + await ctx.embed_reply(data["text"][0], footer_text = "{}Powered by Yandex.Translate".format("Detected Language Code: {} | ".format(data["detected"]["lang"]) if not from_language_code else "")) - @commands.command(aliases = ["urband", "urban_dictionary", "urbandefine", "urban_define"], pass_context = True) + @commands.command(aliases = ["urband", "urban_dictionary", "urbandefine", "urban_define"]) @checks.not_forbidden() async def urbandictionary(self, ctx, *, term : str): '''Urban Dictionary''' @@ -1215,16 +1215,17 @@ async def urbandictionary(self, ctx, *, term : str): async with clients.aiohttp_session.get("http://api.urbandictionary.com/v0/define?term={}".format(term.replace('+', ' '))) as resp: data = await resp.json() if not data or "list" not in data or not data["list"]: - await self.bot.embed_reply(":no_entry: No results found") + await ctx.embed_reply(":no_entry: No results found") return num_results = len(data["list"]) # if one definition if num_results > 10: num_reults = 10 - response, embed = await self.bot.embed_reply("React with a number from 1 to {} to view each definition".format(num_results)) + response = await ctx.embed_reply("React with a number from 1 to {} to view each definition".format(num_results)) + embed = response.embeds[0] numbers = {"1⃣": 1, "2⃣": 2, "3⃣": 3, "4⃣": 4, "5⃣": 5, "6⃣": 6, "7⃣": 7, "8⃣": 8, "9⃣": 9, "🔟" : 10} for number_emote in sorted(numbers.keys())[:num_results]: await self.bot.add_reaction(response, number_emote) while True: - emoji_response = await self.bot.wait_for_reaction(user = ctx.message.author, message = response, emoji = sorted(numbers.keys())[:num_results]) + emoji_response = await self.bot.wait_for_reaction(user = ctx.author, message = response, emoji = sorted(numbers.keys())[:num_results]) reaction = emoji_response.reaction number = numbers[reaction.emoji] definition = data["list"][number - 1] @@ -1237,7 +1238,7 @@ async def urbandictionary(self, ctx, *, term : str): embed.set_footer(text = "Select a different number for another definition") await self.bot.edit_message(response, embed = embed) - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def weather(self, ctx, *, location : str): '''Weather''' @@ -1245,10 +1246,10 @@ async def weather(self, ctx, *, location : str): try: observation = clients.owm_client.weather_at_place(location) except pyowm.exceptions.not_found_error.NotFoundError: - await self.bot.embed_reply(":no_entry: Location not found") + await ctx.embed_reply(":no_entry: Location not found") return except pyowm.exceptions.api_call_error.BadGatewayError: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") # Add exception message to response when pyowm issue (https://github.com/csparpa/pyowm/issues/176) fixed return location = observation.get_location() @@ -1262,8 +1263,8 @@ async def weather(self, ctx, *, location : str): pressure = weather.get_pressure()["press"] visibility = weather.get_visibility_distance() embed = discord.Embed(description = "**__{}__**".format(location.get_name()), color = clients.bot_color, timestamp = weather.get_reference_time(timeformat = "date").replace(tzinfo = None)) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.add_field(name = "Conditions", value = "{}{}".format(condition, emote)) embed.add_field(name = "Temperature", value = "{}°C\n{}°F".format(weather.get_temperature(unit = "celsius")["temp"], weather.get_temperature(unit = "fahrenheit")["temp"])) embed.add_field(name = "Wind", value = "{0} {1:.2f} km/h\n{0} {2:.2f} mi/h".format(self.wind_degrees_to_direction(wind["deg"]), wind["speed"] * 3.6, wind["speed"] * 2.236936)) @@ -1294,7 +1295,7 @@ def wind_degrees_to_direction(self, degrees): @commands.command() @checks.not_forbidden() - async def websitescreenshot(self, url : str): + async def websitescreenshot(self, ctx, url : str): '''Take a screenshot of a website''' response, embed = None, None while True: @@ -1307,37 +1308,37 @@ async def websitescreenshot(self, url : str): embed.description = "Processing {}\nEstimated wait time: {} sec".format(url, wait_time) await self.bot.edit_message(response, embed = embed) else: - response, embed = await self.bot.embed_reply("Processing {}\nEstimated wait time: {} sec".format(url, wait_time)) + response = await ctx.embed_reply("Processing {}\nEstimated wait time: {} sec".format(url, wait_time)) await asyncio.sleep(wait_time) elif data["status"] == "finished": - await self.bot.embed_reply("Your screenshot of {}:".format(url), image_url = data["image_url"]) + await ctx.embed_reply("Your screenshot of {}:".format(url), image_url = data["image_url"]) return elif data["status"] == "error": - await self.bot.embed_reply(":no_entry: Error: {}".format(data["msg"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["msg"])) return @commands.command(aliases = ["whatare"]) @checks.not_forbidden() - async def whatis(self, *search : str): #WIP + async def whatis(self, ctx, *search : str): '''WIP''' if not search: - await self.bot.embed_reply("What is what?") + await ctx.embed_reply("What is what?") else: url = "https://kgsearch.googleapis.com/v1/entities:search?limit=1&query={}&key={}".format('+'.join(search), credentials.google_apikey) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() if data.get("itemListElement") and data["itemListElement"][0].get("result", {}).get("detailedDescription", {}).get("articleBody", {}): - await self.bot.embed_reply(data["itemListElement"][0]["result"]["detailedDescription"]["articleBody"]) + await ctx.embed_reply(data["itemListElement"][0]["result"]["detailedDescription"]["articleBody"]) else: - await self.bot.embed_reply("I don't know what that is") + await ctx.embed_reply("I don't know what that is") @commands.group(aliases = ["worldofwarcraft"]) @checks.not_forbidden() - async def wow(self): + async def wow(self, ctx): '''World of Warcraft''' pass - @wow.command(name = "character", pass_context = True) + @wow.command(name = "character") @checks.not_forbidden() async def wow_character(self, ctx, character : str, *, realm : str): '''WIP''' @@ -1358,11 +1359,11 @@ async def wow_character(self, ctx, character : str, *, realm : str): async with clients.aiohttp_session.get("https://us.api.battle.net/wow/character/{}/{}?apikey={}".format(realm, character, credentials.battle_net_api_key)) as resp: data = await resp.json() if resp.status != 200: - await self.bot.embed_reply(":no_entry: Error: {}".format(data["reason"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data["reason"])) return embed = discord.Embed(title = data["name"], url = "http://us.battle.net/wow/en/character/{}/{}/".format(data["realm"].replace(' ', '-'), data["name"]), description = "{} ({})".format(data["realm"], data["battlegroup"]), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.add_field(name = "Level", value = data["level"]) embed.add_field(name = "Achievement Points", value = data["achievementPoints"]) embed.add_field(name = "Class", value = "{}\n[Talent Calculator](http://us.battle.net/wow/en/tool/talent-calculator#{})".format(classes.get(data["class"], "Unknown"), data["calcClass"])) @@ -1374,18 +1375,18 @@ async def wow_character(self, ctx, character : str, *, realm : str): await self.bot.say(embed = embed) # faction and total honorable kills? - @wow.command(name = "statistics", pass_context = True) + @wow.command(name = "statistics") @checks.not_forbidden() async def wow_statistics(self, ctx, character : str, *, realm : str): '''WIP''' async with clients.aiohttp_session.get("https://us.api.battle.net/wow/character/{}/{}?fields=statistics&apikey={}".format(realm, character, credentials.battle_net_api_key)) as resp: data = await resp.json() embed = discord.Embed(title = data["name"], url = "http://us.battle.net/wow/en/character/{}/{}/".format(data["realm"].replace(' ', '-'), data["name"]), description = "{} ({})".format(data["realm"], data["battlegroup"]), color = clients.bot_color) - avatar = ctx.message.author.avatar_url or ctx.message.author.default_avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) statistics = data["statistics"] - @commands.group(pass_context = True, invoke_without_command = True) + @commands.group(invoke_without_command = True) @checks.not_forbidden() async def xkcd(self, ctx, number : int = 0): '''Find xkcd's''' @@ -1398,27 +1399,27 @@ async def xkcd(self, ctx, number : int = 0): async def process_xkcd(self, ctx, url): async with clients.aiohttp_session.get(url) as resp: if resp.status == 404: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = await resp.json() - await self.bot.embed_reply(None, title = data["title"], title_url = "http://xkcd.com/{}".format(data["num"]), image_url = data["img"], footer_text = data["alt"], timestamp = datetime.datetime(int(data["year"]), int(data["month"]), int(data["day"]))) + await ctx.embed_reply(title = data["title"], title_url = "http://xkcd.com/{}".format(data["num"]), image_url = data["img"], footer_text = data["alt"], timestamp = datetime.datetime(int(data["year"]), int(data["month"]), int(data["day"]))) - @commands.command(aliases = ["ytinfo", "youtube_info", "yt_info"], pass_context = True) + @commands.command(aliases = ["ytinfo", "youtube_info", "yt_info"]) @checks.not_forbidden() async def youtubeinfo(self, ctx, url : str): '''Information on Youtube videos''' # TODO: Add to audio cog? ''' toggles = {} - with open(message.server.name + "_toggles.json", "r") as toggles_file: + with open(message.guild.name + "_toggles.json", "r") as toggles_file: toggles = json.load(toggles_file) if message.content.split()[1] == "on": toggles["youtubeinfo"] = True - with open(message.server.name + "_toggles.json", "w") as toggles_file: + with open(message.guild.name + "_toggles.json", "w") as toggles_file: json.dump(toggles, toggles_file, indent = 4) elif message.content.split()[1] == "off": toggles["youtubeinfo"] = False - with open(message.server.name + "_toggles.json", "w") as toggles_file: + with open(message.guild.name + "_toggles.json", "w") as toggles_file: json.dump(toggles, toggles_file, indent = 4) else: ''' diff --git a/Discord/cogs/rss.py b/Discord/cogs/rss.py index 1636e57cfa..cd05a4af91 100644 --- a/Discord/cogs/rss.py +++ b/Discord/cogs/rss.py @@ -34,43 +34,43 @@ def __unload(self): @commands.group(invoke_without_command = True) @checks.is_permitted() - async def rss(self): + async def rss(self, ctx): '''RSS''' pass - @rss.command(name = "add", aliases = ["addfeed", "feedadd"], pass_context = True) + @rss.command(name = "add", aliases = ["addfeed", "feedadd"]) @checks.is_permitted() async def rss_add(self, ctx, url : str): '''Add a feed to a channel''' - channel = discord.utils.find(lambda c: c["id"] == ctx.message.channel.id, self.feeds_info["channels"]) + channel = discord.utils.find(lambda c: c["id"] == ctx.channel.id, self.feeds_info["channels"]) if channel: channel["feeds"].append(url) else: - self.feeds_info["channels"].append({"name": ctx.message.channel.name, "id": ctx.message.channel.id, "feeds": [url]}) + self.feeds_info["channels"].append({"name": ctx.channel.name, "id": ctx.channel.id, "feeds": [url]}) with open("data/rss_feeds.json", 'w') as feeds_file: json.dump(self.feeds_info, feeds_file, indent = 4) - await self.bot.embed_reply("The feed, {}, has been added to this channel".format(url)) + await ctx.embed_reply("The feed, {}, has been added to this channel".format(url)) - @rss.command(name = "remove", aliases = ["delete", "removefeed", "feedremove", "deletefeed", "feeddelete"], pass_context = True) + @rss.command(name = "remove", aliases = ["delete", "removefeed", "feedremove", "deletefeed", "feeddelete"]) @checks.is_permitted() async def rss_remove(self, ctx, url : str): '''Remove a feed from a channel''' - channel = discord.utils.find(lambda c: c["id"] == ctx.message.channel.id, self.feeds_info["channels"]) + channel = discord.utils.find(lambda c: c["id"] == ctx.channel.id, self.feeds_info["channels"]) if not channel or url not in channel["feeds"]: - await self.bot.embed_reply(":no_entry: This channel isn't following that feed") + await ctx.embed_reply(":no_entry: This channel isn't following that feed") return channel["feeds"].remove(url) with open("data/rss_feeds.json", 'w') as feeds_file: json.dump(self.feeds_info, feeds_file, indent = 4) - await self.bot.embed_reply("The feed, {}, has been removed from this channel".format(url)) + await ctx.embed_reply("The feed, {}, has been removed from this channel".format(url)) - @rss.command(aliases = ["feed"], pass_context = True) + @rss.command(aliases = ["feed"]) @checks.not_forbidden() async def feeds(self, ctx): '''Show feeds being followed in this channel''' for channel in self.feeds_info["channels"]: - if ctx.message.channel.id == channel["id"]: - await self.bot.embed_reply("\n".join(channel["feeds"])) + if ctx.channel.id == channel["id"]: + await ctx.embed_reply("\n".join(channel["feeds"])) async def check_rss_feeds(self): await self.bot.wait_until_ready() diff --git a/Discord/cogs/search.py b/Discord/cogs/search.py index 5ff414d017..3ac3e4f5d3 100644 --- a/Discord/cogs/search.py +++ b/Discord/cogs/search.py @@ -34,31 +34,31 @@ def __unload(self): @commands.group(invoke_without_command = True) @checks.not_forbidden() - async def search(self): + async def search(self, ctx): ''' Search things All search subcommands are also commands ''' - await self.bot.embed_reply(":grey_question: Search what?") + await ctx.embed_reply(":grey_question: Search what?") @search.command() @checks.not_forbidden() - async def imgur(self, *, search : str): + async def imgur(self, ctx, *, search : str): '''Search images on imgur''' result = clients.imgur_client.gallery_search(search, sort = "top") if not result: - await self.bot.embed_reply(":no_entry: No results found") + await ctx.embed_reply(":no_entry: No results found") return result = result[0] if result.is_album: result = clients.imgur_client.get_album(result.id).images[0] - await self.bot.embed_reply(None, image_url = result["link"]) + await ctx.embed_reply(image_url = result["link"]) else: - await self.bot.embed_reply(None, image_url = result.link) + await ctx.embed_reply(image_url = result.link) @search.command(aliases = ["yt"]) @checks.not_forbidden() - async def youtube(self, *, search : str): + async def youtube(self, ctx, *, search : str): '''Find a Youtube video''' ydl = youtube_dl.YoutubeDL({"default_search": "auto", "noplaylist": True, "quiet": True}) func = functools.partial(ydl.extract_info, search, download = False) @@ -70,113 +70,113 @@ async def youtube(self, *, search : str): @youtube.error async def youtube_error(self, error, ctx): if isinstance(error, commands.errors.CommandInvokeError) and isinstance(error.original, youtube_dl.utils.DownloadError): - await self.bot.embed_reply(":no_entry: Error: {}".format(error.original)) + await ctx.embed_reply(":no_entry: Error: {}".format(error.original)) @commands.command() @checks.not_forbidden() - async def amazon(self, *search : str): + async def amazon(self, ctx, *search : str): '''Search with Amazon''' - await self.bot.embed_reply("[Amazon search for \"{}\"](https://smile.amazon.com/s/?field-keywords={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[Amazon search for \"{}\"](https://smile.amazon.com/s/?field-keywords={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def aol(self, *search : str): + async def aol(self, ctx, *search : str): '''Search with AOL''' - await self.bot.embed_reply("[AOL search for \"{}\"](https://search.aol.com/aol/search?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[AOL search for \"{}\"](https://search.aol.com/aol/search?q={})".format(' '.join(search), '+'.join(search))) @commands.command(name = "ask.com") @checks.not_forbidden() - async def ask_com(self, *search : str): + async def ask_com(self, ctx, *search : str): '''Search with Ask.com''' - await self.bot.embed_reply("[Ask.com search for \"{}\"](http://www.ask.com/web?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[Ask.com search for \"{}\"](http://www.ask.com/web?q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def baidu(self, *search : str): + async def baidu(self, ctx, *search : str): '''Search with Baidu''' - await self.bot.embed_reply("[Baidu search for \"{}\"](http://www.baidu.com/s?wd={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[Baidu search for \"{}\"](http://www.baidu.com/s?wd={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def bing(self, *search : str): + async def bing(self, ctx, *search : str): '''Search with Bing''' - await self.bot.embed_reply("[Bing search for \"{}\"](http://www.bing.com/search?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[Bing search for \"{}\"](http://www.bing.com/search?q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def duckduckgo(self, *search : str): + async def duckduckgo(self, ctx, *search : str): '''Search with DuckDuckGo''' - await self.bot.embed_reply("[DuckDuckGo search for \"{}\"](https://www.duckduckgo.com/?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[DuckDuckGo search for \"{}\"](https://www.duckduckgo.com/?q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def google(self, *, search : str): + async def google(self, ctx, *, search : str): '''Google search''' - await self.bot.embed_reply("[Google search for \"{}\"](https://www.google.com/search?q={})".format(search, search.replace(' ', '+'))) + await ctx.embed_reply("[Google search for \"{}\"](https://www.google.com/search?q={})".format(search, search.replace(' ', '+'))) @commands.command(aliases = ["im_feeling_lucky"]) @checks.not_forbidden() - async def imfeelinglucky(self, *search : str): + async def imfeelinglucky(self, ctx, *search : str): '''First Google result of a search''' - await self.bot.embed_reply("[First Google result of \"{}\"](https://www.google.com/search?btnI&q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[First Google result of \"{}\"](https://www.google.com/search?btnI&q={})".format(' '.join(search), '+'.join(search))) @commands.command(name = "lma.ctfy") @checks.not_forbidden() - async def lma_ctfy(self, *search : str): + async def lma_ctfy(self, ctx, *search : str): '''Let Me Ask.Com That For You''' - await self.bot.embed_reply("[LMA.CTFY: \"{}\"](http://lmgtfy.com/?s=k&q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMA.CTFY: \"{}\"](http://lmgtfy.com/?s=k&q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def lmaoltfy(self, *search : str): + async def lmaoltfy(self, ctx, *search : str): '''Let Me AOL That For You''' - await self.bot.embed_reply("[LMAOLTFY: \"{}\"](http://lmgtfy.com/?s=a&q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMAOLTFY: \"{}\"](http://lmgtfy.com/?s=a&q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def lmatfy(self, *search : str): + async def lmatfy(self, ctx, *search : str): '''Let Me Amazon That For You''' - await self.bot.embed_reply("[LMATFY: \"{}\"](http://lmatfy.co/?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMATFY: \"{}\"](http://lmatfy.co/?q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def lmbdtfy(self, *search : str): + async def lmbdtfy(self, ctx, *search : str): '''Let Me Baidu That For You''' - await self.bot.embed_reply("[LMBDTFY: \"{}\"](https://lmbtfy.cn/?{})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMBDTFY: \"{}\"](https://lmbtfy.cn/?{})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def lmbtfy(self, *search : str): + async def lmbtfy(self, ctx, *search : str): '''Let Me Bing That For You''' output = "[LMBTFY: \"{}\"](http://lmbtfy.com/?s=b&q={})\n".format(' '.join(search), '+'.join(search)) output += "[LMBTFY: \"{}\"](http://letmebingthatforyou.com/q={})".format(' '.join(search), '+'.join(search)) - await self.bot.embed_reply(output) + await ctx.embed_reply(output) @commands.command() @checks.not_forbidden() - async def lmdtfy(self, *search : str): + async def lmdtfy(self, ctx, *search : str): '''Let Me DuckDuckGo That For You''' - await self.bot.embed_reply("[LMDTFY: \"{}\"](http://lmgtfy.com/?s=d&q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMDTFY: \"{}\"](http://lmgtfy.com/?s=d&q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def lmgtfy(self, *search : str): + async def lmgtfy(self, ctx, *search : str): '''Let Me Google That For You''' - await self.bot.embed_reply("[LMGTFY: \"{}\"](http://lmgtfy.com/?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMGTFY: \"{}\"](http://lmgtfy.com/?q={})".format(' '.join(search), '+'.join(search))) @commands.command() @checks.not_forbidden() - async def lmytfy(self, *search : str): + async def lmytfy(self, ctx, *search : str): '''Let Me Yahoo That For You''' - await self.bot.embed_reply("[LMYTFY: \"{}\"](http://lmgtfy.com/?s=y&q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[LMYTFY: \"{}\"](http://lmgtfy.com/?s=y&q={})".format(' '.join(search), '+'.join(search))) @commands.group(description = "[UESP](http://uesp.net/wiki/Main_Page)", invoke_without_command = True) @checks.not_forbidden() - async def uesp(self, *, search : str): + async def uesp(self, ctx, *, search : str): '''Look something up on the Unofficial Elder Scrolls Pages''' - await self.process_uesp(search) + await self.process_uesp(ctx, search) - async def process_uesp(self, search, random = False, redirect = True): + async def process_uesp(self, ctx, search, random = False, redirect = True): # TODO: Add User-Agent if random: async with clients.aiohttp_session.get("http://en.uesp.net/w/api.php", params = {"action": "query", "list": "random", "rnnamespace": "0|" + '|'.join(str(i) for i in range(100, 152)) + "|200|201", "format": "json"}) as resp: @@ -188,19 +188,19 @@ async def process_uesp(self, search, random = False, redirect = True): try: search = data["query"].get("searchinfo", {}).get("suggestion") or data["query"]["search"][0]["title"] except IndexError: - await self.bot.embed_reply(":no_entry: Page not found") + await ctx.embed_reply(":no_entry: Page not found") return async with clients.aiohttp_session.get("http://en.uesp.net/w/api.php", params = {"action": "query", "redirects": "", "prop": "info|revisions|images", "titles": search, "inprop": "url", "rvprop": "content", "format": "json"}) as resp: data = await resp.json() if "pages" not in data["query"]: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return page_id = list(data["query"]["pages"].keys())[0] page = data["query"]["pages"][page_id] if "missing" in page: - await self.bot.embed_reply(":no_entry: Page not found") + await ctx.embed_reply(":no_entry: Page not found") elif "invalid" in page: - await self.bot.embed_reply(":no_entry: Error: {}".format(page["invalidreason"])) + await ctx.embed_reply(":no_entry: Error: {}".format(page["invalidreason"])) elif redirect and "redirects" in data["query"]: await self.process_wikipedia(data["query"]["redirects"][-1]["to"], redirect = False) # TODO: Handle section links/tofragments @@ -225,15 +225,15 @@ async def process_uesp(self, search, random = False, redirect = True): description = re.sub("\n+", '\n', description) thumbnail = data["query"]["pages"][page_id].get("thumbnail") image_url = thumbnail["source"].replace("{}px".format(thumbnail["width"]), "1200px") if thumbnail else None - await self.bot.embed_reply(description, title = page["title"], title_url = page["fullurl"], image_url = image_url) # canonicalurl? + await ctx.embed_reply(description, title = page["title"], title_url = page["fullurl"], image_url = image_url) # canonicalurl? @commands.group(aliases = ["wiki"], invoke_without_command = True) @checks.not_forbidden() - async def wikipedia(self, *, search : str): + async def wikipedia(self, ctx, *, search : str): '''Look something up on Wikipedia''' - await self.process_wikipedia(search) + await self.process_wikipedia(ctx, search) - async def process_wikipedia(self, search, random = False, redirect = True): + async def process_wikipedia(self, ctx, search, random = False, redirect = True): # TODO: Add User-Agent if random: async with clients.aiohttp_session.get("https://en.wikipedia.org/w/api.php", params = {"action": "query", "list": "random", "rnnamespace": 0, "format": "json"}) as resp: @@ -245,30 +245,30 @@ async def process_wikipedia(self, search, random = False, redirect = True): try: search = data["query"].get("searchinfo", {}).get("suggestion") or data["query"]["search"][0]["title"] except IndexError: - await self.bot.embed_reply(":no_entry: Page not found") + await ctx.embed_reply(":no_entry: Page not found") return async with clients.aiohttp_session.get("https://en.wikipedia.org/w/api.php", params = {"action": "query", "redirects": "", "prop": "info|extracts|pageimages", "titles": search, "inprop": "url", "exintro": "", "explaintext": "", "pithumbsize": 9000, "pilicense": "any", "format": "json"}) as resp: # exchars? data = await resp.json() if "pages" not in data["query"]: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return page_id = list(data["query"]["pages"].keys())[0] page = data["query"]["pages"][page_id] if "missing" in page: - await self.bot.embed_reply(":no_entry: Page not found") + await ctx.embed_reply(":no_entry: Page not found") elif "invalid" in page: - await self.bot.embed_reply(":no_entry: Error: {}".format(page["invalidreason"])) + await ctx.embed_reply(":no_entry: Error: {}".format(page["invalidreason"])) elif redirect and "redirects" in data["query"]: - await self.process_wikipedia(data["query"]["redirects"][-1]["to"], redirect = False) + await self.process_wikipedia(ctx, data["query"]["redirects"][-1]["to"], redirect = False) # TODO: Handle section links/tofragments else: description = page["extract"] if len(page["extract"]) <= 512 else page["extract"][:512] + "..." description = re.sub("\s+ \s+", ' ', description) thumbnail = data["query"]["pages"][page_id].get("thumbnail") image_url = thumbnail["source"].replace("{}px".format(thumbnail["width"]), "1200px") if thumbnail else None - await self.bot.embed_reply(description, title = page["title"], title_url = page["fullurl"], image_url = image_url) # canonicalurl? + await ctx.embed_reply(description, title = page["title"], title_url = page["fullurl"], image_url = image_url) # canonicalurl? - @commands.group(aliases = ["wa", "wolfram_alpha"], pass_context = True, invoke_without_command = True) + @commands.group(aliases = ["wa", "wolfram_alpha"], invoke_without_command = True) @checks.not_forbidden() async def wolframalpha(self, ctx, *, search : str): ''' @@ -277,7 +277,7 @@ async def wolframalpha(self, ctx, *, search : str): ''' await self._wolframalpha(ctx, search) - @wolframalpha.command(name = "location", pass_context = True) + @wolframalpha.command(name = "location") @checks.not_forbidden() async def wolframalpha_location(self, ctx, location: str, *, search : str): '''Input location''' @@ -291,7 +291,7 @@ async def _wolframalpha(self, ctx, search, location = clients.fake_location): didyoumean = result.didyoumeans["didyoumean"]["#text"] else: didyoumean = result.didyoumeans["didyoumean"][0]["#text"] - await self.bot.embed_reply("Using closest Wolfram|Alpha interpretation: `{}`".format(didyoumean)) + await ctx.embed_reply("Using closest Wolfram|Alpha interpretation: `{}`".format(didyoumean)) result = clients.wolfram_alpha_client.query(didyoumean, ip = clients.fake_ip, location = location) if hasattr(result, "pods"): for pod in result.pods: @@ -299,14 +299,14 @@ async def _wolframalpha(self, ctx, search, location = clients.fake_location): for subpod in pod.subpods: image = next(subpod.img) images.append(image.src) - if subpod.plaintext and subpod.plaintext.replace('\n', ' ') not in (image.title, image.alt, image.title.strip(' '), image.alt.strip(' ')) or not ctx.message.server.me.permissions_in(ctx.message.channel).embed_links: + if subpod.plaintext and subpod.plaintext.replace('\n', ' ') not in (image.title, image.alt, image.title.strip(' '), image.alt.strip(' ')) or not ctx.me.permissions_in(ctx.channel).embed_links: print("Wolfram Alpha:\n") print(image.title) print(image.alt) print(subpod.plaintext.replace('\n', ' ')) text_output.append("\n{}".format(subpod.plaintext)) if not text_output: - await self.bot.embed_reply(None, title = pod.title, image_url = images[0]) + await ctx.embed_reply(title = pod.title, image_url = images[0]) for image in images[1:]: await self.bot.embed_say(None, image_url = image) else: @@ -316,16 +316,16 @@ async def _wolframalpha(self, ctx, search, location = clients.fake_location): output += "".join(text_output) await self.bot.reply(output) if result.timedout: - await self.bot.embed_reply("Some results timed out: {}".format(result.timedout.replace(',', ", "))) + await ctx.embed_reply("Some results timed out: {}".format(result.timedout.replace(',', ", "))) elif result.timedout: - await self.bot.embed_reply("Standard computation time exceeded") + await ctx.embed_reply("Standard computation time exceeded") else: - await self.bot.embed_reply(":no_entry: No results found") + await ctx.embed_reply(":no_entry: No results found") # await self.bot.reply(next(result.results).text) @commands.command() @checks.not_forbidden() - async def yahoo(self, *search : str): + async def yahoo(self, ctx, *search : str): '''Search with Yahoo''' - await self.bot.embed_reply("[Yahoo search for \"{}\"](https://search.yahoo.com/search?q={})".format(' '.join(search), '+'.join(search))) + await ctx.embed_reply("[Yahoo search for \"{}\"](https://search.yahoo.com/search?q={})".format(' '.join(search), '+'.join(search))) diff --git a/Discord/cogs/tools.py b/Discord/cogs/tools.py index 4851256823..1cf95a0afa 100644 --- a/Discord/cogs/tools.py +++ b/Discord/cogs/tools.py @@ -50,16 +50,16 @@ def __init__(self, bot): @commands.command() @checks.not_forbidden() - async def add(self, *numbers : float): + async def add(self, ctx, *numbers : float): '''Add numbers together''' if not numbers: - await self.bot.embed_reply("Add what?") + await ctx.embed_reply("Add what?") return - await self.bot.embed_reply("{} = {:g}".format(" + ".join("{:g}".format(number) for number in numbers), sum(numbers))) + await ctx.embed_reply("{} = {:g}".format(" + ".join("{:g}".format(number) for number in numbers), sum(numbers))) @commands.command(aliases = ["calc", "calculator"]) @checks.not_forbidden() - async def calculate(self, *, equation : str): + async def calculate(self, ctx, *, equation : str): '''Calculator''' #_equation = re.sub("[^[0-9]+-/*^%\.]", "", equation).replace('^', "**") #words replacements = {"pi" : "math.pi", 'e' : "math.e", "sin" : "math.sin", "cos" : "math.cos", "tan" : "math.tan", '^' : "**"} @@ -73,58 +73,58 @@ async def calculate(self, *, equation : str): future = self.bot.loop.run_in_executor(None, async_result.get, 10.0) try: result = await asyncio.wait_for(future, 10.0, loop = self.bot.loop) - await self.bot.embed_reply("{} = {}".format(equation, result)) + await ctx.embed_reply("{} = {}".format(equation, result)) except discord.errors.HTTPException: - await self.bot.embed_reply(":no_entry: Output too long") + await ctx.embed_reply(":no_entry: Output too long") except SyntaxError: - await self.bot.embed_reply(":no_entry: Syntax error") + await ctx.embed_reply(":no_entry: Syntax error") except ZeroDivisionError: - await self.bot.embed_reply(":no_entry: Error: Division by zero") + await ctx.embed_reply(":no_entry: Error: Division by zero") except (concurrent.futures.TimeoutError, multiprocessing.context.TimeoutError): - await self.bot.embed_reply(":no_entry: Execution exceeded time limit") + await ctx.embed_reply(":no_entry: Execution exceeded time limit") @commands.command(aliases = ["differ", "derivative", "differentiation"]) @checks.not_forbidden() - async def differentiate(self, *, equation : str): + async def differentiate(self, ctx, *, equation : str): ''' Differentiate an equation with respect to x (dx) ''' x = sympy.symbols('x') try: - await self.bot.embed_reply("`{}`".format(sympy.diff(equation.strip('`'), x)), title = "Derivative of {}".format(equation)) + await ctx.embed_reply("`{}`".format(sympy.diff(equation.strip('`'), x)), title = "Derivative of {}".format(equation)) except Exception as e: - await self.bot.embed_reply(py_code_block.format("{}: {}".format(type(e).__name__, e)), title = "Error") + await ctx.embed_reply(py_code_block.format("{}: {}".format(type(e).__name__, e)), title = "Error") @commands.group(aliases = ["integral", "integration"], invoke_without_command = True) @checks.not_forbidden() - async def integrate(self, *, equation : str): + async def integrate(self, ctx, *, equation : str): ''' Integrate an equation with respect to x (dx) ''' x = sympy.symbols('x') try: - await self.bot.embed_reply("`{}`".format(sympy.integrate(equation.strip('`'), x)), title = "Integral of {}".format(equation)) + await ctx.embed_reply("`{}`".format(sympy.integrate(equation.strip('`'), x)), title = "Integral of {}".format(equation)) except Exception as e: - await self.bot.embed_reply(py_code_block.format("{}: {}".format(type(e).__name__, e)), title = "Error") + await ctx.embed_reply(py_code_block.format("{}: {}".format(type(e).__name__, e)), title = "Error") @integrate.command(name = "definite") @checks.not_forbidden() - async def integrate_definite(self, lower_limit : str, upper_limit : str, *, equation : str): + async def integrate_definite(self, ctx, lower_limit : str, upper_limit : str, *, equation : str): ''' Definite integral of an equation with respect to x (dx) ''' x = sympy.symbols('x') try: - await self.bot.embed_reply("`{}`".format(sympy.integrate(equation.strip('`'), (x, lower_limit, upper_limit))), title = "Definite Integral of {} from {} to {}".format(equation, lower_limit, upper_limit)) + await ctx.embed_reply("`{}`".format(sympy.integrate(equation.strip('`'), (x, lower_limit, upper_limit))), title = "Definite Integral of {} from {} to {}".format(equation, lower_limit, upper_limit)) except Exception as e: - await self.bot.embed_reply(py_code_block.format("{}: {}".format(type(e).__name__, e)), title = "Error") + await ctx.embed_reply(py_code_block.format("{}: {}".format(type(e).__name__, e)), title = "Error") @commands.command(aliases = ["charinfo", "char_info", "character_info"]) @checks.not_forbidden() - async def characterinfo(self, character : str): + async def characterinfo(self, ctx, character : str): '''Information about a unicode character''' character = character[0] # TODO: return info on each character in the input string; use paste tool api? @@ -134,50 +134,50 @@ async def characterinfo(self, character : str): name = "UNKNOWN" hex_char = hex(ord(character)) url = "http://www.fileformat.info/info/unicode/char/{}/index.htm".format(hex_char[2:]) - await self.bot.embed_reply("`{} ({})`".format(character, hex_char), title = name, title_url = url) + await ctx.embed_reply("`{} ({})`".format(character, hex_char), title = name, title_url = url) @commands.command(aliases = ["choice", "pick"]) @checks.not_forbidden() - async def choose(self, *choices : str): + async def choose(self, ctx, *choices : str): ''' Randomly chooses between multiple options choose <...> ''' if not choices: - await self.bot.embed_reply("Choose between what?") + await ctx.embed_reply("Choose between what?") return - await self.bot.embed_reply(random.choice(choices)) + await ctx.embed_reply(random.choice(choices)) @commands.command(aliases = ["flip"]) @checks.not_forbidden() - async def coin(self): + async def coin(self, ctx): '''Flip a coin''' - await self.bot.embed_reply(random.choice(["Heads!", "Tails!"])) + await ctx.embed_reply(random.choice(["Heads!", "Tails!"])) @commands.group(aliases = ["decrpyt"]) @checks.not_forbidden() - async def decode(self): + async def decode(self, ctx): '''Decodes coded messages''' return @decode.group(name = "caesar", aliases = ["rot"], invoke_without_command = True) - async def decode_caesar(self, key : int, *, message : str): + async def decode_caesar(self, ctx, key : int, *, message : str): ''' Decodes caesar codes key: 0 - 26 ''' if not 0 <= key <= 26: - await self.bot.embed_reply(":no_entry: Key must be in range 0 - 26") + await ctx.embed_reply(":no_entry: Key must be in range 0 - 26") return - await self.bot.embed_reply(ciphers.decode_caesar(message, key)) + await ctx.embed_reply(ciphers.decode_caesar(message, key)) @decode_caesar.command(name = "brute") - async def decode_caesar_brute(self, message : str): + async def decode_caesar_brute(self, ctx, message : str): '''Brute force decode caesar code''' - await self.bot.embed_reply(ciphers.brute_force_caesar(message)) + await ctx.embed_reply(ciphers.brute_force_caesar(message)) @decode.group(name = "gost", aliases = ["гост"]) - async def decode_gost(self): + async def decode_gost(self, ctx): ''' Russian Federation/Soviet Union GOST Межгосударственный стандарт @@ -187,7 +187,7 @@ async def decode_gost(self): ... @decode_gost.group(name = "28147-89", aliases = ["магма", "magma"]) - async def decode_gost_28147_89(self): + async def decode_gost_28147_89(self, ctx): ''' GOST 28147-89 block cipher Also known as Магма or Magma @@ -197,43 +197,43 @@ async def decode_gost_28147_89(self): ... @decode_gost_28147_89.command(name = "cbc") - async def ddecode_gost_28147_89_cbc(self, key : str, *, data : str): + async def ddecode_gost_28147_89_cbc(self, ctx, key : str, *, data : str): '''Magma with CBC mode of operation''' try: - await self.bot.embed_reply(pygost.gost28147.cbc_decrypt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) + await ctx.embed_reply(pygost.gost28147.cbc_decrypt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @decode_gost_28147_89.command(name = "cfb") - async def decode_gost_28147_89_cfb(self, key : str, *, data : str): + async def decode_gost_28147_89_cfb(self, ctx, key : str, *, data : str): '''Magma with CFB mode of operation''' try: - await self.bot.embed_reply(pygost.gost28147.cfb_decrypt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) + await ctx.embed_reply(pygost.gost28147.cfb_decrypt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @decode_gost_28147_89.command(name = "cnt") - async def decode_gost_28147_89_cnt(self, key : str, *, data : str): + async def decode_gost_28147_89_cnt(self, ctx, key : str, *, data : str): '''Magma with CNT mode of operation''' try: - await self.bot.embed_reply(pygost.gost28147.cnt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) + await ctx.embed_reply(pygost.gost28147.cnt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @decode_gost_28147_89.command(name = "ecb") - async def decode_gost_28147_89_ecb(self, key : str, *, data : str): + async def decode_gost_28147_89_ecb(self, ctx, key : str, *, data : str): ''' Magma with ECB mode of operation data block size must be 8 (64-bit) This means the data length must be a multiple of 8 ''' try: - await self.bot.embed_reply(pygost.gost28147.ecb_decrypt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) + await ctx.embed_reply(pygost.gost28147.ecb_decrypt(key.encode("utf-8"), bytearray.fromhex(data)).decode("utf-8")) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @decode_gost.command(name = "34.12-2015", aliases = ["кузнечик", "kuznyechik"]) - async def decode_gost_34_12_2015(self, key : str, *, data : str): + async def decode_gost_34_12_2015(self, ctx, key : str, *, data : str): ''' GOST 34.12-2015 128-bit block cipher Also known as Кузнечик or Kuznyechik @@ -241,19 +241,19 @@ async def decode_gost_34_12_2015(self, key : str, *, data : str): ''' # TODO: Add decode kuznyechik alias if len(key) < 32: - await self.bot.embed_reply(":no_entry: Error: key length must be at least 32") + await ctx.embed_reply(":no_entry: Error: key length must be at least 32") return if len(data) < 16: - await self.bot.embed_reply(":no_entry: Error: data length must be at least 16") + await ctx.embed_reply(":no_entry: Error: data length must be at least 16") return - await self.bot.embed_reply(pygost.gost3412.GOST3412Kuz(key.encode("utf-8")).decrypt(bytearray.fromhex(data)).decode("utf-8")) + await ctx.embed_reply(pygost.gost3412.GOST3412Kuz(key.encode("utf-8")).decrypt(bytearray.fromhex(data)).decode("utf-8")) @decode.command(name = "morse") - async def decode_morse(self, *, message : str): + async def decode_morse(self, ctx, *, message : str): '''Decodes morse code''' - await self.bot.embed_reply(ciphers.decode_morse(message)) + await ctx.embed_reply(ciphers.decode_morse(message)) - @decode.command(name = "qr", pass_context = True) + @decode.command(name = "qr") async def decode_qr(self, ctx, file_url : str = ""): ''' Decodes QR codes @@ -264,58 +264,58 @@ async def decode_qr(self, ctx, file_url : str = ""): if ctx.message.attachments and "filename" in ctx.message.attachments[0]: await self._decode_qr(ctx.message.attachments[0]["url"]) if not file_url and not (ctx.message.attachments and "filename" in ctx.message.attachments[0]): - await self.bot.embed_reply(":no_entry: Please input a file url or attach an image") + await ctx.embed_reply(":no_entry: Please input a file url or attach an image") async def _decode_qr(self, file_url): url = "https://api.qrserver.com/v1/read-qr-code/?fileurl={}".format(file_url) async with clients.aiohttp_session.get(url) as resp: if resp.status == 400: - await self.bot.embed_reply(":no_entry: Error") + await ctx.embed_reply(":no_entry: Error") return data = await resp.json() if data[0]["symbol"][0]["error"]: - await self.bot.embed_reply(":no_entry: Error: {}".format(data[0]["symbol"][0]["error"])) + await ctx.embed_reply(":no_entry: Error: {}".format(data[0]["symbol"][0]["error"])) return decoded = data[0]["symbol"][0]["data"].replace("QR-Code:", "") if len(decoded) > 1024: - await self.bot.embed_reply(decoded[:1021] + "...", footer_text = "Decoded message exceeded character limit") + await ctx.embed_reply(decoded[:1021] + "...", footer_text = "Decoded message exceeded character limit") return - await self.bot.embed_reply(decoded) + await ctx.embed_reply(decoded) @decode.command(name = "reverse") - async def decode_reverse(self, *, message : str): + async def decode_reverse(self, ctx, *, message : str): '''Reverses text''' - await self.bot.embed_reply(message[::-1]) + await ctx.embed_reply(message[::-1]) @commands.group(aliases = ["encrypt"]) @checks.not_forbidden() - async def encode(self): + async def encode(self, ctx): '''Encode messages''' return @encode.command(name = "adler32", aliases = ["adler-32"]) - async def encode_adler32(self, *, message : str): + async def encode_adler32(self, ctx, *, message : str): '''Compute Adler-32 checksum''' - await self.bot.embed_reply(zlib.adler32(message.encode("utf-8"))) + await ctx.embed_reply(zlib.adler32(message.encode("utf-8"))) @encode.command(name = "caesar", aliases = ["rot"]) - async def encode_caesar(self, key : int, *, message : str): + async def encode_caesar(self, ctx, key : int, *, message : str): ''' Encode a message using caesar code key: 0 - 26 ''' if not 0 <= key <= 26: - await self.bot.embed_reply(":no_entry: Key must be in range 0 - 26") + await ctx.embed_reply(":no_entry: Key must be in range 0 - 26") return - await self.bot.embed_reply(ciphers.encode_caesar(message, key)) + await ctx.embed_reply(ciphers.encode_caesar(message, key)) @encode.command(name = "crc32", aliases = ["crc-32"]) - async def encode_crc32(self, *, message : str): + async def encode_crc32(self, ctx, *, message : str): '''Compute CRC32 checksum''' - await self.bot.embed_reply(zlib.crc32(message.encode("utf-8"))) + await ctx.embed_reply(zlib.crc32(message.encode("utf-8"))) @encode.group(name = "gost", aliases = ["гост"]) - async def encode_gost(self): + async def encode_gost(self, ctx): ''' Russian Federation/Soviet Union GOST Межгосударственный стандарт @@ -325,7 +325,7 @@ async def encode_gost(self): ... @encode_gost.group(name = "28147-89", aliases = ["магма", "magma"]) - async def encode_gost_28147_89(self): + async def encode_gost_28147_89(self, ctx): ''' GOST 28147-89 block cipher Also known as Магма or Magma @@ -335,53 +335,53 @@ async def encode_gost_28147_89(self): ... @encode_gost_28147_89.command(name = "cbc") - async def encode_gost_28147_89_cbc(self, key : str, *, data : str): + async def encode_gost_28147_89_cbc(self, ctx, key : str, *, data : str): '''Magma with CBC mode of operation''' try: - await self.bot.embed_reply(pygost.gost28147.cbc_encrypt(key.encode("utf-8"), data.encode("utf-8")).hex()) + await ctx.embed_reply(pygost.gost28147.cbc_encrypt(key.encode("utf-8"), data.encode("utf-8")).hex()) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @encode_gost_28147_89.command(name = "cfb") - async def encode_gost_28147_89_cfb(self, key : str, *, data : str): + async def encode_gost_28147_89_cfb(self, ctx, key : str, *, data : str): '''Magma with CFB mode of operation''' try: - await self.bot.embed_reply(pygost.gost28147.cfb_encrypt(key.encode("utf-8"), data.encode("utf-8")).hex()) + await ctx.embed_reply(pygost.gost28147.cfb_encrypt(key.encode("utf-8"), data.encode("utf-8")).hex()) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @encode_gost_28147_89.command(name = "cnt") - async def encode_gost_28147_89_cnt(self, key : str, *, data : str): + async def encode_gost_28147_89_cnt(self, ctx, key : str, *, data : str): '''Magma with CNT mode of operation''' try: - await self.bot.embed_reply(pygost.gost28147.cnt(key.encode("utf-8"), data.encode("utf-8")).hex()) + await ctx.embed_reply(pygost.gost28147.cnt(key.encode("utf-8"), data.encode("utf-8")).hex()) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @encode_gost_28147_89.command(name = "ecb") - async def encode_gost_28147_89_ecb(self, key : str, *, data : str): + async def encode_gost_28147_89_ecb(self, ctx, key : str, *, data : str): ''' Magma with ECB mode of operation data block size must be 8 (64-bit) This means the data length must be a multiple of 8 ''' try: - await self.bot.embed_reply(pygost.gost28147.ecb_encrypt(key.encode("utf-8"), data.encode("utf-8")).hex()) + await ctx.embed_reply(pygost.gost28147.ecb_encrypt(key.encode("utf-8"), data.encode("utf-8")).hex()) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @encode_gost_28147_89.command(name = "mac") - async def encode_gost_28147_89_mac(self, key : str, *, data : str): + async def encode_gost_28147_89_mac(self, ctx, key : str, *, data : str): '''Magma with MAC mode of operation''' try: mac = pygost.gost28147_mac.MAC(key = key.encode("utf-8")) mac.update(data.encode("utf-8")) - await self.bot.embed_reply(mac.hexdigest()) + await ctx.embed_reply(mac.hexdigest()) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) @encode_gost.group(name = "34.11-2012", aliases = ["стрибог", "streebog"]) - async def encode_gost_34_11_2012(self): + async def encode_gost_34_11_2012(self, ctx): ''' GOST 34.11-2012 hash function Also known as Стрибог or Streebog @@ -390,28 +390,28 @@ async def encode_gost_34_11_2012(self): ... @encode_gost_34_11_2012.command(name = "256") - async def encode_gost_34_11_2012_256(self, *, data : str): + async def encode_gost_34_11_2012_256(self, ctx, *, data : str): ''' GOST 34.11-2012 256-bit hash function Also known as Streebog-256 ''' - await self.bot.embed_reply(pygost.gost34112012.GOST34112012(data.encode("utf-8"), digest_size = 32).hexdigest()) + await ctx.embed_reply(pygost.gost34112012.GOST34112012(data.encode("utf-8"), digest_size = 32).hexdigest()) @encode_gost_34_11_2012.command(name = "512") - async def encode_gost_34_11_2012_512(self, *, data : str): + async def encode_gost_34_11_2012_512(self, ctx, *, data : str): ''' GOST 34.11-2012 512-bit hash function Also known as Streebog-512 ''' - await self.bot.embed_reply(pygost.gost34112012.GOST34112012(data.encode("utf-8"), digest_size = 64).hexdigest()) + await ctx.embed_reply(pygost.gost34112012.GOST34112012(data.encode("utf-8"), digest_size = 64).hexdigest()) @encode_gost.command(name = "34.11-94") - async def encode_gost_34_11_94(self, *, data : str): + async def encode_gost_34_11_94(self, ctx, *, data : str): '''GOST 34.11-94 hash function''' - await self.bot.embed_reply(pygost.gost341194.GOST341194(data.encode("utf-8")).hexdigest()) + await ctx.embed_reply(pygost.gost341194.GOST341194(data.encode("utf-8")).hexdigest()) @encode_gost.command(name = "34.12-2015", aliases = ["кузнечик", "kuznyechik"]) - async def encode_gost_34_12_2015(self, key : str, *, data : str): + async def encode_gost_34_12_2015(self, ctx, key : str, *, data : str): ''' GOST 34.12-2015 128-bit block cipher Also known as Кузнечик or Kuznyechik @@ -419,81 +419,81 @@ async def encode_gost_34_12_2015(self, key : str, *, data : str): ''' # TODO: Add encode kuznyechik alias if len(key) < 32: - await self.bot.embed_reply(":no_entry: Error: key length must be at least 32") + await ctx.embed_reply(":no_entry: Error: key length must be at least 32") return if len(data) < 16: - await self.bot.embed_reply(":no_entry: Error: data length must be at least 16") + await ctx.embed_reply(":no_entry: Error: data length must be at least 16") return - await self.bot.embed_reply(pygost.gost3412.GOST3412Kuz(key.encode("utf-8")).encrypt(data.encode("utf-8")).hex()) + await ctx.embed_reply(pygost.gost3412.GOST3412Kuz(key.encode("utf-8")).encrypt(data.encode("utf-8")).hex()) @encode.command(name = "md4") - async def encode_md4(self, *, message : str): + async def encode_md4(self, ctx, *, message : str): '''Generate MD4 hash''' h = hashlib.new("md4") h.update(message.encode("utf-8")) - await self.bot.embed_reply(h.hexdigest()) + await ctx.embed_reply(h.hexdigest()) @encode.command(name = "md5") - async def encode_md5(self, *, message : str): + async def encode_md5(self, ctx, *, message : str): '''Generate MD5 hash''' - await self.bot.embed_reply(hashlib.md5(message.encode("utf-8")).hexdigest()) + await ctx.embed_reply(hashlib.md5(message.encode("utf-8")).hexdigest()) @encode.command(name = "morse") - async def encode_morse(self, *, message : str): + async def encode_morse(self, ctx, *, message : str): '''Encode a message in morse code''' - await self.bot.embed_reply(ciphers.encode_morse(message)) + await ctx.embed_reply(ciphers.encode_morse(message)) @encode.command(name = "qr") - async def encode_qr(self, *, message : str): + async def encode_qr(self, ctx, *, message : str): '''Encode a message in a QR code''' url = "https://api.qrserver.com/v1/create-qr-code/?data={}".format(message).replace(' ', '+') - await self.bot.embed_reply(None, image_url = url) + await ctx.embed_reply(image_url = url) @encode.command(name = "reverse") - async def encode_reverse(self, *, message : str): + async def encode_reverse(self, ctx, *, message : str): '''Reverses text''' - await self.bot.embed_reply(message[::-1]) + await ctx.embed_reply(message[::-1]) @encode.command(name = "ripemd160", aliases = ["ripemd-160"]) - async def encode_ripemd160(self, *, message : str): + async def encode_ripemd160(self, ctx, *, message : str): '''Generate RIPEMD-160 hash''' h = hashlib.new("ripemd160") h.update(message.encode("utf-8")) - await self.bot.embed_reply(h.hexdigest()) + await ctx.embed_reply(h.hexdigest()) @encode.command(name = "sha1", aliases = ["sha-1"]) - async def encode_sha1(self, *, message : str): + async def encode_sha1(self, ctx, *, message : str): '''Generate SHA-1 hash''' - await self.bot.embed_reply(hashlib.sha1(message.encode("utf-8")).hexdigest()) + await ctx.embed_reply(hashlib.sha1(message.encode("utf-8")).hexdigest()) @encode.command(name = "sha224", aliases = ["sha-224"]) - async def encode_sha224(self, *, message : str): + async def encode_sha224(self, ctx, *, message : str): '''Generate SHA-224 hash''' - await self.bot.embed_reply(hashlib.sha224(message.encode("utf-8")).hexdigest()) + await ctx.embed_reply(hashlib.sha224(message.encode("utf-8")).hexdigest()) @encode.command(name = "sha256", aliases = ["sha-256"]) - async def encode_sha256(self, *, message : str): + async def encode_sha256(self, ctx, *, message : str): '''Generate SHA-256 hash''' - await self.bot.embed_reply(hashlib.sha256(message.encode("utf-8")).hexdigest()) + await ctx.embed_reply(hashlib.sha256(message.encode("utf-8")).hexdigest()) @encode.command(name = "sha384", aliases = ["sha-384"]) - async def encode_sha384(self, *, message : str): + async def encode_sha384(self, ctx, *, message : str): '''Generate SHA-384 hash''' - await self.bot.embed_reply(hashlib.sha384(message.encode("utf-8")).hexdigest()) + await ctx.embed_reply(hashlib.sha384(message.encode("utf-8")).hexdigest()) @encode.command(name = "sha512", aliases = ["sha-512"]) - async def encode_sha512(self, *, message : str): + async def encode_sha512(self, ctx, *, message : str): '''Generate SHA-512 hash''' - await self.bot.embed_reply(hashlib.sha512(message.encode("utf-8")).hexdigest()) + await ctx.embed_reply(hashlib.sha512(message.encode("utf-8")).hexdigest()) @encode.command(name = "whirlpool") - async def encode_whirlpool(self, *, message : str): + async def encode_whirlpool(self, ctx, *, message : str): '''Generate Whirlpool hash''' h = hashlib.new("whirlpool") h.update(message.encode("utf-8")) - await self.bot.embed_reply(h.hexdigest()) + await ctx.embed_reply(h.hexdigest()) - @commands.group(aliases = ["plot"], pass_context = True, invoke_without_command = True) + @commands.group(aliases = ["plot"], invoke_without_command = True) @checks.not_forbidden() async def graph(self, ctx, lower_limit : int, upper_limit : int, *, equation : str): '''WIP''' @@ -501,7 +501,7 @@ async def graph(self, ctx, lower_limit : int, upper_limit : int, *, equation : s try: equation = self.string_to_equation(equation) except SyntaxError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) return x = numpy.linspace(lower_limit, upper_limit, 250) try: @@ -512,11 +512,11 @@ async def graph(self, ctx, lower_limit : int, upper_limit : int, *, equation : s try: matplotlib.pyplot.plot(x, y) except ValueError as e: - await self.bot.embed_reply(":no_entry: Error: {}".format(e)) + await ctx.embed_reply(":no_entry: Error: {}".format(e)) return matplotlib.pyplot.savefig(filename) matplotlib.pyplot.clf() - await self.bot.send_file(destination = ctx.message.channel, fp = filename, content = ctx.message.author.display_name + ':') + await self.bot.send_file(destination = ctx.channel, fp = filename, content = ctx.author.display_name + ':') # TODO: Send as embed? def string_to_equation(self, string): @@ -529,81 +529,81 @@ def string_to_equation(self, string): string = string.replace(old, new) return string - @graph.command(name = "alternative", aliases = ["alt", "complex"], pass_context = True) + @graph.command(name = "alternative", aliases = ["alt", "complex"]) @checks.is_owner() async def graph_alternative(self, ctx, *, data : str): '''WIP''' filename = "data/temp/graph_alternative.png" seaborn.jointplot(**eval(data)).savefig(name) - await self.bot.send_file(destination = ctx.message.channel, fp = filename, content = ctx.message.author.display_name + ':') + await self.bot.send_file(destination = ctx.channel, fp = filename, content = ctx.author.display_name + ':') - @commands.group(pass_context = True, aliases = ["trigger", "note", "tags", "triggers", "notes"], invoke_without_command = True) + @commands.group(aliases = ["trigger", "note", "tags", "triggers", "notes"], invoke_without_command = True) @checks.not_forbidden() async def tag(self, ctx, tag : str = ""): '''Tags/notes that you can trigger later''' if not tag: - await self.bot.embed_reply("Add a tag with `{0}tag add [tag] [content]`\nUse `{0}tag [tag]` to trigger the tag you added\n`{0}tag edit [tag] [content]` to edit it and `{0}tag delete [tag]` to delete it".format(ctx.prefix)) + await ctx.embed_reply("Add a tag with `{0}tag add [tag] [content]`\nUse `{0}tag [tag]` to trigger the tag you added\n`{0}tag edit [tag] [content]` to edit it and `{0}tag delete [tag]` to delete it".format(ctx.prefix)) return - if tag in self.tags_data.get(ctx.message.author.id, {}).get("tags", []): - await self.bot.reply(self.tags_data[ctx.message.author.id]["tags"][tag]) + if tag in self.tags_data.get(ctx.author.id, {}).get("tags", []): + await self.bot.reply(self.tags_data[ctx.author.id]["tags"][tag]) elif tag in self.tags_data["global"]: await self.bot.reply(self.tags_data["global"][tag]["response"]) self.tags_data["global"][tag]["usage_counter"] += 1 with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) else: - close_matches = difflib.get_close_matches(tag, list(self.tags_data.get(ctx.message.author.id, {}).get("tags", {}).keys()) + list(self.tags_data["global"].keys())) + close_matches = difflib.get_close_matches(tag, list(self.tags_data.get(ctx.author.id, {}).get("tags", {}).keys()) + list(self.tags_data["global"].keys())) close_matches = "\nDid you mean:\n{}".format('\n'.join(close_matches)) if close_matches else "" - await self.bot.embed_reply("Tag not found{}".format(close_matches)) + await ctx.embed_reply("Tag not found{}".format(close_matches)) - @tag.command(name = "list", aliases = ["all", "mine"], pass_context = True) + @tag.command(name = "list", aliases = ["all", "mine"]) async def tag_list(self, ctx): '''List your tags''' if (await self.check_no_tags(ctx)): return tags_paginator = paginator.CustomPaginator(seperator = ", ") - for tag in sorted(self.tags_data[ctx.message.author.id]["tags"].keys()): + for tag in sorted(self.tags_data[ctx.author.id]["tags"].keys()): tags_paginator.add_section(tag) # DM for page in tags_paginator.pages: - await self.bot.embed_reply(page, title = "Your tags:") + await ctx.embed_reply(page, title = "Your tags:") - @tag.command(name = "add", aliases = ["make", "new", "create"], pass_context = True) + @tag.command(name = "add", aliases = ["make", "new", "create"]) async def tag_add(self, ctx, tag : str, *, content : str): '''Add a tag''' - if not ctx.message.author.id in self.tags_data: - self.tags_data[ctx.message.author.id] = {"name" : ctx.message.author.name, "tags" : {}} - tags = self.tags_data[ctx.message.author.id]["tags"] + if not ctx.author.id in self.tags_data: + self.tags_data[ctx.author.id] = {"name" : ctx.author.name, "tags" : {}} + tags = self.tags_data[ctx.author.id]["tags"] if tag in tags: - await self.bot.embed_reply("You already have that tag\nUse `{}tag edit ` to edit it".format(ctx.prefix)) + await ctx.embed_reply("You already have that tag\nUse `{}tag edit ` to edit it".format(ctx.prefix)) return tags[tag] = utilities.clean_content(content) with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":thumbsup::skin-tone-2: Your tag has been added") + await ctx.embed_reply(":thumbsup::skin-tone-2: Your tag has been added") - @tag.command(name = "edit", aliases = ["update"], pass_context = True) + @tag.command(name = "edit", aliases = ["update"]) async def tag_edit(self, ctx, tag : str, *, content : str): '''Edit one of your tags''' if (await self.check_no_tags(ctx)): return if (await self.check_no_tag(ctx, tag)): return - self.tags_data[ctx.message.author.id]["tags"][tag] = utilities.clean_content(content) + self.tags_data[ctx.author.id]["tags"][tag] = utilities.clean_content(content) with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":ok_hand::skin-tone-2: Your tag has been edited") + await ctx.embed_reply(":ok_hand::skin-tone-2: Your tag has been edited") - @tag.command(name = "delete", aliases = ["remove", "destroy"], pass_context = True) + @tag.command(name = "delete", aliases = ["remove", "destroy"]) async def tag_delete(self, ctx, tag : str): '''Delete one of your tags''' if (await self.check_no_tags(ctx)): return if (await self.check_no_tag(ctx, tag)): return try: - del self.tags_data[ctx.message.author.id]["tags"][tag] + del self.tags_data[ctx.author.id]["tags"][tag] except KeyError: - await self.bot.embed_reply(":no_entry: Tag not found") + await ctx.embed_reply(":no_entry: Tag not found") return with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":ok_hand::skin-tone-2: Your tag has been deleted") + await ctx.embed_reply(":ok_hand::skin-tone-2: Your tag has been deleted") @tag.command(name = "expunge", pass_context = True) @checks.is_owner() @@ -612,111 +612,111 @@ async def tag_expunge(self, ctx, owner : discord.Member, tag : str): try: del self.tags_data[owner.id]["tags"][tag] except KeyError: - await self.bot.embed_reply(":no_entry: Tag not found") + await ctx.embed_reply(":no_entry: Tag not found") return with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":ok_hand::skin-tone-2: {}'s tag has been deleted".format(owner.mention)) + await ctx.embed_reply(":ok_hand::skin-tone-2: {}'s tag has been deleted".format(owner.mention)) - @tag.command(name = "search", aliases = ["contains", "find"], pass_context = True) + @tag.command(name = "search", aliases = ["contains", "find"]) async def tag_search(self, ctx, *, search : str): '''Search your tags''' if (await self.check_no_tags(ctx)): return - tags = self.tags_data[ctx.message.author.id]["tags"] + tags = self.tags_data[ctx.author.id]["tags"] results = [t for t in tags.keys() if search in t] if results: - await self.bot.embed_reply("{} tags found: {}".format(len(results), ", ".join(results))) + await ctx.embed_reply("{} tags found: {}".format(len(results), ", ".join(results))) return close_matches = difflib.get_close_matches(search, tags.keys()) close_matches = "\nDid you mean:\n{}".format('\n'.join(close_matches)) if close_matches else "" - await self.bot.embed_reply("No tags found{}".format(close_matches)) + await ctx.embed_reply("No tags found{}".format(close_matches)) - @tag.command(name = "globalize", aliases = ["globalise"], pass_context = True) + @tag.command(name = "globalize", aliases = ["globalise"]) async def tag_globalize(self, ctx, tag : str): '''Globalize a tag''' if (await self.check_no_tags(ctx)): return if (await self.check_no_tag(ctx, tag)): return if tag in self.tags_data["global"]: - await self.bot.embed_reply("That global tag already exists\nIf you own it, use `{}tag global edit ` to edit it".format(ctx.prefix)) + await ctx.embed_reply("That global tag already exists\nIf you own it, use `{}tag global edit ` to edit it".format(ctx.prefix)) return - self.tags_data["global"][tag] = {"response": self.tags_data[ctx.message.author.id]["tags"][tag], "owner": ctx.message.author.id, "created_at": time.time(), "usage_counter": 0} - del self.tags_data[ctx.message.author.id]["tags"][tag] + self.tags_data["global"][tag] = {"response": self.tags_data[ctx.author.id]["tags"][tag], "owner": ctx.author.id, "created_at": time.time(), "usage_counter": 0} + del self.tags_data[ctx.author.id]["tags"][tag] with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":thumbsup::skin-tone-2: Your tag has been {}d".format(ctx.invoked_with)) + await ctx.embed_reply(":thumbsup::skin-tone-2: Your tag has been {}d".format(ctx.invoked_with)) # TODO: rename, aliases @tag.group(name = "global", invoke_without_command = True) - async def tag_global(self): + async def tag_global(self, ctx): '''Global tags''' ... - @tag_global.command(name = "add", aliases = ["make", "new", "create"], pass_context = True) + @tag_global.command(name = "add", aliases = ["make", "new", "create"]) async def tag_global_add(self, ctx, tag : str, *, content : str): '''Add a global tag''' tags = self.tags_data["global"] if tag in tags: - await self.bot.embed_reply("That global tag already exists\nIf you own it, use `{}tag global edit ` to edit it".format(ctx.prefix)) + await ctx.embed_reply("That global tag already exists\nIf you own it, use `{}tag global edit ` to edit it".format(ctx.prefix)) return - tags[tag] = {"response": utilities.clean_content(content), "owner": ctx.message.author.id, "created_at": time.time(), "usage_counter": 0} + tags[tag] = {"response": utilities.clean_content(content), "owner": ctx.author.id, "created_at": time.time(), "usage_counter": 0} with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":thumbsup::skin-tone-2: Your tag has been added") + await ctx.embed_reply(":thumbsup::skin-tone-2: Your tag has been added") - @tag_global.command(name = "edit", aliases = ["update"], pass_context = True) + @tag_global.command(name = "edit", aliases = ["update"]) async def tag_global_edit(self, ctx, tag : str, *, content : str): '''Edit one of your global tags''' if tag not in self.tags_data["global"]: - await self.bot.embed_reply(":no_entry: That global tag doesn't exist") + await ctx.embed_reply(":no_entry: That global tag doesn't exist") return - elif self.tags_data["global"][tag]["owner"] != ctx.message.author.id: - await self.bot.embed_reply(":no_entry: You don't own that global tag") + elif self.tags_data["global"][tag]["owner"] != ctx.author.id: + await ctx.embed_reply(":no_entry: You don't own that global tag") return self.tags_data["global"][tag]["response"] = utilities.clean_content(content) with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":ok_hand::skin-tone-2: Your tag has been edited") + await ctx.embed_reply(":ok_hand::skin-tone-2: Your tag has been edited") - @tag_global.command(name = "delete", aliases = ["remove", "destroy"], pass_context = True) + @tag_global.command(name = "delete", aliases = ["remove", "destroy"]) async def tag_global_delete(self, ctx, tag : str): '''Delete one of your global tags''' if tag not in self.tags_data["global"]: - await self.bot.embed_reply(":no_entry: That global tag doesn't exist") + await ctx.embed_reply(":no_entry: That global tag doesn't exist") return - elif self.tags_data["global"][tag]["owner"] != ctx.message.author.id: - await self.bot.embed_reply(":no_entry: You don't own that global tag") + elif self.tags_data["global"][tag]["owner"] != ctx.author.id: + await ctx.embed_reply(":no_entry: You don't own that global tag") return del self.tags_data["global"][tag] with open("data/tags.json", 'w') as tags_file: json.dump(self.tags_data, tags_file, indent = 4) - await self.bot.embed_reply(":ok_hand::skin-tone-2: Your tag has been deleted") + await ctx.embed_reply(":ok_hand::skin-tone-2: Your tag has been deleted") # TODO: global search, list? async def check_no_tags(self, ctx): - if not ctx.message.author.id in self.tags_data: - await self.bot.embed_reply("You don't have any tags :slight_frown:\nAdd one with `{}{} add `".format(ctx.prefix, ctx.invoked_with)) - return not ctx.message.author.id in self.tags_data + if not ctx.author.id in self.tags_data: + await ctx.embed_reply("You don't have any tags :slight_frown:\nAdd one with `{}{} add `".format(ctx.prefix, ctx.invoked_with)) + return not ctx.author.id in self.tags_data async def check_no_tag(self, ctx, tag): - tags = self.tags_data[ctx.message.author.id]["tags"] + tags = self.tags_data[ctx.author.id]["tags"] if not tag in tags: close_matches = difflib.get_close_matches(tag, tags.keys()) close_matches = "\nDid you mean:\n{}".format('\n'.join(close_matches)) if close_matches else "" - await self.bot.embed_reply("You don't have that tag{}".format(close_matches)) + await ctx.embed_reply("You don't have that tag{}".format(close_matches)) return not tag in tags - @commands.command(pass_context = True) + @commands.command() @checks.not_forbidden() async def timer(self, ctx, seconds : int): '''Timer''' # TODO: other units, persistence through restarts - await self.bot.embed_reply("I'll remind you in {} seconds".format(seconds)) + await ctx.embed_reply("I'll remind you in {} seconds".format(seconds)) await asyncio.sleep(seconds) - await self.bot.say("{}: {} seconds have passed".format(ctx.message.author.mention, seconds)) + await self.bot.say("{}: {} seconds have passed".format(ctx.author.mention, seconds)) - @commands.command(pass_context = True, hidden = True) + @commands.command(hidden = True) @checks.not_forbidden() async def webmtogif(self, ctx, url : str): ''' @@ -729,5 +729,5 @@ async def webmtogif(self, ctx, url : str): clip = moviepy.editor.VideoFileClip("data/temp/webmtogif.webm") clip.write_gif("data/temp/webmtogif.gif", fps = 1, program = "ffmpeg") # clip.write_gif("data/temp/webmtogif.gif", fps=15, program="ImageMagick", opt="optimizeplus") - await self.bot.send_file(ctx.message.channel, "data/temp/webmtogif.gif") + await self.bot.send_file(ctx.channel, "data/temp/webmtogif.gif") diff --git a/Discord/cogs/twitch.py b/Discord/cogs/twitch.py index 4314032859..610ab3abaa 100644 --- a/Discord/cogs/twitch.py +++ b/Discord/cogs/twitch.py @@ -36,159 +36,159 @@ def __unload(self): @commands.group(invoke_without_command = True) @checks.is_permitted() - async def twitch(self): + async def twitch(self, ctx): '''Twitch''' pass @twitch.group(name = "add", invoke_without_command = True) @checks.is_permitted() - async def twitch_add(self): + async def twitch_add(self, ctx): '''Add Twitch games, keywords, or channels to follow''' pass - @twitch_add.command(name = "filter", pass_context = True) + @twitch_add.command(name = "filter") @checks.is_permitted() async def twitch_add_filter(self, ctx, *, string : str): '''Add string to filter Twitch stream titles by''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) # TODO: Check if already filtered if channel: channel["filters"].append(string) else: - self.streams_info["channels"][ctx.message.channel.id] = {"name": ctx.message.channel.name, "filters": [string], "games": [], "keywords": [], "streams": []} + self.streams_info["channels"][ctx.channel.id] = {"name": ctx.channel.name, "filters": [string], "games": [], "keywords": [], "streams": []} with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Added the filter, `{}`, to this text channel\n" + await ctx.embed_reply("Added the filter, `{}`, to this text channel\n" "I will now filter all streams for this string in the title".format(string)) - @twitch_add.command(name = "game", pass_context = True) + @twitch_add.command(name = "game") @checks.is_permitted() async def twitch_add_game(self, ctx, *, game : str): '''Add a Twitch game to follow''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) # TODO: Add documentation on 100 limit # TODO: Check if already following if channel: channel["games"].append(game) else: - self.streams_info["channels"][ctx.message.channel.id] = {"name": ctx.message.channel.name, "filters": [], "games": [game], "keywords": [], "streams": []} + self.streams_info["channels"][ctx.channel.id] = {"name": ctx.channel.name, "filters": [], "games": [game], "keywords": [], "streams": []} with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Added the game, [`{0}`](https://www.twitch.tv/directory/game/{0}), to this text channel\n" + await ctx.embed_reply("Added the game, [`{0}`](https://www.twitch.tv/directory/game/{0}), to this text channel\n" "I will now announce here when Twitch streams playing this game go live".format(game)) - @twitch_add.command(name = "keyword", aliases = ["query", "search"], pass_context = True) + @twitch_add.command(name = "keyword", aliases = ["query", "search"]) @checks.is_permitted() async def twitch_add_keyword(self, ctx, *, keyword : str): '''Add a Twitch keyword(s) search to follow''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) # TODO: Add documentation on 100 limit # TODO: Check if already following if channel: channel["keywords"].append(keyword) else: - self.streams_info["channels"][ctx.message.channel.id] = {"name": ctx.message.channel.name, "filters": [], "games": [], "keywords": [keyword], "streams": []} + self.streams_info["channels"][ctx.channel.id] = {"name": ctx.channel.name, "filters": [], "games": [], "keywords": [keyword], "streams": []} with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Added the keyword search, `{}`, to this text channel\n" + await ctx.embed_reply("Added the keyword search, `{}`, to this text channel\n" "I will now announce here when Twitch streams with this keyword go live".format(keyword)) - @twitch_add.command(name = "channel", aliases = ["stream"], pass_context = True) + @twitch_add.command(name = "channel", aliases = ["stream"]) @checks.is_permitted() async def twitch_add_channel(self, ctx, username : str): '''Add a Twitch channel to follow''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) # TODO: Check if already following if channel: channel["streams"].append(username) else: - self.streams_info["channels"][ctx.message.channel.id] = {"name": ctx.message.channel.name, "filters": [], "games": [], "keywords": [], "streams": [username]} + self.streams_info["channels"][ctx.channel.id] = {"name": ctx.channel.name, "filters": [], "games": [], "keywords": [], "streams": [username]} with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Added the Twitch channel, [`{0}`](https://www.twitch.tv/{0}), to this text channel\n" + await ctx.embed_reply("Added the Twitch channel, [`{0}`](https://www.twitch.tv/{0}), to this text channel\n" "I will now announce here when this Twitch channel goes live".format(username)) @twitch.group(name = "remove", aliases = ["delete"], invoke_without_command = True) @checks.is_permitted() - async def twitch_remove(self): + async def twitch_remove(self, ctx): '''Remove Twitch games, keywords, or channels being followed''' pass - @twitch_remove.command(name = "filter", pass_context = True) + @twitch_remove.command(name = "filter") @checks.is_permitted() async def twitch_remove_filter(self, ctx, *, string : str): '''Remove a string Twitch stream titles are being filtered by''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) if not channel or filter not in channel["filters"]: - await self.bot.embed_reply(":no_entry: This text channel doesn't have that filter") + await ctx.embed_reply(":no_entry: This text channel doesn't have that filter") return channel["filters"].remove(filter) with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Removed the filter, `{}`, from this text channel".format(string)) + await ctx.embed_reply("Removed the filter, `{}`, from this text channel".format(string)) - @twitch_remove.command(name = "game", pass_context = True) + @twitch_remove.command(name = "game") @checks.is_permitted() async def twitch_remove_game(self, ctx, *, game : str): '''Remove a Twitch game being followed''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) if not channel or game not in channel["games"]: - await self.bot.embed_reply(":no_entry: This text channel isn't following that game") + await ctx.embed_reply(":no_entry: This text channel isn't following that game") return channel["games"].remove(game) with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Removed the game, [`{0}`](https://www.twitch.tv/directory/game/{0}), from this text channel".format(game)) + await ctx.embed_reply("Removed the game, [`{0}`](https://www.twitch.tv/directory/game/{0}), from this text channel".format(game)) - @twitch_remove.command(name = "keyword", aliases = ["query", "search"], pass_context = True) + @twitch_remove.command(name = "keyword", aliases = ["query", "search"]) @checks.is_permitted() async def twitch_remove_keyword(self, ctx, *, keyword : str): '''Remove a Twitch keyword(s) search being followed''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) if not channel or keyword not in channel["keywords"]: - await self.bot.embed_reply(":no_entry: This text channel isn't following that keyword") + await ctx.embed_reply(":no_entry: This text channel isn't following that keyword") return channel["keywords"].remove(keyword) with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Removed the Twitch keyword search, `{}`, from this text channel".format(keyword)) + await ctx.embed_reply("Removed the Twitch keyword search, `{}`, from this text channel".format(keyword)) - @twitch_remove.command(name = "channel", aliases = ["stream"], pass_context = True) + @twitch_remove.command(name = "channel", aliases = ["stream"]) @checks.is_permitted() async def twitch_remove_channel(self, ctx, username : str): '''Remove a Twitch channel being followed''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) if not channel or username not in channel["streams"]: - await self.bot.embed_reply(":no_entry: This text channel isn't following that Twitch channel") + await ctx.embed_reply(":no_entry: This text channel isn't following that Twitch channel") return channel["streams"].remove(username) with open("data/twitch_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Removed the Twitch channel, [`{0}`](https://www.twitch.tv/{0}), from this text channel".format(username)) + await ctx.embed_reply("Removed the Twitch channel, [`{0}`](https://www.twitch.tv/{0}), from this text channel".format(username)) - @twitch.command(name = "filters", pass_context = True) + @twitch.command(name = "filters") @checks.not_forbidden() async def twitch_filters(self, ctx): '''Show strings Twitch stream titles are being filtered by in this text channel''' - await self.bot.embed_reply('\n'.join(self.streams_info["channels"].get(ctx.message.channel.id, {}).get("filters", []))) + await ctx.embed_reply('\n'.join(self.streams_info["channels"].get(ctx.channel.id, {}).get("filters", []))) - @twitch.command(name = "games", pass_context = True) + @twitch.command(name = "games") @checks.not_forbidden() async def twitch_games(self, ctx): '''Show Twitch games being followed in this text channel''' - await self.bot.embed_reply('\n'.join(self.streams_info["channels"].get(ctx.message.channel.id, {}).get("games", []))) + await ctx.embed_reply('\n'.join(self.streams_info["channels"].get(ctx.channel.id, {}).get("games", []))) - @twitch.command(name = "keywords", aliases = ["queries", "searches"], pass_context = True) + @twitch.command(name = "keywords", aliases = ["queries", "searches"]) @checks.not_forbidden() async def twitch_keywords(self, ctx): '''Show Twitch keywords being followed in this text channel''' - await self.bot.embed_reply('\n'.join(self.streams_info["channels"].get(ctx.message.channel.id, {}).get("keywords", []))) + await ctx.embed_reply('\n'.join(self.streams_info["channels"].get(ctx.channel.id, {}).get("keywords", []))) - @twitch.command(name = "channels", aliases = ["streams"], pass_context = True) + @twitch.command(name = "channels", aliases = ["streams"]) @checks.not_forbidden() async def twitch_channels(self, ctx): '''Show Twitch channels being followed in this text channel''' - await self.bot.embed_reply(clients.code_block.format('\n'.join(self.streams_info["channels"].get(ctx.message.channel.id, {}).get("streams", [])))) + await ctx.embed_reply(clients.code_block.format('\n'.join(self.streams_info["channels"].get(ctx.channel.id, {}).get("streams", [])))) async def check_twitch_streams(self): await self.bot.wait_until_ready() diff --git a/Discord/cogs/twitter.py b/Discord/cogs/twitter.py index a4918061d9..381390910c 100644 --- a/Discord/cogs/twitter.py +++ b/Discord/cogs/twitter.py @@ -87,48 +87,49 @@ def __unload(self): @commands.group(invoke_without_command = True) @checks.is_permitted() - async def twitter(self): + async def twitter(self, ctx): '''Twitter''' pass - @twitter.command(name = "status", pass_context = True) + @twitter.command(name = "status") @checks.not_forbidden() async def twitter_status(self, ctx, handle : str): '''Get twitter status''' tweet = clients.twitter_api.user_timeline(handle, count = 1)[0] embed = discord.Embed(title = '@' + tweet.user.screen_name, url = "https://twitter.com/{}/status/{}".format(tweet.user.screen_name, tweet.id), description = tweet.text, timestamp = tweet.created_at, color = 0x00ACED) - avatar = ctx.message.author.default_avatar_url if not ctx.message.author.avatar else ctx.message.author.avatar_url - embed.set_author(name = ctx.message.author.display_name, icon_url = avatar) + avatar = ctx.author.avatar_url or ctx.author.default_avatar_url + embed.set_author(name = ctx.author.display_name, icon_url = avatar) embed.set_footer(text = tweet.user.name, icon_url = tweet.user.profile_image_url) await self.bot.say(embed = embed) - @twitter.command(name = "add", aliases = ["addhandle", "handleadd"], pass_context = True) + @twitter.command(name = "add", aliases = ["addhandle", "handleadd"]) @checks.is_permitted() async def twitter_add(self, ctx, handle : str): ''' Add a Twitter handle to a text channel A delay of up to 2 min. is possible due to Twitter rate limits ''' - if handle in self.feeds_info["channels"].get(ctx.message.channel.id, {}).get("handles", []): - await self.bot.embed_reply(":no_entry: This text channel is already following that Twitter handle") + if handle in self.feeds_info["channels"].get(ctx.channel.id, {}).get("handles", []): + await ctx.embed_reply(":no_entry: This text channel is already following that Twitter handle") return - message, embed = await self.bot.embed_reply(":hourglass: Please wait") + message = await ctx.embed_reply(":hourglass: Please wait") + embed = message.embeds[0] try: - await self.stream_listener.add_feed(ctx.message.channel, handle) + await self.stream_listener.add_feed(ctx.channel, handle) except tweepy.error.TweepError as e: embed.description = ":no_entry: Error: {}".format(e) await self.bot.edit_message(message, embed = embed) return - if ctx.message.channel.id in self.feeds_info["channels"]: - self.feeds_info["channels"][ctx.message.channel.id]["handles"].append(handle) + if ctx.channel.id in self.feeds_info["channels"]: + self.feeds_info["channels"][ctx.channel.id]["handles"].append(handle) else: - self.feeds_info["channels"][ctx.message.channel.id] = {"name" : ctx.message.channel.name, "handles" : [handle]} + self.feeds_info["channels"][ctx.channel.id] = {"name" : ctx.channel.name, "handles" : [handle]} with open("data/twitter_feeds.json", 'w') as feeds_file: json.dump(self.feeds_info, feeds_file, indent = 4) embed.description = "Added the Twitter handle, [`{0}`](https://twitter.com/{0}), to this text channel".format(handle) await self.bot.edit_message(message, embed = embed) - @twitter.command(name = "remove", aliases = ["delete", "removehandle", "handleremove", "deletehandle", "handledelete"], pass_context = True) + @twitter.command(name = "remove", aliases = ["delete", "removehandle", "handleremove", "deletehandle", "handledelete"]) @checks.is_permitted() async def twitter_remove(self, ctx, handle : str): ''' @@ -136,22 +137,23 @@ async def twitter_remove(self, ctx, handle : str): A delay of up to 2 min. is possible due to Twitter rate limits ''' try: - self.feeds_info["channels"].get(ctx.message.channel.id, {}).get("handles", []).remove(handle) + self.feeds_info["channels"].get(ctx.channel.id, {}).get("handles", []).remove(handle) except ValueError: - await self.bot.embed_reply(":no_entry: This text channel isn't following that Twitter handle") + await ctx.embed_reply(":no_entry: This text channel isn't following that Twitter handle") else: with open("data/twitter_feeds.json", 'w') as feeds_file: json.dump(self.feeds_info, feeds_file, indent = 4) - message, embed = await self.bot.embed_reply(":hourglass: Please wait") - await self.stream_listener.remove_feed(ctx.message.channel, handle) + message = await ctx.embed_reply(":hourglass: Please wait") + await self.stream_listener.remove_feed(ctx.channel, handle) + embed = message.embeds[0] embed.description = "Removed the Twitter handle, [`{0}`](https://twitter.com/{0}), from this text channel.".format(handle) await self.bot.edit_message(message, embed = embed) - @twitter.command(aliases = ["handle", "feeds", "feed", "list"], pass_context = True) + @twitter.command(aliases = ["handle", "feeds", "feed", "list"]) @checks.not_forbidden() async def handles(self, ctx): '''Show Twitter handles being followed in a text channel''' - await self.bot.embed_reply('\n'.join(self.feeds_info["channels"].get(ctx.message.channel.id, {}).get("handles", []))) + await ctx.embed_reply('\n'.join(self.feeds_info["channels"].get(ctx.channel.id, {}).get("handles", []))) # TODO: Add message if none async def start_twitter_feeds(self): diff --git a/Discord/cogs/youtube.py b/Discord/cogs/youtube.py index ecb12dc51a..54627cdde8 100644 --- a/Discord/cogs/youtube.py +++ b/Discord/cogs/youtube.py @@ -39,49 +39,49 @@ def __unload(self): # TODO: Follow channels/new video uploads - @youtube.group(name = "streams", aliases = ["stream"], pass_context = True, invoke_without_command = True) # Handle stream alias when audio cog not loaded first + @youtube.group(name = "streams", aliases = ["stream"], invoke_without_command = True) # Handle stream alias when audio cog not loaded first @checks.is_permitted() async def youtube_streams(self, ctx): '''Youtube Streams''' - await self.bot.embed_reply("See {}help youtube streams".format(ctx.prefix)) + await ctx.embed_reply("See {}help youtube streams".format(ctx.prefix)) - @youtube_streams.command(name = "add", pass_context = True, invoke_without_command = True) + @youtube_streams.command(name = "add", invoke_without_command = True) @checks.is_permitted() async def youtube_streams_add(self, ctx, channel_id : str): '''Add Youtube channel to follow''' # TODO: Check channel ID validity # TODO: Add by username option - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) if channel: if channel_id in channel["channel_ids"]: - await self.bot.embed_reply(":no_entry: This text channel is already following that Youtube channel") + await ctx.embed_reply(":no_entry: This text channel is already following that Youtube channel") return channel["channel_ids"].append(channel_id) else: - self.streams_info["channels"][ctx.message.channel.id] = {"name": ctx.message.channel.name, "channel_ids": [channel_id]} + self.streams_info["channels"][ctx.channel.id] = {"name": ctx.channel.name, "channel_ids": [channel_id]} with open("data/youtube_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Added the Youtube channel, [`{0}`](https://www.youtube.com/channel/{0}), to this text channel\n" + await ctx.embed_reply("Added the Youtube channel, [`{0}`](https://www.youtube.com/channel/{0}), to this text channel\n" "I will now announce here when this Youtube channel goes live".format(channel_id)) - @youtube_streams.command(name = "remove", aliases = ["delete"], pass_context = True, invoke_without_command = True) + @youtube_streams.command(name = "remove", aliases = ["delete"], invoke_without_command = True) @checks.is_permitted() async def youtube_streams_remove(self, ctx, channel_id : str): '''Remove Youtube channel being followed''' - channel = self.streams_info["channels"].get(ctx.message.channel.id) + channel = self.streams_info["channels"].get(ctx.channel.id) if not channel or channel_id not in channel["channel_ids"]: - await self.bot.embed_reply(":no_entry: This text channel isn't following that Youtube channel") + await ctx.embed_reply(":no_entry: This text channel isn't following that Youtube channel") return channel["channel_ids"].remove(channel_id) with open("data/youtube_streams.json", 'w') as streams_file: json.dump(self.streams_info, streams_file, indent = 4) - await self.bot.embed_reply("Removed the Youtube channel, [`{0}`](https://www.youtube.com/channel/{0}), from this text channel".format(channel_id)) + await ctx.embed_reply("Removed the Youtube channel, [`{0}`](https://www.youtube.com/channel/{0}), from this text channel".format(channel_id)) - @youtube_streams.command(name = "channels", aliases = ["streams"], pass_context = True) + @youtube_streams.command(name = "channels", aliases = ["streams"]) @checks.not_forbidden() async def youtube_streams_channels(self, ctx): '''Show Youtube channels being followed in this text channel''' - await self.bot.embed_reply(clients.code_block.format('\n'.join(self.streams_info["channels"].get(ctx.message.channel.id, {}).get("channel_ids", [])))) + await ctx.embed_reply(clients.code_block.format('\n'.join(self.streams_info["channels"].get(ctx.channel.id, {}).get("channel_ids", [])))) async def check_youtube_streams(self): await self.bot.wait_until_ready() diff --git a/Discord/modules/adventure.py b/Discord/modules/adventure.py index 4ea0f65742..d4c26cffcf 100644 --- a/Discord/modules/adventure.py +++ b/Discord/modules/adventure.py @@ -37,7 +37,9 @@ def wood_lvl(wood_type): return wood_types.index(wood_type) + 1 class AdventurePlayer: - + + '''Adventure Player''' + def __init__(self, user_id): self.user_id = user_id _initial_data = initial_data.copy() @@ -91,6 +93,7 @@ def stop_foraging(self): return False, self.last_action def create_item(self, items): + '''Create/Craft an item''' for item in items: if item not in self.inventory: return None @@ -135,6 +138,7 @@ def stop_woodcutting(self): return False, self.last_action def chop_once(self, wood_type): + '''Chop a tree once''' wood = self.inventory[wood_type] = self.inventory.get(wood_type, 0) + 1 xp = self.woodcutting_xp = self.woodcutting_xp + wood_lvl(wood_type) self.write_data() diff --git a/Discord/modules/gofish.py b/Discord/modules/gofish.py index 82843cceda..861ad0a920 100644 --- a/Discord/modules/gofish.py +++ b/Discord/modules/gofish.py @@ -1,37 +1,45 @@ import pydealer -started = False - -def start(number): - global started, number_of_players, played, hands, deck - started = True - number_of_players = number - played = [False] * number_of_players - deck = pydealer.Deck() - deck.shuffle() - hands = {} - for i in range(number_of_players): - if number_of_players <= 4: - hands[i] = deck.deal(7) +class GoFishRound: + + '''Round of Go Fish''' + + def __init__(self): + self.started = False + self.number_of_players = 0 + self.played = [] + self.hands = {} + self.deck = pydealer.Deck() + self.deck.shuffle() + + def start(number): + '''Start a round of Go Fish''' + self.started = True + self.number_of_players = number + self.played = [False] * self.number_of_players + for i in range(self.number_of_players): + if self.number_of_players <= 4: + self.hands[i] = self.deck.deal(7) + else: + self.hands[i] = self.deck.deal(5) + self.hands[i].sort() + + def hand(player_number): + hand_string = "" + if player_number <= self.number_of_players: + for card in hands[player_number].cards: + hand_string += card.value + " of " + card.suit + ", " else: - hands[i] = deck.deal(5) - hands[i].sort() + return + return hand_string[:-2] -def hand(player_number): - hand_string = "" - if player_number <= number_of_players: - for card in hands[player_number].cards: - hand_string += card.value + " of " + card.suit + ", " - else: - return - return hand_string[:-2] + def ask(player_number, asked_player, card): + if self.played[player_number - 1]: + return -1 + if player_number <= self.number_of_players and asked_player <= self.number_of_players: + if len(self.hands[player_number].get(card)): + self.played[player_number - 1] = True + else: + return -2 -def ask(player_number, asked_player, card): - if played[player_number - 1]: - return -1 - if player_number <= number_of_players and asked_player <= number_of_players: - if len(hands[player_number].get(card)): - played[player_number - 1] = True - else: - return -2 diff --git a/Discord/modules/logging.py b/Discord/modules/logging.py index e5c5d31033..d29880ca9d 100644 --- a/Discord/modules/logging.py +++ b/Discord/modules/logging.py @@ -16,6 +16,8 @@ class Logger(object): + '''Logger''' + def __init__(self, log, prefix = ""): self.console = sys.__stdout__ self.log = log diff --git a/Discord/modules/maze.py b/Discord/modules/maze.py index 45fa232f4a..c563f756fc 100644 --- a/Discord/modules/maze.py +++ b/Discord/modules/maze.py @@ -2,7 +2,9 @@ from random import shuffle, randint class Maze: - + + '''Maze''' + def __init__(self, columns, rows, random_start = False, random_end = False): self.columns = 2 if columns < 2 else 100 if columns > 100 else columns self.rows = 2 if rows < 2 else 100 if rows > 100 else rows @@ -63,6 +65,7 @@ def __repr__(self): return self.maze_string def move(self, direction): + '''Move inside the maze''' if direction.lower() == 'n': if not self.directions[self.column][self.row][0]: return False @@ -97,6 +100,7 @@ def move(self, direction): return True def print_visible(self): + '''The visible output of the maze''' if self.rows <= 10 and self.columns <= 10: return '\n'.join(self.visible) start_row = self.row - self.row % 10 @@ -130,6 +134,7 @@ def test_print(self): # def __str__(self): def generate_connection(self, c, r): + '''Generate connections for the maze''' self.generate_visited[c][r] = True directions = [[0, -1], [1, 0], [0, 1], [-1, 0]] shuffle(directions) diff --git a/Discord/modules/poker.py b/Discord/modules/poker.py index 01735f6c4a..3e7b4308a8 100644 --- a/Discord/modules/poker.py +++ b/Discord/modules/poker.py @@ -3,6 +3,8 @@ class PokerRound: + '''Round of poker''' + def __init__(self): self.status = None self.players = [] diff --git a/Discord/modules/utilities.py b/Discord/modules/utilities.py index 0052c7ffc6..b265280132 100644 --- a/Discord/modules/utilities.py +++ b/Discord/modules/utilities.py @@ -107,13 +107,13 @@ def embed_total_characters(embed): def get_permission(ctx, permission, *, type = "user", id = None): try: - with open("data/permissions/{}.json".format(ctx.message.server.id), "x+") as permissions_file: - json.dump({"name" : ctx.message.server.name}, permissions_file, indent = 4) + with open("data/permissions/{}.json".format(ctx.guild.id), "x+") as permissions_file: + json.dump({"name" : ctx.guild.name}, permissions_file, indent = 4) except FileExistsError: pass else: return None - with open("data/permissions/{}.json".format(ctx.message.server.id), "r") as permissions_file: + with open("data/permissions/{}.json".format(ctx.guild.id), "r") as permissions_file: permissions_data = json.load(permissions_file) if type == "everyone": return permissions_data.get("everyone", {}).get(permission) @@ -123,7 +123,7 @@ def get_permission(ctx, permission, *, type = "user", id = None): elif type == "user": user_setting = permissions_data.get("users", {}).get(id, {}).get(permission) if user_setting is not None: return user_setting - user = discord.utils.get(ctx.message.server.members, id = id) + user = discord.utils.get(ctx.guild.members, id = id) role_positions = {} for role in user.roles: role_positions[role.position] = role @@ -140,9 +140,9 @@ async def get_user(ctx, name): user_id = mention.group(1) user = await ctx.bot.get_user_info(user_id) if user: return user - if ctx.message.server: + if ctx.guild: # check if exact match - matches = [member for member in ctx.message.server.members if member.name == name or member.nick == name] + matches = [member for member in ctx.guild.members if member.name == name or member.nick == name] if len(matches) == 1: return matches[0] elif len(matches) > 1: @@ -154,10 +154,10 @@ async def get_user(ctx, name): await ctx.bot.say("Multiple users with the name, {}. Which one did you mean?\n" "**Enter the number it is in the list.**".format(name)) await ctx.bot.say(members) - message = await ctx.bot.wait_for_message(author = ctx.message.author, check = lambda m: m.content.isdigit() and 1 <= int(m.content) <= len(matches)) + message = await ctx.bot.wait_for_message(author = ctx.author, check = lambda m: m.content.isdigit() and 1 <= int(m.content) <= len(matches)) return matches[int(message.content) - 1] # check if beginning match - start_matches = [member for member in ctx.message.server.members if member.name.startswith(name) or member.nick and member.nick.startswith(name)] + start_matches = [member for member in ctx.guild.members if member.name.startswith(name) or member.nick and member.nick.startswith(name)] if len(start_matches) == 1: return start_matches[0] elif len(start_matches) > 1: @@ -168,7 +168,7 @@ async def get_user(ctx, name): members += '\n' await ctx.bot.reply("Multiple users with names starting with {}. Which one did you mean? **Enter the number.**".format(name)) await ctx.bot.say(members) - message = await ctx.bot.wait_for_message(author = ctx.message.author, check = lambda m: m.content.isdigit() and 1 <= int(m.content) <= len(start_matches)) + message = await ctx.bot.wait_for_message(author = ctx.author, check = lambda m: m.content.isdigit() and 1 <= int(m.content) <= len(start_matches)) return start_matches[int(message.content) - 1] # check if with discriminator user_info = re.match(r"^(.+)#(\d{4})", name) diff --git a/Discord/modules/war.py b/Discord/modules/war.py index 25cb82e21c..6e9c202556 100644 --- a/Discord/modules/war.py +++ b/Discord/modules/war.py @@ -1,107 +1,117 @@ import pydealer -started = False +class WarRound: + + '''Round of War''' + + def __init__(self): + self.started = False + self.number_of_players = 0 + self.played = [] + self.hands = {} + self.cards = {} + self.cards_played = {} + self.tied_cards = pydealer.Stack() + self.tied_players = [] + self.tied_played = {} + + def start(number): + '''Start a round of War''' + self.started = True + self.number_of_players = number + self.played = [False] * self.number_of_players + count = 1 + temp = self.number_of_players + while temp > 1: + deck = pydealer.Deck() + deck.shuffle() + self.hands[count] = deck.deal(5) + self.hands[count + 1] = deck.deal(5) + self.cards[count], self.cards[count + 1] = deck.split() + count += 2 + temp -= 2 + if temp == 1: + deck = pydealer.Deck() + deck.shuffle() + self.hands[count] = deck.deal(5) + discard = deck.deal(5) + self.cards[count], discard = deck.split() + # hand1.sort() + # hand2.sort() -def start(number): - global started, number_of_players, played, hands, cards, cardsplayed, tiedcards - started = True - number_of_players = number - played = [False] * number_of_players - cardsplayed = {} - hands = {} - cards = {} - tiedcards = pydealer.Stack() - count = 1 - temp = number_of_players - while temp > 1: - deck = pydealer.Deck() - deck.shuffle() - hands[count] = deck.deal(5) - hands[count + 1] = deck.deal(5) - cards[count], cards[count + 1] = deck.split() - count += 2 - temp -= 2 - if temp == 1: - deck = pydealer.Deck() - deck.shuffle() - hands[count] = deck.deal(5) - discard = deck.deal(5) - cards[count], discard = deck.split() - # hand1.sort() - # hand2.sort() - -def hand(player_number): - hand_string = "" - if player_number <= number_of_players: - for card in hands[player_number].cards: - hand_string += card.value + " of " + card.suit + ", " - else: - return - return hand_string[:-2] + def hand(player_number): + hand_string = "" + if player_number <= self.number_of_players: + for card in self.hands[player_number].cards: + hand_string += card.value + " of " + card.suit + ", " + else: + return + return hand_string[:-2] -def card_count(player_number): - if player_number <= number_of_players: - return cards[player_number].size + hands[player_number].size - else: - return + def card_count(player_number): + if player_number <= self.number_of_players: + return self.cards[player_number].size + self.hands[player_number].size + else: + return -def play(player_number, card): - global played, cardsplayed, hands, cards, tiedcards, tiedplayers, tiedplayed - if tiedcards.size: - if player_number not in tiedplayers: - return -3, -1, -1 - if tiedplayed[player_number]: + def play(player_number, card): + '''Play a card''' + if self.tied_cards.size: + if player_number not in self.tied_players: + return -3, -1, -1 + if self.tied_played[player_number]: + return -1, -1, -1 + if self.played[player_number - 1]: return -1, -1, -1 - if played[player_number - 1]: - return -1, -1, -1 - cardplayed = hands[player_number].get(card, limit=1) - if len(cardplayed) == 0: - return -4, -1, -1 - else: - cardsplayed[player_number - 1] = cardplayed[0] - hands[player_number].add(cards[player_number].deal()) - if tiedcards.size: - tiedplayed[player_number] = True - if not all(list(tiedplayed.values())): - return 0, cardsplayed, -1 - list_of_cards_played = [] - for tiedplayer in tiedplayers: - list_of_cards_played.append(cardsplayed[tiedplayer - 1]) - else: - played[player_number - 1] = True - if not all(played): - return 0, cardsplayed, -1 - played = [False for flag in played] - list_of_cards_played = [] - for i in range(number_of_players): - list_of_cards_played.append(cardsplayed[i]) - allcardsplayed = pydealer.Stack(cards=list_of_cards_played) - allcardsplayedsorted = pydealer.Stack(cards=list_of_cards_played) - allcardsplayedsorted.sort(ranks=pydealer.POKER_RANKS) - highestcard = allcardsplayedsorted.deal(1)[0] - highestplayers = allcardsplayed.find(highestcard.value) - cardsplayed = {} - if len(highestplayers) == 1 and not tiedcards.size: - cards[highestplayers[0] + 1].add(allcardsplayed, end="bottom") - return highestplayers[0] + 1, allcardsplayed, -1 - elif len(highestplayers) == 1: - cards[tiedplayers[highestplayers[0]]].add(allcardsplayed, end="bottom") - cards[tiedplayers[highestplayers[0]]].add(tiedcards, end="bottom") - tiedcards = pydealer.Stack() - return tiedplayers[highestplayers[0]], allcardsplayed, -1 - else: - if tiedcards.size: - temp = [] - for highestplayer in highestplayers: - temp.append(tiedplayers[highestplayer]) - tiedplayers = temp + card_played = self.hands[player_number].get(card, limit=1) + if len(card_played) == 0: + return -4, -1, -1 else: - tiedplayers = [] - for highestplayer in highestplayers: - tiedplayers.append(highestplayer + 1) - tiedcards.add(allcardsplayed) - tiedplayed = {} - for tiedplayer in tiedplayers: - tiedplayed[tiedplayer] = False - return -2, allcardsplayed, tiedplayers + self.cards_played[player_number - 1] = card_played[0] + self.hands[player_number].add(self.cards[player_number].deal()) + if self.tied_cards.size: + self.tied_played[player_number] = True + if not all(list(self.tied_played.values())): + return 0, self.cards_played, -1 + list_of_cards_played = [] + for tied_player in self.tied_players: + list_of_cards_played.append(self.cards_played[tied_player - 1]) + else: + self.played[player_number - 1] = True + if not all(self.played): + return 0, self.cards_played, -1 + self.played = [False for flag in self.played] + list_of_cards_played = [] + for i in range(self.number_of_players): + list_of_cards_played.append(self.cards_played[i]) + all_cards_played = pydealer.Stack(cards=list_of_cards_played) + all_cards_played_sorted = pydealer.Stack(cards=list_of_cards_played) + all_cards_played_sorted.sort(ranks=pydealer.POKER_RANKS) + highest_card = all_cards_played_sorted.deal(1)[0] + highest_players = all_cards_played.find(highest_card.value) + self.cards_played = {} + if len(highest_players) == 1 and not self.tied_cards.size: + self.cards[highest_players[0] + 1].add(all_cards_played, end="bottom") + return highest_players[0] + 1, all_cards_played, -1 + elif len(highest_players) == 1: + self.cards[self.tied_players[highest_players[0]]].add(all_cards_played, end="bottom") + self.cards[self.tied_players[highest_players[0]]].add(self.tied_cards, end="bottom") + self.tied_cards = pydealer.Stack() + return self.tied_players[highest_players[0]], all_cards_played, -1 + else: + if self.tied_cards.size: + temp = [] + for highest_player in highest_players: + temp.append(self.tied_players[highest_player]) + self.tied_players = temp + else: + self.tied_players = [] + for highest_player in highest_players: + self.tied_players.append(highest_player + 1) + self.tied_cards.add(all_cards_played) + self.tied_played = {} + for tied_player in self.tied_players: + self.tied_played[tied_player] = False + return -2, all_cards_played, self.tied_players + diff --git a/Discord/utilities/audio_player.py b/Discord/utilities/audio_player.py index 5740a99563..7bbdf003b5 100644 --- a/Discord/utilities/audio_player.py +++ b/Discord/utilities/audio_player.py @@ -26,7 +26,7 @@ class AudioPlayer: def __init__(self, client, text_channel): self.bot = client self.text_channel = text_channel - self.server = text_channel.server + self.server = text_channel.guild self.queue = asyncio.Queue() self.current = None self.play_next_song = asyncio.Event() @@ -61,13 +61,13 @@ async def join_channel(self, user, channel): utilities.remove_symbols(_channel.name).startswith(' '.join(channel)), self.server.channels) if not voice_channel: raise errors.AudioNotPlaying - if self.bot.is_voice_connected(self.server): + if self.server.voice_client: await self.server.voice_client.move_to(voice_channel) return True await self.bot.join_voice_channel(voice_channel) async def leave_channel(self): - if self.bot.is_voice_connected(self.server): + if self.server.voice_client: if self.current and self.current["stream"].is_playing(): self.current["stream"].stop() self.player.cancel() @@ -305,7 +305,7 @@ async def play_file(self, filename, requester, timestamp): if not filename: filename = random.choice(self.audio_files) elif filename not in self.audio_files: - await self.bot.embed_reply(":no_entry: File not found") + await ctx.embed_reply(":no_entry: File not found") return True return (await self._interrupt("data/audio_files/" + filename, filename, requester, timestamp)) @@ -316,7 +316,7 @@ async def play_from_library(self, filename, requester, timestamp, *, clear_flag if not filename: filename = random.choice(self.library_files) elif filename not in self.library_files: - await self.bot.embed_reply(":no_entry: Song file not found") + await ctx.embed_reply(":no_entry: Song file not found") return True return (await self._interrupt(clients.library_files + filename, filename, requester, timestamp, clear_flag = clear_flag)) ## print([f for f in os.listdir(clients.library_files) if not f.endswith((".mp3", ".m4a", ".jpg"))]) @@ -334,7 +334,7 @@ async def play_library(self, requester, timestamp): else: paused = True self.not_interrupted.clear() - while self.bot.is_voice_connected(self.server) and self.library_flag: + while self.server.voice_client and self.library_flag: await self.play_from_library("", requester, timestamp, clear_flag = False) await asyncio.sleep(0.1) # wait to check self.not_interrupted.set() @@ -374,7 +374,7 @@ def _resume_from_interruption(self): self.bot.loop.call_soon_threadsafe(self.resume_flag.set) async def add_playlist(self, playlist, requester, timestamp): - response, embed = await self.bot.embed_reply(":cd: Loading..") + response = await ctx.embed_reply(":cd: Loading..") ydl = youtube_dl.YoutubeDL(self.ytdl_playlist_options) func = functools.partial(ydl.extract_info, playlist, download = False) await self.bot.loop.run_in_executor(None, func) @@ -382,6 +382,7 @@ async def add_playlist(self, playlist, requester, timestamp): videos = [json.loads(line) for line in playlist_info_file if line.startswith('{')] playlist_info_file.seek(0) playlist_info_file.truncate() + embed = response.embeds[0] for position, video in enumerate(videos, start = 1): embed.description = ":cd: Loading {}/{}".format(position, len(videos)) await self.bot.edit_message(response, embed = embed) @@ -400,7 +401,7 @@ async def radio_on(self, requester, timestamp): return False if not self.radio_flag: if not self.current: - await self.bot.embed_reply(":no_entry: Please play a song to base the radio station off of first") + await ctx.embed_reply(":no_entry: Please play a song to base the radio station off of first") # TODO: Non song based station? return None await self.bot.send_embed(self.text_channel, ":radio: Radio based on `{}` is now on".format(self.current["info"]["title"])) @@ -412,7 +413,7 @@ async def radio_on(self, requester, timestamp): paused = False else: paused = True - while self.bot.is_voice_connected(self.server) and self.radio_flag: + while self.server.voice_client and self.radio_flag: url = "https://www.googleapis.com/youtube/v3/search?part=snippet&relatedToVideoId={}&type=video&key={}".format(videoid, credentials.google_apikey) async with clients.aiohttp_session.get(url) as resp: data = await resp.json() diff --git a/Discord/utilities/checks.py b/Discord/utilities/checks.py index 33c6a18340..309e2573f5 100644 --- a/Discord/utilities/checks.py +++ b/Discord/utilities/checks.py @@ -1,4 +1,5 @@ +import discord from discord.ext import commands from utilities import errors @@ -9,7 +10,7 @@ from clients import client def is_owner_check(ctx): - return ctx.message.author.id == clients.owner_id + return ctx.author.id == clients.owner_id def is_owner(): @@ -22,7 +23,7 @@ def predicate(ctx): return commands.check(predicate) def is_server_owner_check(ctx): - return ctx.message.channel.is_private or ctx.message.author == ctx.message.server.owner or is_owner_check(ctx) + return isinstance(ctx.channel, discord.DMChannel) or ctx.author == ctx.guild.owner or is_owner_check(ctx) def is_server_owner(): @@ -35,13 +36,13 @@ def predicate(ctx): return commands.check(predicate) def is_voice_connected_check(ctx): - return ctx.message.server and client.is_voice_connected(ctx.message.server) + return ctx.guild and ctx.guild.voice_client def is_voice_connected(): def predicate(ctx): if not is_voice_connected_check(ctx): - if is_server_owner_check(ctx) or utilities.get_permission(ctx, "join", id = ctx.message.author.id): + if is_server_owner_check(ctx) or utilities.get_permission(ctx, "join", id = ctx.author.id): raise errors.PermittedVoiceNotConnected else: raise errors.NotPermittedVoiceNotConnected @@ -50,7 +51,7 @@ def predicate(ctx): return commands.check(predicate) def has_permissions_check(ctx, permissions): - _permissions = ctx.message.channel.permissions_for(ctx.message.author) + _permissions = ctx.channel.permissions_for(ctx.author) return all(getattr(_permissions, permission, None) == setting for permission, setting in permissions.items()) or is_owner_check(ctx) def has_permissions(**permissions): @@ -66,7 +67,7 @@ def predicate(ctx): def dm_or_has_permissions(**permissions): def predicate(ctx): - if ctx.message.channel.is_private or has_permissions_check(ctx, permissions): + if isinstance(ctx.channel, discord.DMChannel) or has_permissions_check(ctx, permissions): return True else: raise errors.MissingPermissions @@ -74,7 +75,7 @@ def predicate(ctx): return commands.check(predicate) def has_capability_check(ctx, permissions): - _permissions = ctx.message.channel.permissions_for(ctx.message.server.me) + _permissions = ctx.channel.permissions_for(ctx.me) return all(getattr(_permissions, permission, None) == True for permission in permissions) def has_capability(*permissions): @@ -90,7 +91,7 @@ def predicate(ctx): def dm_or_has_capability(*permissions): def predicate(ctx): - if ctx.message.channel.is_private or has_capability_check(ctx, permissions): + if isinstance(ctx.channel, discord.DMChannel) or has_capability_check(ctx, permissions): return True else: raise errors.MissingCapability(permissions) @@ -100,7 +101,7 @@ def predicate(ctx): def has_permissions_and_capability(**permissions): def predicate(ctx): - if ctx.message.channel.is_private: + if isinstance(ctx.channel, discord.DMChannel): return False elif not has_permissions_check(ctx, permissions): raise errors.MissingPermissions @@ -114,7 +115,7 @@ def predicate(ctx): def dm_or_has_permissions_and_capability(**permissions): def predicate(ctx): - if ctx.message.channel.is_private: + if isinstance(ctx.channel, discord.DMChannel): return True elif not has_permissions_check(ctx, permissions): raise errors.MissingPermissions @@ -126,9 +127,9 @@ def predicate(ctx): return commands.check(predicate) def not_forbidden_check(ctx): - if ctx.message.channel.is_private: + if isinstance(ctx.channel, discord.DMChannel): return True - permitted = utilities.get_permission(ctx, ctx.command.name, id = ctx.message.author.id) + permitted = utilities.get_permission(ctx, ctx.command.name, id = ctx.author.id) # TODO: Include subcommands? return permitted or permitted is None or is_server_owner_check(ctx) @@ -143,14 +144,15 @@ def predicate(ctx): return commands.check(predicate) def is_permitted_check(ctx): - if ctx.message.channel.is_private: + '''Check if permitted''' + if isinstance(ctx.channel, discord.DMChannel): return True command = ctx.command - permitted = utilities.get_permission(ctx, command.name, id = ctx.message.author.id) + permitted = utilities.get_permission(ctx, command.name, id = ctx.author.id) while command.parent is not None and not permitted: # permitted is None instead? command = command.parent - permitted = utilities.get_permission(ctx, command.name, id = ctx.message.author.id) + permitted = utilities.get_permission(ctx, command.name, id = ctx.author.id) # include non-final parent commands? return permitted or is_server_owner_check(ctx) diff --git a/Discord/utilities/errors.py b/Discord/utilities/errors.py index c4f4926ce6..ae3933fab8 100644 --- a/Discord/utilities/errors.py +++ b/Discord/utilities/errors.py @@ -2,39 +2,51 @@ from discord.ext.commands.errors import CommandError class NotOwner(CommandError): + '''Not Owner''' pass class NotServerOwner(CommandError): + '''Not Server Owner''' pass class VoiceNotConnected(CommandError): + '''Voice Not Connected''' pass class PermittedVoiceNotConnected(VoiceNotConnected): + '''Permitted, but Voice Not Connected''' pass class NotPermittedVoiceNotConnected(VoiceNotConnected): + '''Voice Not Connected, and Not Permitted''' pass class MissingPermissions(CommandError): + '''Missing Permissions''' pass class MissingCapability(CommandError): + '''Missing Capability''' def __init__(self, permissions): self.permissions = permissions class NotPermitted(CommandError): + '''Not Permitted''' pass class LichessUserNotFound(CommandError): + '''Lichess User Not Found''' pass class AudioError(CommandError): + '''Audio Error''' pass class AudioNotPlaying(AudioError): + '''Audio Not Playing''' pass class AudioAlreadyDone(AudioError): + '''Audio Already Done playing''' pass diff --git a/Discord/utilities/help_formatter.py b/Discord/utilities/help_formatter.py index ff8d070900..0e37ff9aa1 100644 --- a/Discord/utilities/help_formatter.py +++ b/Discord/utilities/help_formatter.py @@ -11,7 +11,10 @@ class CustomHelpFormatter(HelpFormatter): + '''Custom Help Formatter''' + def format(self): + '''Format''' description_paginator = Paginator(max_size = 2048) max_width = self.max_name_size if self.is_bot(): @@ -82,7 +85,8 @@ def category(tup): self._add_subcommands_to_page(max_width, subcommands, description_paginator) return self.embeds(title, description_paginator) - def embeds(self, title, paginator): + @staticmethod + def embeds(title, paginator): embeds = [discord.Embed(title = title, description = paginator.pages[0] if paginator.pages else None, color = clients.bot_color)] for page in paginator.pages[1:]: embeds.append(discord.Embed(description = page, color = clients.bot_color)) @@ -92,8 +96,9 @@ def _add_subcommands_to_page(self, max_width, commands, paginator): for line in self._subcommands_lines(max_width, commands): paginator.add_line(line) - def _subcommands_lines(self, max_width, commands): - # def _subcommands_lines(self, max_width, commands, indent = True): + @staticmethod + def _subcommands_lines(max_width, commands): + # def _subcommands_lines(max_width, commands, indent = True): lines = [] for name, command in commands: if name in command.aliases: # skip aliases