运行播放命令时未定义的歌曲

Posted

技术标签:

【中文标题】运行播放命令时未定义的歌曲【英文标题】:undefined song when I run the play command 【发布时间】:2021-07-01 05:18:16 【问题描述】:

我正在尝试使用yt-search 构建一个音乐不和谐机器人,但每当我播放歌曲时它都会给我undefined,它会在不播放歌曲的情况下加入语音频道。我正在尝试使用yt-search 来查找我想要的视频,或者仅使用URL 然后将其传递给ytdl 以使用yt-search 提供的URL 运行它,但我认为我在某些方面是错误的。我不知道在哪里,你能修复我的代码吗?

显示问题的图片:

我的代码:

const Discord = require("discord.js");
const  prefix, token  = require("./config.json");
const ytdl = require("ytdl-core");
const yts = require("yt-search");

const client = new Discord.Client();

const queue = new Map();

client.once("ready", () => 
  console.log("Ready!");
);

client.once("reconnecting", () => 
  console.log("Reconnecting!");
);

client.once("disconnect", () => 
  console.log("Disconnect!");
);

client.on("message", async message => 
  if (message.author.bot) return;
  if (!message.content.startsWith(prefix)) return;

  const serverQueue = queue.get(message.guild.id);

  if (message.content.startsWith(`$prefixplay`)) 
    execute(message, serverQueue);
    return;
   else if (message.content.startsWith(`$prefixskip`)) 
    skip(message, serverQueue);
    return;
   else if (message.content.startsWith(`$prefixstop`)) 
    stop(message, serverQueue);
    return;
   else 
    message.channel.send("You need to enter a valid command!");
  
);

async function execute(message, serverQueue) 
  const args = message.content.split(" ");

  const voiceChannel = message.member.voice.channel;
  if (!voiceChannel)
    return message.channel.send(
      "You need to be in a voice channel to play music!"
    );
  const permissions = voiceChannel.permissionsFor(message.client.user);
  if (!permissions.has("CONNECT") || !permissions.has("SPEAK")) 
    return message.channel.send(
      "I need the permissions to join and speak in your voice channel!"
    );
  
  const r = await yts(args[1,2]);
  const video = r.videos.slice( 0, 1 );
  console.log(video);
  const songInfo = await ytdl.getInfo(video.url);
  const song = 
        title: songInfo.videoDetails.title,
        url: songInfo.videoDetails.video_url,
   ;

  if (!serverQueue) 
    const queueContruct = 
      textChannel: message.channel,
      voiceChannel: voiceChannel,
      connection: null,
      songs: [],
      volume: 5,
      playing: true
    ;

    queue.set(message.guild.id, queueContruct);

    queueContruct.songs.push(song);

    try 
      var connection = await voiceChannel.join();
      queueContruct.connection = connection;
      play(message.guild, queueContruct.songs[0]);
     catch (err) 
      console.log(err);
      queue.delete(message.guild.id);
      return message.channel.send(err);
    
   else 
    serverQueue.songs.push(song);
    return message.channel.send(`$song.title has been added to the queue!`);
  


function skip(message, serverQueue) 
  if (!message.member.voice.channel)
    return message.channel.send(
      "You have to be in a voice channel to stop the music!"
    );
  if (!serverQueue)
    return message.channel.send("There is no song that I could skip!");
  serverQueue.connection.dispatcher.end();


function stop(message, serverQueue) 
  if (!message.member.voice.channel)
    return message.channel.send(
      "You have to be in a voice channel to stop the music!"
    );
    
  if (!serverQueue)
    return message.channel.send("There is no song that I could stop!");
    
  serverQueue.songs = [];
  serverQueue.connection.dispatcher.end();


function play(guild, song) 
  const serverQueue = queue.get(guild.id);
  if (!song) 
    serverQueue.voiceChannel.leave();
    queue.delete(guild.id);
    return;
  

  const dispatcher = serverQueue.connection
    .play(ytdl(song.url))
    .on("finish", () => 
      serverQueue.songs.shift();
      play(guild, serverQueue.songs[0]);
    )
    .on("error", error => console.error(error));
  dispatcher.setVolumeLogarithmic(serverQueue.volume / 5);
  serverQueue.textChannel.send(`Start playing: **$song.title**`);


client.login(token);

【问题讨论】:

【参考方案1】:

有两个错误。我不确定您认为args[1,2] 是什么,但它与args[2] 相同,后者是args 数组的第三项。通过阅读您的代码,我认为您想在这里使用一个字符串,即搜索词。通过从args 数组中删除第一项(命令)并加入其余项,您将收到一个可以用作关键字的字符串。看看下面的例子:

const message =  content: '!play some music I want'
const args = message.content.split(' ')

console.log( args )
// => ["!play", "some", "music", "I", "want"]
console.log( 'args[1, 2]': args[1, 2] )
// => "music"
console.log( 'search': args.slice(1).join(' ') )
// => "some music I want"

另一个错误是await yts(query) 返回一个结果数组,当您定义video 变量时,您使用r.videos.slice(0, 1).slice() 方法返回一个新数组,其中第一项为r.videos

由于video 变量是一个数组,video.url 是未定义的。您可以改用第一项来修复它,因为它将具有 url 属性。您还应该检查是否有任何搜索结果。

查看下面的更新代码:

async function execute(message, serverQueue) 
  const args = message.content.split(' ');

  const voiceChannel = message.member.voice.channel;
  if (!voiceChannel)
    return message.channel.send(
      'You need to be in a voice channel to play music!',
    );
  const permissions = voiceChannel.permissionsFor(message.client.user);
  if (!permissions.has('CONNECT') || !permissions.has('SPEAK')) 
    return message.channel.send(
      'I need the permissions to join and speak in your voice channel!',
    );
  
  const query = args.slice(1).join(' ');
  const results = await yts(query);

  if (!results.videos.length)
    return message.channel.send(`No results for \`$query\``);

  const firstVideo = results.videos[0];
  const songInfo = await ytdl.getInfo(firstVideo.url);
  const song = 
    title: songInfo.videoDetails.title,
    url: songInfo.videoDetails.video_url,
  ;
  console.log(song);

  if (!serverQueue) 
    // ...
    // ...

【讨论】:

以上是关于运行播放命令时未定义的歌曲的主要内容,如果未能解决你的问题,请参考以下文章

在 jenkins 的 Visual Studio for Linux 项目上运行 devenv 时未定义的远程主机

未捕获的类型错误:无法读取未定义的属性(读取“替换”)

尝试使用外部库时未定义的引用

运行 Jest 测试时未定义`regeneratorRuntime`

编译具有相同标头的 C 和 C++ 文件时未定义的引用

运行时未定义 ts-node 导入