1
0
Fork 0
mirror of synced 2024-05-19 20:12:30 +12:00

Add an import command for playlists; handle new downloading method of songs

This commit is contained in:
Phxntxm 2017-07-02 22:19:20 -05:00
parent 56ca4dabf2
commit 0be369fb79

View file

@ -92,12 +92,8 @@ class VoiceState:
if self.playing or not self.voice:
return
if self.current:
source = FFmpegPCMAudio(
self.current.filename,
before_options='-nostdin',
options='-vn -b:a 128k'
)
source = PCMVolumeTransformer(source, volume=self.volume)
# Transform our source into a volume source
source = PCMVolumeTransformer(self.current, volume=self.volume)
self.voice.play(source, after=self.after)
self.current.start_time = time.time()
# We handle users who join a user queue without songs (either at all, or ready) elsewhere
@ -110,13 +106,7 @@ class VoiceState:
async def next_song(self):
if not self.user_queue:
_result = await self.songs.get_next_entry()
if _result:
fut, self.current = _result
if fut.exception():
raise ExtractionError(fut.exception())
else:
self.current = None
self.current = await self.songs.next_entry()
else:
try:
dj = self.djs.popleft()
@ -124,13 +114,7 @@ class VoiceState:
self.dj = None
self.current = None
else:
_result = await dj.get_next_entry()
if _result:
fut, song = _result
else:
return await self.next_song()
if fut.exception():
raise ExtractionError(fut.exception())
song = await dj.next_entry()
# Add an extra check here in case in the very short period of time possible, someone has queued a
# song while we are downloading the next...which caused 2 play calls to be done
# The 2nd may be called while the first has already started playing...this check is for that 2nd one
@ -161,6 +145,15 @@ class Music:
self.downloader = down
self.bot.downloader = down
def __unload(self):
for state in self.voice_states.values():
try:
if state.voice:
state.voice.stop()
self.bot.loop.create_task(state.voice.disconnect())
except:
pass
async def queue_embed_task(self, state, channel, author):
index = 0
message = None
@ -197,7 +190,7 @@ class Music:
dj = entry
entry = entry.peek()
# Get the entry's embed
embed = entry.to_embed()
embed = entry.embed
# Set the embed's title to indicate the amount of things in the queue
count = len(queue)
@ -326,12 +319,44 @@ class Music:
async def add_entry(self, song, ctx):
state = self.voice_states[ctx.message.guild.id]
entry, _ = await state.songs.add_entry(song)
entry = await state.songs.add_entry(song)
if not state.playing:
await state.play_next_song()
self.bot.loop.create_task(state.play_next_song())
entry.requester = ctx.message.author
return entry
async def import_playlist(self, url, ctx):
state = self.voice_states[ctx.message.guild.id]
try:
msg = await ctx.send("Looking up {}\nThis may take a while...".format(url))
except:
msg = None
num_songs = None
successful = 0
failed = 0
fmt = "Downloading {} songs\n{} successful\n{} failed"
if msg:
# Go through each song in the playlist
async for success in state.songs.import_from(url, ctx.message.author):
# If this hasn't been set yet, the first yield is the number of songs
# Otherwise just add one based on successful or not
if not num_songs:
num_songs = success
elif success:
# If we're not playing yet and this is the first successful one we found
if not state.playing and successful == 0:
await state.play_next_song()
successful += 1
else:
failed += 1
try:
await msg.edit(content=fmt.format(num_songs, successful, failed))
except:
pass
else:
await state.songs.import_from(url)
async def join_channel(self, channel, text_channel):
state = self.voice_states.get(channel.guild.id)
log.info("Joining channel {} in guild {}".format(channel.id, channel.guild.id))
@ -436,6 +461,37 @@ class Music:
return await self.join_channel(channel, ctx.channel)
@commands.command(name='import')
@commands.guild_only()
@utils.custom_perms(send_messages=True)
@utils.check_restricted()
async def _import(self, ctx, *, song: str):
"""Imports a song into the current voice queue"""
# If we don't have a voice state yet, create one
if not self.bot.db.load('server_settings', key=ctx.message.guild.id, pluck='playlists_allowed'):
await ctx.send("You cannot import playlists at this time; the {}allowplaylists command can be used to change this setting".format(ctx.prefix))
return
if ctx.message.guild.id not in self.voice_states:
if not await ctx.invoke(self.join):
return
state = self.voice_states.get(ctx.message.guild.id)
# If this is a user queue, this is the wrong command
if state.user_queue:
await ctx.send("The current queue type is the DJ queue. "
"Use the command {}dj to join this queue".format(ctx.prefix))
return
# Ensure the user is in the voice channel
try:
if ctx.message.author.voice.channel != ctx.message.guild.me.voice.channel:
await ctx.send("You need to be in the channel to use this command!")
return
except AttributeError:
await ctx.send("You need to be in the channel to use this command!")
return
song = re.sub('[<>\[\]]', '', song)
await self.import_playlist(song, ctx)
@commands.command()
@commands.guild_only()
@utils.custom_perms(send_messages=True)
@ -462,8 +518,10 @@ class Music:
try:
if ctx.message.author.voice.channel != ctx.message.guild.me.voice.channel:
await ctx.send("You need to be in the channel to use this command!")
return
except AttributeError:
await ctx.send("You need to be in the channel to use this command!")
return
song = re.sub('[<>\[\]]', '', song)
if len(song) == 11:
@ -472,12 +530,17 @@ class Music:
# Youtube will still succeed if this *is* an ID provided, if there's a . after
song += "."
try:
msg = await ctx.send("Looking up {}...".format(song))
except:
msg = None
try:
entry = await self.add_entry(song, ctx)
except LiveStreamError as e:
await ctx.send(str(e))
except WrongEntryTypeError:
await ctx.send("Cannot enqueue playlists at this time.")
await ctx.send("Please use the {}import command to import a playlist.".format(ctx.prefix))
except ExtractionError as e:
error = e.message.split('\n')
if len(error) >= 3:
@ -496,9 +559,12 @@ class Music:
if entry is None:
await ctx.send("Sorry but I couldn't download/find {}".format(song))
else:
embed = entry.to_embed()
embed = entry.embed
embed.title = "Enqueued song!"
await ctx.send(embed=embed)
try:
await msg.edit(content=None, embed=embed)
except:
await ctx.send(embed=embed)
except discord.Forbidden:
pass
@ -727,7 +793,7 @@ class Music:
fmt = "{0[0]}m {0[1]}s/{1[0]}m {1[1]}s".format(progress, length)
embed.add_field(name='Progress', value=fmt, inline=False)
# And send the embed
await ctx.send(embed=embed)
await ctx.send(embed=embed)
@commands.command()
@commands.guild_only()