koishi-plugin-echo-cave 1.7.3 → 1.7.5
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/lib/cave-helper.d.ts +4 -0
- package/lib/index.cjs +122 -90
- package/lib/msg-helper.d.ts +3 -4
- package/package.json +9 -11
package/lib/index.cjs
CHANGED
|
@@ -36,74 +36,6 @@ __export(index_exports, {
|
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(index_exports);
|
|
38
38
|
var import_koishi_plugin_adapter_onebot = require("@pynickle/koishi-plugin-adapter-onebot");
|
|
39
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
40
|
-
var import_koishi = require("koishi");
|
|
41
|
-
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
42
|
-
|
|
43
|
-
// src/image-helper.ts
|
|
44
|
-
var import_node_fs = require("node:fs");
|
|
45
|
-
var import_node_path = __toESM(require("node:path"), 1);
|
|
46
|
-
async function saveImages(ctx, imgElement) {
|
|
47
|
-
const imgUrl = imgElement.url;
|
|
48
|
-
const originalImgName = imgElement.file;
|
|
49
|
-
const lastDotIndex = originalImgName.lastIndexOf(".");
|
|
50
|
-
let imgExt = "";
|
|
51
|
-
if (lastDotIndex === -1) {
|
|
52
|
-
imgExt = "png";
|
|
53
|
-
} else {
|
|
54
|
-
imgExt = originalImgName.substring(lastDotIndex + 1);
|
|
55
|
-
}
|
|
56
|
-
const imgPath = import_node_path.default.join(ctx.baseDir, "data", "cave", "images");
|
|
57
|
-
const imgName = (/* @__PURE__ */ new Date()).getTime().toString();
|
|
58
|
-
let fullImgPath = import_node_path.default.join(imgPath, `${imgName}.${imgExt}`);
|
|
59
|
-
ctx.logger.info(
|
|
60
|
-
`Saving image from URL: ${imgUrl} to path: ${imgName}.${imgExt}`
|
|
61
|
-
);
|
|
62
|
-
const buffer = await ctx.http.get(imgUrl);
|
|
63
|
-
if (buffer.byteLength === 0) throw new Error("Image download failed");
|
|
64
|
-
await import_node_fs.promises.writeFile(fullImgPath, Buffer.from(buffer));
|
|
65
|
-
return fullImgPath;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/forward-helper.ts
|
|
69
|
-
async function reconstructForwardMsg(ctx, message) {
|
|
70
|
-
return Promise.all(
|
|
71
|
-
message.map(async (msg) => {
|
|
72
|
-
const content = await processMessageContent(ctx, msg);
|
|
73
|
-
return {
|
|
74
|
-
type: "node",
|
|
75
|
-
data: {
|
|
76
|
-
user_id: msg.sender.user_id,
|
|
77
|
-
nickname: msg.sender.nickname,
|
|
78
|
-
content
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
})
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
async function processMessageContent(ctx, msg) {
|
|
85
|
-
if (typeof msg.message === "string") {
|
|
86
|
-
return msg.message;
|
|
87
|
-
}
|
|
88
|
-
const firstElement = msg.message[0];
|
|
89
|
-
if (firstElement?.type === "forward") {
|
|
90
|
-
return reconstructForwardMsg(ctx, firstElement.data.content);
|
|
91
|
-
}
|
|
92
|
-
return Promise.all(
|
|
93
|
-
msg.message.map(async (element) => {
|
|
94
|
-
if (element.type === "image") {
|
|
95
|
-
return {
|
|
96
|
-
...element,
|
|
97
|
-
data: {
|
|
98
|
-
...element.data,
|
|
99
|
-
url: await saveImages(ctx, element.data)
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return element;
|
|
104
|
-
})
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
39
|
|
|
108
40
|
// src/cqcode-helper.ts
|
|
109
41
|
function createTextMsg(content) {
|
|
@@ -118,10 +50,7 @@ function createTextMsg(content) {
|
|
|
118
50
|
// src/onebot-helper.ts
|
|
119
51
|
async function getUserName(ctx, session, userId) {
|
|
120
52
|
try {
|
|
121
|
-
const memberInfo = await session.onebot.getGroupMemberInfo(
|
|
122
|
-
session.channelId,
|
|
123
|
-
userId
|
|
124
|
-
);
|
|
53
|
+
const memberInfo = await session.onebot.getGroupMemberInfo(session.channelId, userId);
|
|
125
54
|
return memberInfo.card || memberInfo.nickname || userId;
|
|
126
55
|
} catch (error) {
|
|
127
56
|
ctx.logger.warn(`\u83B7\u53D6\u7FA4\u6210\u5458\u4FE1\u606F\u5931\u8D25\uFF08userId: ${userId}\uFF09\uFF1A`, error);
|
|
@@ -129,7 +58,7 @@ async function getUserName(ctx, session, userId) {
|
|
|
129
58
|
}
|
|
130
59
|
}
|
|
131
60
|
|
|
132
|
-
// src/
|
|
61
|
+
// src/cave-helper.ts
|
|
133
62
|
async function sendCaveMsg(ctx, session, caveMsg) {
|
|
134
63
|
const { channelId } = session;
|
|
135
64
|
const content = JSON.parse(caveMsg.content);
|
|
@@ -226,9 +155,7 @@ async function sendCaveMsg(ctx, session, caveMsg) {
|
|
|
226
155
|
const last = content.at(-1);
|
|
227
156
|
const needsNewline = last?.type === "text";
|
|
228
157
|
content.unshift(createTextMsg(chosen.prefix));
|
|
229
|
-
content.push(
|
|
230
|
-
createTextMsg(`${needsNewline ? "\n\n" : ""}${chosen.suffix}`)
|
|
231
|
-
);
|
|
158
|
+
content.push(createTextMsg(`${needsNewline ? "\n\n" : ""}${chosen.suffix}`));
|
|
232
159
|
await session.onebot.sendGroupMsg(channelId, content);
|
|
233
160
|
}
|
|
234
161
|
function formatDate(date) {
|
|
@@ -239,13 +166,117 @@ function formatDate(date) {
|
|
|
239
166
|
});
|
|
240
167
|
}
|
|
241
168
|
|
|
169
|
+
// src/image-helper.ts
|
|
170
|
+
var import_axios = __toESM(require("axios"), 1);
|
|
171
|
+
var import_node_fs = require("node:fs");
|
|
172
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
173
|
+
async function saveImages(ctx, imgElement) {
|
|
174
|
+
const imgUrl = imgElement.url;
|
|
175
|
+
const originalImgName = imgElement.file;
|
|
176
|
+
const ext = (() => {
|
|
177
|
+
const i = originalImgName.lastIndexOf(".");
|
|
178
|
+
return i === -1 ? "png" : originalImgName.slice(i + 1).toLowerCase();
|
|
179
|
+
})();
|
|
180
|
+
const imgDir = import_node_path.default.join(ctx.baseDir, "data", "cave", "images");
|
|
181
|
+
const imgName = Date.now().toString();
|
|
182
|
+
const fullImgPath = import_node_path.default.join(imgDir, `${imgName}.${ext}`);
|
|
183
|
+
ctx.logger.info(`Saving image from ${imgUrl} -> ${fullImgPath}`);
|
|
184
|
+
try {
|
|
185
|
+
await import_node_fs.promises.mkdir(imgDir, { recursive: true });
|
|
186
|
+
const res = await import_axios.default.get(imgUrl, {
|
|
187
|
+
responseType: "arraybuffer",
|
|
188
|
+
validateStatus: () => true
|
|
189
|
+
});
|
|
190
|
+
if (res.status < 200 || res.status >= 300) {
|
|
191
|
+
ctx.logger.warn(`Image download failed: HTTP ${res.status}`);
|
|
192
|
+
return imgUrl;
|
|
193
|
+
}
|
|
194
|
+
const type = res.headers["content-type"];
|
|
195
|
+
if (!type || !type.startsWith("image/")) {
|
|
196
|
+
ctx.logger.warn(`Invalid image content-type: ${type}`);
|
|
197
|
+
return imgUrl;
|
|
198
|
+
}
|
|
199
|
+
const buffer = Buffer.from(res.data);
|
|
200
|
+
if (!buffer || buffer.length === 0) {
|
|
201
|
+
ctx.logger.warn("Downloaded image buffer is empty");
|
|
202
|
+
return imgUrl;
|
|
203
|
+
}
|
|
204
|
+
await import_node_fs.promises.writeFile(fullImgPath, buffer);
|
|
205
|
+
ctx.logger.info(`Image saved successfully: ${fullImgPath}`);
|
|
206
|
+
return fullImgPath;
|
|
207
|
+
} catch (err) {
|
|
208
|
+
ctx.logger.error(`Failed to save image: ${err}`);
|
|
209
|
+
return imgUrl;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// src/forward-helper.ts
|
|
214
|
+
async function reconstructForwardMsg(ctx, message) {
|
|
215
|
+
return Promise.all(
|
|
216
|
+
message.map(async (msg) => {
|
|
217
|
+
const content = await processForwardMessageContent(ctx, msg);
|
|
218
|
+
return {
|
|
219
|
+
type: "node",
|
|
220
|
+
data: {
|
|
221
|
+
user_id: msg.sender.user_id,
|
|
222
|
+
nickname: msg.sender.nickname,
|
|
223
|
+
content
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
})
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
async function processForwardMessageContent(ctx, msg) {
|
|
230
|
+
if (typeof msg.message === "string") {
|
|
231
|
+
return msg.message;
|
|
232
|
+
}
|
|
233
|
+
const firstElement = msg.message[0];
|
|
234
|
+
if (firstElement?.type === "forward") {
|
|
235
|
+
return reconstructForwardMsg(ctx, firstElement.data.content);
|
|
236
|
+
}
|
|
237
|
+
return Promise.all(
|
|
238
|
+
msg.message.map(async (element) => {
|
|
239
|
+
if (element.type === "image") {
|
|
240
|
+
return {
|
|
241
|
+
...element,
|
|
242
|
+
data: {
|
|
243
|
+
...element.data,
|
|
244
|
+
url: await saveImages(ctx, element.data)
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
return element;
|
|
249
|
+
})
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/msg-helper.ts
|
|
254
|
+
async function processMessageContent(ctx, msg) {
|
|
255
|
+
return Promise.all(
|
|
256
|
+
msg.map(async (element) => {
|
|
257
|
+
if (element.type === "image") {
|
|
258
|
+
return {
|
|
259
|
+
...element,
|
|
260
|
+
data: {
|
|
261
|
+
...element.data,
|
|
262
|
+
url: await saveImages(ctx, element.data)
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return element;
|
|
267
|
+
})
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
242
271
|
// src/index.ts
|
|
272
|
+
var import_koishi_plugin_adapter_onebot2 = require("@pynickle/koishi-plugin-adapter-onebot");
|
|
273
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
274
|
+
var import_koishi = require("koishi");
|
|
275
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
243
276
|
var name = "echo-cave";
|
|
244
277
|
var inject = ["database"];
|
|
245
278
|
var Config = import_koishi.Schema.object({
|
|
246
|
-
adminMessageProtection: import_koishi.Schema.boolean().description(
|
|
247
|
-
"\u5F00\u542F\u7BA1\u7406\u5458\u6D88\u606F\u4FDD\u62A4\uFF0C\u5F00\u542F\u540E\u7BA1\u7406\u5458\u53D1\u5E03\u7684\u6D88\u606F\u53EA\u80FD\u7531\u7BA1\u7406\u5458\u5220\u9664"
|
|
248
|
-
).default(false)
|
|
279
|
+
adminMessageProtection: import_koishi.Schema.boolean().description("\u5F00\u542F\u7BA1\u7406\u5458\u6D88\u606F\u4FDD\u62A4\uFF0C\u5F00\u542F\u540E\u7BA1\u7406\u5458\u53D1\u5E03\u7684\u6D88\u606F\u53EA\u80FD\u7531\u7BA1\u7406\u5458\u5220\u9664").default(false)
|
|
249
280
|
});
|
|
250
281
|
function apply(ctx, cfg) {
|
|
251
282
|
const imgPath = import_node_path2.default.join(ctx.baseDir, "data", "cave", "images");
|
|
@@ -269,10 +300,9 @@ function apply(ctx, cfg) {
|
|
|
269
300
|
unique: ["content"]
|
|
270
301
|
}
|
|
271
302
|
);
|
|
272
|
-
ctx.command(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
).action(async ({ session }, id) => await getCave(ctx, session, id));
|
|
303
|
+
ctx.command("cave [id:number]", "\u968F\u673A\u83B7\u53D6 / \u83B7\u53D6\u7279\u5B9A id \u7684\u56DE\u58F0\u6D1E\u4FE1\u606F").action(
|
|
304
|
+
async ({ session }, id) => await getCave(ctx, session, id)
|
|
305
|
+
);
|
|
276
306
|
ctx.command("cave.echo", "\u5C06\u6D88\u606F\u5B58\u5165\u56DE\u58F0\u6D1E").action(
|
|
277
307
|
async ({ session }) => await addCave(ctx, session)
|
|
278
308
|
);
|
|
@@ -369,10 +399,7 @@ async function deleteCave(ctx, session, cfg, id) {
|
|
|
369
399
|
const userAuthority = user.authority;
|
|
370
400
|
const isCurrentUserAdmin = userAuthority >= 4;
|
|
371
401
|
if (cfg.adminMessageProtection) {
|
|
372
|
-
const caveUser = await ctx.database.getUser(
|
|
373
|
-
session.platform,
|
|
374
|
-
caveMsg.userId
|
|
375
|
-
);
|
|
402
|
+
const caveUser = await ctx.database.getUser(session.platform, caveMsg.userId);
|
|
376
403
|
const isCaveUserAdmin = caveUser.authority >= 4;
|
|
377
404
|
if (isCaveUserAdmin && !isCurrentUserAdmin) {
|
|
378
405
|
return "\u26D4 \u8BE5\u6D88\u606F\u7531\u7BA1\u7406\u5458\u53D1\u5E03\uFF0C\u5DF2\u5F00\u542F\u7BA1\u7406\u5458\u6D88\u606F\u4FDD\u62A4\uFF0C\u53EA\u6709\u7BA1\u7406\u5458\u53EF\u4EE5\u5220\u9664\u3002";
|
|
@@ -404,9 +431,14 @@ async function addCave(ctx, session) {
|
|
|
404
431
|
content = JSON.stringify(message);
|
|
405
432
|
} else {
|
|
406
433
|
type = "msg";
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
)
|
|
434
|
+
const message = (await session.onebot.getMsg(messageId)).message;
|
|
435
|
+
let msgJson;
|
|
436
|
+
if (typeof message === "string") {
|
|
437
|
+
msgJson = import_koishi_plugin_adapter_onebot2.CQCode.parse(message);
|
|
438
|
+
} else {
|
|
439
|
+
msgJson = message;
|
|
440
|
+
}
|
|
441
|
+
content = JSON.stringify(await processMessageContent(ctx, msgJson));
|
|
410
442
|
}
|
|
411
443
|
await ctx.database.get("echo_cave", { content }).then((existing) => {
|
|
412
444
|
if (existing) {
|
package/lib/msg-helper.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function formatDate(date: Date): string;
|
|
1
|
+
import { CQCode } from '@pynickle/koishi-plugin-adapter-onebot';
|
|
2
|
+
import { Context } from 'koishi';
|
|
3
|
+
export declare function processMessageContent(ctx: Context, msg: CQCode[]): Promise<CQCode[]>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-echo-cave",
|
|
3
3
|
"description": "Group echo cave",
|
|
4
|
-
"version": "1.7.
|
|
4
|
+
"version": "1.7.5",
|
|
5
5
|
"main": "lib/index.cjs",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
],
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"scripts": {
|
|
14
|
-
"lint": "
|
|
15
|
-
"lint:fix": "
|
|
14
|
+
"lint": "npx oxlint ./src",
|
|
15
|
+
"lint:fix": "npx oxlint ./src --fix",
|
|
16
|
+
"fmt": "npx oxfmt ./src",
|
|
16
17
|
"build": "node esbuild.config.js && tsc --emitDeclarationOnly",
|
|
17
18
|
"release": "semantic-release"
|
|
18
19
|
},
|
|
@@ -26,7 +27,8 @@
|
|
|
26
27
|
"koishi": "^4.18.9"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
|
-
"@pynickle/koishi-plugin-adapter-onebot": "^1.0.0"
|
|
30
|
+
"@pynickle/koishi-plugin-adapter-onebot": "^1.0.0",
|
|
31
|
+
"axios": "^1.13.2"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
34
|
"@semantic-release/changelog": "^6.0.3",
|
|
@@ -34,17 +36,13 @@
|
|
|
34
36
|
"@semantic-release/git": "^10.0.1",
|
|
35
37
|
"@semantic-release/npm": "^13.1.2",
|
|
36
38
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
37
|
-
"@trivago/prettier-plugin-sort-imports": "^6.0.0",
|
|
38
39
|
"@types/node": "^24.10.1",
|
|
39
40
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
40
41
|
"esbuild": "^0.27.0",
|
|
41
42
|
"esbuild-plugin-yaml": "^0.0.1",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"eslint-plugin-prettier": "^5.5.4",
|
|
45
|
-
"prettier": "^3.7.2",
|
|
43
|
+
"oxfmt": "^0.16.0",
|
|
44
|
+
"oxlint": "^1.31.0",
|
|
46
45
|
"semantic-release": "^25.0.2",
|
|
47
|
-
"typescript": "^5.9.3"
|
|
48
|
-
"typescript-eslint": "^8.48.0"
|
|
46
|
+
"typescript": "^5.9.3"
|
|
49
47
|
}
|
|
50
48
|
}
|