Merge pull request #21 from hydrabolt/indev

fix fatal bug
This commit is contained in:
Amish Shah
2015-08-30 22:00:23 +01:00
8 changed files with 544 additions and 136 deletions

View File

@@ -55,6 +55,40 @@ Here is a list of other Discord APIs:
--- ---
### Changes in 3.1.4
No, not π. But instead, pseduo-synchronous messaging was added! This means that
you can tell your Client to make a queue of "actions" per channel, and it will
work through them one by one. This is a really useful tool if you need to send
messages in a specific order without callback hell.
It also allows you to store responses - such as created messages - in the returned
promise - named action. Example:
```js
var mybot = new Discord.Client({
queue : true //enable queueing, disabled by default
});
mybot.on("message", function(msg){
mybot.sendMessage(msg.channel, "this is message 1");
var action = mybot.sendMessage(msg.channel, "this is message 2");
mybot.sendMessage(msg.channel, "this is message 3").then(rmv);
function rmv(){
if(!action.error){
mybot.deleteMessage(action.message);
}
}
});
```
This is still in development, and will see many more enhancements in future.
---
### Links ### Links
**[Documentation](https://github.com/discord-js/discord.js/wiki/Documentation)** **[Documentation](https://github.com/discord-js/discord.js/wiki/Documentation)**

41
examples/avatar.js Normal file
View File

@@ -0,0 +1,41 @@
/*
this bot is an avatar bot, and will give a user their avatar's URL
*/
var Discord = require("../");
// Get the email and password
var AuthDetails = require("./auth.json");
var bot = new Discord.Client();
bot.on("ready", function () {
console.log("Ready to begin! Serving in " + bot.channels.length + " channels");
});
bot.on("disconnected", function () {
console.log("Disconnected!");
process.exit(1); //exit node.js with an error
});
bot.on("message", function (msg) {
if (msg.content === "$avatar") {
//see if the user has an avatar
if( msg.sender.avatarURL ){
bot.reply(msg, msg.sender.avatarURL);
}else{
//using reply with a message automatically does:
// '@sender, ' for you!
bot.reply(msg, "you don't have an avatar!");
}
//alert the console
console.log("served " + msg.sender.username);
}
});
bot.login(AuthDetails.email, AuthDetails.password);

36
examples/catapi.js Normal file
View File

@@ -0,0 +1,36 @@
/*
this bot will send an image of a cat to a channel.
may be slow depending on your internet connection.
*/
var Discord = require("../");
// Get the email and password
var AuthDetails = require("./auth.json");
var bot = new Discord.Client();
bot.on("ready", function () {
console.log("Ready to begin! Serving in " + bot.channels.length + " channels");
});
bot.on("disconnected", function () {
console.log("Disconnected!");
process.exit(1); //exit node.js with an error
});
bot.on("message", function (msg) {
if (msg.content === "$cat") {
//send a message to the channel the ping message was sent in.
bot.sendMessage(msg.channel, "pong!");
//alert the console
console.log("pong-ed " + msg.sender.username);
}
});
bot.login(AuthDetails.email, AuthDetails.password);

View File

@@ -11,23 +11,26 @@ var AuthDetails = require("./auth.json");
var bot = new Discord.Client(); var bot = new Discord.Client();
bot.on("ready", function(){ bot.on("ready", function () {
console.log("Ready to begin! Serving in " + bot.channels.length + " channels"); console.log("Ready to begin! Serving in " + bot.channels.length + " channels");
}); });
bot.on("disconnected", function(){ bot.on("disconnected", function () {
console.log("Disconnected!"); console.log("Disconnected!");
process.exit(1); //exit node.js with an error process.exit(1); //exit node.js with an error
}); });
bot.on("message", function(msg){ bot.on("message", function (msg) {
if(msg.content.substring(0,4) === "ping"){ if (msg.content.substring(0, 4) === "ping") {
//send a message to the channel the ping message was sent in. //send a message to the channel the ping message was sent in.
bot.sendMessage( msg.channel, "pong!" ); bot.sendMessage(msg.channel, "pong!");
//alert the console
console.log("pong-ed " + msg.sender.username);
} }
}); });

View File

@@ -19,7 +19,7 @@ var WebSocket = require("ws");
var fs = require("fs"); var fs = require("fs");
var defaultOptions = { var defaultOptions = {
queue: [] queue: false
}; };
var Client = (function () { var Client = (function () {
@@ -35,7 +35,7 @@ var Client = (function () {
further efforts will be made to connect. further efforts will be made to connect.
*/ */
this.options = options; this.options = options;
this.options.queue = this.options.queue || []; this.options.queue = this.options.queue;
this.token = token; this.token = token;
this.state = 0; this.state = 0;
this.websocket = null; this.websocket = null;
@@ -62,7 +62,7 @@ var Client = (function () {
this.pmChannelCache = []; this.pmChannelCache = [];
this.readyTime = null; this.readyTime = null;
this.checkingQueue = {}; this.checkingQueue = {};
this.messageQueue = {}; this.queue = {};
} }
_createClass(Client, [{ _createClass(Client, [{
@@ -339,7 +339,7 @@ var Client = (function () {
var self = this; var self = this;
return new Promise(function (resolve, reject) { var prom = new Promise(function (resolve, reject) {
if (timeout) { if (timeout) {
setTimeout(remove, timeout); setTimeout(remove, timeout);
} else { } else {
@@ -347,17 +347,37 @@ var Client = (function () {
} }
function remove() { function remove() {
request.del(Endpoints.CHANNELS + "/" + message.channel.id + "/messages/" + message.id).set("authorization", self.token).end(function (err, res) { if (self.options.queue) {
if (err) { if (!self.queue[message.channel.id]) {
callback(err); self.queue[message.channel.id] = [];
reject(err);
} else {
callback(null);
resolve();
} }
}); self.queue[message.channel.id].push({
action: "deleteMessage",
message: message,
then: good,
error: bad
});
self.checkQueue(message.channel.id);
} else {
self._deleteMessage(message).then(good)["catch"](bad);
}
}
function good() {
prom.success = true;
callback(null);
resolve();
}
function bad(err) {
prom.error = err;
callback(err);
reject(err);
} }
}); });
return prom;
} }
}, { }, {
key: "updateMessage", key: "updateMessage",
@@ -366,26 +386,41 @@ var Client = (function () {
var self = this; var self = this;
return new Promise(function (resolve, reject) { var prom = new Promise(function (resolve, reject) {
content = content instanceof Array ? content.join("\n") : content; content = content instanceof Array ? content.join("\n") : content;
request.patch(Endpoints.CHANNELS + "/" + message.channel.id + "/messages/" + message.id).set("authorization", self.token).send({ if (self.options.queue) {
content: content, if (!self.queue[message.channel.id]) {
mentions: [] self.queue[message.channel.id] = [];
}).end(function (err, res) {
if (err) {
callback(err);
reject(err);
} else {
var msg = new Message(res.body, message.channel, message.mentions, message.sender);
callback(null, msg);
resolve(msg);
message.channel.messages[message.channel.messages.indexOf(message)] = msg;
} }
}); self.queue[message.channel.id].push({
action: "updateMessage",
message: message,
content: content,
then: good,
error: bad
});
self.checkQueue(message.channel.id);
} else {
self._updateMessage(message, content).then(good)["catch"](bad);
}
function good(msg) {
prom.message = msg;
callback(null, msg);
resolve(msg);
}
function bad(error) {
prom.error = error;
callback(error);
reject(error);
}
}); });
return prom;
} }
}, { }, {
key: "setUsername", key: "setUsername",
@@ -549,7 +584,7 @@ var Client = (function () {
var self = this; var self = this;
return new Promise(function (resolve, reject) { var prom = new Promise(function (resolve, reject) {
var fstream; var fstream;
@@ -563,27 +598,41 @@ var Client = (function () {
self.resolveDestination(destination).then(send)["catch"](error); self.resolveDestination(destination).then(send)["catch"](error);
function send(destination) { function send(destination) {
request.post(Endpoints.CHANNELS + "/" + destination + "/messages").set("authorization", self.token).attach("file", fstream, fileName).end(function (err, res) { if (self.options.queue) {
//queue send file too
if (err) { if (!self.queue[destination]) {
error(err); self.queue[destination] = [];
} else {
var chann = self.getChannel("id", destination);
if (chann) {
var msg = chann.addMessage(new Message(res.body, chann, [], self.user));
callback(null, msg);
resolve(msg);
}
} }
});
self.queue[destination].push({
action: "sendFile",
attachment: fstream,
attachmentName: fileName,
then: good,
error: bad
});
self.checkQueue(destination);
} else {
//not queue
self._sendFile(destination, fstream, fileName).then(good)["catch"](bad);
}
} }
function error(err) { function good(msg) {
prom.message = msg;
callback(null, msg);
resolve(msg);
}
function bad(err) {
prom.error = err;
callback(err); callback(err);
reject(err); reject(err);
} }
}); });
return prom;
} }
}, { }, {
key: "sendMessage", key: "sendMessage",
@@ -605,18 +654,18 @@ var Client = (function () {
} }
function send(destination) { function send(destination) {
if (~self.options.queue.indexOf("sendMessage")) { if (self.options.queue) {
//we're QUEUEING messages, so sending them sequentially based on servers. //we're QUEUEING messages, so sending them sequentially based on servers.
if (!self.messageQueue[destination]) { if (!self.queue[destination]) {
self.messageQueue[destination] = []; self.queue[destination] = [];
} }
self.messageQueue[destination].push({ self.queue[destination].push({
action: "sendMessage", action: "sendMessage",
content: message, content: message,
mentions: mentions, mentions: mentions,
then: [mgood], then: mgood,
error: [mbad] error: mbad
}); });
self.checkQueue(destination); self.checkQueue(destination);
@@ -1395,6 +1444,62 @@ var Client = (function () {
}); });
}); });
} }
}, {
key: "_sendFile",
value: function _sendFile(destination, attachment) {
var attachmentName = arguments.length <= 2 || arguments[2] === undefined ? "DEFAULT BECAUSE YOU DIDN'T SPECIFY WHY.png" : arguments[2];
var self = this;
return new Promise(function (resolve, reject) {
request.post(Endpoints.CHANNELS + "/" + destination + "/messages").set("authorization", self.token).attach("file", attachment, attachmentName).end(function (err, res) {
if (err) {
reject(err);
} else {
var chann = self.getChannel("id", destination);
if (chann) {
var msg = chann.addMessage(new Message(res.body, chann, [], self.user));
resolve(msg);
}
}
});
});
}
}, {
key: "_updateMessage",
value: function _updateMessage(message, content) {
var self = this;
return new Promise(function (resolve, reject) {
request.patch(Endpoints.CHANNELS + "/" + message.channel.id + "/messages/" + message.id).set("authorization", self.token).send({
content: content,
mentions: []
}).end(function (err, res) {
if (err) {
reject(err);
} else {
var msg = new Message(res.body, message.channel, message.mentions, message.sender);
resolve(msg);
message.channel.messages[message.channel.messages.indexOf(message)] = msg;
}
});
});
}
}, {
key: "_deleteMessage",
value: function _deleteMessage(message) {
var self = this;
return new Promise(function (resolve, reject) {
request.del(Endpoints.CHANNELS + "/" + message.channel.id + "/messages/" + message.id).set("authorization", self.token).end(function (err, res) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
}, { }, {
key: "checkQueue", key: "checkQueue",
value: function checkQueue(channelID) { value: function checkQueue(channelID) {
@@ -1405,21 +1510,57 @@ var Client = (function () {
if (!this.checkingQueue[channelID]) { if (!this.checkingQueue[channelID]) {
(function () { (function () {
var doNext = function doNext() { var doNext = function doNext() {
if (self.messageQueue[channelID].length === 0) { if (self.queue[channelID].length === 0) {
done(); done();
return; return;
} }
var queuedEvent = self.messageQueue[channelID][0]; var queuedEvent = self.queue[channelID][0];
switch (queuedEvent.action) { switch (queuedEvent.action) {
case "sendMessage": case "sendMessage":
var msgToSend = queuedEvent; var msgToSend = queuedEvent;
self._sendMessage(channelID, msgToSend.content, msgToSend.mentions).then(function (msg) { self._sendMessage(channelID, msgToSend.content, msgToSend.mentions).then(function (msg) {
msgToSend.then[0](msg); msgToSend.then(msg);
self.messageQueue[channelID].shift(); self.queue[channelID].shift();
doNext(); doNext();
})["catch"](function (err) { })["catch"](function (err) {
msgToSend["catch"][0](err); msgToSend.error(err);
self.messageQueue[channelID].shift(); self.queue[channelID].shift();
doNext();
});
break;
case "sendFile":
var fileToSend = queuedEvent;
self._sendFile(channelID, fileToSend.attachment, fileToSend.attachmentName).then(function (msg) {
fileToSend.then(msg);
self.queue[channelID].shift();
doNext();
})["catch"](function (err) {
fileToSend.error(err);
self.queue[channelID].shift();
doNext();
});
break;
case "updateMessage":
var msgToUpd = queuedEvent;
self._updateMessage(msgToUpd.message, msgToUpd.content).then(function (msg) {
msgToUpd.then(msg);
self.queue[channelID].shift();
doNext();
})["catch"](function (err) {
msgToUpd.error(err);
self.queue[channelID].shift();
doNext();
});
break;
case "deleteMessage":
var msgToDel = queuedEvent;
self._deleteMessage(msgToDel.message).then(function (msg) {
msgToDel.then(msg);
self.queue[channelID].shift();
doNext();
})["catch"](function (err) {
msgToDel.error(err);
self.queue[channelID].shift();
doNext(); doNext();
}); });
break; break;

View File

@@ -1,6 +1,6 @@
{ {
"name": "discord.js", "name": "discord.js",
"version": "3.1.3", "version": "3.1.4",
"description": "A way to interface with the Discord API", "description": "A way to interface with the Discord API",
"main": "./lib/index.js", "main": "./lib/index.js",
"scripts": { "scripts": {

View File

@@ -13,7 +13,7 @@ var WebSocket = require("ws");
var fs = require("fs"); var fs = require("fs");
var defaultOptions = { var defaultOptions = {
queue: [] queue: false
} }
class Client { class Client {
@@ -25,7 +25,7 @@ class Client {
further efforts will be made to connect. further efforts will be made to connect.
*/ */
this.options = options; this.options = options;
this.options.queue = this.options.queue || []; this.options.queue = this.options.queue;
this.token = token; this.token = token;
this.state = 0; this.state = 0;
this.websocket = null; this.websocket = null;
@@ -52,7 +52,7 @@ class Client {
this.pmChannelCache = []; this.pmChannelCache = [];
this.readyTime = null; this.readyTime = null;
this.checkingQueue = {}; this.checkingQueue = {};
this.messageQueue = {}; this.queue = {};
} }
get uptime() { get uptime() {
@@ -384,18 +384,33 @@ class Client {
} }
function remove() { function remove() {
request if(self.options.queue){
.del(`${Endpoints.CHANNELS}/${message.channel.id}/messages/${message.id}`) if (!self.queue[message.channel.id]) {
.set("authorization", self.token) self.queue[message.channel.id] = [];
.end(function (err, res) { }
if (err) { self.queue[message.channel.id].push({
callback(err); action: "deleteMessage",
reject(err); message: message,
} else { then: good,
callback(null); error: bad
resolve();
}
}); });
self.checkQueue(message.channel.id);
}else{
self._deleteMessage(message).then(good).catch(bad);
}
}
function good(){
prom.success = true;
callback(null);
resolve();
}
function bad(err){
prom.error = err;
callback(err);
reject(err);
} }
}); });
@@ -406,31 +421,42 @@ class Client {
var self = this; var self = this;
return new Promise(function (resolve, reject) { var prom = new Promise(function (resolve, reject) {
content = (content instanceof Array ? content.join("\n") : content); content = (content instanceof Array ? content.join("\n") : content);
request if(self.options.queue){
.patch(`${Endpoints.CHANNELS}/${message.channel.id}/messages/${message.id}`) if (!self.queue[message.channel.id]) {
.set("authorization", self.token) self.queue[message.channel.id] = [];
.send({ }
self.queue[message.channel.id].push({
action: "updateMessage",
message: message,
content: content, content: content,
mentions: [] then: good,
}) error: bad
.end(function (err, res) {
if (err) {
callback(err);
reject(err);
} else {
var msg = new Message(res.body, message.channel, message.mentions, message.sender);
callback(null, msg);
resolve(msg);
message.channel.messages[message.channel.messages.indexOf(message)] = msg;
}
}); });
self.checkQueue(message.channel.id);
}else{
self._updateMessage(message, content).then(good).catch(bad);
}
function good(msg){
prom.message = msg;
callback(null, msg);
resolve(msg);
}
function bad(error){
prom.error = error;
callback(error);
reject(error);
}
}); });
return prom;
} }
setUsername(newName, callback = function (err) { }) { setUsername(newName, callback = function (err) { }) {
@@ -563,7 +589,7 @@ class Client {
var self = this; var self = this;
return new Promise(function (resolve, reject) { var prom = new Promise(function (resolve, reject) {
var fstream; var fstream;
@@ -577,35 +603,42 @@ class Client {
self.resolveDestination(destination).then(send).catch(error); self.resolveDestination(destination).then(send).catch(error);
function send(destination) { function send(destination) {
request if(self.options.queue){
.post(`${Endpoints.CHANNELS}/${destination}/messages`) //queue send file too
.set("authorization", self.token) if (!self.queue[destination]) {
.attach("file", fstream, fileName) self.queue[destination] = [];
.end(function (err, res) { }
if (err) {
error(err);
} else {
var chann = self.getChannel("id", destination);
if (chann) {
var msg = chann.addMessage(new Message(res.body, chann, [], self.user));
callback(null, msg);
resolve(msg);
}
}
self.queue[destination].push({
action: "sendFile",
attachment : fstream,
attachmentName : fileName,
then: good,
error: bad
}); });
self.checkQueue(destination);
}else{
//not queue
self._sendFile(destination, fstream, fileName).then(good).catch(bad);
}
} }
function error(err) { function good(msg) {
prom.message = msg;
callback(null, msg);
resolve(msg);
}
function bad(err) {
prom.error = err;
callback(err); callback(err);
reject(err); reject(err);
} }
}); });
return prom;
} }
@@ -625,18 +658,18 @@ class Client {
} }
function send(destination) { function send(destination) {
if (~self.options.queue.indexOf("sendMessage")) { if (self.options.queue) {
//we're QUEUEING messages, so sending them sequentially based on servers. //we're QUEUEING messages, so sending them sequentially based on servers.
if (!self.messageQueue[destination]) { if (!self.queue[destination]) {
self.messageQueue[destination] = []; self.queue[destination] = [];
} }
self.messageQueue[destination].push({ self.queue[destination].push({
action: "sendMessage", action: "sendMessage",
content: message, content: message,
mentions: mentions, mentions: mentions,
then: [mgood], then: mgood,
error: [mbad] error: mbad
}); });
self.checkQueue(destination); self.checkQueue(destination);
@@ -1156,6 +1189,73 @@ class Client {
}); });
} }
_sendFile(destination, attachment, attachmentName = "DEFAULT BECAUSE YOU DIDN'T SPECIFY WHY.png"){
var self = this;
return new Promise(function(resolve, reject){
request
.post(`${Endpoints.CHANNELS}/${destination}/messages`)
.set("authorization", self.token)
.attach("file", attachment, attachmentName)
.end(function (err, res) {
if (err) {
reject(err);
} else {
var chann = self.getChannel("id", destination);
if (chann) {
var msg = chann.addMessage(new Message(res.body, chann, [], self.user));
resolve(msg);
}
}
});
});
}
_updateMessage(message, content){
var self = this;
return new Promise(function(resolve, reject){
request
.patch(`${Endpoints.CHANNELS}/${message.channel.id}/messages/${message.id}`)
.set("authorization", self.token)
.send({
content: content,
mentions: []
})
.end(function (err, res) {
if (err) {
reject(err);
} else {
var msg = new Message(res.body, message.channel, message.mentions, message.sender);
resolve(msg);
message.channel.messages[message.channel.messages.indexOf(message)] = msg;
}
});
});
}
_deleteMessage(message){
var self = this;
return new Promise(function(resolve, reject){
request
.del(`${Endpoints.CHANNELS}/${message.channel.id}/messages/${message.id}`)
.set("authorization", self.token)
.end(function (err, res) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
checkQueue(channelID) { checkQueue(channelID) {
@@ -1167,26 +1267,68 @@ class Client {
doNext(); doNext();
function doNext() { function doNext() {
if (self.messageQueue[channelID].length === 0) { if (self.queue[channelID].length === 0) {
done(); done();
return; return;
} }
var queuedEvent = self.messageQueue[channelID][0]; var queuedEvent = self.queue[channelID][0];
switch (queuedEvent.action) { switch (queuedEvent.action) {
case "sendMessage": case "sendMessage":
var msgToSend = queuedEvent; var msgToSend = queuedEvent;
self._sendMessage(channelID, msgToSend.content, msgToSend.mentions) self._sendMessage(channelID, msgToSend.content, msgToSend.mentions)
.then(function (msg) { .then(function (msg) {
msgToSend.then[0](msg); msgToSend.then(msg);
self.messageQueue[channelID].shift(); self.queue[channelID].shift();
doNext(); doNext();
}) })
.catch(function (err) { .catch(function (err) {
msgToSend.catch[0](err); msgToSend.error(err);
self.messageQueue[channelID].shift(); self.queue[channelID].shift();
doNext(); doNext();
}); });
break; break;
case "sendFile":
var fileToSend = queuedEvent;
self._sendFile(channelID, fileToSend.attachment, fileToSend.attachmentName)
.then(function (msg){
fileToSend.then(msg);
self.queue[channelID].shift();
doNext();
})
.catch(function(err){
fileToSend.error(err);
self.queue[channelID].shift();
doNext();
});
break;
case "updateMessage":
var msgToUpd = queuedEvent;
self._updateMessage(msgToUpd.message, msgToUpd.content)
.then(function(msg){
msgToUpd.then(msg);
self.queue[channelID].shift();
doNext();
})
.catch(function(err){
msgToUpd.error(err);
self.queue[channelID].shift();
doNext();
});
break;
case "deleteMessage":
var msgToDel = queuedEvent;
self._deleteMessage(msgToDel.message)
.then(function(msg){
msgToDel.then(msg);
self.queue[channelID].shift();
doNext();
})
.catch(function(err){
msgToDel.error(err);
self.queue[channelID].shift();
doNext();
});
break;
default: default:
done(); done();
break; break;

View File

@@ -1,26 +1,37 @@
var Discord = require("../"); var Discord = require("../");
var mybot = new Discord.Client({ var mybot = new Discord.Client({
queue : ["sendMessage"] queue: true
}); });
var fs = require("fs");
var server, channel, message, sentMessage = false; var server, channel, message, sentMessage = false;
mybot.on("message", function(message){ mybot.on("message", function (message) {
if( mybot.user.equals(message.sender) ){ if (mybot.user.equals(message.sender)) {
return; return;
} }
if (message.content !== "$$$") {
return;
}
var action1 = mybot.sendMessage(message.channel, "this is message " + 1); var action1 = mybot.sendMessage(message.channel, "this is message " + 1);
var action2 = mybot.sendMessage(message.channel, "this is message " + 2).then(log); var action2 = mybot.sendMessage(message.channel, "this is message " + 2).then(log);
function log(){ function log() {
mybot.sendMessage(message.channel, action1.message ? action1.message : action1.error); mybot.updateMessage(action1.message, "blurg");
mybot.sendMessage(message.channel, "This is message 3 million minus the million so basically just 3");
mybot.deleteMessage(action1.message);
mybot.sendMessage(message.channel, "This is message RJNGEIKGNER").then(log2);
} }
}); });
function error(err){ function dump(msg) {
console.log(msg);
}
function error(err) {
console.log(err); console.log(err);
} }