我现在一直在编写一个 discord bot,在过去的两天里,我的 discord.py 编码技能有了很大的提高,这让我开始编写一个音乐机器人。我有一个预制的代码并尝试成功理解它,现在已经编写了我自己的代码。现在我快完成了(我认为)并且显然存在问题。我的代码多次包含 vc.is_playing 但不知何故它在 play_ 命令中不起作用。我的代码:
@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)
如你所见,我在代码底部有“停止”命令,“vc.is_playing”在那里工作。但是当我在“_play”中使用它时,它不起作用!这里的错误信息:
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'
这是第一个问题。第二个问题是,当 while 循环应该运行时,机器人什么都不做…… [!] 我在 repl.it/replit.com 上运行这个机器人
答案 0 :(得分:1)
我还没有真正搞砸discord.py
的音乐部分,但修复应该很容易。
在第一个 if 语句中,您正在检查 vc
是否为 NoneType
,您还应该在其中定义 vc
(因为您没有退出函数)
if not vc:
channel = ctx.author.voice.channel
vc = await channel.connect()
答案 1 :(得分:0)
显然我必须制作第二个 vc = ...,但我必须以不同的方式命名。
现在是:
@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