2016-10-09 19:14:02 +00:00
|
|
|
"use strict";
|
|
|
|
|
2014-09-13 21:29:45 +00:00
|
|
|
var _ = require("lodash");
|
2016-04-19 10:20:18 +00:00
|
|
|
var Helper = require("../helper");
|
2017-11-08 21:10:17 +00:00
|
|
|
const User = require("./user");
|
2017-09-14 07:41:50 +00:00
|
|
|
const userLog = require("../userLog");
|
2017-07-06 15:33:09 +00:00
|
|
|
const storage = require("../plugins/storage");
|
2014-09-13 21:29:45 +00:00
|
|
|
|
|
|
|
module.exports = Chan;
|
|
|
|
|
|
|
|
Chan.Type = {
|
|
|
|
CHANNEL: "channel",
|
|
|
|
LOBBY: "lobby",
|
2016-03-09 20:04:07 +00:00
|
|
|
QUERY: "query",
|
|
|
|
SPECIAL: "special",
|
2014-09-13 21:29:45 +00:00
|
|
|
};
|
|
|
|
|
2017-09-20 07:44:36 +00:00
|
|
|
let id = 1;
|
2014-09-13 21:29:45 +00:00
|
|
|
|
|
|
|
function Chan(attr) {
|
2016-10-02 07:37:37 +00:00
|
|
|
_.defaults(this, attr, {
|
2014-09-13 21:29:45 +00:00
|
|
|
id: id++,
|
|
|
|
messages: [],
|
|
|
|
name: "",
|
2017-04-01 08:33:17 +00:00
|
|
|
key: "",
|
2014-10-10 20:05:25 +00:00
|
|
|
topic: "",
|
2014-09-13 21:29:45 +00:00
|
|
|
type: Chan.Type.CHANNEL,
|
2016-05-13 10:23:05 +00:00
|
|
|
firstUnread: 0,
|
2014-09-21 16:48:01 +00:00
|
|
|
unread: 0,
|
2017-09-03 15:57:07 +00:00
|
|
|
highlight: 0,
|
2017-11-15 06:35:15 +00:00
|
|
|
users: [],
|
2016-10-02 07:37:37 +00:00
|
|
|
});
|
2014-09-13 21:29:45 +00:00
|
|
|
}
|
|
|
|
|
2017-08-11 12:02:58 +00:00
|
|
|
Chan.prototype.destroy = function() {
|
|
|
|
this.dereferencePreviews(this.messages);
|
|
|
|
};
|
|
|
|
|
2016-09-25 06:41:10 +00:00
|
|
|
Chan.prototype.pushMessage = function(client, msg, increasesUnread) {
|
|
|
|
var obj = {
|
2016-04-19 10:28:07 +00:00
|
|
|
chan: this.id,
|
2017-11-15 06:35:15 +00:00
|
|
|
msg: msg,
|
2016-09-25 06:41:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// If this channel is open in any of the clients, do not increase unread counter
|
2017-07-10 19:47:03 +00:00
|
|
|
const isOpen = _.find(client.attachedClients, {openChannel: this.id}) !== undefined;
|
2016-09-25 06:41:10 +00:00
|
|
|
|
|
|
|
if ((increasesUnread || msg.highlight) && !isOpen) {
|
|
|
|
obj.unread = ++this.unread;
|
|
|
|
}
|
|
|
|
|
|
|
|
client.emit("msg", obj);
|
2016-04-19 10:28:07 +00:00
|
|
|
|
|
|
|
// Never store messages in public mode as the session
|
|
|
|
// is completely destroyed when the page gets closed
|
2016-06-08 09:26:24 +00:00
|
|
|
if (Helper.config.public) {
|
2016-04-19 10:28:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-19 10:20:18 +00:00
|
|
|
this.messages.push(msg);
|
|
|
|
|
2017-09-14 07:41:50 +00:00
|
|
|
if (client.config.log === true) {
|
2017-09-17 05:11:04 +00:00
|
|
|
writeUserLog.call(this, client, msg);
|
2017-09-14 07:41:50 +00:00
|
|
|
}
|
|
|
|
|
2016-06-08 09:26:24 +00:00
|
|
|
if (Helper.config.maxHistory >= 0 && this.messages.length > Helper.config.maxHistory) {
|
2017-07-06 15:33:09 +00:00
|
|
|
const deleted = this.messages.splice(0, this.messages.length - Helper.config.maxHistory);
|
|
|
|
|
2017-08-11 12:02:58 +00:00
|
|
|
// If maxHistory is 0, image would be dereferenced before client had a chance to retrieve it,
|
|
|
|
// so for now, just don't implement dereferencing for this edge case.
|
|
|
|
if (Helper.config.prefetch && Helper.config.prefetchStorage && Helper.config.maxHistory > 0) {
|
|
|
|
this.dereferencePreviews(deleted);
|
2017-07-06 15:33:09 +00:00
|
|
|
}
|
2016-04-19 10:20:18 +00:00
|
|
|
}
|
2016-05-13 10:23:05 +00:00
|
|
|
|
2017-10-17 12:42:43 +00:00
|
|
|
if (msg.self) {
|
|
|
|
// reset counters/markers when receiving self-/echo-message
|
|
|
|
this.firstUnread = 0;
|
|
|
|
this.highlight = 0;
|
|
|
|
} else if (!isOpen) {
|
2016-05-13 10:23:05 +00:00
|
|
|
if (!this.firstUnread) {
|
|
|
|
this.firstUnread = msg.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.highlight) {
|
2017-09-03 15:57:07 +00:00
|
|
|
this.highlight++;
|
2016-05-13 10:23:05 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-19 10:20:18 +00:00
|
|
|
};
|
|
|
|
|
2017-08-11 12:02:58 +00:00
|
|
|
Chan.prototype.dereferencePreviews = function(messages) {
|
|
|
|
messages.forEach((message) => {
|
|
|
|
if (message.preview && message.preview.thumb) {
|
|
|
|
storage.dereference(message.preview.thumb);
|
|
|
|
message.preview.thumb = null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-03-14 11:44:06 +00:00
|
|
|
Chan.prototype.sortUsers = function(irc) {
|
|
|
|
var userModeSortPriority = {};
|
2016-10-12 07:55:40 +00:00
|
|
|
irc.network.options.PREFIX.forEach((prefix, index) => {
|
2016-03-14 11:44:06 +00:00
|
|
|
userModeSortPriority[prefix.symbol] = index;
|
|
|
|
});
|
|
|
|
|
|
|
|
userModeSortPriority[""] = 99; // No mode is lowest
|
|
|
|
|
|
|
|
this.users = this.users.sort(function(a, b) {
|
|
|
|
if (a.mode === b.mode) {
|
2017-06-01 18:54:46 +00:00
|
|
|
return a.nick.toLowerCase() < b.nick.toLowerCase() ? -1 : 1;
|
2016-03-14 11:44:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return userModeSortPriority[a.mode] - userModeSortPriority[b.mode];
|
|
|
|
});
|
2014-09-13 21:29:45 +00:00
|
|
|
};
|
|
|
|
|
2017-07-24 06:01:25 +00:00
|
|
|
Chan.prototype.findMessage = function(msgId) {
|
|
|
|
return this.messages.find((message) => message.id === msgId);
|
|
|
|
};
|
|
|
|
|
2017-07-10 10:56:37 +00:00
|
|
|
Chan.prototype.findUser = function(nick) {
|
|
|
|
return _.find(this.users, {nick: nick});
|
|
|
|
};
|
|
|
|
|
2017-11-08 21:10:17 +00:00
|
|
|
Chan.prototype.getUser = function(nick) {
|
|
|
|
return this.findUser(nick) || new User({nick: nick});
|
|
|
|
};
|
|
|
|
|
2014-09-13 21:29:45 +00:00
|
|
|
Chan.prototype.toJSON = function() {
|
|
|
|
var clone = _.clone(this);
|
2017-07-10 10:56:58 +00:00
|
|
|
clone.users = []; // Do not send user list, the client will explicitly request it when needed
|
2014-09-13 21:29:45 +00:00
|
|
|
clone.messages = clone.messages.slice(-100);
|
|
|
|
return clone;
|
|
|
|
};
|
2017-09-14 07:41:50 +00:00
|
|
|
|
|
|
|
function writeUserLog(client, msg) {
|
|
|
|
const target = client.find(this.id);
|
|
|
|
|
2017-09-29 07:37:27 +00:00
|
|
|
if (!target) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-09-14 07:41:50 +00:00
|
|
|
userLog.write(
|
|
|
|
client.name,
|
|
|
|
target.network.host, // TODO: Fix #1392, multiple connections to same server results in duplicate logs
|
|
|
|
this.type === Chan.Type.LOBBY ? target.network.host : this.name,
|
|
|
|
msg
|
|
|
|
);
|
|
|
|
}
|