1 | "use strict";
|
2 |
|
3 | var _ = require("lodash");
|
4 | var Helper = require("../helper");
|
5 | const User = require("./user");
|
6 | const userLog = require("../userLog");
|
7 | const storage = require("../plugins/storage");
|
8 |
|
9 | module.exports = Chan;
|
10 |
|
11 | Chan.Type = {
|
12 | CHANNEL: "channel",
|
13 | LOBBY: "lobby",
|
14 | QUERY: "query",
|
15 | SPECIAL: "special",
|
16 | };
|
17 |
|
18 | Chan.State = {
|
19 | PARTED: 0,
|
20 | JOINED: 1,
|
21 | };
|
22 |
|
23 | let id = 1;
|
24 |
|
25 | function Chan(attr) {
|
26 | _.defaults(this, attr, {
|
27 | id: id++,
|
28 | messages: [],
|
29 | name: "",
|
30 | key: "",
|
31 | topic: "",
|
32 | type: Chan.Type.CHANNEL,
|
33 | state: Chan.State.PARTED,
|
34 | firstUnread: 0,
|
35 | unread: 0,
|
36 | highlight: 0,
|
37 | users: new Map(),
|
38 | });
|
39 | }
|
40 |
|
41 | Chan.prototype.destroy = function() {
|
42 | this.dereferencePreviews(this.messages);
|
43 | };
|
44 |
|
45 | Chan.prototype.pushMessage = function(client, msg, increasesUnread) {
|
46 | var obj = {
|
47 | chan: this.id,
|
48 | msg: msg,
|
49 | };
|
50 |
|
51 |
|
52 | const isOpen = _.find(client.attachedClients, {openChannel: this.id}) !== undefined;
|
53 |
|
54 | if ((increasesUnread || msg.highlight) && !isOpen) {
|
55 | obj.unread = ++this.unread;
|
56 | }
|
57 |
|
58 | client.emit("msg", obj);
|
59 |
|
60 |
|
61 |
|
62 | if (Helper.config.public) {
|
63 | return;
|
64 | }
|
65 |
|
66 | this.messages.push(msg);
|
67 |
|
68 | if (client.config.log === true) {
|
69 | writeUserLog.call(this, client, msg);
|
70 | }
|
71 |
|
72 | if (Helper.config.maxHistory >= 0 && this.messages.length > Helper.config.maxHistory) {
|
73 | const deleted = this.messages.splice(0, this.messages.length - Helper.config.maxHistory);
|
74 |
|
75 |
|
76 |
|
77 | if (Helper.config.prefetch && Helper.config.prefetchStorage && Helper.config.maxHistory > 0) {
|
78 | this.dereferencePreviews(deleted);
|
79 | }
|
80 | }
|
81 |
|
82 | if (msg.self) {
|
83 |
|
84 | this.firstUnread = 0;
|
85 | this.highlight = 0;
|
86 | } else if (!isOpen) {
|
87 | if (!this.firstUnread) {
|
88 | this.firstUnread = msg.id;
|
89 | }
|
90 |
|
91 | if (msg.highlight) {
|
92 | this.highlight++;
|
93 | }
|
94 | }
|
95 | };
|
96 |
|
97 | Chan.prototype.dereferencePreviews = function(messages) {
|
98 | messages.forEach((message) => {
|
99 | if (message.preview && message.preview.thumb) {
|
100 | storage.dereference(message.preview.thumb);
|
101 | message.preview.thumb = null;
|
102 | }
|
103 | });
|
104 | };
|
105 |
|
106 | Chan.prototype.getSortedUsers = function(irc) {
|
107 | const users = Array.from(this.users.values());
|
108 |
|
109 | if (!irc || !irc.network || !irc.network.options || !irc.network.options.PREFIX) {
|
110 | return users;
|
111 | }
|
112 |
|
113 | var userModeSortPriority = {};
|
114 | irc.network.options.PREFIX.forEach((prefix, index) => {
|
115 | userModeSortPriority[prefix.symbol] = index;
|
116 | });
|
117 |
|
118 | userModeSortPriority[""] = 99;
|
119 |
|
120 | return users.sort(function(a, b) {
|
121 | if (a.mode === b.mode) {
|
122 | return a.nick.toLowerCase() < b.nick.toLowerCase() ? -1 : 1;
|
123 | }
|
124 |
|
125 | return userModeSortPriority[a.mode] - userModeSortPriority[b.mode];
|
126 | });
|
127 | };
|
128 |
|
129 | Chan.prototype.findMessage = function(msgId) {
|
130 | return this.messages.find((message) => message.id === msgId);
|
131 | };
|
132 |
|
133 | Chan.prototype.findUser = function(nick) {
|
134 | return this.users.get(nick.toLowerCase());
|
135 | };
|
136 |
|
137 | Chan.prototype.getUser = function(nick) {
|
138 | return this.findUser(nick) || new User({nick: nick});
|
139 | };
|
140 |
|
141 | Chan.prototype.setUser = function(user) {
|
142 | this.users.set(user.nick.toLowerCase(), user);
|
143 | };
|
144 |
|
145 | Chan.prototype.removeUser = function(user) {
|
146 | this.users.delete(user.nick.toLowerCase());
|
147 | };
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | Chan.prototype.getFilteredClone = function(lastActiveChannel, lastMessage) {
|
159 | return Object.keys(this).reduce((newChannel, prop) => {
|
160 | if (prop === "users") {
|
161 |
|
162 | newChannel[prop] = [];
|
163 | } else if (prop === "messages") {
|
164 |
|
165 | if (lastMessage > -1) {
|
166 |
|
167 |
|
168 | newChannel[prop] = this[prop]
|
169 | .filter((m) => m.id > lastMessage)
|
170 | .slice(-100);
|
171 | } else {
|
172 |
|
173 |
|
174 | const messagesToSend = lastActiveChannel === true || this.id === lastActiveChannel ? -100 : -1;
|
175 |
|
176 | newChannel[prop] = this[prop].slice(messagesToSend);
|
177 | }
|
178 | } else {
|
179 | newChannel[prop] = this[prop];
|
180 | }
|
181 |
|
182 | return newChannel;
|
183 | }, {});
|
184 | };
|
185 |
|
186 | function writeUserLog(client, msg) {
|
187 | if (!msg.isLoggable()) {
|
188 | return false;
|
189 | }
|
190 |
|
191 | const target = client.find(this.id);
|
192 |
|
193 | if (!target) {
|
194 | return false;
|
195 | }
|
196 |
|
197 | userLog.write(
|
198 | client.name,
|
199 | target.network.host,
|
200 | this.type === Chan.Type.LOBBY ? target.network.host : this.name,
|
201 | msg
|
202 | );
|
203 | }
|