nodebb-plugin-discord-onekite 1.0.10 → 1.0.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 CHANGED
@@ -1,2 +1,4 @@
1
- # nodebb-plugin-discord-onekite v1.0.8
2
- Clean build (no debug). Server-side ACP + success alert.
1
+ # nodebb-plugin-discord-onekite v1.0.9
2
+
3
+ - Uses action:topic.post for new topics and action:topic.reply for replies (more reliable than action:*save for notifications).
4
+ - Server-side ACP settings + NodeBB-style toast (bottom-right) after save.
package/library.js CHANGED
@@ -49,7 +49,7 @@ async function postToDiscord(webhookUrl, payload) {
49
49
  }
50
50
  }
51
51
 
52
- async function buildTopicEmbed({ tid, pid, type }) {
52
+ async function buildTopicEmbed({ tid, pid, isReply }) {
53
53
  const baseUrl = meta.config.url;
54
54
 
55
55
  const topicData = await topics.getTopicFields(tid, ['tid', 'uid', 'cid', 'title', 'slug', 'timestamp', 'mainPid']);
@@ -58,11 +58,10 @@ async function buildTopicEmbed({ tid, pid, type }) {
58
58
  const topicUrl = `${baseUrl}/topic/${topicData.slug || topicData.tid}`;
59
59
  const u = await user.getUserFields(topicData.uid, ['username', 'picture']);
60
60
 
61
- const isReply = type === 'reply';
62
61
  const embed = {
63
62
  title: topicData.title || (isReply ? 'Nouvelle réponse' : 'Nouveau sujet'),
64
63
  url: isReply && pid ? `${topicUrl}/${pid}` : topicUrl,
65
- timestamp: new Date(isReply ? Date.now() : (topicData.timestamp || Date.now())).toISOString(),
64
+ timestamp: new Date(Date.now()).toISOString(),
66
65
  author: u?.username ? { name: u.username, icon_url: u.picture || undefined } : undefined,
67
66
  footer: { text: 'NodeBB → Discord (Onekite)' },
68
67
  };
@@ -72,6 +71,12 @@ async function buildTopicEmbed({ tid, pid, type }) {
72
71
  return { topicData, embed };
73
72
  }
74
73
 
74
+ function extractTidPid(data) {
75
+ const tid = data?.tid || data?.topic?.tid || data?.post?.tid;
76
+ const pid = data?.pid || data?.post?.pid;
77
+ return { tid, pid };
78
+ }
79
+
75
80
  const Plugin = {};
76
81
 
77
82
  Plugin.init = async ({ router }) => {
@@ -110,22 +115,16 @@ Plugin.addAdminNavigation = (header) => {
110
115
  return header;
111
116
  };
112
117
 
113
- Plugin.onTopicSave = async (data) => {
118
+ // Fired when a new topic is posted (creation)
119
+ Plugin.onTopicPost = async (data) => {
114
120
  try {
115
121
  const settings = await getSettings();
116
122
  if (!settings.webhookUrl) return;
117
123
 
118
- const tid = data?.tid || data?.topic?.tid;
124
+ const { tid } = extractTidPid(data);
119
125
  if (!tid) return;
120
126
 
121
- const isNew =
122
- data?.isNew === true ||
123
- data?.topic?.isNew === true ||
124
- (typeof data?.topic?.postcount === 'number' && data.topic.postcount === 1);
125
-
126
- if (!isNew) return;
127
-
128
- const built = await buildTopicEmbed({ tid, type: 'topic' });
127
+ const built = await buildTopicEmbed({ tid, isReply: false });
129
128
  if (!built) return;
130
129
 
131
130
  if (!cidAllowed(built.topicData.cid, settings.cids)) return;
@@ -137,23 +136,22 @@ Plugin.onTopicSave = async (data) => {
137
136
  }
138
137
  };
139
138
 
140
- Plugin.onPostSave = async (data) => {
139
+ // Fired when a reply is made in a topic
140
+ Plugin.onTopicReply = async (data) => {
141
141
  try {
142
142
  const settings = await getSettings();
143
143
  if (!settings.notifyReplies) return;
144
144
  if (!settings.webhookUrl) return;
145
145
 
146
- const pid = data?.pid || data?.post?.pid;
147
- const tid = data?.tid || data?.post?.tid;
148
- if (!pid || !tid) return;
149
-
150
- const isNew = data?.isNew === true || data?.post?.isNew === true;
151
- if (!isNew) return;
146
+ const { tid, pid } = extractTidPid(data);
147
+ if (!tid || !pid) return;
152
148
 
153
- const built = await buildTopicEmbed({ tid, pid, type: 'reply' });
149
+ const built = await buildTopicEmbed({ tid, pid, isReply: true });
154
150
  if (!built) return;
155
151
 
152
+ // Safety: don't notify if somehow this is the main post
156
153
  if (built.topicData?.mainPid && String(built.topicData.mainPid) === String(pid)) return;
154
+
157
155
  if (!cidAllowed(built.topicData.cid, settings.cids)) return;
158
156
 
159
157
  await postToDiscord(settings.webhookUrl, { embeds: [built.embed] });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-discord-onekite",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
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
@@ -13,13 +13,16 @@
13
13
  "method": "addAdminNavigation"
14
14
  },
15
15
  {
16
- "hook": "action:topic.save",
17
- "method": "onTopicSave"
16
+ "hook": "action:topic.post",
17
+ "method": "onTopicPost"
18
18
  },
19
19
  {
20
- "hook": "action:post.save",
21
- "method": "onPostSave"
20
+ "hook": "action:topic.reply",
21
+ "method": "onTopicReply"
22
22
  }
23
23
  ],
24
- "templates": "templates"
24
+ "templates": "templates",
25
+ "acpScripts": [
26
+ "static/lib/acp-toast.js"
27
+ ]
25
28
  }
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+ /* global $, app, ajaxify */
3
+
4
+ (function () {
5
+ function showToastIfSaved() {
6
+ if (!ajaxify || !ajaxify.data || ajaxify.data.template !== 'admin/plugins/discord-onekite') return;
7
+
8
+ try {
9
+ const url = new URL(window.location.href);
10
+ const saved = url.searchParams.get('saved');
11
+ if (saved === '1' || saved === 'true') {
12
+ if (window.app && typeof app.alertSuccess === 'function') {
13
+ app.alertSuccess('Paramètres enregistrés !');
14
+ }
15
+ // remove the query param to avoid re-toasting on navigation
16
+ url.searchParams.delete('saved');
17
+ window.history.replaceState({}, document.title, url.toString());
18
+ }
19
+ } catch (e) {
20
+ // ignore
21
+ }
22
+ }
23
+
24
+ $(window).on('action:ajaxify.end', showToastIfSaved);
25
+ $(showToastIfSaved);
26
+ })();