nodebb-plugin-discord-onekite 1.0.1 → 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,5 +1,8 @@
1
- # nodebb-plugin-discord-onekite (NodeBB v4.x) — v1.0.0 (ACP fix)
1
+ # nodebb-plugin-discord-onekite (NodeBB v4.x) — v1.0.2
2
2
 
3
- - Catégories listées dans l'ACP (chargées via /api/categories)
4
- - Sauvegarde via settings.save
5
- - Aucune catégorie sélectionnée => toutes
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.
7
+
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
- // requirement: 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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-discord-onekite",
3
- "version": "1.0.1",
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
@@ -9,5 +9,8 @@
9
9
  { "hook": "action:topic.save", "method": "onTopicSave" },
10
10
  { "hook": "action:post.save", "method": "onPostSave" }
11
11
  ],
12
- "templates": "static/templates"
12
+ "templates": "static/templates",
13
+ "modules": {
14
+ "../admin/plugins/discord-onekite.js": "./static/lib/admin.js"
15
+ }
13
16
  }
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+ /* global $, app, ajaxify */
3
+
4
+ define('admin/plugins/discord-onekite', ['settings', 'api'], function (settings, api) {
5
+ const ACP = {};
6
+ let initialized = false;
7
+
8
+ function normalizeCids(v) {
9
+ if (!v) return [];
10
+ if (Array.isArray(v)) return v.map(String).filter(Boolean);
11
+ if (typeof v === 'string') return v.split(',').map(s => s.trim()).filter(Boolean);
12
+ return [];
13
+ }
14
+
15
+ async function loadCategoriesIntoSelect(savedCids) {
16
+ const $select = $('#cids');
17
+ if (!$select.length) return;
18
+
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);
33
+ });
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;
41
+ }
42
+ initialized = true;
43
+
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
+ });
51
+
52
+ const savedCids = normalizeCids(saved.cids);
53
+
54
+ // 2) Populate fields
55
+ settings.load('discord-onekite', $form);
56
+
57
+ // 3) Populate categories + apply selection
58
+ try {
59
+ await loadCategoriesIntoSelect(savedCids);
60
+ } catch (e) {
61
+ // eslint-disable-next-line no-console
62
+ console.error('[discord-onekite] categories load failed', e);
63
+ app.alertError('Impossible de charger la liste des catégories.');
64
+ }
65
+
66
+ // 4) Save
67
+ $('#save').off('click.discordOnekite').on('click.discordOnekite', function () {
68
+ settings.save('discord-onekite', $form, function () {
69
+ app.alertSuccess('Paramètres enregistrés !');
70
+ });
71
+ });
72
+ };
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
+
82
+ return ACP;
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>
@@ -31,60 +28,3 @@
31
28
  <!-- IMPORT admin/partials/save_button.tpl -->
32
29
  </form>
33
30
  </div>
34
-
35
- <script>
36
- require(['settings', 'api'], function (settings, api) {
37
- var $form = $('.discord-onekite-settings');
38
- var $select = $('#cids');
39
-
40
- function normalizeCids(v) {
41
- if (!v) { return []; }
42
- if (Array.isArray(v)) { return v.map(String); }
43
- if (typeof v === 'string') {
44
- return v.split(',').map(function (s) { return s.trim(); }).filter(Boolean);
45
- }
46
- return [];
47
- }
48
-
49
- // 1) Load saved settings (fills webhookUrl + checkbox; we also keep cids for later)
50
- settings.get('discord-onekite', function (saved) {
51
- saved = saved || {};
52
- // Populate simple fields now
53
- settings.load('discord-onekite', $form);
54
-
55
- var savedCids = normalizeCids(saved.cids);
56
-
57
- // 2) Load categories, then build options, then apply saved selection
58
- api.get('/categories', {}).then(function (res) {
59
- var categories = (res && res.categories) ? res.categories : [];
60
- $select.empty();
61
-
62
- categories
63
- .filter(function (c) { return c && typeof c.cid !== 'undefined' && c.name; })
64
- .forEach(function (c) {
65
- var opt = $('<option />').val(String(c.cid)).text(c.name);
66
- if (savedCids.includes(String(c.cid))) {
67
- opt.prop('selected', true);
68
- }
69
- opt.appendTo($select);
70
- });
71
- }).catch(function (e) {
72
- console.error('[discord-onekite] Could not load categories', e);
73
- if (window.app && app.alertError) {
74
- app.alertError('Impossible de charger la liste des catégories.');
75
- } else {
76
- alert('Impossible de charger la liste des catégories.');
77
- }
78
- });
79
-
80
- // 3) Save handler
81
- $('#save').off('click.discordOnekite').on('click.discordOnekite', function () {
82
- settings.save('discord-onekite', $form, function () {
83
- if (window.app && app.alertSuccess) {
84
- app.alertSuccess('Paramètres enregistrés !');
85
- }
86
- });
87
- });
88
- });
89
- });
90
- </script>