目前,我一直在为 Discord 编写一个机器人。
我已经设法让它根据给定的搜索字词查询 YouTube,然后从顶部结果中播放音频,但是当我尝试在列表中排队音轨并在音频流完成后播放它们时遇到了一个问题.
const API_KEY = "<my API Key>";
var discord = require("discord.js");
var ytdl = require('ytdl-core');
var request = require('superagent');
var bot = new discord.Client();
var voiceChannel = null;
var ytAudioQueue = [];
bot.on('ready', function() {
console.log('I am ready');
});
bot.on('message', function(message) {
var messageParts = message.content.split(' ');
var command = messageParts[0].toLowerCase();
var parameters = messageParts.splice(1, messageParts.length);
console.log("command: " + command);
console.log("parameters: " + parameters);
switch (command) {
case "hi":
message.reply("Hey there!");
break;
case "*help":
HelpCommand(message);
break;
case "*join":
message.reply("Attempting to join channel: " + parameters[0]);
JoinCommand(parameters[0], message);
break;
case "*play":
PlayCommand(parameters.join(" "), message);
break;
}
});
voiceChannel.on('speaking', (user, speaking) => {
// the audio has finished playing, so remove it from the queue and start playing the next song
if (!speaking && ytAudioQueue.length > 1) {
ytAudioQueue.pop();
if (voiceChannel == null) {
JoinCommand(bot.channels.find(val => val.type === 'voice').name).then(function() {
PlayStream(ytAudioQueue.first);
});
}
else {
PlayStream(ytAudioQueue.first);
}
}
});
/* COMMAND HANDLERS */
/// lists out all of the bot commands
function HelpCommand(originalMessage) {
originalMessage.reply("*join <channel-to-join> - Connects to bot to a channel by channel name");
originalMessage.reply("*play <YouTube search term> - Plays audio from YouTube based on the search term");
}
/// plays audio based on results from youtube search
function PlayCommand(searchTerm) {
//bot.sendMessage("Searching Youtube for audio...");
YoutubeSearch(searchTerm);
}
/// joins the bot to the specified voice channel
function JoinCommand(channelName) {
if (voiceChannel) {
voiceChannel.disconnet();
}
var voiceChannel = GetChannelByName(channelName);
return voiceChannel.join();
}
/* END COMMAND HANDLERS */
/* HELPER METHODS */
/// returns the channel that matches the name provided
function GetChannelByName(name) {
var channel = bot.channels.find(val => val.name === name);
return channel;
}
function YoutubeSearch(searchKeywords) {
var requestUrl = 'https://www.googleapis.com/youtube/v3/search' + `?part=snippet&q=${escape(searchKeywords)}&key=${API_KEY}`;
request(requestUrl, (error, response) => {
if (!error && response.statusCode == 200) {
var body = response.body;
if (body.items.length == 0) {
console.log("Your search gave 0 results");
return videoId;
}
for (var item of body.items) {
if (item.id.kind === 'youtube#video') {
QueueYtAudioStream(item.id.videoId);
}
}
}
else {
console.log("Unexpected error when searching YouTube");
return null;
}
});
return null;
}
/// Queues result of Youtube search into stream
function QueueYtAudioStream(videoId) {
var streamUrl = `https://www.youtube.com/watch?v=${videoId}`;
ytAudioQueue.push(streamUrl);
}
// plays a given stream
function PlayStream(streamUrl) {
const streamOptions = {seek: 0, volume: 1};
console.log("Streaming audio from " + streamUrl);
if (streamUrl) {
const stream = ytdl(streamUrl, {filter: 'audioonly'});
const dispatcher = bot.voiceConnections.first().playStream(stream, streamOptions);
}
}
/* END HELPER METHODS */
bot.login("<BOT LOGIN ID HERE>");
https://jsfiddle.net/o3Lvqt94/
我的想法是,一旦voiceChannel停止讲话,我就可以开始播放下一个audioStream,但是由于未在启动时设置,因此事件失败,虽然我可以这样做,但我认为它不适合我作为语音通道的需求可以用另一个命令来改变。