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 +7 -4
- package/library.js +4 -8
- package/package.json +1 -1
- package/plugin.json +4 -1
- package/static/lib/admin.js +83 -0
- package/static/templates/admin/plugins/discord-onekite.tpl +1 -61
package/README.md
CHANGED
|
@@ -1,5 +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
|
-
|
|
4
|
-
-
|
|
5
|
-
-
|
|
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
|
-
//
|
|
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
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>
|