From 74896d921ef60864807253469c5868babaa0c8d3 Mon Sep 17 00:00:00 2001 From: phxntxm Date: Mon, 29 May 2017 16:17:00 -0500 Subject: [PATCH 1/6] Move joining a channel to it's own method --- cogs/music.py | 87 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/cogs/music.py b/cogs/music.py index c43fbac..aa6a7e2 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -8,7 +8,6 @@ from . import utils import math import asyncio -import inspect import time import re import logging @@ -60,7 +59,6 @@ class VoiceState: self.current = None async def audio_player_task(self): - fmt = "" while True: if self.playing: await asyncio.sleep(1) @@ -81,12 +79,11 @@ class VoiceState: continue except discord.Forbidden: pass - except Exception as e: + except: await song.channel.send("Failed to download {}!".format(song.title)) log.error(traceback.format_exc()) continue - source = FFmpegPCMAudio( self.current.filename, before_options='-nostdin', @@ -251,7 +248,8 @@ class Music: pass await message.delete() - async def on_voice_state_update(self, member, before, after): + # noinspection PyUnusedLocal + async def on_voice_state_update(self, _, __, after): if after is None or after.channel is None: return state = self.voice_states.get(after.channel.guild.id) @@ -266,6 +264,51 @@ class Music: entry, _ = await state.songs.add_entry(song, ctx) return entry + async def join_channel(self, channel): + state = self.voice_states.get(channel.guild.id) + log.info("Joining channel {} in guild {}".format(channel.id, channel.guild.id)) + + # Send a message letting the channel know we are attempting to join + try: + msg = await channel.send("Trying to join channel {}...".format(channel.name)) + except discord.Forbidden: + msg = None + + try: + # If we're already connected, try moving to the channel + if state and state.voice and state.voice.channel: + await state.voice.move_to(channel) + # Otherwise, try connecting + else: + await channel.connect() + + # If we have connnected, create our voice state + self.voice_states[channel.guild.id] = VoiceState(channel.guild, self.bot) + + # If we can send messages, edit it to let the channel know we have succesfully joined + if msg: + await msg.edit(content="Ready to play audio in channel {}".format(channel.name)) + return True + # If we time out trying to join, just let them know and return False + except asyncio.TimeoutError: + if msg: + await msg.edit(content="Sorry, but I couldn't connect right now! Please try again later") + return False + # Theoretically this should never happen, however in rare cirumstances it does + # This error arises when we are already in a channel and don't use "move" + # We already checked if that existed above though, so this means the voice connection got stuck somewhere + except discord.ClientException: + if channel.guild.voice_client: + # Force a disconnection + await channel.guild.voice_client.disconnect(force=True) + # Log this so we can track it + log.warning( + "Force cleared voice connection on guild {} after being stuck " + "between connected/not connected".format(channel.guild.id)) + # Let them know what happened + await channel.send("Sorry but I couldn't connect...try again?") + return False + @commands.command(pass_context=True) @commands.guild_only() @utils.custom_perms(send_messages=True) @@ -308,30 +351,12 @@ class Music: perms = channel.permissions_for(ctx.message.guild.me) - log.info("Joining channel {} in guild {}".format(channel.id, ctx.message.guild.id)) - if not perms.connect or not perms.speak or not perms.use_voice_activation: await ctx.send("I do not have correct permissions in {}! Please turn on `connect`, `speak`, and `use " "voice activation`".format(channel.name)) return False - state = self.voice_states.get(ctx.message.guild.id) - try: - if state and state.voice and state.voice.channel: - await state.voice.move_to(channel) - else: - await channel.connect() - self.voice_states[ctx.message.guild.id] = VoiceState(ctx.message.guild, self.bot) - return True - except asyncio.TimeoutError: - await ctx.send("Sorry, but I couldn't connect right now! Please try again later") - return False - except discord.ClientException: - if channel.guild.voice_client: - await channel.guild.voice_client.disconnect(force=True) - log.warning("Force cleared voice connection on guild {} after being stuck between connected/not connected".format(ctx.message.guild.id)) - await ctx.send("Sorry but I couldn't connect...try again?") - + return await self.join_channel(channel) @commands.command() @commands.guild_only() @@ -349,7 +374,7 @@ class Music: return song = re.sub('[<>\[\]]', '', song) - if len (song) == 11: + if len(song) == 11: # Youtube-dl will attempt to things with the length of 11 as a video ID # If this is a search, this causes it to break # Youtube will still succeed if this *is* an ID provided, if there's a . after @@ -395,7 +420,7 @@ class Music: state = self.voice_states.get(ctx.message.guild.id) if value: - value = value / 100 + value /= 100 if state is None or state.voice is None: await ctx.send("I need to be in a channel before my volume can be set") elif value is None: @@ -432,17 +457,17 @@ class Music: This also clears the queue. """ state = self.voice_states.get(ctx.message.guild.id) + voice = ctx.message.guild.voice_client + if voice: + voice.stop() + await voice.disconnect(force=True) - # Stop playing whatever song is playing. - if state and state.voice: - state.voice.stop() - + if state: state.songs.clear() # This will cancel the audio event we're using to loop through the queue # Then erase the voice_state entirely, and disconnect from the channel state.audio_player.cancel() - await state.voice.disconnect() try: del self.voice_states[ctx.message.guild.id] except KeyError: From d5b1f0a64d708c86d08be8bd02a729ffdeacb687 Mon Sep 17 00:00:00 2001 From: phxntxm Date: Mon, 29 May 2017 16:27:12 -0500 Subject: [PATCH 2/6] Handle when there are no songs in the queue --- cogs/music.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cogs/music.py b/cogs/music.py index aa6a7e2..a886944 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -527,8 +527,11 @@ class Music: @utils.custom_perms(send_messages=True) async def queuelength(self, ctx): """Prints the length of the queue""" - await ctx.send("There are a total of {} songs in the queue" - .format(len(self.voice_states.get(ctx.message.guild.id).songs.entries))) + state = self.voice_states.get(ctx.message.guild.id) + if state: + await ctx.send("There are a total of {} songs in the queue".format(len(state.songs.entries))) + else: + await ctx.send("There are no songs in the queue") @commands.command(pass_context=True) @commands.guild_only() From bf5f65b0b751072fa88da09aef59b935de478241 Mon Sep 17 00:00:00 2001 From: phxntxm Date: Mon, 29 May 2017 16:27:25 -0500 Subject: [PATCH 3/6] Handle if the avatar is too large --- cogs/images.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cogs/images.py b/cogs/images.py index b11a666..c13ef77 100644 --- a/cogs/images.py +++ b/cogs/images.py @@ -8,6 +8,7 @@ from bs4 import BeautifulSoup as bs from . import utils + class Images: def __init__(self, bot): self.bot = bot @@ -29,11 +30,10 @@ class Images: return image = await utils.download_image(filename) - filename = re.search('.*\/i\/(.*)', filename).group(1) + filename = re.search('.*/i/(.*)', filename).group(1) f = discord.File(image, filename=filename) await ctx.send(file=f) - @commands.command(aliases=['dog', 'rd']) @utils.custom_perms(send_messages=True) async def doggo(self, ctx): @@ -88,8 +88,11 @@ class Images: if filedata is None: await ctx.send(url) else: - f = discord.File(filedata, filename=filename) - await ctx.send(file=f) + try: + f = discord.File(filedata, filename=filename) + await ctx.send(file=f) + except discord.HTTPException: + await ctx.send("Sorry but that avatar is too large for me to send!") else: await ctx.send(url) @@ -149,7 +152,7 @@ class Images: # Get the image link from the now random page'd and random result from that page index = random.SystemRandom().randint(0, len(results) - 1) - #image_link = 'https://derpibooru.org/{}'.format(results[index]['id']) + # image_link = 'https://derpibooru.org/{}'.format(results[index]['id']) image_link = 'https:{}'.format(results[index]['image']) else: await ctx.send("No results with that search term, {0}!".format(ctx.message.author.mention)) @@ -205,5 +208,6 @@ class Images: await ctx.send("No results with that tag {}".format(ctx.message.author.mention)) return + def setup(bot): bot.add_cog(Images(bot)) From 83e68a4c7fc8a7bc46c1cfcf0c1646ec384cc3a8 Mon Sep 17 00:00:00 2001 From: phxntxm Date: Mon, 29 May 2017 16:29:43 -0500 Subject: [PATCH 4/6] Handle if there aren't any nsfw channels on this server --- cogs/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/admin.py b/cogs/admin.py index 482a576..eadd2b5 100644 --- a/cogs/admin.py +++ b/cogs/admin.py @@ -226,7 +226,7 @@ class Administration: server_settings = await utils.get_content('server_settings', key) channel = str(ctx.message.channel.id) try: - channels = server_settings['nsfw_channels'] + channels = server_settings.get('nsfw_channels', None) if channel in channels: channels.remove(channel) From 7c30ed595a206cce534d7746b4f40679f0448726 Mon Sep 17 00:00:00 2001 From: phxntxm Date: Mon, 29 May 2017 16:29:49 -0500 Subject: [PATCH 5/6] PEP8 --- cogs/mod.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cogs/mod.py b/cogs/mod.py index a0511d6..d85f5d4 100644 --- a/cogs/mod.py +++ b/cogs/mod.py @@ -3,9 +3,8 @@ from discord.ext import commands from . import utils import discord -import re import asyncio -import rethinkdb as r + class Moderation: """Commands that can be used by a or an admin, depending on the command""" @@ -13,8 +12,6 @@ class Moderation: def __init__(self, bot): self.bot = bot - - @commands.command() @commands.guild_only() @utils.custom_perms(kick_members=True) From 1cc88ce6ab3e1b0c82aca66430b1abfe297bc864 Mon Sep 17 00:00:00 2001 From: phxntxm Date: Mon, 29 May 2017 16:33:31 -0500 Subject: [PATCH 6/6] Catch HTTPExceptions as this usually means an explicit word was sent --- cogs/music.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/music.py b/cogs/music.py index a886944..74e4ff2 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -409,7 +409,7 @@ class Music: embed = entry.to_embed() embed.title = "Enqueued song!" await ctx.send(embed=embed) - except discord.Forbidden: + except (discord.Forbidden, discord.HTTPException): pass @commands.command(pass_context=True)