Python 当其他命令正在运行时,Discord bot不接受命令

Python 当其他命令正在运行时,Discord bot不接受命令,python,asynchronous,urllib,discord.py,youtube-dl,Python,Asynchronous,Urllib,Discord.py,Youtube Dl,我正在开发一个discord机器人,它可以找到spotify播放列表,并将曲目的youtube对应项排队。我运行了一个循环,它使用一个tracknames列表在youtube上搜索视频,然后获取最重要的结果并发送给一个异步函数来播放它。但是,当bot处于该循环中时,它不接受其他命令。我可以使此命令与其他命令同时运行吗?下面是我申请的全部代码 from bs4 import BeautifulSoup import urllib.request import os import requests

我正在开发一个discord机器人,它可以找到spotify播放列表,并将曲目的youtube对应项排队。我运行了一个循环,它使用一个tracknames列表在youtube上搜索视频,然后获取最重要的结果并发送给一个异步函数来播放它。但是,当bot处于该循环中时,它不接受其他命令。我可以使此命令与其他命令同时运行吗?下面是我申请的全部代码

from bs4 import BeautifulSoup
import urllib.request
import os
import requests
import base64
import json
import time
import discord
import shutil
from discord.utils import get
from discord import FFmpegPCMAudio
import youtube_dl
import asyncio
from asgiref.sync import async_to_sync

from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

bot = commands.Bot(command_prefix='s- ')

accessToken = ""

clientIDSECRET = os.getenv('SPOTIFY_ID')+':'+os.getenv('SPOTIFY_SECRET')

base64Auth = base64.b64encode(clientIDSECRET.encode("utf-8")).decode('ascii')
trackStrings = []

def pretty_print_POST(req):
    print('{}\n{}\r\n{}\r\n\r\n{}'.format(
        '-----------START-----------',
        req.method + ' ' + req.url,
        '\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
        req.body,
    ))

@bot.event
async def on_ready():    
    payload={'grant_type':'client_credentials'}
    headers = {'Authorization':f'Basic {base64Auth}'}
    req = requests.Request('POST', "https://accounts.spotify.com/api/token", data = payload, headers = headers)
    prep = req.prepare()
    pretty_print_POST(prep)
    s = requests.Session()
    response = s.send(prep)
    global accessToken
    accessToken = json.loads(response.content)["access_token"]
    print(accessToken)

@bot.command(pass_context=True, aliases=['sp'])
async def spotlist(ctx, userName, playlistName = "", shuffle=False, limit=100, offset=0):
    print(limit)
    if limit > 100 or limit < 0:
        await ctx.send(f'Limit out of bounds! It needs to be between 0 and 100.')
        return
    playlistId = ""
    headers = {'Authorization':f'Bearer {accessToken}'}
    if playlistName == "id":
        playlistId = userName #Username assumed to be a playlist id instead
    else:
        playlists = json.loads(requests.get(f'https://api.spotify.com/v1/users/{userName}/playlists', headers=headers).content)
        for playlist in playlists["items"]:
            if playlist["name"] == playlistName:
                playlistId = playlist["id"]
    nextURL = f'https://api.spotify.com/v1/playlists/{playlistId}/tracks?offset={offset}&limit={limit}'
    while nextURL != None:
        trackResponse = requests.get(nextURL, headers = headers)
        tracks = json.loads(trackResponse.content)
        if(tracks["total"] <= offset):
            await ctx.send(f'Offset (third argument) is too large! Your playlist is {tracks["total"]} long.')
            return
        for track in tracks["items"]:
            trackStrings.append(track["track"]["name"] + " " + track["track"]["artists"][0]["name"])
        nextURL = tracks["next"]
        if(limit != 100):
            break

    for trackString in trackStrings:
        try:
            await play(ctx, await SearchVid(trackString))
        except:
            print("couldn't find song")

@bot.command(pass_context=True, aliases=['j', 'joi'])
async def join(ctx):
    channel = ctx.message.author.voice.channel
    voice = get(bot.voice_clients, guild=ctx.guild)

    if voice and voice.is_connected():
        await voice.move_to(channel)
    else:
        voice = await channel.connect()

@bot.command(pass_context=True, aliases=['l', 'lea'])
async def leave(ctx):
    voice = get(bot.voice_clients, guild=ctx.guild)

    if voice and voice.is_connected():
        await voice.disconnect()
    else:
        await ctx.send("Don't think I am in a voice channel")


async def playSong(ctx):   
    voice = get(bot.voice_clients, guild=ctx.guild)
    DIR = os.path.abspath(os.path.realpath("Queue"))

    try:
        first_file = os.listdir(DIR)[0]
    except:
        print("No more queued song(s)\n")
        return

    song_path = os.path.abspath(os.path.realpath("Queue") + "\\" + first_file)
    async def func(x):
        os.remove(song_path)
        await playSong(ctx)
    try:
        voice.play(discord.FFmpegPCMAudio(song_path), after=async_to_sync(func))
        await ctx.send(f"playing {first_file}")
        voice.source = discord.PCMVolumeTransformer(voice.source)
        voice.source.volume = 0.07
    except:
        print("song already playing")
    still_q = len(os.listdir(DIR))
    print(f"Songs still in queue: {still_q}")


@bot.command(pass_context=True, aliases=['p', 'pla'])
async def play(ctx, url: str = ""): 

    await join(ctx) 

    Queue_infile = os.path.isdir("./Queue")
    if Queue_infile is True:
        DIR = os.path.abspath(os.path.realpath("Queue"))
        try:
            _ = os.listdir(DIR)[0]
        except:
            print("No more queued song(s)\n")
            await queue(ctx, url)
            await playSong(ctx)
        else:
            await queue(ctx, url)
            await playSong(ctx)
    else:
        return

@bot.command(pass_context=True, aliases=['s'])
async def skip(ctx):
    await stop(ctx)

@bot.command(pass_context=True, aliases=['pa', 'pau'])
async def pause(ctx):

    voice = get(bot.voice_clients, guild=ctx.guild)

    if voice and voice.is_playing():
        print("Music paused")
        voice.pause()
        await ctx.send("Music paused")
    else:
        print("Music not playing failed pause")
        await ctx.send("Music not playing failed pause")


@bot.command(pass_context=True, aliases=['r', 'res'])
async def resume(ctx):

    voice = get(bot.voice_clients, guild=ctx.guild)

    if voice and voice.is_paused():
        print("Resumed music")
        voice.resume()
        await ctx.send("Resumed music")
    else:
        print("Music is not paused")
        await ctx.send("Music is not paused")

async def stop(ctx):

    voice = get(bot.voice_clients, guild=ctx.guild)

    if voice and voice.is_playing():
        voice.stop()
    else:
        print("No music playing failed to stop")


async def SearchVid(textToSearch):
    print(textToSearch)
    query = urllib.parse.quote(textToSearch)
    url = "https://www.youtube.com/results?search_query=" + query
    response = urllib.request.urlopen(url)
    html = response.read()
    soup = BeautifulSoup(html, 'html.parser')
    for vid in soup.findAll(attrs={'class':'yt-uix-tile-link'}):
        if not vid['href'].startswith("https://googleads.g.doubleclick.net/"):
            return 'https://www.youtube.com' + vid['href']

async def queue(ctx, url: str):
    Queue_infile = os.path.isdir("./Queue")
    if Queue_infile is False:
        os.mkdir("Queue")
    DIR = os.path.abspath(os.path.realpath("Queue"))
    q_num = len(os.listdir(DIR))

    queue_path = os.path.abspath(os.path.realpath("Queue") + f"\\{q_num} %(title)s.%(ext)s")
    print(queue_path)
    ydl_opts = {
        'format': 'bestaudio/best',
        'outtmpl': queue_path,
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }],
    }

    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        print("Downloading audio now\n")
        print(url)
        ydl.download([url])
        name = os.listdir(DIR)[-1]
        await ctx.send("Adding song " + str(name) + " to the queue")

    print("Song added to queue\n")

bot.run(TOKEN)
从bs4导入美化组
导入urllib.request
导入操作系统
导入请求
导入base64
导入json
导入时间
进口不和
进口舒蒂尔
从discord.utils导入获取
从discord导入ffmpegpcaudio
导入youtube\u dl
导入异步
从asgiref.sync导入异步到同步
从discord.ext导入命令
从dotenv导入加载\u dotenv
加载_dotenv()
TOKEN=os.getenv('DISCORD_TOKEN')
bot=commands.bot(命令前缀=s-)
accessToken=“”
clientIDSECRET=os.getenv('SPOTIFY_ID')+':'+os.getenv('SPOTIFY_SECRET'))
base64Auth=base64.b64encode(clientIDSECRET.encode(“utf-8”)).decode(“ascii”)
trackStrings=[]
def漂亮打印贴(要求):
打印({}\n{}\r\n{}\r\n{}\r\n\r\n{})。格式(
“---------开始----------”,
请求方法+“”+请求url,
“\r\n”.join(“{}:{}.”在req.headers.items()中为k,v设置格式(k,v),
请求主体,
))
@机器人事件
_ready()上的异步定义:
有效负载={'grant_type':'client_credentials'}
headers={'Authorization':f'Basic{base64Auth}}
req=请求。请求('POST','https://accounts.spotify.com/api/token,数据=有效负载,标题=标题)
prep=req.prepare()
漂亮的印刷术(准备)
s=请求。会话()
响应=发送(准备)
全局访问令牌
accessToken=json.loads(response.content)[“访问令牌”]
打印(accessToken)
@命令(pass_context=True,别名=['sp'])
异步def spotlist(ctx,用户名,playliName=“”,随机播放=False,限制=100,偏移量=0):
打印(限制)
如果限制>100或限制<0:
等待ctx.send(f'Limit out bounds!它需要介于0和100之间。)
返回
playlid=“”
headers={'Authorization':f'Bearer{accessToken}}
如果playlame==“id”:
playlaid=用户名#假定用户名为播放列表id
其他:
playlists=json.load(requests.get(f'https://api.spotify.com/v1/users/{userName}/playlists',headers=headers.content)
对于播放列表[“项目”]中的播放列表:
如果播放列表[“名称”]==播放名称:
playlid=播放列表[“id”]
nextURL=f'https://api.spotify.com/v1/playlists/{playlid}/曲目?偏移量={offset}&limit={limit}'
而下一个无:
trackResponse=requests.get(nextURL,headers=headers)
tracks=json.load(trackResponse.content)

如果(tracks[“total”],我肯定会建议使用模块线程。我目前没有足够的时间阅读您的代码并将其放入,尽管我可能稍后会编辑此答案。 参考:


线程允许您一次运行多个函数。

您使用的是阻塞库。Discord.py是一个异步库,您需要使用不会阻塞代码的东西。在中,您可以看到一个使用
请求
库的示例,这是阻塞,您应该使用它来生成异步请求。

谢谢,我来看看这是一个糟糕的建议。为什么在代码是异步的情况下使用线程?您需要使同步操作在代码中执行异步。