nodebb-plugin-onekite-discord 1.0.12 → 1.0.14
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/library.js +35 -57
- package/package.json +1 -1
- package/plugin.json +1 -1
package/library.js
CHANGED
|
@@ -2,37 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* - NodeBB rendered: text(url) or text (url)
|
|
13
|
-
* - Bare URLs: https://... or http://... or www.example.com
|
|
14
|
-
*
|
|
15
|
-
* Note: We'll output masked links in embed fields, where Discord supports them.
|
|
8
|
+
* Flatten any link-like markup to plain URLs so Discord auto-linkifies them.
|
|
9
|
+
* Supported:
|
|
10
|
+
* - [text](url)
|
|
11
|
+
* - <a href="url">text</a>
|
|
12
|
+
* - text(url) / text (url)
|
|
13
|
+
* - bare URLs and www.*
|
|
16
14
|
*/
|
|
17
|
-
function
|
|
18
|
-
if (!str || typeof str !== 'string') return
|
|
19
|
-
|
|
20
|
-
const links = [];
|
|
21
|
-
const seen = new Set();
|
|
15
|
+
function flattenLinksToUrls(str) {
|
|
16
|
+
if (!str || typeof str !== 'string') return str;
|
|
22
17
|
|
|
23
18
|
const normalizeUrl = (u) => {
|
|
24
|
-
if (!u) return
|
|
19
|
+
if (!u) return u;
|
|
25
20
|
let url = String(u).trim();
|
|
26
21
|
url = url.replace(/^<(.+)>$/, '$1');
|
|
27
22
|
url = url.replace(/^https:\//i, 'https://');
|
|
28
23
|
url = url.replace(/^http:\//i, 'http://');
|
|
29
24
|
if (/^www\./i.test(url)) url = 'https://' + url;
|
|
30
|
-
// Very small sanity check
|
|
31
|
-
if (!/^https?:\/\//i.test(url)) return null;
|
|
32
25
|
return url;
|
|
33
|
-
fields: linkFields,
|
|
34
26
|
};
|
|
35
27
|
|
|
28
|
+
// HTML links -> URL
|
|
29
|
+
str = str.replace(/<a\s+[^>]*href=["']([^"']+)["'][^>]*>.*?<\/a>/gi, (_m, href) => {
|
|
30
|
+
return normalizeUrl(href);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Markdown [text](url) -> URL
|
|
34
|
+
str = str.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, _text, url) => {
|
|
35
|
+
return normalizeUrl(url);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// text(url) or text (url) -> URL
|
|
39
|
+
str = str.replace(/([^\n\r()]{1,200}?)\s*\((https?:\/\/[^)\s]+|www\.[^)\\s]+)\)/g, (_m, _text, url) => {
|
|
40
|
+
return normalizeUrl(url);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return str;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
;
|
|
47
|
+
|
|
36
48
|
const push = (text, url) => {
|
|
37
49
|
const u = normalizeUrl(url);
|
|
38
50
|
if (!u) return;
|
|
@@ -73,46 +85,12 @@ function extractDiscordLinks(str) {
|
|
|
73
85
|
return links;
|
|
74
86
|
}
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
* Remove/flatten link markup from text for embed.description readability.
|
|
78
|
-
* - [text](url) -> text
|
|
79
|
-
* - <a href="url">text</a> -> text
|
|
80
|
-
* - text(url) -> text
|
|
81
|
-
* - leaves bare URLs as-is (optional), but we can also remove them if desired.
|
|
82
|
-
*/
|
|
83
|
-
function stripLinkMarkup(str) {
|
|
84
|
-
if (!str || typeof str !== 'string') return str;
|
|
85
|
-
|
|
86
|
-
// HTML links -> text
|
|
87
|
-
str = str.replace(/<a\s+[^>]*href=["'][^"']+["'][^>]*>(.*?)<\/a>/gi, (_m, text) => text);
|
|
88
|
-
|
|
89
|
-
// Markdown masked -> text
|
|
90
|
-
str = str.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, text) => text);
|
|
91
|
-
|
|
92
|
-
// NodeBB rendered -> text
|
|
93
|
-
str = str.replace(/([^\n\r()]{1,200}?)\s*\((https?:\/\/[^)\s]+|www\.[^)\s]+)\)/g, (_m, text) => String(text).trim());
|
|
88
|
+
?)\s*\((https?:\/\/[^)\s]+|www\.[^)\s]+)\)/g, (_m, text) => String(text).trim());
|
|
94
89
|
|
|
95
90
|
return str;
|
|
96
91
|
}
|
|
97
92
|
|
|
98
|
-
|
|
99
|
-
* Normalize links for Discord embeds.
|
|
100
|
-
* Discord does NOT support masked links in embed descriptions.
|
|
101
|
-
* NodeBB may already render links as: texte(url)
|
|
102
|
-
* We always output a plain URL so Discord auto-linkifies it.
|
|
103
|
-
*/
|
|
104
|
-
function formatDiscordLinks(str) {
|
|
105
|
-
if (!str || typeof str !== 'string') return str;
|
|
106
|
-
|
|
107
|
-
const normalizeUrl = (u) => {
|
|
108
|
-
if (!u) return u;
|
|
109
|
-
let url = String(u).trim();
|
|
110
|
-
url = url.replace(/^<(.+)>$/, '$1');
|
|
111
|
-
url = url.replace(/^https:\//i, 'https://');
|
|
112
|
-
url = url.replace(/^http:\//i, 'http://');
|
|
113
|
-
if (/^www\./i.test(url)) url = 'https://' + url;
|
|
114
|
-
return url;
|
|
115
|
-
};
|
|
93
|
+
;
|
|
116
94
|
|
|
117
95
|
// HTML <a href="...">...</a> -> URL
|
|
118
96
|
str = str.replace(/<a\s+[^>]*href=["']([^"']+)["'][^>]*>.*?<\/a>/gi, (_m, href) => {
|
|
@@ -353,7 +331,7 @@ for (let i = 0; i < extractedLinks.length && linkFields.length < maxFields; i +=
|
|
|
353
331
|
const embedTitle = `${replyIcon}${safeTitle} – ${username}`.slice(0, 256);
|
|
354
332
|
|
|
355
333
|
// Embed title becomes clickable via embed.url
|
|
356
|
-
return { topicData, content: '', embed: { title: embedTitle, url: targetUrl, description:
|
|
334
|
+
return { topicData, content: '', embed: { title: embedTitle, url: targetUrl, description: flattenLinksToUrls(excerpt || ''), fields: linkFields } };
|
|
357
335
|
}
|
|
358
336
|
|
|
359
337
|
function extractTidPid(data) {
|
|
@@ -416,4 +394,4 @@ Plugin.onTopicReply = async (data) => {
|
|
|
416
394
|
await sendDiscord(settings.webhookUrl, { content: built.content, embeds: [built.embed] });
|
|
417
395
|
};
|
|
418
396
|
|
|
419
|
-
module.exports = Plugin;
|
|
397
|
+
module.exports = Plugin;
|
package/package.json
CHANGED
package/plugin.json
CHANGED