From bf8a16b7fe2872390ee9c46b681c39b204c01537 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Fri, 27 Apr 2018 13:16:23 +0300 Subject: [PATCH] Use per-client channel and message ids Fixes #2341 --- src/client.js | 21 ++++++++++++++++++--- src/models/chan.js | 6 +++--- src/models/msg.js | 4 +--- src/plugins/inputs/query.js | 2 +- src/plugins/irc-events/banlist.js | 2 +- src/plugins/irc-events/chghost.js | 17 ++++++++--------- src/plugins/irc-events/join.js | 2 +- src/plugins/irc-events/list.js | 2 +- src/plugins/irc-events/message.js | 2 +- src/plugins/irc-events/nick.js | 5 ++--- src/plugins/irc-events/whois.js | 2 +- src/plugins/sqlite.js | 8 ++++++-- test/models/chan.js | 5 +++-- test/plugins/sqlite.js | 4 +++- 14 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/client.js b/src/client.js index be1275f9..d5f96d03 100644 --- a/src/client.js +++ b/src/client.js @@ -70,6 +70,8 @@ function Client(manager, name, config = {}) { attachedClients: {}, config: config, id: uuidv4(), + idChan: 1, + idMsg: 1, name: name, networks: [], sockets: manager.sockets, @@ -80,7 +82,7 @@ function Client(manager, name, config = {}) { let delay = 0; if (!Helper.config.public) { - client.messageStorage = new MessageStorage(); + client.messageStorage = new MessageStorage(client); if (client.config.log && Helper.config.messageStorage.includes("sqlite")) { client.messageStorage.enable(client.name); @@ -109,6 +111,13 @@ function Client(manager, name, config = {}) { } } +Client.prototype.createChannel = function(attr) { + const chan = new Chan(attr); + chan.id = this.idChan++; + + return chan; +}; + Client.prototype.emit = function(event, data) { if (this.sockets !== null) { this.sockets.in(this.id).emit(event, data); @@ -140,6 +149,9 @@ Client.prototype.connect = function(args) { const client = this; let channels = []; + // Get channel id for lobby before creating other channels for nicer ids + const lobbyChannelId = client.idChan++; + if (args.channels) { let badName = false; @@ -149,7 +161,7 @@ Client.prototype.connect = function(args) { return; } - channels.push(new Chan({ + channels.push(client.createChannel({ name: chan.name, key: chan.key || "", type: chan.type, @@ -166,7 +178,7 @@ Client.prototype.connect = function(args) { .replace(/,/g, " ") .split(/\s+/g) .map(function(chan) { - return new Chan({ + return client.createChannel({ name: chan, }); }); @@ -189,6 +201,9 @@ Client.prototype.connect = function(args) { channels: channels, }); + // Set network lobby channel id + network.channels[0].id = lobbyChannelId; + client.networks.push(network); client.emit("network", { networks: [network.getFilteredClone(this.lastActiveChannel, -1)], diff --git a/src/models/chan.js b/src/models/chan.js index f573712a..ce8ed98c 100644 --- a/src/models/chan.js +++ b/src/models/chan.js @@ -20,11 +20,9 @@ Chan.State = { JOINED: 1, }; -let id = 1; - function Chan(attr) { _.defaults(this, attr, { - id: id++, + id: 0, messages: [], name: "", key: "", @@ -46,6 +44,8 @@ Chan.prototype.pushMessage = function(client, msg, increasesUnread) { const chan = this.id; const obj = {chan, msg}; + msg.id = client.idMsg++; + // If this channel is open in any of the clients, do not increase unread counter const isOpen = _.find(client.attachedClients, {openChannel: chan}) !== undefined; diff --git a/src/models/msg.js b/src/models/msg.js index a91bb76b..2d292add 100644 --- a/src/models/msg.js +++ b/src/models/msg.js @@ -2,8 +2,6 @@ const _ = require("lodash"); -let id = 0; - class Msg { constructor(attr) { // Some properties need to be copied in the Msg object instead of referenced @@ -20,7 +18,7 @@ class Msg { _.defaults(this, attr, { from: {}, - id: id++, + id: 0, previews: [], text: "", type: Msg.Type.MESSAGE, diff --git a/src/plugins/inputs/query.js b/src/plugins/inputs/query.js index 7712146b..a3eda2fe 100644 --- a/src/plugins/inputs/query.js +++ b/src/plugins/inputs/query.js @@ -43,7 +43,7 @@ exports.input = function(network, chan, cmd, args) { } } - const newChan = new Chan({ + const newChan = this.createChannel({ type: Chan.Type.QUERY, name: target, }); diff --git a/src/plugins/irc-events/banlist.js b/src/plugins/irc-events/banlist.js index f058b665..723ae3fc 100644 --- a/src/plugins/irc-events/banlist.js +++ b/src/plugins/irc-events/banlist.js @@ -33,7 +33,7 @@ module.exports = function(irc, network) { let chan = network.getChannel(chanName); if (typeof chan === "undefined") { - chan = new Chan({ + chan = client.createChannel({ type: Chan.Type.SPECIAL, name: chanName, }); diff --git a/src/plugins/irc-events/chghost.js b/src/plugins/irc-events/chghost.js index 2636bb5f..b6e458fa 100644 --- a/src/plugins/irc-events/chghost.js +++ b/src/plugins/irc-events/chghost.js @@ -8,14 +8,6 @@ module.exports = function(irc, network) { // If server supports CHGHOST cap, then changing the hostname does not require // sending PART and JOIN, which means less work for us over all irc.on("user updated", function(data) { - const msg = new Msg({ - time: data.time, - type: Msg.Type.CHGHOST, - new_ident: data.ident !== data.new_ident ? data.new_ident : "", - new_host: data.hostname !== data.new_host ? data.new_host : "", - self: data.nick === irc.user.nick, - }); - network.channels.forEach((chan) => { const user = chan.findUser(data.nick); @@ -23,7 +15,14 @@ module.exports = function(irc, network) { return; } - msg.from = user; + const msg = new Msg({ + time: data.time, + type: Msg.Type.CHGHOST, + new_ident: data.ident !== data.new_ident ? data.new_ident : "", + new_host: data.hostname !== data.new_host ? data.new_host : "", + self: data.nick === irc.user.nick, + from: user, + }); chan.pushMessage(client, msg); }); diff --git a/src/plugins/irc-events/join.js b/src/plugins/irc-events/join.js index 29031f93..304fba83 100644 --- a/src/plugins/irc-events/join.js +++ b/src/plugins/irc-events/join.js @@ -11,7 +11,7 @@ module.exports = function(irc, network) { let chan = network.getChannel(data.channel); if (typeof chan === "undefined") { - chan = new Chan({ + chan = client.createChannel({ name: data.channel, state: Chan.State.JOINED, }); diff --git a/src/plugins/irc-events/list.js b/src/plugins/irc-events/list.js index 0a94bafe..4a141375 100644 --- a/src/plugins/irc-events/list.js +++ b/src/plugins/irc-events/list.js @@ -42,7 +42,7 @@ module.exports = function(irc, network) { let chan = network.getChannel("Channel List"); if (typeof chan === "undefined") { - chan = new Chan({ + chan = client.createChannel({ type: Chan.Type.SPECIAL, name: "Channel List", }); diff --git a/src/plugins/irc-events/message.js b/src/plugins/irc-events/message.js index fa20c6a8..a6e523ff 100644 --- a/src/plugins/irc-events/message.js +++ b/src/plugins/irc-events/message.js @@ -63,7 +63,7 @@ module.exports = function(irc, network) { showInActive = true; chan = network.channels[0]; } else { - chan = new Chan({ + chan = client.createChannel({ type: Chan.Type.QUERY, name: target, }); diff --git a/src/plugins/irc-events/nick.js b/src/plugins/irc-events/nick.js index 322b97d4..9f2172ca 100644 --- a/src/plugins/irc-events/nick.js +++ b/src/plugins/irc-events/nick.js @@ -6,14 +6,13 @@ module.exports = function(irc, network) { const client = this; irc.on("nick", function(data) { - let msg; const self = data.nick === irc.user.nick; if (self) { network.setNick(data.new_nick); const lobby = network.channels[0]; - msg = new Msg({ + const msg = new Msg({ text: `You're now known as ${data.new_nick}`, }); lobby.pushMessage(client, msg, true); @@ -32,7 +31,7 @@ module.exports = function(irc, network) { return; } - msg = new Msg({ + const msg = new Msg({ time: data.time, from: user, type: Msg.Type.NICK, diff --git a/src/plugins/irc-events/whois.js b/src/plugins/irc-events/whois.js index 6fe09599..ef6128be 100644 --- a/src/plugins/irc-events/whois.js +++ b/src/plugins/irc-events/whois.js @@ -9,7 +9,7 @@ module.exports = function(irc, network) { let chan = network.getChannel(data.nick); if (typeof chan === "undefined") { - chan = new Chan({ + chan = client.createChannel({ type: Chan.Type.QUERY, name: data.nick, }); diff --git a/src/plugins/sqlite.js b/src/plugins/sqlite.js index 2e4d0f87..c0c48c7d 100644 --- a/src/plugins/sqlite.js +++ b/src/plugins/sqlite.js @@ -17,7 +17,8 @@ const schema = [ ]; class MessageStorage { - constructor() { + constructor(client) { + this.client = client; this.isEnabled = false; } @@ -133,7 +134,10 @@ class MessageStorage { msg.time = row.time; msg.type = row.type; - return new Msg(msg); + const newMsg = new Msg(msg); + newMsg.id = this.client.idMsg++; + + return newMsg; }).reverse()); } )); diff --git a/test/models/chan.js b/test/models/chan.js index 34053ddf..9469e111 100644 --- a/test/models/chan.js +++ b/test/models/chan.js @@ -29,8 +29,9 @@ describe("Chan", function() { describe("#findMessage(id)", function() { const chan = new Chan({ messages: [ - new Msg(), + new Msg({id: 1}), new Msg({ + id: 2, text: "Message to be found", }), new Msg(), @@ -38,7 +39,7 @@ describe("Chan", function() { }); it("should find a message in the list of messages", function() { - expect(chan.findMessage(1).text).to.equal("Message to be found"); + expect(chan.findMessage(2).text).to.equal("Message to be found"); }); it("should not find a message that does not exist", function() { diff --git a/test/plugins/sqlite.js b/test/plugins/sqlite.js index 0d6e33a8..f343ac69 100644 --- a/test/plugins/sqlite.js +++ b/test/plugins/sqlite.js @@ -13,7 +13,9 @@ describe("SQLite Message Storage", function() { // Delete database file from previous test run before(function(done) { - store = new MessageStorage(); + store = new MessageStorage({ + idMsg: 1, + }); if (fs.existsSync(expectedPath)) { fs.unlink(expectedPath, done);