Deleted examples, beginning to write in EC6.

Examples and Hydrabot will soon live in a separate repo which is better
suited to learning - this is so the main package isn't bloated.
This commit is contained in:
hydrabolt
2015-08-23 16:55:23 +01:00
parent 16b007c635
commit 35b61312b9
40 changed files with 1830 additions and 2486 deletions

69
src/Client.js Normal file
View File

@@ -0,0 +1,69 @@
//discord.js modules
var Endpoints = require("./Endpoints.js");
//node modules
var request = require("superagent");
var defaultOptions = {
cache_tokens: false
}
class Client {
constructor(options = defaultOptions, token = undefined) {
/*
When created, if a token is specified the Client will
try connecting with it. If the token is incorrect, no
further efforts will be made to connect.
*/
this.options = options;
this.token = token;
this.state = 0;
this.websocket = null;
this.events = new Map();
this.user = null;
/*
State values:
0 - idle
1 - logging in
2 - logged in
3 - ready
4 - disconnected
*/
}
get ready() {
return this.state === 3;
}
//def login
login(email = "foo@bar.com", password = "pass1234s", callback = function(){}) {
var self = this;
if (this.state === 0 || this.state === 4) {
this.state = 1; //set the state to logging in
request
.post(Endpoints.LOGIN)
.send({
email : email,
password : password
}).end(function(err, res){
if(err){
self.state = 4; //set state to disconnected
callback(err);
}else{
self.state = 2; //set state to logged in (not yet ready)
self.token = res.body.token;
}
});
}
}
}

11
src/Endpoints.js Normal file
View File

@@ -0,0 +1,11 @@
exports.BASE_DOMAIN = "discordapp.com";
exports.BASE = `https://${exports.BASE_DOMAIN}`;
exports.WEBSOCKET_HUB = `wss://${exports.BASE_DOMAIN}/hub`;
exports.API = `${exports.BASE}/api`;
exports.AUTH = `${exports.API}/auth`;
exports.LOGIN = `${exports.AUTH}/login`;
exports.LOGIN = `${exports.AUTH}/logout`;
exports.USERS = `${exports.API}/users`;
exports.SERVERS = `${exports.API}/guilds`;
exports.CHANNELS = `${exports.API}/channels`;

6
src/PMChannel.js Normal file
View File

@@ -0,0 +1,6 @@
var User = require("./user.js").User;
exports.PMChannel = function(user, id){
this.user = new User(user);
this.id = id;
}

68
src/TokenManager.js Normal file
View File

@@ -0,0 +1,68 @@
var fs = require( "fs" );
var crypto = require( "crypto" );
var md5 = require( "md5" );
var tokens = {};
exports.TokenManager = function( folder, file ) {
this.path = folder + file;
var self = this;
try {
var fd = fs.openSync( self.path, "wx" );
self.writeTokens();
} catch ( e ) {
self.readTokens();
}
}
exports.TokenManager.prototype.addToken = function( id, token, pass ) {
tokens[ md5( id ) ] = encrypt( token, pass );
this.writeTokens();
}
exports.TokenManager.prototype.readTokens = function() {
tokens = JSON.parse( fs.readFileSync( this.path, "utf8" ) );
for ( tkn in tokens ) {
tokens[ tkn ] = decrypt( tokens[ tkn ], tkn );
}
}
exports.TokenManager.prototype.writeTokens = function() {
var tkn = {};
for ( token in tokens ) {
tkn[ token ] = encrypt( tokens[ token ], token );
}
fs.writeFile( this.path, JSON.stringify( tkn ), function( err ) {
} );
}
exports.TokenManager.prototype.exists = function( id ) {
return tokens[ md5( id ) ];
}
exports.TokenManager.prototype.getToken = function( id, pass ) {
try{
return decrypt( tokens[ md5( id ) ], pass );
}catch(e){
return false;
}
}
function encrypt( string, password ) {
var cipher = crypto.createCipher( "aes-256-ctr", password )
var crypted = cipher.update( string, 'utf8', 'hex' )
crypted += cipher.final( 'hex' );
return crypted;
}
function decrypt( string, password ) {
var decipher = crypto.createDecipher( "aes-256-ctr", password )
var dec = decipher.update( string, 'hex', 'utf8' )
dec += decipher.final( 'utf8' );
return dec;
}

28
src/channel.js Normal file
View File

@@ -0,0 +1,28 @@
var List = require("./list.js").List;
exports.Channel = function(name, server, type, id, isPrivate){
if(!type){ //there's no second argument
var channel = name;
name = channel.name;
server = server;
type = channel.type;
id = channel.id;
isPrivate = channel.is_private;
}
this.name = name;
this.server = server;
this.type = type;
this.id = id;
this.isPrivate = isPrivate;
this.messages = new List("id", 5000);
}
exports.Channel.equals = function(otherChannel){
if(otherChannel.id === this.id){
return true;
} else {
return false;
}
}

21
src/index.js Normal file
View File

@@ -0,0 +1,21 @@
var request = require("superagent");
var Endpoints = require("./lib/endpoints.js");
var Server = require("./lib/server.js").Server;
var Message = require("./lib/message.js").Message;
var User = require("./lib/user.js").User;
var Channel = require("./lib/channel.js").Channel;
var List = require("./lib/list.js").List;
var Invite = require("./lib/invite.js").Invite;
var PMChannel = require("./lib/PMChannel.js").PMChannel;
var WebSocket = require('ws');
var Internal = require("./lib/internal.js").Internal;
var TokenManager = require("./lib/TokenManager.js").TokenManager;
exports.Endpoints = Endpoints;
exports.Server = Server;
exports.Message = Message;
exports.User = User;
exports.Channel = Channel;
exports.List = List;
exports.Invite = Invite;
exports.PMChannel = PMChannel;

277
src/internal.js Normal file
View File

@@ -0,0 +1,277 @@
var request = require( "superagent" );
var Endpoints = require( "./endpoints.js" );
var Internal = {};
Internal.XHR = {};
Internal.WebSocket = {};
Internal.WebSocket.properties = {
"$os": "discord.js",
"$browser": "discord.js",
"$device": "discord.js",
"$referrer": "",
"$referring_domain": ""
};
Internal.XHR.login = function( email, password, callback ) {
request
.post( Endpoints.LOGIN )
.send( {
email: email,
password: password
} )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body.token );
}
} );
}
Internal.XHR.logout = function( token, callback ) {
request
.post( Endpoints.LOGOUT )
.end( function( err, res ) {
err ? callback( err ) : callback( null );
} );
}
Internal.XHR.createServer = function( token, name, region, callback ) {
request
.post( Endpoints.SERVERS )
.set( "authorization", token )
.send( {
name: name,
region: region
} )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.leaveServer = function( token, serverId, callback ) {
request
.del( Endpoints.SERVERS + "/" + serverId )
.set( "authorization", token )
.end( function( err, res ) {
err ? callback( err ) : callback( null );
} );
}
Internal.XHR.createInvite = function( token, channelId, options, callback ) {
request
.post( Endpoints.CHANNELS + "/" + channelId + "/invites" )
.set( "authorization", token )
.send( options )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} )
}
Internal.XHR.startPM = function( token, selfID, userID, callback ) {
request
.post( Endpoints.USERS + "/" + selfID + "/channels" )
.set( "authorization", token )
.send( {
recipient_id: userID
} )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.sendMessage = function( token, channelID, messageParameters, callback ) {
request
.post( Endpoints.CHANNELS + "/" + channelID + "/messages" )
.set( "authorization", token )
.send( messageParameters )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.sendFile = function( token, channelID, file, fileName, callback ) {
request
.post( Endpoints.CHANNELS + "/" + channelID + "/messages" )
.set( "authorization", token )
.attach("file", file, fileName)
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.deleteMessage = function( token, channelID, messageID, callback ) {
request
.del( Endpoints.CHANNELS + "/" + channelID + "/messages/" + messageID )
.set( "authorization", token )
.end( function( err ) {
err ? callback( err ) : callback( null );
} );
}
Internal.XHR.updateMessage = function( token, channelID, messageID, messageParameters, callback ) {
request
.patch( Endpoints.CHANNELS + "/" + channelID + "/messages/" + messageID )
.set( "authorization", token )
.send( messageParameters )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.getChannelLogs = function( token, channelID, amount, callback ) {
request
.get( Endpoints.CHANNELS + "/" + channelID + "/messages?limit=" + amount )
.set( "authorization", token )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.createChannel = function( token, serverID, name, type, callback ) {
request
.post( Endpoints.SERVERS + "/" + serverID + "/channels" )
.set( "authorization", token )
.send( {
name: name,
type: type
} )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.deleteChannel = function( token, channelID, callback ) {
request
.del( Endpoints.CHANNELS + "/" + channelID )
.set( "authorization", token )
.end( function( err ) {
err ? callback( err ) : callback( null );
} );
}
Internal.XHR.deleteServer = function( token, serverID, callback ) {
request
.del( Endpoints.SERVERS + "/" + serverID )
.set( "authorization", token )
.end( function( err ) {
err ? callback( err ) : callback( null );
} );
}
Internal.XHR.getChannels = function( token, serverID, callback ) {
request
.get( Endpoints.SERVERS + "/" + serverID + "/channels" )
.set( "authorization", token )
.end( function( err ) {
err ? callback( err ) : callback( null );
} );
}
Internal.XHR.getServer = function( token, serverID, callback ) {
request
.get( Endpoints.SERVERS + "/" + serverID )
.set( "authorization", token )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body );
}
} );
}
Internal.XHR.acceptInvite = function( token, inviteID, callback ) {
request
.post( Endpoints.API + "/invite/" + inviteID )
.set( "authorization", token )
.end( function( err, res ) {
if ( err ) {
callback( err );
} else {
callback( null, res.body )
}
} );
}
Internal.XHR.setUsername = function( token, avatar, email, newPassword, password, username, callback ) {
request
.patch( Endpoints.API + "/users/@me" )
.set( "authorization", token )
.send( {
avatar: avatar,
email: email,
new_password: newPassword,
password: password,
username: username
} )
.end( function( err ) {
callback( err );
} );
}
exports.Internal = Internal;

21
src/invite.js Normal file
View File

@@ -0,0 +1,21 @@
var User = require("./user.js").User;
exports.Invite = function(json){
this.max_age = json.max_age;
this.code = json.code;
this.server = json.guild;
this.revoked = json.revoked;
this.created_at = Date.parse(json.created_at);
this.temporary = json.temporary;
this.uses = json.uses;
this.max_uses = json.uses;
this.inviter = new User(json.inviter);
this.xkcdpass = json.xkcdpass;
this.channel = json.channel;
}
exports.Invite.prototype.generateInviteURL = function(xkcd){
var code = (xkcd ? this.xkcdpass : this.code);
return "https://discord.gg/"+code;
}

248
src/list.js Normal file
View File

@@ -0,0 +1,248 @@
/**
* Similar to a Java set. Contains no duplicate elements and includes filter
* functions. Discriminates between elements based on a discriminator passed
* when created. Generally "ID"
* @class List
*/
exports.List = function( discriminator, cap ) {
/**
* What to use to distringuish duplicates
* @attribute discriminator
* @type {String}
*/
this.discriminator = discriminator;
/**
* The maximum amount of elements allowed in the list.
* @default Infinity
* @attribute cap
* @type {Number}
*/
this.cap = cap || Number.MAX_SAFE_INTEGER;
/**
* The Array version of the List.
* @type {Array}
* @attribute contents
*/
this.contents = [];
}
/**
* Adds an element to the list if it isn't already there.
* @method add
* @param {Object/Array} element The element(s) to add
* @example
* List.add( obj );
* List.add( [ obj, obj, obj ] );
*/
exports.List.prototype.add = function( child ) {
var self = this;
if ( child.constructor === Array ) {
children = child;
for ( child of children ) {
addChild( child );
}
} else {
addChild( child );
}
function addChild( child ) {
if ( self.length() > self.cap ) {
self.splice( 0, 1 );
}
if ( self.filter( self.discriminator, child[ self.discriminator ] ).length() === 0 )
self.contents.push( child );
}
}
/**
* Returns the length of the List
* @method length
* @return {Number}
*/
exports.List.prototype.length = function() {
return this.contents.length;
}
/**
* Gets the index of an element in the List or defaults to false
* @param {Object} object The element we want to get the index of
* @return {Number/Boolean} The index if the object is in the list, or false.
* @method getIndex
*/
exports.List.prototype.getIndex = function( object ) {
var index = false;
for ( elementIndex in this.contents ) {
var element = this.contents[ elementIndex ];
if ( element[ this.discriminator ] == object[ this.discriminator ] ) {
return elementIndex;
}
}
return index;
}
/**
* Removes an element at the specified index
* @param {Number} index
* @method removeIndex
*/
exports.List.prototype.removeIndex = function( index ) {
this.contents.splice( index, 1 );
}
/**
* Removes an element from the list
* @param {Object} element
* @method removeElement
* @return {Boolean} whether the operation was successful or not.
*/
exports.List.prototype.removeElement = function( child ) {
for ( _element in this.contents ) {
var element = this.contents[ _element ];
if ( child[ this.discriminator ] == element[ this.discriminator ] ) {
this.removeIndex( _element, 1 );
return true;
}
}
return false;
}
/**
* Replaces an element in the list with a specified element
* @method updateElement
* @param {Object} element Element to update.
* @param {Object} newElement New Element
* @return {Boolean} whether the operation was successful or not.
*/
exports.List.prototype.updateElement = function( child, newChild ) {
for ( _element in this.contents ) {
var element = this.contents[ _element ];
if ( child[ this.discriminator ] == element[ this.discriminator ] ) {
this.contents[ _element ] = newChild;
return true;
}
}
return false;
}
exports.List.prototype.concatSublists = function( whereList, discriminator ) {
//this is meant to look at the contents, and assuming the contents are all lists, concatenate their values.
var concatList = new exports.List( discriminator );
for ( item of this.contents ) {
var itemList = item[ whereList ];
concatList.add( itemList.contents );
}
return concatList;
}
exports.List.prototype.filter = function( key, value, onlyOne, caseInsen ) {
var results = [];
value = change( value );
for ( index in this.contents ) {
var child = this.contents[ index ];
if ( change( child[ key ] ) == value ) {
if ( onlyOne ) {
return child;
} else {
results.push( child );
}
}
}
function change( val ) {
if ( caseInsen ) {
val = val.toUpperCase();
}
return val;
}
if ( onlyOne ) {
return false;
}
var retList = new exports.List( this.discriminator );
retList.contents = results;
return retList;
}
exports.List.prototype.getValues = function( key ){
var valList = [];
for( child of this.contents){
valList.push( child[key] );
}
return valList;
}
exports.List.prototype.deepFilter = function( keys, value, onlyOne, caseInsen ) {
var results = [];
value = change( value );
for ( index in this.contents ) {
var child = this.contents[ index ];
var buffer = child;
for ( key of keys ) {
if(buffer instanceof exports.List){
buffer = buffer.contents;
}
if(buffer instanceof Array){
for(elem of buffer){
if( change(elem[key]) == value ){
buffer = elem;
}
}
}
buffer = buffer[ key ];
}
if ( change( buffer ) == value ) {
if ( onlyOne ) {
return child;
} else {
results.push( child );
}
}
}
function change( val ) {
if ( caseInsen ) {
val = val.toUpperCase();
}
return val;
}
if ( onlyOne ) {
return false;
}
var retList = new exports.List( this.discriminator );
retList.contents = results;
return retList;
}

39
src/message.js Normal file
View File

@@ -0,0 +1,39 @@
var User = require( "./user.js" ).User;
var List = require( "./list.js" ).List;
var PMChannel = require( "./PMChannel.js" ).PMChannel;
exports.Message = function( time, author, content, channel, id, mentions, everyoneMentioned, embeds ) {
if ( !content ) {
message = time;
channel = author;
time = message.timestamp;
author = message.author;
content = message.content;
id = message.id;
mentions = message.mentions;
everyoneMentioned = message.mention_everyone;
embeds = message.embeds;
}
this.time = Date.parse( time );
this.author = new User( author );
this.content = content.replace( /\s+/g, ' ' ).trim(); //content.replace(/<[^>]*>/g, "").replace(/\s+/g, ' ').trim();
this.channel = channel;
this.id = id;
this.mentions = new List( "id" );
this.everyoneMentioned = everyoneMentioned;
this.embeds = embeds;
for ( x in mentions ) {
var _mention = mentions[ x ];
this.mentions.add( new User( _mention ) );
}
}
exports.Message.prototype.isPM = function() {
return ( this.channel instanceof PMChannel );
}
exports.Message.prototype.isMentioned = function( user ) {
return ( this.mentions.filter( "id", user.id ).length > 0 );
}

106
src/server.js Normal file
View File

@@ -0,0 +1,106 @@
var User = require( "./user.js" ).User;
var List = require( "./list.js" ).List;
/**
* A wrapper for Server information, contains channels and users too. Developers should not instantiate the class, instead they should
* manipulate Server objects given to them.
* @class Server
* @param {String} region The region of the server
*/
exports.Server = function( region, ownerID, name, id, members, icon, afkTimeout, afkChannelId ) {
/**
* The region of the Server
* @type {String}
* @attribute region
*/
this.region = region;
/**
* The ID of the owner of the Server (not a User!)
* @type {String}
* @attribute ownerID
*/
this.ownerID = ownerID;
/**
* The name of the Server
* @type {String}
* @attribute name
*/
this.name = name;
/**
* The ID of the Server
* @type {String}
* @attribute id
*/
this.id = id;
/**
* List containing members of the Server
* @param {List}
* @attribute members
*/
this.members = new List( "id" );
/**
* List containing channelss of the Server
* @param {List}
* @attribute channels
*/
this.channels = new List( "id" );
/**
* ID of the Icon of the Server
* @param {String}
* @attribute icon
*/
this.icon = icon;
/**
* The amount of seconds that should pass before the user is
* @type {Number}
* @attribute afkTimeout
*/
this.afkTimeout = afkTimeout;
/**
* The ID of the AFK Channel, evaluates to false if doesn't exist.
* @type {String}
* @attribute afkChannelId
*/
this.afkChannelId = afkChannelId;
for ( x in members ) {
var member = members[ x ].user;
this.members.add( new User( member ) );
}
}
/**
* Returns a valid URL pointing towards the server's icon if it has one.
* @method getIconURL
* @return {String/Boolean} If there is an icon, a URL is returned. If not, false is returned.
*/
exports.Server.prototype.getIconURL = function(){
if(!this.icon)
return false;
return "https://discordapp.com/api/guilds/"+this.id+"/icons/"+this.icon+".jpg";
}
/**
* Returns the AFK Channel if a server has one
* @method getAFKChannel
* @return {Channel/Boolean} If there is an AFK Channel, a Channel is returned. If not, false is returned.
*/
exports.Server.prototype.getAFKChannel = function(){
if(!this.afkChannelId)
return false;
return this.channels.filter("id", this.afkChannelId, true);
}
/**
* Returns the #general channel of the server.
* @method getDefaultChannel
* @return {Channel} Returns the #general channel of the Server.
*/
exports.Server.prototype.getDefaultChannel = function() {
return this.channels.filter( "name", "general", true );
}

37
src/user.js Normal file
View File

@@ -0,0 +1,37 @@
exports.User = function( username, id, discriminator, avatar ) {
if ( !id ) { //there's no second argument
var user = username;
username = user.username;
id = user.id;
discriminator = user.discriminator;
avatar = user.avatar;
}
this.username = username;
this.discriminator = discriminator;
this.id = id;
this.avatar = avatar;
}
exports.User.prototype.getAvatarURL = function() {
if ( !this.avatar )
return false;
return "https://discordapp.com/api/users/" + this.id + "/avatars/" + this.avatar + ".jpg";
}
exports.User.prototype.mention = function() {
return "<@" + this.id + ">";
}
exports.User.prototype.equals = function( otherUser ) {
return otherUser.id === this.id;
}
exports.User.prototype.equalsStrict = function( otherUser ) {
return ( this.username === otherUser.username && this.discriminator === otherUser.discriminator && this.id === otherUser.id && this.avatar === otherUser.avatar );
}