elai
elai

Reputation: 11

Discord music bot queue command, but vc.is_playing somehow doesn't work here?

I've now been coding a discord bot and over the last two days my discord.py coding skills have improved drastically which led me to coding a music bot. I had a pre made code and tried understanding it successfully and have coded now my own code. Now I'm almost finished (I think) and there apparently is a problem. My code includes vc.is_playing several times but somehow it doesn't work in the play_ command. My code:

@bot.command(name='play', aliases=['p'])
async def _play(ctx, url : str): #just the command
    queueurls = [] #the list where the incoming url's are stored
    vc = ctx.voice_client 
    if not vc: #if the bot is not in the channel...
      channel = ctx.author.voice.channel
      await channel.connect() #...then connect the bot the channel the author of the command is in
    url = ctx.message.content #the URL is just what the author of the command has written
    url = ttourl(url) #ttourl(url) is just a def to turn for example "!p Hello" into "Hello" and then into an YouTube URL (https://www.youtube.com/watch?v=video id)
    queueurls.append(url) #then apply that URL to the list above
    if not vc.is_playing(): #(HERE'S THE PROBLEM) when the bot isn't already playing anything...
      while queueurls != []: #go into the loop until the queueurls list is empty
        voice = discord.utils.get(bot.voice_clients, guild=ctx.guild)
        url = queueurls[0] #the url is the first item in the queueurls list
        queueurls.pop(0) #now erase that out of the list
        with youtube_dl.YoutubeDL(ytdlopts) as ydl: #and now download the video
          ydl.download([url])
        audio = "songstemp/song.mp3"
        voice.play(discord.FFmpegPCMAudio("songstemp/song.mp3")) #play that song
        time.sleep(audiosec(audio)) #wait until the song is finished...
        if os.path.exists("songstemp/song.mp3"): #...and then if the song is there...
          path = "songstemp/song.mp3"
          os.remove(path) #...delete it
    else: #if the bot is already playing something, then just do nothing, but the url is added to the list so the while loop should play the song when the other song is finished
      pass

  @bot.command(name="stop")
  async def stop_(ctx): #just the stop command
    vc = ctx.voice_client
    if vc.is_playing(): #here, is_playing works just fine.
      vc.stop()
      path = "songstemp/song.mp3"
      os.remove(path)

As you can see I have the command "stop" at the bottom of the code and the "vc.is_playing" works in there. But as I use it in the "_play", it does not work! Here the error message:

Ignoring exception in command play:
Traceback (most recent call last):
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "main.py", line 69, in _play
    if not vc.is_playing():
AttributeError: 'NoneType' object has no attribute 'is_playing'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'is_playing'

That is the first problem. The second problem is, that the bot is doing nothing, when the while loop should be running... [!] I am running this bot on repl.it / replit.com

Upvotes: 0

Views: 1199

Answers (2)

elai
elai

Reputation: 11

apparently I had to make a second vc = ..., but I had to name it differently.

So now It's:

@bot.command(name='play', aliases=['sing', 'p'])
async def _play(ctx, url : str):
    queueurls = []
    vc = ctx.voice_client #first definition of ctx.voice_client
    if not vc: #use first definition
      channel = ctx.author.voice.channel
      await channel.connect()
    url = ctx.message.content
    url = ttourl(url)
    queueurls.append(url)
    voicec = ctx.voice_client #second definition of ctx.voice_client
    if not voicec.is_playing(): #use second definition
      while queueurls != []:
        voice = discord.utils.get(bot.voice_clients, guild=ctx.guild)
        url = queueurls[0]
        queueurls.pop(0)
        with youtube_dl.YoutubeDL(ytdlopts) as ydl:
          ydl.download([url])
        voice.play(discord.FFmpegPCMAudio("songstemp/song.mp3"))
        if os.path.exists("songstemp/song.mp3"):
          path = "songstemp/song.mp3"
          os.remove(path)
    else:
      pass

Upvotes: 0

Łukasz Kwieciński
Łukasz Kwieciński

Reputation: 15728

I haven't really messed up with the music part of discord.py, but the fix should be pretty easy.

In the first if-statement, you're checking if vc is a NoneType, you should also define vc inside there (because you're not exiting of the function)

if not vc:
    channel = ctx.author.voice.channel
    vc = await channel.connect()

Upvotes: 1

Related Questions