irc-framework
Version:
A better IRC framework for node.js
421 lines (414 loc) • 16.6 kB
JavaScript
'use strict';
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.array.from.js");
require("core-js/modules/es.array.is-array.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.array.slice.js");
require("core-js/modules/es.date.to-string.js");
require("core-js/modules/es.function.name.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.regexp.to-string.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/es.array.index-of.js");
require("core-js/modules/es.array.map.js");
require("core-js/modules/es.object.assign.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.string.match.js");
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var _ = {
each: require('lodash/each'),
map: require('lodash/map')
};
var Helpers = require('../../helpers');
var handlers = {
NICK: function NICK(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
handler.emit('nick', {
nick: command.nick,
ident: command.ident,
hostname: command.hostname,
new_nick: command.params[0],
time: time,
tags: command.tags,
batch: command.batch
});
},
ACCOUNT: function ACCOUNT(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
var account = command.params[0] === '*' ? false : command.params[0];
handler.emit('account', {
nick: command.nick,
ident: command.ident,
hostname: command.hostname,
account: account,
time: time,
tags: command.tags
});
},
// If the chghost CAP is enabled and 'enable_chghost' option is true
CHGHOST: function CHGHOST(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
handler.emit('user updated', {
nick: command.nick,
ident: command.ident,
hostname: command.hostname,
new_ident: command.params[0],
new_hostname: command.params[1],
time: time,
tags: command.tags,
batch: command.batch
});
},
SETNAME: function SETNAME(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
handler.emit('user updated', {
nick: command.nick,
ident: command.ident,
hostname: command.hostname,
new_gecos: command.params[0],
time: time,
tags: command.tags,
batch: command.batch
});
},
AWAY: function AWAY(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
var message = command.params[command.params.length - 1] || '';
if (message === '') {
// back
handler.emit('back', {
self: false,
nick: command.nick,
message: '',
time: time,
tags: command.tags
});
} else {
handler.emit('away', {
self: false,
nick: command.nick,
message: message,
time: time,
tags: command.tags
});
}
},
RPL_NOWAWAY: function RPL_NOWAWAY(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
handler.emit('away', {
self: true,
nick: command.params[0],
message: command.params[1] || '',
time: time,
tags: command.tags
});
},
RPL_UNAWAY: function RPL_UNAWAY(command, handler) {
// Check if we have a server-time
var time = command.getServerTime();
handler.emit('back', {
self: true,
nick: command.params[0],
message: command.params[1] || '',
// example: "<nick> is now back."
time: time,
tags: command.tags
});
},
RPL_ISON: function RPL_ISON(command, handler) {
handler.emit('users online', {
nicks: (command.params[command.params.length - 1] || '').split(' '),
tags: command.tags
});
},
ERR_NICKNAMEINUSE: function ERR_NICKNAMEINUSE(command, handler) {
handler.emit('nick in use', {
nick: command.params[1],
reason: command.params[command.params.length - 1],
tags: command.tags
});
},
ERR_ERRONEOUSNICKNAME: function ERR_ERRONEOUSNICKNAME(command, handler) {
handler.emit('nick invalid', {
nick: command.params[1],
reason: command.params[command.params.length - 1],
tags: command.tags
});
},
RPL_ENDOFWHOIS: function RPL_ENDOFWHOIS(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
if (!cache.nick) {
cache.nick = command.params[1];
cache.error = 'not_found';
}
handler.emit('whois', cache);
cache.destroy();
},
RPL_AWAY: function RPL_AWAY(command, handler) {
var cache_key = 'whois.' + command.params[1].toLowerCase();
var message = command.params[command.params.length - 1] || 'is away';
// RPL_AWAY may come as a response to PRIVMSG, and not be a part of whois
// If so, emit away event separately for it
if (!handler.hasCache(cache_key)) {
// Check if we have a server-time
var time = command.getServerTime();
handler.emit('away', {
self: false,
nick: command.params[1],
message: message,
time: time,
tags: command.tags
});
return;
}
var cache = handler.cache(cache_key);
cache.away = message;
},
RPL_WHOISUSER: function RPL_WHOISUSER(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.nick = command.params[1];
cache.ident = command.params[2];
cache.hostname = command.params[3];
cache.real_name = command.params[5];
},
RPL_WHOISHELPOP: function RPL_WHOISHELPOP(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.helpop = command.params[command.params.length - 1];
},
RPL_WHOISBOT: function RPL_WHOISBOT(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.bot = command.params[command.params.length - 1];
},
RPL_WHOISSERVER: function RPL_WHOISSERVER(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.server = command.params[2];
cache.server_info = command.params[command.params.length - 1];
},
RPL_WHOISOPERATOR: function RPL_WHOISOPERATOR(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.operator = command.params[command.params.length - 1];
},
RPL_WHOISCHANNELS: function RPL_WHOISCHANNELS(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
if (cache.channels) {
cache.channels += ' ' + command.params[command.params.length - 1];
} else {
cache.channels = command.params[command.params.length - 1];
}
},
RPL_WHOISMODES: function RPL_WHOISMODES(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.modes = command.params[command.params.length - 1];
},
RPL_WHOISIDLE: function RPL_WHOISIDLE(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.idle = command.params[2];
if (command.params[3]) {
cache.logon = command.params[3];
}
},
RPL_WHOISREGNICK: function RPL_WHOISREGNICK(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.registered_nick = command.params[command.params.length - 1];
},
RPL_WHOISHOST: function RPL_WHOISHOST(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
var last_param = command.params[command.params.length - 1];
// <source> 378 <target> <nick> :is connecting from <user>@<host> <ip>
var match = last_param.match(/.*@([^ ]+) ([^ ]+).*$/); // https://regex101.com/r/AQz7RE/2
if (!match) {
return;
}
cache.actual_ip = match[2];
cache.actual_hostname = match[1];
},
RPL_WHOISSECURE: function RPL_WHOISSECURE(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.secure = true;
},
RPL_WHOISCERTFP: function RPL_WHOISCERTFP(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
var certfp = command.params[command.params.length - 1];
cache.certfp = cache.certfp || certfp;
cache.certfps = cache.certfps || [];
cache.certfps.push(certfp);
},
RPL_WHOISACCOUNT: function RPL_WHOISACCOUNT(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.account = command.params[2];
},
RPL_WHOISSPECIAL: function RPL_WHOISSPECIAL(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.special = cache.special || [];
cache.special.push(command.params[command.params.length - 1]);
},
RPL_WHOISCOUNTRY: function RPL_WHOISCOUNTRY(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.country = command.params[command.params.length - 1];
if (command.params.length === 4) {
cache.country_code = command.params[2];
}
},
RPL_WHOISASN: function RPL_WHOISASN(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.asn = command.params[command.params.length - 1];
},
RPL_WHOISACTUALLY: function RPL_WHOISACTUALLY(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
// <source> 338 <target> <nick> [<user>@]<host> <ip> :Actual user@host, Actual IP
var user_host = command.params[command.params.length - 3] || '';
var mask_sep = user_host.indexOf('@');
var user = user_host.substring(0, mask_sep) || undefined;
var host = user_host.substring(mask_sep + 1);
var ip = command.params[command.params.length - 2];
// UnrealIRCd uses this numeric for something else resulting in ip+host
// to be empty, so ignore this is that's the case
if (ip && host) {
cache.actual_ip = ip;
cache.actual_username = user;
cache.actual_hostname = host;
}
},
RPL_WHOWASUSER: function RPL_WHOWASUSER(command, handler) {
var cache_key = command.params[1].toLowerCase();
var whois_cache = handler.cache('whois.' + cache_key);
// multiple RPL_WHOWASUSER replies are received prior to the RPL_ENDOFWHOWAS command
// one for each timestamp the server is aware of, from newest to oldest.
// They are optionally interleaved with various other numerics such as RPL_WHOISACTUALLY etc.
// Hence if we already find something we are receiving older data and need to make sure that we
// store anything already in the cache into its own entry
var whowas_cache = handler.cache('whowas.' + cache_key);
if (!whowas_cache.whowas) {
// this will get populated by the next RPL_WHOWASUSER or RPL_ENDOFWHOWAS
whowas_cache.whowas = [];
} else {
// push the previous event prior to modifying anything
whowas_cache.whowas.push(whois_cache);
// ensure we are starting with a clean cache for the next data
whois_cache.destroy();
whois_cache = handler.cache('whois.' + cache_key);
}
whois_cache.nick = command.params[1];
whois_cache.ident = command.params[2];
whois_cache.hostname = command.params[3];
whois_cache.real_name = command.params[command.params.length - 1];
},
RPL_ENDOFWHOWAS: function RPL_ENDOFWHOWAS(command, handler) {
// Because the WHOIS and WHOWAS numerics clash with eachother,
// a cache key will have more than what is just in RPL_WHOWASUSER.
// This is why we borrow from the whois.* cache key ID.
//
// This exposes some fields (that may or may not be set).
// Valid keys that should always be set: nick, ident, hostname, real_name
// Valid optional keys: actual_ip, actual_hostname, account, server,
// server_info, actual_username
// More optional fields MAY exist, depending on the type of ircd.
var cache_key = command.params[1].toLowerCase();
var whois_cache = handler.cache('whois.' + cache_key);
var whowas_cache = handler.cache('whowas.' + cache_key);
// after all prior RPL_WHOWASUSER pushed newer events onto the history stack
// push the last one to complete the set (server returns from newest to oldest)
whowas_cache.whowas = whowas_cache.whowas || [];
if (!whois_cache.error) {
whowas_cache.whowas.push(whois_cache);
Object.assign(whowas_cache, whowas_cache.whowas[0]);
} else {
Object.assign(whowas_cache, whois_cache);
}
handler.emit('whowas', whowas_cache);
whois_cache.destroy();
whowas_cache.destroy();
},
ERR_WASNOSUCHNICK: function ERR_WASNOSUCHNICK(command, handler) {
var cache_key = command.params[1].toLowerCase();
var cache = handler.cache('whois.' + cache_key);
cache.nick = command.params[1];
cache.error = 'no_such_nick';
},
RPL_UMODEIS: function RPL_UMODEIS(command, handler) {
var nick = command.params[0];
var raw_modes = command.params[1];
handler.emit('user info', {
nick: nick,
raw_modes: raw_modes,
tags: command.tags
});
},
RPL_HOSTCLOAKING: function RPL_HOSTCLOAKING(command, handler) {
handler.emit('displayed host', {
nick: command.params[0],
hostname: command.params[1],
tags: command.tags
});
},
RPL_MONONLINE: function RPL_MONONLINE(command, handler) {
var users = (command.params[command.params.length - 1] || '').split(',');
var parsed = _.map(users, function (user) {
return Helpers.parseMask(user).nick;
});
handler.emit('users online', {
nicks: parsed,
tags: command.tags
});
},
RPL_MONOFFLINE: function RPL_MONOFFLINE(command, handler) {
var users = (command.params[command.params.length - 1] || '').split(',');
handler.emit('users offline', {
nicks: users,
tags: command.tags
});
},
RPL_MONLIST: function RPL_MONLIST(command, handler) {
var _cache$nicks;
var cache = handler.cache('monitorList.' + command.params[0]);
if (!cache.nicks) {
cache.nicks = [];
}
var users = command.params[command.params.length - 1].split(',');
(_cache$nicks = cache.nicks).push.apply(_cache$nicks, _toConsumableArray(users));
},
RPL_ENDOFMONLIST: function RPL_ENDOFMONLIST(command, handler) {
var cache = handler.cache('monitorList.' + command.params[0]);
handler.emit('monitorList', {
nicks: cache.nicks || []
});
cache.destroy();
}
};
module.exports = function AddCommandHandlers(command_controller) {
_.each(handlers, function (handler, handler_command) {
command_controller.addHandler(handler_command, handler);
});
};