2016-10-09 19:14:02 +00:00
|
|
|
"use strict";
|
|
|
|
|
2018-01-11 11:33:36 +00:00
|
|
|
const _ = require("lodash");
|
2017-11-28 17:25:15 +00:00
|
|
|
const uuidv4 = require("uuid/v4");
|
2018-01-11 11:33:36 +00:00
|
|
|
const Chan = require("./chan");
|
2014-09-13 21:29:45 +00:00
|
|
|
|
|
|
|
module.exports = Network;
|
|
|
|
|
2017-09-20 07:44:36 +00:00
|
|
|
let id = 1;
|
2014-09-13 21:29:45 +00:00
|
|
|
|
2017-11-29 19:54:09 +00:00
|
|
|
/**
|
|
|
|
* @type {Object} List of keys which should not be sent to the client.
|
|
|
|
*/
|
|
|
|
const filteredFromClient = {
|
|
|
|
awayMessage: true,
|
|
|
|
chanCache: true,
|
|
|
|
highlightRegex: true,
|
|
|
|
irc: true,
|
|
|
|
password: true,
|
|
|
|
};
|
|
|
|
|
2014-09-13 21:29:45 +00:00
|
|
|
function Network(attr) {
|
2016-10-02 07:37:37 +00:00
|
|
|
_.defaults(this, attr, {
|
2014-10-11 20:44:56 +00:00
|
|
|
name: "",
|
|
|
|
host: "",
|
|
|
|
port: 6667,
|
|
|
|
tls: false,
|
2018-02-17 08:22:28 +00:00
|
|
|
rejectUnauthorized: false,
|
2014-10-11 20:44:56 +00:00
|
|
|
password: "",
|
2016-12-18 09:24:50 +00:00
|
|
|
awayMessage: "",
|
2014-11-09 16:01:22 +00:00
|
|
|
commands: [],
|
2014-10-11 20:44:56 +00:00
|
|
|
username: "",
|
|
|
|
realname: "",
|
2014-09-13 21:29:45 +00:00
|
|
|
channels: [],
|
2016-04-03 05:12:49 +00:00
|
|
|
ip: null,
|
|
|
|
hostname: null,
|
2014-09-13 21:29:45 +00:00
|
|
|
id: id++,
|
|
|
|
irc: null,
|
2016-03-08 18:50:48 +00:00
|
|
|
serverOptions: {
|
|
|
|
PREFIX: [],
|
2017-04-16 09:31:32 +00:00
|
|
|
NETWORK: "",
|
2016-03-08 18:50:48 +00:00
|
|
|
},
|
2016-05-29 02:07:34 +00:00
|
|
|
chanCache: [],
|
2016-10-02 07:37:37 +00:00
|
|
|
});
|
|
|
|
|
2017-11-28 17:25:15 +00:00
|
|
|
if (!this.uuid) {
|
|
|
|
this.uuid = uuidv4();
|
|
|
|
}
|
|
|
|
|
2017-07-06 12:02:32 +00:00
|
|
|
if (!this.name) {
|
|
|
|
this.name = this.host;
|
|
|
|
}
|
|
|
|
|
2014-09-13 21:29:45 +00:00
|
|
|
this.channels.unshift(
|
2014-10-11 22:47:24 +00:00
|
|
|
new Chan({
|
|
|
|
name: this.name,
|
2017-11-15 06:35:15 +00:00
|
|
|
type: Chan.Type.LOBBY,
|
2014-10-11 22:47:24 +00:00
|
|
|
})
|
2014-09-13 21:29:45 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-08-11 12:02:58 +00:00
|
|
|
Network.prototype.destroy = function() {
|
|
|
|
this.channels.forEach((channel) => channel.destroy());
|
|
|
|
};
|
|
|
|
|
2016-05-12 11:15:38 +00:00
|
|
|
Network.prototype.setNick = function(nick) {
|
|
|
|
this.nick = nick;
|
|
|
|
this.highlightRegex = new RegExp(
|
|
|
|
// Do not match characters and numbers (unless IRC color)
|
|
|
|
"(?:^|[^a-z0-9]|\x03[0-9]{1,2})" +
|
|
|
|
|
|
|
|
// Escape nickname, as it may contain regex stuff
|
2016-11-19 08:49:16 +00:00
|
|
|
_.escapeRegExp(nick) +
|
2016-05-12 11:15:38 +00:00
|
|
|
|
|
|
|
// Do not match characters and numbers
|
|
|
|
"(?:[^a-z0-9]|$)",
|
|
|
|
|
|
|
|
// Case insensitive search
|
|
|
|
"i"
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2017-11-29 19:54:09 +00:00
|
|
|
/**
|
|
|
|
* Get a clean clone of this network that will be sent to the client.
|
|
|
|
* This function performs manual cloning of network object for
|
|
|
|
* better control of performance and memory usage.
|
|
|
|
*
|
|
|
|
* Both of the parameters that are accepted by this function are passed into channels' getFilteredClone call.
|
|
|
|
*
|
|
|
|
* @see {@link Chan#getFilteredClone}
|
|
|
|
*/
|
|
|
|
Network.prototype.getFilteredClone = function(lastActiveChannel, lastMessage) {
|
2018-02-19 11:12:01 +00:00
|
|
|
const filteredNetwork = Object.keys(this).reduce((newNetwork, prop) => {
|
2017-11-29 19:54:09 +00:00
|
|
|
if (prop === "channels") {
|
|
|
|
// Channels objects perform their own cloning
|
|
|
|
newNetwork[prop] = this[prop].map((channel) => channel.getFilteredClone(lastActiveChannel, lastMessage));
|
|
|
|
} else if (!filteredFromClient[prop]) {
|
|
|
|
// Some properties that are not useful for the client are skipped
|
|
|
|
newNetwork[prop] = this[prop];
|
|
|
|
}
|
|
|
|
|
|
|
|
return newNetwork;
|
|
|
|
}, {});
|
2018-02-19 11:12:01 +00:00
|
|
|
|
|
|
|
filteredNetwork.status = this.getNetworkStatus();
|
|
|
|
|
|
|
|
return filteredNetwork;
|
|
|
|
};
|
|
|
|
|
|
|
|
Network.prototype.getNetworkStatus = function() {
|
|
|
|
const status = {
|
|
|
|
connected: false,
|
|
|
|
secure: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (this.irc && this.irc.connection && this.irc.connection.transport) {
|
|
|
|
const transport = this.irc.connection.transport;
|
|
|
|
|
|
|
|
if (transport.socket) {
|
2018-02-20 08:35:45 +00:00
|
|
|
const isLocalhost = transport.socket.remoteAddress === "127.0.0.1";
|
|
|
|
const isAuthorized = transport.socket.encrypted && transport.socket.authorized;
|
|
|
|
|
2018-02-19 11:12:01 +00:00
|
|
|
status.connected = transport.isConnected();
|
2018-02-20 08:35:45 +00:00
|
|
|
status.secure = isAuthorized || isLocalhost;
|
2018-02-19 11:12:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
2014-10-11 20:44:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Network.prototype.export = function() {
|
2018-01-11 11:33:36 +00:00
|
|
|
const network = _.pick(this, [
|
2017-11-28 17:25:15 +00:00
|
|
|
"uuid",
|
2016-12-18 09:24:50 +00:00
|
|
|
"awayMessage",
|
2016-05-12 11:15:38 +00:00
|
|
|
"nick",
|
2014-10-11 22:47:24 +00:00
|
|
|
"name",
|
|
|
|
"host",
|
|
|
|
"port",
|
|
|
|
"tls",
|
2018-02-17 08:22:28 +00:00
|
|
|
"rejectUnauthorized",
|
2014-10-11 22:47:24 +00:00
|
|
|
"password",
|
|
|
|
"username",
|
2014-11-09 16:01:22 +00:00
|
|
|
"realname",
|
2016-04-03 05:12:49 +00:00
|
|
|
"commands",
|
|
|
|
"ip",
|
2017-11-15 06:35:15 +00:00
|
|
|
"hostname",
|
2014-10-11 22:47:24 +00:00
|
|
|
]);
|
2016-05-12 11:15:38 +00:00
|
|
|
|
2016-06-19 17:12:42 +00:00
|
|
|
network.channels = this.channels
|
|
|
|
.filter(function(channel) {
|
2018-01-30 16:46:34 +00:00
|
|
|
return channel.type === Chan.Type.CHANNEL || channel.type === Chan.Type.QUERY;
|
2016-06-19 17:12:42 +00:00
|
|
|
})
|
|
|
|
.map(function(chan) {
|
2018-01-30 16:46:34 +00:00
|
|
|
const keys = ["name"];
|
2018-02-20 07:28:04 +00:00
|
|
|
|
2018-01-30 16:46:34 +00:00
|
|
|
if (chan.type === Chan.Type.CHANNEL) {
|
|
|
|
keys.push("key");
|
|
|
|
} else if (chan.type === Chan.Type.QUERY) {
|
|
|
|
keys.push("type");
|
|
|
|
}
|
2018-02-20 07:28:04 +00:00
|
|
|
|
2018-01-30 16:46:34 +00:00
|
|
|
return _.pick(chan, keys);
|
2016-06-19 17:12:42 +00:00
|
|
|
});
|
2016-05-12 11:15:38 +00:00
|
|
|
|
2014-10-11 20:44:56 +00:00
|
|
|
return network;
|
2014-09-13 21:29:45 +00:00
|
|
|
};
|
|
|
|
|
2016-03-20 14:28:47 +00:00
|
|
|
Network.prototype.getChannel = function(name) {
|
|
|
|
name = name.toLowerCase();
|
|
|
|
|
2018-02-05 12:35:01 +00:00
|
|
|
return _.find(this.channels, function(that, i) {
|
|
|
|
// Skip network lobby (it's always unshifted into first position)
|
|
|
|
return i > 0 && that.name.toLowerCase() === name;
|
2016-03-20 14:28:47 +00:00
|
|
|
});
|
|
|
|
};
|