Discord bot在运行其他命令时不接受命令

问题描述 投票:0回答:1

我正在开发一个discord机器人,该机器人可以找到Spotify播放列表,并将曲目的youtube对应对象排队。我正在运行一个循环,该循环使用跟踪名称列表在youtube上搜索视频,然后获取最高结果并将其发送到播放该视频的异步函数。但是,尽管漫游器处于此循环中,但它不接受其他命令。我可以使其与其他命令同时运行吗?以下是我的应用程序的所有代码

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)
python asynchronous urllib discord.py youtube-dl
1个回答
0
投票

我肯定会建议使用模块线程。我目前没有足够的时间来阅读您的代码并将其放入,尽管我稍后可能会编辑此答案。参考:https://docs.python.org/3/library/threading.html

线程允许您一次运行多个功能。

© www.soinside.com 2019 - 2024. All rights reserved.