nodebb-plugin-discord-onekite 1.0.2 → 1.0.3

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
@@ -1,7 +1,8 @@
1
- # nodebb-plugin-discord-onekite (NodeBB v4.x) — v1.0.1
1
+ # nodebb-plugin-discord-onekite (NodeBB v4.x) — v1.0.2
2
2
 
3
- Fix: template build errors by removing inline <script> from the .tpl and using acpScripts properly.
3
+ Fix ACP issues:
4
+ - Uses `modules` mapping so `require('admin/plugins/discord-onekite')` always resolves.
5
+ - Multi-select uses `name="cids[]"` so selections persist.
6
+ - Also hooks `action:ajaxify.end` as a fallback in admin to re-init after navigation.
4
7
 
5
- - Categories list loads in ACP
6
- - Settings save works
7
- - No categories selected => notify all
8
+ Requirement: no categories selected => notify all.
package/library.js CHANGED
@@ -15,14 +15,13 @@ const SETTINGS_KEY = 'discord-onekite';
15
15
  function normalizeCids(value) {
16
16
  if (!value) return [];
17
17
  if (Array.isArray(value)) return value.map(v => String(v)).filter(Boolean);
18
- if (typeof value === 'string') {
19
- return value.split(',').map(s => s.trim()).filter(Boolean);
20
- }
18
+ if (typeof value === 'string') return value.split(',').map(s => s.trim()).filter(Boolean);
21
19
  return [];
22
20
  }
23
21
 
24
22
  async function getSettings() {
25
23
  const s = await meta.settings.get(SETTINGS_KEY);
24
+ // Note: when select name is cids[], nodebb may save it as array or comma string; normalize handles both.
26
25
  return {
27
26
  webhookUrl: (s && s.webhookUrl) ? String(s.webhookUrl).trim() : '',
28
27
  notifyReplies: !!(s && (s.notifyReplies === true || s.notifyReplies === 'on' || s.notifyReplies === 'true')),
@@ -31,8 +30,7 @@ async function getSettings() {
31
30
  }
32
31
 
33
32
  function cidAllowed(topicCid, allowedCids) {
34
- // none selected => ALL
35
- if (!allowedCids || allowedCids.length === 0) return true;
33
+ if (!allowedCids || allowedCids.length === 0) return true; // none selected => ALL
36
34
  return allowedCids.includes(String(topicCid));
37
35
  }
38
36
 
@@ -69,9 +67,7 @@ async function buildTopicEmbed({ tid, pid, type }) {
69
67
  footer: { text: 'NodeBB → Discord (Onekite)' },
70
68
  };
71
69
 
72
- if (isReply) {
73
- embed.description = 'Nouvelle réponse dans un sujet.';
74
- }
70
+ if (isReply) embed.description = 'Nouvelle réponse dans un sujet.';
75
71
 
76
72
  return { topicData, embed };
77
73
  }
@@ -118,7 +114,6 @@ Plugin.onTopicSave = async (data) => {
118
114
 
119
115
  await postToDiscord(settings.webhookUrl, { embeds: [built.embed] });
120
116
  } catch (err) {
121
- // eslint-disable-next-line no-console
122
117
  console.error(err);
123
118
  }
124
119
  };
@@ -144,7 +139,6 @@ Plugin.onPostSave = async (data) => {
144
139
 
145
140
  await postToDiscord(settings.webhookUrl, { embeds: [built.embed] });
146
141
  } catch (err) {
147
- // eslint-disable-next-line no-console
148
142
  console.error(err);
149
143
  }
150
144
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-discord-onekite",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Discord webhook notifier for Onekite (NodeBB v4.x only)",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/plugin.json CHANGED
@@ -10,5 +10,7 @@
10
10
  { "hook": "action:post.save", "method": "onPostSave" }
11
11
  ],
12
12
  "templates": "static/templates",
13
- "acpScripts": ["static/lib/admin.js"]
13
+ "modules": {
14
+ "../admin/plugins/discord-onekite.js": "./static/lib/admin.js"
15
+ }
14
16
  }
@@ -1,61 +1,69 @@
1
1
  'use strict';
2
- /* global $, app */
2
+ /* global $, app, ajaxify */
3
3
 
4
4
  define('admin/plugins/discord-onekite', ['settings', 'api'], function (settings, api) {
5
5
  const ACP = {};
6
+ let initialized = false;
6
7
 
7
8
  function normalizeCids(v) {
8
9
  if (!v) return [];
9
10
  if (Array.isArray(v)) return v.map(String).filter(Boolean);
10
- if (typeof v === 'string') {
11
- return v.split(',').map(s => s.trim()).filter(Boolean);
12
- }
11
+ if (typeof v === 'string') return v.split(',').map(s => s.trim()).filter(Boolean);
13
12
  return [];
14
13
  }
15
14
 
16
- ACP.init = async function () {
17
- const $form = $('.discord-onekite-settings');
15
+ async function loadCategoriesIntoSelect(savedCids) {
18
16
  const $select = $('#cids');
17
+ if (!$select.length) return;
19
18
 
20
- // Load current saved settings (including cids) BEFORE fetching categories,
21
- // so we can apply selection after options are created.
22
- let saved = {};
23
- try {
24
- saved = await new Promise((resolve) => {
25
- settings.get('discord-onekite', (data) => resolve(data || {}));
19
+ const res = await api.get('/categories');
20
+
21
+ // Depending on endpoint, categories may be at res.categories or res.category
22
+ const categories = (res && (res.categories || res.category || res.data || [])) || [];
23
+ const list = Array.isArray(categories) ? categories : [];
24
+
25
+ $select.empty();
26
+ list
27
+ .filter(c => c && typeof c.cid !== 'undefined' && c.name)
28
+ .forEach(c => {
29
+ const cid = String(c.cid);
30
+ const $opt = $('<option />').val(cid).text(c.name);
31
+ if (savedCids.includes(cid)) $opt.prop('selected', true);
32
+ $opt.appendTo($select);
26
33
  });
27
- } catch (e) {
28
- saved = {};
34
+ }
35
+
36
+ ACP.init = async function () {
37
+ // NodeBB will call init() on page load for template admin/plugins/discord-onekite.
38
+ // But ACP is ajaxified; ensure we don't double-bind.
39
+ if (initialized) {
40
+ return;
29
41
  }
42
+ initialized = true;
30
43
 
31
- // Populate simple fields (webhookUrl, notifyReplies, etc.)
32
- settings.load('discord-onekite', $form);
44
+ const $form = $('.discord-onekite-settings');
45
+ if (!$form.length) return;
46
+
47
+ // 1) Load raw settings first (to get cids)
48
+ const saved = await new Promise((resolve) => {
49
+ settings.get('discord-onekite', (data) => resolve(data || {}));
50
+ });
33
51
 
34
52
  const savedCids = normalizeCids(saved.cids);
35
53
 
36
- // Fetch categories list and populate select
37
- try {
38
- const res = await api.get('/categories');
39
- const categories = (res && res.categories) ? res.categories : [];
54
+ // 2) Populate fields
55
+ settings.load('discord-onekite', $form);
40
56
 
41
- $select.empty();
42
- categories
43
- .filter(c => c && typeof c.cid !== 'undefined' && c.name)
44
- .forEach(c => {
45
- const cid = String(c.cid);
46
- const $opt = $('<option />').val(cid).text(c.name);
47
- if (savedCids.includes(cid)) {
48
- $opt.prop('selected', true);
49
- }
50
- $opt.appendTo($select);
51
- });
57
+ // 3) Populate categories + apply selection
58
+ try {
59
+ await loadCategoriesIntoSelect(savedCids);
52
60
  } catch (e) {
53
61
  // eslint-disable-next-line no-console
54
- console.error('[discord-onekite] Could not load categories', e);
62
+ console.error('[discord-onekite] categories load failed', e);
55
63
  app.alertError('Impossible de charger la liste des catégories.');
56
64
  }
57
65
 
58
- // Save button
66
+ // 4) Save
59
67
  $('#save').off('click.discordOnekite').on('click.discordOnekite', function () {
60
68
  settings.save('discord-onekite', $form, function () {
61
69
  app.alertSuccess('Paramètres enregistrés !');
@@ -63,5 +71,13 @@ define('admin/plugins/discord-onekite', ['settings', 'api'], function (settings,
63
71
  });
64
72
  };
65
73
 
74
+ // In case NodeBB doesn't call init (theme/custom admin), also listen for ajaxify end
75
+ $(window).off('action:ajaxify.end.discordOnekite').on('action:ajaxify.end.discordOnekite', function () {
76
+ if (ajaxify && ajaxify.data && ajaxify.data.template === 'admin/plugins/discord-onekite') {
77
+ initialized = false;
78
+ ACP.init();
79
+ }
80
+ });
81
+
66
82
  return ACP;
67
83
  });
@@ -8,9 +8,6 @@
8
8
  <div class="mb-3">
9
9
  <label class="form-label" for="webhookUrl">Discord Webhook URL</label>
10
10
  <input type="text" class="form-control" id="webhookUrl" name="webhookUrl" placeholder="https://discord.com/api/webhooks/..." />
11
- <p class="form-text text-muted">
12
- Discord → Salon #notifications → Intégrations → Webhooks → Copier l’URL.
13
- </p>
14
11
  </div>
15
12
 
16
13
  <div class="form-check mb-3">
@@ -22,7 +19,7 @@
22
19
 
23
20
  <div class="mb-3">
24
21
  <label class="form-label" for="cids">Catégories à notifier</label>
25
- <select class="form-select" id="cids" name="cids" multiple size="12"></select>
22
+ <select class="form-select" id="cids" name="cids[]" multiple size="12"></select>
26
23
  <p class="form-text text-muted">
27
24
  Si aucune catégorie n’est sélectionnée : <strong>toutes les catégories</strong> seront notifiées.
28
25
  </p>