From 84960e00eb1d9ae6b71fec9c3a9d0365e11f68fe Mon Sep 17 00:00:00 2001 From: Sweetbread Date: Tue, 9 May 2023 23:24:00 +0300 Subject: [PATCH] [feat]: Add queue command --- cogs/music.py | 90 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 36 deletions(-) diff --git a/cogs/music.py b/cogs/music.py index 960dc8e..5afa0e2 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -10,34 +10,32 @@ from discord.ext import commands from bot import db +FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'} +YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist':'True'} + # TODO: locale class Music(commands.Cog, name="Музыка"): def __init__(self, bot): self.bot = bot - self.query = {} + self.queue = {} - def play_(self, inter, url): - YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist':'True'} - FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'} - with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl: - info = ydl.extract_info(url, download=False) + def play_(self, inter, info): try: URL = info['url'] except: URL = url logger.debug(URL) - with open("tmp/tmp.log", 'w') as f: - f.write(dumps(info)) + audio_source = discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS) inter.guild.voice_client.play(audio_source, after=lambda error: self.next_(inter, error)) - asyncio.run_coroutine_threadsafe(self.send_embed_(inter, info, url), self.bot.loop) + asyncio.run_coroutine_threadsafe(self.send_embed_(inter, info), self.bot.loop) - async def send_embed_(self, inter, info, url): + async def send_embed_(self, inter, info): embed = discord.Embed ( title=info["title"], - url=url, + url=info['url'], description=info["description"] ) embed.set_author ( @@ -50,8 +48,8 @@ class Music(commands.Cog, name="Музыка"): except: await inter.channel.send(embed=embed) - async def end_of_query_(self, inter): - await inter.response.send_message("В очереди больше не осталось песен") + async def end_of_queue_(self, inter): + await inter.channel.send("В очереди больше не осталось песен") @app_commands.command(description="Plays music from popular platforms") @app_commands.describe(url="URL from Youtube/RuTube and other platforms") @@ -64,36 +62,36 @@ class Music(commands.Cog, name="Музыка"): return if inter.guild.voice_client is None: await channel.connect() + self.queue[channel.id] = { + "adder": inter.user.id, + "cur_pos": 0, + "queue": [], + "context": inter, + "skip_policy": "everyone" + } elif inter.user.voice.channel != inter.guild.voice_client.channel: await inter.response.send_message(f"Занято каналом {inter.guild.voice_client.channel.mention}") return client = inter.guild.voice_client - if url=="": - url = self.query[str(channel.id)][0] - del self.query[str(channel.id)][0] + with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl: + info = ydl.extract_info(url, download=False) - if str(channel.id) not in self.query.keys(): - self.query[str(channel.id)] = { - "requester_id": inter.user.id, - "music_pos": 0, - "query": [], - "context": inter - } - self.query[str(channel.id)]["query"].append(url) + self.queue[channel.id]["queue"].append({'requester': inter.user.id, 'url': url, 'info': info}) if client.is_playing() or client.is_paused(): - logger.debug("\n".join(self.query[str(channel.id)]['query'])) await inter.response.send_message("Добавлена новая песня в очередь") return else: inter.guild.voice_client.stop() - self.play_(inter, url) + self.play_(inter, info) @app_commands.command() async def stop(self, inter): + queue = self.queue[inter.user.voice.channel.id] + queue['cur_pos'] = len(queue['queue'])-1 inter.guild.voice_client.stop() await inter.response.send_message("Остановлено") @@ -114,21 +112,41 @@ class Music(commands.Cog, name="Музыка"): @app_commands.command() async def next(self, inter): - self.next_(inter) + inter.guild.voice_client.stop() + + @app_commands.command(name='queue') + async def _queue(self, inter): + queue = self.queue[inter.user.voice.channel.id] + text = '' + for pos, item in enumerate(queue['queue']): + if queue['cur_pos'] == pos: text += '>>> ' + else: text += ' ' + + text += f"{pos+1}. " + text += item['info']['title'] + text += '\n - Запросил: ' + self.bot.get_user(item['requester']).name + + text += '\n' + await inter.response.send_message(f"```\n{text}\n```") + def next_(self, inter, error=None): - logger.debug("\n....".join(["Query:"]+self.query[str(inter.user.voice.channel.id)]['query'])) + if error: + logger.error(error) + return inter.guild.voice_client.stop() - query = self.query[str(inter.user.voice.channel.id)] - query["music_pos"] = query["music_pos"] + 1 - logger.debug((len(query["query"]), query["music_pos"])) - if len(query["query"]) == query["music_pos"]: - asyncio.run_coroutine_threadsafe(self.end_of_query_(inter), self.bot.loop) - logger.debug([query["music_pos"]]) - url = query["query"][query["music_pos"]] - self.play_(inter, url) + queue = self.queue[inter.user.voice.channel.id] + queue["cur_pos"] += 1 + logger.debug((len(queue["queue"]), queue["cur_pos"])) + if len(queue["queue"]) == queue["cur_pos"]: + asyncio.run_coroutine_threadsafe(self.end_of_queue_(inter), self.bot.loop) + return + + #logger.debug([query["music_pos"]]) + info = queue["queue"][queue["cur_pos"]]['info'] + self.play_(inter, info) async def setup(bot):