nodebb-plugin-integration 0.4.4 → 0.6.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 +156 -145
- package/README.ru.md +147 -136
- package/docs/MCP.md +718 -0
- package/docs/MCP.ru.md +719 -0
- package/package.json +3 -2
- package/src/mcp/server.js +32 -28
- package/src/mcp/tools.js +294 -76
- package/src/nodebb/posts.js +72 -21
- package/src/nodebb/topics.js +121 -24
- package/src/nodebb/users.js +19 -4
- package/src/routes/api.js +297 -35
- package/src/routes/index.js +24 -31
package/src/nodebb/posts.js
CHANGED
|
@@ -3,18 +3,10 @@
|
|
|
3
3
|
const NodeBB = require("./index");
|
|
4
4
|
|
|
5
5
|
const META_FIELDS = [
|
|
6
|
-
"pid",
|
|
7
|
-
"tid",
|
|
8
|
-
"uid",
|
|
9
|
-
"timestamp",
|
|
10
|
-
"deleted",
|
|
11
|
-
"cid"
|
|
6
|
+
"pid", "tid", "uid", "timestamp", "deleted", "cid"
|
|
12
7
|
];
|
|
13
8
|
|
|
14
|
-
const CONTENT_FIELDS = [
|
|
15
|
-
"pid",
|
|
16
|
-
"content"
|
|
17
|
-
];
|
|
9
|
+
const CONTENT_FIELDS = ["pid", "content"];
|
|
18
10
|
|
|
19
11
|
function validatePid(pid) {
|
|
20
12
|
pid = Number(pid);
|
|
@@ -26,9 +18,18 @@ function validatePid(pid) {
|
|
|
26
18
|
return pid;
|
|
27
19
|
}
|
|
28
20
|
|
|
21
|
+
function validateUid(uid) {
|
|
22
|
+
uid = Number(uid);
|
|
23
|
+
|
|
24
|
+
if (!Number.isSafeInteger(uid) || uid <= 0) {
|
|
25
|
+
throw new TypeError("Invalid user ID");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return uid;
|
|
29
|
+
}
|
|
30
|
+
|
|
29
31
|
async function getPostMeta(pid) {
|
|
30
32
|
pid = validatePid(pid);
|
|
31
|
-
|
|
32
33
|
const posts = NodeBB.get("posts");
|
|
33
34
|
|
|
34
35
|
if (typeof posts.getPostFields !== "function") {
|
|
@@ -40,7 +41,6 @@ async function getPostMeta(pid) {
|
|
|
40
41
|
|
|
41
42
|
async function getPostContent(pid) {
|
|
42
43
|
pid = validatePid(pid);
|
|
43
|
-
|
|
44
44
|
const posts = NodeBB.get("posts");
|
|
45
45
|
|
|
46
46
|
if (typeof posts.getPostFields !== "function") {
|
|
@@ -61,17 +61,13 @@ async function getPosts(pids = [], uid) {
|
|
|
61
61
|
throw new TypeError("Invalid user ID");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
const unique = [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.map(Number)
|
|
68
|
-
.filter(pid => Number.isSafeInteger(pid) && pid > 0)
|
|
64
|
+
const unique = [...new Set(
|
|
65
|
+
pids.map(Number).filter(
|
|
66
|
+
pid => Number.isSafeInteger(pid) && pid > 0
|
|
69
67
|
)
|
|
70
|
-
];
|
|
68
|
+
)];
|
|
71
69
|
|
|
72
|
-
if (!unique.length)
|
|
73
|
-
return [];
|
|
74
|
-
}
|
|
70
|
+
if (!unique.length) return [];
|
|
75
71
|
|
|
76
72
|
const posts = NodeBB.get("posts");
|
|
77
73
|
|
|
@@ -84,10 +80,65 @@ async function getPosts(pids = [], uid) {
|
|
|
84
80
|
return result.posts || result;
|
|
85
81
|
}
|
|
86
82
|
|
|
83
|
+
async function editPost(pid, uid, content) {
|
|
84
|
+
pid = validatePid(pid);
|
|
85
|
+
uid = validateUid(uid);
|
|
86
|
+
|
|
87
|
+
const posts = NodeBB.get("posts");
|
|
88
|
+
|
|
89
|
+
if (typeof posts.edit !== "function") {
|
|
90
|
+
throw new Error("NodeBB posts.edit is unavailable");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return posts.edit({ pid, uid, content });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function deletePost(pid, uid) {
|
|
97
|
+
pid = validatePid(pid);
|
|
98
|
+
uid = validateUid(uid);
|
|
99
|
+
|
|
100
|
+
const posts = NodeBB.get("posts");
|
|
101
|
+
|
|
102
|
+
if (!posts.tools || typeof posts.tools.delete !== "function") {
|
|
103
|
+
throw new Error("NodeBB posts.tools.delete is unavailable");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return posts.tools.delete(uid, pid);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function restorePost(pid, uid) {
|
|
110
|
+
pid = validatePid(pid);
|
|
111
|
+
uid = validateUid(uid);
|
|
112
|
+
|
|
113
|
+
const posts = NodeBB.get("posts");
|
|
114
|
+
|
|
115
|
+
if (!posts.tools || typeof posts.tools.restore !== "function") {
|
|
116
|
+
throw new Error("NodeBB posts.tools.restore is unavailable");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return posts.tools.restore(uid, pid);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function getUserPostIds(uid, start, stop) {
|
|
123
|
+
uid = validateUid(uid);
|
|
124
|
+
|
|
125
|
+
const users = NodeBB.get("users");
|
|
126
|
+
|
|
127
|
+
if (typeof users.getPostIds !== "function") {
|
|
128
|
+
throw new Error("NodeBB users.getPostIds is unavailable");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return users.getPostIds(uid, start, stop);
|
|
132
|
+
}
|
|
133
|
+
|
|
87
134
|
module.exports = {
|
|
88
135
|
getPostMeta,
|
|
89
136
|
getPostContent,
|
|
90
137
|
getPosts,
|
|
138
|
+
editPost,
|
|
139
|
+
deletePost,
|
|
140
|
+
restorePost,
|
|
141
|
+
getUserPostIds,
|
|
91
142
|
META_FIELDS,
|
|
92
143
|
CONTENT_FIELDS
|
|
93
144
|
};
|
package/src/nodebb/topics.js
CHANGED
|
@@ -3,22 +3,19 @@
|
|
|
3
3
|
const NodeBB = require("./index");
|
|
4
4
|
|
|
5
5
|
const FIELDS = [
|
|
6
|
-
"tid",
|
|
7
|
-
"uid",
|
|
8
|
-
"title",
|
|
9
|
-
"cid",
|
|
10
|
-
"timestamp",
|
|
11
|
-
"mainPid",
|
|
12
|
-
"deleted"
|
|
6
|
+
"tid", "uid", "title", "cid", "timestamp", "mainPid", "deleted", "postcount"
|
|
13
7
|
];
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
throw new TypeError("Invalid topic ID");
|
|
9
|
+
function validId(value, name) {
|
|
10
|
+
const id = Number(value);
|
|
11
|
+
if (!Number.isSafeInteger(id) || id <= 0) {
|
|
12
|
+
throw new TypeError(`Invalid ${name}`);
|
|
20
13
|
}
|
|
14
|
+
return id;
|
|
15
|
+
}
|
|
21
16
|
|
|
17
|
+
async function getTopic(tid) {
|
|
18
|
+
tid = validId(tid, "topic ID");
|
|
22
19
|
const topics = NodeBB.get("topics");
|
|
23
20
|
|
|
24
21
|
if (typeof topics.getTopicFields !== "function") {
|
|
@@ -28,13 +25,19 @@ async function getTopic(tid) {
|
|
|
28
25
|
return topics.getTopicFields(tid, FIELDS);
|
|
29
26
|
}
|
|
30
27
|
|
|
31
|
-
async function
|
|
32
|
-
tid =
|
|
28
|
+
async function getTopicData(tid) {
|
|
29
|
+
tid = validId(tid, "topic ID");
|
|
30
|
+
const topics = NodeBB.get("topics");
|
|
33
31
|
|
|
34
|
-
if (
|
|
35
|
-
throw new
|
|
32
|
+
if (typeof topics.getTopicData !== "function") {
|
|
33
|
+
throw new Error("NodeBB topics.getTopicData is unavailable");
|
|
36
34
|
}
|
|
37
35
|
|
|
36
|
+
return topics.getTopicData(tid);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function getTopicPids(tid) {
|
|
40
|
+
tid = validId(tid, "topic ID");
|
|
38
41
|
const topics = NodeBB.get("topics");
|
|
39
42
|
|
|
40
43
|
if (typeof topics.getPids !== "function") {
|
|
@@ -61,9 +64,7 @@ async function getTopics(tids = []) {
|
|
|
61
64
|
)
|
|
62
65
|
)];
|
|
63
66
|
|
|
64
|
-
if (!unique.length)
|
|
65
|
-
return [];
|
|
66
|
-
}
|
|
67
|
+
if (!unique.length) return [];
|
|
67
68
|
|
|
68
69
|
const topics = NodeBB.get("topics");
|
|
69
70
|
|
|
@@ -75,18 +76,114 @@ async function getTopics(tids = []) {
|
|
|
75
76
|
|
|
76
77
|
for (const tid of unique) {
|
|
77
78
|
const topic = await getTopic(tid);
|
|
78
|
-
|
|
79
|
-
if (topic) {
|
|
80
|
-
result.push(topic);
|
|
81
|
-
}
|
|
79
|
+
if (topic) result.push(topic);
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
return result;
|
|
85
83
|
}
|
|
86
84
|
|
|
85
|
+
async function createTopic(data) {
|
|
86
|
+
const topics = NodeBB.get("topics");
|
|
87
|
+
|
|
88
|
+
if (typeof topics.post !== "function") {
|
|
89
|
+
throw new Error("NodeBB topics.post is unavailable");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return topics.post(data);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function createReply(data) {
|
|
96
|
+
const topics = NodeBB.get("topics");
|
|
97
|
+
|
|
98
|
+
if (typeof topics.reply !== "function") {
|
|
99
|
+
throw new Error("NodeBB topics.reply is unavailable");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return topics.reply(data);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function deleteTopic(tid, uid) {
|
|
106
|
+
tid = validId(tid, "topic ID");
|
|
107
|
+
uid = validId(uid, "user ID");
|
|
108
|
+
|
|
109
|
+
const topics = NodeBB.get("topics");
|
|
110
|
+
|
|
111
|
+
if (!topics.tools || typeof topics.tools.delete !== "function") {
|
|
112
|
+
throw new Error("NodeBB topics.tools.delete is unavailable");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return topics.tools.delete(tid, uid);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function restoreTopic(tid, uid) {
|
|
119
|
+
tid = validId(tid, "topic ID");
|
|
120
|
+
uid = validId(uid, "user ID");
|
|
121
|
+
|
|
122
|
+
const topics = NodeBB.get("topics");
|
|
123
|
+
|
|
124
|
+
if (!topics.tools || typeof topics.tools.restore !== "function") {
|
|
125
|
+
throw new Error("NodeBB topics.tools.restore is unavailable");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return topics.tools.restore(tid, uid);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function listTopics(options) {
|
|
132
|
+
const topics = NodeBB.get("topics");
|
|
133
|
+
|
|
134
|
+
if (typeof topics.getSortedTopics !== "function") {
|
|
135
|
+
throw new Error("NodeBB topics.getSortedTopics is unavailable");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const params = {
|
|
139
|
+
uid: validId(options.uid, "user ID"),
|
|
140
|
+
start: options.start,
|
|
141
|
+
stop: options.stop,
|
|
142
|
+
sort: options.sort || "recent"
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
if (options.cid !== undefined) {
|
|
146
|
+
params.cids = validId(options.cid, "category ID");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return topics.getSortedTopics(params);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function getTopicPosts(tid, uid, start, limit, reverse = false) {
|
|
153
|
+
tid = validId(tid, "topic ID");
|
|
154
|
+
uid = validId(uid, "user ID");
|
|
155
|
+
|
|
156
|
+
const topics = NodeBB.get("topics");
|
|
157
|
+
const topicData = await getTopicData(tid);
|
|
158
|
+
|
|
159
|
+
if (!topicData) return [];
|
|
160
|
+
|
|
161
|
+
if (typeof topics.getTopicPosts !== "function") {
|
|
162
|
+
throw new Error("NodeBB topics.getTopicPosts is unavailable");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const stop = start + limit - 1;
|
|
166
|
+
|
|
167
|
+
return topics.getTopicPosts(
|
|
168
|
+
topicData,
|
|
169
|
+
`tid:${tid}:posts`,
|
|
170
|
+
start,
|
|
171
|
+
stop,
|
|
172
|
+
uid,
|
|
173
|
+
Boolean(reverse)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
87
177
|
module.exports = {
|
|
88
178
|
getTopic,
|
|
179
|
+
getTopicData,
|
|
89
180
|
getTopics,
|
|
90
181
|
getTopicPids,
|
|
182
|
+
createTopic,
|
|
183
|
+
createReply,
|
|
184
|
+
deleteTopic,
|
|
185
|
+
restoreTopic,
|
|
186
|
+
listTopics,
|
|
187
|
+
getTopicPosts,
|
|
91
188
|
FIELDS
|
|
92
|
-
};
|
|
189
|
+
};
|
package/src/nodebb/users.js
CHANGED
|
@@ -36,9 +36,7 @@ async function getUsers(uids = []) {
|
|
|
36
36
|
)
|
|
37
37
|
)];
|
|
38
38
|
|
|
39
|
-
if (!unique.length)
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
39
|
+
if (!unique.length) return [];
|
|
42
40
|
|
|
43
41
|
const users = NodeBB.get("users");
|
|
44
42
|
|
|
@@ -56,8 +54,25 @@ async function getUsers(uids = []) {
|
|
|
56
54
|
return result;
|
|
57
55
|
}
|
|
58
56
|
|
|
57
|
+
async function getPostIds(uid, start, stop) {
|
|
58
|
+
uid = Number(uid);
|
|
59
|
+
|
|
60
|
+
if (!Number.isSafeInteger(uid) || uid <= 0) {
|
|
61
|
+
throw new TypeError("Invalid user ID");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const users = NodeBB.get("users");
|
|
65
|
+
|
|
66
|
+
if (typeof users.getPostIds !== "function") {
|
|
67
|
+
throw new Error("NodeBB users.getPostIds is unavailable");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return users.getPostIds(uid, start, stop);
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
module.exports = {
|
|
60
74
|
getUser,
|
|
61
75
|
getUsers,
|
|
76
|
+
getPostIds,
|
|
62
77
|
FIELDS
|
|
63
|
-
};
|
|
78
|
+
};
|