import nextcord from nextcord.ext import commands import yt_dlp import os import threading import time from main import client SquogPlaying = { } SquogVideo = { "verbose": True, 'final_ext': 'mp3', 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', }], "outtmpl": './music/%(uploader)s_%(title)s.%(ext)s', "quality": "low" } SquogCurrentConnection = None SquogDownload = yt_dlp.YoutubeDL(SquogVideo) class Voice(commands.Cog): def __init__(self, bot): self.client = bot @commands.command(description="Join the voice channel.") async def join(self, ctx: nextcord.Message): if not ctx.guild.voice_client: if ctx.author.voice: await ctx.author.voice.channel.connect() await ctx.reply("Joined.") else: await ctx.reply("Can't join as you aren't in any voice channel.") else: await ctx.reply("Can't join as i'm already in a voice channel.") @commands.command(description="Leaves the voice channel.") async def leave(self, ctx: nextcord.Message): if ctx.guild.voice_client: await ctx.guild.voice_client.disconnect(force=True) await ctx.reply("Left.") SquogPlaying[ctx.guild.id] = False else: await ctx.reply("Can't leave as i'm not in any voice channel.") @commands.command(description="Plays music in the voice channel.", usage={"link"}) async def play(self, ctx: nextcord.Message, link, loop: bool | None): if not ctx.guild.voice_client: return await ctx.reply("I'm not in a voice channel.") if ctx.guild.voice_client.is_playing(): return await ctx.reply("I'm already playing music.") # Extracting info for the filename if loop: SquogPlaying[ctx.guild.id] = True SquogInfo = SquogDownload.extract_info(link, download=False) Embed = nextcord.Embed(title="Loading music", description=SquogDownload.prepare_filename(SquogInfo)) # Notifying the user that music is getting started so they know its there await ctx.reply(embed=Embed) SquogVoiceClient = ctx.guild.voice_client # Function I will pass to the thread def Process(): #Downloading the music SquogDownload.download(link) #Getting the filename again SquogFinalName = SquogDownload.prepare_filename(SquogInfo) #Getting the file extension (webp, mp4) SquogExt = os.path.splitext(SquogFinalName) #Finding the file length without the extension SquogLength = SquogFinalName.find(SquogExt[1]) + 1 #Convering the extension to mp3 because #yt-dlp returns the original filename instead of the converted one SquogEvilFilename = f"{SquogFinalName[:SquogLength]}mp3" #Starting the music if ctx.guild.id in SquogPlaying and SquogPlaying[ctx.guild.id]: while SquogPlaying[ctx.guild.id]: SquogVoiceClient.play(nextcord.FFmpegPCMAudio(f"{SquogEvilFilename}")) while SquogVoiceClient.is_playing(): time.sleep(.2) else: SquogVoiceClient.play(nextcord.FFmpegPCMAudio(f"{SquogEvilFilename}")) # I've to start this in a different thread because of how long some videos take to load... threading.Thread(target=Process).start() return None @commands.command(description="Stops the music in voice channel") async def stop(self, ctx: nextcord.Message): if not ctx.guild.voice_client: return await ctx.reply("I'm not in a voice channel.") if not ctx.guild.voice_client.is_playing(): return await ctx.reply("I'm not playing music.") ctx.guild.voice_client.stop() SquogPlaying[ctx.guild.id] = False return None @client.event async def on_voice_state_update(member: nextcord.Member, before: nextcord.VoiceState, after: nextcord.VoiceState): if before.channel and not after.channel: if before.channel.members.__len__() == 1 and member.guild.voice_client and member.guild.voice_client.channel == before.channel: await before.channel.guild.voice_client.disconnect(force=True) def setup(bot): bot.add_cog(Voice(bot))