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 +6 -5
- package/library.js +4 -10
- package/package.json +1 -1
- package/plugin.json +3 -1
- package/static/lib/admin.js +49 -33
- package/static/templates/admin/plugins/discord-onekite.tpl +1 -4
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
# nodebb-plugin-discord-onekite (NodeBB v4.x) — v1.0.
|
|
1
|
+
# nodebb-plugin-discord-onekite (NodeBB v4.x) — v1.0.2
|
|
2
2
|
|
|
3
|
-
Fix
|
|
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
|
-
|
|
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
package/plugin.json
CHANGED
package/static/lib/admin.js
CHANGED
|
@@ -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
|
-
|
|
17
|
-
const $form = $('.discord-onekite-settings');
|
|
15
|
+
async function loadCategoriesIntoSelect(savedCids) {
|
|
18
16
|
const $select = $('#cids');
|
|
17
|
+
if (!$select.length) return;
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
//
|
|
37
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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]
|
|
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
|
|
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>
|