thelounge-plugin-ntfy 1.3.0 → 1.4.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 CHANGED
@@ -24,8 +24,10 @@ This plugin introduces the `/ntfy` command, subcommands are:
24
24
  - `/ntfy status`: Show the ntfy listener status for this network
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>
@@ -26,10 +28,16 @@ const ntfyCommand = {
26
28
  );
27
29
  say(`/${command} test - Send a test notification`);
28
30
  say(
29
- `/${command} config set <setting_key> <setting_value> - Set a configuration setting`,
31
+ `/${command} config set <setting_key> <setting_value> - Set a global configuration setting`,
30
32
  );
31
33
  say(
32
- `/${command} config remove <setting_key> - Set configuration setting to null`,
34
+ `/${command} config remove <setting_key> - Set global configuration setting to null`,
35
+ );
36
+ say(
37
+ `/${command} config network set <setting_key> <setting_value> - Set a per-network setting for this network`,
38
+ );
39
+ say(
40
+ `/${command} config network remove <setting_key> - Remove per-network setting for this network`,
33
41
  );
34
42
  say(
35
43
  `/${command} config print - Print the current configuration with warnings if any`,
@@ -229,13 +237,26 @@ const ntfyCommand = {
229
237
  const [userConfig, errors] = loadUserConfig(client.client.name);
230
238
 
231
239
  const sensitiveKeys = new Set(["ntfy.password", "ntfy.token"]);
240
+ const perNetworkKeys = new Set([
241
+ "config.notify_on_private_messages",
242
+ ]);
232
243
 
233
244
  const printConfig = (obj, parentKey = "") => {
234
245
  for (const key in obj) {
235
246
  const value = obj[key];
236
247
  const fullKey = parentKey ? `${parentKey}.${key}` : key;
237
248
 
238
- if (typeof value === "object" && value !== null) {
249
+ if (perNetworkKeys.has(fullKey)) {
250
+ // Special handling for per-network settings
251
+ if (typeof value === "object" && value !== null) {
252
+ const networkValue = value[network.uuid];
253
+ say(
254
+ `${fullKey}=${networkValue !== undefined ? networkValue : "(not set for this network)"}`,
255
+ );
256
+ } else {
257
+ say(`${fullKey}=(not set for this network)`);
258
+ }
259
+ } else if (typeof value === "object" && value !== null) {
239
260
  printConfig(value, fullKey);
240
261
  } else if (sensitiveKeys.has(fullKey) && value) {
241
262
  say(`${fullKey}=********`);
@@ -268,6 +289,78 @@ const ntfyCommand = {
268
289
  break;
269
290
  }
270
291
 
292
+ case "network": {
293
+ const networkArgs = subsubcommand.slice(1);
294
+
295
+ if (networkArgs.length === 0) {
296
+ helpMessage();
297
+ return;
298
+ }
299
+
300
+ if (typeof networkArgs[0] !== "string") {
301
+ helpMessage();
302
+ return;
303
+ }
304
+
305
+ switch (networkArgs[0].toLowerCase()) {
306
+ case "set": {
307
+ const setArgs = networkArgs.slice(1);
308
+
309
+ if (setArgs.length < 2) {
310
+ say("Usage: /ntfy config network set <setting_key> <value>");
311
+ say(
312
+ `Available per-network settings: ${Array.from(PER_NETWORK_KEYS).join(", ")}`,
313
+ );
314
+ return;
315
+ }
316
+
317
+ const settingKey = setArgs[0];
318
+ const settingValue = setArgs.slice(1).join(" ");
319
+ const response = saveNetworkSetting(
320
+ client.client.name,
321
+ settingKey,
322
+ network.uuid,
323
+ settingValue,
324
+ );
325
+
326
+ say(response);
327
+
328
+ break;
329
+ }
330
+
331
+ case "remove": {
332
+ const removeArgs = networkArgs.slice(1);
333
+
334
+ if (removeArgs.length < 1) {
335
+ say("Usage: /ntfy config network remove <setting_key>");
336
+ say(
337
+ `Available per-network settings: ${Array.from(PER_NETWORK_KEYS).join(", ")}`,
338
+ );
339
+ return;
340
+ }
341
+
342
+ const settingKey = removeArgs[0];
343
+ const response = saveNetworkSetting(
344
+ client.client.name,
345
+ settingKey,
346
+ network.uuid,
347
+ null,
348
+ );
349
+
350
+ say(response);
351
+
352
+ break;
353
+ }
354
+
355
+ default: {
356
+ helpMessage();
357
+ break;
358
+ }
359
+ }
360
+
361
+ break;
362
+ }
363
+
271
364
  default: {
272
365
  helpMessage();
273
366
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thelounge-plugin-ntfy",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "A plugin for The Lounge that sends push notifications via ntfy when highlighted",
5
5
  "keywords": [
6
6
  "thelounge",
package/src/config.js CHANGED
@@ -21,20 +21,21 @@ const DEFAULT_CONFIG = {
21
21
  token: null,
22
22
  },
23
23
  config: {
24
- notify_on_private_messages: false,
24
+ notify_on_private_messages: {}, // Per-network: { "network-uuid": true/false }
25
25
  },
26
26
  };
27
27
 
28
- const ALLOWED_KEYS = new Set([
28
+ const GLOBAL_KEYS = new Set([
29
29
  "ntfy.server",
30
30
  "ntfy.topic",
31
31
  "ntfy.username",
32
32
  "ntfy.password",
33
33
  "ntfy.token",
34
- "config.notify_on_private_messages",
35
34
  ]);
35
+ const GLOBAL_BOOLEAN_KEYS = new Set([]);
36
36
 
37
- const BOOLEAN_KEYS = new Set(["config.notify_on_private_messages"]);
37
+ const PER_NETWORK_KEYS = new Set(["config.notify_on_private_messages"]);
38
+ const PER_NETWORK_BOOLEAN_KEYS = new Set(["config.notify_on_private_messages"]);
38
39
 
39
40
  const SENSITIVE_KEYS = new Set(["ntfy.password", "ntfy.token"]);
40
41
 
@@ -110,8 +111,9 @@ const userConfigSchema = {
110
111
  required: ["notify_on_private_messages"],
111
112
  properties: {
112
113
  notify_on_private_messages: {
113
- type: "boolean",
114
- default: false,
114
+ type: "object",
115
+ additionalProperties: { type: ["boolean", "string"] },
116
+ default: {},
115
117
  },
116
118
  },
117
119
  },
@@ -227,7 +229,7 @@ function saveUserSetting(username, settingKey, settingValue) {
227
229
  throw new Error("Root directory is not set");
228
230
  }
229
231
 
230
- if (ALLOWED_KEYS.has(settingKey)) {
232
+ if (GLOBAL_KEYS.has(settingKey)) {
231
233
  let userConfig = loadUserConfig(username)[0];
232
234
 
233
235
  const keys = settingKey.split(".");
@@ -245,7 +247,7 @@ function saveUserSetting(username, settingKey, settingValue) {
245
247
  return `Error: expected value to be a string`;
246
248
  }
247
249
 
248
- if (BOOLEAN_KEYS.has(settingKey)) {
250
+ if (GLOBAL_BOOLEAN_KEYS.has(settingKey)) {
249
251
  try {
250
252
  settingValue = settingValue
251
253
  ? JSON.parse(settingValue.toLowerCase())
@@ -276,12 +278,103 @@ function saveUserSetting(username, settingKey, settingValue) {
276
278
  }
277
279
 
278
280
  return `Invalid setting ${settingKey}, allowed settings are: ${Array.from(
279
- ALLOWED_KEYS,
281
+ GLOBAL_KEYS,
280
282
  ).join(", ")}`;
281
283
  }
282
284
 
285
+ function saveNetworkSetting(username, settingKey, networkUuid, settingValue) {
286
+ if (!rootDir) {
287
+ throw new Error("Root directory is not set");
288
+ }
289
+
290
+ if (!PER_NETWORK_KEYS.has(settingKey)) {
291
+ return `Invalid per-network setting ${settingKey}, allowed settings are: ${Array.from(
292
+ PER_NETWORK_KEYS,
293
+ ).join(", ")}`;
294
+ }
295
+
296
+ let userConfig = loadUserConfig(username)[0];
297
+
298
+ const keys = settingKey.split(".");
299
+
300
+ let curr = userConfig;
301
+
302
+ for (let i = 0; i < keys.length - 1; i++) {
303
+ const key = keys[i];
304
+ if (key in curr) {
305
+ curr = curr[key];
306
+ }
307
+ }
308
+
309
+ const finalKey = keys[keys.length - 1];
310
+
311
+ if (!curr[finalKey] || typeof curr[finalKey] !== "object") {
312
+ curr[finalKey] = {};
313
+ }
314
+
315
+ if (settingValue === null) {
316
+ delete curr[finalKey][networkUuid];
317
+ } else if (PER_NETWORK_BOOLEAN_KEYS.has(settingKey)) {
318
+ try {
319
+ const boolValue = JSON.parse(settingValue.toLowerCase());
320
+
321
+ if (typeof boolValue !== "boolean") {
322
+ return `Invalid value for ${settingKey}, expected a boolean`;
323
+ }
324
+
325
+ curr[finalKey][networkUuid] = boolValue;
326
+ } catch {
327
+ return `Invalid value for ${settingKey}, expected a boolean (true/false)`;
328
+ }
329
+ } else {
330
+ curr[finalKey][networkUuid] = settingValue;
331
+ }
332
+
333
+ const configToSave = encryptSensitiveFields(userConfig);
334
+
335
+ const userConfigPath = path.join(rootDir, "config", `${username}.json`);
336
+
337
+ fs.mkdirSync(path.dirname(userConfigPath), { recursive: true });
338
+ fs.writeFileSync(
339
+ userConfigPath,
340
+ JSON.stringify(configToSave, null, 2),
341
+ "utf-8",
342
+ );
343
+
344
+ return "Success";
345
+ }
346
+
347
+ function getNetworkSetting(
348
+ userConfig,
349
+ settingKey,
350
+ networkUuid,
351
+ defaultValue = false,
352
+ ) {
353
+ const keys = settingKey.split(".");
354
+
355
+ let curr = userConfig;
356
+
357
+ for (const key of keys) {
358
+ if (curr && typeof curr === "object" && key in curr) {
359
+ curr = curr[key];
360
+ } else {
361
+ return defaultValue;
362
+ }
363
+ }
364
+
365
+ if (curr && typeof curr === "object" && networkUuid in curr) {
366
+ return curr[networkUuid];
367
+ }
368
+
369
+ return defaultValue;
370
+ }
371
+
283
372
  module.exports = {
284
373
  setRootDir,
285
374
  loadUserConfig,
286
375
  saveUserSetting,
376
+ saveNetworkSetting,
377
+ getNetworkSetting,
378
+ PER_NETWORK_KEYS,
379
+ PER_NETWORK_BOOLEAN_KEYS,
287
380
  };
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) {
@@ -23,7 +23,7 @@ function createHandler(client, network) {
23
23
  // Mentions always notify
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
- if (userConfig.config.notify_on_private_messages) {
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
  }