SquogBot/commands/voice.py
2025-05-07 15:06:16 +07:00

121 lines
4.5 KiB
Python

import nextcord
from nextcord.ext import commands
import yt_dlp
import os
import threading
import time
from main import client
SquogFinalName: str = None
SquogPlaying = {
}
SquogVideo = {
"verbose": True,
'final_ext': 'mp3',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
}],
"outtmpl": './music/%(uploader)s_%(title)s.%(ext)s',
"quality": "low"
}
SquogCurrentConnection: nextcord.VoiceClient = 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):
print("Joining")
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):
print("Leaving")
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
@client.event
async def on_voice_state_update(self, member: nextcord.Member, before: nextcord.VoiceState, after: nextcord.VoiceState | None):
print(self, member, before, after)
if before.channel and not after.channel:
print(f'{member} left a vc.')
if before.channel.members.__len__() == 0 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))