2016-10-23 5 views
-1

Ich habe gerade einen Bot für Discord geschrieben.Queuing Audio zum Abspielen über Discord Bot

Ich habe es geschafft, es zu bekommen YouTube basierend gegebene Suchbegriffe abzufragen und dann Audio vom obersten Ergebnis abzuspielen, jedoch bin ich auf ein Problem gestoßen, wenn ich versuche, Audiotracks in einer Liste anzulegen und sie einmal abzuspielen Audiostream wurde abgeschlossen.

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/

Meine Idee war, dass ich das Abspielen der nächsten Audiostream beginnen könnte, sobald die Voicechannel sprechen aufgehört hat, aber das Ereignis nicht, da dies beim Start nicht gesetzt ist, während ich dieses ich tun konnte, glaube nicht, dass es meinen Bedürfnissen entspricht, da der Sprachkanal mit einem anderen Befehl geändert werden kann.

Antwort

1

verwendete ich Ihren Code als Basis für meine eigenen Bot Discord und löste das Sie Bug erwähnt . Ich änderte einfach

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

zu

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

Ich bin froh zu hören, dass mein Code gut genutzt wurde :) Ich werde dieses Update ausprobieren! –

0

Meine Lösung.

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

Es gibt immer noch einige Bugs mit dieser Lösung, manchmal die Warteschlange Audio spielt, manchmal nicht. Ich bin mir nicht sicher, was mit der Logik nicht stimmt. –

0

Ich sage das que in einem Array speichern würde

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

und Sie retreive es

que[0] 

und Auto mit dem 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; 
    } 
    } 
} 

zeigen die 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 der Nachricht

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

, die hoffentlich funktionieren sollte zu senden.

Verwandte Themen