Change users array to be a Map
This commit is contained in:
parent
56a9ad184d
commit
0f75c1a138
@ -483,7 +483,7 @@ Client.prototype.names = function(data) {
|
||||
|
||||
client.emit("names", {
|
||||
id: target.chan.id,
|
||||
users: target.chan.users,
|
||||
users: target.chan.getSortedUsers(target.network.irc),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,7 @@ function Chan(attr) {
|
||||
firstUnread: 0,
|
||||
unread: 0,
|
||||
highlight: 0,
|
||||
users: [],
|
||||
users: new Map(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ Chan.prototype.dereferencePreviews = function(messages) {
|
||||
});
|
||||
};
|
||||
|
||||
Chan.prototype.sortUsers = function(irc) {
|
||||
Chan.prototype.getSortedUsers = function(irc) {
|
||||
var userModeSortPriority = {};
|
||||
irc.network.options.PREFIX.forEach((prefix, index) => {
|
||||
userModeSortPriority[prefix.symbol] = index;
|
||||
@ -105,7 +105,9 @@ Chan.prototype.sortUsers = function(irc) {
|
||||
|
||||
userModeSortPriority[""] = 99; // No mode is lowest
|
||||
|
||||
this.users = this.users.sort(function(a, b) {
|
||||
const users = Array.from(this.users.values());
|
||||
|
||||
return users.sort(function(a, b) {
|
||||
if (a.mode === b.mode) {
|
||||
return a.nick.toLowerCase() < b.nick.toLowerCase() ? -1 : 1;
|
||||
}
|
||||
@ -119,13 +121,21 @@ Chan.prototype.findMessage = function(msgId) {
|
||||
};
|
||||
|
||||
Chan.prototype.findUser = function(nick) {
|
||||
return _.find(this.users, {nick: nick});
|
||||
return this.users.get(nick.toLowerCase());
|
||||
};
|
||||
|
||||
Chan.prototype.getUser = function(nick) {
|
||||
return this.findUser(nick) || new User({nick: nick});
|
||||
};
|
||||
|
||||
Chan.prototype.setUser = function(user) {
|
||||
this.users.set(user.nick.toLowerCase(), user);
|
||||
};
|
||||
|
||||
Chan.prototype.removeUser = function(user) {
|
||||
this.users.delete(user.nick.toLowerCase());
|
||||
};
|
||||
|
||||
Chan.prototype.toJSON = function() {
|
||||
var clone = _.clone(this);
|
||||
clone.users = []; // Do not send user list, the client will explicitly request it when needed
|
||||
|
@ -1,6 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require("lodash");
|
||||
const Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
@ -9,7 +8,7 @@ module.exports = function(irc, network) {
|
||||
const away = data.message;
|
||||
|
||||
network.channels.forEach((chan) => {
|
||||
const user = _.find(chan.users, {nick: data.nick});
|
||||
const user = chan.findUser(data.nick);
|
||||
|
||||
if (!user || user.away === away) {
|
||||
return;
|
||||
|
@ -35,8 +35,7 @@ module.exports = function(irc, network) {
|
||||
});
|
||||
chan.pushMessage(client, msg);
|
||||
|
||||
chan.users.push(user);
|
||||
chan.sortUsers(irc);
|
||||
chan.setUser(new User({nick: data.nick}));
|
||||
client.emit("users", {
|
||||
chan: chan.id,
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require("lodash");
|
||||
const Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
@ -25,9 +24,9 @@ module.exports = function(irc, network) {
|
||||
chan.pushMessage(client, msg);
|
||||
|
||||
if (data.kicked === irc.user.nick) {
|
||||
chan.users = [];
|
||||
chan.users = new Map();
|
||||
} else {
|
||||
chan.users = _.without(chan.users, msg.target);
|
||||
chan.removeUser(msg.target);
|
||||
}
|
||||
|
||||
client.emit("users", {
|
||||
|
@ -113,8 +113,6 @@ module.exports = function(irc, network) {
|
||||
// TODO: This is horrible
|
||||
irc.raw("NAMES", data.target);
|
||||
} else {
|
||||
targetChan.sortUsers(irc);
|
||||
|
||||
client.emit("users", {
|
||||
chan: targetChan.id,
|
||||
});
|
||||
|
@ -1,7 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const User = require("../../models/user");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
const client = this;
|
||||
|
||||
@ -11,31 +9,16 @@ module.exports = function(irc, network) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create lookup map of current users,
|
||||
// as we need to keep certain properties
|
||||
// and we can recycle existing User objects
|
||||
const oldUsers = new Map();
|
||||
const newUsers = new Map();
|
||||
|
||||
chan.users.forEach((user) => {
|
||||
oldUsers.set(user.nick, user);
|
||||
data.users.forEach((user) => {
|
||||
const newUser = chan.getUser(user.nick);
|
||||
newUser.setModes(user.modes, network.prefixLookup);
|
||||
|
||||
newUsers.set(user.nick.toLowerCase(), newUser);
|
||||
});
|
||||
|
||||
chan.users = data.users.map((user) => {
|
||||
const oldUser = oldUsers.get(user.nick);
|
||||
|
||||
// For existing users, we only need to update mode
|
||||
if (oldUser) {
|
||||
oldUser.setModes(user.modes, network.prefixLookup);
|
||||
return oldUser;
|
||||
}
|
||||
|
||||
return new User({
|
||||
nick: user.nick,
|
||||
modes: user.modes,
|
||||
}, network.prefixLookup);
|
||||
});
|
||||
|
||||
chan.sortUsers(irc);
|
||||
chan.users = newUsers;
|
||||
|
||||
client.emit("users", {
|
||||
chan: chan.id,
|
||||
|
@ -32,6 +32,10 @@ module.exports = function(irc, network) {
|
||||
return;
|
||||
}
|
||||
|
||||
chan.removeUser(user);
|
||||
user.nick = data.new_nick;
|
||||
chan.setUser(user);
|
||||
|
||||
msg = new Msg({
|
||||
time: data.time,
|
||||
from: user,
|
||||
@ -43,7 +47,6 @@ module.exports = function(irc, network) {
|
||||
|
||||
user.nick = data.new_nick;
|
||||
|
||||
chan.sortUsers(irc);
|
||||
client.emit("users", {
|
||||
chan: chan.id,
|
||||
});
|
||||
|
@ -32,7 +32,7 @@ module.exports = function(irc, network) {
|
||||
});
|
||||
chan.pushMessage(client, msg);
|
||||
|
||||
chan.users = _.without(chan.users, user);
|
||||
chan.removeUser(user);
|
||||
client.emit("users", {
|
||||
chan: chan.id,
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const _ = require("lodash");
|
||||
const Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
@ -23,7 +22,7 @@ module.exports = function(irc, network) {
|
||||
});
|
||||
chan.pushMessage(client, msg);
|
||||
|
||||
chan.users = _.without(chan.users, user);
|
||||
chan.removeUser(user);
|
||||
client.emit("users", {
|
||||
chan: chan.id,
|
||||
});
|
||||
|
@ -1,12 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
var expect = require("chai").expect;
|
||||
|
||||
var Chan = require("../../src/models/chan");
|
||||
var Msg = require("../../src/models/msg");
|
||||
var User = require("../../src/models/user");
|
||||
const expect = require("chai").expect;
|
||||
const Chan = require("../../src/models/chan");
|
||||
const Msg = require("../../src/models/msg");
|
||||
const User = require("../../src/models/user");
|
||||
|
||||
describe("Chan", function() {
|
||||
const network = {
|
||||
network: {
|
||||
options: {
|
||||
PREFIX: [
|
||||
{symbol: "~", mode: "q"},
|
||||
{symbol: "&", mode: "a"},
|
||||
{symbol: "@", mode: "o"},
|
||||
{symbol: "%", mode: "h"},
|
||||
{symbol: "+", mode: "v"},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const prefixLookup = {};
|
||||
|
||||
network.network.options.PREFIX.forEach((mode) => {
|
||||
prefixLookup[mode.mode] = mode.symbol;
|
||||
});
|
||||
|
||||
describe("#findMessage(id)", function() {
|
||||
const chan = new Chan({
|
||||
messages: [
|
||||
@ -27,40 +46,51 @@ describe("Chan", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#sortUsers(irc)", function() {
|
||||
var network = {
|
||||
network: {
|
||||
options: {
|
||||
PREFIX: [
|
||||
{symbol: "~", mode: "q"},
|
||||
{symbol: "&", mode: "a"},
|
||||
{symbol: "@", mode: "o"},
|
||||
{symbol: "%", mode: "h"},
|
||||
{symbol: "+", mode: "v"},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
describe("#setUser(user)", function() {
|
||||
it("should make key lowercase", function() {
|
||||
const chan = new Chan();
|
||||
chan.setUser(new User({nick: "TestUser"}));
|
||||
|
||||
var prefixLookup = {};
|
||||
|
||||
network.network.options.PREFIX.forEach((mode) => {
|
||||
prefixLookup[mode.mode] = mode.symbol;
|
||||
expect(chan.users.has("testuser")).to.be.true;
|
||||
});
|
||||
|
||||
var makeUser = function(nick) {
|
||||
return new User({nick: nick}, prefixLookup);
|
||||
};
|
||||
it("should update user object", function() {
|
||||
const chan = new Chan();
|
||||
chan.setUser(new User({nick: "TestUser"}, prefixLookup));
|
||||
chan.setUser(new User({nick: "TestUseR", modes: ["o"]}, prefixLookup));
|
||||
const user = chan.getUser("TestUSER");
|
||||
|
||||
expect(user.mode).to.equal("@");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getUser(nick)", function() {
|
||||
it("should returning existing object", function() {
|
||||
const chan = new Chan();
|
||||
chan.setUser(new User({nick: "TestUseR", modes: ["o"]}, prefixLookup));
|
||||
const user = chan.getUser("TestUSER");
|
||||
|
||||
expect(user.mode).to.equal("@");
|
||||
});
|
||||
|
||||
it("should make new User object if not found", function() {
|
||||
const chan = new Chan();
|
||||
const user = chan.getUser("very-testy-user");
|
||||
|
||||
expect(user.nick).to.equal("very-testy-user");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getSortedUsers(irc)", function() {
|
||||
var getUserNames = function(chan) {
|
||||
return chan.users.map((u) => u.nick);
|
||||
return chan.getSortedUsers(network).map((u) => u.nick);
|
||||
};
|
||||
|
||||
it("should sort a simple user list", function() {
|
||||
var chan = new Chan({users: [
|
||||
const chan = new Chan();
|
||||
[
|
||||
"JocelynD", "YaManicKill", "astorije", "xPaw", "Max-P",
|
||||
].map(makeUser)});
|
||||
chan.sortUsers(network);
|
||||
].forEach((nick) => chan.setUser(new User({nick: nick}, prefixLookup)));
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal([
|
||||
"astorije", "JocelynD", "Max-P", "xPaw", "YaManicKill",
|
||||
@ -68,14 +98,12 @@ describe("Chan", function() {
|
||||
});
|
||||
|
||||
it("should group users by modes", function() {
|
||||
var chan = new Chan({users: [
|
||||
new User({nick: "JocelynD", modes: ["a", "o"]}, prefixLookup),
|
||||
new User({nick: "YaManicKill", modes: ["v"]}, prefixLookup),
|
||||
new User({nick: "astorije", modes: ["h"]}, prefixLookup),
|
||||
new User({nick: "xPaw", modes: ["q"]}, prefixLookup),
|
||||
new User({nick: "Max-P", modes: ["o"]}, prefixLookup),
|
||||
]});
|
||||
chan.sortUsers(network);
|
||||
const chan = new Chan();
|
||||
chan.setUser(new User({nick: "JocelynD", modes: ["a", "o"]}, prefixLookup));
|
||||
chan.setUser(new User({nick: "YaManicKill", modes: ["v"]}, prefixLookup));
|
||||
chan.setUser(new User({nick: "astorije", modes: ["h"]}, prefixLookup));
|
||||
chan.setUser(new User({nick: "xPaw", modes: ["q"]}, prefixLookup));
|
||||
chan.setUser(new User({nick: "Max-P", modes: ["o"]}, prefixLookup));
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal([
|
||||
"xPaw", "JocelynD", "Max-P", "astorije", "YaManicKill",
|
||||
@ -83,14 +111,12 @@ describe("Chan", function() {
|
||||
});
|
||||
|
||||
it("should sort a mix of users and modes", function() {
|
||||
var chan = new Chan({users: [
|
||||
new User({nick: "JocelynD"}, prefixLookup),
|
||||
new User({nick: "YaManicKill", modes: ["o"]}, prefixLookup),
|
||||
new User({nick: "astorije"}, prefixLookup),
|
||||
new User({nick: "xPaw"}, prefixLookup),
|
||||
new User({nick: "Max-P", modes: ["o"]}, prefixLookup),
|
||||
]});
|
||||
chan.sortUsers(network);
|
||||
const chan = new Chan();
|
||||
chan.setUser(new User({nick: "JocelynD"}, prefixLookup));
|
||||
chan.setUser(new User({nick: "YaManicKill", modes: ["o"]}, prefixLookup));
|
||||
chan.setUser(new User({nick: "astorije"}, prefixLookup));
|
||||
chan.setUser(new User({nick: "xPaw"}, prefixLookup));
|
||||
chan.setUser(new User({nick: "Max-P", modes: ["o"]}, prefixLookup));
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal(
|
||||
["Max-P", "YaManicKill", "astorije", "JocelynD", "xPaw"]
|
||||
@ -98,18 +124,20 @@ describe("Chan", function() {
|
||||
});
|
||||
|
||||
it("should be case-insensitive", function() {
|
||||
var chan = new Chan({users: ["aB", "Ad", "AA", "ac"].map(makeUser)});
|
||||
chan.sortUsers(network);
|
||||
const chan = new Chan();
|
||||
[
|
||||
"aB", "Ad", "AA", "ac",
|
||||
].forEach((nick) => chan.setUser(new User({nick: nick}, prefixLookup)));
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal(["AA", "aB", "ac", "Ad"]);
|
||||
});
|
||||
|
||||
it("should parse special characters successfully", function() {
|
||||
var chan = new Chan({users: [
|
||||
const chan = new Chan();
|
||||
[
|
||||
"[foo", "]foo", "(foo)", "{foo}", "<foo>", "_foo", "@foo", "^foo",
|
||||
"&foo", "!foo", "+foo", "Foo",
|
||||
].map(makeUser)});
|
||||
chan.sortUsers(network);
|
||||
].forEach((nick) => chan.setUser(new User({nick: nick}, prefixLookup)));
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal([
|
||||
"!foo", "&foo", "(foo)", "+foo", "<foo>", "@foo", "[foo", "]foo",
|
||||
|
Loading…
Reference in New Issue
Block a user