Moved all http request related code into method to allow override of useragent, removed superagent end detour

This commit is contained in:
Simon Schick
2015-12-11 00:11:10 +01:00
parent 6afff4e087
commit c5ccfab658
2 changed files with 815 additions and 873 deletions

View File

@@ -52,6 +52,16 @@ user
A User_ object representing the logged in client's user. A User_ object representing the logged in client's user.
userAgent
~~~~~~~~~
An object containing `url`, `version` and `full`.
Setting this property allows the discord developers to keep track of active bots,
it defaults to the discord.js git repo and the current version of the package.
`url` should be the repository/homepage of the creator.
`version` should be the version of your bot.
`full` is read only and will be automatically generated upon setting.
----- -----
Functions Functions

View File

@@ -24,24 +24,6 @@ import VoiceConnection from "../Voice/VoiceConnection";
var zlib; var zlib;
var libVersion = require('../../package.json').version; var libVersion = require('../../package.json').version;
//todo: move this somewhere else
var originalEnd = request.Request.prototype.end;
request.Request.prototype.end = function(callback) {
this.set('User-Agent', 'DiscordBot (https://github.com/hydrabolt/discord.js, ' + libVersion + ')');
return new Promise((resolve, reject) => {
originalEnd.call(this, (err, response) => {
if (callback) {
callback(err, response);
}
if (err) {
return reject(err);
}
resolve(response);
});
});
};
function waitFor(condition, value = condition, interval = 20) { function waitFor(condition, value = condition, interval = 20) {
return new Promise(resolve => { return new Promise(resolve => {
var int = setInterval(() => { var int = setInterval(() => {
@@ -67,11 +49,37 @@ export default class InternalClient {
this.setup(discordClient); this.setup(discordClient);
} }
apiRequest(method, url, useAuth, data, file) {
let ret = request[method](url);
if(useAuth) {
ret.set("authorization", this.token);
}
if(data) {
ret.send(data);
}
if(file) {
ret.attach("file", file.file, file.name);
}
ret.set('User-Agent', this.userAgentInfo.full);
return new Promise((resolve, reject) => {
ret.end((error, data) => {
if(error) {
return reject(error);
}
resolve(data.body);
});
});
}
setup(discordClient) { setup(discordClient) {
discordClient = discordClient || this.client; discordClient = discordClient || this.client;
this.client = discordClient; this.client = discordClient;
this.state = ConnectionState.IDLE; this.state = ConnectionState.IDLE;
this.websocket = null; this.websocket = null;
this.userAgent = {
url: 'https://github.com/hydrabolt/discord.js',
version: require('../../package.json').version
};
if (this.client.options.compress) { if (this.client.options.compress) {
zlib = require("zlib"); zlib = require("zlib");
@@ -121,6 +129,15 @@ export default class InternalClient {
return (this.readyTime ? Date.now() - this.readyTime : null); return (this.readyTime ? Date.now() - this.readyTime : null);
} }
set userAgent(info) {
info.full = `DiscordBot (${info.url}, ${info.version})`;
this.userAgentInfo = info;
}
get userAgent() {
return this.userAgentInfo;
}
//def leaveVoiceChannel //def leaveVoiceChannel
leaveVoiceChannel() { leaveVoiceChannel() {
if (this.voiceConnection) { if (this.voiceConnection) {
@@ -201,14 +218,10 @@ export default class InternalClient {
createServer(name, region = "london") { createServer(name, region = "london") {
name = this.resolver.resolveString(name); name = this.resolver.resolveString(name);
return request return this.apiRequest('post', Endpoints.SERVERS, true, { name, region })
.post(Endpoints.SERVERS)
.set("authorization", this.token)
.send({ name, region })
.end()
.then(res => { .then(res => {
// valid server, wait until it is cached // valid server, wait until it is cached
return waitFor(() => this.servers.get("id", res.body.id)); return waitFor(() => this.servers.get("id", res.id));
}); });
} }
@@ -218,13 +231,10 @@ export default class InternalClient {
if(!invite) { if(!invite) {
return Promise.reject(new Error("Not a valid invite")); return Promise.reject(new Error("Not a valid invite"));
} }
return request return this.apiRequest("post", Endpoints.INVITE(invite), true)
.post(Endpoints.INVITE(invite))
.set("authorization", this.token)
.end()
.then(res => { .then(res => {
// valid server, wait until it is received via ws and cached // valid server, wait until it is received via ws and cached
return waitFor(() => this.servers.get("id", res.body.guild.id)); return waitFor(() => this.servers.get("id", res.guild.id));
}); });
} }
@@ -236,10 +246,7 @@ export default class InternalClient {
return Promise.reject(new Error("server did not resolve")); return Promise.reject(new Error("server did not resolve"));
} }
return request return this.apiRequest("del", Endpoints.SERVER(server.id), true)
.del(Endpoints.SERVER(server.id))
.set("authorization", this.token)
.end()
.then(() => { .then(() => {
// remove channels of server then the server // remove channels of server then the server
for (var chan of server.channels) { for (var chan of server.channels) {
@@ -259,15 +266,12 @@ export default class InternalClient {
this.state = ConnectionState.LOGGING_IN; this.state = ConnectionState.LOGGING_IN;
return request return this.apiRequest("post", Endpoints.LOGIN, false, {
.post(Endpoints.LOGIN)
.send({
email, email,
password password
}) })
.end()
.then(res => { .then(res => {
var token = res.body.token; var token = res.token;
this.state = ConnectionState.LOGGED_IN; this.state = ConnectionState.LOGGED_IN;
this.token = token; this.token = token;
this.email = email; this.email = email;
@@ -295,10 +299,7 @@ export default class InternalClient {
return Promise.reject(new Error("Client is not logged in!")); return Promise.reject(new Error("Client is not logged in!"));
} }
return request return this.apiRequest("post", Endpoints.LOGOUT, true)
.post(Endpoints.LOGOUT)
.set("authorization", this.token)
.end()
.then(() => { .then(() => {
if (this.websocket) { if (this.websocket) {
this.websocket.close(); this.websocket.close();
@@ -318,25 +319,18 @@ export default class InternalClient {
return Promise.reject(new Error("Unable to resolve resUser to a User")); return Promise.reject(new Error("Unable to resolve resUser to a User"));
} }
// start the PM // start the PM
return request return this.apiRequest("post", Endpoints.USER_CHANNELS(user.id), true, {
.post(`${Endpoints.USER_CHANNELS(user.id) }`)
.set("authorization", this.token)
.send({
recipient_id: user.id recipient_id: user.id
}) })
.end()
.then(res => { .then(res => {
return this.private_channels.add(new PMChannel(res.body, this.client)); return this.private_channels.add(new PMChannel(res, this.client));
}); });
} }
// def getGateway // def getGateway
getGateway() { getGateway() {
return request return this.apiRequest("get", Endpoints.GATEWAY, true)
.get(Endpoints.GATEWAY) .then(res => res.url);
.set("authorization", this.token)
.end()
.then(res => res.body.url);
} }
// def sendMessage // def sendMessage
@@ -348,17 +342,13 @@ export default class InternalClient {
var content = this.resolver.resolveString(_content); var content = this.resolver.resolveString(_content);
var mentions = this.resolver.resolveMentions(content); var mentions = this.resolver.resolveMentions(content);
return request return this.apiRequest("post", Endpoints.CHANNEL_MESSAGES(destination.id), true, {
.post(Endpoints.CHANNEL_MESSAGES(destination.id))
.set("authorization", this.token)
.send({
content: content, content: content,
mentions: mentions, mentions: mentions,
tts: options.tts tts: options.tts
}) })
.end()
.then(res => .then(res =>
destination.messages.add(new Message(res.body, destination, this.client)) destination.messages.add(new Message(res, destination, this.client))
); );
}); });
@@ -373,10 +363,7 @@ export default class InternalClient {
var chain = options.wait ? delay(options.wait) : Promise.resolve(); var chain = options.wait ? delay(options.wait) : Promise.resolve();
return chain.then(() => return chain.then(() =>
request this.apiRequest("del", Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
.del(Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id))
.set("authorization", this.token)
.end()
) )
.then(() => message.channel.messages.remove(message)); .then(() => message.channel.messages.remove(message));
} }
@@ -393,18 +380,19 @@ export default class InternalClient {
var content = this.resolver.resolveString(_content); var content = this.resolver.resolveString(_content);
var mentions = this.resolver.resolveMentions(content); var mentions = this.resolver.resolveMentions(content);
return request return this.apiRequest(
.patch(Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id)) "patch",
.set("authorization", this.token) Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id),
.send({ true,
content: content, {
tts: options.tts, content: content,
mentions: mentions tts: options.tts,
}) mentions: mentions
.end() }
)
.then(res => message.channel.messages.update( .then(res => message.channel.messages.update(
message, message,
new Message(res.body, message.channel, this.client) new Message(res, message.channel, this.client)
)); ));
} }
@@ -412,12 +400,11 @@ export default class InternalClient {
sendFile(where, _file, name = "image.png") { sendFile(where, _file, name = "image.png") {
return this.resolver.resolveChannel(where) return this.resolver.resolveChannel(where)
.then(channel => .then(channel =>
request this.apiRequest("post", Endpoints.CHANNEL_MESSAGES(channel.id), true, null, {
.post(Endpoints.CHANNEL_MESSAGES(channel.id)) name,
.set("authorization", this.token) file: this.resolver.resolveFile(_file)
.attach("file", this.resolver.resolveFile(_file), name) })
.end() .then(res => channel.messages.add(new Message(res, channel, this.client)))
.then(res => channel.messages.add(new Message(res.body, channel, this.client)))
); );
} }
@@ -439,11 +426,12 @@ export default class InternalClient {
} }
} }
return request return this.apiRequest(
.get(Endpoints.CHANNEL_MESSAGES(channel.id) + "?" + qs.stringify(qsObject)) "get",
.set("authorization", this.token) `Endpoints.CHANNEL_MESSAGES(channel.id)?${qs.stringify(qsObject)}`,
.end() true
.then(res => res.body.map( )
.then(res => res.map(
msg => channel.messages.add(new Message(msg, channel, this.client)) msg => channel.messages.add(new Message(msg, channel, this.client))
)); ));
}); });
@@ -453,12 +441,9 @@ export default class InternalClient {
getBans(server) { getBans(server) {
server = this.resolver.resolveServer(server); server = this.resolver.resolveServer(server);
return request return this.apiRequest("get", Endpoints.SERVER_BANS(server.id), true)
.get(`${Endpoints.SERVER_BANS(server.id) }`)
.set("authorization", this.token)
.end()
.then(res => { .then(res => {
res.body.map(ban => { res.map(ban => {
return this.users.add(new User(ban.user, this.client)); return this.users.add(new User(ban.user, this.client));
}); });
}); });
@@ -469,20 +454,16 @@ export default class InternalClient {
server = this.resolver.resolveServer(server); server = this.resolver.resolveServer(server);
return request return this.apiRequest("post", Endpoints.SERVER_CHANNELS(server.id), true, {
.post(Endpoints.SERVER_CHANNELS(server.id))
.set("authorization", this.token)
.send({
name, name,
type type
}) })
.end()
.then(res => { .then(res => {
var channel; var channel;
if (res.body.type === "text") { if (res.type === "text") {
channel = new TextChannel(res.body, this.client, server); channel = new TextChannel(res, this.client, server);
}else{ } else {
channel = new VoiceChannel(res.body, this.client, server); channel = new VoiceChannel(res, this.client, server);
} }
return server.channels.add(this.channels.add(channel)); return server.channels.add(this.channels.add(channel));
}); });
@@ -493,17 +474,12 @@ export default class InternalClient {
return this.resolver.resolveChannel(_channel) return this.resolver.resolveChannel(_channel)
.then(channel => .then(channel =>
request this.apiRequest("del", Endpoints.CHANNEL(channel.id), true)
.del(Endpoints.CHANNEL(channel.id))
.set("authorization", this.token)
.end()
.then(() => { .then(() => {
channel.server.channels.remove(channel); channel.server.channels.remove(channel);
this.channels.remove(channel); this.channels.remove(channel);
}), error => { })
error.message = "Couldn't resolve to channel - " + error.toString(); );
throw error;
});
} }
// def banMember // def banMember
@@ -511,10 +487,11 @@ export default class InternalClient {
user = this.resolver.resolveUser(user); user = this.resolver.resolveUser(user);
server = this.resolver.resolveServer(server); server = this.resolver.resolveServer(server);
return request return this.apiRequest(
.put(`${Endpoints.SERVER_BANS(server.id)}/${user.id}?delete-message-days=${length}`) "put",
.set("authorization", this.token) `${Endpoints.SERVER_BANS(server.id)}/${user.id}?delete-message-days=${length}`,
.end();//will expose api result, probably not bad tho true
);
} }
// def unbanMember // def unbanMember
@@ -523,10 +500,7 @@ export default class InternalClient {
server = this.resolver.resolveServer(server); server = this.resolver.resolveServer(server);
user = this.resolver.resolveUser(user); user = this.resolver.resolveUser(user);
return request return this.apiRequest("del", `${Endpoints.SERVER_BANS(server.id)}/${user.id}`, true)
.del(`${Endpoints.SERVER_BANS(server.id) }/${user.id}`)
.set("authorization", this.token)
.end();//will expose api result, probably not bad tho
} }
// def kickMember // def kickMember
@@ -534,28 +508,21 @@ export default class InternalClient {
user = this.resolver.resolveUser(user); user = this.resolver.resolveUser(user);
server = this.resolver.resolveServer(server); server = this.resolver.resolveServer(server);
return request return this.apiRequest("del", `${Endpoints.SERVER_MEMBERS(server.id) }/${user.id}`, true);
.del(`${Endpoints.SERVER_MEMBERS(server.id) }/${user.id}`)
.set("authorization", this.token)
.end();
} }
// def createRole // def createRole
createRole(server, data) { createRole(server, data) {
server = this.resolver.resolveServer(server); server = this.resolver.resolveServer(server);
return request return this.apiRequest("post", Endpoints.SERVER_ROLES(server.id), true)
.post(Endpoints.SERVER_ROLES(server.id))
.set("authorization", this.token)
.end()
.then(res => { .then(res => {
var role = server.roles.add(new Role(res.body, server, this.client)); var role = server.roles.add(new Role(res, server, this.client));
if (data) { if (data) {
return this.updateRole(role, data); return this.updateRole(role, data);
} }
return role; return role;
}); });
} }
// def updateRole // def updateRole
@@ -581,22 +548,15 @@ export default class InternalClient {
} }
} }
return request return this.apiRequest("patch", `${Endpoints.SERVER_ROLES(server.id)}/${role.id}`, true, newData)
.patch(Endpoints.SERVER_ROLES(server.id) + "/" + role.id)
.set("authorization", this.token)
.send(newData)
.end()
.then(res => { .then(res => {
return server.roles.update(role, new Role(res.body, server, this.client)); return server.roles.update(role, new Role(res, server, this.client));
}); });
} }
// def deleteRole // def deleteRole
deleteRole(role) { deleteRole(role) {
return request return this.apiRequest("del", `${Endpoints.SERVER_ROLES(role.server.id)}/${role.id}`, true)
.del(Endpoints.SERVER_ROLES(role.server.id) + "/" + role.id)
.set("authorization", this.token)
.end();
} }
//def addMemberToRole //def addMemberToRole
@@ -613,13 +573,14 @@ export default class InternalClient {
var roleIDS = role.server.memberMap[member.id].roles.map(r => r.id).concat(role.id); var roleIDS = role.server.memberMap[member.id].roles.map(r => r.id).concat(role.id);
return request return this.apiRequest(
.patch(Endpoints.SERVER_MEMBERS(role.server.id) + "/" + member.id) "patch",
.set("authorization", this.token) `${Endpoints.SERVER_MEMBERS(role.server.id)}/${member.id}`,
.send({ true,
roles: roleIDS {
}) roles: roleIDS
.end(); }
);
} }
//def addMemberToRole //def addMemberToRole
@@ -643,13 +604,14 @@ export default class InternalClient {
roleIDS.concat(role.id); roleIDS.concat(role.id);
} }
return request return this.apiRequest(
.patch(Endpoints.SERVER_MEMBERS(role.server.id) + "/" + member.id) "patch",
.set("authorization", this.token) `${Endpoints.SERVER_MEMBERS(role.server.id)}/${member.id}`,
.send({ true,
roles: roleIDS {
}) roles: roleIDS
.end(); }
);
} }
//def removeMemberFromRole //def removeMemberFromRole
@@ -673,13 +635,14 @@ export default class InternalClient {
} }
} }
return request return this.apiRequest(
.patch(Endpoints.SERVER_MEMBERS(role.server.id) + "/" + member.id) "patch",
.set("authorization", this.token) `${Endpoints.SERVER_MEMBERS(role.server.id)}/${member.id}`,
.send({ true,
roles: roleIDS {
}) roles: roleIDS
.end(); }
);
} }
//def removeMemberFromRoles //def removeMemberFromRoles
@@ -708,13 +671,14 @@ export default class InternalClient {
} }
} }
return request return this.apiRequest(
.patch(Endpoints.SERVER_MEMBERS(role.server.id) + "/" + member.id) "patch",
.set("authorization", this.token) `${Endpoints.SERVER_MEMBERS(role.server.id)}/${member.id}`,
.send({ true,
roles: roleIDS {
}) roles: roleIDS
.end(); }
);
} }
// def createInvite // def createInvite
@@ -749,12 +713,8 @@ export default class InternalClient {
epoint = Endpoints.SERVER_INVITES(chanServ.id); epoint = Endpoints.SERVER_INVITES(chanServ.id);
} }
return request return this.apiRequest("post", epoint, true, options)
.post(epoint) .then(res => new Invite(res, this.channels.get("id", res.channel.id), this.client));
.set("authorization", this.token)
.send(options)
.end()
.then(res => new Invite(res.body, this.channels.get("id", res.body.channel.id), this.client));
} }
//def deleteInvite //def deleteInvite
@@ -764,10 +724,7 @@ export default class InternalClient {
if(!invite) { if(!invite) {
throw new Error("Not a valid invite"); throw new Error("Not a valid invite");
} }
return request return this.apiRequest("del", Endpoints.INVITE(invite), true);
.del(Endpoints.INVITE(invite))
.set("authorization", this.token)
.end();
} }
//def overwritePermissions //def overwritePermissions
@@ -812,11 +769,12 @@ export default class InternalClient {
} }
} }
return request return this.apiRequest(
.put(Endpoints.CHANNEL_PERMISSIONS(channel.id) + "/" + data.id) "put",
.set("authorization", this.token) `${Endpoints.CHANNEL_PERMISSIONS(channel.id)}/${data.id}`,
.send(data) true,
.end(); data
);
}); });
} }
@@ -852,10 +810,7 @@ export default class InternalClient {
//def sendTyping //def sendTyping
sendTyping(channel) { sendTyping(channel) {
return this.resolver.resolveChannel(channel).then(channel => return this.resolver.resolveChannel(channel).then(channel =>
request this.apiRequest("post", Endpoints.CHANNEL(channel.id) + "/typing", true)
.post(Endpoints.CHANNEL(channel.id) + "/typing")
.set("authorization", this.token)
.end()
); );
} }
@@ -886,7 +841,7 @@ export default class InternalClient {
.then(channel => { .then(channel => {
if(!this.intervals.typing[channel.id]){ if(!this.intervals.typing[channel.id]){
// typing interval doesn't exist // typing interval doesn"t exist
throw new Error("Not typing in that channel"); throw new Error("Not typing in that channel");
} }
@@ -898,17 +853,13 @@ export default class InternalClient {
//def updateDetails //def updateDetails
updateDetails(data) { updateDetails(data) {
return request return this.apiRequest("patch", Endpoints.ME, true, {
.patch(Endpoints.ME)
.set("authorization", this.token)
.send({
avatar: this.resolver.resolveToBase64(data.avatar) || this.user.avatar, avatar: this.resolver.resolveToBase64(data.avatar) || this.user.avatar,
email : data.email || this.email, email: data.email || this.email,
new_password : data.newPassword || null, new_password: data.newPassword || null,
password : data.password || this.password, password: data.password || this.password,
username : data.username || this.user.username username: data.username || this.user.username
}) });
.end();
} }
//def setAvatar //def setAvatar
@@ -925,16 +876,12 @@ export default class InternalClient {
setChannelTopic(chann, topic = "") { setChannelTopic(chann, topic = "") {
return this.resolver.resolveChannel(chann) return this.resolver.resolveChannel(chann)
.then(channel => .then(channel =>
request this.apiRequest("patch", Endpoints.CHANNEL(channel.id), true, {
.patch(Endpoints.CHANNEL(channel.id))
.set("authorization", this.token)
.send({
name: channel.name, name: channel.name,
position: channel.position, position: channel.position,
topic: topic topic: topic
}) })
.end() .then(res => channel.topic = res.topic)
.then(res => channel.topic = res.body.topic)
); );
} }
@@ -942,16 +889,12 @@ export default class InternalClient {
setChannelName(chann, name = "discordjs_is_the_best") { setChannelName(chann, name = "discordjs_is_the_best") {
return this.resolver.resolveChannel(chann) return this.resolver.resolveChannel(chann)
.then(channel => .then(channel =>
request this.apiRequest("patch", Endpoints.CHANNEL(channel.id), true, {
.patch(Endpoints.CHANNEL(channel.id))
.set("authorization", this.token)
.send({
name: name, name: name,
position: channel.position, position: channel.position,
topic: channel.topic topic: channel.topic
}) })
.end() .then(res => channel.name = res.name)
.then(res => channel.name = res.body.name)
); );
} }
@@ -959,18 +902,14 @@ export default class InternalClient {
setChannelNameAndTopic(chann, name = "discordjs_is_the_best", topic = "") { setChannelNameAndTopic(chann, name = "discordjs_is_the_best", topic = "") {
return this.resolver.resolveChannel(chann) return this.resolver.resolveChannel(chann)
.then(channel => .then(channel =>
request this.apiRequest("patch", Endpoints.CHANNEL(channel.id), true, {
.patch(Endpoints.CHANNEL(channel.id))
.set("authorization", this.token)
.send({
name: name, name: name,
position: channel.position, position: channel.position,
topic: topic topic: topic
}) })
.end()
.then(res => { .then(res => {
channel.name = res.body.name; channel.name = res.name;
channel.topic = res.body.topic; channel.topic = res.topic;
}) })
); );
} }
@@ -979,16 +918,12 @@ export default class InternalClient {
setChannelPosition(chann, position = 0) { setChannelPosition(chann, position = 0) {
return this.resolver.resolveChannel(chann) return this.resolver.resolveChannel(chann)
.then(channel => .then(channel =>
request this.apiRequest("patch", Endpoints.CHANNEL(channel.id), true, {
.patch(Endpoints.CHANNEL(channel.id))
.set("authorization", this.token)
.send({
name: channel.name, name: channel.name,
position: position, position: position,
topic: channel.topic topic: channel.topic
}) })
.end() .then(res => channel.position = res.position)
.then(res => channel.position = res.body.position)
); );
} }
@@ -1005,10 +940,7 @@ export default class InternalClient {
Promise.reject(new Error("Message does not exist")); Promise.reject(new Error("Message does not exist"));
} }
return request return this.apiRequest("post", Endpoints.CHANNEL_MESSAGE(msg.channel.id, msg.id) + "/ack", true);
.post(Endpoints.CHANNEL_MESSAGE(msg.channel.id, msg.id) + "/ack")
.set("authorization", this.token)
.end();
} }
sendWS(object) { sendWS(object) {