forked from mrhso/LilyWhiteBot
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathwikilinky.js
131 lines (106 loc) · 3.33 KB
/
wikilinky.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* linky - 自動將聊天中的[[]]與{{}}換成 Wiki 系統的連結
*
* 配置方法:在 config.js 中
plugins 中加入一個「wikilinky」,然後在末尾補一個:
"wikilinky": {
"groups": {
"qq/123123123": "https://zh.wikipedia.org/wiki/$1"
}
}
*/
'use strict';
const BridgeMsg = require('./transport/BridgeMsg.js');
const compare = (x, y) => {
return x.pos - y.pos;
};
let map = {};
const pad = (str) => {
return `00${str}`.substr(-2);
};
const genlink = (v) => {
// 處理「#」
let str = v.replace(/ /gu, '_');
let p = str.indexOf('#');
if (p === -1) {
return encodeURI(str);
} else {
/*
對於「#」後面的內容:
不轉成 ASCII 的:字母、數字、「-」、「.」、「:」、「_」
空白轉成「_」
*/
let s1 = encodeURI(str.substring(0, p));
let s2 = str.substring(p+1);
let plain = Buffer.from(s2, 'utf-8').toString('binary');
s2 = plain.replace(/[^A-Za-z0-9\-\.:_]/gu, (ch) => {
return `.${pad(ch.charCodeAt(0).toString(16).toUpperCase())}`;
});
return `${s1}#${s2}`;
}
};
const linky = (string, prefix) => {
let text = {}; // 去重複
let links = [];
string.replace(/\[\[\s*([^\[\|]+?)\s*(|\|.+?)\]\]/gu, (s, l, _, offset) => {
if (!text[l]) {
links.push({ pos: offset, link: prefix.replace('$1', genlink(l)) });
text[l] = true;
}
return s;
});
string.replace(/([^\{]|^)\{\{\s*([^\{#\[\]\|]+?)\s*(|\|.+?)\}\}/gu, (s, _, l, __, offset) => {
let t = l;
if (!t.startsWith(':') && !t.toLowerCase().startsWith('template:')) {
t = 'Template:' + t;
}
if (!text[t]) {
links.push({ pos: offset, link: prefix.replace('$1', `${genlink(t)}`) });
text[t] = true;
}
return s;
});
links.sort(compare);
return links;
};
const processlinky = (context, bridge) => {
try {
let rule = map[BridgeMsg.getUIDFromContext(context, context.to)];
if (rule) {
let links = linky(context.text, rule);
if (links.length > 0) {
context.reply(links.map(l => l.link).join(' '));
// 若互聯且在公開群組調用,則讓其他群也看到連結
if (bridge && !context.isPrivate) {
bridge.send(new BridgeMsg(context, {
text: links.map(l => l.link).join(' '),
isNotice: true,
}));
}
}
}
} catch (ex) {
}
};
module.exports = (pluginManager, options) => {
const bridge = pluginManager.plugins.transport;
if (!options) {
return;
}
let types = {};
BridgeMsg.setHandlers(pluginManager.handlers);
for (let [type, handler] of pluginManager.handlers) {
map[type] = {};
}
let groups = options.groups || {};
for (let group in groups) {
let client = BridgeMsg.parseUID(group);
if (client.uid) {
map[client.uid] = groups[group];
types[client.client] = true;
}
}
for (let type in types) {
pluginManager.handlers.get(type).on('text', (context) => processlinky(context, bridge));
}
};