2016-10-23 3 views
-1

Я сейчас играю в роли бота для Discord.Очередь аудио для воспроизведения через Discord Bot

Мне удалось получить запрос на запросы, основанные на 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 прекратил говорить, однако события не так как это не устанавливается при запуске, в то время как я мог бы сделать это я не думаю, что это подойдет моим потребностям, поскольку речевой канал может быть изменен с помощью другой команды.

ответ

1

Я использовал код в качестве базы для моего собственного раздора бота и решить эту ошибку вы упомянули , Я просто изменил

dispatcher.on('end',() => {       
    PlayNextStreamInQueue(); 
}); 

в

dispatcher.on('end',() => {      
    dispatcher = null;     
    PlayNextStreamInQueue(); 
}); 
+0

рад слышать, что мой код был полезен :) Я попробую это исправить! –

0

Мое решение.

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 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]); 
      break; 
     case "*play": 
      PlayCommand(parameters.join(" "), message); 
      break; 
     case "*playqueue": 
      PlayQueueCommand(message); 
      break; 
    } 
}); 

/* 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"); 
    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.com/watch?v="; 

exports.watchVideoUrl = WATCH_VIDEO_URL; 

exports.search = function search(searchKeywords, callback) { 
    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; 
      } 

      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; 
}; 
+0

Есть еще некоторые ошибки с этим решением, иногда в очереди звуковые игры, иногда это не так. Я не уверен, что не так с логикой. –

0

Я бы сказал, сохранить Que в массиве

var que = { 
    0 = "LINK"; 
}; 

и вы извлечь его с помощью

que[0] 

и авто в 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; 
    } 
    } 
} 

, чтобы показать 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 из сообщения отправить

message("ANYTHING BEFORE THE QUE\n" + showque() + "ANYTHING AFTER"); 

, что мы надеемся, должно работать.

Смежные вопросы