import discord
from discord.ext import commands
from discord.ext import tasks
import yt_dlp
import asyncio
from dotenv import load_dotenv
import os
import time
from collections import deque
from spotipy import Spotify
from spotipy.oauth2 import SpotifyClientCredentials
from imageio_ffmpeg import get_ffmpeg_exe
ffmpeg_path = get_ffmpeg_exe()
ffmpeg_options = {
'executable': ffmpeg_path,
'options': '-vn'
}
load_dotenv()
TOKEN = os.getenv("MTM3NTYzOTU1MTQ1MTg2MDk5Mg.GAAlil.XDbRE4iYEdgLCqK8QmLpKS2VoyKr2JqYPGXiDE")
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="!", intents=intents)
SPOTIFY_CLIENT_ID = "35fa18c25bd24041af97e3f8f0b27d84"
SPOTIFY_CLIENT_SECRET = "3ca1783aac3c4f87ade7faab25ce6373"
spotify = Spotify(client_credentials_manager=SpotifyClientCredentials(
client_id=SPOTIFY_CLIENT_ID,
client_secret=SPOTIFY_CLIENT_SECRET
))
voice_clients = {}
yt_dl_options = {"format": "bestaudio/best"}
ytdl = yt_dlp.YoutubeDL(yt_dl_options)
ffmpeg_options = {'options': '-vn'}
queues = {}
last_played_time = {}
@tasks.loop(minutes=1)
async def check_inactivity():
current_time = time.time()
for guild_id, last_time in list(last_played_time.items()):
if current_time - last_time > 300:
if guild_id in voice_clients:
voice_clients[guild_id].stop()
await voice_clients[guild_id].disconnect()
del voice_clients[guild_id]
del queues[guild_id]
del last_played_time[guild_id]
print(f"Disconnected from guild {guild_id} due to inactivity.")
@bot.event
async def on_ready():
print(f'{bot.user} is now online and ready!')
check_inactivity.start()
async def play_next(ctx):
if ctx.guild.id in queues and queues[ctx.guild.id]:
next_song = queues[ctx.guild.id].popleft()
song_url = next_song["url"]
title = next_song["title"]
player = discord.FFmpegPCMAudio(song_url, **ffmpeg_options)
voice_clients[ctx.guild.id].play(player, after=lambda e: bot.loop.create_task(play_next(ctx)))
await ctx.send(f"Now playing: {title}")
last_played_time[ctx.guild.id] = time.time()
else:
last_played_time[ctx.guild.id] = time.time()
@bot.command(name="play", help="Plays audio from a YouTube or Spotify URL")
async def play(ctx, url: str):
try:
if not ctx.author.voice:
await ctx.send("You must be connected to a voice channel to play music.")
return
if ctx.guild.id not in voice_clients or not voice_clients[ctx.guild.id].is_connected():
voice_client = await ctx.author.voice.channel.connect()
voice_clients[ctx.guild.id] = voice_client
if "spotify.com" in url:
if "track" in url:
track = spotify.track(url)
query = f"{track['name']} {track['artists'][0]['name']}"
elif "playlist" in url:
playlist = spotify.playlist(url)
for item in playlist["tracks"]["items"]:
track = item["track"]
query = f"{track['name']} {track['artists'][0]['name']}"
await add_to_queue(ctx, query)
await ctx.send("All songs in the playlist have been added to the queue.")
return
else:
await ctx.send("Unsupported Spotify URL.")
return
else:
query = url
await add_to_queue(ctx, query)
except Exception as e:
print(e)
await ctx.send("An error occurred while trying to play the song.")
async def add_to_queue(ctx, query):
try:
loop = asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(f"ytsearch:{query}", download=False))
if "entries" in data:
data = data["entries"][0]
song_url = data["url"]
title = data["title"]
if ctx.guild.id not in queues:
queues[ctx.guild.id] = deque()
queues[ctx.guild.id].append({"url": song_url, "title": title})
await ctx.send(f"Added to queue: {title}")
if not voice_clients[ctx.guild.id].is_playing():
await play_next(ctx)
except Exception as e:
print(e)
await ctx.send("An error occurred while trying to add the song to the queue.")
@bot.command(name="skip", help="Skips the current song")
async def skip(ctx):
if ctx.guild.id in voice_clients and voice_clients[ctx.guild.id].is_playing():
voice_clients[ctx.guild.id].stop()
await play_next(ctx)
await ctx.send("Skipped to the next song!")
else:
await ctx.send("No song is currently playing.")
is_looping = False
async def loop(ctx):
global is_looping
await ctx.send(f" Now looping{ 'enable' if is_looping else 'disabled'})
# Stop command
@bot.command(name="stop", help="Stops the audio and disconnects from the voice channel")
async def stop(ctx):
try:
if ctx.guild.id in voice_clients:
voice_clients[ctx.guild.id].stop()
await voice_clients[ctx.guild.id].disconnect()
del voice_clients[ctx.guild.id]
del queues[ctx.guild.id]
del last_played_time[ctx.guild.id] # Remove from tracking
await ctx.send("Disconnected from the voice channel.")
else:
await ctx.send("I am not connected to any voice channel.")
except Exception as e:
print(e)
await ctx.send("An error occurred while trying to stop the audio.")
# Run the bot
bot.run("MTM3NTYzOTU1MTQ1MTg2MDk5Mg.GAAlil.XDbRE4iYEdgLCqK8QmLpKS2VoyKr2JqYPGXiDE")