nodebb-plugin-discord-onekite 1.1.15 → 1.1.16

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,8 +1,12 @@
1
- # nodebb-plugin-discord-onekite v1.1.4.7
1
+ # nodebb-plugin-discord-onekite v1.1.4.8
2
2
 
3
- Discord output cleanup:
4
- - Removes the extra content line under the title.
5
- - Sends an embed where:
6
- - title is clickable (embed.url)
7
- - embed description contains the message excerpt
8
- - `content` is only used as a fallback if Discord rejects embeds.
3
+ ACP (NodeBB v4):
4
+ - Save button at top: "Enregistrer les paramètres"
5
+ - Uses custom API routes (GET/POST) registered with `routeHelpers.setupApiRoute`:
6
+ - GET /api/plugins/discord-onekite/settings
7
+ - POST /api/plugins/discord-onekite/settings
8
+ - Shows NodeBB toast on save
9
+
10
+ Discord:
11
+ - Embed only: clickable title (embed.url) + message excerpt in embed.description (no duplicate lines)
12
+ - Absolute URL prefix fallback to https://www.onekite.com
package/library.js CHANGED
@@ -129,7 +129,8 @@ async function getPostExcerpt(pid) {
129
129
  }
130
130
 
131
131
  async function buildPayload({ tid, pid, isReply }) {
132
- const baseUrl = normalizeBaseUrl(meta.config.url);
132
+ let baseUrl = normalizeBaseUrl(meta.config.url || meta.config['url']);
133
+ if (!baseUrl) { baseUrl = 'https://www.onekite.com'; }
133
134
 
134
135
  const topicData = await topics.getTopicFields(tid, ['tid', 'uid', 'cid', 'title', 'slug', 'mainPid']);
135
136
  if (!topicData) return null;
@@ -182,6 +183,39 @@ Plugin.init = async ({ router }) => {
182
183
  controllers.renderAdminPage
183
184
  );
184
185
 
186
+ // API routes for ACP (client calls /api/plugins/discord-onekite/settings)
187
+ routeHelpers.setupApiRoute(router, 'get', '/plugins/discord-onekite/settings', [middleware.admin.checkPrivileges], async (req, res) => {
188
+ const s = await meta.settings.get(SETTINGS_KEY);
189
+ res.json({
190
+ settings: {
191
+ webhookUrl: (s && s.webhookUrl) ? String(s.webhookUrl).trim() : '',
192
+ notifyReplies: !!(s && (s.notifyReplies === true || s.notifyReplies === 'on' || s.notifyReplies === 'true')),
193
+ cids: (() => {
194
+ const v = s && s.cids;
195
+ if (!v) return [];
196
+ if (Array.isArray(v)) return v.map(String).filter(Boolean);
197
+ if (typeof v === 'string') return v.split(',').map(x => x.trim()).filter(Boolean);
198
+ return [];
199
+ })(),
200
+ },
201
+ });
202
+ });
203
+
204
+ routeHelpers.setupApiRoute(router, 'post', '/plugins/discord-onekite/settings', [middleware.admin.checkPrivileges], async (req, res) => {
205
+ try {
206
+ const payload = {
207
+ webhookUrl: req.body.webhookUrl || '',
208
+ notifyReplies: req.body.notifyReplies ? 'on' : '',
209
+ cids: req.body.cids || '',
210
+ };
211
+ await meta.settings.set(SETTINGS_KEY, payload);
212
+ res.json({ ok: true });
213
+ } catch (e) {
214
+ console.error('[discord-onekite] save failed', e);
215
+ res.status(500).json({ ok: false });
216
+ }
217
+ });
218
+
185
219
  // AJAX save endpoint for ACP (used by admin.js)
186
220
  router.post('/api/admin/plugins/discord-onekite/save',
187
221
  middleware.admin.checkPrivileges,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-discord-onekite",
3
- "version": "1.1.15",
3
+ "version": "1.1.16",
4
4
  "description": "Discord webhook notifier for Onekite (NodeBB v4.x only)",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
@@ -1,22 +1,65 @@
1
1
  'use strict';
2
2
  /* global $, app */
3
3
 
4
- define('admin/plugins/discord-onekite', ['settings'], function (settings) {
4
+ define('admin/plugins/discord-onekite', ['api'], function (api) {
5
5
  const ACP = {};
6
6
 
7
+ function getMultiSelectValues(selector) {
8
+ const el = document.querySelector(selector);
9
+ if (!el) return [];
10
+ return Array.from(el.selectedOptions || []).map(o => o.value);
11
+ }
12
+
13
+ function setMultiSelectValues(selector, values) {
14
+ const el = document.querySelector(selector);
15
+ if (!el) return;
16
+ const set = new Set((values || []).map(String));
17
+ Array.from(el.options).forEach(opt => { opt.selected = set.has(String(opt.value)); });
18
+ }
19
+
20
+ async function loadSettings() {
21
+ try {
22
+ const res = await api.get('/plugins/discord-onekite/settings');
23
+ if (res && res.settings) {
24
+ $('#webhookUrl').val(res.settings.webhookUrl || '');
25
+ $('#notifyReplies').prop('checked', !!res.settings.notifyReplies);
26
+ setMultiSelectValues('#cids', res.settings.cids || []);
27
+ }
28
+ } catch (err) {
29
+ // eslint-disable-next-line no-console
30
+ console.error(err);
31
+ }
32
+ }
33
+
34
+ async function saveSettings() {
35
+ const payload = {
36
+ webhookUrl: String($('#webhookUrl').val() || '').trim(),
37
+ notifyReplies: $('#notifyReplies').is(':checked'),
38
+ cids: getMultiSelectValues('#cids'),
39
+ };
40
+
41
+ try {
42
+ await api.post('/plugins/discord-onekite/settings', payload);
43
+ if (window.app && typeof app.alertSuccess === 'function') {
44
+ app.alertSuccess('Paramètres enregistrés !');
45
+ }
46
+ } catch (err) {
47
+ // eslint-disable-next-line no-console
48
+ console.error(err);
49
+ if (window.app && typeof app.alertError === 'function') {
50
+ app.alertError('Erreur lors de l’enregistrement');
51
+ }
52
+ }
53
+ }
54
+
7
55
  ACP.init = function () {
8
- const $form = $('.discord-onekite-settings');
9
- if (!$form.length) return;
56
+ if (!$('.discord-onekite-settings').length) return;
10
57
 
11
- settings.sync('discord-onekite', $form);
58
+ loadSettings();
12
59
 
13
60
  $('#save').off('click.discordOnekite').on('click.discordOnekite', function (e) {
14
61
  e.preventDefault();
15
- settings.persist('discord-onekite', $form, function () {
16
- if (window.app && typeof app.alertSuccess === 'function') {
17
- app.alertSuccess('Paramètres enregistrés !');
18
- }
19
- });
62
+ saveSettings();
20
63
  });
21
64
  };
22
65
 
@@ -1,6 +1,11 @@
1
1
  <div class="acp-page-container">
2
- <h4>Discord Onekite</h4>
3
- <p class="text-muted">Notifications Discord via webhook.</p>
2
+ <div class="d-flex justify-content-between align-items-start mb-3">
3
+ <div>
4
+ <h4 class="mb-1">Discord Onekite</h4>
5
+ <p class="text-muted mb-0">Notifications Discord via webhook.</p>
6
+ </div>
7
+ <button id="save" type="button" class="btn btn-primary">Enregistrer les paramètres</button>
8
+ </div>
4
9
 
5
10
  <form role="form" class="discord-onekite-settings">
6
11
  <div class="mb-3">
@@ -26,7 +31,5 @@
26
31
  Si aucune catégorie n’est sélectionnée : <strong>toutes les catégories</strong> seront notifiées.
27
32
  </p>
28
33
  </div>
29
-
30
- <button id="save" type="button" class="btn btn-primary">Enregistrer les paramètres</button>
31
34
  </form>
32
35
  </div>