9123144fe2
REF: Added in Terms of Services Code REF: Added in Data Privacy Code REF: Added the code needed for Selena to run DOC: launch.json is only for development
140 lines
5.7 KiB
Python
140 lines
5.7 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
from discord import app_commands
|
|
from yt_dlp import YoutubeDL
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
YTDL_OPTIONS = {
|
|
'format': 'bestaudio',
|
|
'noplaylist': 'True',
|
|
}
|
|
|
|
FFMPEG_OPTIONS = {
|
|
'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
|
'options': '-vn'
|
|
}
|
|
|
|
ytdl = YoutubeDL(YTDL_OPTIONS)
|
|
|
|
|
|
class Music(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
self.queue = []
|
|
self.is_playing = False
|
|
self.volume = 0.3
|
|
|
|
async def join(self, interaction: discord.Interaction):
|
|
channel = interaction.user.voice.channel
|
|
if interaction.guild.voice_client is None:
|
|
await channel.connect(self_deaf=True) # Join the channel deafened
|
|
await interaction.followup.send("Joined the voice channel.")
|
|
else:
|
|
await interaction.followup.send("Already in a voice channel.")
|
|
|
|
async def leave(self, interaction: discord.Interaction):
|
|
if interaction.guild.voice_client:
|
|
await interaction.guild.voice_client.disconnect()
|
|
await interaction.followup.send("Left the voice channel.")
|
|
else:
|
|
await interaction.followup.send("Not connected to a voice channel.")
|
|
|
|
async def play(self, interaction: discord.Interaction, search: str):
|
|
if not interaction.guild.voice_client:
|
|
await self.join(interaction)
|
|
|
|
info = ytdl.extract_info(f"ytsearch:{search}", download=False)['entries'][0]
|
|
url = info['url']
|
|
|
|
if interaction.guild.voice_client.is_playing():
|
|
self.queue.append((url, info['title']))
|
|
await interaction.followup.send(f'Queued: {info["title"]}')
|
|
else:
|
|
source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url, **FFMPEG_OPTIONS), volume=self.volume)
|
|
interaction.guild.voice_client.play(source, after=lambda e: self.bot.loop.create_task(self.play_next(interaction)))
|
|
self.is_playing = True
|
|
await interaction.followup.send(f'Playing: {info["title"]}')
|
|
|
|
async def play_next(self, interaction: discord.Interaction):
|
|
if self.queue:
|
|
url, title = self.queue.pop(0)
|
|
source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url, **FFMPEG_OPTIONS), volume=self.volume)
|
|
interaction.guild.voice_client.play(source, after=lambda e: self.bot.loop.create_task(self.play_next(interaction)))
|
|
await interaction.followup.send(f'Playing next: {title}')
|
|
else:
|
|
self.is_playing = False
|
|
|
|
async def pause(self, interaction: discord.Interaction):
|
|
if interaction.guild.voice_client.is_playing():
|
|
interaction.guild.voice_client.pause()
|
|
await interaction.followup.send("Paused the song.")
|
|
else:
|
|
await interaction.followup.send("No song is currently playing.")
|
|
|
|
async def resume(self, interaction: discord.Interaction):
|
|
if interaction.guild.voice_client.is_paused():
|
|
interaction.guild.voice_client.resume()
|
|
await interaction.followup.send("Resumed the song.")
|
|
else:
|
|
await interaction.followup.send("The song is not paused.")
|
|
|
|
async def stop(self, interaction: discord.Interaction):
|
|
if interaction.guild.voice_client.is_playing():
|
|
interaction.guild.voice_client.stop()
|
|
self.queue = []
|
|
await interaction.followup.send("Stopped the song.")
|
|
else:
|
|
await interaction.followup.send("No song is currently playing.")
|
|
|
|
async def set_volume(self, interaction: discord.Interaction, volume: float):
|
|
self.volume = volume
|
|
if interaction.guild.voice_client and interaction.guild.voice_client.source:
|
|
interaction.guild.voice_client.source.volume = self.volume
|
|
await interaction.followup.send(f"Volume set to {volume * 100}%.")
|
|
else:
|
|
await interaction.followup.send("No audio source found.")
|
|
|
|
def setup(self, tree: discord.app_commands.CommandTree):
|
|
@tree.command(name="join", description="Join the voice channel")
|
|
async def join_command(interaction: discord.Interaction):
|
|
await interaction.response.defer()
|
|
await self.join(interaction)
|
|
|
|
@tree.command(name="leave", description="Leave the voice channel")
|
|
async def leave_command(interaction: discord.Interaction):
|
|
await interaction.response.defer()
|
|
await self.leave(interaction)
|
|
|
|
@tree.command(name="play", description="Play a song from YouTube")
|
|
async def play_command(interaction: discord.Interaction, search: str):
|
|
await interaction.response.defer()
|
|
await self.play(interaction, search)
|
|
|
|
@tree.command(name="pause", description="Pause the current song")
|
|
async def pause_command(interaction: discord.Interaction):
|
|
await interaction.response.defer()
|
|
await self.pause(interaction)
|
|
|
|
@tree.command(name="resume", description="Resume the paused song")
|
|
async def resume_command(interaction: discord.Interaction):
|
|
await interaction.response.defer()
|
|
await self.resume(interaction)
|
|
|
|
@tree.command(name="stop", description="Stop the current song")
|
|
async def stop_command(interaction: discord.Interaction):
|
|
await interaction.response.defer()
|
|
await self.stop(interaction)
|
|
|
|
@tree.command(name="volume", description="Set the volume (0 to 1)")
|
|
async def volume_command(interaction: discord.Interaction, volume: float):
|
|
await interaction.response.defer()
|
|
await self.set_volume(interaction, volume)
|
|
|
|
|
|
def setup(bot):
|
|
music = Music(bot)
|
|
music.setup(bot.tree)
|