You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord音乐机器人join命令失效及播放列表/队列功能添加求助

Discord音乐机器人问题修复与功能扩展

一、修复"Command 'join' is not found"错误

这个问题核心是你的Cog未被正确加载到机器人客户端,或主文件配置缺失,具体修复步骤如下:

  1. 确保Cog被正确加载

    • 如果音乐Cog代码单独存放在music.py中,主文件(如main.py)需显式加载扩展:
      import discord
      from discord.ext import commands
      
      # 启用必要权限,否则无法读取命令或获取语音频道信息
      intents = discord.Intents.default()
      intents.message_content = True
      intents.voice_states = True
      
      client = commands.Bot(command_prefix='?', intents=intents)
      
      @client.event
      async def on_ready():
          print(f'Logged in as {client.user}')
          # 加载音乐Cog
          await client.load_extension('music')  # 'music'为Cog文件名(不含.py)
      
      client.run('你的机器人Token')
      
    • 若所有代码在同一文件,需在创建客户端后手动调用setup函数:
      # ... 你的music Cog代码 ...
      
      intents = discord.Intents.default()
      intents.message_content = True
      intents.voice_states = True
      
      client = commands.Bot(command_prefix='?', intents=intents)
      
      # 加载Cog
      setup(client)
      
      @client.event
      async def on_ready():
          print(f'Logged in as {client.user}')
      
      client.run('你的机器人Token')
      
  2. 检查Discord开发者门户权限
    确保在开发者门户中启用Message Content Intent和Voice States Intent,否则机器人无法正常读取命令或获取语音状态。

二、添加队列与播放列表功能

以下是基于你原有代码扩展的完整实现:

import discord
from discord.ext import commands
import youtube_dl
from collections import deque

class music(commands.Cog):
    def __init__(self, client):
        self.client = client
        self.queue = deque()  # 用双端队列存储待播放歌曲

    @commands.command()
    async def join(self,ctx):
        if ctx.author.voice is None:
            await ctx.send("You're not in a voice channel!")
        voice_channel = ctx.author.voice.channel
        if ctx.voice_client is None:
            await voice_channel.connect()
        else:
            await ctx.voice_client.move_to(voice_channel)

    @commands.command()
    async def disconnect(self,ctx):
        await ctx.voice_client.disconnect()

    @commands.command()
    async def play(self, ctx, *, url):
        # 检查用户是否在语音频道
        if ctx.author.voice is None:
            await ctx.send("You're not in a voice channel!")
            return
        # 机器人不在频道则自动加入
        if ctx.voice_client is None:
            await ctx.author.voice.channel.connect()
        
        FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
        YDL_OPTIONS = {'format': "bestaudio", 'extract_flat': True}  # extract_flat用于解析播放列表

        with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
            info = ydl.extract_info(url, download=False)
            # 判断是否为播放列表
            if 'entries' in info:
                # 遍历添加所有列表歌曲到队列
                valid_entries = [entry for entry in info['entries'] if entry]
                for entry in valid_entries:
                    song_url = entry['url'] if 'url' in entry else entry['webpage_url']
                    self.queue.append((song_url, entry['title']))
                await ctx.send(f"Added {len(valid_entries)} songs from playlist to queue!")
            else:
                # 单首歌曲加入队列
                song_url = info['url'] if 'url' in info else info['webpage_url']
                self.queue.append((song_url, info['title']))
                await ctx.send(f"Added '{info['title']}' to queue!")
        
        # 当前无播放任务则启动播放
        if not ctx.voice_client.is_playing():
            await self.play_next(ctx)

    async def play_next(self, ctx):
        if self.queue:
            song_url, song_title = self.queue.popleft()
            FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
            source = await discord.FFmpegOpusAudio.from_probe(song_url, **FFMPEG_OPTIONS)
            # 播放完成后自动触发下一首
            ctx.voice_client.play(source, after=lambda e: self.client.loop.create_task(self.play_next(ctx)))
            await ctx.send(f"Now playing: '{song_title}'")
        else:
            await ctx.send("Queue is empty! No more songs to play.")

    @commands.command()
    async def skip(self, ctx):
        if ctx.voice_client and ctx.voice_client.is_playing():
            ctx.voice_client.stop()
            await ctx.send("Skipped current song!")
        else:
            await ctx.send("No song is playing right now!")

    @commands.command()
    async def queue(self, ctx):
        if not self.queue:
            await ctx.send("Queue is empty!")
            return
        # 格式化队列信息
        queue_msg = "Current queue:\n"
        for idx, (_, title) in enumerate(self.queue, 1):
            queue_msg += f"{idx}. '{title}'\n"
        await ctx.send(queue_msg)

    @commands.command()
    async def pause(self,ctx):
        await ctx.voice_client.pause()
        await ctx.channel.send("Paused")
    
    @commands.command()
    async def resume(self,ctx):
        await ctx.voice_client.resume()
        await ctx.channel.send("Resume")

def setup(client):
    client.add_cog(music(client))

功能说明

  • 队列管理:用deque实现高效的歌曲入队/出队,支持查看队列(?queue)、跳过歌曲(?skip)
  • 播放列表解析:自动识别YouTube播放列表,将所有歌曲批量加入队列
  • 自动续播:当前歌曲播放完成后,自动播放队列中的下一首

内容的提问来源于stack exchange,提问作者Him

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 06:55:16