I have been playing around in writing a bot for Discord at the moment.
I have managed to get it to query YouTube based given search terms and then play audio from the top result, however I have e across an issue when I am trying to to queue audio tracks in a list and play them once an audio stream has pleted.
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 mand = messageParts[0].toLowerCase();
var parameters = messageParts.splice(1, messageParts.length);
console.log("mand: " + mand);
console.log("parameters: " + parameters);
switch (mand) {
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 mands
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 = '' + `?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 = `=${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>");
/
My idea was that I could mence the playing of the next audioStream once the voiceChannel has stopped speaking, however the event fails as this is not set on startup, whilst I could do this I do not think it will suit my needs as the voice channel can be changed with another mand.
I have been playing around in writing a bot for Discord at the moment.
I have managed to get it to query YouTube based given search terms and then play audio from the top result, however I have e across an issue when I am trying to to queue audio tracks in a list and play them once an audio stream has pleted.
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 mand = messageParts[0].toLowerCase();
var parameters = messageParts.splice(1, messageParts.length);
console.log("mand: " + mand);
console.log("parameters: " + parameters);
switch (mand) {
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 mands
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./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./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/o3Lvqt94/
My idea was that I could mence the playing of the next audioStream once the voiceChannel has stopped speaking, however the event fails as this is not set on startup, whilst I could do this I do not think it will suit my needs as the voice channel can be changed with another mand.
Share Improve this question edited Oct 23, 2016 at 17:08 ReyAnthonyRenacia 17.6k6 gold badges41 silver badges63 bronze badges asked Oct 23, 2016 at 8:09 Matthew PigramMatthew Pigram 1,4305 gold badges28 silver badges67 bronze badges 03 Answers
Reset to default 1I used your code as a base for my own Discord bot and solved the bug you mentioned. I simply changed
dispatcher.on('end', () => {
PlayNextStreamInQueue();
});
to
dispatcher.on('end', () => {
dispatcher = null;
PlayNextStreamInQueue();
});
My solution.
index.js
var discord = require("discord.js"); // discord library
var ytdl = require('ytdl-core'); // youtube download library
var youtube = require('./youtube.js'); // performs youtube API requests
var bot = new discord.Client();
var ytAudioQueue = [];
var dispatcher = null;
bot.on('ready', function () {
console.log('I am ready');
});
bot.on('message', function (message) {
var messageParts = message.content.split(' ');
var mand = messageParts[0].toLowerCase();
var parameters = messageParts.splice(1, messageParts.length);
console.log("mand: " + mand);
console.log("parameters: " + parameters);
switch (mand) {
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]);
break;
case "*play":
PlayCommand(parameters.join(" "), message);
break;
case "*playqueue":
PlayQueueCommand(message);
break;
}
});
/* COMMAND HANDLERS */
/// lists out all of the bot mands
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");
originalMessage.reply("*playqueue - Lists the audio remaining in the play queue");
}
/// plays audio based on results from youtube search
function PlayCommand(searchTerm) {
// if not connected to a voice channel then connect to first one
if (bot.voiceConnections.array().length == 0) {
var defaultVoiceChannel = bot.channels.find(val => val.type === 'voice').name;
JoinCommand(defaultVoiceChannel);
}
// search youtube using the given search search term and perform callback action if video is found
youtube.search(searchTerm, QueueYtAudioStream);
}
/// lists out all music queued to play
function PlayQueueCommand(message) {
var queueString = "";
for(var x = 0; x < ytAudioQueue.length; x++) {
queueString += ytAudioQueue[x].videoName + ", ";
}
queueString = queueString.substring(0, queueString.length - 2);
message.reply(queueString);
}
/// joins the bot to the specified voice channel
function JoinCommand(channelName) {
var voiceChannel = GetChannelByName(channelName);
if (voiceChannel) {
voiceChannel.join();
console.log("Joined " + voiceChannel.name);
}
return voiceChannel;
}
/* 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;
}
/// Queues result of Youtube search into stream
function QueueYtAudioStream(videoId, videoName) {
var streamUrl = `${youtube.watchVideoUrl}${videoId}`;
if (!ytAudioQueue.length) {
ytAudioQueue.push(
{
'streamUrl': streamUrl,
'videoName': videoName
}
);
console.log("Queued audio " + videoName);
PlayStream(ytAudioQueue[0].streamUrl);
}
else {
ytAudioQueue.push(
{
'streamUrl': streamUrl,
'videoName': videoName
}
);
console.log("Queued audio " + videoName);
}
}
/// Plays a given stream
function PlayStream(streamUrl) {
const streamOptions = {seek: 0, volume: 1};
if (streamUrl) {
const stream = ytdl(streamUrl, {filter: 'audioonly'});
if (dispatcher == null) {
var voiceConnection = bot.voiceConnections.first();
//console.log(voiceConnection);
if (voiceConnection) {
console.log("Now Playing " + ytAudioQueue[0].videoName);
dispatcher = bot.voiceConnections.first().playStream(stream, streamOptions);
dispatcher.on('end', () => {
PlayNextStreamInQueue();
});
dispatcher.on('error', (err) => {
console.log(err);
});
}
}
else {
dispatcher = bot.voiceConnections.first().playStream(stream, streamOptions);
}
}
}
/// Plays the next stream in the queue
function PlayNextStreamInQueue() {
ytAudioQueue.splice(0, 1);
// if there are streams remaining in the queue then try to play
if (ytAudioQueue.length != 0) {
console.log("Now Playing " + ytAudioQueue[0].videoName);
PlayStream(ytAudioQueue[0].streamUrl);
}
}
/* END HELPER METHODS */
bot.login("redacted");
youtube.js
var request = require('superagent');
const API_KEY = "redacted";
const WATCH_VIDEO_URL = "https://www.youtube./watch?v=";
exports.watchVideoUrl = WATCH_VIDEO_URL;
exports.search = function search(searchKeywords, callback) {
var requestUrl = 'https://www.googleapis./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;
}
for (var item of body.items) {
if (item.id.kind === 'youtube#video') {
callback(item.id.videoId, item.snippet.title);
return; // prevent adding entire list of youtube videos
}
}
}
else {
console.log("Unexpected error when searching YouTube");
return;
}
});
return;
};
I'd say save the que in an array
var que = {
0 = "LINK";
};
and you retreive it using
que[0]
and auto the que
function skip() {
for (var i = 0; var length = que.length; i < length; i++) {
if (i != length) {
que[i] = que[(i+1)];
} else {
que[i] = null;
}
}
}
to show the que
function showque() {
var queText = "";
for (var i = 0; var length = que.length; i < length; i++) {
queText = queText + "[" + i + "] " + que[i] + "\n";
}
return queText;
}
snipet of message to send
message("ANYTHING BEFORE THE QUE\n" + showque() + "ANYTHING AFTER");
that hopefully should work.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745406696a4626345.html
评论列表(0条)