blah
This commit is contained in:
commit
4bbee1160d
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
cfg/
|
||||||
|
node_modules/
|
2940
package-lock.json
generated
Normal file
2940
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
33
package.json
Normal file
33
package.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "keinBotv3",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Bot, kennste?",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "./node_modules/.bin/babel src --presets=es2015 --plugins=add-module-exports --out-dir dist",
|
||||||
|
"start": "npm run build && node dist/index.js"
|
||||||
|
},
|
||||||
|
"author": "Flummi & jkhsjdhjs",
|
||||||
|
"license": "WTFPL",
|
||||||
|
"dependencies": {
|
||||||
|
"axon": "1.0.0",
|
||||||
|
"cloudscraper": "^1.4.1",
|
||||||
|
"eventemitter2": "0.4.13",
|
||||||
|
"forever-monitor": "^1.7.1",
|
||||||
|
"irc-colors": "^1.4.0",
|
||||||
|
"irc-message": "2.0.1",
|
||||||
|
"irc-socket": "github:ircanywhere/irc-socket",
|
||||||
|
"json-stringify-safe": "^5.0.0",
|
||||||
|
"lodash": "2.4.1",
|
||||||
|
"nodejs-mysql": "^0.1.3",
|
||||||
|
"pause-queue": "~0.1.0",
|
||||||
|
"safe-eval": "^0.3.0",
|
||||||
|
"youtube-dl": "^1.12.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-cli": "^6.26.0",
|
||||||
|
"babel-core": "^6.26.0",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-preset-es2015": "^6.24.1"
|
||||||
|
}
|
||||||
|
}
|
25
src/bot.js
Normal file
25
src/bot.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { cfg, read } from './inc/cfg.js';
|
||||||
|
|
||||||
|
|
||||||
|
read().then(() => {
|
||||||
|
console.log( cfg );
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*var config = new (require(__dirname+'/inc/cfg'))();
|
||||||
|
config.read()
|
||||||
|
.then(
|
||||||
|
data => {
|
||||||
|
config.cfg = data;
|
||||||
|
var lib = new (require(__dirname+'/inc/lib'))(config.cfg);
|
||||||
|
lib.events.on('message', function(msg) {
|
||||||
|
if( msg.event[1] === 'privmsg' ) {
|
||||||
|
var e = lib.reply(msg);
|
||||||
|
console.log( `(${e.time}) ${e.network} -> ${e.channel} -> ${e.user.nick}: ${e.message}` );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
console.log( "error! " + err );
|
||||||
|
}
|
||||||
|
)*/
|
38
src/inc/cfg.js
Normal file
38
src/inc/cfg.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import sql from './sql.js';
|
||||||
|
|
||||||
|
let cfg = {
|
||||||
|
irc: {},
|
||||||
|
main: {},
|
||||||
|
websrv: {},
|
||||||
|
trigger: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const read = () => new Promise((resolve, reject) => {
|
||||||
|
sql.exec("select * from `cfg`", (err, rows) => {
|
||||||
|
if(err || rows.length < 1)
|
||||||
|
reject({ error: "no cfg" });
|
||||||
|
else {
|
||||||
|
for(let row in rows) {
|
||||||
|
cfg[rows[row].class ][ rows[row].key] = ((type, value) => {
|
||||||
|
switch(type) {
|
||||||
|
case 'string':
|
||||||
|
return value;
|
||||||
|
break;
|
||||||
|
case 'int':
|
||||||
|
return parseInt(value);
|
||||||
|
break;
|
||||||
|
case 'bool':
|
||||||
|
return (value === 'true')?true:false;
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
return JSON.parse(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})(rows[row].type, rows[row].value);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
export { cfg, read };
|
0
src/inc/events.js
Normal file
0
src/inc/events.js
Normal file
94
src/inc/events/message.js
Normal file
94
src/inc/events/message.js
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
const safeEval = require('safe-eval');
|
||||||
|
const util = require('util');
|
||||||
|
const fs = require('fs');
|
||||||
|
const ytdl = util.promisify(require('youtube-dl').getInfo);
|
||||||
|
require('irc-colors').global();
|
||||||
|
|
||||||
|
module.exports = (lib) => {
|
||||||
|
lib.events.on('message', function(msg) {
|
||||||
|
if( msg.event[1] === 'privmsg' ) { // Triggerauswertung und blah
|
||||||
|
//lib.rpc.emit('call', 'rizon', 'privmsg', [ '#f0ck', JSON.stringify(msg) ]);
|
||||||
|
var e = lib.reply(msg);
|
||||||
|
switch(e.message) {
|
||||||
|
case "1":
|
||||||
|
e.reply("normal");
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
e.replyAction("action");
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
e.replyNotice("notice");
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
e.reply("Debugzeugs (lib.interfaces.rpc.sock) in die Konsole pfostiert.");
|
||||||
|
console.log(lib.interfaces.rpc.sock);
|
||||||
|
break;
|
||||||
|
case "6":
|
||||||
|
e.reply("\x02!kick kbotv3\x02");
|
||||||
|
break;
|
||||||
|
case "5":
|
||||||
|
e.reply("!kick kbotv3");
|
||||||
|
break;
|
||||||
|
case "whois":
|
||||||
|
lib.rpc.emit('call', e.network, 'raw', [ 'whois', e.user.nick ]);
|
||||||
|
e.reply(`whois an ${e.user.nick} ist raus!`);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(e.user.nick === "Flummi" || e.user.nick === "jkhsjdhjs" || e.user.nick === "pFT" || e.user.nick === "mrhanky" || e.user.nick === "gz") {
|
||||||
|
if(e.message.match(/^\.js /)) { // JS-Sandbox
|
||||||
|
let args = e.message.substring(3);
|
||||||
|
var context = {
|
||||||
|
e: e,
|
||||||
|
msg: msg,
|
||||||
|
setInterval: setInterval,
|
||||||
|
clearInterval: clearInterval
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var output = safeEval(args, context);
|
||||||
|
if(typeof output !== undefined && output !== 'undefined' && output) {
|
||||||
|
let blah = JSON.stringify( output );
|
||||||
|
if(blah != "Converting circular structure to JSON")
|
||||||
|
e.reply( blah.length > 250 ? `holy fuck, Ausgabe wäre viel zu lang! (${blah.length} Zeichen :DDDDDD)` : blah );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
e.reply(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(e.message.match(/https?:\/\/[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?/gi)) { // parser
|
||||||
|
let links = e.message.match(/https?:\/\/[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?/gi);
|
||||||
|
const args = [
|
||||||
|
//"-j",
|
||||||
|
//"-q",
|
||||||
|
"--no-progress",
|
||||||
|
"--no-warnings",
|
||||||
|
"--no-check-certificate",
|
||||||
|
"--max-filesize 500m",
|
||||||
|
'-o "./tmp/%(title)s.%(ext)s"'
|
||||||
|
];
|
||||||
|
|
||||||
|
Promise.all( links.map( link => checkRepost( link ) ) ) // repostcheck
|
||||||
|
.then( res => Promise.all( res.map( link => ytdl(link) ) ) ) // get informations
|
||||||
|
.then( res => {
|
||||||
|
res.forEach( data => {
|
||||||
|
e.reply( data.title );
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( msg.event === 'metadata' )
|
||||||
|
console.log(msg);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function checkRepost(link) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve( link );
|
||||||
|
});
|
||||||
|
}
|
9
src/inc/events/sync.js
Normal file
9
src/inc/events/sync.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = (lib) => {
|
||||||
|
lib.events.on('message', function(msg) {
|
||||||
|
if( msg.event == 'synchronize' ) {
|
||||||
|
if( msg.keys.length == 0 )
|
||||||
|
setTimeout(lib.loadIRC, 500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
11
src/inc/events/whois.js
Normal file
11
src/inc/events/whois.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
module.exports = (lib) => {
|
||||||
|
lib.events.on('message', function(msg) {
|
||||||
|
if( msg.event[1] === 'whois' || (msg.event[1] === 'unknown' && msg.message.command === 'RPL_WHOISNICKSERVREG') ) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( msg.event[1] === 'who' ) {
|
||||||
|
console.log(msg.message.who);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
243
src/inc/irc/api.js
Normal file
243
src/inc/irc/api.js
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
var child_process,
|
||||||
|
axon = require('axon'),
|
||||||
|
_ = require('lodash'),
|
||||||
|
QueuePool = require(__dirname + '/queuepool').QueuePool,
|
||||||
|
irc = require(__dirname + '/irc'),
|
||||||
|
readWriteStream = require(__dirname + '/stub.js').ReadWriteNetStream,
|
||||||
|
stringify = require('json-stringify-safe'),
|
||||||
|
Events = irc.Events,
|
||||||
|
Client = irc.Client,
|
||||||
|
Clients = {};
|
||||||
|
|
||||||
|
function Api() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this._keepOpen = false;
|
||||||
|
this._eventQueue = [];
|
||||||
|
this._rpcClients = 0;
|
||||||
|
// some internal settings
|
||||||
|
|
||||||
|
process.on('uncaughtException', function(err) {
|
||||||
|
self.emit('uncaughtException', {message: stringify(err)});
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Api.prototype.getClient = function(key) {
|
||||||
|
return Clients[key].irc.supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.prototype.setupServer = function(options) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
axon.codec.define('json', {
|
||||||
|
encode: JSON.stringify,
|
||||||
|
decode: JSON.parse
|
||||||
|
});
|
||||||
|
// setup a json codec
|
||||||
|
|
||||||
|
this._events = axon.socket('push');
|
||||||
|
this._events.bind(options.events);
|
||||||
|
this._events.format('json');
|
||||||
|
// setup the events socket
|
||||||
|
|
||||||
|
this._events.on('connect', function() {
|
||||||
|
self.emit('metadata', {pid: process.pid, incomingPort: options.rpc, outgoingPort: options.events});
|
||||||
|
self.emit('synchronize', {keys: _.keys(Clients)});
|
||||||
|
});
|
||||||
|
// setup some events for our outbound port
|
||||||
|
|
||||||
|
this._rpc = axon.socket('sub-emitter');
|
||||||
|
this._rpc.bind(options.rpc);
|
||||||
|
// we also setup an inbound socket which uses the sub emitter
|
||||||
|
|
||||||
|
this._rpc.on('createClient', function(key, client, dummy) {
|
||||||
|
self.unhookEvent(key, '*');
|
||||||
|
// do this first
|
||||||
|
|
||||||
|
var user = self.createClient(key, client, dummy || false);
|
||||||
|
// create the client
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// bail
|
||||||
|
|
||||||
|
self.hookEvent(key, '*', function(object) {
|
||||||
|
self.emit(this.event, {message: object});
|
||||||
|
});
|
||||||
|
// we're obviously using the rpc to create clients, so they don't
|
||||||
|
// have an option to hook events, they just get the lot, and choose what they
|
||||||
|
// wanna do with them on their incoming pipe
|
||||||
|
});
|
||||||
|
|
||||||
|
//this._rpc.on('test', function(key, client, dummy)
|
||||||
|
|
||||||
|
this._rpc.on('destroyClient', function(key) {
|
||||||
|
self.destroyClient(key);
|
||||||
|
// delete client
|
||||||
|
});
|
||||||
|
|
||||||
|
this._rpc.on('call', function(key, call, params) {
|
||||||
|
if (!_.has(Clients, key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var client = Clients[key];
|
||||||
|
// get the client object
|
||||||
|
|
||||||
|
if (!_.has(Client.prototype, call)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// property is undefined
|
||||||
|
|
||||||
|
if (_.isArray(params) && call !== 'raw') {
|
||||||
|
Client.prototype[call].apply(client.irc, params);
|
||||||
|
} else {
|
||||||
|
Client.prototype[call].call(client.irc, params);
|
||||||
|
}
|
||||||
|
// call the function
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Api.prototype.connect = function(options) {
|
||||||
|
var self = this,
|
||||||
|
interfaces = {
|
||||||
|
events: axon.socket('pull'),
|
||||||
|
rpc: axon.socket('pub-emitter')
|
||||||
|
};
|
||||||
|
// create these so our end-user doesn't have to
|
||||||
|
|
||||||
|
axon.codec.define('json', {
|
||||||
|
encode: JSON.stringify,
|
||||||
|
decode: JSON.parse
|
||||||
|
});
|
||||||
|
// setup a json codec
|
||||||
|
|
||||||
|
interfaces.rpc.connect(options.rpc);
|
||||||
|
// setup our outgoing connection
|
||||||
|
|
||||||
|
interfaces.events.connect(options.events);
|
||||||
|
interfaces.events.format('json');
|
||||||
|
// setup our incoming connection
|
||||||
|
|
||||||
|
if (!options.automaticSetup) {
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
// just return interfaces if handleErrors is false
|
||||||
|
|
||||||
|
interfaces.events.on('socket error', function(e) {
|
||||||
|
if (e.syscall === 'connect' && e.code === 'ECONNREFUSED') {
|
||||||
|
self.setupServer(options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// socket error
|
||||||
|
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
Api.prototype.emit = function(event, data) {
|
||||||
|
if (this._events) {
|
||||||
|
this._events.send(_.extend({event: event}, data));
|
||||||
|
} else {
|
||||||
|
Events.emit(event, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// the following functions let us manage clients by creating
|
||||||
|
// them, and destroying them
|
||||||
|
|
||||||
|
Api.prototype.createClient = function(key, object, dummy) {
|
||||||
|
var self = this,
|
||||||
|
dummy = dummy || false,
|
||||||
|
socket = (dummy) ? readWriteStream : undefined;
|
||||||
|
// we can create a dummy client with stub.js for testing purposes
|
||||||
|
|
||||||
|
if (_.has(Clients, key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// check if a client with this key exists, don't bother throwing, too risky to be
|
||||||
|
// exiting the process over this sort of stuff.
|
||||||
|
|
||||||
|
Clients[key] = {
|
||||||
|
key: key,
|
||||||
|
options: object,
|
||||||
|
dummy: dummy,
|
||||||
|
irc: new Client(key, object, socket),
|
||||||
|
events: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hookEvent(key, 'failed', function(message) {
|
||||||
|
setTimeout(function() {
|
||||||
|
self.destroyClient(key);
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
// hook onto a failed event and destroy the client
|
||||||
|
|
||||||
|
this.hookEvent(key, 'throttled', function(message) {
|
||||||
|
QueuePool.queuePause(object.server);
|
||||||
|
});
|
||||||
|
// hook onto a throttling event
|
||||||
|
|
||||||
|
return Clients[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
Api.prototype.destroyClient = function(key) {
|
||||||
|
if (!_.has(Clients, key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// no client exists, lets bail
|
||||||
|
|
||||||
|
Clients[key].irc.disconnect();
|
||||||
|
// send a disconnect to be nice
|
||||||
|
|
||||||
|
delete Clients[key].irc;
|
||||||
|
delete Clients[key];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// the following functions handle hooking onto events
|
||||||
|
// and unhooking them
|
||||||
|
|
||||||
|
Api.prototype.hookEvent = function(key, e, callback, once) {
|
||||||
|
var once = once || false;
|
||||||
|
// check for once at the end, if so only apply event once
|
||||||
|
|
||||||
|
if (once) {
|
||||||
|
Events.once([key, e], callback);
|
||||||
|
} else {
|
||||||
|
Events.off([key, e], callback);
|
||||||
|
Events.on([key, e], callback);
|
||||||
|
}
|
||||||
|
// add the hook
|
||||||
|
};
|
||||||
|
|
||||||
|
Api.prototype.unhookEvent = function(key, e, callback) {
|
||||||
|
if (!callback) {
|
||||||
|
Events.removeAllListeners([key, e]);
|
||||||
|
} else {
|
||||||
|
Events.off([key, e], callback);
|
||||||
|
}
|
||||||
|
// add the hook
|
||||||
|
};
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
Error.prototype.toJSON = function () {
|
||||||
|
var json = {};
|
||||||
|
Object.getOwnPropertyNames(this).forEach(addToJSON, this);
|
||||||
|
return json;
|
||||||
|
|
||||||
|
function addToJSON(name) {
|
||||||
|
var pd = Object.getOwnPropertyDescriptor(this, name);
|
||||||
|
pd.enumerable = true;
|
||||||
|
Object.defineProperty(json, name, pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.Api = Api;
|
||||||
|
exports.axon = axon;
|
330
src/inc/irc/codes.js
Normal file
330
src/inc/irc/codes.js
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
module.exports = {
|
||||||
|
'001': 'RPL_WELCOME',
|
||||||
|
'002': 'RPL_YOURHOST', // RFC2812
|
||||||
|
'003': 'RPL_CREATED', // RFC2812
|
||||||
|
'004': 'RPL_MYINFO', // RFC2812
|
||||||
|
'005': 'RPL_ISUPPORT', // draft-brocklesby-irc-isupport-03
|
||||||
|
'008': 'RPL_SNOMASK', // ircu
|
||||||
|
'009': 'RPL_STATMEMTOT', // ircu
|
||||||
|
'010': 'RPL_REDIR', // ratbox
|
||||||
|
'014': 'RPL_YOURCOOKIE', // IRCnet
|
||||||
|
'015': 'RPL_MAP', // ircu
|
||||||
|
'016': 'RPL_MAPMORE', // ircu
|
||||||
|
'017': 'RPL_MAPEND', // ircu
|
||||||
|
'020': 'RPL_CONNECTING', // IRCnet
|
||||||
|
'042': 'RPL_YOURID', // IRCnet
|
||||||
|
'043': 'RPL_SAVENICK', // IRCnet
|
||||||
|
'050': 'RPL_ATTEMPTINGJUNC', // aircd
|
||||||
|
'051': 'RPL_ATTEMPTINGREROUTE', // aircd
|
||||||
|
|
||||||
|
'200': 'RPL_TRACELINK', // RFC1459
|
||||||
|
'201': 'RPL_TRACECONNECTING', // RFC1459
|
||||||
|
'202': 'RPL_TRACEHANDSHAKE', // RFC1459
|
||||||
|
'203': 'RPL_TRACEUNKNOWN', // RFC1459
|
||||||
|
'204': 'RPL_TRACEOPERATOR', // RFC1459
|
||||||
|
'205': 'RPL_TRACEUSER', // RFC1459
|
||||||
|
'206': 'RPL_TRACESERVER', // RFC1459
|
||||||
|
'207': 'RPL_TRACECAPTURED', // hybrid (RFC2812 TRACESERVICE)
|
||||||
|
'208': 'RPL_TRACENEWTYPE', // RFC1459
|
||||||
|
'209': 'RPL_TRACECLASS', // RFC2812
|
||||||
|
'210': 'RPL_STATS', // aircd (single stats reply)
|
||||||
|
'211': 'RPL_STATSLINKINFO', // RFC1459
|
||||||
|
'212': 'RPL_STATSCOMMANDS', // RFC1459
|
||||||
|
'213': 'RPL_STATSCLINE', // RFC1459
|
||||||
|
'214': 'RPL_STATSNLINE', // RFC1459
|
||||||
|
'215': 'RPL_STATSILINE', // RFC1459
|
||||||
|
'216': 'RPL_STATSKLINE', // RFC1459
|
||||||
|
'217': 'RPL_STATSQLINE', // RFC1459
|
||||||
|
'218': 'RPL_STATSYLINE', // RFC1459
|
||||||
|
'219': 'RPL_ENDOFSTATS', // RFC1459
|
||||||
|
|
||||||
|
'220': 'RPL_STATSPLINE', // hybrid
|
||||||
|
'221': 'RPL_UMODEIS', // RFC1459
|
||||||
|
'222': 'RPL_SQLINE_NICK', // DALnet
|
||||||
|
'223': 'RPL_STATSGLINE', // Unreal
|
||||||
|
'224': 'RPL_STATSFLINE', // hybrid
|
||||||
|
'225': 'RPL_STATSDLINE', // hybrid
|
||||||
|
'226': 'RPL_STATSALINE', // hybrid
|
||||||
|
'227': 'RPL_STATSVLINE', // Unreal
|
||||||
|
'228': 'RPL_STATSCCOUNT', // hybrid
|
||||||
|
|
||||||
|
'231': 'RPL_SERVICEINFO', // RFC1459
|
||||||
|
'233': 'RPL_SERVICE', // RFC1459
|
||||||
|
'234': 'RPL_SERVLIST', // RFC1459
|
||||||
|
'235': 'RPL_SERVLISTEND', // RFC1459
|
||||||
|
'239': 'RPL_STATSIAUTH', // IRCnet
|
||||||
|
|
||||||
|
'241': 'RPL_STATSLLINE', // RFC1459
|
||||||
|
'242': 'RPL_STATSUPTIME', // RFC1459
|
||||||
|
'243': 'RPL_STATSOLINE', // RFC1459
|
||||||
|
'244': 'RPL_STATSHLINE', // RFC1459
|
||||||
|
'245': 'RPL_STATSSLINE', // Bahamut, IRCnet, hybrid
|
||||||
|
'247': 'RPL_STATSXLINE', // hybrid
|
||||||
|
'248': 'RPL_STATSULINE', // hybrid
|
||||||
|
'249': 'RPL_STATSDEBUG', // hybrid
|
||||||
|
|
||||||
|
'250': 'RPL_STATSCONN', // ircu, Unreal, hybrid
|
||||||
|
'251': 'RPL_LUSERCLIENT', // RFC1459
|
||||||
|
'252': 'RPL_LUSEROP', // RFC1459
|
||||||
|
'253': 'RPL_LUSERUNKNOWN', // RFC1459
|
||||||
|
'254': 'RPL_LUSERCHANNELS', // RFC1459
|
||||||
|
'255': 'RPL_LUSERME', // RFC1459
|
||||||
|
'256': 'RPL_ADMINME', // RFC1459
|
||||||
|
'257': 'RPL_ADMINLOC1', // RFC1459
|
||||||
|
'258': 'RPL_ADMINLOC2', // RFC1459
|
||||||
|
'259': 'RPL_ADMINEMAIL', // RFC1459
|
||||||
|
|
||||||
|
'261': 'RPL_TRACELOG', // RFC1459
|
||||||
|
'262': 'RPL_ENDOFTRACE', // hybrid
|
||||||
|
'263': 'RPL_LOAD2HI', // hybrid
|
||||||
|
'265': 'RPL_LOCALUSERS', // aircd, Bahamut, hybrid
|
||||||
|
'266': 'RPL_GLOBALUSERS', // aircd, Bahamut, hybrid
|
||||||
|
'267': 'RPL_START_NETSTAT', // aircd
|
||||||
|
'268': 'RPL_NETSTAT', // aircd
|
||||||
|
'269': 'RPL_END_NETSTAT', // aircd
|
||||||
|
|
||||||
|
'270': 'RPL_PRIVS', // ircu
|
||||||
|
'271': 'RPL_SILELIST', // ircu
|
||||||
|
'272': 'RPL_ENDOFSILELIST', // ircu
|
||||||
|
'275': 'RPL_WHOISSSL', // oftc-hybrid
|
||||||
|
'276': 'RPL_WHOISCERTFP', // oftc-hybrid
|
||||||
|
|
||||||
|
'280': 'RPL_GLIST', // ircu
|
||||||
|
'281': 'RPL_ACCEPTLIST', // ratbox/chary
|
||||||
|
'282': 'RPL_ENDOFACCEPT', // ratbox/chary
|
||||||
|
|
||||||
|
'300': 'RPL_NONE', // RFC1459
|
||||||
|
'301': 'RPL_AWAY', // RFC1459
|
||||||
|
'302': 'RPL_USERHOST', // RFC1459
|
||||||
|
'303': 'RPL_ISON', // RFC1459
|
||||||
|
'304': 'RPL_TEXT', // hybrid
|
||||||
|
'305': 'RPL_UNAWAY', // RFC1459
|
||||||
|
'306': 'RPL_NOWAWAY', // RFC1459
|
||||||
|
'307': 'RPL_WHOISNICKSERVREG', // An issue of contention.
|
||||||
|
'308': 'RPL_WHOISADMIN', // hybrid
|
||||||
|
|
||||||
|
'310': 'RPL_WHOISMODES', // Plexus
|
||||||
|
'311': 'RPL_WHOISUSER', // RFC1459
|
||||||
|
'312': 'RPL_WHOISSERVER', // RFC1459
|
||||||
|
'313': 'RPL_WHOISOPERATOR', // RFC1459
|
||||||
|
'314': 'RPL_WHOWASUSER', // RFC1459
|
||||||
|
'315': 'RPL_ENDOFWHO', // RFC1459
|
||||||
|
'316': 'RPL_WHOISCHANOP', // reserved in rb/chary
|
||||||
|
'317': 'RPL_WHOISIDLE', // RFC1459
|
||||||
|
'318': 'RPL_ENDOFWHOIS', // RFC1459
|
||||||
|
'319': 'RPL_WHOISCHANNELS', // RFC1459
|
||||||
|
|
||||||
|
'321': 'RPL_LISTSTART', // RFC1459
|
||||||
|
'322': 'RPL_LIST', // RFC1459
|
||||||
|
'323': 'RPL_LISTEND', // RFC1459
|
||||||
|
'324': 'RPL_CHANNELMODEIS', // RFC1459
|
||||||
|
'325': 'RPL_CHANNELMLOCK', // sorircd 1.3
|
||||||
|
'328': 'RPL_CHANNELURL', // ratbox/chary
|
||||||
|
'329': 'RPL_CREATIONTIME', // Bahamut
|
||||||
|
|
||||||
|
'330': 'RPL_WHOISLOGGEDIN', // ratbox/chary
|
||||||
|
'331': 'RPL_NOTOPIC', // RFC1459
|
||||||
|
'332': 'RPL_TOPIC', // RFC1459
|
||||||
|
'333': 'RPL_TOPICWHOTIME', // ircu
|
||||||
|
'337': 'RPL_WHOISTEXT', // ratbox/chary
|
||||||
|
'338': 'RPL_WHOISACTUALLY', // Bahamut, ircu
|
||||||
|
|
||||||
|
'340': 'RPL_USERIP', // ircu
|
||||||
|
'341': 'RPL_INVITING', // RFC1459
|
||||||
|
'342': 'RPL_SUMMONING', // RFC1459
|
||||||
|
'345': 'RPL_INVITED', // GameSurge
|
||||||
|
'346': 'RPL_INVITELIST', // RFC2812
|
||||||
|
'347': 'RPL_ENDOFINVITELIST', // RFC2812
|
||||||
|
'348': 'RPL_EXCEPTLIST', // RFC2812
|
||||||
|
'349': 'RPL_ENDOFEXCEPTLIST', // RFC2812
|
||||||
|
|
||||||
|
'351': 'RPL_VERSION', // RFC1459
|
||||||
|
'352': 'RPL_WHOREPLY', // RFC1459
|
||||||
|
'353': 'RPL_NAMREPLY', // RFC1459
|
||||||
|
'354': 'RPL_WHOSPCRPL', // ircu
|
||||||
|
|
||||||
|
'360': 'RPL_WHOWASREAL', // ratbox/chary
|
||||||
|
'361': 'RPL_KILLDONE', // RFC1459
|
||||||
|
'362': 'RPL_CLOSING', // RFC1459
|
||||||
|
'363': 'RPL_CLOSEEND', // RFC1459
|
||||||
|
'364': 'RPL_LINKS', // RFC1459
|
||||||
|
'365': 'RPL_ENDOFLINKS', // RFC1459
|
||||||
|
'366': 'RPL_ENDOFNAMES', // RFC1459
|
||||||
|
'367': 'RPL_BANLIST', // RFC1459
|
||||||
|
'368': 'RPL_ENDOFBANLIST', // RFC1459
|
||||||
|
'369': 'RPL_ENDOFWHOWAS', // RFC1459
|
||||||
|
|
||||||
|
'371': 'RPL_INFO', // RFC1459
|
||||||
|
'372': 'RPL_MOTD', // RFC1459
|
||||||
|
'373': 'RPL_INFOSTART', // RFC1459
|
||||||
|
'374': 'RPL_ENDOFINFO', // RFC1459
|
||||||
|
'375': 'RPL_MOTDSTART', // RFC1459
|
||||||
|
'376': 'RPL_ENDOFMOTD', // RFC1459
|
||||||
|
'378': 'RPL_WHOISHOST', // charybdis
|
||||||
|
|
||||||
|
'381': 'RPL_YOUREOPER', // RFC1459
|
||||||
|
'382': 'RPL_REHASHING', // RFC1459
|
||||||
|
'383': 'RPL_YOURESERVICE', // RFC2812
|
||||||
|
'384': 'RPL_MYPORTIS', // RFC1459
|
||||||
|
'385': 'RPL_NOTOPERANYMORE', // AustHex, hybrid, Unreal
|
||||||
|
'386': 'RPL_RSACHALLENGE', // ratbox
|
||||||
|
|
||||||
|
'391': 'RPL_TIME', // RFC1459
|
||||||
|
'392': 'RPL_USERSSTART', // RFC1459
|
||||||
|
'393': 'RPL_USERS', // RFC1459
|
||||||
|
'394': 'RPL_ENDOFUSERS', // RFC1459
|
||||||
|
'395': 'RPL_NOUSERS', // RFC1459
|
||||||
|
'396': 'RPL_HOSTHIDDEN', // ircu
|
||||||
|
|
||||||
|
'401': 'ERR_NOSUCHNICK', // RFC1459
|
||||||
|
'402': 'ERR_NOSUCHSERVER', // RFC1459
|
||||||
|
'403': 'ERR_NOSUCHCHANNEL', // RFC1459
|
||||||
|
'404': 'ERR_CANNOTSENDTOCHAN', // RFC1459
|
||||||
|
'405': 'ERR_TOOMANYCHANNELS', // RFC1459
|
||||||
|
'406': 'ERR_WASNOSUCHNICK', // RFC1459
|
||||||
|
'407': 'ERR_TOOMANYTARGETS', // RFC1459
|
||||||
|
'408': 'ERR_NOSUCHSERVICE', // RFC2812
|
||||||
|
'409': 'ERR_NOORIGIN', // RFC1459
|
||||||
|
|
||||||
|
'410': 'ERR_INVALIDCAPCMD', // hybrid
|
||||||
|
'411': 'ERR_NORECIPIENT', // RFC1459
|
||||||
|
'412': 'ERR_NOTEXTTOSEND', // RFC1459
|
||||||
|
'413': 'ERR_NOTOPLEVEL', // RFC1459
|
||||||
|
'414': 'ERR_WILDTOPLEVEL', // RFC1459
|
||||||
|
'415': 'ERR_BADMASK', // RFC2812
|
||||||
|
'416': 'ERR_TOOMANYMATCHES', // ratbox
|
||||||
|
|
||||||
|
'421': 'ERR_UNKNOWNCOMMAND', // RFC1459
|
||||||
|
'422': 'ERR_NOMOTD', // RFC1459
|
||||||
|
'423': 'ERR_NOADMININFO', // RFC1459
|
||||||
|
'424': 'ERR_FILEERROR', // RFC1459
|
||||||
|
'425': 'ERR_NOOPERMOTD', // Unreal
|
||||||
|
'429': 'ERR_TOOMANYAWAY', // Bahamut
|
||||||
|
|
||||||
|
'430': 'ERR_EVENTNICKCHANGE', // AustHex
|
||||||
|
'431': 'ERR_NONICKNAMEGIVEN', // RFC1459
|
||||||
|
'432': 'ERR_ERRONEUSNICKNAME', // RFC1459
|
||||||
|
'433': 'ERR_NICKNAMEINUSE', // RFC1459
|
||||||
|
'436': 'ERR_NICKCOLLISION', // RFC1459
|
||||||
|
'437': 'ERR_UNAVAILRESOURCE', // hybrid
|
||||||
|
'438': 'ERR_NICKTOOFAST', // hybrid
|
||||||
|
'439': 'ERR_TARGETTOOFAST', // ircu
|
||||||
|
|
||||||
|
'440': 'ERR_SERVICESDOWN', // Bahamut, Unreal
|
||||||
|
'441': 'ERR_USERNOTINCHANNEL', // RFC1459
|
||||||
|
'442': 'ERR_NOTONCHANNEL', // RFC1459
|
||||||
|
'443': 'ERR_USERONCHANNEL', // RFC1459
|
||||||
|
'444': 'ERR_NOLOGIN', // RFC1459
|
||||||
|
'445': 'ERR_SUMMONDISABLED', // RFC1459
|
||||||
|
'446': 'ERR_USERSDISABLED', // RFC1459
|
||||||
|
'447': 'ERR_NONICKCHANGE', // Unreal
|
||||||
|
'449': 'ERR_NOTIMPLEMENTED', // ircu
|
||||||
|
|
||||||
|
'451': 'ERR_NOTREGISTERED', // RFC1459
|
||||||
|
'455': 'ERR_HOSTILENAME', // Unreal
|
||||||
|
'456': 'ERR_ACCEPTFULL', // hybrid
|
||||||
|
'457': 'ERR_ACCEPTEXIST', // hybrid
|
||||||
|
'458': 'ERR_ACCEPTNOT', // hybrid
|
||||||
|
'459': 'ERR_NOHIDING', // Unreal
|
||||||
|
|
||||||
|
'460': 'ERR_NOTFORHALFOPS', // Unreal
|
||||||
|
'461': 'ERR_NEEDMOREPARAMS', // RFC1459
|
||||||
|
'462': 'ERR_ALREADYREGISTRED', // RFC1459
|
||||||
|
'463': 'ERR_NOPERMFORHOST', // RFC1459
|
||||||
|
'464': 'ERR_PASSWDMISMATCH', // RFC1459
|
||||||
|
'465': 'ERR_YOUREBANNEDCREEP', // RFC1459
|
||||||
|
'466': 'ERR_YOUWILLBEBANNED', // RFC1459
|
||||||
|
'467': 'ERR_KEYSET', // RFC1459
|
||||||
|
'469': 'ERR_LINKSET', // Unreal
|
||||||
|
|
||||||
|
'470': 'ERR_LINKCHANNEL', // charybdis
|
||||||
|
'471': 'ERR_CHANNELISFULL', // RFC1459
|
||||||
|
'472': 'ERR_UNKNOWNMODE', // RFC1459
|
||||||
|
'473': 'ERR_INVITEONLYCHAN', // RFC1459
|
||||||
|
'474': 'ERR_BANNEDFROMCHAN', // RFC1459
|
||||||
|
'475': 'ERR_BADCHANNELKEY', // RFC1459
|
||||||
|
'476': 'ERR_BADCHANMASK', // RFC2812
|
||||||
|
'477': 'ERR_NEEDREGGEDNICK', // ratbox (REGONLYCHAN in hyb7)
|
||||||
|
'478': 'ERR_BANLISTFULL', // ircu
|
||||||
|
'479': 'ERR_BADCHANNAME', // hybrid
|
||||||
|
|
||||||
|
'480': 'ERR_SSLONLYCHAN', // ratbox
|
||||||
|
'481': 'ERR_NOPRIVILEGES', // RFC1459
|
||||||
|
'482': 'ERR_CHANOPRIVSNEEDED', // RFC1459
|
||||||
|
'483': 'ERR_CANTKILLSERVER', // RFC1459
|
||||||
|
'484': 'ERR_ISCHANSERVICE', // ratbox (ERR_RESTRICTED in hyb7)
|
||||||
|
'485': 'ERR_BANNEDNICK', // ratbox
|
||||||
|
'488': 'ERR_TSLESSCHAN', // IRCnet
|
||||||
|
'489': 'ERR_VOICENEEDED', // ircu
|
||||||
|
|
||||||
|
'491': 'ERR_NOOPERHOST', // RFC1459
|
||||||
|
'492': 'ERR_NOSERVICEHOST', // RFC1459
|
||||||
|
'493': 'ERR_NOFEATURE', // ircu
|
||||||
|
'494': 'ERR_OWNMODE', // Bahamut
|
||||||
|
'495': 'ERR_BADLOGTYPE', // ircu
|
||||||
|
'496': 'ERR_BADLOGSYS', // ircu
|
||||||
|
'497': 'ERR_BADLOGVALUE', // ircu
|
||||||
|
'498': 'ERR_ISOPERLCHAN', // ircu
|
||||||
|
|
||||||
|
'501': 'ERR_UMODEUNKNOWNFLAG', // RFC1459
|
||||||
|
'502': 'ERR_USERSDONTMATCH', // RFC1459
|
||||||
|
'503': 'ERR_GHOSTEDCLIENT', // hybrid
|
||||||
|
'504': 'ERR_USERNOTONSERV', // hybrid
|
||||||
|
|
||||||
|
'513': 'ERR_WRONGPONG', // hybrid
|
||||||
|
'517': 'ERR_DISABLED', // ircu
|
||||||
|
'518': 'ERR_LONGMASK', // ircu
|
||||||
|
|
||||||
|
'521': 'ERR_LISTSYNTAX', // hybrid
|
||||||
|
'522': 'ERR_WHOSYNTAX', // hybrid
|
||||||
|
'523': 'ERR_WHOLIMITEXCEEDED', // hybrid
|
||||||
|
'524': 'ERR_HELPNOTFOUND', // hybrid
|
||||||
|
|
||||||
|
'670': 'RPL_STARTTLS', // ircv3 tls-3.1
|
||||||
|
'671': 'RPL_WHOISSECURE', // Unreal
|
||||||
|
|
||||||
|
'691': 'ERR_STARTTLS', // ircv3 tls-3.2
|
||||||
|
|
||||||
|
'702': 'RPL_MODLIST', // hybrid
|
||||||
|
'703': 'RPL_ENDOFMODLIST', // hybrid
|
||||||
|
'704': 'RPL_HELPSTART', // hybrid
|
||||||
|
'705': 'RPL_HELPTXT', // hybrid
|
||||||
|
'706': 'RPL_ENDOFHELP', // hybrid
|
||||||
|
'707': 'ERR_TARGCHANGE', // ratbox
|
||||||
|
|
||||||
|
'710': 'RPL_KNOCK', // hybrid
|
||||||
|
'711': 'RPL_KNOCKDLVR', // hybrid
|
||||||
|
'712': 'ERR_TOOMANYKNOCK', // hybrid
|
||||||
|
'713': 'ERR_CHANOPEN', // hybrid
|
||||||
|
'714': 'ERR_KNOCKONCHAN', // hybrid
|
||||||
|
'715': 'ERR_KNOCKDISABLED', // hybrid
|
||||||
|
'716': 'RPL_TARGUMODEG', // hybrid
|
||||||
|
'717': 'RPL_TARGNOTIFY', // hybrid
|
||||||
|
'718': 'RPL_UMODEGMSG', // hybrid
|
||||||
|
|
||||||
|
'720': 'RPL_OMOTDSTART', // hybrid
|
||||||
|
'721': 'RPL_OMOTD', // hybrid
|
||||||
|
'722': 'RPL_ENDOFOMOTD', // hybrid
|
||||||
|
'723': 'ERR_NOPRIVS', // hybrid
|
||||||
|
'724': 'RPL_TESTMASK', // hybrid
|
||||||
|
'725': 'RPL_TESTLINE', // hybrid
|
||||||
|
'726': 'RPL_NOTESTLINE', // hybrid
|
||||||
|
'727': 'RPL_TESTMASKGECOS', // ratbox
|
||||||
|
'728': 'RPL_QUIETLIST', // charybdis
|
||||||
|
'729': 'RPL_ENDOFQUIETLIST', // charybdis
|
||||||
|
|
||||||
|
'730': 'RPL_MONONLINE', // ircv3 monitor ext
|
||||||
|
'731': 'RPL_MONOFFLINE', // ircv3 monitor ext
|
||||||
|
'732': 'RPL_MONLIST', // ircv3 monitor ext
|
||||||
|
'733': 'RPL_ENDOFMONLIST', // ircv3 monitor ext
|
||||||
|
'734': 'ERR_MONLISTFULL', // ircv3 monitor ext
|
||||||
|
|
||||||
|
'740': 'RPL_RSACHALLENGE2', // ratbox
|
||||||
|
'741': 'RPL_ENDOFRSACHALLENGE2', // ratbox
|
||||||
|
|
||||||
|
'900': 'RPL_SASLAUTHENTICATED', // charbydis / kiwiirc
|
||||||
|
'903': 'RPL_SASLLOGGEDIN', // charbydis / kiwiirc
|
||||||
|
'904': 'ERR_SASLNOTAUTHORISED', // charbydis / kiwiirc
|
||||||
|
'906': 'ERR_SASLABORTED', // charbydis / kiwiirc
|
||||||
|
'907': 'ERR_SASLALREADYAUTHED' // charbydis / kiwiirc
|
||||||
|
};
|
1570
src/inc/irc/irc.js
Normal file
1570
src/inc/irc/irc.js
Normal file
File diff suppressed because it is too large
Load Diff
125
src/inc/irc/listcache.js
Normal file
125
src/inc/irc/listcache.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
var _ = require('lodash'),
|
||||||
|
Events = require(__dirname + '/irc').Events;
|
||||||
|
|
||||||
|
function ListCache() {
|
||||||
|
this.lists = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// this object manages list caching, in a normal single client
|
||||||
|
// scenario, grabbing the list on request is fine, but irc-factory
|
||||||
|
// isnt really designed for single client usage
|
||||||
|
// the ircanywhere use case requires lists to be available to all, for
|
||||||
|
// all networks.
|
||||||
|
|
||||||
|
ListCache.prototype.requestList = function(ircObject, search, page, limit) {
|
||||||
|
if (!Events) {
|
||||||
|
Events = require(__dirname + '/irc').Events;
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this,
|
||||||
|
key = ircObject.key;
|
||||||
|
|
||||||
|
if (key === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.lists[key]) {
|
||||||
|
this.createList(ircObject);
|
||||||
|
ircObject.raw(['LIST']);
|
||||||
|
|
||||||
|
Events.once([ircObject.key, 'listend'], function() {
|
||||||
|
self.filterList(ircObject, search, page, limit);
|
||||||
|
});
|
||||||
|
// no cache is available? request one and wait to filter it
|
||||||
|
} else {
|
||||||
|
self.filterList(ircObject, search, page, limit);
|
||||||
|
// looks like we already have a cached list, pass it straight to filter
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTimeout(this.lists[key].deleteTimer);
|
||||||
|
this.lists[key].deleteTimer = setTimeout(function() {
|
||||||
|
delete self.lists[key];
|
||||||
|
}, 600000);
|
||||||
|
// lets set a timer to trash this data if its not been requested in a while (10min)
|
||||||
|
// the only reason we cache it is to prevent people doing /list then /list, then /list
|
||||||
|
// and blocking the process
|
||||||
|
};
|
||||||
|
|
||||||
|
ListCache.prototype.filterList = function(ircObject, search, page, limit) {
|
||||||
|
var key = ircObject.key,
|
||||||
|
regex = new RegExp('(' + search + ')', 'i'),
|
||||||
|
list = this.lists[key];
|
||||||
|
|
||||||
|
if (key === '' || !list) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// make sure the list exists
|
||||||
|
|
||||||
|
var output = {
|
||||||
|
list: [],
|
||||||
|
raw: [],
|
||||||
|
search: search.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\$&").replace(/\(\.\*\)/g, '*'),
|
||||||
|
page: page,
|
||||||
|
limit: limit,
|
||||||
|
time: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
var clone = _.cloneDeep(list.list);
|
||||||
|
var buffer = _.sortBy(clone, function(channel) {
|
||||||
|
return 0 - channel.users;
|
||||||
|
});
|
||||||
|
// sort it
|
||||||
|
|
||||||
|
buffer = _.filter(buffer, function(channel) {
|
||||||
|
return regex.test(channel.channel);
|
||||||
|
});
|
||||||
|
// filter via the search parameters
|
||||||
|
|
||||||
|
buffer = _.take(_.rest(buffer, (page - 1) * limit), limit);
|
||||||
|
// paginate
|
||||||
|
|
||||||
|
for (var c in buffer) {
|
||||||
|
var channel = buffer[c];
|
||||||
|
output.raw.push(channel.raw);
|
||||||
|
delete buffer[c].raw;
|
||||||
|
}
|
||||||
|
// i don't really like this, but we pull .raw from channel objects
|
||||||
|
// and push it into the output
|
||||||
|
|
||||||
|
Events.emit([ircObject.key, 'list'], _.extend(output, {
|
||||||
|
list: buffer
|
||||||
|
}));
|
||||||
|
// emit the list event
|
||||||
|
};
|
||||||
|
|
||||||
|
ListCache.prototype.createList = function(ircObject) {
|
||||||
|
var key = ircObject.key;
|
||||||
|
if (key === '' || this.lists[key]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lists[key] = {
|
||||||
|
key: key,
|
||||||
|
requestedAt: new Date(),
|
||||||
|
deleteTimer: null,
|
||||||
|
list: []
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ListCache.prototype.insertListData = function(ircObject, message) {
|
||||||
|
var key = ircObject.key;
|
||||||
|
if (key !== '' && !this.lists[key]) {
|
||||||
|
this.createList(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lists[key].list.push({
|
||||||
|
channel: message.params[1],
|
||||||
|
users: message.params[2],
|
||||||
|
topic: message.params[3],
|
||||||
|
raw: message.raw
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
exports.ListCache = new ListCache();
|
65
src/inc/irc/queuepool.js
Normal file
65
src/inc/irc/queuepool.js
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
var pausequeue = require('pause-queue'),
|
||||||
|
_ = require('lodash'),
|
||||||
|
api = require(__dirname + '/api').Api,
|
||||||
|
Queues = {};
|
||||||
|
|
||||||
|
function QueuePool() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// these functions provide a way to push a new client into the queue, this means
|
||||||
|
// we can send 1000 clients to boot up, but in the old code they would do it at once
|
||||||
|
// which just wouldn't work, we now queue it with time in between.
|
||||||
|
|
||||||
|
QueuePool.prototype.queueJob = function(server, qid, key, fn) {
|
||||||
|
var queue = this.queueExists(server);
|
||||||
|
|
||||||
|
queue.push({key: key, qid: qid}, fn);
|
||||||
|
// here we take the server hostname, just directly so irc.freenode.org and chat.freenode.org
|
||||||
|
// are different. We have individual queues for hostnames so we can pause that queue if we've
|
||||||
|
// hit the throttling limit for that server or network
|
||||||
|
};
|
||||||
|
|
||||||
|
QueuePool.prototype.queueExists = function(server) {
|
||||||
|
server = server.toLowerCase();
|
||||||
|
|
||||||
|
if (!Queues[server]) {
|
||||||
|
Queues[server] = pausequeue(function(task, done) {
|
||||||
|
setTimeout(done, 1000);
|
||||||
|
// we don't get to the next item until we wait 1.5 seconds
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Queues[server];
|
||||||
|
// checks if a queue exists, creates or returns an existing queue
|
||||||
|
};
|
||||||
|
|
||||||
|
QueuePool.prototype.queueLength = function(server) {
|
||||||
|
return this.queueExists(server).length() + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
QueuePool.prototype.queuePause = function(server) {
|
||||||
|
var queue = this.queueExists(server);
|
||||||
|
|
||||||
|
if (!queue.paused) {
|
||||||
|
queue.pause();
|
||||||
|
// pause the queue
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
queue.tasks = _.sortBy(queue.tasks, function(task) {
|
||||||
|
return task.data.qid;
|
||||||
|
});
|
||||||
|
// make sure its re-sorted via the time of insert
|
||||||
|
|
||||||
|
queue.resume();
|
||||||
|
}, 30000);
|
||||||
|
// attempt to try and start again in 30 seconds
|
||||||
|
// generally we've no idea how long the servers throttle wait is, default is 60
|
||||||
|
// but incase of it being less we can just try 30, that way if it is something like
|
||||||
|
// 30 we're not losing 30 seconds of potential reconnect time
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
exports.QueuePool = new QueuePool();
|
52
src/inc/irc/stub.js
Normal file
52
src/inc/irc/stub.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
var events = require('events'),
|
||||||
|
util = require('util'),
|
||||||
|
_ = require('lodash');
|
||||||
|
|
||||||
|
function ReadWriteStream() {
|
||||||
|
events.EventEmitter.call(this);
|
||||||
|
this.readable = true;
|
||||||
|
this.writable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(ReadWriteStream, events.EventEmitter);
|
||||||
|
|
||||||
|
['end', 'error', 'close', 'setEncoding', 'pause', 'resume', 'destroy', 'drain', 'write', {name: 'rewrite', event: 'data'}, 'destroySoon'].forEach(function(func) {
|
||||||
|
ReadWriteStream.prototype[func.name || func] = (function(func) {
|
||||||
|
var event = func.event || func;
|
||||||
|
return function() {
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
args.unshift(event);
|
||||||
|
this.emit.apply(this, args);
|
||||||
|
};
|
||||||
|
}(func));
|
||||||
|
});
|
||||||
|
|
||||||
|
function ReadWriteNetStream(specialTimeout) {
|
||||||
|
this.specialTimeout = specialTimeout || false;
|
||||||
|
ReadWriteStream.call(this);
|
||||||
|
this.bufferSize = 0;
|
||||||
|
this.remoteAddress = '';
|
||||||
|
this.remotePort = '';
|
||||||
|
this.bytesRead = '';
|
||||||
|
this.bytesWritten = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
util.inherits(ReadWriteNetStream, ReadWriteStream);
|
||||||
|
|
||||||
|
// Net.Socket
|
||||||
|
['connect', 'setSecure', 'setTimeout', 'setNoDelay', 'setKeepAlive', 'address', 'timeout'].forEach(function(funcName) {
|
||||||
|
ReadWriteNetStream.prototype[funcName.name || funcName] = (function(func) {
|
||||||
|
var event = funcName.event || func;
|
||||||
|
return function(a, b) {
|
||||||
|
if (this.specialTimeout && funcName === 'setTimeout' && _.isFunction(b)) {
|
||||||
|
this.on('timeout', b);
|
||||||
|
}
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
args.unshift(event);
|
||||||
|
this.emit.apply(this, args);
|
||||||
|
};
|
||||||
|
}(funcName));
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.ReadWriteStream = ReadWriteStream;
|
||||||
|
module.exports.ReadWriteNetStream = ReadWriteNetStream;
|
61
src/inc/lib.js
Normal file
61
src/inc/lib.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
var factory = require(__dirname+'/../inc/api');
|
||||||
|
var fs = require('fs');
|
||||||
|
var self = Lib.prototype;
|
||||||
|
|
||||||
|
self.api = new factory.Api();
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
events: 31920,
|
||||||
|
rpc: 31930,
|
||||||
|
automaticSetup: true
|
||||||
|
};
|
||||||
|
self.interfaces = self.api.connect(options);
|
||||||
|
self.events = self.interfaces.events;
|
||||||
|
self.rpc = self.interfaces.rpc;
|
||||||
|
|
||||||
|
module.exports = Lib;
|
||||||
|
function Lib(config) {
|
||||||
|
self.cfg = config;
|
||||||
|
self.loadEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.loadEvents = () => {
|
||||||
|
var files = fs.readdirSync(__dirname+'/events/');
|
||||||
|
files.forEach(file => {
|
||||||
|
if(file.substr(-3, 3) === '.js') {
|
||||||
|
console.log('Loading event', file);
|
||||||
|
require(__dirname+'/events/' + file)(self);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reply = (tmp) => {
|
||||||
|
return {
|
||||||
|
network: tmp.event[0],
|
||||||
|
channel: tmp.message.target,
|
||||||
|
user: {
|
||||||
|
nick: tmp.message.nickname,
|
||||||
|
username: tmp.message.username,
|
||||||
|
hostname: tmp.message.hostname
|
||||||
|
},
|
||||||
|
message: tmp.message.message,
|
||||||
|
time: tmp.message.time,
|
||||||
|
reply: function(msg) {
|
||||||
|
self.rpc.emit('call', this.event[0], 'privmsg', [ this.message.target, msg ]);
|
||||||
|
}.bind(tmp),
|
||||||
|
replyAction: function(msg) {
|
||||||
|
self.rpc.emit('call', this.event[0], 'privmsg', [ this.message.target, '\u0001' + 'ACTION ' + msg + '\u0001' ]);
|
||||||
|
}.bind(tmp),
|
||||||
|
replyNotice: function(msg) {
|
||||||
|
self.rpc.emit('call', this.event[0], 'notice', [ this.message.target, msg ]);
|
||||||
|
}.bind(tmp)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
self.loadIRC = () => {
|
||||||
|
for(let srv in self.cfg.irc) {
|
||||||
|
self.rpc.emit( 'createClient', srv, self.cfg.irc[srv] );
|
||||||
|
console.log('Loading server', srv);
|
||||||
|
}
|
||||||
|
console.log('All servers have been loaded successfully');
|
||||||
|
};
|
61
src/inc/sql.js
Normal file
61
src/inc/sql.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import mysql from 'nodejs-mysql';
|
||||||
|
|
||||||
|
const sql = mysql.getInstance( require(`${__dirname}/../../cfg/mysql.json`) );
|
||||||
|
export default sql;
|
||||||
|
|
||||||
|
/*var mysql = require('mysql');
|
||||||
|
|
||||||
|
var self = Cfg.prototype;
|
||||||
|
module.exports = Cfg;
|
||||||
|
|
||||||
|
var haDC = () => {
|
||||||
|
self.sql = mysql.createConnection(require(__dirname+'/../cfg/mysql.json'));
|
||||||
|
self.sql.connect(err => {
|
||||||
|
if(err) setTimeout(haDC, 2000);
|
||||||
|
});
|
||||||
|
self.sql.on('error', (err) => {
|
||||||
|
if(err.code === 'PROTOCOL_CONNECTION_LOST') haDC();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
haDC();
|
||||||
|
|
||||||
|
|
||||||
|
function Cfg() {
|
||||||
|
self.cfg = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.read = (kat, key) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var out = {
|
||||||
|
irc: {},
|
||||||
|
main: {},
|
||||||
|
websrv: {},
|
||||||
|
trigger: {}
|
||||||
|
};
|
||||||
|
self.sql.query("select * from `cfg`" + (kat?" where `class` = '"+kat+"'"+(key?" && `key` = '"+key+"'":""):""), (err, rows) => {
|
||||||
|
if(err || rows.length < 1)
|
||||||
|
reject( err );
|
||||||
|
else {
|
||||||
|
rows.forEach(e => {
|
||||||
|
out[e.class][e.key] = ((type, value) => {
|
||||||
|
switch(type) {
|
||||||
|
case 'string':
|
||||||
|
return value;
|
||||||
|
break;
|
||||||
|
case 'int':
|
||||||
|
return parseInt(value);
|
||||||
|
break;
|
||||||
|
case 'bool':
|
||||||
|
return (value === 'true')?true:false;
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
return JSON.parse(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})(e.type, e.value);
|
||||||
|
});
|
||||||
|
resolve(key?out[kat][key]:out);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};*/
|
31
src/index.js
Normal file
31
src/index.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
const forever = require(__dirname+'/../node_modules/forever-monitor');
|
||||||
|
|
||||||
|
var child = new (forever.Monitor)(`${__dirname}/bot.js`, {
|
||||||
|
max: 1,
|
||||||
|
silent: false,
|
||||||
|
cwd: __dirname,
|
||||||
|
args: [],
|
||||||
|
spinSleepTime: 5000,
|
||||||
|
watch: true,
|
||||||
|
watchIgnoreDotFiles: true,
|
||||||
|
watchIgnorePatterns: [
|
||||||
|
'node_modules/*',
|
||||||
|
'tmp/*'
|
||||||
|
],
|
||||||
|
watchDirectory: __dirname
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('watch:restart', info => {
|
||||||
|
console.log(`Restaring bot because ${info.stat} changed`);
|
||||||
|
});
|
||||||
|
child.on('restart', () => {
|
||||||
|
console.log(`restarting bot for ${child.times} time`);
|
||||||
|
});
|
||||||
|
child.on('start', () => {
|
||||||
|
console.log('starting bot');
|
||||||
|
});
|
||||||
|
child.on('exit:code', code => {
|
||||||
|
console.log(`detected bot exited with code ${code}`);
|
||||||
|
//child.restart();
|
||||||
|
});
|
||||||
|
child.start();
|
Loading…
Reference in New Issue
Block a user