thelounge-plugin-ntfy 1.3.0 → 1.5.0
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 +11 -7
- package/index.js +278 -42
- package/package.json +1 -1
- package/src/config.js +124 -9
- package/src/handler.js +14 -7
package/README.md
CHANGED
|
@@ -19,13 +19,15 @@ Restart The Lounge after installation
|
|
|
19
19
|
|
|
20
20
|
This plugin introduces the `/ntfy` command, subcommands are:
|
|
21
21
|
|
|
22
|
-
- `/ntfy start`: Start the ntfy listener for the network
|
|
23
|
-
- `/ntfy stop`: Stop the ntfy listener for the network
|
|
24
|
-
- `/ntfy status`: Show the ntfy listener status for this network
|
|
22
|
+
- `/ntfy start [all]`: Start the ntfy listener for the network or all networks if 'all' is specified
|
|
23
|
+
- `/ntfy stop [all]`: Stop the ntfy listener for the network or all networks if 'all' is specified
|
|
24
|
+
- `/ntfy status [all]`: Show the ntfy listener status for this network or all networks if 'all' is specified
|
|
25
25
|
- `/ntfy test`: Send a test notification
|
|
26
26
|
- `/ntfy config`: Config commands
|
|
27
|
-
- `/ntfy config set <setting_key> <setting_value>`: Set a configuration setting
|
|
28
|
-
- `/ntfy config remove <setting_key>`: Set a configuration setting to null
|
|
27
|
+
- `/ntfy config set <setting_key> <setting_value>`: Set a global configuration setting
|
|
28
|
+
- `/ntfy config remove <setting_key>`: Set a global configuration setting to null
|
|
29
|
+
- `/ntfy config network set <setting_key> <setting_value>`: Set a per-network setting for this network
|
|
30
|
+
- `/ntfy config network remove <setting_key>`: Remove per-network setting for this network
|
|
29
31
|
- `/ntfy config print`: Print the current configuration with warnings if any
|
|
30
32
|
|
|
31
33
|
## Setup
|
|
@@ -46,12 +48,14 @@ To start/stop sending push notifications in the desired network, enter:
|
|
|
46
48
|
|
|
47
49
|
## Private Messages
|
|
48
50
|
|
|
49
|
-
By default, you will only be notified when you are mentioned, **this includes messages sent privately to you**. If you want to be notified of all private messages, enter this command and start the notifier like usual:
|
|
51
|
+
By default, you will only be notified when you are mentioned, **this includes messages sent privately to you**. If you want to be notified of all private messages on a specific network, enter this command while connected to that network and start the notifier like usual:
|
|
50
52
|
|
|
51
53
|
```
|
|
52
|
-
/ntfy config set config.notify_on_private_messages true
|
|
54
|
+
/ntfy config network set config.notify_on_private_messages true
|
|
53
55
|
```
|
|
54
56
|
|
|
57
|
+
This setting is per-network, so you can enable it for some networks and disable it for others.
|
|
58
|
+
|
|
55
59
|
## License
|
|
56
60
|
|
|
57
61
|
This plugin is licensed under [MIT](https://opensource.org/license/mit)
|
package/index.js
CHANGED
|
@@ -6,6 +6,8 @@ const {
|
|
|
6
6
|
setRootDir,
|
|
7
7
|
loadUserConfig,
|
|
8
8
|
saveUserSetting,
|
|
9
|
+
saveNetworkSetting,
|
|
10
|
+
PER_NETWORK_KEYS,
|
|
9
11
|
} = require("./src/config.js");
|
|
10
12
|
|
|
11
13
|
// user -> Map<network.uuid -> handler and client>
|
|
@@ -19,17 +21,27 @@ const ntfyCommand = {
|
|
|
19
21
|
|
|
20
22
|
const helpMessage = () => {
|
|
21
23
|
say(`${command} command help:`);
|
|
22
|
-
say(`/${command} start - Start the ntfy listener for this network`);
|
|
23
|
-
say(`/${command} stop - Stop the ntfy listener for this network`);
|
|
24
24
|
say(
|
|
25
|
-
`/${command}
|
|
25
|
+
`/${command} start [all] - Start the ntfy listener for this network or all networks if 'all' is specified`,
|
|
26
|
+
);
|
|
27
|
+
say(
|
|
28
|
+
`/${command} stop [all] - Stop the ntfy listener for this network or all networks if 'all' is specified`,
|
|
29
|
+
);
|
|
30
|
+
say(
|
|
31
|
+
`/${command} status [all] - Show the ntfy listener status for this network or all networks if 'all' is specified`,
|
|
26
32
|
);
|
|
27
33
|
say(`/${command} test - Send a test notification`);
|
|
28
34
|
say(
|
|
29
|
-
`/${command} config set <setting_key> <setting_value> - Set a configuration setting`,
|
|
35
|
+
`/${command} config set <setting_key> <setting_value> - Set a global configuration setting`,
|
|
30
36
|
);
|
|
31
37
|
say(
|
|
32
|
-
`/${command} config remove <setting_key> - Set configuration setting to null`,
|
|
38
|
+
`/${command} config remove <setting_key> - Set global configuration setting to null`,
|
|
39
|
+
);
|
|
40
|
+
say(
|
|
41
|
+
`/${command} config network set <setting_key> <setting_value> - Set a per-network setting for this network`,
|
|
42
|
+
);
|
|
43
|
+
say(
|
|
44
|
+
`/${command} config network remove <setting_key> - Remove per-network setting for this network`,
|
|
33
45
|
);
|
|
34
46
|
say(
|
|
35
47
|
`/${command} config print - Print the current configuration with warnings if any`,
|
|
@@ -51,82 +63,221 @@ const ntfyCommand = {
|
|
|
51
63
|
|
|
52
64
|
switch (subcommand[0].toLowerCase()) {
|
|
53
65
|
case "start": {
|
|
66
|
+
let all = false;
|
|
54
67
|
const [_, errors] = loadUserConfig(client.client.name);
|
|
68
|
+
const subsubcommand = subcommand.slice(1);
|
|
69
|
+
|
|
70
|
+
if (
|
|
71
|
+
typeof subsubcommand[0] === "string" &&
|
|
72
|
+
subsubcommand.length > 0 &&
|
|
73
|
+
subsubcommand[0].toLowerCase() === "all"
|
|
74
|
+
) {
|
|
75
|
+
all = true;
|
|
76
|
+
}
|
|
55
77
|
|
|
56
78
|
if (errors.length > 0) {
|
|
57
|
-
say(
|
|
79
|
+
say(
|
|
80
|
+
`Cannot start ntfy listener${all ? "s" : ""} due to invalid configuration:`,
|
|
81
|
+
);
|
|
82
|
+
|
|
58
83
|
for (const error of errors) {
|
|
59
84
|
say(`- ${error.instancePath} ${error.message}`);
|
|
60
85
|
}
|
|
86
|
+
|
|
61
87
|
return;
|
|
62
88
|
}
|
|
63
89
|
|
|
64
90
|
const userListeners = globalActiveListeners.get(client.client.name);
|
|
65
91
|
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
) {
|
|
71
|
-
say("ntfy listener is already running for this network");
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
92
|
+
if (all) {
|
|
93
|
+
const networks = client.client.networks;
|
|
94
|
+
let started = 0;
|
|
95
|
+
let skipped = 0;
|
|
74
96
|
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
for (const net of networks) {
|
|
98
|
+
if (
|
|
99
|
+
userListeners &&
|
|
100
|
+
typeof userListeners.has === "function" &&
|
|
101
|
+
userListeners.has(net.uuid)
|
|
102
|
+
) {
|
|
103
|
+
skipped++;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
77
106
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
107
|
+
const handler = createHandler(client, net);
|
|
108
|
+
net.irc.on("privmsg", handler);
|
|
109
|
+
|
|
110
|
+
if (!userListeners) {
|
|
111
|
+
const map = new Map();
|
|
112
|
+
map.set(net.uuid, { handler: handler, client: client });
|
|
113
|
+
globalActiveListeners.set(client.client.name, map);
|
|
114
|
+
} else {
|
|
115
|
+
userListeners.set(net.uuid, {
|
|
116
|
+
handler: handler,
|
|
117
|
+
client: client,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
started++;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (started === 0 && skipped === 0) {
|
|
125
|
+
say("No networks available to start ntfy listeners");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (started > 0) {
|
|
129
|
+
say(
|
|
130
|
+
`Started ntfy listener${started !== 1 ? "s" : ""} for ${started} network${started !== 1 ? "s" : ""}`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (skipped > 0) {
|
|
134
|
+
say(
|
|
135
|
+
`Skipped ${skipped} network${skipped !== 1 ? "s" : ""} because ntfy listener is already running`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
82
138
|
} else {
|
|
83
|
-
|
|
84
|
-
|
|
139
|
+
if (
|
|
140
|
+
userListeners &&
|
|
141
|
+
typeof userListeners.has === "function" &&
|
|
142
|
+
userListeners.has(network.uuid)
|
|
143
|
+
) {
|
|
144
|
+
say("ntfy listener is already running for this network");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const handler = createHandler(client, network);
|
|
149
|
+
network.irc.on("privmsg", handler);
|
|
150
|
+
|
|
151
|
+
if (!userListeners) {
|
|
152
|
+
const map = new Map();
|
|
153
|
+
map.set(network.uuid, { handler: handler, client: client });
|
|
154
|
+
globalActiveListeners.set(client.client.name, map);
|
|
155
|
+
} else {
|
|
156
|
+
userListeners.set(network.uuid, {
|
|
157
|
+
handler: handler,
|
|
158
|
+
client: client,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
85
161
|
|
|
86
|
-
|
|
162
|
+
say("ntfy listener started for this network");
|
|
163
|
+
}
|
|
87
164
|
|
|
88
165
|
break;
|
|
89
166
|
}
|
|
90
167
|
|
|
91
168
|
case "stop": {
|
|
92
|
-
|
|
169
|
+
let all = false;
|
|
170
|
+
const subsubcommand = subcommand.slice(1);
|
|
93
171
|
|
|
94
172
|
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
173
|
+
typeof subsubcommand[0] === "string" &&
|
|
174
|
+
subsubcommand.length > 0 &&
|
|
175
|
+
subsubcommand[0].toLowerCase() === "all"
|
|
98
176
|
) {
|
|
99
|
-
|
|
100
|
-
return;
|
|
177
|
+
all = true;
|
|
101
178
|
}
|
|
102
179
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
180
|
+
const userListeners = globalActiveListeners.get(client.client.name);
|
|
181
|
+
|
|
182
|
+
if (all) {
|
|
183
|
+
const networks = client.client.networks;
|
|
184
|
+
let stopped = 0;
|
|
185
|
+
let skipped = 0;
|
|
186
|
+
|
|
187
|
+
for (const net of networks) {
|
|
188
|
+
if (
|
|
189
|
+
!userListeners ||
|
|
190
|
+
typeof userListeners.has !== "function" ||
|
|
191
|
+
!userListeners.has(net.uuid)
|
|
192
|
+
) {
|
|
193
|
+
skipped++;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
106
196
|
|
|
107
|
-
|
|
197
|
+
const { handler } = userListeners.get(net.uuid);
|
|
198
|
+
net.irc.removeListener("privmsg", handler);
|
|
199
|
+
userListeners.delete(net.uuid);
|
|
200
|
+
stopped++;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (stopped === 0 && skipped === 0) {
|
|
204
|
+
say("No networks available to stop ntfy listeners");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (stopped > 0) {
|
|
208
|
+
say(
|
|
209
|
+
`Stopped ntfy listener${stopped !== 1 ? "s" : ""} for ${stopped} network${stopped !== 1 ? "s" : ""}`,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if (skipped > 0) {
|
|
213
|
+
say(
|
|
214
|
+
`Skipped ${skipped} network${skipped !== 1 ? "s" : ""} because ntfy listener was not running`,
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
if (
|
|
219
|
+
!userListeners ||
|
|
220
|
+
typeof userListeners.has !== "function" ||
|
|
221
|
+
!userListeners.has(network.uuid)
|
|
222
|
+
) {
|
|
223
|
+
say("ntfy listener is not running for this network");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const { handler } = userListeners.get(network.uuid);
|
|
228
|
+
network.irc.removeListener("privmsg", handler);
|
|
229
|
+
userListeners.delete(network.uuid);
|
|
230
|
+
|
|
231
|
+
say("ntfy listener stopped for this network");
|
|
232
|
+
}
|
|
108
233
|
|
|
109
234
|
break;
|
|
110
235
|
}
|
|
111
236
|
|
|
112
237
|
case "status": {
|
|
113
|
-
|
|
238
|
+
let all = false;
|
|
239
|
+
const subsubcommand = subcommand.slice(1);
|
|
114
240
|
|
|
115
241
|
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
242
|
+
typeof subsubcommand[0] === "string" &&
|
|
243
|
+
subsubcommand.length > 0 &&
|
|
244
|
+
subsubcommand[0].toLowerCase() === "all"
|
|
119
245
|
) {
|
|
120
|
-
|
|
246
|
+
all = true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const userListeners = globalActiveListeners.get(client.client.name);
|
|
250
|
+
|
|
251
|
+
if (all) {
|
|
252
|
+
const networks = client.client.networks;
|
|
253
|
+
for (const net of networks) {
|
|
254
|
+
if (
|
|
255
|
+
userListeners &&
|
|
256
|
+
typeof userListeners.has === "function" &&
|
|
257
|
+
userListeners.has(net.uuid)
|
|
258
|
+
) {
|
|
259
|
+
say(`${net.name}: running`);
|
|
260
|
+
} else {
|
|
261
|
+
say(`${net.name}: not running`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
121
264
|
} else {
|
|
122
|
-
|
|
265
|
+
if (
|
|
266
|
+
userListeners &&
|
|
267
|
+
typeof userListeners.has === "function" &&
|
|
268
|
+
userListeners.has(network.uuid)
|
|
269
|
+
) {
|
|
270
|
+
say("ntfy listener is running for this network");
|
|
271
|
+
} else {
|
|
272
|
+
say("ntfy listener is not running for this network");
|
|
273
|
+
}
|
|
123
274
|
}
|
|
124
275
|
|
|
125
276
|
break;
|
|
126
277
|
}
|
|
127
278
|
|
|
128
279
|
case "test": {
|
|
129
|
-
const { NtfyClient
|
|
280
|
+
const { NtfyClient } = await import("ntfy");
|
|
130
281
|
|
|
131
282
|
const [userConfig, errors] = loadUserConfig(client.client.name);
|
|
132
283
|
|
|
@@ -152,7 +303,7 @@ const ntfyCommand = {
|
|
|
152
303
|
const ntfyClient = new NtfyClient({
|
|
153
304
|
server: userConfig.ntfy.server,
|
|
154
305
|
topic: userConfig.ntfy.topic,
|
|
155
|
-
priority:
|
|
306
|
+
priority: userConfig.ntfy.priority,
|
|
156
307
|
tags: ["speech_balloon"],
|
|
157
308
|
authorization: ntfyAuth,
|
|
158
309
|
});
|
|
@@ -229,13 +380,26 @@ const ntfyCommand = {
|
|
|
229
380
|
const [userConfig, errors] = loadUserConfig(client.client.name);
|
|
230
381
|
|
|
231
382
|
const sensitiveKeys = new Set(["ntfy.password", "ntfy.token"]);
|
|
383
|
+
const perNetworkKeys = new Set([
|
|
384
|
+
"config.notify_on_private_messages",
|
|
385
|
+
]);
|
|
232
386
|
|
|
233
387
|
const printConfig = (obj, parentKey = "") => {
|
|
234
388
|
for (const key in obj) {
|
|
235
389
|
const value = obj[key];
|
|
236
390
|
const fullKey = parentKey ? `${parentKey}.${key}` : key;
|
|
237
391
|
|
|
238
|
-
if (
|
|
392
|
+
if (perNetworkKeys.has(fullKey)) {
|
|
393
|
+
// Special handling for per-network settings
|
|
394
|
+
if (typeof value === "object" && value !== null) {
|
|
395
|
+
const networkValue = value[network.uuid];
|
|
396
|
+
say(
|
|
397
|
+
`${fullKey}=${networkValue !== undefined ? networkValue : "(not set for this network)"}`,
|
|
398
|
+
);
|
|
399
|
+
} else {
|
|
400
|
+
say(`${fullKey}=(not set for this network)`);
|
|
401
|
+
}
|
|
402
|
+
} else if (typeof value === "object" && value !== null) {
|
|
239
403
|
printConfig(value, fullKey);
|
|
240
404
|
} else if (sensitiveKeys.has(fullKey) && value) {
|
|
241
405
|
say(`${fullKey}=********`);
|
|
@@ -268,6 +432,78 @@ const ntfyCommand = {
|
|
|
268
432
|
break;
|
|
269
433
|
}
|
|
270
434
|
|
|
435
|
+
case "network": {
|
|
436
|
+
const networkArgs = subsubcommand.slice(1);
|
|
437
|
+
|
|
438
|
+
if (networkArgs.length === 0) {
|
|
439
|
+
helpMessage();
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (typeof networkArgs[0] !== "string") {
|
|
444
|
+
helpMessage();
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
switch (networkArgs[0].toLowerCase()) {
|
|
449
|
+
case "set": {
|
|
450
|
+
const setArgs = networkArgs.slice(1);
|
|
451
|
+
|
|
452
|
+
if (setArgs.length < 2) {
|
|
453
|
+
say("Usage: /ntfy config network set <setting_key> <value>");
|
|
454
|
+
say(
|
|
455
|
+
`Available per-network settings: ${Array.from(PER_NETWORK_KEYS).join(", ")}`,
|
|
456
|
+
);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const settingKey = setArgs[0];
|
|
461
|
+
const settingValue = setArgs.slice(1).join(" ");
|
|
462
|
+
const response = saveNetworkSetting(
|
|
463
|
+
client.client.name,
|
|
464
|
+
settingKey,
|
|
465
|
+
network.uuid,
|
|
466
|
+
settingValue,
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
say(response);
|
|
470
|
+
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
case "remove": {
|
|
475
|
+
const removeArgs = networkArgs.slice(1);
|
|
476
|
+
|
|
477
|
+
if (removeArgs.length < 1) {
|
|
478
|
+
say("Usage: /ntfy config network remove <setting_key>");
|
|
479
|
+
say(
|
|
480
|
+
`Available per-network settings: ${Array.from(PER_NETWORK_KEYS).join(", ")}`,
|
|
481
|
+
);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const settingKey = removeArgs[0];
|
|
486
|
+
const response = saveNetworkSetting(
|
|
487
|
+
client.client.name,
|
|
488
|
+
settingKey,
|
|
489
|
+
network.uuid,
|
|
490
|
+
null,
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
say(response);
|
|
494
|
+
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
default: {
|
|
499
|
+
helpMessage();
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
|
|
271
507
|
default: {
|
|
272
508
|
helpMessage();
|
|
273
509
|
break;
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -19,22 +19,26 @@ const DEFAULT_CONFIG = {
|
|
|
19
19
|
username: null,
|
|
20
20
|
password: null,
|
|
21
21
|
token: null,
|
|
22
|
+
priority: 3,
|
|
22
23
|
},
|
|
23
24
|
config: {
|
|
24
|
-
notify_on_private_messages: false
|
|
25
|
+
notify_on_private_messages: {}, // Per-network: { "network-uuid": true/false }
|
|
25
26
|
},
|
|
26
27
|
};
|
|
27
28
|
|
|
28
|
-
const
|
|
29
|
+
const GLOBAL_KEYS = new Set([
|
|
29
30
|
"ntfy.server",
|
|
30
31
|
"ntfy.topic",
|
|
31
32
|
"ntfy.username",
|
|
32
33
|
"ntfy.password",
|
|
33
34
|
"ntfy.token",
|
|
34
|
-
"
|
|
35
|
+
"ntfy.priority",
|
|
35
36
|
]);
|
|
37
|
+
const GLOBAL_BOOLEAN_KEYS = new Set([]);
|
|
38
|
+
const GLOBAL_NUMERIC_KEYS = new Set(["ntfy.priority"]);
|
|
36
39
|
|
|
37
|
-
const
|
|
40
|
+
const PER_NETWORK_KEYS = new Set(["config.notify_on_private_messages"]);
|
|
41
|
+
const PER_NETWORK_BOOLEAN_KEYS = new Set(["config.notify_on_private_messages"]);
|
|
38
42
|
|
|
39
43
|
const SENSITIVE_KEYS = new Set(["ntfy.password", "ntfy.token"]);
|
|
40
44
|
|
|
@@ -66,6 +70,13 @@ const userConfigSchema = {
|
|
|
66
70
|
nullable: true,
|
|
67
71
|
errorMessage: "Invalid ntfy token, must start with 'tk_'",
|
|
68
72
|
},
|
|
73
|
+
priority: {
|
|
74
|
+
type: "integer",
|
|
75
|
+
minimum: 1,
|
|
76
|
+
maximum: 5,
|
|
77
|
+
default: 3,
|
|
78
|
+
errorMessage: "Priority must be an integer between 1 and 5",
|
|
79
|
+
},
|
|
69
80
|
},
|
|
70
81
|
allOf: [
|
|
71
82
|
{
|
|
@@ -110,8 +121,9 @@ const userConfigSchema = {
|
|
|
110
121
|
required: ["notify_on_private_messages"],
|
|
111
122
|
properties: {
|
|
112
123
|
notify_on_private_messages: {
|
|
113
|
-
type: "
|
|
114
|
-
|
|
124
|
+
type: "object",
|
|
125
|
+
additionalProperties: { type: ["boolean", "string"] },
|
|
126
|
+
default: {},
|
|
115
127
|
},
|
|
116
128
|
},
|
|
117
129
|
},
|
|
@@ -227,7 +239,7 @@ function saveUserSetting(username, settingKey, settingValue) {
|
|
|
227
239
|
throw new Error("Root directory is not set");
|
|
228
240
|
}
|
|
229
241
|
|
|
230
|
-
if (
|
|
242
|
+
if (GLOBAL_KEYS.has(settingKey)) {
|
|
231
243
|
let userConfig = loadUserConfig(username)[0];
|
|
232
244
|
|
|
233
245
|
const keys = settingKey.split(".");
|
|
@@ -245,7 +257,7 @@ function saveUserSetting(username, settingKey, settingValue) {
|
|
|
245
257
|
return `Error: expected value to be a string`;
|
|
246
258
|
}
|
|
247
259
|
|
|
248
|
-
if (
|
|
260
|
+
if (GLOBAL_BOOLEAN_KEYS.has(settingKey)) {
|
|
249
261
|
try {
|
|
250
262
|
settingValue = settingValue
|
|
251
263
|
? JSON.parse(settingValue.toLowerCase())
|
|
@@ -259,6 +271,18 @@ function saveUserSetting(username, settingKey, settingValue) {
|
|
|
259
271
|
}
|
|
260
272
|
}
|
|
261
273
|
|
|
274
|
+
if (GLOBAL_NUMERIC_KEYS.has(settingKey)) {
|
|
275
|
+
try {
|
|
276
|
+
settingValue = settingValue ? Number(settingValue) : NaN;
|
|
277
|
+
|
|
278
|
+
if (isNaN(settingValue) || typeof settingValue !== "number") {
|
|
279
|
+
return `Invalid value for ${settingKey}, expected a number`;
|
|
280
|
+
}
|
|
281
|
+
} catch {
|
|
282
|
+
return `Invalid value for ${settingKey}, expected a number`;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
262
286
|
curr[keys[keys.length - 1]] = settingValue;
|
|
263
287
|
|
|
264
288
|
const configToSave = encryptSensitiveFields(userConfig);
|
|
@@ -276,12 +300,103 @@ function saveUserSetting(username, settingKey, settingValue) {
|
|
|
276
300
|
}
|
|
277
301
|
|
|
278
302
|
return `Invalid setting ${settingKey}, allowed settings are: ${Array.from(
|
|
279
|
-
|
|
303
|
+
GLOBAL_KEYS,
|
|
280
304
|
).join(", ")}`;
|
|
281
305
|
}
|
|
282
306
|
|
|
307
|
+
function saveNetworkSetting(username, settingKey, networkUuid, settingValue) {
|
|
308
|
+
if (!rootDir) {
|
|
309
|
+
throw new Error("Root directory is not set");
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (!PER_NETWORK_KEYS.has(settingKey)) {
|
|
313
|
+
return `Invalid per-network setting ${settingKey}, allowed settings are: ${Array.from(
|
|
314
|
+
PER_NETWORK_KEYS,
|
|
315
|
+
).join(", ")}`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let userConfig = loadUserConfig(username)[0];
|
|
319
|
+
|
|
320
|
+
const keys = settingKey.split(".");
|
|
321
|
+
|
|
322
|
+
let curr = userConfig;
|
|
323
|
+
|
|
324
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
325
|
+
const key = keys[i];
|
|
326
|
+
if (key in curr) {
|
|
327
|
+
curr = curr[key];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const finalKey = keys[keys.length - 1];
|
|
332
|
+
|
|
333
|
+
if (!curr[finalKey] || typeof curr[finalKey] !== "object") {
|
|
334
|
+
curr[finalKey] = {};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (settingValue === null) {
|
|
338
|
+
delete curr[finalKey][networkUuid];
|
|
339
|
+
} else if (PER_NETWORK_BOOLEAN_KEYS.has(settingKey)) {
|
|
340
|
+
try {
|
|
341
|
+
const boolValue = JSON.parse(settingValue.toLowerCase());
|
|
342
|
+
|
|
343
|
+
if (typeof boolValue !== "boolean") {
|
|
344
|
+
return `Invalid value for ${settingKey}, expected a boolean`;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
curr[finalKey][networkUuid] = boolValue;
|
|
348
|
+
} catch {
|
|
349
|
+
return `Invalid value for ${settingKey}, expected a boolean (true/false)`;
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
curr[finalKey][networkUuid] = settingValue;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const configToSave = encryptSensitiveFields(userConfig);
|
|
356
|
+
|
|
357
|
+
const userConfigPath = path.join(rootDir, "config", `${username}.json`);
|
|
358
|
+
|
|
359
|
+
fs.mkdirSync(path.dirname(userConfigPath), { recursive: true });
|
|
360
|
+
fs.writeFileSync(
|
|
361
|
+
userConfigPath,
|
|
362
|
+
JSON.stringify(configToSave, null, 2),
|
|
363
|
+
"utf-8",
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
return "Success";
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function getNetworkSetting(
|
|
370
|
+
userConfig,
|
|
371
|
+
settingKey,
|
|
372
|
+
networkUuid,
|
|
373
|
+
defaultValue = false,
|
|
374
|
+
) {
|
|
375
|
+
const keys = settingKey.split(".");
|
|
376
|
+
|
|
377
|
+
let curr = userConfig;
|
|
378
|
+
|
|
379
|
+
for (const key of keys) {
|
|
380
|
+
if (curr && typeof curr === "object" && key in curr) {
|
|
381
|
+
curr = curr[key];
|
|
382
|
+
} else {
|
|
383
|
+
return defaultValue;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (curr && typeof curr === "object" && networkUuid in curr) {
|
|
388
|
+
return curr[networkUuid];
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return defaultValue;
|
|
392
|
+
}
|
|
393
|
+
|
|
283
394
|
module.exports = {
|
|
284
395
|
setRootDir,
|
|
285
396
|
loadUserConfig,
|
|
286
397
|
saveUserSetting,
|
|
398
|
+
saveNetworkSetting,
|
|
399
|
+
getNetworkSetting,
|
|
400
|
+
PER_NETWORK_KEYS,
|
|
401
|
+
PER_NETWORK_BOOLEAN_KEYS,
|
|
287
402
|
};
|
package/src/handler.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const { loadUserConfig } = require("./config.js");
|
|
3
|
+
const { loadUserConfig, getNetworkSetting } = require("./config.js");
|
|
4
4
|
const { PluginLogger } = require("./logger.js");
|
|
5
5
|
|
|
6
6
|
function createHandler(client, network) {
|
|
@@ -19,11 +19,11 @@ function createHandler(client, network) {
|
|
|
19
19
|
let notify = false;
|
|
20
20
|
let userConfig;
|
|
21
21
|
|
|
22
|
-
if (mentioned) {
|
|
23
|
-
// Mentions always notify
|
|
22
|
+
if (mentioned && !isPM) {
|
|
23
|
+
// Mentions always notify in channels
|
|
24
24
|
notify = true;
|
|
25
25
|
} else if (isPM) {
|
|
26
|
-
// PMs notify only if enabled in config
|
|
26
|
+
// PMs notify only if enabled in config for this network
|
|
27
27
|
const [uc, errors] = loadUserConfig(client.client.name);
|
|
28
28
|
|
|
29
29
|
if (errors.length > 0) {
|
|
@@ -32,7 +32,14 @@ function createHandler(client, network) {
|
|
|
32
32
|
|
|
33
33
|
userConfig = uc;
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
const notifyOnPMs = getNetworkSetting(
|
|
36
|
+
userConfig,
|
|
37
|
+
"config.notify_on_private_messages",
|
|
38
|
+
network.uuid,
|
|
39
|
+
false,
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (notifyOnPMs) {
|
|
36
43
|
notify = true;
|
|
37
44
|
}
|
|
38
45
|
}
|
|
@@ -64,12 +71,12 @@ function createHandler(client, network) {
|
|
|
64
71
|
};
|
|
65
72
|
}
|
|
66
73
|
|
|
67
|
-
const { NtfyClient
|
|
74
|
+
const { NtfyClient } = await import("ntfy");
|
|
68
75
|
|
|
69
76
|
const ntfyClient = new NtfyClient({
|
|
70
77
|
server: userConfig.ntfy.server,
|
|
71
78
|
topic: userConfig.ntfy.topic,
|
|
72
|
-
priority:
|
|
79
|
+
priority: userConfig.ntfy.priority,
|
|
73
80
|
tags: ["speech_balloon"],
|
|
74
81
|
authorization: ntfyAuth,
|
|
75
82
|
});
|