Pushing changes
This commit is contained in:
194
node_modules/discordie/examples/echo.js
generated
vendored
Normal file
194
node_modules/discordie/examples/echo.js
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
"use strict";
|
||||
|
||||
// voice echo bot
|
||||
|
||||
// records and sends audio using `proxy` mode (without decoding/encoding/saving anything)
|
||||
// variable `var recordTime = 10;` controls duration of recording in seconds
|
||||
|
||||
// commands:
|
||||
// ~!~echo - joins voice channel and records audio, then plays recorded audio back
|
||||
// ~!~stop - stops recording/playing
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
client.connect(auth);
|
||||
|
||||
var recordTime = 10;
|
||||
var recordTimer = null;
|
||||
|
||||
var recordReply = null;
|
||||
var recordStartTime = null;
|
||||
var recordedData = [];
|
||||
var recordingUser = null;
|
||||
|
||||
client.Dispatcher.on("MESSAGE_CREATE", e => {
|
||||
console.log("new message: ");
|
||||
console.log(JSON.stringify(e.message, null, " "));
|
||||
console.log("e.message.content: " + e.message.content);
|
||||
|
||||
const content = e.message.content;
|
||||
const guild = e.message.channel.guild;
|
||||
|
||||
if (content == "~!~echo") {
|
||||
if (recordingUser)
|
||||
return e.message.reply("Already recording");
|
||||
|
||||
const channelToJoin = e.message.author.getVoiceChannel(guild);
|
||||
if (!channelToJoin)
|
||||
return e.message.reply("Join a voice channel first");
|
||||
|
||||
channelToJoin.join().then(info => {
|
||||
recordReply = e.message.reply.bind(e.message);
|
||||
e.message.reply("Recording audio for " + recordTime + " seconds");
|
||||
recordedData = [];
|
||||
recordingUser = e.message.author.id;
|
||||
recordStartTime = Date.now();
|
||||
|
||||
recordTimer = setTimeout(() => {
|
||||
play(info);
|
||||
e.message.reply("Playing");
|
||||
}, recordTime * 1000);
|
||||
});
|
||||
}
|
||||
|
||||
if (content == "~!~stop") {
|
||||
e.message.reply("Stopped");
|
||||
stopPlaying = true;
|
||||
recordingUser = false;
|
||||
if (recordTimer) {
|
||||
clearTimeout(recordTimer);
|
||||
recordTimer = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.Dispatcher.on("VOICE_CONNECTED", e => {
|
||||
e.voiceConnection.getDecoder()
|
||||
.onPacket = (packet) => {
|
||||
const user = e.voiceConnection.ssrcToMember(packet.ssrc);
|
||||
if (!user) return;
|
||||
if (user.id != recordingUser) return;
|
||||
packet.playbackTime = Date.now() - recordStartTime;
|
||||
recordedData.push(packet);
|
||||
|
||||
const name = user ? user.username : "<unknown>";
|
||||
console.log(
|
||||
"recording " + packet.chunk.length +
|
||||
" bytes from " + name +
|
||||
" @ " + packet.timestamp
|
||||
);
|
||||
};
|
||||
// set callback on `.onPacketDecoded` to enable decoding and
|
||||
// have decoded audio in `packet.chunk`
|
||||
});
|
||||
|
||||
var stopPlaying = false;
|
||||
function play(info) {
|
||||
stopPlaying = false;
|
||||
var playbackStartTime = Date.now();
|
||||
|
||||
if (!client.VoiceConnections.length)
|
||||
return console.log("Voice not connected");
|
||||
|
||||
if (!info) info = client.VoiceConnections[0];
|
||||
var voiceConnection = info.voiceConnection;
|
||||
|
||||
var encoder = voiceConnection.getEncoder({ frameDuration: 20, proxy: true });
|
||||
|
||||
function sendPacket() {
|
||||
var packet = recordedData[0];
|
||||
if (!packet && recordReply) {
|
||||
recordReply("Finished playing");
|
||||
}
|
||||
if (!packet || stopPlaying) {
|
||||
recordingUser = null;
|
||||
return;
|
||||
}
|
||||
var currentTime = (Date.now() - playbackStartTime);
|
||||
var nextTime = packet.playbackTime - currentTime;
|
||||
setTimeout(sendPacket, nextTime);
|
||||
|
||||
if (currentTime < nextTime) return;
|
||||
|
||||
recordedData.shift(packet);
|
||||
var numSamples = opus_packet_get_samples_per_frame(packet.chunk);
|
||||
console.log("playing ", packet.chunk.length, numSamples);
|
||||
encoder.enqueue(packet.chunk, numSamples);
|
||||
}
|
||||
sendPacket();
|
||||
}
|
||||
|
||||
client.Dispatcher.onAny((type, args) => {
|
||||
console.log("\nevent "+type);
|
||||
|
||||
if (args.type == "READY" || args.type == "READY" ||
|
||||
type == "GATEWAY_READY" || type == "ANY_GATEWAY_READY" ||
|
||||
type == "GATEWAY_DISPATCH") {
|
||||
return console.log("e " + (args.type || type));
|
||||
}
|
||||
|
||||
console.log("args " + JSON.stringify(args));
|
||||
});
|
||||
|
||||
// ===========================================================================
|
||||
// Opus helper functions
|
||||
// ===========================================================================
|
||||
|
||||
const Constants = {
|
||||
OPUS_BAD_ARG: -1,
|
||||
OPUS_INVALID_PACKET: -4
|
||||
};
|
||||
|
||||
function opus_packet_get_samples_per_frame(packet, sampleRate) {
|
||||
sampleRate = sampleRate || 48000;
|
||||
|
||||
let audiosize;
|
||||
if (packet[0] & 0x80) {
|
||||
audiosize = ((packet[0] >> 3) & 0x3);
|
||||
audiosize = (sampleRate << audiosize) / 400;
|
||||
} else if ((packet[0] & 0x60) == 0x60) {
|
||||
audiosize = (packet[0] & 0x08) ? sampleRate / 50 : sampleRate / 100;
|
||||
} else {
|
||||
audiosize = ((packet[0] >> 3) & 0x3);
|
||||
if (audiosize == 3) {
|
||||
audiosize = sampleRate * 60 / 1000;
|
||||
} else {
|
||||
audiosize = (sampleRate << audiosize) / 100;
|
||||
}
|
||||
}
|
||||
return audiosize;
|
||||
}
|
||||
|
||||
function opus_packet_get_nb_frames(packet) {
|
||||
var count;
|
||||
if (packet.length < 1) return Constants.OPUS_BAD_ARG;
|
||||
count = packet[0] & 0x3;
|
||||
|
||||
if (count == 0) return 1;
|
||||
else if (count != 3) return 2;
|
||||
else if (packet.length < 2) return Constants.OPUS_INVALID_PACKET;
|
||||
else return packet[1] & 0x3F;
|
||||
}
|
||||
|
||||
function opus_packet_get_nb_samples(packet, sampleRate)
|
||||
{
|
||||
sampleRate = sampleRate || 48000;
|
||||
|
||||
var count = opus_packet_get_nb_frames(packet);
|
||||
if (count < 0) return count;
|
||||
|
||||
var samples = count * opus_packet_get_samples_per_frame(packet, sampleRate);
|
||||
/* Can't have more than 120 ms */
|
||||
if (samples * 25 > sampleRate * 3)
|
||||
return Constants.OPUS_INVALID_PACKET;
|
||||
return samples;
|
||||
}
|
145
node_modules/discordie/examples/echoproxy.js
generated
vendored
Normal file
145
node_modules/discordie/examples/echoproxy.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
"use strict";
|
||||
|
||||
// voice echo bot
|
||||
|
||||
// simple audio proxy - mirrors user's audio
|
||||
// can be useful for redirecting audio into another channel/server through
|
||||
// different bot instance
|
||||
|
||||
// commands:
|
||||
// ~!~start - starts proxying audio for the invoker
|
||||
// ~!~stop - stops proxying audio for the invoker
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
client.connect(auth);
|
||||
|
||||
var proxyingUser = null;
|
||||
|
||||
client.Dispatcher.on("MESSAGE_CREATE", e => {
|
||||
console.log("new message: ");
|
||||
console.log(JSON.stringify(e.message, null, " "));
|
||||
console.log("e.message.content: " + e.message.content);
|
||||
|
||||
const content = e.message.content;
|
||||
const guild = e.message.channel.guild;
|
||||
|
||||
if (content == "~!~start") {
|
||||
if (proxyingUser)
|
||||
return e.message.reply("Already proxying");
|
||||
|
||||
const channelToJoin = e.message.author.getVoiceChannel(guild);
|
||||
if (!channelToJoin)
|
||||
return e.message.reply("Join a voice channel first");
|
||||
|
||||
channelToJoin.join().then(info => {
|
||||
e.message.reply("Proxying audio for user " + e.message.author.username);
|
||||
proxyingUser = e.message.author.id;
|
||||
});
|
||||
}
|
||||
|
||||
if (content == "~!~stop") {
|
||||
e.message.reply("Stopped");
|
||||
proxyingUser = null;
|
||||
}
|
||||
});
|
||||
|
||||
client.Dispatcher.on("VOICE_CONNECTED", e => {
|
||||
var encoder = e.voiceConnection.getEncoder({ frameDuration: 20, proxy: true });
|
||||
var decoder = e.voiceConnection.getDecoder();
|
||||
|
||||
decoder.onPacket = (packet) => {
|
||||
if (!proxyingUser) return;
|
||||
|
||||
const user = e.voiceConnection.ssrcToMember(packet.ssrc);
|
||||
if (!user) return;
|
||||
if (user.id != proxyingUser) return;
|
||||
|
||||
const name = user ? user.username : "<unknown>";
|
||||
console.log(
|
||||
"proxying " + packet.chunk.length +
|
||||
" bytes from " + name +
|
||||
" @ " + packet.timestamp
|
||||
);
|
||||
|
||||
var numSamples = opus_packet_get_samples_per_frame(packet.chunk);
|
||||
encoder.enqueue(packet.chunk, numSamples);
|
||||
};
|
||||
// set callback on `.onPacketDecoded` to enable decoding and
|
||||
// have decoded audio in `packet.chunk`
|
||||
});
|
||||
|
||||
client.Dispatcher.onAny((type, args) => {
|
||||
console.log("\nevent "+type);
|
||||
|
||||
if (args.type == "READY" || args.type == "READY" ||
|
||||
type == "GATEWAY_READY" || type == "ANY_GATEWAY_READY" ||
|
||||
type == "GATEWAY_DISPATCH") {
|
||||
return console.log("e " + (args.type || type));
|
||||
}
|
||||
|
||||
console.log("args " + JSON.stringify(args));
|
||||
});
|
||||
|
||||
// ===========================================================================
|
||||
// Opus helper functions
|
||||
// ===========================================================================
|
||||
|
||||
const Constants = {
|
||||
OPUS_BAD_ARG: -1,
|
||||
OPUS_INVALID_PACKET: -4
|
||||
};
|
||||
|
||||
function opus_packet_get_samples_per_frame(packet, sampleRate) {
|
||||
sampleRate = sampleRate || 48000;
|
||||
|
||||
let audiosize;
|
||||
if (packet[0] & 0x80) {
|
||||
audiosize = ((packet[0] >> 3) & 0x3);
|
||||
audiosize = (sampleRate << audiosize) / 400;
|
||||
} else if ((packet[0] & 0x60) == 0x60) {
|
||||
audiosize = (packet[0] & 0x08) ? sampleRate / 50 : sampleRate / 100;
|
||||
} else {
|
||||
audiosize = ((packet[0] >> 3) & 0x3);
|
||||
if (audiosize == 3) {
|
||||
audiosize = sampleRate * 60 / 1000;
|
||||
} else {
|
||||
audiosize = (sampleRate << audiosize) / 100;
|
||||
}
|
||||
}
|
||||
return audiosize;
|
||||
}
|
||||
|
||||
function opus_packet_get_nb_frames(packet) {
|
||||
var count;
|
||||
if (packet.length < 1) return Constants.OPUS_BAD_ARG;
|
||||
count = packet[0] & 0x3;
|
||||
|
||||
if (count == 0) return 1;
|
||||
else if (count != 3) return 2;
|
||||
else if (packet.length < 2) return Constants.OPUS_INVALID_PACKET;
|
||||
else return packet[1] & 0x3F;
|
||||
}
|
||||
|
||||
function opus_packet_get_nb_samples(packet, sampleRate)
|
||||
{
|
||||
sampleRate = sampleRate || 48000;
|
||||
|
||||
var count = opus_packet_get_nb_frames(packet);
|
||||
if (count < 0) return count;
|
||||
|
||||
var samples = count * opus_packet_get_samples_per_frame(packet, sampleRate);
|
||||
/* Can't have more than 120 ms */
|
||||
if (samples * 25 > sampleRate * 3)
|
||||
return Constants.OPUS_INVALID_PACKET;
|
||||
return samples;
|
||||
}
|
145
node_modules/discordie/examples/encoderstream.js
generated
vendored
Normal file
145
node_modules/discordie/examples/encoderstream.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
"use strict";
|
||||
|
||||
//// note: run "npm install lame" in this folder first
|
||||
|
||||
// audio example implemented using AudioEncoderStream
|
||||
|
||||
// audio decoding using "lame"
|
||||
|
||||
// commands:
|
||||
// ping
|
||||
// vjoin <channelname> -- joins matching channel for current guild
|
||||
// vleave
|
||||
// play -- plays test.mp3
|
||||
// stop
|
||||
|
||||
var lame = require('lame');
|
||||
var fs = require('fs');
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
client.connect(auth);
|
||||
|
||||
client.Dispatcher.on("GATEWAY_READY", e => {
|
||||
const guild = client.Guilds.getBy("name", "test");
|
||||
if (!guild) return console.log("Guild not found");
|
||||
|
||||
const general = guild.voiceChannels.find(c => c.name == "General");
|
||||
if (!general) return console.log("Channel not found");
|
||||
|
||||
return general.join(false, false);
|
||||
});
|
||||
|
||||
client.Dispatcher.on("MESSAGE_CREATE", (e) => {
|
||||
const content = e.message.content;
|
||||
const channel = e.message.channel;
|
||||
const guild = e.message.channel.guild;
|
||||
|
||||
if (content == "ping") {
|
||||
channel.sendMessage("pong");
|
||||
}
|
||||
|
||||
if (content == "vleave") {
|
||||
client.Channels
|
||||
.filter(channel => channel.isGuildVoice && channel.joined)
|
||||
.forEach(channel => channel.leave());
|
||||
}
|
||||
|
||||
if (content.indexOf("vjoin ") == 0) {
|
||||
const targetChannel = content.replace("vjoin ", "");
|
||||
|
||||
var vchannel =
|
||||
guild.voiceChannels
|
||||
.find(channel => channel.name.toLowerCase().indexOf(targetChannel) >= 0);
|
||||
if (vchannel) vchannel.join().then(info => play(info));
|
||||
}
|
||||
|
||||
if (content.indexOf("play") == 0) {
|
||||
if (!client.VoiceConnections.length) {
|
||||
return e.message.reply("Not connected to any channel");
|
||||
}
|
||||
var info = client.VoiceConnections.getForGuild(guild);
|
||||
if (info) play(info);
|
||||
}
|
||||
|
||||
if (content.indexOf("stop") == 0) {
|
||||
var info = client.VoiceConnections.getForGuild(guild);
|
||||
if (info) {
|
||||
var encoderStream = info.voiceConnection.getEncoderStream();
|
||||
encoderStream.unpipeAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.Dispatcher.on("VOICE_CONNECTED", e => {
|
||||
// uncomment to play on join
|
||||
//play();
|
||||
});
|
||||
|
||||
function play(info) {
|
||||
if (!client.VoiceConnections.length) {
|
||||
return console.log("Voice not connected");
|
||||
}
|
||||
|
||||
if (!info) info = client.VoiceConnections[0];
|
||||
|
||||
var mp3decoder = new lame.Decoder();
|
||||
var file = fs.createReadStream("test.mp3");
|
||||
file.pipe(mp3decoder);
|
||||
|
||||
mp3decoder.on('format', pcmfmt => {
|
||||
// note: discordie encoder does resampling if rate != 48000
|
||||
var options = {
|
||||
frameDuration: 60,
|
||||
sampleRate: pcmfmt.sampleRate,
|
||||
channels: pcmfmt.channels,
|
||||
float: false
|
||||
};
|
||||
|
||||
var encoderStream = info.voiceConnection.getEncoderStream(options);
|
||||
if (!encoderStream) {
|
||||
return console.log(
|
||||
"Unable to get encoder stream, connection is disposed"
|
||||
);
|
||||
}
|
||||
|
||||
// Stream instance is persistent until voice connection is disposed;
|
||||
// you can register timestamp listener once when connection is initialized
|
||||
// or access timestamp with `encoderStream.timestamp`
|
||||
encoderStream.resetTimestamp();
|
||||
encoderStream.removeAllListeners("timestamp");
|
||||
encoderStream.on("timestamp", time => console.log("Time " + time));
|
||||
|
||||
// only 1 stream at a time can be piped into AudioEncoderStream
|
||||
// previous stream will automatically unpipe
|
||||
mp3decoder.pipe(encoderStream);
|
||||
mp3decoder.once('end', () => play(info));
|
||||
|
||||
// must be registered after `pipe()`
|
||||
encoderStream.once("unpipe", () => file.destroy());
|
||||
});
|
||||
}
|
||||
|
||||
client.Dispatcher.onAny((type, e) => {
|
||||
var ignore = [
|
||||
"READY",
|
||||
"GATEWAY_READY",
|
||||
"ANY_GATEWAY_READY",
|
||||
"GATEWAY_DISPATCH",
|
||||
"PRESENCE_UPDATE",
|
||||
"TYPING_START",
|
||||
];
|
||||
if (ignore.find(t => (t == type || t == e.type))) {
|
||||
return console.log("<" + type + ">");
|
||||
}
|
||||
|
||||
console.log("\nevent " + type);
|
||||
return console.log("args " + JSON.stringify(e));
|
||||
});
|
120
node_modules/discordie/examples/ffmpegencoder.js
generated
vendored
Normal file
120
node_modules/discordie/examples/ffmpegencoder.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
|
||||
//// note: install ffmpeg/avconv first
|
||||
|
||||
// audio decoding and encoding using built in ffmpeg wrappers
|
||||
// (opus encoding is done entierly by ffmpeg)
|
||||
|
||||
// commands:
|
||||
// ping
|
||||
// vjoin <channelname> -- joins matching channel for current guild
|
||||
// vleave
|
||||
// play -- plays test.mp3
|
||||
// stop
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
client.connect(auth);
|
||||
|
||||
client.Dispatcher.on("GATEWAY_READY", e => {
|
||||
const guild = client.Guilds.getBy("name", "test");
|
||||
if (!guild) return console.log("Guild not found");
|
||||
|
||||
const general = guild.voiceChannels.find(c => c.name == "General");
|
||||
if (!general) return console.log("Channel not found");
|
||||
|
||||
return general.join(false, false);
|
||||
});
|
||||
|
||||
client.Dispatcher.on("MESSAGE_CREATE", (e) => {
|
||||
const content = e.message.content;
|
||||
const channel = e.message.channel;
|
||||
const guild = e.message.channel.guild;
|
||||
|
||||
if (content == "ping") {
|
||||
channel.sendMessage("pong");
|
||||
}
|
||||
|
||||
if (content == "vleave") {
|
||||
client.Channels
|
||||
.filter(channel => channel.isGuildVoice && channel.joined)
|
||||
.forEach(channel => channel.leave());
|
||||
}
|
||||
|
||||
if (content.indexOf("vjoin ") == 0) {
|
||||
const targetChannel = content.replace("vjoin ", "");
|
||||
|
||||
var vchannel =
|
||||
guild.voiceChannels
|
||||
.find(channel => channel.name.toLowerCase().indexOf(targetChannel) >= 0);
|
||||
if (vchannel) vchannel.join().then(info => play(info));
|
||||
}
|
||||
|
||||
if (content.indexOf("play") == 0) {
|
||||
if (!client.VoiceConnections.length) {
|
||||
return e.message.reply("Not connected to any channel");
|
||||
}
|
||||
var info = client.VoiceConnections.getForGuild(guild);
|
||||
if (info) play(info);
|
||||
}
|
||||
|
||||
if (content.indexOf("stop") == 0) {
|
||||
var info = client.VoiceConnections.getForGuild(guild);
|
||||
if (info) {
|
||||
var encoderStream = info.voiceConnection.getEncoderStream();
|
||||
encoderStream.unpipeAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.Dispatcher.on("VOICE_CONNECTED", e => {
|
||||
// uncomment to play on join
|
||||
// play();
|
||||
});
|
||||
|
||||
function play(info) {
|
||||
if (!client.VoiceConnections.length) {
|
||||
return console.log("Voice not connected");
|
||||
}
|
||||
|
||||
if (!info) info = client.VoiceConnections[0];
|
||||
|
||||
var encoder = info.voiceConnection.createExternalEncoder({
|
||||
type: "ffmpeg",
|
||||
source: "test.mp3"
|
||||
});
|
||||
if (!encoder) return console.log("Voice connection is no longer valid");
|
||||
|
||||
encoder.once("end", () => play(info));
|
||||
|
||||
var encoderStream = encoder.play();
|
||||
encoderStream.resetTimestamp();
|
||||
encoderStream.removeAllListeners("timestamp");
|
||||
encoderStream.on("timestamp", time => console.log("Time " + time));
|
||||
}
|
||||
|
||||
client.Dispatcher.onAny((type, e) => {
|
||||
var ignore = [
|
||||
"READY",
|
||||
"GATEWAY_READY",
|
||||
"ANY_GATEWAY_READY",
|
||||
"GATEWAY_DISPATCH",
|
||||
"PRESENCE_UPDATE",
|
||||
"TYPING_START",
|
||||
];
|
||||
if (ignore.find(t => (t == type || t == e.type))) {
|
||||
return console.log("<" + type + ">");
|
||||
}
|
||||
|
||||
console.log("\nevent " + type);
|
||||
return console.log("args " + JSON.stringify(e));
|
||||
});
|
193
node_modules/discordie/examples/lowlevelaudio/massive.js
generated
vendored
Normal file
193
node_modules/discordie/examples/lowlevelaudio/massive.js
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
"use strict";
|
||||
|
||||
//// note: run "npm install lame" in this folder first
|
||||
|
||||
// example bot
|
||||
|
||||
// audio decoding using "lame"
|
||||
|
||||
// commands:
|
||||
// ping
|
||||
// vjoin <channelname> -- joins matching channel for current guild
|
||||
// vleave
|
||||
// play -- plays test.mp3
|
||||
// stop
|
||||
|
||||
var lame = require('lame');
|
||||
var fs = require('fs');
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
function connect() { client.connect(auth); }
|
||||
connect();
|
||||
|
||||
client.Dispatcher.on(Discordie.Events.GATEWAY_READY, (e) => {
|
||||
// client.Users
|
||||
// client.Channels
|
||||
// client.DirectMessageChannels
|
||||
// client.Guilds
|
||||
// client.Messages
|
||||
// are collection interfaces with filter(fn), get(id), getBy(k, v)
|
||||
|
||||
// client.User
|
||||
// contains current user
|
||||
|
||||
const guild = client.Guilds.getBy("name", "test");
|
||||
// or:
|
||||
// client.Guilds.filter(g => (g.name == "test"))[0];
|
||||
|
||||
// e.data contains raw READY event
|
||||
|
||||
if (guild) {
|
||||
// guild.voiceChannels returns an array
|
||||
const general = guild.voiceChannels.filter(c => c.name == "General")[0];
|
||||
|
||||
// IVoiceChannel.join(selfMute, selfDeaf)
|
||||
if (general)
|
||||
return general.join(false, false);
|
||||
|
||||
return console.log("Channel not found");
|
||||
}
|
||||
console.log("Guild not found");
|
||||
});
|
||||
|
||||
client.Dispatcher.on(Discordie.Events.MESSAGE_CREATE, (e) => {
|
||||
console.log("new message: ");
|
||||
console.log(JSON.stringify(e.message, null, " "));
|
||||
console.log("e.message.content: " + e.message.content);
|
||||
|
||||
if(e.message.content == "ping") {
|
||||
e.message.channel.sendMessage("pong");
|
||||
|
||||
// e.message.reply("pong")
|
||||
// will prefix the message with a mention
|
||||
}
|
||||
if(e.message.content == "vleave") {
|
||||
var c = e.message.channel;
|
||||
|
||||
client.Channels
|
||||
.filter(channel => channel.isGuildVoice && channel.joined)
|
||||
.forEach(channel => channel.leave());
|
||||
}
|
||||
if(e.message.content.indexOf("vjoin ") == 0) {
|
||||
const targetChannel = e.message.content.replace("vjoin ", "");
|
||||
|
||||
e.message.channel.guild.voiceChannels
|
||||
.forEach(channel => {
|
||||
if(channel.name.toLowerCase().indexOf(targetChannel) >= 0)
|
||||
channel.join().then(v => play(v));
|
||||
// channel.join() returns a promise with voiceConnectionInfo
|
||||
});
|
||||
}
|
||||
if(e.message.content.indexOf("play") == 0) {
|
||||
if(!client.VoiceConnections.length) {
|
||||
return e.message.reply("Not connected to any channel");
|
||||
}
|
||||
play();
|
||||
}
|
||||
if(e.message.content.indexOf("stop") == 0) {
|
||||
stopPlaying = true;
|
||||
}
|
||||
});
|
||||
client.Dispatcher.on(Discordie.Events.MESSAGE_UPDATE, (e) => {
|
||||
console.log("updated message: ");
|
||||
console.log(JSON.stringify(e.message));
|
||||
});
|
||||
client.Dispatcher.on(Discordie.Events.MESSAGE_DELETE, (e) => {
|
||||
console.log("deleted message: ");
|
||||
console.log(JSON.stringify(e.message));
|
||||
|
||||
// e.message now has 'e.message.deleted' set to true
|
||||
// properties in e.message will be null if the message is not cached
|
||||
});
|
||||
|
||||
client.Dispatcher.on(Discordie.Events.VOICE_CONNECTED, (data) => {
|
||||
if(client.VoiceConnections.length <= 0) {
|
||||
return console.log("Voice not connected");
|
||||
}
|
||||
|
||||
// uncomment to play on join
|
||||
//play();
|
||||
});
|
||||
|
||||
var stopPlaying = false;
|
||||
function play(voiceConnectionInfo) {
|
||||
stopPlaying = false;
|
||||
|
||||
var mp3decoder = new lame.Decoder();
|
||||
mp3decoder.on('format', decode);
|
||||
fs.createReadStream("test.mp3").pipe(mp3decoder);
|
||||
|
||||
function decode(pcmfmt) {
|
||||
// note: discordie encoder does resampling if rate != 48000
|
||||
var options = {
|
||||
frameDuration: 60,
|
||||
sampleRate: pcmfmt.sampleRate,
|
||||
channels: pcmfmt.channels,
|
||||
float: false
|
||||
};
|
||||
|
||||
const frameDuration = 60;
|
||||
|
||||
var readSize =
|
||||
pcmfmt.sampleRate / 1000 *
|
||||
options.frameDuration *
|
||||
pcmfmt.bitDepth / 8 *
|
||||
pcmfmt.channels;
|
||||
|
||||
mp3decoder.once('readable', function() {
|
||||
if(!client.VoiceConnections.length) {
|
||||
return console.log("Voice not connected");
|
||||
}
|
||||
|
||||
if(!voiceConnectionInfo) {
|
||||
// get first if not specified
|
||||
voiceConnectionInfo = client.VoiceConnections[0];
|
||||
}
|
||||
var voiceConnection = voiceConnectionInfo.voiceConnection;
|
||||
|
||||
// one encoder per voice connection
|
||||
var encoder = voiceConnection.getEncoder(options);
|
||||
|
||||
const needBuffer = () => encoder.onNeedBuffer();
|
||||
encoder.onNeedBuffer = function() {
|
||||
var chunk = mp3decoder.read(readSize);
|
||||
if (stopPlaying) return;
|
||||
|
||||
// delay the packet if no data buffered
|
||||
if (!chunk) return setTimeout(needBuffer, options.frameDuration);
|
||||
|
||||
var sampleCount = readSize / pcmfmt.channels / (pcmfmt.bitDepth / 8);
|
||||
encoder.enqueue(chunk, sampleCount);
|
||||
};
|
||||
|
||||
needBuffer();
|
||||
});
|
||||
|
||||
mp3decoder.once('end', () => setTimeout(play, 100, voiceConnectionInfo));
|
||||
}
|
||||
}
|
||||
|
||||
client.Dispatcher.onAny((type, e) => {
|
||||
var ignore = [
|
||||
"READY",
|
||||
"GATEWAY_READY",
|
||||
"ANY_GATEWAY_READY",
|
||||
"GATEWAY_DISPATCH",
|
||||
"PRESENCE_UPDATE",
|
||||
"TYPING_START",
|
||||
];
|
||||
if(ignore.find(t => (t == type || t == e.type))) {
|
||||
return console.log("<" + type + ">");
|
||||
}
|
||||
|
||||
console.log("\nevent " + type);
|
||||
return console.log("args " + JSON.stringify(e));
|
||||
});
|
238
node_modules/discordie/examples/lowlevelaudio/massive2.js
generated
vendored
Normal file
238
node_modules/discordie/examples/lowlevelaudio/massive2.js
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
"use strict";
|
||||
|
||||
//// note: install ffmpeg/avconv first
|
||||
|
||||
// example bot
|
||||
|
||||
// commands:
|
||||
// ping
|
||||
// vjoin <channelname> -- joins matching channel for current guild
|
||||
// vleave
|
||||
// play -- plays test.mp3
|
||||
// stop
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var child_process = require('child_process');
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
function connect() { client.connect(auth); }
|
||||
connect();
|
||||
|
||||
client.Dispatcher.on(Discordie.Events.GATEWAY_READY, (e) => {
|
||||
// client.Users
|
||||
// client.Channels
|
||||
// client.DirectMessageChannels
|
||||
// client.Guilds
|
||||
// client.Messages
|
||||
// are collection interfaces with filter(fn), get(id), getBy(k, v)
|
||||
|
||||
// client.User
|
||||
// contains current user
|
||||
|
||||
const guild = client.Guilds.getBy("name", "test");
|
||||
// or:
|
||||
// client.Guilds.filter(g => (g.name == "test"))[0];
|
||||
|
||||
// e.data contains raw READY event
|
||||
|
||||
if (guild) {
|
||||
// guild.voiceChannels returns an array
|
||||
const general = guild.voiceChannels.filter(c => c.name == "General")[0];
|
||||
|
||||
// IVoiceChannel.join(selfMute, selfDeaf)
|
||||
if (general)
|
||||
return general.join(false, false);
|
||||
|
||||
return console.log("Channel not found");
|
||||
}
|
||||
console.log("Guild not found");
|
||||
});
|
||||
|
||||
client.Dispatcher.on(Discordie.Events.MESSAGE_CREATE, (e) => {
|
||||
console.log("new message: ");
|
||||
console.log(JSON.stringify(e.message, null, " "));
|
||||
console.log("e.message.content: " + e.message.content);
|
||||
|
||||
if(e.message.content == "ping") {
|
||||
e.message.channel.sendMessage("pong");
|
||||
|
||||
// e.message.reply("pong")
|
||||
// will prefix the message with a mention
|
||||
}
|
||||
if(e.message.content == "vleave") {
|
||||
var c = e.message.channel;
|
||||
|
||||
client.Channels
|
||||
.filter(channel => channel.isGuildVoice && channel.joined)
|
||||
.forEach(channel => channel.leave());
|
||||
}
|
||||
if(e.message.content.indexOf("vjoin ") == 0) {
|
||||
const targetChannel = e.message.content.replace("vjoin ", "");
|
||||
|
||||
e.message.channel.guild.voiceChannels
|
||||
.forEach(channel => {
|
||||
if(channel.name.toLowerCase().indexOf(targetChannel) >= 0)
|
||||
channel.join().then(v => play(v));
|
||||
// channel.join() returns a promise with voiceConnectionInfo
|
||||
});
|
||||
}
|
||||
if(e.message.content.indexOf("play") == 0) {
|
||||
if(!client.VoiceConnections.length) {
|
||||
return e.message.reply("Not connected to any channel");
|
||||
}
|
||||
play();
|
||||
}
|
||||
if(e.message.content.indexOf("stop") == 0) {
|
||||
stop();
|
||||
}
|
||||
});
|
||||
client.Dispatcher.on(Discordie.Events.MESSAGE_UPDATE, (e) => {
|
||||
console.log("updated message: ");
|
||||
console.log(JSON.stringify(e.message));
|
||||
});
|
||||
client.Dispatcher.on(Discordie.Events.MESSAGE_DELETE, (e) => {
|
||||
console.log("deleted message: ");
|
||||
console.log(JSON.stringify(e.message));
|
||||
|
||||
// e.message now has 'e.message.deleted' set to true
|
||||
// properties in e.message will be null if the message is not cached
|
||||
});
|
||||
|
||||
client.Dispatcher.on(Discordie.Events.VOICE_CONNECTED, (data) => {
|
||||
if(client.VoiceConnections.length <= 0) {
|
||||
return console.log("Voice not connected");
|
||||
}
|
||||
|
||||
// uncomment to play on join
|
||||
//play();
|
||||
});
|
||||
|
||||
function getConverter(args, options) {
|
||||
var binaries = [
|
||||
'ffmpeg',
|
||||
'ffmpeg.exe',
|
||||
'avconv',
|
||||
'avconv.exe'
|
||||
];
|
||||
|
||||
var paths = process.env.PATH.split(path.delimiter).concat(["."]);
|
||||
|
||||
for (var name of binaries) {
|
||||
for (var p of paths) {
|
||||
var binary = p + path.sep + name;
|
||||
if (!fs.existsSync(binary)) continue;
|
||||
return child_process.spawn(name, args, options);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var ffmpeg = null;
|
||||
function stop() {
|
||||
stopPlaying = true;
|
||||
if (!ffmpeg) return;
|
||||
ffmpeg.kill();
|
||||
ffmpeg = null;
|
||||
}
|
||||
|
||||
var stopPlaying = false;
|
||||
function play(voiceConnectionInfo) {
|
||||
stopPlaying = false;
|
||||
|
||||
var sampleRate = 48000;
|
||||
var bitDepth = 16;
|
||||
var channels = 2;
|
||||
|
||||
if (ffmpeg) ffmpeg.kill();
|
||||
|
||||
ffmpeg = getConverter([
|
||||
"-re",
|
||||
"-i", "test.mp3",
|
||||
"-f", "s16le",
|
||||
"-ar", sampleRate,
|
||||
"-ac", channels,
|
||||
"-"
|
||||
], {stdio: ['pipe', 'pipe', 'ignore']});
|
||||
if (!ffmpeg) return console.log("ffmpeg/avconv not found");
|
||||
|
||||
var _ffmpeg = ffmpeg;
|
||||
var ff = ffmpeg.stdout;
|
||||
|
||||
// note: discordie encoder does resampling if rate != 48000
|
||||
var options = {
|
||||
frameDuration: 60,
|
||||
sampleRate: sampleRate,
|
||||
channels: channels,
|
||||
float: false
|
||||
};
|
||||
|
||||
const frameDuration = 60;
|
||||
|
||||
var readSize =
|
||||
sampleRate / 1000 *
|
||||
options.frameDuration *
|
||||
bitDepth / 8 *
|
||||
channels;
|
||||
|
||||
ff.once('readable', function() {
|
||||
if(!client.VoiceConnections.length) {
|
||||
return console.log("Voice not connected");
|
||||
}
|
||||
|
||||
if(!voiceConnectionInfo) {
|
||||
// get first if not specified
|
||||
voiceConnectionInfo = client.VoiceConnections[0];
|
||||
}
|
||||
var voiceConnection = voiceConnectionInfo.voiceConnection;
|
||||
|
||||
// one encoder per voice connection
|
||||
var encoder = voiceConnection.getEncoder(options);
|
||||
|
||||
const needBuffer = () => encoder.onNeedBuffer();
|
||||
encoder.onNeedBuffer = function() {
|
||||
var chunk = ff.read(readSize);
|
||||
|
||||
if (_ffmpeg.killed) return;
|
||||
if (stopPlaying) return stop();
|
||||
|
||||
// delay the packet if no data buffered
|
||||
if (!chunk) return setTimeout(needBuffer, options.frameDuration);
|
||||
|
||||
var sampleCount = readSize / channels / (bitDepth / 8);
|
||||
encoder.enqueue(chunk, sampleCount);
|
||||
};
|
||||
|
||||
needBuffer();
|
||||
});
|
||||
|
||||
ff.once('end', () => {
|
||||
if (stopPlaying) return;
|
||||
setTimeout(play, 100, voiceConnectionInfo);
|
||||
});
|
||||
}
|
||||
|
||||
client.Dispatcher.onAny((type, e) => {
|
||||
var ignore = [
|
||||
"READY",
|
||||
"GATEWAY_READY",
|
||||
"ANY_GATEWAY_READY",
|
||||
"GATEWAY_DISPATCH",
|
||||
"PRESENCE_UPDATE",
|
||||
"TYPING_START",
|
||||
];
|
||||
if(ignore.find(t => (t == type || t == e.type))) {
|
||||
return console.log("<" + type + ">");
|
||||
}
|
||||
|
||||
console.log("\nevent " + type);
|
||||
return console.log("args " + JSON.stringify(e));
|
||||
});
|
227
node_modules/discordie/examples/permissions.js
generated
vendored
Normal file
227
node_modules/discordie/examples/permissions.js
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
"use strict";
|
||||
|
||||
// example bot
|
||||
|
||||
// commands:
|
||||
// ping
|
||||
// do - creates a role Testing, assigns it to the member, adds member permission for channel
|
||||
// undo
|
||||
|
||||
var Discordie;
|
||||
try { Discordie = require("../"); } catch(e) {}
|
||||
try { Discordie = require("discordie"); } catch(e) {}
|
||||
|
||||
var client = new Discordie({autoReconnect: true});
|
||||
var Events = Discordie.Events;
|
||||
|
||||
var auth = { token: "<BOT-TOKEN>" };
|
||||
try { auth = require("./auth"); } catch(e) {}
|
||||
|
||||
client.connect(auth);
|
||||
|
||||
client.Dispatcher.on("GATEWAY_READY", e => {
|
||||
console.log("Ready");
|
||||
});
|
||||
|
||||
client.Dispatcher.on("MESSAGE_CREATE", e => {
|
||||
console.log("new message: ");
|
||||
console.log(JSON.stringify(e.message, null, " "));
|
||||
console.log("e.message.content: " + e.message.content);
|
||||
|
||||
var content = e.message.content;
|
||||
|
||||
if (content === "ping") channel.sendMessage("pong");
|
||||
if (content === "do") doCommand(e);
|
||||
if (content === "undo") undoCommand(e);
|
||||
});
|
||||
|
||||
function onError(e) {
|
||||
if (!e) return console.error("Unknown error");
|
||||
|
||||
if(e.response && e.response.error)
|
||||
return console.error(e.response.error);
|
||||
|
||||
console.error(e.toString());
|
||||
}
|
||||
|
||||
function doCommand(e) {
|
||||
var guild = e.message.guild;
|
||||
var channel = e.message.channel;
|
||||
var member = e.message.member;
|
||||
|
||||
// chain of actions
|
||||
console.log(" >> creating role");
|
||||
|
||||
guild.createRole()
|
||||
.then(assignRole)
|
||||
.catch(onError);
|
||||
|
||||
function assignRole(role) {
|
||||
console.log(" >> assigning role");
|
||||
|
||||
member.assignRole(role)
|
||||
.then(() => setRolePermissions(role))
|
||||
.catch(onError);
|
||||
}
|
||||
function setRolePermissions(role) {
|
||||
console.log(" >> setting role permissions");
|
||||
|
||||
/*
|
||||
List of role permissions:
|
||||
General: {
|
||||
CREATE_INSTANT_INVITE,
|
||||
KICK_MEMBERS,
|
||||
BAN_MEMBERS,
|
||||
ADMINISTRATOR,
|
||||
MANAGE_CHANNELS,
|
||||
MANAGE_GUILD,
|
||||
CHANGE_NICKNAME,
|
||||
MANAGE_NICKNAMES,
|
||||
MANAGE_ROLES,
|
||||
MANAGE_WEBHOOKS,
|
||||
MANAGE_EMOJIS,
|
||||
},
|
||||
Text: {
|
||||
READ_MESSAGES,
|
||||
SEND_MESSAGES,
|
||||
SEND_TTS_MESSAGES,
|
||||
MANAGE_MESSAGES,
|
||||
EMBED_LINKS,
|
||||
ATTACH_FILES,
|
||||
READ_MESSAGE_HISTORY,
|
||||
MENTION_EVERYONE,
|
||||
EXTERNAL_EMOTES,
|
||||
ADD_REACTIONS,
|
||||
},
|
||||
Voice: {
|
||||
CONNECT,
|
||||
SPEAK,
|
||||
MUTE_MEMBERS,
|
||||
DEAFEN_MEMBERS,
|
||||
MOVE_MEMBERS,
|
||||
USE_VAD,
|
||||
}
|
||||
*/
|
||||
|
||||
var perms = role.permissions;
|
||||
perms.General.KICK_MEMBERS = true;
|
||||
perms.General.BAN_MEMBERS = true;
|
||||
perms.Text.MENTION_EVERYONE = true;
|
||||
|
||||
// 'role.permissions' object resets on error
|
||||
|
||||
var newRoleName = "Testing";
|
||||
var color = 0xE74C3C; // RED
|
||||
var hoist = true; // show separate group
|
||||
|
||||
role.commit(newRoleName, color, hoist)
|
||||
.then(createChannelPermissions)
|
||||
.catch(onError);
|
||||
}
|
||||
function createChannelPermissions() {
|
||||
console.log(" >> creating channel permissions");
|
||||
|
||||
channel.createPermissionOverwrite(member)
|
||||
.then(setChannelPermissions)
|
||||
.catch(onError);
|
||||
}
|
||||
function setChannelPermissions(overwrite) {
|
||||
console.log(" >> setting channel permissions");
|
||||
|
||||
var allow = overwrite.allow;
|
||||
var deny = overwrite.deny;
|
||||
|
||||
/*
|
||||
List of channel permissions:
|
||||
General: {
|
||||
CREATE_INSTANT_INVITE,
|
||||
MANAGE_CHANNEL,
|
||||
MANAGE_PERMISSIONS
|
||||
},
|
||||
Text: {
|
||||
READ_MESSAGES,
|
||||
SEND_MESSAGES,
|
||||
SEND_TTS_MESSAGES,
|
||||
MANAGE_MESSAGES,
|
||||
EMBED_LINKS,
|
||||
ATTACH_FILES,
|
||||
READ_MESSAGE_HISTORY,
|
||||
MENTION_EVERYONE,
|
||||
},
|
||||
Voice: {
|
||||
CONNECT,
|
||||
SPEAK,
|
||||
MUTE_MEMBERS,
|
||||
DEAFEN_MEMBERS,
|
||||
MOVE_MEMBERS,
|
||||
USE_VAD,
|
||||
}
|
||||
*/
|
||||
|
||||
// .Text only exists for text channels
|
||||
// .Voice only exists for voice channels
|
||||
// .General exists for both
|
||||
|
||||
allow.General.MANAGE_CHANNEL = true;
|
||||
allow.General.MANAGE_PERMISSIONS = true;
|
||||
|
||||
overwrite.commit()
|
||||
.then((overwrite) => console.log(" >> finished"))
|
||||
.catch(onError);
|
||||
}
|
||||
}
|
||||
|
||||
function undoCommand(e) {
|
||||
var channel = e.message.channel;
|
||||
var member = e.message.member;
|
||||
|
||||
removeOverwrite();
|
||||
function removeOverwrite() {
|
||||
console.log(" >> removing overwrite");
|
||||
var overwrites = channel.permission_overwrites;
|
||||
var overwrite = overwrites.find(o => (o.id == member.id));
|
||||
if (!overwrite) {
|
||||
console.log(" >> no overwrite");
|
||||
unassignRoleTesting();
|
||||
return;
|
||||
}
|
||||
overwrite.delete()
|
||||
.then(unassignRoleTesting)
|
||||
.catch(onError);
|
||||
}
|
||||
function unassignRoleTesting() {
|
||||
console.log(" >> unassigning role");
|
||||
var role = member.roles.find(r => r.name == "Testing");
|
||||
if (!role) {
|
||||
console.log(" >> no role, finished");
|
||||
return;
|
||||
}
|
||||
member.unassignRole(role)
|
||||
.then(() => deleteRoleTesting(role))
|
||||
.catch(onError);
|
||||
}
|
||||
function deleteRoleTesting(role) {
|
||||
console.log(" >> unassigning role");
|
||||
|
||||
role.delete()
|
||||
.then((overwrite) => console.log(" >> finished"))
|
||||
.catch(onError);
|
||||
}
|
||||
}
|
||||
|
||||
client.Dispatcher.onAny((type, e) => {
|
||||
var ignore = [
|
||||
"READY",
|
||||
"GATEWAY_READY",
|
||||
"ANY_GATEWAY_READY",
|
||||
"GATEWAY_DISPATCH",
|
||||
"PRESENCE_UPDATE",
|
||||
"TYPING_START",
|
||||
];
|
||||
if(ignore.find(t => (t == type || t == e.type))) {
|
||||
return console.log("<" + type + ">");
|
||||
}
|
||||
|
||||
console.log("\nevent " + type);
|
||||
return console.log("args " + JSON.stringify(e));
|
||||
});
|
Reference in New Issue
Block a user