nodebb-plugin-discord-onekite 1.1.10 → 1.1.11
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 -3
- package/library.js +46 -16
- package/package.json +1 -1
- package/static/lib/admin.js +0 -1
- package/templates/admin/plugins/discord-onekite.tpl +6 -9
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
# nodebb-plugin-discord-onekite v1.1.
|
|
1
|
+
# nodebb-plugin-discord-onekite v1.1.4.2
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Based on v1.1.4.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Change: Discord notification format is now:
|
|
6
|
+
- Single clickable link line: 🆕 Nouveau sujet : [Titre](URL) (or reply variant)
|
|
7
|
+
- Excerpt below
|
|
8
|
+
|
|
9
|
+
ACP behavior unchanged from v1.1.4.
|
package/library.js
CHANGED
|
@@ -8,6 +8,7 @@ const middleware = require.main.require('./src/middleware');
|
|
|
8
8
|
|
|
9
9
|
const topics = require.main.require('./src/topics');
|
|
10
10
|
const posts = require.main.require('./src/posts');
|
|
11
|
+
const user = require.main.require('./src/user');
|
|
11
12
|
|
|
12
13
|
const controllers = require('./lib/controllers');
|
|
13
14
|
|
|
@@ -37,6 +38,15 @@ function ensureAbsoluteUrl(baseUrl, maybeUrl) {
|
|
|
37
38
|
return s;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
function isValidHttpUrl(s) {
|
|
42
|
+
try {
|
|
43
|
+
const u = new URL(s);
|
|
44
|
+
return u.protocol === 'http:' || u.protocol === 'https:';
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
function stripHtml(html) {
|
|
41
51
|
if (!html) return '';
|
|
42
52
|
return String(html)
|
|
@@ -89,15 +99,15 @@ async function postToDiscord(webhookUrl, payload) {
|
|
|
89
99
|
}
|
|
90
100
|
}
|
|
91
101
|
|
|
92
|
-
async function sendDiscord(webhookUrl, payload) {
|
|
102
|
+
async function sendDiscord(webhookUrl, payload, fallbackContent) {
|
|
93
103
|
if (!webhookUrl) return;
|
|
104
|
+
|
|
94
105
|
try {
|
|
95
106
|
await postToDiscord(webhookUrl, payload);
|
|
96
107
|
} catch (e) {
|
|
97
|
-
|
|
98
|
-
if (e && e.statusCode === 400 && payload && payload.content) {
|
|
108
|
+
if (e && e.statusCode === 400 && fallbackContent) {
|
|
99
109
|
try {
|
|
100
|
-
await postToDiscord(webhookUrl, { content:
|
|
110
|
+
await postToDiscord(webhookUrl, { content: fallbackContent });
|
|
101
111
|
return;
|
|
102
112
|
} catch (e2) {
|
|
103
113
|
console.error(e2);
|
|
@@ -121,25 +131,40 @@ async function getPostExcerpt(pid) {
|
|
|
121
131
|
async function buildPayload({ tid, pid, isReply }) {
|
|
122
132
|
const baseUrl = normalizeBaseUrl(meta.config.url);
|
|
123
133
|
|
|
124
|
-
const topicData = await topics.getTopicFields(tid, ['tid', 'cid', 'title', 'slug', 'mainPid']);
|
|
134
|
+
const topicData = await topics.getTopicFields(tid, ['tid', 'uid', 'cid', 'title', 'slug', 'mainPid']);
|
|
125
135
|
if (!topicData) return null;
|
|
126
136
|
|
|
137
|
+
// Always build the forum link like the example: https://www.onekite.com/topic/<tid or slug>
|
|
127
138
|
const topicUrl = ensureAbsoluteUrl(baseUrl, `/topic/${topicData.slug || topicData.tid}`);
|
|
128
|
-
const targetUrl = (isReply && pid) ? `${topicUrl}/${pid}` : topicUrl;
|
|
129
139
|
|
|
140
|
+
// For replies, link directly to the post if possible
|
|
141
|
+
const postUrl = (isReply && pid) ? `${topicUrl}/${pid}` : topicUrl;
|
|
142
|
+
|
|
143
|
+
const u = await user.getUserFields(topicData.uid, ['username']);
|
|
130
144
|
const title = (topicData.title || (isReply ? 'Nouvelle réponse' : 'Nouveau sujet')).toString().slice(0, 256);
|
|
145
|
+
const authorName = (u && u.username ? String(u.username) : 'Utilisateur').slice(0, 256);
|
|
146
|
+
|
|
131
147
|
const excerpt = await getPostExcerpt(isReply ? pid : topicData.mainPid);
|
|
148
|
+
const description = truncate(excerpt || (isReply ? `Réponse de ${authorName}` : `Sujet créé par ${authorName}`), 500);
|
|
149
|
+
|
|
150
|
+
// Minimal embed but with URL so the title is clickable
|
|
151
|
+
const embed = {
|
|
152
|
+
title,
|
|
153
|
+
description,
|
|
154
|
+
};
|
|
155
|
+
if (isValidHttpUrl(postUrl)) embed.url = postUrl;
|
|
132
156
|
|
|
133
|
-
//
|
|
157
|
+
// Message format:
|
|
158
|
+
// 1) A single clickable link line: "🆕 Nouveau sujet : [Titre](URL)" (or reply variant)
|
|
159
|
+
// 2) Excerpt below
|
|
134
160
|
const linkLine = isReply
|
|
135
|
-
? `🗨️ Nouvelle réponse : [${title}](${
|
|
161
|
+
? `🗨️ Nouvelle réponse : [${title}](${postUrl})`
|
|
136
162
|
: `🆕 Nouveau sujet : [${title}](${topicUrl})`;
|
|
137
163
|
|
|
138
|
-
const content = [linkLine,
|
|
139
|
-
|
|
140
|
-
const embed = { title, description: excerpt || '' , url: targetUrl };
|
|
164
|
+
const content = [linkLine, description].filter(Boolean).join('
|
|
165
|
+
');
|
|
141
166
|
|
|
142
|
-
return { topicData,
|
|
167
|
+
return { topicData, embed, content };
|
|
143
168
|
}
|
|
144
169
|
|
|
145
170
|
function extractTidPid(data) {
|
|
@@ -158,8 +183,8 @@ Plugin.init = async ({ router }) => {
|
|
|
158
183
|
controllers.renderAdminPage
|
|
159
184
|
);
|
|
160
185
|
|
|
161
|
-
// AJAX save endpoint (used by admin.js
|
|
162
|
-
router.post('/admin/plugins/discord-onekite/save',
|
|
186
|
+
// AJAX save endpoint for ACP (used by admin.js)
|
|
187
|
+
router.post('/api/admin/plugins/discord-onekite/save',
|
|
163
188
|
middleware.admin.checkPrivileges,
|
|
164
189
|
async (req, res) => {
|
|
165
190
|
try {
|
|
@@ -196,9 +221,11 @@ Plugin.onTopicPost = async (data) => {
|
|
|
196
221
|
|
|
197
222
|
const built = await buildPayload({ tid, isReply: false });
|
|
198
223
|
if (!built) return;
|
|
224
|
+
|
|
199
225
|
if (!cidAllowed(built.topicData.cid, settings.cids)) return;
|
|
200
226
|
|
|
201
|
-
|
|
227
|
+
// Send content + embed (content ensures clickable link always)
|
|
228
|
+
await sendDiscord(settings.webhookUrl, { content: built.content, embeds: [built.embed] }, built.content);
|
|
202
229
|
};
|
|
203
230
|
|
|
204
231
|
Plugin.onTopicReply = async (data) => {
|
|
@@ -211,9 +238,12 @@ Plugin.onTopicReply = async (data) => {
|
|
|
211
238
|
|
|
212
239
|
const built = await buildPayload({ tid, pid, isReply: true });
|
|
213
240
|
if (!built) return;
|
|
241
|
+
|
|
242
|
+
if (built.topicData?.mainPid && String(built.topicData.mainPid) === String(pid)) return;
|
|
243
|
+
|
|
214
244
|
if (!cidAllowed(built.topicData.cid, settings.cids)) return;
|
|
215
245
|
|
|
216
|
-
await sendDiscord(settings.webhookUrl, { content: built.content, embeds: [built.embed] });
|
|
246
|
+
await sendDiscord(settings.webhookUrl, { content: built.content, embeds: [built.embed] }, built.content);
|
|
217
247
|
};
|
|
218
248
|
|
|
219
249
|
module.exports = Plugin;
|
package/package.json
CHANGED
package/static/lib/admin.js
CHANGED
|
@@ -21,7 +21,6 @@ define('admin/plugins/discord-onekite', ['api'], function (api) {
|
|
|
21
21
|
cids: getMultiSelectValues('#cids'),
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
// api.post prefixes /api automatically, so server route must be /admin/...
|
|
25
24
|
api.post('/admin/plugins/discord-onekite/save', payload).then(function () {
|
|
26
25
|
if (window.app && typeof app.alertSuccess === 'function') {
|
|
27
26
|
app.alertSuccess('Paramètres enregistrés !');
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
<div class="acp-page-container">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
</div>
|
|
7
|
-
<button id="save" class="btn btn-primary">
|
|
8
|
-
<i class="fa fa-save"></i> Enregistrer
|
|
9
|
-
</button>
|
|
10
|
-
</div>
|
|
2
|
+
<h4>Discord Onekite</h4>
|
|
3
|
+
<p class="text-muted">
|
|
4
|
+
Notifications Discord via webhook.
|
|
5
|
+
</p>
|
|
11
6
|
|
|
12
7
|
<form role="form" class="discord-onekite-settings">
|
|
13
8
|
<div class="mb-3">
|
|
@@ -33,5 +28,7 @@
|
|
|
33
28
|
Si aucune catégorie n’est sélectionnée : <strong>toutes les catégories</strong> seront notifiées.
|
|
34
29
|
</p>
|
|
35
30
|
</div>
|
|
31
|
+
|
|
32
|
+
<!-- IMPORT admin/partials/save_button.tpl -->
|
|
36
33
|
</form>
|
|
37
34
|
</div>
|