@lordbex/thelounge 4.4.3-blowfish → 4.5.0-blowfish-pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -7
- package/dist/defaults/config.js +31 -2
- package/dist/package.json +94 -91
- package/dist/server/client.js +188 -194
- package/dist/server/clientManager.js +75 -72
- package/dist/server/command-line/index.js +44 -43
- package/dist/server/command-line/install.js +37 -70
- package/dist/server/command-line/outdated.js +12 -17
- package/dist/server/command-line/start.js +25 -26
- package/dist/server/command-line/storage.js +26 -31
- package/dist/server/command-line/uninstall.js +16 -23
- package/dist/server/command-line/upgrade.js +20 -26
- package/dist/server/command-line/users/add.js +33 -40
- package/dist/server/command-line/users/edit.js +18 -24
- package/dist/server/command-line/users/index.js +12 -16
- package/dist/server/command-line/users/list.js +11 -39
- package/dist/server/command-line/users/remove.js +16 -22
- package/dist/server/command-line/users/reset.js +34 -35
- package/dist/server/command-line/utils.js +231 -87
- package/dist/server/config.js +61 -52
- package/dist/server/helper.js +29 -28
- package/dist/server/identification.js +39 -34
- package/dist/server/index.js +1 -3
- package/dist/server/log.js +19 -16
- package/dist/server/models/chan.js +36 -33
- package/dist/server/models/msg.js +15 -19
- package/dist/server/models/network.js +102 -104
- package/dist/server/models/prefix.js +4 -7
- package/dist/server/models/user.js +5 -10
- package/dist/server/path-helper.js +8 -0
- package/dist/server/plugins/auth/ldap.js +177 -112
- package/dist/server/plugins/auth/local.js +10 -15
- package/dist/server/plugins/auth.js +6 -35
- package/dist/server/plugins/changelog.js +30 -27
- package/dist/server/plugins/clientCertificate.js +33 -37
- package/dist/server/plugins/dev-server.js +15 -21
- package/dist/server/plugins/inputs/action.js +9 -14
- package/dist/server/plugins/inputs/away.js +1 -3
- package/dist/server/plugins/inputs/ban.js +9 -14
- package/dist/server/plugins/inputs/blow.js +9 -14
- package/dist/server/plugins/inputs/connect.js +5 -10
- package/dist/server/plugins/inputs/ctcp.js +7 -12
- package/dist/server/plugins/inputs/disconnect.js +1 -3
- package/dist/server/plugins/inputs/ignore.js +23 -29
- package/dist/server/plugins/inputs/ignorelist.js +12 -18
- package/dist/server/plugins/inputs/index.js +8 -34
- package/dist/server/plugins/inputs/invite.js +7 -12
- package/dist/server/plugins/inputs/kick.js +7 -12
- package/dist/server/plugins/inputs/kill.js +1 -3
- package/dist/server/plugins/inputs/list.js +1 -3
- package/dist/server/plugins/inputs/mode.js +10 -15
- package/dist/server/plugins/inputs/msg.js +13 -18
- package/dist/server/plugins/inputs/mute.js +9 -15
- package/dist/server/plugins/inputs/nick.js +9 -14
- package/dist/server/plugins/inputs/notice.js +5 -7
- package/dist/server/plugins/inputs/part.js +11 -16
- package/dist/server/plugins/inputs/quit.js +7 -13
- package/dist/server/plugins/inputs/rainbow.js +55 -0
- package/dist/server/plugins/inputs/raw.js +1 -3
- package/dist/server/plugins/inputs/rejoin.js +7 -12
- package/dist/server/plugins/inputs/topic.js +7 -12
- package/dist/server/plugins/inputs/whois.js +1 -3
- package/dist/server/plugins/irc-events/away.js +14 -20
- package/dist/server/plugins/irc-events/cap.js +16 -22
- package/dist/server/plugins/irc-events/chghost.js +14 -13
- package/dist/server/plugins/irc-events/connection.js +61 -63
- package/dist/server/plugins/irc-events/ctcp.js +22 -28
- package/dist/server/plugins/irc-events/error.js +20 -26
- package/dist/server/plugins/irc-events/help.js +7 -13
- package/dist/server/plugins/irc-events/info.js +7 -13
- package/dist/server/plugins/irc-events/invite.js +7 -13
- package/dist/server/plugins/irc-events/join.js +30 -27
- package/dist/server/plugins/irc-events/kick.js +21 -17
- package/dist/server/plugins/irc-events/link.js +122 -109
- package/dist/server/plugins/irc-events/list.js +23 -26
- package/dist/server/plugins/irc-events/message.js +46 -52
- package/dist/server/plugins/irc-events/mode.js +66 -63
- package/dist/server/plugins/irc-events/modelist.js +29 -35
- package/dist/server/plugins/irc-events/motd.js +10 -16
- package/dist/server/plugins/irc-events/names.js +3 -6
- package/dist/server/plugins/irc-events/nick.js +26 -23
- package/dist/server/plugins/irc-events/part.js +19 -15
- package/dist/server/plugins/irc-events/quit.js +17 -14
- package/dist/server/plugins/irc-events/sasl.js +9 -15
- package/dist/server/plugins/irc-events/spgroups.js +38 -0
- package/dist/server/plugins/irc-events/spjoin.js +52 -0
- package/dist/server/plugins/irc-events/topic.js +12 -18
- package/dist/server/plugins/irc-events/unhandled.js +12 -12
- package/dist/server/plugins/irc-events/welcome.js +7 -13
- package/dist/server/plugins/irc-events/whois.js +20 -24
- package/dist/server/plugins/massEventAggregator.js +214 -0
- package/dist/server/plugins/messageStorage/sqlite.js +322 -141
- package/dist/server/plugins/messageStorage/text.js +21 -26
- package/dist/server/plugins/packages/index.js +105 -74
- package/dist/server/plugins/packages/publicClient.js +7 -16
- package/dist/server/plugins/packages/themes.js +11 -16
- package/dist/server/plugins/storage.js +28 -33
- package/dist/server/plugins/sts.js +12 -17
- package/dist/server/plugins/uploader.js +40 -43
- package/dist/server/plugins/webpush.js +23 -51
- package/dist/server/server.js +318 -271
- package/dist/server/storageCleaner.js +29 -37
- package/dist/server/utils/fish.js +349 -389
- package/dist/shared/irc.js +3 -6
- package/dist/shared/linkify.js +7 -14
- package/dist/shared/types/chan.js +6 -9
- package/dist/shared/types/changelog.js +1 -2
- package/dist/shared/types/config.js +1 -2
- package/dist/shared/types/mention.js +1 -2
- package/dist/shared/types/msg.js +3 -5
- package/dist/shared/types/network.js +1 -2
- package/dist/shared/types/storage.js +1 -2
- package/dist/shared/types/user.js +1 -2
- package/index.js +14 -10
- package/package.json +94 -91
- package/public/css/style.css +9 -6
- package/public/css/style.css.map +1 -1
- package/public/fonts/font-awesome/fa-brands-400.ttf +0 -0
- package/public/fonts/font-awesome/fa-brands-400.woff2 +0 -0
- package/public/fonts/font-awesome/fa-duotone-900.ttf +0 -0
- package/public/fonts/font-awesome/fa-duotone-900.woff2 +0 -0
- package/public/fonts/font-awesome/fa-light-300.ttf +0 -0
- package/public/fonts/font-awesome/fa-light-300.woff2 +0 -0
- package/public/fonts/font-awesome/fa-regular-400.ttf +0 -0
- package/public/fonts/font-awesome/fa-regular-400.woff2 +0 -0
- package/public/fonts/font-awesome/fa-solid-900.ttf +0 -0
- package/public/fonts/font-awesome/fa-solid-900.woff2 +0 -0
- package/public/fonts/font-awesome/fa-thin-100.ttf +0 -0
- package/public/fonts/font-awesome/fa-thin-100.woff2 +0 -0
- package/public/fonts/font-awesome/fa-v4compatibility.ttf +0 -0
- package/public/fonts/font-awesome/fa-v4compatibility.woff2 +0 -0
- package/public/js/bundle.js +1 -1
- package/public/js/bundle.js.map +1 -1
- package/public/js/bundle.vendor.js +1 -1
- package/public/js/bundle.vendor.js.LICENSE.txt +24 -6
- package/public/js/bundle.vendor.js.map +1 -1
- package/public/js/loading-error-handlers.js +1 -1
- package/public/service-worker.js +1 -1
- package/public/themes/default.css +1 -1
- package/public/themes/morning.css +1 -1
- package/dist/webpack.config.js +0 -224
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const config_1 = __importDefault(require("../config"));
|
|
14
|
-
const sts_1 = __importDefault(require("../plugins/sts"));
|
|
15
|
-
const clientCertificate_1 = __importDefault(require("../plugins/clientCertificate"));
|
|
16
|
-
const msg_2 = require("../../shared/types/msg");
|
|
17
|
-
const chan_2 = require("../../shared/types/chan");
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
import { v4 as uuidv4 } from "uuid";
|
|
3
|
+
import IrcFramework from "irc-framework";
|
|
4
|
+
import Chan from "./chan.js";
|
|
5
|
+
import Msg from "./msg.js";
|
|
6
|
+
import Prefix from "./prefix.js";
|
|
7
|
+
import Helper from "../helper.js";
|
|
8
|
+
import Config from "../config.js";
|
|
9
|
+
import STSPolicies from "../plugins/sts.js";
|
|
10
|
+
import ClientCertificate from "../plugins/clientCertificate.js";
|
|
11
|
+
import { MessageType } from "../../shared/types/msg.js";
|
|
12
|
+
import { ChanType } from "../../shared/types/chan.js";
|
|
18
13
|
class Network {
|
|
19
14
|
nick;
|
|
20
15
|
name;
|
|
@@ -52,7 +47,7 @@ class Network {
|
|
|
52
47
|
// TODO: this is only available on export
|
|
53
48
|
hasSTSPolicy;
|
|
54
49
|
constructor(attr) {
|
|
55
|
-
|
|
50
|
+
_.defaults(this, attr, {
|
|
56
51
|
name: "",
|
|
57
52
|
nick: "",
|
|
58
53
|
host: "",
|
|
@@ -73,7 +68,7 @@ class Network {
|
|
|
73
68
|
irc: null,
|
|
74
69
|
serverOptions: {
|
|
75
70
|
CHANTYPES: ["#", "&"],
|
|
76
|
-
PREFIX: new
|
|
71
|
+
PREFIX: new Prefix([
|
|
77
72
|
{ symbol: "!", mode: "Y" },
|
|
78
73
|
{ symbol: "@", mode: "o" },
|
|
79
74
|
{ symbol: "%", mode: "h" },
|
|
@@ -94,18 +89,18 @@ class Network {
|
|
|
94
89
|
keepNick: null,
|
|
95
90
|
});
|
|
96
91
|
if (!this.uuid) {
|
|
97
|
-
this.uuid = (
|
|
92
|
+
this.uuid = uuidv4();
|
|
98
93
|
}
|
|
99
94
|
if (!this.name) {
|
|
100
95
|
this.name = this.host;
|
|
101
96
|
}
|
|
102
|
-
this.channels.unshift(new
|
|
97
|
+
this.channels.unshift(new Chan({
|
|
103
98
|
name: this.name,
|
|
104
|
-
type:
|
|
99
|
+
type: ChanType.LOBBY,
|
|
105
100
|
// The lobby only starts as muted if every channel (unless it's special) is muted.
|
|
106
101
|
// This is A) easier to implement and B) stops some confusion on startup.
|
|
107
102
|
muted: this.channels.length >= 1 &&
|
|
108
|
-
this.channels.every((chan) => chan.muted || chan.type ===
|
|
103
|
+
this.channels.every((chan) => chan.muted || chan.type === ChanType.SPECIAL),
|
|
109
104
|
}));
|
|
110
105
|
// Ensure FiSH keys are applied to any pre-existing channels loaded from disk
|
|
111
106
|
this.applyBlowKeysToChannels();
|
|
@@ -115,7 +110,7 @@ class Network {
|
|
|
115
110
|
const cleanNick = (str) => str.replace(/[\x00\s:!@]/g, "_").substring(0, 100);
|
|
116
111
|
// Remove new lines and limit length
|
|
117
112
|
const cleanString = (str) => str.replace(/[\x00\r\n]/g, "").substring(0, 300);
|
|
118
|
-
this.setNick(cleanNick(String(this.nick ||
|
|
113
|
+
this.setNick(cleanNick(String(this.nick || Config.getDefaultNick())));
|
|
119
114
|
if (!this.username) {
|
|
120
115
|
// If username is empty, make one from the provided nick
|
|
121
116
|
this.username = this.nick.replace(/[^a-zA-Z0-9]/g, "");
|
|
@@ -134,8 +129,8 @@ class Network {
|
|
|
134
129
|
this.proxyPassword = cleanString(this.proxyPassword);
|
|
135
130
|
this.proxyEnabled = !!this.proxyEnabled;
|
|
136
131
|
const error = function (network, text) {
|
|
137
|
-
network.getLobby().pushMessage(client, new
|
|
138
|
-
type:
|
|
132
|
+
network.getLobby().pushMessage(client, new Msg({
|
|
133
|
+
type: MessageType.ERROR,
|
|
139
134
|
text: text,
|
|
140
135
|
}), true);
|
|
141
136
|
};
|
|
@@ -145,30 +140,30 @@ class Network {
|
|
|
145
140
|
if (!["", "plain", "external"].includes(this.sasl)) {
|
|
146
141
|
this.sasl = "";
|
|
147
142
|
}
|
|
148
|
-
if (
|
|
143
|
+
if (Config.values.lockNetwork) {
|
|
149
144
|
// This check is needed to prevent invalid user configurations
|
|
150
|
-
if (!
|
|
145
|
+
if (!Config.values.public &&
|
|
151
146
|
this.host &&
|
|
152
147
|
this.host.length > 0 &&
|
|
153
|
-
this.host !==
|
|
148
|
+
this.host !== Config.values.defaults.host) {
|
|
154
149
|
error(this, `The hostname you specified (${this.host}) is not allowed.`);
|
|
155
150
|
return false;
|
|
156
151
|
}
|
|
157
|
-
if (
|
|
158
|
-
this.name =
|
|
152
|
+
if (Config.values.public) {
|
|
153
|
+
this.name = Config.values.defaults.name;
|
|
159
154
|
// Sync lobby channel name
|
|
160
|
-
this.getLobby().name =
|
|
155
|
+
this.getLobby().name = Config.values.defaults.name;
|
|
161
156
|
}
|
|
162
|
-
this.host =
|
|
163
|
-
this.port =
|
|
164
|
-
this.tls =
|
|
165
|
-
this.rejectUnauthorized =
|
|
157
|
+
this.host = Config.values.defaults.host;
|
|
158
|
+
this.port = Config.values.defaults.port;
|
|
159
|
+
this.tls = Config.values.defaults.tls;
|
|
160
|
+
this.rejectUnauthorized = Config.values.defaults.rejectUnauthorized;
|
|
166
161
|
}
|
|
167
162
|
if (this.host.length === 0) {
|
|
168
163
|
error(this, "You must specify a hostname to connect.");
|
|
169
164
|
return false;
|
|
170
165
|
}
|
|
171
|
-
const stsPolicy =
|
|
166
|
+
const stsPolicy = STSPolicies.get(this.host);
|
|
172
167
|
if (stsPolicy && !this.tls) {
|
|
173
168
|
error(this, `${this.host} has an active strict transport security policy, will connect to port ${stsPolicy.port} over a secure connection.`);
|
|
174
169
|
this.port = stsPolicy.port;
|
|
@@ -178,9 +173,9 @@ class Network {
|
|
|
178
173
|
return true;
|
|
179
174
|
}
|
|
180
175
|
createIrcFramework(client) {
|
|
181
|
-
this.irc = new
|
|
176
|
+
this.irc = new IrcFramework.Client({
|
|
182
177
|
version: false, // We handle it ourselves
|
|
183
|
-
outgoing_addr:
|
|
178
|
+
outgoing_addr: Config.values.bind,
|
|
184
179
|
enable_chghost: true,
|
|
185
180
|
enable_echomessage: true,
|
|
186
181
|
enable_setname: true,
|
|
@@ -191,18 +186,21 @@ class Network {
|
|
|
191
186
|
// TODO: this type should be set after setIrcFrameworkOptions
|
|
192
187
|
});
|
|
193
188
|
this.setIrcFrameworkOptions(client);
|
|
194
|
-
|
|
189
|
+
// Request custom capabilities
|
|
190
|
+
const customCaps = [
|
|
195
191
|
"znc.in/self-message", // Legacy echo-message for ZNC
|
|
196
192
|
"znc.in/playback", // See http://wiki.znc.in/Playback
|
|
197
|
-
|
|
193
|
+
"seedpool/enhanced", // THC enhanced client features
|
|
194
|
+
];
|
|
195
|
+
this.irc.requestCap(customCaps);
|
|
198
196
|
}
|
|
199
197
|
setIrcFrameworkOptions(client) {
|
|
200
198
|
this.irc.options.host = this.host;
|
|
201
199
|
this.irc.options.port = this.port;
|
|
202
200
|
this.irc.options.password = this.password;
|
|
203
201
|
this.irc.options.nick = this.nick;
|
|
204
|
-
this.irc.options.username =
|
|
205
|
-
?
|
|
202
|
+
this.irc.options.username = Config.values.useHexIp
|
|
203
|
+
? Helper.ip2hex(client.config.browser.ip)
|
|
206
204
|
: this.username;
|
|
207
205
|
this.irc.options.gecos = this.realname;
|
|
208
206
|
this.irc.options.tls = this.tls;
|
|
@@ -222,12 +220,15 @@ class Network {
|
|
|
222
220
|
}
|
|
223
221
|
if (!this.sasl) {
|
|
224
222
|
delete this.irc.options.sasl_mechanism;
|
|
225
|
-
|
|
223
|
+
// irc-framework has a funny fallback where it uses nick + server pw
|
|
224
|
+
// in the sasl handshake, if account is undefined, so we need an empty
|
|
225
|
+
// object here to really turn it off
|
|
226
|
+
this.irc.options.account = {};
|
|
226
227
|
}
|
|
227
228
|
else if (this.sasl === "external") {
|
|
228
229
|
this.irc.options.sasl_mechanism = "EXTERNAL";
|
|
229
230
|
this.irc.options.account = {};
|
|
230
|
-
this.irc.options.client_certificate =
|
|
231
|
+
this.irc.options.client_certificate = ClientCertificate.get(this.uuid);
|
|
231
232
|
}
|
|
232
233
|
else if (this.sasl === "plain") {
|
|
233
234
|
delete this.irc.options.sasl_mechanism;
|
|
@@ -247,19 +248,19 @@ class Network {
|
|
|
247
248
|
}
|
|
248
249
|
applyBlowKeysToChannels() {
|
|
249
250
|
for (const c of this.channels) {
|
|
250
|
-
if (c.type !==
|
|
251
|
+
if (c.type !== ChanType.CHANNEL && c.type !== ChanType.QUERY) {
|
|
251
252
|
continue;
|
|
252
253
|
}
|
|
253
254
|
c.blowfishKey = this.resolveBlowKeyFor(c.name);
|
|
254
255
|
}
|
|
255
256
|
}
|
|
256
257
|
createWebIrc(client) {
|
|
257
|
-
if (!
|
|
258
|
-
!Object.prototype.hasOwnProperty.call(
|
|
258
|
+
if (!Config.values.webirc ||
|
|
259
|
+
!Object.prototype.hasOwnProperty.call(Config.values.webirc, this.host)) {
|
|
259
260
|
return null;
|
|
260
261
|
}
|
|
261
262
|
const webircObject = {
|
|
262
|
-
password:
|
|
263
|
+
password: Config.values.webirc[this.host],
|
|
263
264
|
username: "thelounge",
|
|
264
265
|
address: client.config.browser?.ip,
|
|
265
266
|
hostname: client.config.browser?.hostname,
|
|
@@ -271,9 +272,9 @@ class Network {
|
|
|
271
272
|
secure: true,
|
|
272
273
|
};
|
|
273
274
|
}
|
|
274
|
-
if (typeof
|
|
275
|
+
if (typeof Config.values.webirc[this.host] === "function") {
|
|
275
276
|
webircObject.password = null;
|
|
276
|
-
return
|
|
277
|
+
return Config.values.webirc[this.host](webircObject, this);
|
|
277
278
|
}
|
|
278
279
|
return webircObject;
|
|
279
280
|
}
|
|
@@ -282,52 +283,49 @@ class Network {
|
|
|
282
283
|
const oldNick = this.nick;
|
|
283
284
|
const oldRealname = this.realname;
|
|
284
285
|
this.keepNick = null;
|
|
285
|
-
this.nick = args.nick;
|
|
286
|
-
this.host = String(args.host
|
|
287
|
-
this.name = String(args.name
|
|
288
|
-
this.port = parseInt(args.port, 10);
|
|
286
|
+
this.nick = String(args.nick ?? "");
|
|
287
|
+
this.host = String(args.host ?? "");
|
|
288
|
+
this.name = String(args.name ?? "") || this.host;
|
|
289
|
+
this.port = parseInt(String(args.port ?? 6667), 10);
|
|
289
290
|
this.tls = !!args.tls;
|
|
290
291
|
this.rejectUnauthorized = !!args.rejectUnauthorized;
|
|
291
|
-
this.password = String(args.password
|
|
292
|
-
this.username = String(args.username
|
|
293
|
-
this.realname = String(args.realname
|
|
294
|
-
this.leaveMessage = String(args.leaveMessage
|
|
295
|
-
this.sasl = String(args.sasl
|
|
296
|
-
this.saslAccount = String(args.saslAccount
|
|
297
|
-
this.saslPassword = String(args.saslPassword
|
|
298
|
-
this.proxyHost = String(args.proxyHost
|
|
299
|
-
this.proxyPort = parseInt(args.proxyPort, 10);
|
|
300
|
-
this.proxyUsername = String(args.proxyUsername
|
|
301
|
-
this.proxyPassword = String(args.proxyPassword
|
|
292
|
+
this.password = String(args.password ?? "");
|
|
293
|
+
this.username = String(args.username ?? "");
|
|
294
|
+
this.realname = String(args.realname ?? "");
|
|
295
|
+
this.leaveMessage = String(args.leaveMessage ?? "");
|
|
296
|
+
this.sasl = String(args.sasl ?? "");
|
|
297
|
+
this.saslAccount = String(args.saslAccount ?? "");
|
|
298
|
+
this.saslPassword = String(args.saslPassword ?? "");
|
|
299
|
+
this.proxyHost = String(args.proxyHost ?? "");
|
|
300
|
+
this.proxyPort = parseInt(String(args.proxyPort ?? 1080), 10);
|
|
301
|
+
this.proxyUsername = String(args.proxyUsername ?? "");
|
|
302
|
+
this.proxyPassword = String(args.proxyPassword ?? "");
|
|
302
303
|
this.proxyEnabled = !!args.proxyEnabled;
|
|
303
304
|
// Split commands into an array
|
|
304
|
-
|
|
305
|
+
const commandsStr = Array.isArray(args.commands)
|
|
306
|
+
? args.commands.join("\n")
|
|
307
|
+
: String(args.commands ?? "");
|
|
308
|
+
this.commands = commandsStr
|
|
305
309
|
.replace(/\r\n|\r|\n/g, "\n")
|
|
306
310
|
.split("\n")
|
|
307
311
|
.filter((command) => command.length > 0);
|
|
308
312
|
// FiSH: read global key and per-target keys (only update when provided)
|
|
309
313
|
if (Object.prototype.hasOwnProperty.call(args, "fishGlobalKey")) {
|
|
310
|
-
this.fishGlobalKey =
|
|
314
|
+
this.fishGlobalKey = Helper.toTrimmedString(args.fishGlobalKey || "");
|
|
311
315
|
}
|
|
312
|
-
|
|
313
|
-
|
|
316
|
+
// FiSH: read per-target keys (only update when provided)
|
|
317
|
+
if (Object.prototype.hasOwnProperty.call(args, "fishKeys")) {
|
|
318
|
+
const value = args.fishKeys;
|
|
314
319
|
const map = {};
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
return;
|
|
320
|
+
if (value && typeof value === "object") {
|
|
321
|
+
for (const [rawName, rawKey] of Object.entries(value)) {
|
|
322
|
+
const name = Helper.toTrimmedString(rawName).toLowerCase();
|
|
323
|
+
const key = Helper.toTrimmedString(rawKey);
|
|
324
|
+
if (name && key) {
|
|
325
|
+
map[name] = key;
|
|
326
|
+
}
|
|
323
327
|
}
|
|
324
|
-
|
|
325
|
-
const key = trimmed.substring(spaceIdx + 1).trim();
|
|
326
|
-
if (!name || !key) {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
map[name] = key;
|
|
330
|
-
});
|
|
328
|
+
}
|
|
331
329
|
this.fishKeys = map;
|
|
332
330
|
}
|
|
333
331
|
// Sync lobby channel name
|
|
@@ -383,7 +381,7 @@ class Network {
|
|
|
383
381
|
// Do not match characters and numbers (unless IRC color)
|
|
384
382
|
"(?:^|[^a-z0-9]|\x03[0-9]{1,2})" +
|
|
385
383
|
// Escape nickname, as it may contain regex stuff
|
|
386
|
-
|
|
384
|
+
_.escapeRegExp(nick) +
|
|
387
385
|
// Do not match characters and numbers
|
|
388
386
|
"(?:[^a-z0-9]|$)",
|
|
389
387
|
// Case insensitive search
|
|
@@ -413,7 +411,7 @@ class Network {
|
|
|
413
411
|
if (this.irc && this.irc.connection && this.irc.connection.transport) {
|
|
414
412
|
const transport = this.irc.connection.transport;
|
|
415
413
|
if (transport.socket) {
|
|
416
|
-
const isLocalhost =
|
|
414
|
+
const isLocalhost = ["127.0.0.1", "::1"].includes(transport.socket.remoteAddress);
|
|
417
415
|
const isAuthorized = transport.socket.encrypted && transport.socket.authorized;
|
|
418
416
|
status.connected = transport.isConnected();
|
|
419
417
|
status.secure = isAuthorized || isLocalhost;
|
|
@@ -423,12 +421,12 @@ class Network {
|
|
|
423
421
|
}
|
|
424
422
|
addChannel(newChan) {
|
|
425
423
|
// Assign FiSH key based on network configuration when adding
|
|
426
|
-
if (newChan && (newChan.type ===
|
|
424
|
+
if (newChan && (newChan.type === ChanType.CHANNEL || newChan.type === ChanType.QUERY)) {
|
|
427
425
|
newChan.blowfishKey = this.resolveBlowKeyFor(newChan.name);
|
|
428
426
|
}
|
|
429
427
|
let index = this.channels.length; // Default to putting as the last item in the array
|
|
430
428
|
// Don't sort special channels in amongst channels/users.
|
|
431
|
-
if (newChan.type ===
|
|
429
|
+
if (newChan.type === ChanType.CHANNEL || newChan.type === ChanType.QUERY) {
|
|
432
430
|
// We start at 1 so we don't test against the lobby
|
|
433
431
|
for (let i = 1; i < this.channels.length; i++) {
|
|
434
432
|
const compareChan = this.channels[i];
|
|
@@ -436,7 +434,7 @@ class Network {
|
|
|
436
434
|
if (newChan.name.localeCompare(compareChan.name, undefined, {
|
|
437
435
|
sensitivity: "base",
|
|
438
436
|
}) <= 0 ||
|
|
439
|
-
(compareChan.type !==
|
|
437
|
+
(compareChan.type !== ChanType.CHANNEL && compareChan.type !== ChanType.QUERY)) {
|
|
440
438
|
index = i;
|
|
441
439
|
break;
|
|
442
440
|
}
|
|
@@ -450,8 +448,8 @@ class Network {
|
|
|
450
448
|
return;
|
|
451
449
|
}
|
|
452
450
|
// https://ircv3.net/specs/extensions/sts#rescheduling-expiry-on-disconnect
|
|
453
|
-
|
|
454
|
-
this.irc.quit(quitMessage || this.leaveMessage ||
|
|
451
|
+
STSPolicies.refreshExpiration(this.host);
|
|
452
|
+
this.irc.quit(quitMessage || this.leaveMessage || Config.values.leaveMessage);
|
|
455
453
|
}
|
|
456
454
|
exportForEdit() {
|
|
457
455
|
const fieldsToReturn = [
|
|
@@ -472,22 +470,21 @@ class Network {
|
|
|
472
470
|
"proxyUsername",
|
|
473
471
|
"proxyPassword",
|
|
474
472
|
];
|
|
475
|
-
if (!
|
|
473
|
+
if (!Config.values.lockNetwork) {
|
|
476
474
|
fieldsToReturn.push("host");
|
|
477
475
|
fieldsToReturn.push("port");
|
|
478
476
|
fieldsToReturn.push("tls");
|
|
479
477
|
fieldsToReturn.push("rejectUnauthorized");
|
|
480
478
|
}
|
|
481
|
-
const data =
|
|
482
|
-
data.hasSTSPolicy = !!
|
|
479
|
+
const data = _.pick(this, fieldsToReturn);
|
|
480
|
+
data.hasSTSPolicy = !!STSPolicies.get(this.host);
|
|
483
481
|
// Include FiSH fields for editing UI
|
|
484
482
|
data.fishGlobalKey = this.fishGlobalKey || "";
|
|
485
|
-
|
|
486
|
-
data.fishKeysText = lines.join("\n");
|
|
483
|
+
data.fishKeys = { ...(this.fishKeys || {}) };
|
|
487
484
|
return data;
|
|
488
485
|
}
|
|
489
486
|
export() {
|
|
490
|
-
const network =
|
|
487
|
+
const network = _.pick(this, [
|
|
491
488
|
"uuid",
|
|
492
489
|
"awayMessage",
|
|
493
490
|
"nick",
|
|
@@ -517,24 +514,25 @@ class Network {
|
|
|
517
514
|
]);
|
|
518
515
|
network.channels = this.channels
|
|
519
516
|
.filter(function (channel) {
|
|
520
|
-
return channel.type ===
|
|
517
|
+
return channel.type === ChanType.CHANNEL || channel.type === ChanType.QUERY;
|
|
521
518
|
})
|
|
522
519
|
.map(function (chan) {
|
|
523
520
|
const keys = ["name", "muted"];
|
|
524
|
-
if (chan.type ===
|
|
521
|
+
if (chan.type === ChanType.CHANNEL) {
|
|
525
522
|
keys.push("key");
|
|
526
523
|
}
|
|
527
|
-
else if (chan.type ===
|
|
524
|
+
else if (chan.type === ChanType.QUERY) {
|
|
528
525
|
keys.push("type");
|
|
526
|
+
keys.push("pinned");
|
|
529
527
|
}
|
|
530
|
-
return
|
|
528
|
+
return _.pick(chan, keys);
|
|
531
529
|
// Override the type because we're omitting ID
|
|
532
530
|
});
|
|
533
531
|
return network;
|
|
534
532
|
}
|
|
535
533
|
getChannel(name) {
|
|
536
534
|
name = name.toLowerCase();
|
|
537
|
-
return
|
|
535
|
+
return _.find(this.channels, function (that, i) {
|
|
538
536
|
// Skip network lobby (it's always unshifted into first position)
|
|
539
537
|
return i > 0 && that.name.toLowerCase() === name;
|
|
540
538
|
});
|
|
@@ -543,4 +541,4 @@ class Network {
|
|
|
543
541
|
return this.channels[0];
|
|
544
542
|
}
|
|
545
543
|
}
|
|
546
|
-
|
|
544
|
+
export default Network;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
1
|
class Prefix {
|
|
4
2
|
prefix;
|
|
5
3
|
modeToSymbol;
|
|
@@ -14,10 +12,9 @@ class Prefix {
|
|
|
14
12
|
// clean out the old cruft
|
|
15
13
|
this.modeToSymbol = {};
|
|
16
14
|
this.symbols = [];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
that.symbols.push(p.symbol);
|
|
15
|
+
this.prefix.forEach((p) => {
|
|
16
|
+
this.modeToSymbol[p.mode] = p.symbol;
|
|
17
|
+
this.symbols.push(p.symbol);
|
|
21
18
|
});
|
|
22
19
|
}
|
|
23
20
|
update(prefix) {
|
|
@@ -28,4 +25,4 @@ class Prefix {
|
|
|
28
25
|
return this.prefix.forEach(f);
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
|
-
|
|
28
|
+
export default Prefix;
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const lodash_1 = __importDefault(require("lodash"));
|
|
7
|
-
const prefix_1 = __importDefault(require("./prefix"));
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
import Prefix from "./prefix.js";
|
|
8
3
|
class User {
|
|
9
4
|
modes;
|
|
10
5
|
// Users in the channel have only one mode assigned
|
|
@@ -13,7 +8,7 @@ class User {
|
|
|
13
8
|
nick;
|
|
14
9
|
lastMessage;
|
|
15
10
|
constructor(attr, prefix) {
|
|
16
|
-
|
|
11
|
+
_.defaults(this, attr, {
|
|
17
12
|
modes: [],
|
|
18
13
|
away: "",
|
|
19
14
|
nick: "",
|
|
@@ -25,7 +20,7 @@ class User {
|
|
|
25
20
|
return this.modes[0] || "";
|
|
26
21
|
},
|
|
27
22
|
});
|
|
28
|
-
this.setModes(this.modes, prefix || new
|
|
23
|
+
this.setModes(this.modes, prefix || new Prefix([]));
|
|
29
24
|
}
|
|
30
25
|
setModes(modes, prefix) {
|
|
31
26
|
// irc-framework sets character mode, but The Lounge works with symbols
|
|
@@ -39,4 +34,4 @@ class User {
|
|
|
39
34
|
};
|
|
40
35
|
}
|
|
41
36
|
}
|
|
42
|
-
|
|
37
|
+
export default User;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
export function getDirname(importMetaUrl) {
|
|
4
|
+
return dirname(fileURLToPath(importMetaUrl));
|
|
5
|
+
}
|
|
6
|
+
export function getFilename(importMetaUrl) {
|
|
7
|
+
return fileURLToPath(importMetaUrl);
|
|
8
|
+
}
|