diff --git a/cogs/music/main.py b/cogs/music/main.py index 0bda551..682ddf9 100644 --- a/cogs/music/main.py +++ b/cogs/music/main.py @@ -92,7 +92,7 @@ class music(commands.Cog): async with ctx.typing(): #TODO potentially save requests before getting stream link # Grab video details such as title thumbnail duration - audio = translate.main(url, self.sp) + audio = await translate.main(url, self.sp) await msg.delete() @@ -103,8 +103,16 @@ class music(commands.Cog): #TODO make sure user isn't queuing in dm for some stupid reason - for song in audio: - song['position'] = await queue.add_song( + + # Setup first song's position + audio[0]['position'] = await queue.add_song( + server, + audio[0], + ctx.author.display_name) + + # Add any other songs + for song in audio[1:]: + await queue.add_song( server, song, ctx.author.display_name) @@ -164,7 +172,7 @@ class music(commands.Cog): # Skip specificed number of songs for _ in range(n-1): - await queue.pop(server.id) + await queue.pop(server.id, True) # Safe to ignore error for now ctx.voice_client.stop() \ No newline at end of file diff --git a/cogs/music/queue.py b/cogs/music/queue.py index 2c6d9a7..ad5f087 100644 --- a/cogs/music/queue.py +++ b/cogs/music/queue.py @@ -4,6 +4,8 @@ import sqlite3 import discord import asyncio +from .translate import search_song + db_path = "./data/music.db" FFMPEG_OPTS = { @@ -62,22 +64,40 @@ async def add_song(server_id, details, queued_by): max_order_num = await get_max(server_id, cursor) + 1 - cursor.execute(""" - INSERT INTO songs (server_id, - song_link, - queued_by, - position, - title, - thumbnail, - duration) - VALUES (?, ?, ?, ?, ?, ?, ?) - """, (server_id, - details['url'], - queued_by, - max_order_num, - details['title'], - details['thumbnail'], - details['duration'])) + if isinstance(details, str): + cursor.execute(""" + INSERT INTO songs (server_id, + song_link, + queued_by, + position, + title, + thumbnail, + duration) + VALUES (?, ?, ?, ?, ?, ?, ?) + """, (server_id, + "Not grabbed", + queued_by, + max_order_num, + details, + "Unkown", + "Unkown")) + else: + cursor.execute(""" + INSERT INTO songs (server_id, + song_link, + queued_by, + position, + title, + thumbnail, + duration) + VALUES (?, ?, ?, ?, ?, ?, ?) + """, (server_id, + details['url'], + queued_by, + max_order_num, + details['title'], + details['thumbnail'], + details['duration'])) conn.commit() conn.close() @@ -86,7 +106,7 @@ async def add_song(server_id, details, queued_by): # Pop song from server -async def pop(server_id): +async def pop(server_id, ignore=False): # Connect to db conn = sqlite3.connect(db_path) cursor = conn.cursor() @@ -106,6 +126,20 @@ async def pop(server_id): if result == None: return None + elif ignore: + await mark_song_as_finished(server_id, result[3]) + return None + elif result[1] == "Not grabbed": + # Fetch song info + song = await search_song(result[4]) + if song == []: + return None + else: + song = song[0] + + await set_current_song(server_id, song['title']) + await mark_song_as_finished(server_id, result[3]) + return song['url'] await set_current_song(server_id, result[4]) await mark_song_as_finished(server_id, result[3]) @@ -286,6 +320,8 @@ class AstroPlayer(discord.FFmpegPCMAudio): def _kill_process(self): super()._kill_process() + if self.ctx.voice_client.is_playing(): + return asyncio.run(play(self.ctx)) # Play and loop songs in server @@ -305,5 +341,5 @@ async def play(ctx): return # else play next song and call play again - await ctx.voice_client.play( + ctx.voice_client.play( AstroPlayer(ctx, url, FFMPEG_OPTS)) \ No newline at end of file diff --git a/cogs/music/translate.py b/cogs/music/translate.py index 5cd0830..25cd858 100644 --- a/cogs/music/translate.py +++ b/cogs/music/translate.py @@ -10,20 +10,20 @@ ydl_opts = { 'ignoreerrors': True, } -def main(url, sp): +async def main(url, sp): #url = url.lower() # Check if link or search if url.startswith("https://") is False: - return search_song(url) + return await search_song(url) #TODO add better regex or something if 'spotify' in url: if 'track' in url: - return spotify_song(url, sp) + return await spotify_song(url, sp) elif 'playlist' in url: - return spotify_playlist(url, sp) + return await spotify_playlist(url, sp) soundcloud_song = 'soundcloud' in url and 'sets' not in url # Not implemented yet @@ -33,15 +33,15 @@ def main(url, sp): youtube_playlist = 'playlist?list=' in url if soundcloud_song or youtube_song: - return song_download(url) + return await song_download(url) if youtube_playlist: - return playlist_download(url) + return await playlist_download(url) return [] -def search_song(search): +async def search_song(search): with ytdlp.YoutubeDL(ydl_opts) as ydl: try: info = ydl.extract_info(f"ytsearch1:{search}", download=False) @@ -58,7 +58,7 @@ def search_song(search): return [data] -def spotify_song(url, sp): +async def spotify_song(url, sp): track = sp.track(url.split("/")[-1].split("?")[0]) search = "" @@ -72,10 +72,10 @@ def spotify_song(url, sp): # set search to name query = search + " - " + track['name'] - return search_song(query) + return await search_song(query) -def spotify_playlist(url, sp): +async def spotify_playlist(url, sp): # Get the playlist uri code code = url.split("/")[-1].split("?")[0] @@ -99,17 +99,27 @@ def spotify_playlist(url, sp): # Remove last column search = search[:-2] search += f" - {track['track']['name']}" + songs.append(search) - searched_result = search_song(search) - if searched_result == []: + #searched_result = search_song(search) + #if searched_result == []: + #continue + + #songs.append(searched_result[0]) + + while True: + search_result = await search_song(songs[0]) + if search_result == []: + songs.pop(0) continue - - songs.append(searched_result[0]) + else: + songs[0] = search_result[0] + break return songs -def song_download(url): +async def song_download(url): with ytdlp.YoutubeDL(ydl_opts) as ydl: try: info = ydl.extract_info(url, download=False) @@ -125,7 +135,7 @@ def song_download(url): return [data] -def playlist_download(url): +async def playlist_download(url): with ytdlp.YoutubeDL(ydl_opts) as ydl: try: info = ydl.extract_info(url, download=False) diff --git a/cogs/music/util.py b/cogs/music/util.py index 530030f..000d2a2 100644 --- a/cogs/music/util.py +++ b/cogs/music/util.py @@ -20,10 +20,12 @@ async def join_vc(ctx: Context): # Join or move to the user's vc if ctx.voice_client is None: - await vc.connect() + vc = await vc.connect() else: # Safe to ignore type error for now - await ctx.voice_client.move_to(vc) + vc = await ctx.voice_client.move_to(vc) + + return vc # Leaving the voice channel of a user @@ -71,7 +73,12 @@ async def display_server_queue(ctx: Context, songs, n): display = f"🔊 Currently playing: ``{await queue.get_current_song(ctx.guild.id)}``\n\n" for i, song in enumerate(songs): - display += f"``{i + 1}.`` {song[0]} - {format_time(song[1])} Queued by {song[2]}\n" + + # If text is not avaialable do not display + time = '' if isinstance(song[1], str) else format_time(song[1]) + + display += f"``{i + 1}.`` {song[0]} - {time} Queued by {song[2]}\n" + msg.add_field(name="Songs:", value=display, inline=True)