nodebb-plugin-integration 0.4.2 → 0.5.0
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 +199 -320
- package/README.ru.md +199 -347
- package/library.js +93 -115
- package/package.json +60 -57
- package/plugin.json +50 -33
- package/public/js/admin.js +58 -45
- package/public/templates/admin/plugins/integration.tpl +213 -0
- package/src/ai/embeddings.js +46 -253
- package/src/ai/indexer.js +156 -343
- package/src/ai/openai.js +74 -330
- package/src/ai/qdrant.js +114 -517
- package/src/ai/search.js +138 -251
- package/src/config/index.js +176 -133
- package/src/config/validation.js +250 -0
- package/src/events/index.js +174 -324
- package/src/mcp/manager.js +396 -0
- package/src/mcp/server.js +347 -177
- package/src/mcp/tools.js +158 -617
- package/src/nodebb/categories.js +39 -0
- package/src/nodebb/index.js +72 -305
- package/src/nodebb/meta.js +24 -273
- package/src/nodebb/posts.js +93 -348
- package/src/nodebb/privileges.js +68 -0
- package/src/nodebb/topics.js +91 -355
- package/src/nodebb/users.js +62 -345
- package/src/routes/api.js +255 -97
- package/src/routes/index.js +64 -49
- package/templates/admin/plugins/integration.tpl +0 -130
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const NodeBB = require("./index");
|
|
4
|
+
|
|
5
|
+
async function getAll() {
|
|
6
|
+
const categories = NodeBB.get("categories");
|
|
7
|
+
|
|
8
|
+
if (typeof categories.getAllCategories !== "function") {
|
|
9
|
+
throw new Error("NodeBB categories.getAllCategories is unavailable");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const result = await categories.getAllCategories();
|
|
13
|
+
|
|
14
|
+
return (result || [])
|
|
15
|
+
.filter(category => category && Number.isSafeInteger(Number(category.cid)))
|
|
16
|
+
.map(category => ({
|
|
17
|
+
cid: Number(category.cid),
|
|
18
|
+
name: category.name || "",
|
|
19
|
+
parentCid: Number(category.parentCid || 0),
|
|
20
|
+
disabled: Boolean(category.disabled)
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function getById(cid) {
|
|
25
|
+
cid = Number(cid);
|
|
26
|
+
|
|
27
|
+
if (!Number.isSafeInteger(cid) || cid < 0) {
|
|
28
|
+
throw new TypeError("Invalid category ID");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const categories = await getAll();
|
|
32
|
+
|
|
33
|
+
return categories.find(category => category.cid === cid) || null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = {
|
|
37
|
+
getAll,
|
|
38
|
+
getById
|
|
39
|
+
};
|
package/src/nodebb/index.js
CHANGED
|
@@ -1,306 +1,73 @@
|
|
|
1
|
-
"use strict";
|
|
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
|
-
return available;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
function isAvailable() {
|
|
101
|
-
|
|
102
|
-
return available;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
function info() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
available,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
url:
|
|
133
|
-
|
|
134
|
-
Config.nodebb.url
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
async function request(
|
|
155
|
-
|
|
156
|
-
path,
|
|
157
|
-
|
|
158
|
-
options = {}
|
|
159
|
-
|
|
160
|
-
) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if(!available) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
throw new Error(
|
|
169
|
-
|
|
170
|
-
"NodeBB API unavailable"
|
|
171
|
-
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const fetch =
|
|
185
|
-
|
|
186
|
-
global.fetch ||
|
|
187
|
-
|
|
188
|
-
require("node-fetch");
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const headers = {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
"Content-Type":
|
|
201
|
-
|
|
202
|
-
"application/json"
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if(Config.nodebb.apiKey) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
headers.Authorization =
|
|
219
|
-
|
|
220
|
-
Config.nodebb.apiKey;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const response =
|
|
233
|
-
|
|
234
|
-
await fetch(
|
|
235
|
-
|
|
236
|
-
Config.nodebb.url + path,
|
|
237
|
-
|
|
238
|
-
{
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
method:
|
|
242
|
-
|
|
243
|
-
options.method || "GET",
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
headers,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
body:
|
|
252
|
-
|
|
253
|
-
options.body
|
|
254
|
-
|
|
255
|
-
? JSON.stringify(options.body)
|
|
256
|
-
|
|
257
|
-
: undefined
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return response.json();
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
module.exports = {
|
|
291
|
-
|
|
292
|
-
check,
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
isAvailable,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
info,
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
request
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const MODULES = Object.freeze({
|
|
4
|
+
meta: "./src/meta",
|
|
5
|
+
posts: "./src/posts",
|
|
6
|
+
topics: "./src/topics",
|
|
7
|
+
users: "./src/user",
|
|
8
|
+
categories: "./src/categories",
|
|
9
|
+
privileges: "./src/privileges",
|
|
10
|
+
plugins: "./src/plugins"
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
let modules = null;
|
|
14
|
+
let loadError = null;
|
|
15
|
+
|
|
16
|
+
function initialize() {
|
|
17
|
+
if (modules) {
|
|
18
|
+
return modules;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof nodebb === "undefined" || !nodebb ||
|
|
22
|
+
typeof nodebb.require !== "function") {
|
|
23
|
+
throw new Error("NodeBB runtime is not available");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const loaded = {};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
for (const [name, path] of Object.entries(MODULES)) {
|
|
30
|
+
loaded[name] = nodebb.require(path);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
modules = Object.freeze(loaded);
|
|
34
|
+
|
|
35
|
+
return modules;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`NodeBB modules initialization failed: ${error.message}`,
|
|
39
|
+
{ cause: error }
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function get(name) {
|
|
45
|
+
if (!Object.prototype.hasOwnProperty.call(MODULES, name)) {
|
|
46
|
+
throw new Error(`Unknown NodeBB module: ${name}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return initialize()[name];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function isAvailable() {
|
|
53
|
+
try {
|
|
54
|
+
initialize();
|
|
55
|
+
return true;
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function info() {
|
|
62
|
+
return {
|
|
63
|
+
available: isAvailable(),
|
|
64
|
+
modules: modules ? Object.keys(modules) : []
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = {
|
|
69
|
+
get,
|
|
70
|
+
initialize,
|
|
71
|
+
isAvailable,
|
|
72
|
+
info
|
|
306
73
|
};
|
package/src/nodebb/meta.js
CHANGED
|
@@ -1,273 +1,24 @@
|
|
|
1
|
-
"use strict";
|
|
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
|
-
let nativeMeta = null;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
function loadNative() {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if(nativeMeta) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return nativeMeta;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if(
|
|
71
|
-
|
|
72
|
-
require.main &&
|
|
73
|
-
|
|
74
|
-
require.main.require
|
|
75
|
-
|
|
76
|
-
) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
nativeMeta =
|
|
81
|
-
|
|
82
|
-
require.main.require(
|
|
83
|
-
|
|
84
|
-
"./src/meta"
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
catch(error) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
nativeMeta = null;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return nativeMeta;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
async function getInfo() {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const meta =
|
|
135
|
-
|
|
136
|
-
loadNative();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
/*
|
|
146
|
-
* Real NodeBB
|
|
147
|
-
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if(
|
|
151
|
-
|
|
152
|
-
meta &&
|
|
153
|
-
|
|
154
|
-
meta.configs &&
|
|
155
|
-
|
|
156
|
-
meta.configs.get
|
|
157
|
-
|
|
158
|
-
) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const config =
|
|
163
|
-
|
|
164
|
-
await meta.configs.get(
|
|
165
|
-
|
|
166
|
-
"config"
|
|
167
|
-
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
title:
|
|
180
|
-
|
|
181
|
-
config.title || "",
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
url:
|
|
186
|
-
|
|
187
|
-
config.url || "",
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
version:
|
|
192
|
-
|
|
193
|
-
config.version || "",
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
language:
|
|
198
|
-
|
|
199
|
-
config.language || null
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/*
|
|
216
|
-
* Standalone mode
|
|
217
|
-
*/
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
title:
|
|
224
|
-
|
|
225
|
-
"NodeBB Integration Development",
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
url:
|
|
230
|
-
|
|
231
|
-
NodeBB.info().url,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
version:
|
|
236
|
-
|
|
237
|
-
"unknown",
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
language:
|
|
242
|
-
|
|
243
|
-
null
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
module.exports = {
|
|
267
|
-
|
|
268
|
-
getInfo
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const NodeBB = require("./index");
|
|
4
|
+
|
|
5
|
+
async function getInfo() {
|
|
6
|
+
const meta = NodeBB.get("meta");
|
|
7
|
+
|
|
8
|
+
if (!meta.configs || typeof meta.configs.list !== "function") {
|
|
9
|
+
throw new Error("NodeBB meta.configs.list is unavailable");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const config = await meta.configs.list();
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
title: config.title || "",
|
|
16
|
+
url: config.url || "",
|
|
17
|
+
version: config.version || "",
|
|
18
|
+
language: config.language || null
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
getInfo
|
|
24
|
+
};
|