123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- module.exports.connected = connected;
- module.exports.processMessage = processMessage;
- module.exports.processSender = processSender;
- module.exports.setHandlers = setHandlers;
- module.exports.setSettings = setSettings;
- var handlers = {
- sendHandler: null,
- findServer: null,
- findUser: null,
- killUser: null,
- newServer: null,
- newUser: null,
- parseUmodes: null,
- getChannel: null,
- quitUser: null
- };
- var settings = {
- ID: null,
- password: null,
- name: null,
- description: null,
- version: null,
- me: null,
- maxUsers: null
- };
- var prefixes = {
- '~': 'q',
- '&': 'a',
- '@': 'o',
- '%': 'h',
- '+': 'v'
- };
- function parseModePrefix(text){
- var modes = [];
- for(var i=0; i<text.length; i++){
- var c = text.charAt(i);
- if(c in prefixes){
- modes[prefixes[c]] = true;
- } else break;
- }
- var uid = text.substring(i);
- var user = handlers.findUser(uid);
- if(!user){
- handlers.killUser(uid);
- return null;
- }
- return { 'user': user, 'modes': modes };
- }
- function connected(){
- ircSend(null, settings.ID, 'PASS', [settings.password]);
- ircSend(null, settings.ID, 'PROTOCTL', ['NICKv2', 'VHP', 'UMODE2', 'NICKIP', 'SJOIN', 'SJOIN2', 'SJ3', 'NOQUIT', 'TKLEXT', 'MLOCK', 'SID']);
- ircSend(null, settings.ID, 'PROTOCTL', ['EAUTH=' + settings.name + ',,,' + settings.version]);
- ircSend(null, settings.ID, 'PROTOCTL', ['SID=' + settings.ID]);
- ircSend(null, settings.ID, 'SERVER', [settings.name, '1', settings.description]);
- }
- function processSender(sender){
- if(sender.nick){
- if(server = handlers.findServer(sender.nick)){
- sender.nick = server.name;
- sender.server = server;
- } else if(user = handlers.findUser(sender.nick)){
- sender.nick = user.name
- sender.ident = user.ident;
- sender.host = user.host;
- sender.user = user;
- } else {
- handlers.killUser(sender.nick);
- return false;
- }
- }
- return sender;
- }
- function processMessage(msg){
- if(!msg) return;
- if(msg.command in cmdBinds){
- cmdBinds[msg.command](msg);
- } else {
- console.log('Unhandled cmd: '+msg.command);
- console.log(msg);
- }
- }
- function setHandlers(newHandlers){
- handlers = newHandlers;
- }
- function setSettings(newSettings){
- settings = newSettings;
- }
- function ircSend(tags, from, cmd, args){
- handlers.send(tags, from, cmd, args);
- }
- var cmdBinds = {
- 'PROTOCTL': function(msg){
- //TODO parse
- console.log(msg);
- },
-
- 'SERVER': function(msg){
- var expr = /^([^-]+)-([^-]+)-([^ ]+) (.*)$/;
- var match = expr.exec(msg.args[2]);
- if(match){
- handlers.newServer(msg.args[0], match[3], match[4], msg.args[1], settings.me);
- } else {
- throw 'Unknown SERVER message';
- }
- },
-
- 'MD': function(msg){
- switch(msg.args[0]){
- case 'client':
- var user = handlers.findUser(msg.args[1]);
- if(!user) return;
- switch(msg.args[2]){
- case 'certfp':
- if(!msg.args[3] || msg.args[3].length == 0) break;
- user.setSecure(true);
- user.setFingerprint(msg.args[3]);
- break;
- default: break;
- }
- break;
- default: break;
- }
- },
-
- 'SMOD': function(msg){ // ignore
- },
-
- 'EOS': function(msg){ // ?
- },
-
- 'SINFO': function(msg){
- console.log(msg);
- },
- 'SID': function(msg){
- handlers.newServer(msg.args[0], msg.args[2], msg.args[3], msg.args[1], msg.sender);
- },
-
- 'UID': function(msg){
- var nick = msg.args[0];
- var distance = msg.args[1];
- var TS = msg.args[2];
- var ident = msg.args[3];
- var host = msg.args[4];
- var uid = msg.args[5];
- var account = msg.args[6];
- var umodes = msg.args[7];
- var vhost = msg.args[8];
- var cloakedHost = msg.args[9];
- var ip = msg.args[10];
- var realname = msg.args[11];
- if(ip != '*'){
- var ipBinary = Buffer.from(ip, 'base64');
- console.log(ipBinary);
- if(ipBinary.byteLength == 4){ // IPv4
- ip = ipBinary[0].toString(10) + '.' + ipBinary[1].toString(10) + '.' + ipBinary[2].toString(10) + '.' + ipBinary[3].toString(10);
- } else if(ipBinary.byteLength == 16){ // IPv6
- ip = '';
- for(var i=0; i<8; i++){
- if(i > 0) ip += ':';
- ip += ipBinary[i*2].toString(16).padStart(2, '0') + ipBinary[i*2+1].toString(16).padStart(2, '0');
- }
- } else {
- throw 'unknown IP format';
- }
- } else {
- ip = null;
- }
- if(vhost == '*'){
- vhost = null;
- }
- if(cloakedHost == '*'){
- cloakedHost = null;
- }
- if(account == '0'){
- account = null;
- }
- handlers.newUser(nick, distance, TS, ident, host, uid, account, handlers.parseUmodes(umodes), vhost, cloakedHost, ip, realname, msg.sender.server);
- },
- 'SJOIN': function(msg){
- var channel = handlers.getChannel(msg.args[1]);
- channel.setTS(msg.args[0]);
- var modeArgs = [];
- for(var i=3; i<msg.args.length - 1; i++){
- modeArgs.push(msg.args[i]);
- }
- channel.addModes(msg.args[2], modeArgs);
- var members = msg.text.split(' ');
- for(var i=0; i<members.length; i++){
- var member = members[i];
- var c = member.charAt(0);
- if(c == '&'){ // +b
- channel.addBan(member.substring(1));
- } else if(c == '"'){ // +e
- channel.addExcept(member.substring(1));
- } else if(c == '\''){ // +I
- channel.addInvex(member.substring(1));
- } else {
- var udata = parseModePrefix(member);
- if(!udata) return;
- console.log(udata.user.name + ' joined ' + msg.args[1]);
- channel.joinUser(udata.user);
- channel.setStatusModes(udata.user, udata.modes);
- }
- }
- console.log(channel);
- },
-
- 'SWHOIS': function(msg){
- //TODO
- },
-
- 'MODE': function(msg){
- //TODO
- },
-
- 'TKL': function(msg){
- //TODO
- },
-
- 'METADATA': function(msg){
- //TODO
- },
-
- 'NETINFO': function(msg){
- ircSend(null, null, [settings.maxUsers, Math.floor(new Date() / 1000), msg.args[2], msg.args[3], "0", "0", "0", msg.args[7]]);
- },
-
- 'SASL': function(msg){
- //TODO
- },
-
- 'PING': function(msg){
- msg.reply(null, 'PONG', msg.args);
- },
- 'QUIT': function(msg){
- handlers.quitUser(msg.sender.user);
- },
- 'PART': function(msg){
- var channel = handlers.getChannel(msg.args[0]);
- channel.removeUser(msg.sender.user);
- },
-
- 'CHGHOST': function(msg){
- var user = handlers.findUser(msg.args[0]);
- if(!user) return;
- user.changeVHost(msg.args[1]);
- },
-
- 'CHGIDENT': function(msg){
- var user = handlers.findUser(msg.args[0]);
- if(!user) return;
- user.changeVIdent(msg.args[1]);
- },
-
- 'CHGNAME': function(msg){
- var user = handlers.findUser(msg.args[0]);
- if(!user) return;
- user.setRealname(msg.args[1]);
- },
-
- 'SETNAME': function(msg){
- msg.sender.user.setRealname(msg.args[0]);
- },
-
- 'SETHOST': function(msg){
- //TODO
- },
-
- 'SETIDENT': function(msg){
- //TODO
- },
-
- 'NICK': function(msg){
- //TODO
- },
-
- 'SDESC': function(msg){
- //TODO
- },
-
- 'TOPIC': function(msg){
- //TODO
- },
- };
|