I created this music bot and I want to improve my queue command because it isn't very functionnal at the moment. Every time that I queue a song I have to use the play command to play it, but I want to play automatically the next song, also it would be cool to implement the queue command into the play command but I've no idea on how to do it. Can you please help??
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes
}
ffmpeg_options = {
'options': '-vn'
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
@classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
# take first item from a playlist
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
queue = []
@client.command(name='queue', help='This command adds a song to the queue')
async def queue_(ctx, url):
global queue
queue.append(url)
await ctx.send(f'`{url}` added to queue!')
@client.command(name='play', help='This command plays songs')
async def play(ctx):
global queue
server = ctx.message.guild
voice_channel = server.voice_client
async with ctx.typing():
player = await YTDLSource.from_url(queue[0], loop=client.loop, stream=True)
voice_channel.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('**Now playing:** {}'.format(player.title))
del(queue[0])
Edit: So I tried to do something like this but it doesn't work, when I try to use !play when a song is playing it doesn't put it in the queue, it says that:ClientException: Already playing audio.
When the song is finished it says that: TypeError: next() missing 2 required positional arguments: 'queue' and 'song'
This is the code:
queue = []
def next(client, queue, song):
if len(queue)>0:
new_song= queue[0]
del queue[0]
play(client, queue, new_song)
@bot.command()
async def join (ctx):
member = ctx.author
if not ctx.message.author.voice:
await ctx.send(f"{member.mention} You are not connected to a voice channel ❌")
else:
channel=ctx.message.author.voice.channel
await channel.connect()
@bot.command(help="This command plays a song.")
async def play (ctx,*args):
server = ctx.message.guild
voice_channel= server.voice_client
url=""
for word in args:
url+=word
url+=''
async with ctx.typing():
player = await YTDLSource.from_url(url ,loop=bot.loop, stream=True)
queue.append(player)
voice_channel.play (player, after=lambda e: next(ctx))
await ctx.send(f"**Now playing:** {player.title}")