Merge pull request #2396 from thelounge/xpaw/fix-2341

Use per-client channel and message ids
This commit is contained in:
Pavel Djundik 2018-05-01 13:26:38 +03:00 committed by GitHub
commit 886301e765
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 50 additions and 32 deletions

View file

@ -70,6 +70,8 @@ function Client(manager, name, config = {}) {
attachedClients: {}, attachedClients: {},
config: config, config: config,
id: uuidv4(), id: uuidv4(),
idChan: 1,
idMsg: 1,
name: name, name: name,
networks: [], networks: [],
sockets: manager.sockets, sockets: manager.sockets,
@ -80,7 +82,7 @@ function Client(manager, name, config = {}) {
let delay = 0; let delay = 0;
if (!Helper.config.public) { if (!Helper.config.public) {
client.messageStorage = new MessageStorage(); client.messageStorage = new MessageStorage(client);
if (client.config.log && Helper.config.messageStorage.includes("sqlite")) { if (client.config.log && Helper.config.messageStorage.includes("sqlite")) {
client.messageStorage.enable(client.name); 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) { Client.prototype.emit = function(event, data) {
if (this.sockets !== null) { if (this.sockets !== null) {
this.sockets.in(this.id).emit(event, data); this.sockets.in(this.id).emit(event, data);
@ -140,6 +149,9 @@ Client.prototype.connect = function(args) {
const client = this; const client = this;
let channels = []; let channels = [];
// Get channel id for lobby before creating other channels for nicer ids
const lobbyChannelId = client.idChan++;
if (args.channels) { if (args.channels) {
let badName = false; let badName = false;
@ -149,7 +161,7 @@ Client.prototype.connect = function(args) {
return; return;
} }
channels.push(new Chan({ channels.push(client.createChannel({
name: chan.name, name: chan.name,
key: chan.key || "", key: chan.key || "",
type: chan.type, type: chan.type,
@ -166,7 +178,7 @@ Client.prototype.connect = function(args) {
.replace(/,/g, " ") .replace(/,/g, " ")
.split(/\s+/g) .split(/\s+/g)
.map(function(chan) { .map(function(chan) {
return new Chan({ return client.createChannel({
name: chan, name: chan,
}); });
}); });
@ -189,6 +201,9 @@ Client.prototype.connect = function(args) {
channels: channels, channels: channels,
}); });
// Set network lobby channel id
network.channels[0].id = lobbyChannelId;
client.networks.push(network); client.networks.push(network);
client.emit("network", { client.emit("network", {
networks: [network.getFilteredClone(this.lastActiveChannel, -1)], networks: [network.getFilteredClone(this.lastActiveChannel, -1)],

View file

@ -20,11 +20,9 @@ Chan.State = {
JOINED: 1, JOINED: 1,
}; };
let id = 1;
function Chan(attr) { function Chan(attr) {
_.defaults(this, attr, { _.defaults(this, attr, {
id: id++, id: 0,
messages: [], messages: [],
name: "", name: "",
key: "", key: "",
@ -46,6 +44,8 @@ Chan.prototype.pushMessage = function(client, msg, increasesUnread) {
const chan = this.id; const chan = this.id;
const obj = {chan, msg}; const obj = {chan, msg};
msg.id = client.idMsg++;
// If this channel is open in any of the clients, do not increase unread counter // If this channel is open in any of the clients, do not increase unread counter
const isOpen = _.find(client.attachedClients, {openChannel: chan}) !== undefined; const isOpen = _.find(client.attachedClients, {openChannel: chan}) !== undefined;

View file

@ -2,8 +2,6 @@
const _ = require("lodash"); const _ = require("lodash");
let id = 0;
class Msg { class Msg {
constructor(attr) { constructor(attr) {
// Some properties need to be copied in the Msg object instead of referenced // Some properties need to be copied in the Msg object instead of referenced
@ -20,7 +18,7 @@ class Msg {
_.defaults(this, attr, { _.defaults(this, attr, {
from: {}, from: {},
id: id++, id: 0,
previews: [], previews: [],
text: "", text: "",
type: Msg.Type.MESSAGE, type: Msg.Type.MESSAGE,

View file

@ -43,7 +43,7 @@ exports.input = function(network, chan, cmd, args) {
} }
} }
const newChan = new Chan({ const newChan = this.createChannel({
type: Chan.Type.QUERY, type: Chan.Type.QUERY,
name: target, name: target,
}); });

View file

@ -33,7 +33,7 @@ module.exports = function(irc, network) {
let chan = network.getChannel(chanName); let chan = network.getChannel(chanName);
if (typeof chan === "undefined") { if (typeof chan === "undefined") {
chan = new Chan({ chan = client.createChannel({
type: Chan.Type.SPECIAL, type: Chan.Type.SPECIAL,
name: chanName, name: chanName,
}); });

View file

@ -8,14 +8,6 @@ module.exports = function(irc, network) {
// If server supports CHGHOST cap, then changing the hostname does not require // If server supports CHGHOST cap, then changing the hostname does not require
// sending PART and JOIN, which means less work for us over all // sending PART and JOIN, which means less work for us over all
irc.on("user updated", function(data) { 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) => { network.channels.forEach((chan) => {
const user = chan.findUser(data.nick); const user = chan.findUser(data.nick);
@ -23,7 +15,14 @@ module.exports = function(irc, network) {
return; 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); chan.pushMessage(client, msg);
}); });

View file

@ -11,7 +11,7 @@ module.exports = function(irc, network) {
let chan = network.getChannel(data.channel); let chan = network.getChannel(data.channel);
if (typeof chan === "undefined") { if (typeof chan === "undefined") {
chan = new Chan({ chan = client.createChannel({
name: data.channel, name: data.channel,
state: Chan.State.JOINED, state: Chan.State.JOINED,
}); });

View file

@ -42,7 +42,7 @@ module.exports = function(irc, network) {
let chan = network.getChannel("Channel List"); let chan = network.getChannel("Channel List");
if (typeof chan === "undefined") { if (typeof chan === "undefined") {
chan = new Chan({ chan = client.createChannel({
type: Chan.Type.SPECIAL, type: Chan.Type.SPECIAL,
name: "Channel List", name: "Channel List",
}); });

View file

@ -63,7 +63,7 @@ module.exports = function(irc, network) {
showInActive = true; showInActive = true;
chan = network.channels[0]; chan = network.channels[0];
} else { } else {
chan = new Chan({ chan = client.createChannel({
type: Chan.Type.QUERY, type: Chan.Type.QUERY,
name: target, name: target,
}); });

View file

@ -6,14 +6,13 @@ module.exports = function(irc, network) {
const client = this; const client = this;
irc.on("nick", function(data) { irc.on("nick", function(data) {
let msg;
const self = data.nick === irc.user.nick; const self = data.nick === irc.user.nick;
if (self) { if (self) {
network.setNick(data.new_nick); network.setNick(data.new_nick);
const lobby = network.channels[0]; const lobby = network.channels[0];
msg = new Msg({ const msg = new Msg({
text: `You're now known as ${data.new_nick}`, text: `You're now known as ${data.new_nick}`,
}); });
lobby.pushMessage(client, msg, true); lobby.pushMessage(client, msg, true);
@ -32,7 +31,7 @@ module.exports = function(irc, network) {
return; return;
} }
msg = new Msg({ const msg = new Msg({
time: data.time, time: data.time,
from: user, from: user,
type: Msg.Type.NICK, type: Msg.Type.NICK,

View file

@ -9,7 +9,7 @@ module.exports = function(irc, network) {
let chan = network.getChannel(data.nick); let chan = network.getChannel(data.nick);
if (typeof chan === "undefined") { if (typeof chan === "undefined") {
chan = new Chan({ chan = client.createChannel({
type: Chan.Type.QUERY, type: Chan.Type.QUERY,
name: data.nick, name: data.nick,
}); });

View file

@ -17,7 +17,8 @@ const schema = [
]; ];
class MessageStorage { class MessageStorage {
constructor() { constructor(client) {
this.client = client;
this.isEnabled = false; this.isEnabled = false;
} }
@ -133,7 +134,10 @@ class MessageStorage {
msg.time = row.time; msg.time = row.time;
msg.type = row.type; msg.type = row.type;
return new Msg(msg); const newMsg = new Msg(msg);
newMsg.id = this.client.idMsg++;
return newMsg;
}).reverse()); }).reverse());
} }
)); ));

View file

@ -29,8 +29,9 @@ describe("Chan", function() {
describe("#findMessage(id)", function() { describe("#findMessage(id)", function() {
const chan = new Chan({ const chan = new Chan({
messages: [ messages: [
new Msg(), new Msg({id: 1}),
new Msg({ new Msg({
id: 2,
text: "Message to be found", text: "Message to be found",
}), }),
new Msg(), new Msg(),
@ -38,7 +39,7 @@ describe("Chan", function() {
}); });
it("should find a message in the list of messages", 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() { it("should not find a message that does not exist", function() {

View file

@ -13,7 +13,9 @@ describe("SQLite Message Storage", function() {
// Delete database file from previous test run // Delete database file from previous test run
before(function(done) { before(function(done) {
store = new MessageStorage(); store = new MessageStorage({
idMsg: 1,
});
if (fs.existsSync(expectedPath)) { if (fs.existsSync(expectedPath)) {
fs.unlink(expectedPath, done); fs.unlink(expectedPath, done);