koishi-plugin-onebot-info-image 0.3.1-beta.1 → 0.4.0-beta.3
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/commandAdminList.d.ts +3 -0
- package/lib/commandGroupEssence.d.ts +38 -0
- package/lib/commandGroupEssenceDetail.d.ts +12 -0
- package/lib/commandGroupNotice.d.ts +45 -0
- package/lib/commandGroupNoticeDetail.d.ts +12 -0
- package/lib/commandInspectStyle.d.ts +3 -0
- package/lib/commandUserInfo.d.ts +3 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +3525 -605
- package/lib/renderGroupEssence.d.ts +15 -0
- package/lib/renderGroupEssenceDetail.d.ts +8 -0
- package/lib/renderGroupNotice.d.ts +7 -0
- package/lib/renderGroupNoticeDetail.d.ts +8 -0
- package/package.json +3 -3
- package/readme.md +4 -2
package/lib/index.js
CHANGED
|
@@ -37,9 +37,9 @@ __export(src_exports, {
|
|
|
37
37
|
usage: () => usage
|
|
38
38
|
});
|
|
39
39
|
module.exports = __toCommonJS(src_exports);
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
40
|
+
var import_koishi7 = require("koishi");
|
|
41
|
+
var import_fs3 = require("fs");
|
|
42
|
+
var import_path3 = require("path");
|
|
43
43
|
|
|
44
44
|
// src/type.ts
|
|
45
45
|
var IMAGE_STYLES = {
|
|
@@ -361,6 +361,9 @@ async function validateFonts(ctx) {
|
|
|
361
361
|
}
|
|
362
362
|
__name(validateFonts, "validateFonts");
|
|
363
363
|
|
|
364
|
+
// src/data_server.ts
|
|
365
|
+
var import_plugin_console = require("@koishijs/plugin-console");
|
|
366
|
+
|
|
364
367
|
// src/renderUserInfo.ts
|
|
365
368
|
var formatMsTimestamp = /* @__PURE__ */ __name((timestamp) => {
|
|
366
369
|
if (!timestamp) return '<span class="unknown">未知</span>';
|
|
@@ -451,12 +454,12 @@ var getSourceHanSerifSCStyleUserInfoHtmlStr = /* @__PURE__ */ __name(async (user
|
|
|
451
454
|
</div>
|
|
452
455
|
</div>
|
|
453
456
|
<div class="group-info-body">
|
|
454
|
-
${getGroupInfoItem("群名片", getValue(userInfo.card), "full-width")}
|
|
457
|
+
${getGroupInfoItem("群名片", getValue(userInfo.card, '<span class="unknown">未设置</span>'), "full-width")}
|
|
455
458
|
<div class="group-level-role-row">
|
|
456
459
|
${getGroupInfoItem("群等级", getValue(userInfo.group_level || userInfo.level), "group-level-item")}
|
|
457
460
|
${getGroupInfoItem("群角色", userInfo.role === "owner" ? "群主" : userInfo.role === "admin" ? "管理员" : userInfo.role === "member" ? "成员" : '<span class="unknown">未知</span>', "group-role-item")}
|
|
458
461
|
</div>
|
|
459
|
-
${getGroupInfoItem("专属头衔", getValue(userInfo.title), "full-width")}
|
|
462
|
+
${getGroupInfoItem("专属头衔", getValue(userInfo.title, '<span class="unknown">未设置</span>'), "full-width")}
|
|
460
463
|
<div class="group-time-row">
|
|
461
464
|
${getGroupInfoItem("加群时间", formatMsTimestamp(userInfo.join_time), "join-time-item")}
|
|
462
465
|
${getGroupInfoItem("最后发言", formatMsTimestamp(userInfo.last_sent_time || userInfo.lastSentTime || userInfo.last_speak_time), "last-speak-item")}
|
|
@@ -887,7 +890,7 @@ body {
|
|
|
887
890
|
<div class="group-details">
|
|
888
891
|
<div class="group-detail-item">
|
|
889
892
|
<div class="group-detail-label">群名片</div>
|
|
890
|
-
<div class="group-detail-value">${userInfo.card || "
|
|
893
|
+
<div class="group-detail-value">${userInfo.card || '<span class="unknown">未设置</span>'}</div>
|
|
891
894
|
</div>
|
|
892
895
|
<div class="group-detail-item">
|
|
893
896
|
<div class="group-detail-label">群角色</div>
|
|
@@ -899,7 +902,7 @@ body {
|
|
|
899
902
|
</div>
|
|
900
903
|
<div class="group-detail-item">
|
|
901
904
|
<div class="group-detail-label">专属头衔</div>
|
|
902
|
-
<div class="group-detail-value accent-color">${userInfo.title || "
|
|
905
|
+
<div class="group-detail-value accent-color">${userInfo.title || '<span class="unknown">无</span>'}</div>
|
|
903
906
|
</div>
|
|
904
907
|
<div class="group-detail-item">
|
|
905
908
|
<div class="group-detail-label">加群时间</div>
|
|
@@ -1089,7 +1092,7 @@ ${contextInfo.memberCount ? `<div class="group-member-count">群人数: ${contex
|
|
|
1089
1092
|
</div>
|
|
1090
1093
|
</div>
|
|
1091
1094
|
<div class="group-info-grid">
|
|
1092
|
-
<div class="group-info-card full-width"><div class="info-label">群名片</div><div class="info-value">${userInfo.card || '<span class="unknown"
|
|
1095
|
+
<div class="group-info-card full-width"><div class="info-label">群名片</div><div class="info-value">${userInfo.card || '<span class="unknown">未设置</span>'}</div></div>
|
|
1093
1096
|
<div class="group-info-card"><div class="info-label">群等级</div><div class="info-value">${userInfo.group_level || '<span class="unknown">未知</span>'}</div></div>
|
|
1094
1097
|
<div class="group-info-card"><div class="info-label">群角色</div><div class="info-value">${getGroupRole(userInfo.role)}</div></div>
|
|
1095
1098
|
<div class="group-info-card full-width"><div class="info-label">专属头衔</div><div class="info-value">${userInfo.title || '<span class="unknown">未获取</span>'}</div></div>
|
|
@@ -1169,8 +1172,8 @@ async function renderUserInfo(ctx, userInfo, contextInfo, imageStyle, enableDark
|
|
|
1169
1172
|
const images = Array.from(document.querySelectorAll("img"));
|
|
1170
1173
|
await Promise.all(images.map((img) => {
|
|
1171
1174
|
if (img.complete) return;
|
|
1172
|
-
return new Promise((
|
|
1173
|
-
img.addEventListener("load",
|
|
1175
|
+
return new Promise((resolve4, reject) => {
|
|
1176
|
+
img.addEventListener("load", resolve4);
|
|
1174
1177
|
img.addEventListener("error", reject);
|
|
1175
1178
|
});
|
|
1176
1179
|
}));
|
|
@@ -1197,6 +1200,427 @@ async function renderUserInfo(ctx, userInfo, contextInfo, imageStyle, enableDark
|
|
|
1197
1200
|
}
|
|
1198
1201
|
__name(renderUserInfo, "renderUserInfo");
|
|
1199
1202
|
|
|
1203
|
+
// src/data_server.ts
|
|
1204
|
+
var path = __toESM(require("path"));
|
|
1205
|
+
var OnebotInfoImageDataServer = class extends import_plugin_console.DataService {
|
|
1206
|
+
static {
|
|
1207
|
+
__name(this, "OnebotInfoImageDataServer");
|
|
1208
|
+
}
|
|
1209
|
+
fontsBase64 = {
|
|
1210
|
+
sourceHanSerif: "",
|
|
1211
|
+
lxgwWenKai: ""
|
|
1212
|
+
};
|
|
1213
|
+
fontLoaded = false;
|
|
1214
|
+
currentTemplate = "sourceHanSerif";
|
|
1215
|
+
currentFont = "sourceHanSerif";
|
|
1216
|
+
currentDarkMode = true;
|
|
1217
|
+
static inject = ["console"];
|
|
1218
|
+
constructor(ctx) {
|
|
1219
|
+
super(ctx, "onebot-info-image", { immediate: true });
|
|
1220
|
+
this.loadFonts();
|
|
1221
|
+
ctx.console.addEntry({
|
|
1222
|
+
dev: path.resolve(__dirname, "../client/index.ts"),
|
|
1223
|
+
prod: path.resolve(__dirname, "../dist")
|
|
1224
|
+
});
|
|
1225
|
+
ctx.console.addListener("onebot-info-image/refresh", async () => {
|
|
1226
|
+
await this.refresh();
|
|
1227
|
+
}, { authority: 0 });
|
|
1228
|
+
ctx.console.addListener("onebot-info-image/setTemplate", async (template) => {
|
|
1229
|
+
this.currentTemplate = template;
|
|
1230
|
+
await this.refresh();
|
|
1231
|
+
}, { authority: 0 });
|
|
1232
|
+
ctx.console.addListener("onebot-info-image/setFont", async (font) => {
|
|
1233
|
+
this.currentFont = font;
|
|
1234
|
+
await this.refresh();
|
|
1235
|
+
}, { authority: 0 });
|
|
1236
|
+
ctx.console.addListener("onebot-info-image/setDarkMode", async (darkMode) => {
|
|
1237
|
+
this.currentDarkMode = darkMode;
|
|
1238
|
+
await this.refresh();
|
|
1239
|
+
}, { authority: 0 });
|
|
1240
|
+
ctx.on("bot-status-updated", async () => {
|
|
1241
|
+
await this.refresh();
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
async loadFonts() {
|
|
1245
|
+
try {
|
|
1246
|
+
await validateFonts(this.ctx);
|
|
1247
|
+
this.fontsBase64.sourceHanSerif = await getFontBase64(this.ctx, IMAGE_STYLES.SOURCE_HAN_SERIF_SC);
|
|
1248
|
+
this.fontsBase64.lxgwWenKai = await getFontBase64(this.ctx, IMAGE_STYLES.LXGW_WENKAI);
|
|
1249
|
+
this.fontLoaded = true;
|
|
1250
|
+
this.ctx.logger("onebot-info-image").info("字体加载完成");
|
|
1251
|
+
await this.refresh();
|
|
1252
|
+
} catch (e) {
|
|
1253
|
+
this.ctx.logger("onebot-info-image").warn("加载字体失败:", e);
|
|
1254
|
+
this.fontLoaded = true;
|
|
1255
|
+
await this.refresh();
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
getHtmlGenerator(template) {
|
|
1259
|
+
switch (template) {
|
|
1260
|
+
case "sourceHanSerif":
|
|
1261
|
+
return getSourceHanSerifSCStyleUserInfoHtmlStr;
|
|
1262
|
+
case "flatMinimal":
|
|
1263
|
+
return getFlatMinimalUserInfoHtmlStr;
|
|
1264
|
+
case "lxgwWenKai":
|
|
1265
|
+
return getLXGWWenKaiUserInfoHtmlStr;
|
|
1266
|
+
default:
|
|
1267
|
+
return getSourceHanSerifSCStyleUserInfoHtmlStr;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
async get() {
|
|
1271
|
+
try {
|
|
1272
|
+
if (!this.fontLoaded) {
|
|
1273
|
+
return {
|
|
1274
|
+
status: "loading",
|
|
1275
|
+
msg: "正在加载字体..."
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
const onebotBot = this.ctx.bots.find((b) => b.platform === "onebot");
|
|
1279
|
+
if (!onebotBot) {
|
|
1280
|
+
return {
|
|
1281
|
+
status: "no_bot",
|
|
1282
|
+
msg: "未找到 OneBot 平台的机器人"
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
const selfId = onebotBot.selfId;
|
|
1286
|
+
const loginInfo = await onebotBot.internal.getLoginInfo();
|
|
1287
|
+
const strangerInfo = await onebotBot.internal.getStrangerInfo(Number(selfId));
|
|
1288
|
+
const avatarUrl = `https://q.qlogo.cn/headimg_dl?dst_uin=${selfId}&spec=640&img_type=jpg`;
|
|
1289
|
+
let avatarBase64 = "";
|
|
1290
|
+
try {
|
|
1291
|
+
const response = await this.ctx.http.get(avatarUrl, { responseType: "arraybuffer" });
|
|
1292
|
+
avatarBase64 = Buffer.from(response).toString("base64");
|
|
1293
|
+
} catch (e) {
|
|
1294
|
+
this.ctx.logger("onebot-info-image").warn("获取头像失败:", e);
|
|
1295
|
+
}
|
|
1296
|
+
const userInfo = {
|
|
1297
|
+
user_id: selfId,
|
|
1298
|
+
nickname: loginInfo.nickname || strangerInfo.nickname,
|
|
1299
|
+
sex: strangerInfo.sex || "",
|
|
1300
|
+
age: strangerInfo.age || 0,
|
|
1301
|
+
sign: strangerInfo.sign,
|
|
1302
|
+
level: strangerInfo.level,
|
|
1303
|
+
login_days: strangerInfo.login_days,
|
|
1304
|
+
qid: strangerInfo.qid
|
|
1305
|
+
};
|
|
1306
|
+
const contextInfo = {
|
|
1307
|
+
isGroup: false
|
|
1308
|
+
};
|
|
1309
|
+
const fontBase64 = this.fontsBase64[this.currentFont] || "";
|
|
1310
|
+
const htmlGenerator = this.getHtmlGenerator(this.currentTemplate);
|
|
1311
|
+
const htmlContent = await htmlGenerator(
|
|
1312
|
+
userInfo,
|
|
1313
|
+
contextInfo,
|
|
1314
|
+
avatarBase64,
|
|
1315
|
+
"",
|
|
1316
|
+
fontBase64,
|
|
1317
|
+
this.currentDarkMode,
|
|
1318
|
+
// 使用当前选择的主题模式
|
|
1319
|
+
true
|
|
1320
|
+
// hidePhoneNumber: 预览中默认隐藏手机号
|
|
1321
|
+
);
|
|
1322
|
+
return {
|
|
1323
|
+
status: "loaded",
|
|
1324
|
+
msg: "加载成功",
|
|
1325
|
+
htmlContent,
|
|
1326
|
+
currentTemplate: this.currentTemplate,
|
|
1327
|
+
currentFont: this.currentFont,
|
|
1328
|
+
currentDarkMode: this.currentDarkMode
|
|
1329
|
+
};
|
|
1330
|
+
} catch (e) {
|
|
1331
|
+
this.ctx.logger("onebot-info-image").error("获取 Bot 信息失败:", e);
|
|
1332
|
+
return {
|
|
1333
|
+
status: "error",
|
|
1334
|
+
msg: `获取失败: ${e.message || e}`
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
|
|
1340
|
+
// src/commandInspectStyle.ts
|
|
1341
|
+
function registerInspectStyleCommand(ctx, config) {
|
|
1342
|
+
ctx.command(config.inspectStyleCommandName, "查看图片样式列表").alias("ais").alias("awa_inspect_style").action(async ({ session }) => {
|
|
1343
|
+
let msg = "用户信息图片样式列表:\n";
|
|
1344
|
+
for (let i = 0; i < config.imageStyleDetails.length; i++) {
|
|
1345
|
+
const o = config.imageStyleDetails[i];
|
|
1346
|
+
msg += ` 【${i}】: ${IMAGE_STYLES[o.styleKey]} ${o.darkMode ? "深色模式" : "浅色模式"} (${o.styleKey})
|
|
1347
|
+
`;
|
|
1348
|
+
}
|
|
1349
|
+
await session.send(msg);
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
__name(registerInspectStyleCommand, "registerInspectStyleCommand");
|
|
1353
|
+
|
|
1354
|
+
// src/commandUserInfo.ts
|
|
1355
|
+
var import_koishi = require("koishi");
|
|
1356
|
+
var import_fs2 = require("fs");
|
|
1357
|
+
var import_path2 = require("path");
|
|
1358
|
+
function registerUserInfoCommand(ctx, config, responseHint) {
|
|
1359
|
+
if (!config.enableUserInfoCommand) return;
|
|
1360
|
+
ctx.command(`${config.userinfoCommandName} [qqId:string]`, `获取用户信息, 发送${responseHint}`).alias("aui").alias("awa_user_info").option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }, qqId) => {
|
|
1361
|
+
if (!session.onebot)
|
|
1362
|
+
return session.send("[error]当前会话不支持onebot协议。");
|
|
1363
|
+
const IMAGE_STYLE_VALUES = Object.values(IMAGE_STYLES);
|
|
1364
|
+
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
1365
|
+
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
1366
|
+
if (options.imageStyleIdx !== void 0) {
|
|
1367
|
+
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
1368
|
+
if (!isIdxValid) {
|
|
1369
|
+
let idxInvalidMsgArr = [
|
|
1370
|
+
`图片样式索引不合法。`,
|
|
1371
|
+
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
1372
|
+
` 当前输入:${options.imageStyleIdx}`,
|
|
1373
|
+
`
|
|
1374
|
+
`,
|
|
1375
|
+
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
1376
|
+
];
|
|
1377
|
+
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
1378
|
+
}
|
|
1379
|
+
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
1380
|
+
}
|
|
1381
|
+
let targetUserId = session.userId;
|
|
1382
|
+
let isDirectQuery = false;
|
|
1383
|
+
if (qqId) {
|
|
1384
|
+
const userIdRegex = /<at id="([^"]+)"(?: name="[^"]*")?\/>/;
|
|
1385
|
+
const match = qqId.match(userIdRegex);
|
|
1386
|
+
if (match) {
|
|
1387
|
+
targetUserId = match[1];
|
|
1388
|
+
isDirectQuery = true;
|
|
1389
|
+
} else {
|
|
1390
|
+
targetUserId = qqId;
|
|
1391
|
+
isDirectQuery = true;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
if (!isDirectQuery) {
|
|
1395
|
+
for (const e of session.event.message.elements) {
|
|
1396
|
+
if (e.type === "at") {
|
|
1397
|
+
targetUserId = e.attrs.id;
|
|
1398
|
+
break;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
const isDirectQueryMsg = `是否直接传入了qq号或者艾特元素作为参数。isDirectQuery = ${isDirectQuery}`;
|
|
1403
|
+
if (config.verboseSessionOutput) await session.send(isDirectQueryMsg);
|
|
1404
|
+
if (config.verboseConsoleOutput) ctx.logger.info(isDirectQueryMsg);
|
|
1405
|
+
const userObj = await session.bot.getUser(targetUserId);
|
|
1406
|
+
let userObjMsg = `userObj =
|
|
1407
|
+
${JSON.stringify(userObj)}`;
|
|
1408
|
+
const userAvatarUrl = userObj.avatar;
|
|
1409
|
+
let userInfoArg = {
|
|
1410
|
+
status: null
|
|
1411
|
+
};
|
|
1412
|
+
let contextInfo = {
|
|
1413
|
+
isGroup: false,
|
|
1414
|
+
groupId: null,
|
|
1415
|
+
groupName: null,
|
|
1416
|
+
groupAvatarUrl: null,
|
|
1417
|
+
memberCount: null,
|
|
1418
|
+
maxMemberCount: null
|
|
1419
|
+
};
|
|
1420
|
+
try {
|
|
1421
|
+
const strangerInfoObj = await session.onebot.getStrangerInfo(targetUserId);
|
|
1422
|
+
let strangerInfoObjMsg = `strangerInfoObj =
|
|
1423
|
+
${JSON.stringify(strangerInfoObj)}`;
|
|
1424
|
+
if (config.verboseSessionOutput) await session.send(strangerInfoObjMsg);
|
|
1425
|
+
if (config.verboseConsoleOutput) ctx.logger.info(strangerInfoObjMsg);
|
|
1426
|
+
let groupMemberInfoObj = void 0;
|
|
1427
|
+
let groupInfoObj = void 0;
|
|
1428
|
+
if (session.guildId) {
|
|
1429
|
+
try {
|
|
1430
|
+
groupMemberInfoObj = await session.onebot.getGroupMemberInfo(session.guildId, targetUserId);
|
|
1431
|
+
let groupMemberInfoObjMsg = `groupMemberInfoObj =
|
|
1432
|
+
${JSON.stringify(groupMemberInfoObj)}`;
|
|
1433
|
+
if (config.verboseSessionOutput) await session.send(groupMemberInfoObjMsg);
|
|
1434
|
+
if (config.verboseConsoleOutput) ctx.logger.info(groupMemberInfoObjMsg);
|
|
1435
|
+
} catch (e) {
|
|
1436
|
+
ctx.logger.warn("获取用户信息失败捏,把groupMemberInfoObj设置成*undefined*好了");
|
|
1437
|
+
}
|
|
1438
|
+
groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
1439
|
+
let groupInfoObjMsg = `groupInfoObj =
|
|
1440
|
+
${JSON.stringify(groupInfoObj)}`;
|
|
1441
|
+
if (config.verboseSessionOutput) await session.send(groupInfoObjMsg);
|
|
1442
|
+
if (config.verboseConsoleOutput) ctx.logger.info(groupInfoObjMsg);
|
|
1443
|
+
userInfoArg = {
|
|
1444
|
+
...groupMemberInfoObj,
|
|
1445
|
+
...strangerInfoObj,
|
|
1446
|
+
// @ts-ignore - strangerInfoObj 实际包含 age 字段,但类型定义中缺失
|
|
1447
|
+
age: strangerInfoObj.age,
|
|
1448
|
+
// @ts-ignore - strangerInfoObj 实际包含 level 字段,但类型定义中缺失 (here ↓)
|
|
1449
|
+
// node_modules/koishi-plugin-adapter-onebot/lib/types.d.ts: export interface StrangerInfo ...
|
|
1450
|
+
level: strangerInfoObj.level,
|
|
1451
|
+
sex: strangerInfoObj.sex,
|
|
1452
|
+
card: groupMemberInfoObj ? groupMemberInfoObj.card : "-",
|
|
1453
|
+
role: groupMemberInfoObj ? groupMemberInfoObj.role : "-",
|
|
1454
|
+
join_time: groupMemberInfoObj ? groupMemberInfoObj.join_time : "-",
|
|
1455
|
+
last_sent_time: groupMemberInfoObj ? groupMemberInfoObj.last_sent_time : "-",
|
|
1456
|
+
group_level: groupMemberInfoObj ? groupMemberInfoObj.level : "-",
|
|
1457
|
+
title: groupMemberInfoObj ? groupMemberInfoObj.title : "这人可能不在群里(",
|
|
1458
|
+
avatar: userObj.avatar
|
|
1459
|
+
};
|
|
1460
|
+
contextInfo = {
|
|
1461
|
+
isGroup: true,
|
|
1462
|
+
groupId: session.guildId,
|
|
1463
|
+
//@ts-ignore - groupInfoObj 在lagrange中 实际包含 GroupName 字段,但类型定义中缺失
|
|
1464
|
+
groupName: groupInfoObj.GroupName || groupInfoObj.group_name,
|
|
1465
|
+
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`,
|
|
1466
|
+
memberCount: groupInfoObj.member_count || 0,
|
|
1467
|
+
maxMemberCount: groupInfoObj.max_member_count || 0
|
|
1468
|
+
};
|
|
1469
|
+
} else {
|
|
1470
|
+
userInfoArg = {
|
|
1471
|
+
...strangerInfoObj,
|
|
1472
|
+
// @ts-ignore - userObj 确实有avatar字段
|
|
1473
|
+
avatar: userObj.avatar
|
|
1474
|
+
};
|
|
1475
|
+
contextInfo = {
|
|
1476
|
+
isGroup: false,
|
|
1477
|
+
groupId: null,
|
|
1478
|
+
groupName: null,
|
|
1479
|
+
groupAvatarUrl: null,
|
|
1480
|
+
memberCount: null,
|
|
1481
|
+
maxMemberCount: null
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
if (config.onebotImplName === ONEBOT_IMPL_NAME.LAGRNAGE) {
|
|
1485
|
+
} else if (config.onebotImplName === ONEBOT_IMPL_NAME.NAPCAT) {
|
|
1486
|
+
const ncUserStatusObj = await session.onebot._request("nc_get_user_status", { user_id: targetUserId });
|
|
1487
|
+
const napcatStatusData = ncUserStatusObj?.data ?? null;
|
|
1488
|
+
userInfoArg.status = {
|
|
1489
|
+
napcat_origin: ncUserStatusObj,
|
|
1490
|
+
message: getNapcatQQStatusText(napcatStatusData?.status, napcatStatusData?.ext_status)
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
let userInfoArgMsg = `userInfoArg =
|
|
1494
|
+
${JSON.stringify(userInfoArg)}`;
|
|
1495
|
+
let contextInfoMsg = `contextInfo =
|
|
1496
|
+
${JSON.stringify(contextInfo)}`;
|
|
1497
|
+
if (config.verboseSessionOutput) {
|
|
1498
|
+
await session.send(userInfoArgMsg);
|
|
1499
|
+
await session.send(contextInfoMsg);
|
|
1500
|
+
}
|
|
1501
|
+
if (config.verboseConsoleOutput) {
|
|
1502
|
+
await ctx.logger.info(userInfoArgMsg);
|
|
1503
|
+
await ctx.logger.info(contextInfoMsg);
|
|
1504
|
+
}
|
|
1505
|
+
const unifiedUserInfo = convertToUnifiedUserInfo(userInfoArg, config.onebotImplName);
|
|
1506
|
+
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
1507
|
+
let unifiedUserInfoMsg = `unifiedUserInfo =
|
|
1508
|
+
${JSON.stringify(unifiedUserInfo)}`;
|
|
1509
|
+
let unifiedContextInfoMsg = `unifiedContextInfo =
|
|
1510
|
+
${JSON.stringify(unifiedContextInfo)}`;
|
|
1511
|
+
if (config.verboseSessionOutput) {
|
|
1512
|
+
await session.send(unifiedUserInfoMsg);
|
|
1513
|
+
await session.send(unifiedContextInfoMsg);
|
|
1514
|
+
}
|
|
1515
|
+
if (config.verboseConsoleOutput) {
|
|
1516
|
+
await ctx.logger.info(unifiedUserInfoMsg);
|
|
1517
|
+
await ctx.logger.info(unifiedContextInfoMsg);
|
|
1518
|
+
}
|
|
1519
|
+
if (config.sendText) {
|
|
1520
|
+
ctx.logger.info("text");
|
|
1521
|
+
const formattedText = formatUserInfoDirectText(unifiedUserInfo, unifiedContextInfo);
|
|
1522
|
+
session.send(`${config.enableQuoteWithText ? import_koishi.h.quote(session.messageId) : ""}${formattedText}`);
|
|
1523
|
+
}
|
|
1524
|
+
if (config.sendImage) {
|
|
1525
|
+
const waitTipMsgId = await session.send(`${import_koishi.h.quote(session.messageId)}🔄正在渲染用户信息图片,请稍候⏳...`);
|
|
1526
|
+
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
1527
|
+
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
1528
|
+
const userInfoimageBase64 = await renderUserInfo(ctx, unifiedUserInfo, unifiedContextInfo, selectedImageStyle, selectedDarkMode, config.imageType, config.screenshotQuality, config.hidePhoneNumber);
|
|
1529
|
+
if (config.verboseFileOutput) {
|
|
1530
|
+
try {
|
|
1531
|
+
const tmpDir = (0, import_path2.resolve)(__dirname, "../tmp");
|
|
1532
|
+
(0, import_fs2.mkdirSync)(tmpDir, { recursive: true });
|
|
1533
|
+
const outputPath = (0, import_path2.resolve)(tmpDir, "image_base64.txt");
|
|
1534
|
+
(0, import_fs2.writeFileSync)(outputPath, userInfoimageBase64, "utf-8");
|
|
1535
|
+
ctx.logger.info(`图片 base64 已输出到: ${outputPath}`);
|
|
1536
|
+
} catch (error) {
|
|
1537
|
+
ctx.logger.error(`写入 base64 文件失败: ${error.message}`);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
await session.send(`${config.enableQuoteWithImage ? import_koishi.h.quote(session.messageId) : ""}${import_koishi.h.image(`data:image/png;base64,${userInfoimageBase64}`)}`);
|
|
1541
|
+
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
1542
|
+
}
|
|
1543
|
+
if (config.sendForward) {
|
|
1544
|
+
const forwardMessageContent = formatUserInfoForwardText(session.bot, unifiedUserInfo, unifiedContextInfo);
|
|
1545
|
+
session.send(import_koishi.h.unescape(forwardMessageContent));
|
|
1546
|
+
}
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
ctx.logger.error(`获取用户信息或渲染图片失败:
|
|
1549
|
+
error=${error}
|
|
1550
|
+
error.stack=${error.stack}`);
|
|
1551
|
+
await session.send(`[error]获取用户信息或渲染图片失败:
|
|
1552
|
+
error.message=${error.message}`);
|
|
1553
|
+
}
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
__name(registerUserInfoCommand, "registerUserInfoCommand");
|
|
1557
|
+
function formatUserInfoDirectText(userInfo, contextInfo) {
|
|
1558
|
+
let output = "";
|
|
1559
|
+
output += `----- 用户信息 (UserInfo) -----
|
|
1560
|
+
`;
|
|
1561
|
+
output += `QQ号 (UserID): ${userInfo.user_id}
|
|
1562
|
+
`;
|
|
1563
|
+
if (userInfo.nickname) output += `昵称 (Nickname): ${userInfo.nickname}
|
|
1564
|
+
`;
|
|
1565
|
+
if (userInfo.card) output += `群昵称 (GroupCard): ${userInfo.card}
|
|
1566
|
+
`;
|
|
1567
|
+
if (userInfo.sex) output += `性别 (Gender): ${userInfo.sex === "male" ? "男 (Male)" : userInfo.sex === "female" ? "女 (Female)" : "未知 (Unknown)"}
|
|
1568
|
+
`;
|
|
1569
|
+
if (userInfo.age) output += `年龄 (Age): ${userInfo.age}
|
|
1570
|
+
`;
|
|
1571
|
+
if (userInfo.level) output += `等级 (Level): ${userInfo.level}
|
|
1572
|
+
`;
|
|
1573
|
+
if (userInfo.sign) output += `个性签名 (Signature): ${userInfo.sign}
|
|
1574
|
+
`;
|
|
1575
|
+
if (userInfo.role) output += `群角色 (GroupRole): ${userInfo.role === "owner" ? "群主 (Owner)" : userInfo.role === "admin" ? "管理员 (Admin)" : "成员 (Member)"}
|
|
1576
|
+
`;
|
|
1577
|
+
if (userInfo.join_time) output += `入群时间 (JoinTime): ${new Date(userInfo.join_time).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
1578
|
+
`;
|
|
1579
|
+
if (userInfo.RegisterTime) output += `注册时间 (RegTime): ${new Date(userInfo.RegisterTime).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
1580
|
+
`;
|
|
1581
|
+
output += `
|
|
1582
|
+
--- 会话信息 (ContextInfo) ---
|
|
1583
|
+
`;
|
|
1584
|
+
output += `是否群聊 (IsGroupChat): ${contextInfo.isGroup ? "是 (Yes)" : "否 (No)"}
|
|
1585
|
+
`;
|
|
1586
|
+
if (contextInfo.isGroup && contextInfo.groupId) output += `群号 (GroupID): ${contextInfo.groupId}
|
|
1587
|
+
`;
|
|
1588
|
+
return output;
|
|
1589
|
+
}
|
|
1590
|
+
__name(formatUserInfoDirectText, "formatUserInfoDirectText");
|
|
1591
|
+
function formatUserInfoForwardText(botSelf, userInfo, contextInfo) {
|
|
1592
|
+
let messages = "";
|
|
1593
|
+
const addMessageBlock = /* @__PURE__ */ __name((authorId, authorName, value) => {
|
|
1594
|
+
messages += `
|
|
1595
|
+
<message>
|
|
1596
|
+
<author ${authorId ? `id="${authorId}"` : ``} ${authorName ? `name="${authorName}"` : ``}/>
|
|
1597
|
+
${value}
|
|
1598
|
+
</message>`;
|
|
1599
|
+
}, "addMessageBlock");
|
|
1600
|
+
addMessageBlock(void 0, "当前时间 (CurrentTime):", `${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`);
|
|
1601
|
+
addMessageBlock(void 0, "信息类型 (InfoType):", "用户信息 (User Info)");
|
|
1602
|
+
addMessageBlock(userInfo.user_id, void 0, `QQ号 (UserID): ${userInfo.user_id}`);
|
|
1603
|
+
if (userInfo.nickname) addMessageBlock(userInfo.user_id, void 0, `昵称 (Nickname): ${userInfo.nickname}`);
|
|
1604
|
+
if (userInfo.card) addMessageBlock(userInfo.user_id, void 0, `群昵称 (GroupCard): ${userInfo.card}`);
|
|
1605
|
+
if (userInfo.sex) addMessageBlock(userInfo.user_id, void 0, `性别 (Gender): ${userInfo.sex === "male" ? "男 (Male)" : userInfo.sex === "female" ? "女 (Female)" : "未知 (Unknown)"}`);
|
|
1606
|
+
if (userInfo.age !== void 0 && userInfo.age !== null) addMessageBlock(userInfo.user_id, void 0, `年龄 (Age): ${userInfo.age}`);
|
|
1607
|
+
if (userInfo.level) addMessageBlock(userInfo.user_id, void 0, `等级 (Level): ${userInfo.level}`);
|
|
1608
|
+
if (userInfo.sign) addMessageBlock(userInfo.user_id, void 0, `个性签名 (Signature): ${userInfo.sign}`);
|
|
1609
|
+
if (userInfo.role) addMessageBlock(userInfo.user_id, void 0, `群角色 (GroupRole): ${userInfo.role === "owner" ? "群主 (Owner)" : userInfo.role === "admin" ? "管理员 (Admin)" : "成员 (Member)"}`);
|
|
1610
|
+
if (userInfo.join_time) addMessageBlock(userInfo.user_id, void 0, `入群时间 (JoinTime): ${new Date(userInfo.join_time).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`);
|
|
1611
|
+
if (userInfo.RegisterTime) addMessageBlock(userInfo.user_id, void 0, `注册时间 (RegTime): ${new Date(userInfo.RegisterTime).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`);
|
|
1612
|
+
addMessageBlock(botSelf.userId, "信息类型 (Info Type):", "会话信息 (Context Info)");
|
|
1613
|
+
addMessageBlock(botSelf.userId, "是否群聊 (Is Group Chat):", `${contextInfo.isGroup ? "是 (Yes)" : "否 (No)"}`);
|
|
1614
|
+
if (contextInfo.isGroup && contextInfo.groupId) addMessageBlock(botSelf.userId, "群号 (Group ID):", `${contextInfo.groupId}`);
|
|
1615
|
+
return `<message forward>
|
|
1616
|
+
${messages}
|
|
1617
|
+
</message>`;
|
|
1618
|
+
}
|
|
1619
|
+
__name(formatUserInfoForwardText, "formatUserInfoForwardText");
|
|
1620
|
+
|
|
1621
|
+
// src/commandAdminList.ts
|
|
1622
|
+
var import_koishi2 = require("koishi");
|
|
1623
|
+
|
|
1200
1624
|
// src/renderAdminList.ts
|
|
1201
1625
|
var generateAdminListItems = /* @__PURE__ */ __name((admins) => {
|
|
1202
1626
|
return admins.map((admin, index) => `
|
|
@@ -1859,8 +2283,8 @@ async function renderAdminList(ctx, admins, contextInfo, imageStyle, enableDarkM
|
|
|
1859
2283
|
await browserPage.waitForSelector("body", { timeout: 15e3 });
|
|
1860
2284
|
await browserPage.evaluate(() => {
|
|
1861
2285
|
const images = Array.from(document.querySelectorAll("img"));
|
|
1862
|
-
return Promise.all(images.filter((img) => !img.complete).map((img) => new Promise((
|
|
1863
|
-
img.onload = img.onerror =
|
|
2286
|
+
return Promise.all(images.filter((img) => !img.complete).map((img) => new Promise((resolve4) => {
|
|
2287
|
+
img.onload = img.onerror = resolve4;
|
|
1864
2288
|
})));
|
|
1865
2289
|
});
|
|
1866
2290
|
const bodyElement = await browserPage.$("body");
|
|
@@ -1885,143 +2309,3059 @@ async function renderAdminList(ctx, admins, contextInfo, imageStyle, enableDarkM
|
|
|
1885
2309
|
}
|
|
1886
2310
|
__name(renderAdminList, "renderAdminList");
|
|
1887
2311
|
|
|
1888
|
-
// src/
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
await
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
await
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2312
|
+
// src/commandAdminList.ts
|
|
2313
|
+
function registerAdminListCommand(ctx, config, responseHint) {
|
|
2314
|
+
if (!config.enableGroupAdminListCommand) return;
|
|
2315
|
+
ctx.command(config.groupAdminListCommandName, `获取群管理员列表, 发送${responseHint}`).alias("al").alias("awa_group_admin_list").option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }) => {
|
|
2316
|
+
if (!session.onebot)
|
|
2317
|
+
return session.send("[error]当前会话不支持onebot协议。");
|
|
2318
|
+
if (!session.guildId)
|
|
2319
|
+
return session.send("[error]当前会话不在群聊中。");
|
|
2320
|
+
const IMAGE_STYLE_VALUES = Object.values(IMAGE_STYLES);
|
|
2321
|
+
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
2322
|
+
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
2323
|
+
if (options.imageStyleIdx !== void 0) {
|
|
2324
|
+
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
2325
|
+
if (!isIdxValid) {
|
|
2326
|
+
let idxInvalidMsgArr = [
|
|
2327
|
+
`图片样式索引不合法。`,
|
|
2328
|
+
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
2329
|
+
` 当前输入:${options.imageStyleIdx}`,
|
|
2330
|
+
`
|
|
2331
|
+
`,
|
|
2332
|
+
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
2333
|
+
];
|
|
2334
|
+
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
2335
|
+
}
|
|
2336
|
+
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
2337
|
+
}
|
|
2338
|
+
try {
|
|
2339
|
+
const groupMemberListObj = await session.onebot.getGroupMemberList(session.guildId);
|
|
2340
|
+
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
2341
|
+
const groupAdminMemberListObj = groupMemberListObj.filter((m) => m.role === "admin" || m.role === "owner");
|
|
2342
|
+
let groupAdminMemberListObjMsg = `groupAdminMemberListObj =
|
|
2343
|
+
${JSON.stringify(groupAdminMemberListObj)}`;
|
|
2344
|
+
if (config.verboseSessionOutput) await session.send(groupAdminMemberListObjMsg);
|
|
2345
|
+
if (config.verboseConsoleOutput) ctx.logger.info(groupAdminMemberListObjMsg);
|
|
2346
|
+
if (groupAdminMemberListObj.length === 0) {
|
|
2347
|
+
return session.send("该群没有管理员。");
|
|
2348
|
+
}
|
|
2349
|
+
const adminListArg = [];
|
|
2350
|
+
for (const member of groupAdminMemberListObj) {
|
|
2351
|
+
try {
|
|
2352
|
+
const userObj = await session.bot.getUser(member.user_id);
|
|
2353
|
+
const rawAdminInfo = {
|
|
2354
|
+
user_id: member.user_id,
|
|
2355
|
+
nickname: member.nickname,
|
|
2356
|
+
card: member.card,
|
|
2357
|
+
role: member.role,
|
|
2358
|
+
level: member.level,
|
|
2359
|
+
join_time: member.join_time,
|
|
2360
|
+
last_sent_time: member.last_sent_time,
|
|
2361
|
+
title: member.title,
|
|
2362
|
+
avatar: userObj.avatar || ""
|
|
2363
|
+
};
|
|
2364
|
+
adminListArg.push(convertToUnifiedAdminInfo(rawAdminInfo, config.onebotImplName));
|
|
2365
|
+
} catch (error) {
|
|
2366
|
+
ctx.logger.error(`获取管理员列表信息失败: ${error}`);
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
adminListArg.sort((a, b) => {
|
|
2370
|
+
if (a.role === "owner" && b.role !== "owner") return -1;
|
|
2371
|
+
if (a.role !== "owner" && b.role === "owner") return 1;
|
|
2372
|
+
const cardA = a.card || "";
|
|
2373
|
+
const cardB = b.card || "";
|
|
2374
|
+
return cardB.localeCompare(cardA, "zh");
|
|
2375
|
+
});
|
|
2376
|
+
const contextInfo = {
|
|
2377
|
+
isGroup: true,
|
|
2378
|
+
groupId: parseInt(session.guildId),
|
|
2379
|
+
groupName: groupInfoObj.group_name || "未知群聊",
|
|
2380
|
+
memberCount: groupInfoObj.member_count || 0,
|
|
2381
|
+
maxMemberCount: groupInfoObj.max_member_count || 0,
|
|
2382
|
+
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`
|
|
2383
|
+
};
|
|
2384
|
+
if (config.sendText) {
|
|
2385
|
+
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2386
|
+
const formattedText = formatAdminListDirectText(adminListArg, unifiedContextInfo);
|
|
2387
|
+
await session.send(`${config.enableQuoteWithText ? import_koishi2.h.quote(session.messageId) : ""}${formattedText}`);
|
|
2388
|
+
}
|
|
2389
|
+
if (config.sendImage) {
|
|
2390
|
+
ctx.logger.info(`context info = ${JSON.stringify(contextInfo)}`);
|
|
2391
|
+
const waitTipMsgId = await session.send(`${import_koishi2.h.quote(session.messageId)}🔄正在渲染群管理员列表图片,请稍候⏳...`);
|
|
2392
|
+
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2393
|
+
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
2394
|
+
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
2395
|
+
const adminListImageBase64 = await renderAdminList(ctx, adminListArg, unifiedContextInfo, selectedImageStyle, selectedDarkMode, config.imageType, config.screenshotQuality);
|
|
2396
|
+
await session.send(`${config.enableQuoteWithImage ? import_koishi2.h.quote(session.messageId) : ""}${import_koishi2.h.image(`data:image/png;base64,${adminListImageBase64}`)}`);
|
|
2397
|
+
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
2398
|
+
}
|
|
2399
|
+
if (config.sendForward) {
|
|
2400
|
+
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2401
|
+
const forwardMessageContent = formatAdminListForwardText(adminListArg, unifiedContextInfo);
|
|
2402
|
+
await session.send(import_koishi2.h.unescape(forwardMessageContent));
|
|
2403
|
+
}
|
|
2404
|
+
} catch (error) {
|
|
2405
|
+
ctx.logger.error(`获取群管理员列表失败: ${error}`);
|
|
2406
|
+
await session.send(`[error]获取群管理员列表失败: ${error.message}`);
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2410
|
+
__name(registerAdminListCommand, "registerAdminListCommand");
|
|
2411
|
+
function formatAdminListDirectText(adminListArg, contextInfo) {
|
|
2412
|
+
let output = "";
|
|
2413
|
+
output += `当前时间 (Current Time): ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
2414
|
+
`;
|
|
2415
|
+
output += `===== 群管理员列表 (Group Admin List) =====
|
|
2416
|
+
`;
|
|
2417
|
+
output += `群名称 (Group Name): ${contextInfo.groupName || "未知群聊"}
|
|
2418
|
+
`;
|
|
2419
|
+
output += `群号 (Group ID): ${contextInfo.groupId}
|
|
2420
|
+
`;
|
|
2421
|
+
output += `成员数 (Member Count): ${contextInfo.memberCount}/${contextInfo.maxMemberCount}
|
|
2422
|
+
`;
|
|
2423
|
+
output += `管理员数量 (Admin Count): ${adminListArg.length}
|
|
2424
|
+
|
|
2425
|
+
`;
|
|
2426
|
+
adminListArg.forEach((admin, index) => {
|
|
2427
|
+
output += `-----No. ${index + 1}. ${admin.role === "owner" ? "群主" : "管理员"} (${admin.role === "owner" ? "Owner" : "Admin"})-----
|
|
2428
|
+
`;
|
|
2429
|
+
output += ` QQ号 (User ID): ${admin.user_id}
|
|
2430
|
+
`;
|
|
2431
|
+
output += ` 昵称 (Nickname): ${admin.nickname || "未知"}
|
|
2432
|
+
`;
|
|
2433
|
+
if (admin.card) output += ` 群名片 (Group Card): ${admin.card}
|
|
2434
|
+
`;
|
|
2435
|
+
if (admin.level) output += ` 等级 (Level): ${admin.level}
|
|
2436
|
+
`;
|
|
2437
|
+
if (admin.join_time) output += ` 入群时间 (Join Time): ${new Date(admin.join_time * 1e3).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
2438
|
+
`;
|
|
2439
|
+
if (admin.title) output += ` 头衔 (Title): ${admin.title}
|
|
2440
|
+
`;
|
|
2441
|
+
output += "\n";
|
|
2442
|
+
});
|
|
2443
|
+
return output;
|
|
2444
|
+
}
|
|
2445
|
+
__name(formatAdminListDirectText, "formatAdminListDirectText");
|
|
2446
|
+
function formatAdminListForwardText(adminListArg, contextInfo) {
|
|
2447
|
+
let messages = "";
|
|
2448
|
+
const addMessageBlock = /* @__PURE__ */ __name((authorId, authorName, adminUsrInfoStr) => {
|
|
2449
|
+
messages += `
|
|
2450
|
+
<message>
|
|
2451
|
+
<author ${authorId ? `id="${authorId}"` : ``} name="${authorName}"/>
|
|
2452
|
+
${adminUsrInfoStr}
|
|
2453
|
+
</message>`;
|
|
2454
|
+
}, "addMessageBlock");
|
|
2455
|
+
addMessageBlock(
|
|
2456
|
+
void 0,
|
|
2457
|
+
"群聊基本信息",
|
|
2458
|
+
[
|
|
2459
|
+
`当前时间: ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`,
|
|
2460
|
+
`=========群聊信息=========`,
|
|
2461
|
+
`群名称: ${contextInfo.groupName || "未知群聊"}`,
|
|
2462
|
+
`群号: ${contextInfo.groupId}`,
|
|
2463
|
+
`成员数: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}`,
|
|
2464
|
+
`管理员数量: ${adminListArg.length}`
|
|
2465
|
+
].join("\n")
|
|
2466
|
+
);
|
|
2467
|
+
for (let i = 0; i < adminListArg.length; i++) {
|
|
2468
|
+
const admin = adminListArg[i];
|
|
2469
|
+
const authorName = admin.card || admin.nickname || `QQ: ${admin.user_id}`;
|
|
2470
|
+
const adminDetails = [
|
|
2471
|
+
`---------No. ${i + 1}---------`,
|
|
2472
|
+
`QQ号: ${admin.user_id}`,
|
|
2473
|
+
`昵称: ${admin.nickname}`,
|
|
2474
|
+
`角色: ${admin.role === "owner" ? "群主" : "管理员"}`,
|
|
2475
|
+
admin.card ? `群昵称: ${admin.card}` : "",
|
|
2476
|
+
admin.level ? `等级: ${admin.level}` : "",
|
|
2477
|
+
admin.title ? `群头衔: ${admin.title}` : "",
|
|
2478
|
+
admin.join_time ? `加入本群时间: ${new Date(admin.join_time * 1e3).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}` : "",
|
|
2479
|
+
admin.last_sent_time ? `最后发言时间: ${new Date(admin.last_sent_time * 1e3).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}` : ""
|
|
2480
|
+
].filter(Boolean).join("\n");
|
|
2481
|
+
addMessageBlock(
|
|
2482
|
+
admin.user_id.toString(),
|
|
2483
|
+
authorName,
|
|
2484
|
+
adminDetails
|
|
2485
|
+
);
|
|
2486
|
+
}
|
|
2487
|
+
return `<message forward>
|
|
2488
|
+
${messages}
|
|
2489
|
+
</message>`;
|
|
2490
|
+
}
|
|
2491
|
+
__name(formatAdminListForwardText, "formatAdminListForwardText");
|
|
2492
|
+
|
|
2493
|
+
// src/commandGroupEssence.ts
|
|
2494
|
+
var import_koishi3 = require("koishi");
|
|
2495
|
+
|
|
2496
|
+
// src/renderGroupEssence.ts
|
|
2497
|
+
function parseEssenceContentToHtml(content) {
|
|
2498
|
+
if (!content || content.length === 0) {
|
|
2499
|
+
return '<span class="empty-msg">[空消息]</span>';
|
|
2500
|
+
}
|
|
2501
|
+
return content.map((item) => {
|
|
2502
|
+
switch (item.type) {
|
|
2503
|
+
case "text":
|
|
2504
|
+
const text = (item.data.text || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br/>");
|
|
2505
|
+
return `<span class="msg-text">${text}</span>`;
|
|
2506
|
+
case "image":
|
|
2507
|
+
const imageUrl = item.data.url || "";
|
|
2508
|
+
if (imageUrl) {
|
|
2509
|
+
return `<span class="msg-image-wrapper"><img class="msg-image-preview" src="${imageUrl}" alt="图片" onerror="this.style.display='none';this.nextSibling.style.display='inline';" /><span class="msg-image-fallback" style="display:none;">[图片]</span></span>`;
|
|
2510
|
+
}
|
|
2511
|
+
return '<span class="msg-image-placeholder">[图片]</span>';
|
|
2512
|
+
case "face":
|
|
2513
|
+
return `<span class="msg-face">[表情:${item.data.id || ""}]</span>`;
|
|
2514
|
+
case "at":
|
|
2515
|
+
return `<span class="msg-at">@${item.data.qq || item.data.name || "某人"}</span>`;
|
|
2516
|
+
case "reply":
|
|
2517
|
+
const replyUserId = item.data.id || item.data.qq || "";
|
|
2518
|
+
return `<span class="msg-reply"><span class="reply-icon">↩</span><span class="reply-text">回复${replyUserId ? ` [${replyUserId}]` : "消息"}</span></span>`;
|
|
2519
|
+
case "forward":
|
|
2520
|
+
return '<span class="msg-forward">[转发消息]</span>';
|
|
2521
|
+
case "video":
|
|
2522
|
+
return '<span class="msg-video">[视频]</span>';
|
|
2523
|
+
case "record":
|
|
2524
|
+
return '<span class="msg-record">[语音]</span>';
|
|
2525
|
+
case "file":
|
|
2526
|
+
return '<span class="msg-file">[文件]</span>';
|
|
2527
|
+
default:
|
|
2528
|
+
return `<span class="msg-unknown">[${item.type}]</span>`;
|
|
2529
|
+
}
|
|
2530
|
+
}).join("");
|
|
2531
|
+
}
|
|
2532
|
+
__name(parseEssenceContentToHtml, "parseEssenceContentToHtml");
|
|
2533
|
+
var generateEssenceListItems = /* @__PURE__ */ __name((records, currentPage, pageSize) => {
|
|
2534
|
+
return records.map((record, index) => {
|
|
2535
|
+
const globalIndex = (currentPage - 1) * pageSize + index + 1;
|
|
2536
|
+
const contentHtml = parseEssenceContentToHtml(record.content);
|
|
2537
|
+
const timeStr = formatTimestamp(record.operator_time);
|
|
2538
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
2539
|
+
return `
|
|
2540
|
+
<div class="essence-item">
|
|
2541
|
+
<div class="essence-column-1">
|
|
2542
|
+
<div class="essence-number">${globalIndex.toString().padStart(2, "0")}</div>
|
|
2543
|
+
<div class="essence-avatar">
|
|
2544
|
+
<img src="${senderAvatarUrl}" alt="头像" />
|
|
2545
|
+
</div>
|
|
2546
|
+
</div>
|
|
2547
|
+
<div class="essence-column-2">
|
|
2548
|
+
<div class="essence-sender">${record.sender_nick || "未知"}</div>
|
|
2549
|
+
<div class="essence-sender-id"><span class="qq-label">QQ:</span> <span class="qq-number">${record.sender_id}</span></div>
|
|
2550
|
+
</div>
|
|
2551
|
+
<div class="essence-column-3">
|
|
2552
|
+
<div class="essence-content">${contentHtml}</div>
|
|
2553
|
+
<div class="essence-meta">
|
|
2554
|
+
<span class="essence-time">⏰ ${timeStr}</span>
|
|
2555
|
+
<span class="essence-operator">📌 ${record.operator_nick}</span>
|
|
2556
|
+
</div>
|
|
2557
|
+
</div>
|
|
2558
|
+
</div>
|
|
2559
|
+
`;
|
|
2560
|
+
}).join("");
|
|
2561
|
+
}, "generateEssenceListItems");
|
|
2562
|
+
var getSourceHanSerifSCStyleEssenceHtmlStr = /* @__PURE__ */ __name(async (result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
2563
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: radial-gradient(circle at center, rgba(255,255,255,0.15), rgba(0,0,0,0.1)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : "background: linear-gradient(135deg, #f8f9fa, #e9ecef);";
|
|
2564
|
+
const timestamp = generateTimestamp();
|
|
2565
|
+
return `<!DOCTYPE html>
|
|
2566
|
+
<html>
|
|
2567
|
+
<head>
|
|
2568
|
+
<style>
|
|
2569
|
+
${fontBase64 ? `@font-face { font-family: 'SourceHanSerifSC-Medium'; src: url('data:font/opentype;charset=utf-8;base64,${fontBase64}') format('opentype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
2570
|
+
|
|
2571
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
2572
|
+
body {
|
|
2573
|
+
font-family: ${fontBase64 ? "'SourceHanSerifSC-Medium'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
2574
|
+
width: 850px;
|
|
2575
|
+
height: auto;
|
|
2576
|
+
min-height: 100vh;
|
|
2577
|
+
display: flex;
|
|
2578
|
+
align-items: center;
|
|
2579
|
+
justify-content: center;
|
|
2580
|
+
${backgroundStyle}
|
|
2581
|
+
background-repeat: no-repeat;
|
|
2582
|
+
position: relative;
|
|
2583
|
+
box-sizing: border-box;
|
|
2584
|
+
overflow: visible;
|
|
2585
|
+
color: #333;
|
|
2586
|
+
padding: 35px;
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
.card {
|
|
2590
|
+
width: 720px;
|
|
2591
|
+
height: auto;
|
|
2592
|
+
min-height: 400px;
|
|
2593
|
+
background: rgba(255, 255, 255, 0.25);
|
|
2594
|
+
backdrop-filter: blur(20px) saturate(180%);
|
|
2595
|
+
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
2596
|
+
border-radius: 24px;
|
|
2597
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
2598
|
+
position: relative;
|
|
2599
|
+
overflow: visible;
|
|
2600
|
+
display: flex;
|
|
2601
|
+
flex-direction: column;
|
|
2602
|
+
padding: 32px;
|
|
2603
|
+
box-sizing: border-box;
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
.group-header { display: flex; align-items: center; margin-bottom: 20px; padding: 18px; background: rgba(255,255,255,0.3); border: 1px solid rgba(255,255,255,0.4); border-radius: 18px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
|
|
2607
|
+
.group-avatar { width: 75px; height: 75px; border-radius: 50%; margin-right: 16px; border: 3px solid rgba(255,255,255,0.6); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
2608
|
+
.group-info { flex: 1; }
|
|
2609
|
+
.group-name { font-size: 28px; font-weight: 700; color: #1a1a1a; margin-bottom: 4px; text-shadow: 0 1px 2px rgba(0,0,0,0.1); }
|
|
2610
|
+
.group-details { font-size: 18px; color: #4a4a4a; line-height: 1.3; font-weight: 500; }
|
|
2611
|
+
|
|
2612
|
+
.title { font-size: 40px; font-weight: 700; margin-bottom: 16px; color: #1a1a1a; text-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }
|
|
2613
|
+
.pagination-info { font-size: 16px; color: #666; text-align: center; margin-bottom: 16px; }
|
|
2614
|
+
|
|
2615
|
+
.essence-list { width: 100%; display: flex; flex-direction: column; gap: 12px; }
|
|
2616
|
+
|
|
2617
|
+
.essence-item { background: rgba(255,255,255,0.6); border: 1px solid rgba(255,255,255,0.5); border-radius: 14px; padding: 16px; display: flex; align-items: flex-start; box-shadow: 0 3px 10px rgba(0,0,0,0.08); transition: all 0.3s ease; backdrop-filter: blur(10px); min-height: 80px; }
|
|
2618
|
+
.essence-item:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(0,0,0,0.12); background: rgba(255,255,255,0.7); }
|
|
2619
|
+
|
|
2620
|
+
.essence-column-1 { display: flex; flex-direction: row; align-items: center; margin-right: 15px; min-width: 100px; }
|
|
2621
|
+
.essence-avatar { margin-bottom: 4px; }
|
|
2622
|
+
.essence-avatar img { width: 60px; height: 60px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.8); box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
2623
|
+
.essence-number { font-size: 22px; margin: 0 10px 0 0; font-weight: 700; color: #666; }
|
|
2624
|
+
|
|
2625
|
+
.essence-column-2 { min-width: 120px; margin-right: 16px; }
|
|
2626
|
+
.essence-sender { font-size: 18px; color: #1a1a1a; font-weight: 600; margin-bottom: 4px; }
|
|
2627
|
+
.essence-sender-id { font-size: 14px; }
|
|
2628
|
+
.qq-label { color: #666; font-weight: 500; }
|
|
2629
|
+
.qq-number { color: #1a1a1a; font-weight: 600; font-family: 'Courier New', monospace; }
|
|
2630
|
+
|
|
2631
|
+
.essence-column-3 { flex: 1; }
|
|
2632
|
+
.essence-content { font-size: 16px; color: #333; line-height: 1.5; margin-bottom: 8px; word-break: break-all; white-space: pre-wrap; max-height: 150px; overflow: hidden; position: relative; }
|
|
2633
|
+
.essence-content::after { content: ''; position: absolute; bottom: 0; right: 0; width: 100%; height: 1.5em; background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.9)); pointer-events: none; }
|
|
2634
|
+
.essence-item:hover .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.95)); }
|
|
2635
|
+
.essence-meta { font-size: 13px; color: #888; display: flex; gap: 16px; flex-wrap: wrap; }
|
|
2636
|
+
.essence-time { color: #666; }
|
|
2637
|
+
.essence-operator { color: #ff8c00; }
|
|
2638
|
+
|
|
2639
|
+
/* 消息内容元素样式 */
|
|
2640
|
+
.msg-text { }
|
|
2641
|
+
.msg-reply { display: inline-flex; align-items: center; background: rgba(100,100,100,0.15); border-left: 3px solid #888; padding: 2px 8px; margin: 2px 4px 2px 0; border-radius: 0 6px 6px 0; font-size: 13px; color: #666; }
|
|
2642
|
+
.msg-reply .reply-icon { margin-right: 4px; font-size: 12px; }
|
|
2643
|
+
.msg-reply .reply-text { font-style: italic; }
|
|
2644
|
+
.msg-image-wrapper { display: inline-block; margin: 4px 4px 4px 0; vertical-align: middle; }
|
|
2645
|
+
.msg-image-preview { max-width: 78px; max-height: 78px; border-radius: 6px; border: 1px solid rgba(0,0,0,0.1); object-fit: cover; vertical-align: middle; }
|
|
2646
|
+
.msg-image-placeholder, .msg-image-fallback { color: #888; font-style: italic; }
|
|
2647
|
+
.msg-at { color: #1e90ff; font-weight: 500; }
|
|
2648
|
+
.msg-face { color: #ff9800; }
|
|
2649
|
+
.msg-forward, .msg-video, .msg-record, .msg-file { color: #888; font-style: italic; background: rgba(0,0,0,0.05); padding: 1px 6px; border-radius: 4px; }
|
|
2650
|
+
.msg-unknown { color: #999; }
|
|
2651
|
+
.empty-msg { color: #999; font-style: italic; }
|
|
2652
|
+
|
|
2653
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(128, 128, 128, 0.6); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
2654
|
+
|
|
2655
|
+
body.dark { color: #e0e0e0; }
|
|
2656
|
+
body.dark .card { background: rgba(20,20,20,0.4); box-shadow: 0 20px 60px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.15); }
|
|
2657
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(255,255,255,0.15); }
|
|
2658
|
+
body.dark .group-name { color: #ffffff; }
|
|
2659
|
+
body.dark .group-details { color: #b0b0b0; }
|
|
2660
|
+
body.dark .title { color: #ffffff; text-shadow: 0 2px 4px rgba(0,0,0,0.4); }
|
|
2661
|
+
body.dark .pagination-info { color: #aaa; }
|
|
2662
|
+
body.dark .essence-item { background: rgba(40,40,40,0.6); border-color: rgba(255,255,255,0.1); box-shadow: 0 3px 10px rgba(0,0,0,0.2); }
|
|
2663
|
+
body.dark .essence-item:hover { box-shadow: 0 6px 20px rgba(0,0,0,0.3); background: rgba(50,50,50,0.7); }
|
|
2664
|
+
body.dark .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(40,40,40,0.9)); }
|
|
2665
|
+
body.dark .essence-item:hover .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(50,50,50,0.95)); }
|
|
2666
|
+
body.dark .essence-number { color: #a0a0a0; }
|
|
2667
|
+
body.dark .essence-sender { color: #ffffff; }
|
|
2668
|
+
body.dark .qq-label { color: #b0b0b0; }
|
|
2669
|
+
body.dark .qq-number { color: #ffffff; }
|
|
2670
|
+
body.dark .essence-content { color: #e0e0e0; }
|
|
2671
|
+
body.dark .essence-meta { color: #888; }
|
|
2672
|
+
body.dark .essence-time { color: #aaa; }
|
|
2673
|
+
body.dark .essence-operator { color: #ffa07a; }
|
|
2674
|
+
body.dark .msg-reply { background: rgba(150,150,150,0.2); border-left-color: #aaa; color: #bbb; }
|
|
2675
|
+
body.dark .msg-at { color: #4da6ff; }
|
|
2676
|
+
body.dark .msg-face { color: #ffb74d; }
|
|
2677
|
+
body.dark .msg-forward, body.dark .msg-video, body.dark .msg-record, body.dark .msg-file { background: rgba(255,255,255,0.1); color: #aaa; }
|
|
2678
|
+
body.dark .msg-image-preview { border-color: rgba(255,255,255,0.2); }
|
|
2679
|
+
body.dark .timestamp-watermark { color: rgba(160, 160, 160, 0.5); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
2680
|
+
</style>
|
|
2681
|
+
</head>
|
|
2682
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
2683
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
2684
|
+
<div class="card">
|
|
2685
|
+
<div class="group-header">
|
|
2686
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
2687
|
+
<div class="group-info">
|
|
2688
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
2689
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
2690
|
+
</div>
|
|
2691
|
+
</div>
|
|
2692
|
+
<div class="title">📌 群精华消息</div>
|
|
2693
|
+
<div class="pagination-info">第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条精华)</div>
|
|
2694
|
+
<div class="essence-list">
|
|
2695
|
+
${generateEssenceListItems(result.records, result.currentPage, result.pageSize)}
|
|
2696
|
+
</div>
|
|
2697
|
+
</div>
|
|
2698
|
+
</body>
|
|
2699
|
+
</html>`;
|
|
2700
|
+
}, "getSourceHanSerifSCStyleEssenceHtmlStr");
|
|
2701
|
+
var getLXGWWenKaiStyleEssenceHtmlStr = /* @__PURE__ */ __name(async (result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
2702
|
+
const timestamp = generateTimestamp();
|
|
2703
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: linear-gradient(45deg, rgba(245,240,230,0.85), rgba(250,245,235,0.85)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : `background: linear-gradient(45deg, #f5f0e6, #faf5eb);`;
|
|
2704
|
+
return `<!DOCTYPE html>
|
|
2705
|
+
<html>
|
|
2706
|
+
<head>
|
|
2707
|
+
<style>
|
|
2708
|
+
${fontBase64 ? `@font-face { font-family: 'LXGWWenKai'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
2709
|
+
|
|
2710
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
2711
|
+
body {
|
|
2712
|
+
font-family: ${fontBase64 ? "'LXGWWenKai'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
2713
|
+
width: 850px;
|
|
2714
|
+
height: auto;
|
|
2715
|
+
min-height: 100vh;
|
|
2716
|
+
display: flex;
|
|
2717
|
+
align-items: center;
|
|
2718
|
+
justify-content: center;
|
|
2719
|
+
${backgroundStyle}
|
|
2720
|
+
position: relative;
|
|
2721
|
+
box-sizing: border-box;
|
|
2722
|
+
overflow: visible;
|
|
2723
|
+
color: #3a2f2a;
|
|
2724
|
+
padding: 35px;
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
body::before { content: ''; position: absolute; top: 16px; left: 16px; right: 16px; bottom: 16px; border: 3px solid #d4af37; border-radius: 20px; background: linear-gradient(135deg, rgba(212,175,55,0.12) 0%, rgba(184,134,11,0.06) 50%, rgba(212,175,55,0.12) 100%); box-shadow: inset 0 0 25px rgba(212,175,55,0.35), 0 0 35px rgba(212,175,55,0.25); z-index: 1; }
|
|
2728
|
+
body::after { content: '◆'; position: absolute; top: 30px; left: 30px; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
2729
|
+
|
|
2730
|
+
.corner-decoration { position: absolute; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
2731
|
+
.corner-decoration.top-right { top: 30px; right: 30px; }
|
|
2732
|
+
.corner-decoration.bottom-left { bottom: 30px; left: 30px; }
|
|
2733
|
+
.corner-decoration.bottom-right { bottom: 30px; right: 30px; }
|
|
2734
|
+
|
|
2735
|
+
.main-container {
|
|
2736
|
+
width: 720px;
|
|
2737
|
+
min-height: 400px;
|
|
2738
|
+
position: relative;
|
|
2739
|
+
z-index: 3;
|
|
2740
|
+
display: flex;
|
|
2741
|
+
flex-direction: column;
|
|
2742
|
+
padding: 32px 28px;
|
|
2743
|
+
box-sizing: border-box;
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2746
|
+
.group-header { display: flex; align-items: center; margin-bottom: 18px; padding: 16px; background: rgba(255,255,255,0.2); border: 1px solid rgba(212,175,55,0.4); border-radius: 16px; box-shadow: 0 4px 16px rgba(212,175,55,0.15); }
|
|
2747
|
+
.group-avatar { width: 64px; height: 64px; border-radius: 9%; margin-right: 14px; border: 3px solid #d4af37; box-shadow: 0 4px 12px rgba(212,175,55,0.3); }
|
|
2748
|
+
.group-info { flex: 1; }
|
|
2749
|
+
.group-name { font-size: 25px; font-weight: bold; color: #8b4513; margin-bottom: 4px; text-shadow: 1px 1px 2px rgba(139,69,19,0.2); }
|
|
2750
|
+
.group-details { font-size: 20px; color: #a0522d; line-height: 1.4; font-weight: 500; }
|
|
2751
|
+
|
|
2752
|
+
.title-section { text-align: center; margin-bottom: 14px; }
|
|
2753
|
+
.main-title { font-size: 46px; font-weight: bold; color: #8b4513; margin-bottom: 6px; text-shadow: 2px 2px 4px rgba(139,69,19,0.3); letter-spacing: 2px; }
|
|
2754
|
+
.pagination-info { font-size: 16px; color: #a0522d; text-align: center; margin-bottom: 14px; font-weight: 500; }
|
|
2755
|
+
|
|
2756
|
+
.essence-list { width: 100%; display: flex; flex-direction: column; gap: 6px; }
|
|
2757
|
+
|
|
2758
|
+
.essence-item { background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 12px; padding: 14px; display: flex; align-items: flex-start; box-shadow: 0 3px 10px rgba(0,0,0,0.08); transition: all 0.3s ease; backdrop-filter: blur(5px); min-height: 70px; }
|
|
2759
|
+
.essence-item:hover { transform: translateY(-1px); box-shadow: 0 5px 18px rgba(212,175,55,0.25); background: rgba(255,255,255,0.3); }
|
|
2760
|
+
|
|
2761
|
+
.essence-column-1 { display: flex; flex-direction: row; align-items: center; margin-right: 14px; min-width: 90px; }
|
|
2762
|
+
.essence-avatar img { width: 55px; height: 55px; border-radius: 50%; border: 2px solid #d4af37; box-shadow: 0 2px 6px rgba(212,175,55,0.2); }
|
|
2763
|
+
.essence-number { font-size: 24px; margin: 0 10px 0 0; font-weight: bold; color: #8b4513; }
|
|
2764
|
+
|
|
2765
|
+
.essence-column-2 { min-width: 110px; margin-right: 14px; }
|
|
2766
|
+
.essence-sender { font-size: 16px; color: #3a2f2a; font-weight: bold; margin-bottom: 3px; }
|
|
2767
|
+
.essence-sender-id { font-size: 13px; }
|
|
2768
|
+
.qq-label { color: #a0522d; font-weight: 500; }
|
|
2769
|
+
.qq-number { color: #3a2f2a; font-family: 'Courier New', monospace; font-weight: bold; }
|
|
2770
|
+
|
|
2771
|
+
.essence-column-3 { flex: 1; }
|
|
2772
|
+
.essence-content { font-size: 15px; color: #3a2f2a; line-height: 1.5; margin-bottom: 6px; word-break: break-all; white-space: pre-wrap; max-height: 140px; overflow: hidden; position: relative; }
|
|
2773
|
+
.essence-content::after { content: ''; position: absolute; bottom: 0; right: 0; width: 100%; height: 1.5em; background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.3)); pointer-events: none; }
|
|
2774
|
+
.essence-item:hover .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.4)); }
|
|
2775
|
+
.essence-meta { font-size: 12px; color: #a0522d; display: flex; gap: 14px; flex-wrap: wrap; }
|
|
2776
|
+
.essence-time { color: #a0522d; }
|
|
2777
|
+
.essence-operator { color: #8b4513; font-weight: 500; }
|
|
2778
|
+
|
|
2779
|
+
/* 消息内容元素样式 */
|
|
2780
|
+
.msg-text { }
|
|
2781
|
+
.msg-reply { display: inline-flex; align-items: center; background: rgba(212,175,55,0.15); border-left: 3px solid #d4af37; padding: 2px 8px; margin: 2px 4px 2px 0; border-radius: 0 6px 6px 0; font-size: 12px; color: #a0522d; }
|
|
2782
|
+
.msg-reply .reply-icon { margin-right: 4px; font-size: 11px; }
|
|
2783
|
+
.msg-reply .reply-text { font-style: italic; }
|
|
2784
|
+
.msg-image-wrapper { display: inline-block; margin: 4px 4px 4px 0; vertical-align: middle; }
|
|
2785
|
+
.msg-image-preview { max-width: 72px; max-height: 72px; border-radius: 6px; border: 1px solid rgba(212,175,55,0.3); object-fit: cover; vertical-align: middle; }
|
|
2786
|
+
.msg-image-placeholder, .msg-image-fallback { color: #a0522d; font-style: italic; }
|
|
2787
|
+
.msg-at { color: #8b4513; font-weight: bold; }
|
|
2788
|
+
.msg-face { color: #d4af37; }
|
|
2789
|
+
.msg-forward, .msg-video, .msg-record, .msg-file { color: #a0522d; font-style: italic; background: rgba(212,175,55,0.1); padding: 1px 6px; border-radius: 4px; }
|
|
2790
|
+
.msg-unknown { color: #8b7355; }
|
|
2791
|
+
.empty-msg { color: #8b7355; font-style: italic; }
|
|
2792
|
+
|
|
2793
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(139, 69, 19, 0.4); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
2794
|
+
|
|
2795
|
+
body.dark { background: linear-gradient(45deg, #2c2416, #3a2f1f); color: #e6d7c3; }
|
|
2796
|
+
body.dark::before { border-color: #b8860b; background: linear-gradient(135deg, rgba(184,134,11,0.18) 0%, rgba(139,69,19,0.12) 50%, rgba(184,134,11,0.18) 100%); box-shadow: inset 0 0 25px rgba(184,134,11,0.45), 0 0 35px rgba(184,134,11,0.35); }
|
|
2797
|
+
body.dark::after { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
2798
|
+
body.dark .corner-decoration { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
2799
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(184,134,11,0.5); }
|
|
2800
|
+
body.dark .group-name { color: #daa520; text-shadow: 1px 1px 2px rgba(218,165,32,0.3); }
|
|
2801
|
+
body.dark .group-details { color: #cd853f; }
|
|
2802
|
+
body.dark .main-title { color: #daa520; text-shadow: 2px 2px 4px rgba(218,165,32,0.4); }
|
|
2803
|
+
body.dark .pagination-info { color: #cd853f; }
|
|
2804
|
+
body.dark .essence-item { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
2805
|
+
body.dark .essence-item:hover { box-shadow: 0 5px 18px rgba(184,134,11,0.35); background: rgba(0,0,0,0.4); }
|
|
2806
|
+
body.dark .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.4)); }
|
|
2807
|
+
body.dark .essence-item:hover .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.5)); }
|
|
2808
|
+
body.dark .essence-number { color: #daa520; }
|
|
2809
|
+
body.dark .essence-sender { color: #e6d7c3; }
|
|
2810
|
+
body.dark .qq-label { color: #cd853f; }
|
|
2811
|
+
body.dark .qq-number { color: #e6d7c3; }
|
|
2812
|
+
body.dark .essence-content { color: #e6d7c3; }
|
|
2813
|
+
body.dark .essence-meta { color: #cd853f; }
|
|
2814
|
+
body.dark .essence-time { color: #cd853f; }
|
|
2815
|
+
body.dark .essence-operator { color: #daa520; }
|
|
2816
|
+
body.dark .msg-reply { background: rgba(184,134,11,0.2); border-left-color: #b8860b; color: #cd853f; }
|
|
2817
|
+
body.dark .msg-at { color: #daa520; }
|
|
2818
|
+
body.dark .msg-face { color: #b8860b; }
|
|
2819
|
+
body.dark .msg-forward, body.dark .msg-video, body.dark .msg-record, body.dark .msg-file { background: rgba(184,134,11,0.15); color: #cd853f; }
|
|
2820
|
+
body.dark .msg-image-preview { border-color: rgba(184,134,11,0.4); }
|
|
2821
|
+
body.dark .timestamp-watermark { color: rgba(218, 165, 32, 0.4); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
2822
|
+
</style>
|
|
2823
|
+
</head>
|
|
2824
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
2825
|
+
<div class="corner-decoration top-right">◆</div>
|
|
2826
|
+
<div class="corner-decoration bottom-left">◆</div>
|
|
2827
|
+
<div class="corner-decoration bottom-right">◆</div>
|
|
2828
|
+
<div class="main-container">
|
|
2829
|
+
<div class="group-header">
|
|
2830
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
2831
|
+
<div class="group-info">
|
|
2832
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
2833
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
2834
|
+
</div>
|
|
2835
|
+
</div>
|
|
2836
|
+
<div class="title-section">
|
|
2837
|
+
<div class="main-title">「 群精华消息 」</div>
|
|
2838
|
+
</div>
|
|
2839
|
+
<div class="pagination-info">第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条精华)</div>
|
|
2840
|
+
<div class="essence-list">
|
|
2841
|
+
${generateEssenceListItems(result.records, result.currentPage, result.pageSize)}
|
|
2842
|
+
</div>
|
|
2843
|
+
</div>
|
|
2844
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
2845
|
+
</body>
|
|
2846
|
+
</html>`;
|
|
2847
|
+
}, "getLXGWWenKaiStyleEssenceHtmlStr");
|
|
2848
|
+
var getFlatMinimalStyleEssenceHtmlStr = /* @__PURE__ */ __name(async (result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
2849
|
+
const timestamp = generateTimestamp();
|
|
2850
|
+
return `<!DOCTYPE html>
|
|
2851
|
+
<html>
|
|
2852
|
+
<head>
|
|
2853
|
+
<style>
|
|
2854
|
+
${fontBase64 ? `@font-face { font-family: 'LXGWWenKai'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
2855
|
+
|
|
2856
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
2857
|
+
body {
|
|
2858
|
+
font-family: ${fontBase64 ? "'LXGWWenKai'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
2859
|
+
width: 850px;
|
|
2860
|
+
height: auto;
|
|
2861
|
+
min-height: 100vh;
|
|
2862
|
+
display: flex;
|
|
2863
|
+
align-items: center;
|
|
2864
|
+
justify-content: center;
|
|
2865
|
+
background: linear-gradient(180deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
2866
|
+
position: relative;
|
|
2867
|
+
box-sizing: border-box;
|
|
2868
|
+
overflow: visible;
|
|
2869
|
+
color: #333;
|
|
2870
|
+
padding: 35px;
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
.card {
|
|
2874
|
+
width: 720px;
|
|
2875
|
+
height: auto;
|
|
2876
|
+
min-height: 400px;
|
|
2877
|
+
background: #ffffff;
|
|
2878
|
+
border-radius: 20px;
|
|
2879
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
|
2880
|
+
position: relative;
|
|
2881
|
+
overflow: visible;
|
|
2882
|
+
display: flex;
|
|
2883
|
+
flex-direction: column;
|
|
2884
|
+
padding: 26px;
|
|
2885
|
+
box-sizing: border-box;
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
.group-header { display: flex; align-items: center; margin-bottom: 16px; padding: 14px; background: #f8f9fa; border-radius: 12px; }
|
|
2889
|
+
.group-avatar { width: 65px; height: 65px; border-radius: 50%; margin-right: 12px; border: 2px solid #e9ecef; }
|
|
2890
|
+
.group-info { flex: 1; }
|
|
2891
|
+
.group-name { font-size: 24px; font-weight: 600; color: #212529; margin-bottom: 2px; }
|
|
2892
|
+
.group-details { font-size: 14px; color: #6c757d; }
|
|
2893
|
+
|
|
2894
|
+
.title { font-size: 32px; font-weight: 600; margin-bottom: 12px; color: #212529; text-align: center; }
|
|
2895
|
+
.pagination-info { font-size: 14px; color: #6c757d; text-align: center; margin-bottom: 12px; }
|
|
2896
|
+
|
|
2897
|
+
.essence-list { width: 100%; display: flex; flex-direction: column; gap: 8px; }
|
|
2898
|
+
|
|
2899
|
+
.essence-item { background: #f8f9fa; border-radius: 10px; padding: 12px; display: flex; align-items: flex-start; transition: background 0.2s ease; min-height: 65px; }
|
|
2900
|
+
.essence-item:hover { background: #e9ecef; }
|
|
2901
|
+
|
|
2902
|
+
.essence-column-1 { display: flex; flex-direction: row; align-items: center; margin-right: 10px; min-width: 85px; }
|
|
2903
|
+
.essence-avatar img { width: 50px; height: 50px; border-radius: 50%; border: 1px solid #dee2e6; }
|
|
2904
|
+
.essence-number { font-size: 18px; margin: 0 8px 0 0; font-weight: 600; color: #adb5bd; }
|
|
2905
|
+
|
|
2906
|
+
.essence-column-2 { min-width: 100px; margin-right: 12px; }
|
|
2907
|
+
.essence-sender { font-size: 15px; color: #212529; font-weight: 600; margin-bottom: 2px; }
|
|
2908
|
+
.essence-sender-id { font-size: 12px; }
|
|
2909
|
+
.qq-label { color: #6c757d; }
|
|
2910
|
+
.qq-number { color: #495057; font-family: 'Courier New', monospace; }
|
|
2911
|
+
|
|
2912
|
+
.essence-column-3 { flex: 1; }
|
|
2913
|
+
.essence-content { font-size: 14px; color: #495057; line-height: 1.4; margin-bottom: 5px; word-break: break-all; white-space: pre-wrap; max-height: 130px; overflow: hidden; position: relative; }
|
|
2914
|
+
.essence-content::after { content: ''; position: absolute; bottom: 0; right: 0; width: 100%; height: 1.4em; background: linear-gradient(to bottom, transparent, rgba(248,249,250,0.95)); pointer-events: none; }
|
|
2915
|
+
.essence-item:hover .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(233,236,239,0.95)); }
|
|
2916
|
+
.essence-meta { font-size: 11px; color: #adb5bd; display: flex; gap: 12px; flex-wrap: wrap; }
|
|
2917
|
+
.essence-time { color: #6c757d; }
|
|
2918
|
+
.essence-operator { color: #fd7e14; }
|
|
2919
|
+
|
|
2920
|
+
/* 消息内容元素样式 */
|
|
2921
|
+
.msg-text { }
|
|
2922
|
+
.msg-reply { display: inline-flex; align-items: center; background: #e9ecef; border-left: 3px solid #adb5bd; padding: 2px 7px; margin: 2px 4px 2px 0; border-radius: 0 5px 5px 0; font-size: 11px; color: #6c757d; }
|
|
2923
|
+
.msg-reply .reply-icon { margin-right: 3px; font-size: 10px; }
|
|
2924
|
+
.msg-reply .reply-text { font-style: italic; }
|
|
2925
|
+
.msg-image-wrapper { display: inline-block; margin: 3px 4px 3px 0; vertical-align: middle; }
|
|
2926
|
+
.msg-image-preview { max-width: 65px; max-height: 65px; border-radius: 5px; border: 1px solid #dee2e6; object-fit: cover; vertical-align: middle; }
|
|
2927
|
+
.msg-image-placeholder, .msg-image-fallback { color: #adb5bd; font-style: italic; }
|
|
2928
|
+
.msg-at { color: #0d6efd; font-weight: 500; }
|
|
2929
|
+
.msg-face { color: #fd7e14; }
|
|
2930
|
+
.msg-forward, .msg-video, .msg-record, .msg-file { color: #6c757d; font-style: italic; background: #e9ecef; padding: 1px 5px; border-radius: 3px; }
|
|
2931
|
+
.msg-unknown { color: #adb5bd; }
|
|
2932
|
+
.empty-msg { color: #adb5bd; font-style: italic; }
|
|
2933
|
+
|
|
2934
|
+
.timestamp-watermark { position: fixed; top: 1px; left: 1px; font-size: 11px; color: rgba(128, 128, 128, 0.4); font-family: 'Courier New', monospace; z-index: 9999; }
|
|
2935
|
+
|
|
2936
|
+
body.dark { background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); color: #e9ecef; }
|
|
2937
|
+
body.dark .card { background: #212529; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); }
|
|
2938
|
+
body.dark .group-header { background: #343a40; }
|
|
2939
|
+
body.dark .group-avatar { border-color: #495057; }
|
|
2940
|
+
body.dark .group-name { color: #f8f9fa; }
|
|
2941
|
+
body.dark .group-details { color: #adb5bd; }
|
|
2942
|
+
body.dark .title { color: #f8f9fa; }
|
|
2943
|
+
body.dark .pagination-info { color: #adb5bd; }
|
|
2944
|
+
body.dark .essence-item { background: #343a40; }
|
|
2945
|
+
body.dark .essence-item:hover { background: #495057; }
|
|
2946
|
+
body.dark .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(52,58,64,0.95)); }
|
|
2947
|
+
body.dark .essence-item:hover .essence-content::after { background: linear-gradient(to bottom, transparent, rgba(73,80,87,0.95)); }
|
|
2948
|
+
body.dark .essence-number { color: #6c757d; }
|
|
2949
|
+
body.dark .essence-sender { color: #f8f9fa; }
|
|
2950
|
+
body.dark .qq-label { color: #adb5bd; }
|
|
2951
|
+
body.dark .qq-number { color: #e9ecef; }
|
|
2952
|
+
body.dark .essence-content { color: #ced4da; }
|
|
2953
|
+
body.dark .essence-time { color: #adb5bd; }
|
|
2954
|
+
body.dark .essence-operator { color: #ffc107; }
|
|
2955
|
+
body.dark .msg-reply { background: #495057; border-left-color: #6c757d; color: #adb5bd; }
|
|
2956
|
+
body.dark .msg-at { color: #6ea8fe; }
|
|
2957
|
+
body.dark .msg-face { color: #ffc107; }
|
|
2958
|
+
body.dark .msg-forward, body.dark .msg-video, body.dark .msg-record, body.dark .msg-file { background: #495057; color: #adb5bd; }
|
|
2959
|
+
body.dark .msg-image-preview { border-color: #495057; }
|
|
2960
|
+
body.dark .timestamp-watermark { color: rgba(200, 200, 200, 0.3); }
|
|
2961
|
+
</style>
|
|
2962
|
+
</head>
|
|
2963
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
2964
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
2965
|
+
<div class="card">
|
|
2966
|
+
<div class="group-header">
|
|
2967
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
2968
|
+
<div class="group-info">
|
|
2969
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
2970
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
2971
|
+
</div>
|
|
2972
|
+
</div>
|
|
2973
|
+
<div class="title">📌 群精华消息</div>
|
|
2974
|
+
<div class="pagination-info">第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条精华)</div>
|
|
2975
|
+
<div class="essence-list">
|
|
2976
|
+
${generateEssenceListItems(result.records, result.currentPage, result.pageSize)}
|
|
2977
|
+
</div>
|
|
2978
|
+
</div>
|
|
2979
|
+
</body>
|
|
2980
|
+
</html>`;
|
|
2981
|
+
}, "getFlatMinimalStyleEssenceHtmlStr");
|
|
2982
|
+
async function renderGroupEssence(ctx, result, contextInfo, imageStyle, enableDarkMode, imageType, screenshotQuality) {
|
|
2983
|
+
const groupAvatarBase64 = await getGroupAvatarBase64(ctx, contextInfo.groupId.toString());
|
|
2984
|
+
const fontBase64 = await getFontBase64(ctx, imageStyle);
|
|
2985
|
+
let htmlContent;
|
|
2986
|
+
switch (imageStyle) {
|
|
2987
|
+
case IMAGE_STYLES.SOURCE_HAN_SERIF_SC:
|
|
2988
|
+
htmlContent = await getSourceHanSerifSCStyleEssenceHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
2989
|
+
break;
|
|
2990
|
+
case IMAGE_STYLES.LXGW_WENKAI:
|
|
2991
|
+
htmlContent = await getLXGWWenKaiStyleEssenceHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
2992
|
+
break;
|
|
2993
|
+
case IMAGE_STYLES.FLAT_MINIMAL:
|
|
2994
|
+
htmlContent = await getFlatMinimalStyleEssenceHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
2995
|
+
break;
|
|
2996
|
+
default:
|
|
2997
|
+
htmlContent = await getSourceHanSerifSCStyleEssenceHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
2998
|
+
}
|
|
2999
|
+
const page = await ctx.puppeteer.page();
|
|
3000
|
+
try {
|
|
3001
|
+
await page.setViewport({ width: 900, height: 1 });
|
|
3002
|
+
await page.setContent(htmlContent, { waitUntil: "domcontentloaded" });
|
|
3003
|
+
const bodyElement = await page.$("body");
|
|
3004
|
+
const boundingBox = await bodyElement?.boundingBox();
|
|
3005
|
+
if (!boundingBox) {
|
|
3006
|
+
throw new Error("无法获取页面元素的边界框");
|
|
3007
|
+
}
|
|
3008
|
+
const screenshot = await page.screenshot({
|
|
3009
|
+
type: imageType,
|
|
3010
|
+
encoding: "base64",
|
|
3011
|
+
clip: boundingBox,
|
|
3012
|
+
quality: imageType === "png" ? void 0 : screenshotQuality
|
|
1928
3013
|
});
|
|
3014
|
+
return screenshot;
|
|
3015
|
+
} finally {
|
|
3016
|
+
await page.close();
|
|
1929
3017
|
}
|
|
1930
|
-
|
|
3018
|
+
}
|
|
3019
|
+
__name(renderGroupEssence, "renderGroupEssence");
|
|
3020
|
+
|
|
3021
|
+
// src/commandGroupEssence.ts
|
|
3022
|
+
function paginateEssenceMessages(essenceList, page, pageSize) {
|
|
3023
|
+
const totalCount = essenceList.length;
|
|
3024
|
+
const totalPages = Math.ceil(totalCount / pageSize);
|
|
3025
|
+
const startIndex = (page - 1) * pageSize;
|
|
3026
|
+
const endIndex = startIndex + pageSize;
|
|
3027
|
+
const records = essenceList.slice(startIndex, endIndex);
|
|
3028
|
+
return {
|
|
3029
|
+
records,
|
|
3030
|
+
totalCount,
|
|
3031
|
+
currentPage: page,
|
|
3032
|
+
pageSize,
|
|
3033
|
+
totalPages,
|
|
3034
|
+
hasNext: page < totalPages,
|
|
3035
|
+
hasPrev: page > 1
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
__name(paginateEssenceMessages, "paginateEssenceMessages");
|
|
3039
|
+
function parseEssenceContent(content) {
|
|
3040
|
+
if (!content || content.length === 0) {
|
|
3041
|
+
return "[空消息]";
|
|
3042
|
+
}
|
|
3043
|
+
return content.map((item) => {
|
|
3044
|
+
switch (item.type) {
|
|
3045
|
+
case "text":
|
|
3046
|
+
return item.data.text || "";
|
|
3047
|
+
case "image":
|
|
3048
|
+
return "[图片]";
|
|
3049
|
+
case "face":
|
|
3050
|
+
return `[表情:${item.data.id || ""}]`;
|
|
3051
|
+
case "at":
|
|
3052
|
+
return `@${item.data.qq || item.data.name || "某人"}`;
|
|
3053
|
+
case "reply":
|
|
3054
|
+
return `[回复:${item.data.id || ""}]`;
|
|
3055
|
+
case "forward":
|
|
3056
|
+
return "[转发消息]";
|
|
3057
|
+
case "video":
|
|
3058
|
+
return "[视频]";
|
|
3059
|
+
case "record":
|
|
3060
|
+
return "[语音]";
|
|
3061
|
+
case "file":
|
|
3062
|
+
return "[文件]";
|
|
3063
|
+
default:
|
|
3064
|
+
return `[${item.type}]`;
|
|
3065
|
+
}
|
|
3066
|
+
}).join("");
|
|
3067
|
+
}
|
|
3068
|
+
__name(parseEssenceContent, "parseEssenceContent");
|
|
3069
|
+
function formatTimestamp(timestamp) {
|
|
3070
|
+
const date = new Date(timestamp * 1e3);
|
|
3071
|
+
return date.toLocaleString("zh-CN", {
|
|
3072
|
+
year: "numeric",
|
|
3073
|
+
month: "2-digit",
|
|
3074
|
+
day: "2-digit",
|
|
3075
|
+
hour: "2-digit",
|
|
3076
|
+
minute: "2-digit"
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
3079
|
+
__name(formatTimestamp, "formatTimestamp");
|
|
3080
|
+
function registerGroupEssenceCommand(ctx, config, responseHint) {
|
|
3081
|
+
if (!config.enableGroupEssenceCommand) return;
|
|
3082
|
+
ctx.command(config.groupEssenceCommandName, `获取群精华消息列表, 发送${responseHint}`).alias("群精华列表").alias("age").option("page", "-p, --page <page:number> 页码,从1开始", { fallback: 1 }).option("pagesize", "-s, --pagesize <pagesize:number> 每页显示条数", { fallback: config.groupEssencePageSize || 5 }).option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }) => {
|
|
3083
|
+
if (!session.onebot)
|
|
3084
|
+
return session.send("[error]当前会话不支持onebot协议。");
|
|
3085
|
+
if (!session.guildId)
|
|
3086
|
+
return session.send("[error]当前会话不在群聊中。");
|
|
3087
|
+
const page = Math.max(1, options.page || 1);
|
|
3088
|
+
const pageSize = Math.max(1, Math.min(50, options.pagesize || config.groupEssencePageSize || 5));
|
|
3089
|
+
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
3090
|
+
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
3091
|
+
if (options.imageStyleIdx !== void 0) {
|
|
3092
|
+
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
3093
|
+
if (!isIdxValid) {
|
|
3094
|
+
let idxInvalidMsgArr = [
|
|
3095
|
+
`图片样式索引不合法。`,
|
|
3096
|
+
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
3097
|
+
` 当前输入:${options.imageStyleIdx}`,
|
|
3098
|
+
`
|
|
3099
|
+
`,
|
|
3100
|
+
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
3101
|
+
];
|
|
3102
|
+
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
3103
|
+
}
|
|
3104
|
+
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
3105
|
+
}
|
|
1931
3106
|
try {
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
await
|
|
3107
|
+
const onebotBot = session.onebot;
|
|
3108
|
+
const groupEssenceMsgList = await onebotBot.getEssenceMsgList(session.guildId);
|
|
3109
|
+
if (!groupEssenceMsgList || groupEssenceMsgList.length === 0) {
|
|
3110
|
+
return session.send("该群暂无精华消息。");
|
|
3111
|
+
}
|
|
3112
|
+
const paginatedResult = paginateEssenceMessages(groupEssenceMsgList, page, pageSize);
|
|
3113
|
+
if (paginatedResult.records.length === 0) {
|
|
3114
|
+
return session.send(`第${page}页没有记录,共${paginatedResult.totalPages}页`);
|
|
3115
|
+
}
|
|
3116
|
+
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
3117
|
+
const contextInfo = {
|
|
3118
|
+
groupId: parseInt(session.guildId),
|
|
3119
|
+
groupName: groupInfoObj.group_name || "未知群聊",
|
|
3120
|
+
memberCount: groupInfoObj.member_count || 0,
|
|
3121
|
+
maxMemberCount: groupInfoObj.max_member_count || 0,
|
|
3122
|
+
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`
|
|
3123
|
+
};
|
|
3124
|
+
if (config.verboseConsoleOutput) {
|
|
3125
|
+
ctx.logger.info(`群精华消息分页结果: ${JSON.stringify(paginatedResult)}`);
|
|
3126
|
+
}
|
|
3127
|
+
if (config.sendText) {
|
|
3128
|
+
const textMessage = formatGroupEssenceAsText(paginatedResult, contextInfo, config);
|
|
3129
|
+
await session.send(`${config.enableQuoteWithText ? import_koishi3.h.quote(session.messageId) : ""}${textMessage}`);
|
|
3130
|
+
}
|
|
3131
|
+
if (config.sendImage) {
|
|
3132
|
+
const waitTipMsgId = await session.send(`${import_koishi3.h.quote(session.messageId)}🔄正在渲染群精华列表图片,请稍候⏳...`);
|
|
3133
|
+
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
3134
|
+
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
3135
|
+
const essenceImageBase64 = await renderGroupEssence(
|
|
3136
|
+
ctx,
|
|
3137
|
+
paginatedResult,
|
|
3138
|
+
contextInfo,
|
|
3139
|
+
selectedImageStyle,
|
|
3140
|
+
selectedDarkMode,
|
|
3141
|
+
config.imageType,
|
|
3142
|
+
config.screenshotQuality
|
|
3143
|
+
);
|
|
3144
|
+
let imageMessage = `${config.enableQuoteWithImage ? import_koishi3.h.quote(session.messageId) : ""}${import_koishi3.h.image(`data:image/png;base64,${essenceImageBase64}`)}`;
|
|
3145
|
+
if (paginatedResult.totalPages > 1) {
|
|
3146
|
+
imageMessage += `
|
|
3147
|
+
📄 第 ${paginatedResult.currentPage}/${paginatedResult.totalPages} 页`;
|
|
3148
|
+
if (paginatedResult.hasPrev) {
|
|
3149
|
+
imageMessage += ` | ◀ ${config.groupEssenceCommandName} -p ${paginatedResult.currentPage - 1}`;
|
|
3150
|
+
}
|
|
3151
|
+
if (paginatedResult.hasNext) {
|
|
3152
|
+
imageMessage += ` | ▶ ${config.groupEssenceCommandName} -p ${paginatedResult.currentPage + 1}`;
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
imageMessage += `
|
|
3156
|
+
📖 用法: ${config.groupEssenceCommandName} -p <页码> -s <每页条数>`;
|
|
3157
|
+
await session.send(imageMessage);
|
|
3158
|
+
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
3159
|
+
}
|
|
3160
|
+
if (config.sendForward) {
|
|
3161
|
+
const forwardMessage = formatGroupEssenceAsForward(paginatedResult, contextInfo, config);
|
|
3162
|
+
await session.send(import_koishi3.h.unescape(forwardMessage));
|
|
3163
|
+
}
|
|
3164
|
+
} catch (error) {
|
|
3165
|
+
ctx.logger.error(`获取群精华消息失败: ${error}`);
|
|
3166
|
+
await session.send(`[error]获取群精华消息失败: ${error.message}`);
|
|
3167
|
+
}
|
|
3168
|
+
});
|
|
3169
|
+
}
|
|
3170
|
+
__name(registerGroupEssenceCommand, "registerGroupEssenceCommand");
|
|
3171
|
+
function formatGroupEssenceAsText(result, contextInfo, config) {
|
|
3172
|
+
let output = "";
|
|
3173
|
+
output += `===== 群精华消息列表 =====
|
|
3174
|
+
`;
|
|
3175
|
+
output += `群名称: ${contextInfo.groupName}
|
|
3176
|
+
`;
|
|
3177
|
+
output += `群号: ${contextInfo.groupId}
|
|
3178
|
+
`;
|
|
3179
|
+
output += `第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条精华)
|
|
3180
|
+
|
|
3181
|
+
`;
|
|
3182
|
+
result.records.forEach((record, index) => {
|
|
3183
|
+
const globalIndex = (result.currentPage - 1) * result.pageSize + index + 1;
|
|
3184
|
+
output += `-----No. ${globalIndex}-----
|
|
3185
|
+
`;
|
|
3186
|
+
output += `发送者: ${record.sender_nick} (${record.sender_id})
|
|
3187
|
+
`;
|
|
3188
|
+
output += `设精华: ${record.operator_nick} (${record.operator_id})
|
|
3189
|
+
`;
|
|
3190
|
+
output += `时间: ${formatTimestamp(record.operator_time)}
|
|
3191
|
+
`;
|
|
3192
|
+
output += `内容: ${parseEssenceContent(record.content)}
|
|
3193
|
+
|
|
3194
|
+
`;
|
|
3195
|
+
});
|
|
3196
|
+
if (result.totalPages > 1) {
|
|
3197
|
+
output += `------------------
|
|
3198
|
+
`;
|
|
3199
|
+
if (result.hasPrev) {
|
|
3200
|
+
output += `上一页: ${config.groupEssenceCommandName} -p ${result.currentPage - 1} -s ${result.pageSize}
|
|
3201
|
+
`;
|
|
3202
|
+
}
|
|
3203
|
+
if (result.hasNext) {
|
|
3204
|
+
output += `下一页: ${config.groupEssenceCommandName} -p ${result.currentPage + 1} -s ${result.pageSize}
|
|
3205
|
+
`;
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
output += `
|
|
3209
|
+
==================
|
|
3210
|
+
`;
|
|
3211
|
+
output += `📖 参数用法:
|
|
3212
|
+
`;
|
|
3213
|
+
output += ` -p, --page <页码> 指定页码(从1开始)
|
|
3214
|
+
`;
|
|
3215
|
+
output += ` -s, --pagesize <条数> 每页显示条数
|
|
3216
|
+
`;
|
|
3217
|
+
output += `📝 示例:
|
|
3218
|
+
`;
|
|
3219
|
+
output += ` ${config.groupEssenceCommandName} -p 2 查看第2页
|
|
3220
|
+
`;
|
|
3221
|
+
output += ` ${config.groupEssenceCommandName} -s 10 每页显示10条
|
|
3222
|
+
`;
|
|
3223
|
+
output += ` ${config.groupEssenceCommandName} -p 3 -s 8 第3页,每页8条
|
|
3224
|
+
`;
|
|
3225
|
+
return output;
|
|
3226
|
+
}
|
|
3227
|
+
__name(formatGroupEssenceAsText, "formatGroupEssenceAsText");
|
|
3228
|
+
function formatGroupEssenceAsForward(result, contextInfo, config) {
|
|
3229
|
+
let messages = "";
|
|
3230
|
+
const addMessageBlock = /* @__PURE__ */ __name((authorId, authorName, content) => {
|
|
3231
|
+
messages += `
|
|
3232
|
+
<message>
|
|
3233
|
+
<author ${authorId ? `id="${authorId}"` : ""} name="${authorName}"/>
|
|
3234
|
+
${content}
|
|
3235
|
+
</message>`;
|
|
3236
|
+
}, "addMessageBlock");
|
|
3237
|
+
addMessageBlock(
|
|
3238
|
+
void 0,
|
|
3239
|
+
"群精华消息列表",
|
|
3240
|
+
[
|
|
3241
|
+
`群名称: ${contextInfo.groupName}`,
|
|
3242
|
+
`群号: ${contextInfo.groupId}`,
|
|
3243
|
+
`第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条精华)`
|
|
3244
|
+
].join("\n")
|
|
3245
|
+
);
|
|
3246
|
+
result.records.forEach((record, index) => {
|
|
3247
|
+
const globalIndex = (result.currentPage - 1) * result.pageSize + index + 1;
|
|
3248
|
+
const messageContent = [
|
|
3249
|
+
`-----No. ${globalIndex}-----`,
|
|
3250
|
+
`发送者: ${record.sender_nick} (${record.sender_id})`,
|
|
3251
|
+
`设精华: ${record.operator_nick} (${record.operator_id})`,
|
|
3252
|
+
`时间: ${formatTimestamp(record.operator_time)}`,
|
|
3253
|
+
`内容: ${parseEssenceContent(record.content)}`
|
|
3254
|
+
].join("\n");
|
|
3255
|
+
addMessageBlock(
|
|
3256
|
+
record.sender_id.toString(),
|
|
3257
|
+
record.sender_nick,
|
|
3258
|
+
messageContent
|
|
3259
|
+
);
|
|
3260
|
+
});
|
|
3261
|
+
if (result.totalPages > 1) {
|
|
3262
|
+
let navText = "";
|
|
3263
|
+
if (result.hasPrev) {
|
|
3264
|
+
navText += `上一页: ${config.groupEssenceCommandName} -p ${result.currentPage - 1} -s ${result.pageSize}
|
|
3265
|
+
`;
|
|
3266
|
+
}
|
|
3267
|
+
if (result.hasNext) {
|
|
3268
|
+
navText += `下一页: ${config.groupEssenceCommandName} -p ${result.currentPage + 1} -s ${result.pageSize}`;
|
|
3269
|
+
}
|
|
3270
|
+
if (navText) {
|
|
3271
|
+
addMessageBlock(void 0, "分页导航", navText);
|
|
3272
|
+
}
|
|
3273
|
+
}
|
|
3274
|
+
const usageText = [
|
|
3275
|
+
`📖 参数用法:`,
|
|
3276
|
+
` -p, --page <页码> 指定页码(从1开始)`,
|
|
3277
|
+
` -s, --pagesize <条数> 每页显示条数`,
|
|
3278
|
+
`📝 示例:`,
|
|
3279
|
+
` ${config.groupEssenceCommandName} -p 2 查看第2页`,
|
|
3280
|
+
` ${config.groupEssenceCommandName} -s 10 每页显示10条`,
|
|
3281
|
+
` ${config.groupEssenceCommandName} -p 3 -s 8 第3页,每页8条`
|
|
3282
|
+
].join("\n");
|
|
3283
|
+
addMessageBlock(void 0, "参数用法", usageText);
|
|
3284
|
+
return `<message forward>
|
|
3285
|
+
${messages}
|
|
3286
|
+
</message>`;
|
|
3287
|
+
}
|
|
3288
|
+
__name(formatGroupEssenceAsForward, "formatGroupEssenceAsForward");
|
|
3289
|
+
|
|
3290
|
+
// src/commandGroupEssenceDetail.ts
|
|
3291
|
+
var import_koishi4 = require("koishi");
|
|
3292
|
+
|
|
3293
|
+
// src/renderGroupEssenceDetail.ts
|
|
3294
|
+
function parseEssenceContentToHtmlFull(content) {
|
|
3295
|
+
if (!content || content.length === 0) {
|
|
3296
|
+
return '<span class="empty-msg">[空消息]</span>';
|
|
3297
|
+
}
|
|
3298
|
+
return content.map((item) => {
|
|
3299
|
+
switch (item.type) {
|
|
3300
|
+
case "text":
|
|
3301
|
+
const text = (item.data.text || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br/>");
|
|
3302
|
+
return `<span class="msg-text">${text}</span>`;
|
|
3303
|
+
case "image":
|
|
3304
|
+
const imageUrl = item.data.url || "";
|
|
3305
|
+
if (imageUrl) {
|
|
3306
|
+
return `<div class="msg-image-wrapper-large"><img class="msg-image-preview-large" src="${imageUrl}" alt="图片" onerror="this.style.display='none';this.nextSibling.style.display='inline';" /><span class="msg-image-fallback" style="display:none;">[图片]</span></div>`;
|
|
3307
|
+
}
|
|
3308
|
+
return '<span class="msg-image-placeholder">[图片]</span>';
|
|
3309
|
+
case "face":
|
|
3310
|
+
return `<span class="msg-face">[表情:${item.data.id || ""}]</span>`;
|
|
3311
|
+
case "at":
|
|
3312
|
+
return `<span class="msg-at">@${item.data.qq || item.data.name || "某人"}</span>`;
|
|
3313
|
+
case "reply":
|
|
3314
|
+
const replyUserId = item.data.id || item.data.qq || "";
|
|
3315
|
+
return `<span class="msg-reply"><span class="reply-icon">↩</span><span class="reply-text">回复${replyUserId ? ` [${replyUserId}]` : "消息"}</span></span>`;
|
|
3316
|
+
case "forward":
|
|
3317
|
+
return '<span class="msg-forward">[转发消息]</span>';
|
|
3318
|
+
case "video":
|
|
3319
|
+
return '<span class="msg-video">[视频]</span>';
|
|
3320
|
+
case "record":
|
|
3321
|
+
return '<span class="msg-record">[语音]</span>';
|
|
3322
|
+
case "file":
|
|
3323
|
+
return '<span class="msg-file">[文件]</span>';
|
|
3324
|
+
default:
|
|
3325
|
+
return `<span class="msg-unknown">[${item.type}]</span>`;
|
|
3326
|
+
}
|
|
3327
|
+
}).join("");
|
|
3328
|
+
}
|
|
3329
|
+
__name(parseEssenceContentToHtmlFull, "parseEssenceContentToHtmlFull");
|
|
3330
|
+
var getSourceHanSerifSCStyleDetailHtmlStr = /* @__PURE__ */ __name(async (record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
3331
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: radial-gradient(circle at center, rgba(255,255,255,0.15), rgba(0,0,0,0.1)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : "background: linear-gradient(135deg, #f8f9fa, #e9ecef);";
|
|
3332
|
+
const timestamp = generateTimestamp();
|
|
3333
|
+
const contentHtml = parseEssenceContentToHtmlFull(record.content);
|
|
3334
|
+
const timeStr = formatTimestamp(record.operator_time);
|
|
3335
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
3336
|
+
const operatorAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.operator_id}&s=640`;
|
|
3337
|
+
return `<!DOCTYPE html>
|
|
3338
|
+
<html>
|
|
3339
|
+
<head>
|
|
3340
|
+
<style>
|
|
3341
|
+
${fontBase64 ? `@font-face { font-family: 'SourceHanSerifSC-Medium'; src: url('data:font/opentype;charset=utf-8;base64,${fontBase64}') format('opentype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
3342
|
+
|
|
3343
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
3344
|
+
body {
|
|
3345
|
+
font-family: ${fontBase64 ? "'SourceHanSerifSC-Medium'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
3346
|
+
width: 850px;
|
|
3347
|
+
height: auto;
|
|
3348
|
+
min-height: 100vh;
|
|
3349
|
+
display: flex;
|
|
3350
|
+
align-items: center;
|
|
3351
|
+
justify-content: center;
|
|
3352
|
+
${backgroundStyle}
|
|
3353
|
+
background-repeat: no-repeat;
|
|
3354
|
+
position: relative;
|
|
3355
|
+
box-sizing: border-box;
|
|
3356
|
+
overflow: visible;
|
|
3357
|
+
color: #333;
|
|
3358
|
+
padding: 35px;
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3361
|
+
.card {
|
|
3362
|
+
width: 720px;
|
|
3363
|
+
height: auto;
|
|
3364
|
+
min-height: 400px;
|
|
3365
|
+
background: rgba(255, 255, 255, 0.25);
|
|
3366
|
+
backdrop-filter: blur(20px) saturate(180%);
|
|
3367
|
+
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
3368
|
+
border-radius: 24px;
|
|
3369
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
3370
|
+
position: relative;
|
|
3371
|
+
overflow: visible;
|
|
3372
|
+
display: flex;
|
|
3373
|
+
flex-direction: column;
|
|
3374
|
+
padding: 32px;
|
|
3375
|
+
box-sizing: border-box;
|
|
3376
|
+
}
|
|
3377
|
+
|
|
3378
|
+
.group-header { display: flex; align-items: center; margin-bottom: 20px; padding: 18px; background: rgba(255,255,255,0.3); border: 1px solid rgba(255,255,255,0.4); border-radius: 18px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
|
|
3379
|
+
.group-avatar { width: 65px; height: 65px; border-radius: 50%; margin-right: 14px; border: 3px solid rgba(255,255,255,0.6); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
3380
|
+
.group-info { flex: 1; }
|
|
3381
|
+
.group-name { font-size: 24px; font-weight: 700; color: #1a1a1a; margin-bottom: 4px; text-shadow: 0 1px 2px rgba(0,0,0,0.1); }
|
|
3382
|
+
.group-details { font-size: 16px; color: #4a4a4a; line-height: 1.3; font-weight: 500; }
|
|
3383
|
+
|
|
3384
|
+
.title { font-size: 36px; font-weight: 700; margin-bottom: 10px; color: #1a1a1a; text-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }
|
|
3385
|
+
.subtitle { font-size: 16px; color: #666; text-align: center; margin-bottom: 20px; }
|
|
3386
|
+
|
|
3387
|
+
.sender-section { display: flex; align-items: center; padding: 16px; background: rgba(255,255,255,0.5); border-radius: 14px; margin-bottom: 16px; }
|
|
3388
|
+
.sender-avatar { width: 70px; height: 70px; border-radius: 50%; margin-right: 16px; border: 3px solid rgba(255,255,255,0.8); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
3389
|
+
.sender-info { flex: 1; }
|
|
3390
|
+
.sender-name { font-size: 22px; font-weight: 600; color: #1a1a1a; margin-bottom: 4px; }
|
|
3391
|
+
.sender-id { font-size: 14px; color: #666; }
|
|
3392
|
+
.qq-label { color: #888; }
|
|
3393
|
+
.qq-number { color: #1a1a1a; font-family: 'Courier New', monospace; font-weight: 600; }
|
|
3394
|
+
|
|
3395
|
+
.content-section { background: rgba(255,255,255,0.6); border-radius: 14px; padding: 20px; margin-bottom: 16px; }
|
|
3396
|
+
.content-title { font-size: 14px; color: #888; margin-bottom: 10px; font-weight: 500; }
|
|
3397
|
+
.content-body { font-size: 17px; color: #333; line-height: 1.7; word-break: break-all; white-space: pre-wrap; }
|
|
3398
|
+
|
|
3399
|
+
.meta-section { display: flex; align-items: center; padding: 14px 16px; background: rgba(255,255,255,0.4); border-radius: 12px; }
|
|
3400
|
+
.operator-avatar { width: 40px; height: 40px; border-radius: 50%; margin-right: 12px; border: 2px solid rgba(255,255,255,0.8); }
|
|
3401
|
+
.meta-info { flex: 1; }
|
|
3402
|
+
.meta-time { font-size: 14px; color: #666; margin-bottom: 2px; }
|
|
3403
|
+
.meta-operator { font-size: 14px; color: #ff8c00; }
|
|
3404
|
+
|
|
3405
|
+
/* 消息内容元素样式 */
|
|
3406
|
+
.msg-text { }
|
|
3407
|
+
.msg-reply { display: inline-flex; align-items: center; background: rgba(100,100,100,0.15); border-left: 3px solid #888; padding: 3px 10px; margin: 4px 6px 4px 0; border-radius: 0 8px 8px 0; font-size: 14px; color: #666; }
|
|
3408
|
+
.msg-reply .reply-icon { margin-right: 5px; font-size: 13px; }
|
|
3409
|
+
.msg-reply .reply-text { font-style: italic; }
|
|
3410
|
+
.msg-image-wrapper-large { display: block; margin: 12px 0; }
|
|
3411
|
+
.msg-image-preview-large { max-width: 100%; max-height: 400px; border-radius: 10px; border: 1px solid rgba(0,0,0,0.1); object-fit: contain; }
|
|
3412
|
+
.msg-image-placeholder, .msg-image-fallback { color: #888; font-style: italic; }
|
|
3413
|
+
.msg-at { color: #1e90ff; font-weight: 500; }
|
|
3414
|
+
.msg-face { color: #ff9800; }
|
|
3415
|
+
.msg-forward, .msg-video, .msg-record, .msg-file { color: #888; font-style: italic; background: rgba(0,0,0,0.05); padding: 2px 8px; border-radius: 4px; }
|
|
3416
|
+
.msg-unknown { color: #999; }
|
|
3417
|
+
.empty-msg { color: #999; font-style: italic; }
|
|
3418
|
+
|
|
3419
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(128, 128, 128, 0.6); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
3420
|
+
|
|
3421
|
+
body.dark { color: #e0e0e0; }
|
|
3422
|
+
body.dark .card { background: rgba(20,20,20,0.4); box-shadow: 0 20px 60px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.15); }
|
|
3423
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(255,255,255,0.15); }
|
|
3424
|
+
body.dark .group-name { color: #ffffff; }
|
|
3425
|
+
body.dark .group-details { color: #b0b0b0; }
|
|
3426
|
+
body.dark .title { color: #ffffff; text-shadow: 0 2px 4px rgba(0,0,0,0.4); }
|
|
3427
|
+
body.dark .subtitle { color: #aaa; }
|
|
3428
|
+
body.dark .sender-section { background: rgba(40,40,40,0.6); }
|
|
3429
|
+
body.dark .sender-name { color: #fff; }
|
|
3430
|
+
body.dark .sender-id { color: #aaa; }
|
|
3431
|
+
body.dark .qq-label { color: #888; }
|
|
3432
|
+
body.dark .qq-number { color: #fff; }
|
|
3433
|
+
body.dark .content-section { background: rgba(40,40,40,0.6); }
|
|
3434
|
+
body.dark .content-title { color: #888; }
|
|
3435
|
+
body.dark .content-body { color: #e0e0e0; }
|
|
3436
|
+
body.dark .meta-section { background: rgba(40,40,40,0.5); }
|
|
3437
|
+
body.dark .meta-time { color: #aaa; }
|
|
3438
|
+
body.dark .meta-operator { color: #ffa07a; }
|
|
3439
|
+
body.dark .msg-reply { background: rgba(150,150,150,0.2); border-left-color: #aaa; color: #bbb; }
|
|
3440
|
+
body.dark .msg-at { color: #4da6ff; }
|
|
3441
|
+
body.dark .msg-face { color: #ffb74d; }
|
|
3442
|
+
body.dark .msg-forward, body.dark .msg-video, body.dark .msg-record, body.dark .msg-file { background: rgba(255,255,255,0.1); color: #aaa; }
|
|
3443
|
+
body.dark .msg-image-preview-large { border-color: rgba(255,255,255,0.2); }
|
|
3444
|
+
body.dark .timestamp-watermark { color: rgba(160, 160, 160, 0.5); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
3445
|
+
</style>
|
|
3446
|
+
</head>
|
|
3447
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
3448
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
3449
|
+
<div class="card">
|
|
3450
|
+
<div class="group-header">
|
|
3451
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
3452
|
+
<div class="group-info">
|
|
3453
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
3454
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
3455
|
+
</div>
|
|
3456
|
+
</div>
|
|
3457
|
+
<div class="title">📌 群精华详情</div>
|
|
3458
|
+
<div class="subtitle">第 ${contextInfo.essenceIndex}/${contextInfo.totalEssenceCount} 条精华消息</div>
|
|
3459
|
+
<div class="sender-section">
|
|
3460
|
+
<img class="sender-avatar" src="${senderAvatarUrl}" alt="发送者头像" />
|
|
3461
|
+
<div class="sender-info">
|
|
3462
|
+
<div class="sender-name">${record.sender_nick || "未知"}</div>
|
|
3463
|
+
<div class="sender-id"><span class="qq-label">QQ:</span> <span class="qq-number">${record.sender_id}</span></div>
|
|
3464
|
+
</div>
|
|
3465
|
+
</div>
|
|
3466
|
+
<div class="content-section">
|
|
3467
|
+
<div class="content-title">💬 消息内容</div>
|
|
3468
|
+
<div class="content-body">${contentHtml}</div>
|
|
3469
|
+
</div>
|
|
3470
|
+
<div class="meta-section">
|
|
3471
|
+
<img class="operator-avatar" src="${operatorAvatarUrl}" alt="操作者头像" />
|
|
3472
|
+
<div class="meta-info">
|
|
3473
|
+
<div class="meta-time">⏰ 设精时间: ${timeStr}</div>
|
|
3474
|
+
<div class="meta-operator">📌 操作者: ${record.operator_nick} (${record.operator_id})</div>
|
|
3475
|
+
</div>
|
|
3476
|
+
</div>
|
|
3477
|
+
</div>
|
|
3478
|
+
</body>
|
|
3479
|
+
</html>`;
|
|
3480
|
+
}, "getSourceHanSerifSCStyleDetailHtmlStr");
|
|
3481
|
+
var getLXGWWenKaiStyleDetailHtmlStr = /* @__PURE__ */ __name(async (record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
3482
|
+
const timestamp = generateTimestamp();
|
|
3483
|
+
const contentHtml = parseEssenceContentToHtmlFull(record.content);
|
|
3484
|
+
const timeStr = formatTimestamp(record.operator_time);
|
|
3485
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
3486
|
+
const operatorAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.operator_id}&s=640`;
|
|
3487
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: linear-gradient(45deg, rgba(245,240,230,0.85), rgba(250,245,235,0.85)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : `background: linear-gradient(45deg, #f5f0e6, #faf5eb);`;
|
|
3488
|
+
return `<!DOCTYPE html>
|
|
3489
|
+
<html>
|
|
3490
|
+
<head>
|
|
3491
|
+
<style>
|
|
3492
|
+
${fontBase64 ? `@font-face { font-family: 'LXGWWenKai'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
3493
|
+
|
|
3494
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
3495
|
+
body {
|
|
3496
|
+
font-family: ${fontBase64 ? "'LXGWWenKai'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
3497
|
+
width: 850px;
|
|
3498
|
+
height: auto;
|
|
3499
|
+
min-height: 100vh;
|
|
3500
|
+
display: flex;
|
|
3501
|
+
align-items: center;
|
|
3502
|
+
justify-content: center;
|
|
3503
|
+
${backgroundStyle}
|
|
3504
|
+
position: relative;
|
|
3505
|
+
box-sizing: border-box;
|
|
3506
|
+
overflow: visible;
|
|
3507
|
+
color: #3a2f2a;
|
|
3508
|
+
padding: 35px;
|
|
3509
|
+
}
|
|
3510
|
+
|
|
3511
|
+
body::before { content: ''; position: absolute; top: 16px; left: 16px; right: 16px; bottom: 16px; border: 3px solid #d4af37; border-radius: 20px; background: linear-gradient(135deg, rgba(212,175,55,0.12) 0%, rgba(184,134,11,0.06) 50%, rgba(212,175,55,0.12) 100%); box-shadow: inset 0 0 25px rgba(212,175,55,0.35), 0 0 35px rgba(212,175,55,0.25); z-index: 1; }
|
|
3512
|
+
body::after { content: '◆'; position: absolute; top: 30px; left: 30px; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
3513
|
+
|
|
3514
|
+
.corner-decoration { position: absolute; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
3515
|
+
.corner-decoration.top-right { top: 30px; right: 30px; }
|
|
3516
|
+
.corner-decoration.bottom-left { bottom: 30px; left: 30px; }
|
|
3517
|
+
.corner-decoration.bottom-right { bottom: 30px; right: 30px; }
|
|
3518
|
+
|
|
3519
|
+
.main-container {
|
|
3520
|
+
width: 720px;
|
|
3521
|
+
min-height: 400px;
|
|
3522
|
+
position: relative;
|
|
3523
|
+
z-index: 3;
|
|
3524
|
+
display: flex;
|
|
3525
|
+
flex-direction: column;
|
|
3526
|
+
padding: 32px 28px;
|
|
3527
|
+
box-sizing: border-box;
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
.group-header { display: flex; align-items: center; margin-bottom: 18px; padding: 16px; background: rgba(255,255,255,0.2); border: 1px solid rgba(212,175,55,0.4); border-radius: 16px; box-shadow: 0 4px 16px rgba(212,175,55,0.15); }
|
|
3531
|
+
.group-avatar { width: 60px; height: 60px; border-radius: 9%; margin-right: 14px; border: 3px solid #d4af37; box-shadow: 0 4px 12px rgba(212,175,55,0.3); }
|
|
3532
|
+
.group-info { flex: 1; }
|
|
3533
|
+
.group-name { font-size: 22px; font-weight: bold; color: #8b4513; margin-bottom: 4px; text-shadow: 1px 1px 2px rgba(139,69,19,0.2); }
|
|
3534
|
+
.group-details { font-size: 16px; color: #a0522d; line-height: 1.3; font-weight: 500; }
|
|
3535
|
+
|
|
3536
|
+
.title-section { text-align: center; margin-bottom: 8px; }
|
|
3537
|
+
.main-title { font-size: 40px; font-weight: bold; color: #8b4513; margin-bottom: 6px; text-shadow: 2px 2px 4px rgba(139,69,19,0.3); letter-spacing: 2px; }
|
|
3538
|
+
.subtitle { font-size: 16px; color: #a0522d; text-align: center; margin-bottom: 18px; font-weight: 500; }
|
|
3539
|
+
|
|
3540
|
+
.sender-section { display: flex; align-items: center; padding: 14px; background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 14px; margin-bottom: 14px; box-shadow: 0 3px 10px rgba(0,0,0,0.08); backdrop-filter: blur(5px); }
|
|
3541
|
+
.sender-avatar { width: 65px; height: 65px; border-radius: 50%; margin-right: 14px; border: 2px solid #d4af37; box-shadow: 0 2px 6px rgba(212,175,55,0.2); }
|
|
3542
|
+
.sender-info { flex: 1; }
|
|
3543
|
+
.sender-name { font-size: 20px; font-weight: bold; color: #3a2f2a; margin-bottom: 4px; }
|
|
3544
|
+
.sender-id { font-size: 13px; }
|
|
3545
|
+
.qq-label { color: #a0522d; font-weight: 500; }
|
|
3546
|
+
.qq-number { color: #3a2f2a; font-family: 'Courier New', monospace; font-weight: bold; }
|
|
3547
|
+
|
|
3548
|
+
.content-section { background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 14px; padding: 18px; margin-bottom: 14px; box-shadow: 0 3px 10px rgba(0,0,0,0.08); backdrop-filter: blur(5px); }
|
|
3549
|
+
.content-title { font-size: 14px; color: #a0522d; margin-bottom: 10px; font-weight: 600; }
|
|
3550
|
+
.content-body { font-size: 16px; color: #3a2f2a; line-height: 1.7; word-break: break-all; white-space: pre-wrap; }
|
|
3551
|
+
|
|
3552
|
+
.meta-section { display: flex; align-items: center; padding: 12px 14px; background: rgba(255,255,255,0.2); border: 1px solid rgba(212,175,55,0.35); border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
|
|
3553
|
+
.operator-avatar { width: 38px; height: 38px; border-radius: 50%; margin-right: 12px; border: 2px solid #d4af37; box-shadow: 0 2px 6px rgba(212,175,55,0.2); }
|
|
3554
|
+
.meta-info { flex: 1; }
|
|
3555
|
+
.meta-time { font-size: 13px; color: #a0522d; margin-bottom: 2px; }
|
|
3556
|
+
.meta-operator { font-size: 13px; color: #8b4513; font-weight: bold; }
|
|
3557
|
+
|
|
3558
|
+
/* 消息内容元素样式 */
|
|
3559
|
+
.msg-text { }
|
|
3560
|
+
.msg-reply { display: inline-flex; align-items: center; background: rgba(212,175,55,0.15); border-left: 3px solid #d4af37; padding: 3px 10px; margin: 4px 6px 4px 0; border-radius: 0 8px 8px 0; font-size: 13px; color: #a0522d; }
|
|
3561
|
+
.msg-reply .reply-icon { margin-right: 5px; font-size: 12px; }
|
|
3562
|
+
.msg-reply .reply-text { font-style: italic; }
|
|
3563
|
+
.msg-image-wrapper-large { display: block; margin: 12px 0; }
|
|
3564
|
+
.msg-image-preview-large { max-width: 100%; max-height: 400px; border-radius: 10px; border: 1px solid rgba(212,175,55,0.3); object-fit: contain; }
|
|
3565
|
+
.msg-image-placeholder, .msg-image-fallback { color: #a0522d; font-style: italic; }
|
|
3566
|
+
.msg-at { color: #8b4513; font-weight: bold; }
|
|
3567
|
+
.msg-face { color: #d4af37; }
|
|
3568
|
+
.msg-forward, .msg-video, .msg-record, .msg-file { color: #a0522d; font-style: italic; background: rgba(212,175,55,0.1); padding: 2px 8px; border-radius: 4px; }
|
|
3569
|
+
.msg-unknown { color: #8b7355; }
|
|
3570
|
+
.empty-msg { color: #8b7355; font-style: italic; }
|
|
3571
|
+
|
|
3572
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(139, 69, 19, 0.4); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
3573
|
+
|
|
3574
|
+
body.dark { background: linear-gradient(45deg, #2c2416, #3a2f1f); color: #e6d7c3; }
|
|
3575
|
+
body.dark::before { border-color: #b8860b; background: linear-gradient(135deg, rgba(184,134,11,0.18) 0%, rgba(139,69,19,0.12) 50%, rgba(184,134,11,0.18) 100%); box-shadow: inset 0 0 25px rgba(184,134,11,0.45), 0 0 35px rgba(184,134,11,0.35); }
|
|
3576
|
+
body.dark::after { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
3577
|
+
body.dark .corner-decoration { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
3578
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(184,134,11,0.5); }
|
|
3579
|
+
body.dark .group-name { color: #daa520; text-shadow: 1px 1px 2px rgba(218,165,32,0.3); }
|
|
3580
|
+
body.dark .group-details { color: #cd853f; }
|
|
3581
|
+
body.dark .main-title { color: #daa520; text-shadow: 2px 2px 4px rgba(218,165,32,0.4); }
|
|
3582
|
+
body.dark .subtitle { color: #cd853f; }
|
|
3583
|
+
body.dark .sender-section { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
3584
|
+
body.dark .sender-name { color: #e6d7c3; }
|
|
3585
|
+
body.dark .sender-id { color: #cd853f; }
|
|
3586
|
+
body.dark .qq-label { color: #cd853f; }
|
|
3587
|
+
body.dark .qq-number { color: #e6d7c3; }
|
|
3588
|
+
body.dark .content-section { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
3589
|
+
body.dark .content-title { color: #cd853f; }
|
|
3590
|
+
body.dark .content-body { color: #e6d7c3; }
|
|
3591
|
+
body.dark .meta-section { background: rgba(0,0,0,0.3); border-color: rgba(184,134,11,0.4); }
|
|
3592
|
+
body.dark .meta-time { color: #cd853f; }
|
|
3593
|
+
body.dark .meta-operator { color: #daa520; }
|
|
3594
|
+
body.dark .msg-reply { background: rgba(184,134,11,0.2); border-left-color: #b8860b; color: #cd853f; }
|
|
3595
|
+
body.dark .msg-at { color: #daa520; }
|
|
3596
|
+
body.dark .msg-face { color: #b8860b; }
|
|
3597
|
+
body.dark .msg-forward, body.dark .msg-video, body.dark .msg-record, body.dark .msg-file { background: rgba(184,134,11,0.15); color: #cd853f; }
|
|
3598
|
+
body.dark .msg-image-preview-large { border-color: rgba(184,134,11,0.4); }
|
|
3599
|
+
body.dark .timestamp-watermark { color: rgba(218, 165, 32, 0.4); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
3600
|
+
</style>
|
|
3601
|
+
</head>
|
|
3602
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
3603
|
+
<div class="corner-decoration top-right">◆</div>
|
|
3604
|
+
<div class="corner-decoration bottom-left">◆</div>
|
|
3605
|
+
<div class="corner-decoration bottom-right">◆</div>
|
|
3606
|
+
<div class="main-container">
|
|
3607
|
+
<div class="group-header">
|
|
3608
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
3609
|
+
<div class="group-info">
|
|
3610
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
3611
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
3612
|
+
</div>
|
|
3613
|
+
</div>
|
|
3614
|
+
<div class="title-section">
|
|
3615
|
+
<div class="main-title">「 群精华详情 」</div>
|
|
3616
|
+
</div>
|
|
3617
|
+
<div class="subtitle">第 ${contextInfo.essenceIndex}/${contextInfo.totalEssenceCount} 条精华消息</div>
|
|
3618
|
+
<div class="sender-section">
|
|
3619
|
+
<img class="sender-avatar" src="${senderAvatarUrl}" alt="发送者头像" />
|
|
3620
|
+
<div class="sender-info">
|
|
3621
|
+
<div class="sender-name">${record.sender_nick || "未知"}</div>
|
|
3622
|
+
<div class="sender-id"><span class="qq-label">QQ:</span> <span class="qq-number">${record.sender_id}</span></div>
|
|
3623
|
+
</div>
|
|
3624
|
+
</div>
|
|
3625
|
+
<div class="content-section">
|
|
3626
|
+
<div class="content-title">💬 消息内容</div>
|
|
3627
|
+
<div class="content-body">${contentHtml}</div>
|
|
3628
|
+
</div>
|
|
3629
|
+
<div class="meta-section">
|
|
3630
|
+
<img class="operator-avatar" src="${operatorAvatarUrl}" alt="操作者头像" />
|
|
3631
|
+
<div class="meta-info">
|
|
3632
|
+
<div class="meta-time">⏰ 设精时间: ${timeStr}</div>
|
|
3633
|
+
<div class="meta-operator">📌 操作者: ${record.operator_nick} (${record.operator_id})</div>
|
|
3634
|
+
</div>
|
|
3635
|
+
</div>
|
|
3636
|
+
</div>
|
|
3637
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
3638
|
+
</body>
|
|
3639
|
+
</html>`;
|
|
3640
|
+
}, "getLXGWWenKaiStyleDetailHtmlStr");
|
|
3641
|
+
var getFlatMinimalStyleDetailHtmlStr = /* @__PURE__ */ __name(async (record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
3642
|
+
const timestamp = generateTimestamp();
|
|
3643
|
+
const contentHtml = parseEssenceContentToHtmlFull(record.content);
|
|
3644
|
+
const timeStr = formatTimestamp(record.operator_time);
|
|
3645
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
3646
|
+
const operatorAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.operator_id}&s=640`;
|
|
3647
|
+
return `<!DOCTYPE html>
|
|
3648
|
+
<html>
|
|
3649
|
+
<head>
|
|
3650
|
+
<style>
|
|
3651
|
+
${fontBase64 ? `@font-face { font-family: 'LXGWWenKai'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
3652
|
+
|
|
3653
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
3654
|
+
body {
|
|
3655
|
+
font-family: ${fontBase64 ? "'LXGWWenKai'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
3656
|
+
width: 850px;
|
|
3657
|
+
height: auto;
|
|
3658
|
+
min-height: 100vh;
|
|
3659
|
+
display: flex;
|
|
3660
|
+
align-items: center;
|
|
3661
|
+
justify-content: center;
|
|
3662
|
+
background: linear-gradient(180deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
3663
|
+
position: relative;
|
|
3664
|
+
box-sizing: border-box;
|
|
3665
|
+
overflow: visible;
|
|
3666
|
+
color: #333;
|
|
3667
|
+
padding: 35px;
|
|
3668
|
+
}
|
|
3669
|
+
|
|
3670
|
+
.card {
|
|
3671
|
+
width: 720px;
|
|
3672
|
+
height: auto;
|
|
3673
|
+
min-height: 400px;
|
|
3674
|
+
background: #ffffff;
|
|
3675
|
+
border-radius: 20px;
|
|
3676
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
|
|
3677
|
+
position: relative;
|
|
3678
|
+
overflow: visible;
|
|
3679
|
+
display: flex;
|
|
3680
|
+
flex-direction: column;
|
|
3681
|
+
padding: 26px;
|
|
3682
|
+
box-sizing: border-box;
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3685
|
+
.group-header { display: flex; align-items: center; margin-bottom: 16px; padding: 14px; background: #f8f9fa; border-radius: 12px; }
|
|
3686
|
+
.group-avatar { width: 55px; height: 55px; border-radius: 50%; margin-right: 12px; border: 2px solid #e9ecef; }
|
|
3687
|
+
.group-info { flex: 1; }
|
|
3688
|
+
.group-name { font-size: 20px; font-weight: 600; color: #212529; margin-bottom: 2px; }
|
|
3689
|
+
.group-details { font-size: 13px; color: #6c757d; }
|
|
3690
|
+
|
|
3691
|
+
.title { font-size: 28px; font-weight: 600; margin-bottom: 6px; color: #212529; text-align: center; }
|
|
3692
|
+
.subtitle { font-size: 14px; color: #6c757d; text-align: center; margin-bottom: 16px; }
|
|
3693
|
+
|
|
3694
|
+
.sender-section { display: flex; align-items: center; padding: 12px; background: #f8f9fa; border-radius: 12px; margin-bottom: 12px; }
|
|
3695
|
+
.sender-avatar { width: 60px; height: 60px; border-radius: 50%; margin-right: 14px; border: 2px solid #e9ecef; }
|
|
3696
|
+
.sender-info { flex: 1; }
|
|
3697
|
+
.sender-name { font-size: 18px; font-weight: 600; color: #212529; margin-bottom: 3px; }
|
|
3698
|
+
.sender-id { font-size: 12px; color: #6c757d; }
|
|
3699
|
+
.qq-label { color: #6c757d; }
|
|
3700
|
+
.qq-number { color: #495057; font-family: 'Courier New', monospace; font-weight: 600; }
|
|
3701
|
+
|
|
3702
|
+
.content-section { background: #f8f9fa; border-radius: 12px; padding: 16px; margin-bottom: 12px; }
|
|
3703
|
+
.content-title { font-size: 12px; color: #6c757d; margin-bottom: 8px; font-weight: 500; }
|
|
3704
|
+
.content-body { font-size: 15px; color: #495057; line-height: 1.6; word-break: break-all; white-space: pre-wrap; }
|
|
3705
|
+
|
|
3706
|
+
.meta-section { display: flex; align-items: center; padding: 10px 12px; background: #f8f9fa; border-radius: 10px; }
|
|
3707
|
+
.operator-avatar { width: 35px; height: 35px; border-radius: 50%; margin-right: 10px; border: 1px solid #e9ecef; }
|
|
3708
|
+
.meta-info { flex: 1; }
|
|
3709
|
+
.meta-time { font-size: 12px; color: #6c757d; margin-bottom: 2px; }
|
|
3710
|
+
.meta-operator { font-size: 12px; color: #fd7e14; }
|
|
3711
|
+
|
|
3712
|
+
/* 消息内容元素样式 */
|
|
3713
|
+
.msg-text { }
|
|
3714
|
+
.msg-reply { display: inline-flex; align-items: center; background: #e9ecef; border-left: 3px solid #adb5bd; padding: 3px 9px; margin: 4px 6px 4px 0; border-radius: 0 7px 7px 0; font-size: 12px; color: #6c757d; }
|
|
3715
|
+
.msg-reply .reply-icon { margin-right: 4px; font-size: 11px; }
|
|
3716
|
+
.msg-reply .reply-text { font-style: italic; }
|
|
3717
|
+
.msg-image-wrapper-large { display: block; margin: 10px 0; }
|
|
3718
|
+
.msg-image-preview-large { max-width: 100%; max-height: 400px; border-radius: 8px; border: 1px solid #dee2e6; object-fit: contain; }
|
|
3719
|
+
.msg-image-placeholder, .msg-image-fallback { color: #adb5bd; font-style: italic; }
|
|
3720
|
+
.msg-at { color: #0d6efd; font-weight: 500; }
|
|
3721
|
+
.msg-face { color: #fd7e14; }
|
|
3722
|
+
.msg-forward, .msg-video, .msg-record, .msg-file { color: #6c757d; font-style: italic; background: #e9ecef; padding: 2px 7px; border-radius: 4px; }
|
|
3723
|
+
.msg-unknown { color: #adb5bd; }
|
|
3724
|
+
.empty-msg { color: #adb5bd; font-style: italic; }
|
|
3725
|
+
|
|
3726
|
+
.timestamp-watermark { position: fixed; top: 1px; left: 1px; font-size: 11px; color: rgba(128, 128, 128, 0.4); font-family: 'Courier New', monospace; z-index: 9999; }
|
|
3727
|
+
|
|
3728
|
+
body.dark { background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); color: #e9ecef; }
|
|
3729
|
+
body.dark .card { background: #212529; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3); }
|
|
3730
|
+
body.dark .group-header { background: #343a40; }
|
|
3731
|
+
body.dark .group-avatar { border-color: #495057; }
|
|
3732
|
+
body.dark .group-name { color: #f8f9fa; }
|
|
3733
|
+
body.dark .group-details { color: #adb5bd; }
|
|
3734
|
+
body.dark .title { color: #f8f9fa; }
|
|
3735
|
+
body.dark .subtitle { color: #adb5bd; }
|
|
3736
|
+
body.dark .sender-section { background: #343a40; }
|
|
3737
|
+
body.dark .sender-avatar { border-color: #495057; }
|
|
3738
|
+
body.dark .sender-name { color: #f8f9fa; }
|
|
3739
|
+
body.dark .sender-id { color: #adb5bd; }
|
|
3740
|
+
body.dark .qq-label { color: #adb5bd; }
|
|
3741
|
+
body.dark .qq-number { color: #e9ecef; }
|
|
3742
|
+
body.dark .content-section { background: #343a40; }
|
|
3743
|
+
body.dark .content-title { color: #adb5bd; }
|
|
3744
|
+
body.dark .content-body { color: #ced4da; }
|
|
3745
|
+
body.dark .meta-section { background: #343a40; }
|
|
3746
|
+
body.dark .meta-time { color: #adb5bd; }
|
|
3747
|
+
body.dark .meta-operator { color: #ffc107; }
|
|
3748
|
+
body.dark .msg-reply { background: #495057; border-left-color: #6c757d; color: #adb5bd; }
|
|
3749
|
+
body.dark .msg-at { color: #6ea8fe; }
|
|
3750
|
+
body.dark .msg-face { color: #ffc107; }
|
|
3751
|
+
body.dark .msg-forward, body.dark .msg-video, body.dark .msg-record, body.dark .msg-file { background: #495057; color: #adb5bd; }
|
|
3752
|
+
body.dark .msg-image-preview-large { border-color: #495057; }
|
|
3753
|
+
body.dark .timestamp-watermark { color: rgba(200, 200, 200, 0.3); }
|
|
3754
|
+
</style>
|
|
3755
|
+
</head>
|
|
3756
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
3757
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
3758
|
+
<div class="card">
|
|
3759
|
+
<div class="group-header">
|
|
3760
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
3761
|
+
<div class="group-info">
|
|
3762
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
3763
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
3764
|
+
</div>
|
|
3765
|
+
</div>
|
|
3766
|
+
<div class="title">📌 群精华详情</div>
|
|
3767
|
+
<div class="subtitle">第 ${contextInfo.essenceIndex}/${contextInfo.totalEssenceCount} 条精华消息</div>
|
|
3768
|
+
<div class="sender-section">
|
|
3769
|
+
<img class="sender-avatar" src="${senderAvatarUrl}" alt="发送者头像" />
|
|
3770
|
+
<div class="sender-info">
|
|
3771
|
+
<div class="sender-name">${record.sender_nick || "未知"}</div>
|
|
3772
|
+
<div class="sender-id"><span class="qq-label">QQ:</span> <span class="qq-number">${record.sender_id}</span></div>
|
|
3773
|
+
</div>
|
|
3774
|
+
</div>
|
|
3775
|
+
<div class="content-section">
|
|
3776
|
+
<div class="content-title">💬 消息内容</div>
|
|
3777
|
+
<div class="content-body">${contentHtml}</div>
|
|
3778
|
+
</div>
|
|
3779
|
+
<div class="meta-section">
|
|
3780
|
+
<img class="operator-avatar" src="${operatorAvatarUrl}" alt="操作者头像" />
|
|
3781
|
+
<div class="meta-info">
|
|
3782
|
+
<div class="meta-time">⏰ 设精时间: ${timeStr}</div>
|
|
3783
|
+
<div class="meta-operator">📌 操作者: ${record.operator_nick} (${record.operator_id})</div>
|
|
3784
|
+
</div>
|
|
3785
|
+
</div>
|
|
3786
|
+
</div>
|
|
3787
|
+
</body>
|
|
3788
|
+
</html>`;
|
|
3789
|
+
}, "getFlatMinimalStyleDetailHtmlStr");
|
|
3790
|
+
async function renderGroupEssenceDetail(ctx, record, contextInfo, imageStyle, enableDarkMode, imageType, screenshotQuality) {
|
|
3791
|
+
const groupAvatarBase64 = await getGroupAvatarBase64(ctx, contextInfo.groupId.toString());
|
|
3792
|
+
const fontBase64 = await getFontBase64(ctx, imageStyle);
|
|
3793
|
+
let htmlContent;
|
|
3794
|
+
switch (imageStyle) {
|
|
3795
|
+
case IMAGE_STYLES.SOURCE_HAN_SERIF_SC:
|
|
3796
|
+
htmlContent = await getSourceHanSerifSCStyleDetailHtmlStr(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
3797
|
+
break;
|
|
3798
|
+
case IMAGE_STYLES.LXGW_WENKAI:
|
|
3799
|
+
htmlContent = await getLXGWWenKaiStyleDetailHtmlStr(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
3800
|
+
break;
|
|
3801
|
+
case IMAGE_STYLES.FLAT_MINIMAL:
|
|
3802
|
+
htmlContent = await getFlatMinimalStyleDetailHtmlStr(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
3803
|
+
break;
|
|
3804
|
+
default:
|
|
3805
|
+
htmlContent = await getSourceHanSerifSCStyleDetailHtmlStr(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
3806
|
+
}
|
|
3807
|
+
const page = await ctx.puppeteer.page();
|
|
3808
|
+
try {
|
|
3809
|
+
await page.setViewport({ width: 900, height: 1 });
|
|
3810
|
+
await page.setContent(htmlContent, { waitUntil: "domcontentloaded" });
|
|
3811
|
+
const bodyElement = await page.$("body");
|
|
3812
|
+
const boundingBox = await bodyElement?.boundingBox();
|
|
3813
|
+
if (!boundingBox) {
|
|
3814
|
+
throw new Error("无法获取页面元素的边界框");
|
|
3815
|
+
}
|
|
3816
|
+
const screenshot = await page.screenshot({
|
|
3817
|
+
type: imageType,
|
|
3818
|
+
encoding: "base64",
|
|
3819
|
+
clip: boundingBox,
|
|
3820
|
+
quality: imageType === "png" ? void 0 : screenshotQuality
|
|
3821
|
+
});
|
|
3822
|
+
return screenshot;
|
|
3823
|
+
} finally {
|
|
3824
|
+
await page.close();
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
__name(renderGroupEssenceDetail, "renderGroupEssenceDetail");
|
|
3828
|
+
|
|
3829
|
+
// src/commandGroupEssenceDetail.ts
|
|
3830
|
+
function parseEssenceContentDetail(content) {
|
|
3831
|
+
if (!content || content.length === 0) {
|
|
3832
|
+
return "[空消息]";
|
|
3833
|
+
}
|
|
3834
|
+
return content.map((item) => {
|
|
3835
|
+
switch (item.type) {
|
|
3836
|
+
case "text":
|
|
3837
|
+
return item.data.text || "";
|
|
3838
|
+
case "image":
|
|
3839
|
+
return "[图片]";
|
|
3840
|
+
case "face":
|
|
3841
|
+
return `[表情:${item.data.id || ""}]`;
|
|
3842
|
+
case "at":
|
|
3843
|
+
return `@${item.data.qq || item.data.name || "某人"}`;
|
|
3844
|
+
case "reply":
|
|
3845
|
+
const replyId = item.data.id || item.data.qq || "";
|
|
3846
|
+
return `[回复:${replyId}]`;
|
|
3847
|
+
case "forward":
|
|
3848
|
+
return "[转发消息]";
|
|
3849
|
+
case "video":
|
|
3850
|
+
return "[视频]";
|
|
3851
|
+
case "record":
|
|
3852
|
+
return "[语音]";
|
|
3853
|
+
case "file":
|
|
3854
|
+
return "[文件]";
|
|
3855
|
+
default:
|
|
3856
|
+
return `[${item.type}]`;
|
|
3857
|
+
}
|
|
3858
|
+
}).join("");
|
|
3859
|
+
}
|
|
3860
|
+
__name(parseEssenceContentDetail, "parseEssenceContentDetail");
|
|
3861
|
+
function formatGroupEssenceDetailAsText(record, contextInfo, config) {
|
|
3862
|
+
const content = parseEssenceContentDetail(record.content);
|
|
3863
|
+
const timeStr = formatTimestamp(record.operator_time);
|
|
3864
|
+
let output = `📌 群精华消息详情
|
|
3865
|
+
`;
|
|
3866
|
+
output += `==================
|
|
3867
|
+
`;
|
|
3868
|
+
output += `📍 群聊: ${contextInfo.groupName} (${contextInfo.groupId})
|
|
3869
|
+
`;
|
|
3870
|
+
output += `📊 第 ${contextInfo.essenceIndex}/${contextInfo.totalEssenceCount} 条精华
|
|
3871
|
+
`;
|
|
3872
|
+
output += `------------------
|
|
3873
|
+
`;
|
|
3874
|
+
output += `👤 发送者: ${record.sender_nick}
|
|
3875
|
+
`;
|
|
3876
|
+
output += `🆔 QQ号: ${record.sender_id}
|
|
3877
|
+
`;
|
|
3878
|
+
output += `------------------
|
|
3879
|
+
`;
|
|
3880
|
+
output += `💬 消息内容:
|
|
3881
|
+
${content}
|
|
3882
|
+
`;
|
|
3883
|
+
output += `------------------
|
|
3884
|
+
`;
|
|
3885
|
+
output += `⏰ 设精时间: ${timeStr}
|
|
3886
|
+
`;
|
|
3887
|
+
output += `📌 操作者: ${record.operator_nick} (${record.operator_id})
|
|
3888
|
+
`;
|
|
3889
|
+
output += `==================
|
|
3890
|
+
`;
|
|
3891
|
+
output += `📖 用法: ${config.groupEssenceDetailCommandName} <序号>
|
|
3892
|
+
`;
|
|
3893
|
+
output += `📝 示例: ${config.groupEssenceDetailCommandName} 5 查看第5条精华详情
|
|
3894
|
+
`;
|
|
3895
|
+
return output;
|
|
3896
|
+
}
|
|
3897
|
+
__name(formatGroupEssenceDetailAsText, "formatGroupEssenceDetailAsText");
|
|
3898
|
+
function formatGroupEssenceDetailAsForward(record, contextInfo, config) {
|
|
3899
|
+
const content = parseEssenceContentDetail(record.content);
|
|
3900
|
+
const timeStr = formatTimestamp(record.operator_time);
|
|
3901
|
+
let messages = "";
|
|
3902
|
+
const addMessageBlock = /* @__PURE__ */ __name((userId, nickname, content2) => {
|
|
3903
|
+
if (userId) {
|
|
3904
|
+
messages += `<message user-id="${userId}" nickname="${nickname}">${content2}</message>
|
|
3905
|
+
`;
|
|
3906
|
+
} else {
|
|
3907
|
+
messages += `<message nickname="${nickname}">${content2}</message>
|
|
3908
|
+
`;
|
|
3909
|
+
}
|
|
3910
|
+
}, "addMessageBlock");
|
|
3911
|
+
addMessageBlock(void 0, "📌 群精华详情", `第 ${contextInfo.essenceIndex}/${contextInfo.totalEssenceCount} 条精华消息`);
|
|
3912
|
+
addMessageBlock(void 0, "📍 群聊信息", `${contextInfo.groupName}
|
|
3913
|
+
群号: ${contextInfo.groupId}
|
|
3914
|
+
成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}`);
|
|
3915
|
+
addMessageBlock(String(record.sender_id), record.sender_nick, `发送者: ${record.sender_nick}
|
|
3916
|
+
QQ: ${record.sender_id}`);
|
|
3917
|
+
addMessageBlock(String(record.sender_id), record.sender_nick, `💬 消息内容:
|
|
3918
|
+
${content}`);
|
|
3919
|
+
addMessageBlock(String(record.operator_id), record.operator_nick, `📌 设精信息:
|
|
3920
|
+
操作者: ${record.operator_nick}
|
|
3921
|
+
时间: ${timeStr}`);
|
|
3922
|
+
const usageText = [
|
|
3923
|
+
`📖 用法: ${config.groupEssenceDetailCommandName} <序号>`,
|
|
3924
|
+
`📝 示例: ${config.groupEssenceDetailCommandName} 5 查看第5条精华详情`
|
|
3925
|
+
].join("\n");
|
|
3926
|
+
addMessageBlock(void 0, "使用帮助", usageText);
|
|
3927
|
+
return `<message forward>
|
|
3928
|
+
${messages}
|
|
3929
|
+
</message>`;
|
|
3930
|
+
}
|
|
3931
|
+
__name(formatGroupEssenceDetailAsForward, "formatGroupEssenceDetailAsForward");
|
|
3932
|
+
function registerGroupEssenceDetailCommand(ctx, config, responseHint) {
|
|
3933
|
+
if (!config.enableGroupEssenceCommand) return;
|
|
3934
|
+
ctx.command(`${config.groupEssenceDetailCommandName} <num:number>`, `获取指定序号的群精华消息详情, 发送${responseHint}`).alias("群精华详情").alias("aged").option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }, num) => {
|
|
3935
|
+
if (!session.onebot)
|
|
3936
|
+
return session.send("[error]当前会话不支持onebot协议。");
|
|
3937
|
+
if (!session.guildId)
|
|
3938
|
+
return session.send("[error]当前会话不在群聊中。");
|
|
3939
|
+
if (num === void 0 || num === null || isNaN(num)) {
|
|
3940
|
+
return session.send(`[error]请输入要查看的精华消息序号。
|
|
3941
|
+
用法: ${config.groupEssenceDetailCommandName} <序号>
|
|
3942
|
+
示例: ${config.groupEssenceDetailCommandName} 5`);
|
|
3943
|
+
}
|
|
3944
|
+
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
3945
|
+
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
3946
|
+
if (options.imageStyleIdx !== void 0) {
|
|
3947
|
+
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
3948
|
+
if (!isIdxValid) {
|
|
3949
|
+
let idxInvalidMsgArr = [
|
|
3950
|
+
`图片样式索引不合法。`,
|
|
3951
|
+
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
3952
|
+
` 当前输入:${options.imageStyleIdx}`,
|
|
3953
|
+
`
|
|
3954
|
+
`,
|
|
3955
|
+
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
3956
|
+
];
|
|
3957
|
+
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
3958
|
+
}
|
|
3959
|
+
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
3960
|
+
}
|
|
3961
|
+
try {
|
|
3962
|
+
const onebotBot = session.onebot;
|
|
3963
|
+
const groupEssenceMsgList = await onebotBot.getEssenceMsgList(session.guildId);
|
|
3964
|
+
if (!groupEssenceMsgList || groupEssenceMsgList.length === 0) {
|
|
3965
|
+
return session.send("该群暂无精华消息。");
|
|
3966
|
+
}
|
|
3967
|
+
const index = Math.floor(num);
|
|
3968
|
+
if (index < 1 || index > groupEssenceMsgList.length) {
|
|
3969
|
+
return session.send(`[error]序号超出范围。
|
|
3970
|
+
有效范围: 1 - ${groupEssenceMsgList.length}
|
|
3971
|
+
当前输入: ${index}`);
|
|
3972
|
+
}
|
|
3973
|
+
const targetRecord = groupEssenceMsgList[index - 1];
|
|
3974
|
+
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
3975
|
+
const contextInfo = {
|
|
3976
|
+
groupId: parseInt(session.guildId),
|
|
3977
|
+
groupName: groupInfoObj.group_name || "未知群聊",
|
|
3978
|
+
memberCount: groupInfoObj.member_count || 0,
|
|
3979
|
+
maxMemberCount: groupInfoObj.max_member_count || 0,
|
|
3980
|
+
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`,
|
|
3981
|
+
essenceIndex: index,
|
|
3982
|
+
totalEssenceCount: groupEssenceMsgList.length
|
|
3983
|
+
};
|
|
3984
|
+
if (config.verboseConsoleOutput) {
|
|
3985
|
+
ctx.logger.info(`群精华消息详情: ${JSON.stringify(targetRecord)}`);
|
|
3986
|
+
}
|
|
3987
|
+
if (config.sendText) {
|
|
3988
|
+
const textMessage = formatGroupEssenceDetailAsText(targetRecord, contextInfo, config);
|
|
3989
|
+
await session.send(`${config.enableQuoteWithText ? import_koishi4.h.quote(session.messageId) : ""}${textMessage}`);
|
|
3990
|
+
}
|
|
3991
|
+
if (config.sendImage) {
|
|
3992
|
+
const waitTipMsgId = await session.send(`${import_koishi4.h.quote(session.messageId)}🔄正在渲染群精华详情图片,请稍候⏳...`);
|
|
3993
|
+
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
3994
|
+
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
3995
|
+
const essenceDetailImageBase64 = await renderGroupEssenceDetail(
|
|
3996
|
+
ctx,
|
|
3997
|
+
targetRecord,
|
|
3998
|
+
contextInfo,
|
|
3999
|
+
selectedImageStyle,
|
|
4000
|
+
selectedDarkMode,
|
|
4001
|
+
config.imageType,
|
|
4002
|
+
config.screenshotQuality
|
|
4003
|
+
);
|
|
4004
|
+
let imageMessage = `${config.enableQuoteWithImage ? import_koishi4.h.quote(session.messageId) : ""}${import_koishi4.h.image(`data:image/png;base64,${essenceDetailImageBase64}`)}`;
|
|
4005
|
+
imageMessage += `
|
|
4006
|
+
📌 第 ${index}/${groupEssenceMsgList.length} 条精华 | 📖 ${config.groupEssenceDetailCommandName} <序号>`;
|
|
4007
|
+
await session.send(imageMessage);
|
|
4008
|
+
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
4009
|
+
}
|
|
4010
|
+
if (config.sendForward) {
|
|
4011
|
+
const forwardMessage = formatGroupEssenceDetailAsForward(targetRecord, contextInfo, config);
|
|
4012
|
+
await session.send(import_koishi4.h.unescape(forwardMessage));
|
|
4013
|
+
}
|
|
4014
|
+
} catch (error) {
|
|
4015
|
+
ctx.logger.error(`获取群精华消息详情失败: ${error}`);
|
|
4016
|
+
await session.send(`[error]获取群精华消息详情失败: ${error.message}`);
|
|
4017
|
+
}
|
|
4018
|
+
});
|
|
4019
|
+
}
|
|
4020
|
+
__name(registerGroupEssenceDetailCommand, "registerGroupEssenceDetailCommand");
|
|
4021
|
+
|
|
4022
|
+
// src/commandGroupNotice.ts
|
|
4023
|
+
var import_koishi5 = require("koishi");
|
|
4024
|
+
|
|
4025
|
+
// src/renderGroupNotice.ts
|
|
4026
|
+
function parseNoticeContentToHtml(text) {
|
|
4027
|
+
if (!text) {
|
|
4028
|
+
return '<span class="empty-msg">[空公告]</span>';
|
|
4029
|
+
}
|
|
4030
|
+
let parsed = parseNoticeText(text);
|
|
4031
|
+
parsed = parsed.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br/>");
|
|
4032
|
+
return `<span class="notice-text">${parsed}</span>`;
|
|
4033
|
+
}
|
|
4034
|
+
__name(parseNoticeContentToHtml, "parseNoticeContentToHtml");
|
|
4035
|
+
function getNoticeImageUrl(imageId) {
|
|
4036
|
+
return `https://gdynamic.qpic.cn/gdynamic/${imageId}/0`;
|
|
4037
|
+
}
|
|
4038
|
+
__name(getNoticeImageUrl, "getNoticeImageUrl");
|
|
4039
|
+
var generateNoticeListItems = /* @__PURE__ */ __name((records, currentPage, pageSize, groupId) => {
|
|
4040
|
+
return records.map((record, index) => {
|
|
4041
|
+
const globalIndex = (currentPage - 1) * pageSize + index + 1;
|
|
4042
|
+
const contentHtml = parseNoticeContentToHtml(record.message.text);
|
|
4043
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
4044
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
4045
|
+
const imageCount = record.message.images?.length || 0;
|
|
4046
|
+
let imagesHtml = "";
|
|
4047
|
+
if (record.message.images && record.message.images.length > 0) {
|
|
4048
|
+
const imageItems = record.message.images.slice(0, 3).map((img) => {
|
|
4049
|
+
const imgUrl = getNoticeImageUrl(img.id);
|
|
4050
|
+
return `<img class="notice-image-preview" src="${imgUrl}" alt="公告图片" onerror="this.style.display='none';" />`;
|
|
4051
|
+
}).join("");
|
|
4052
|
+
imagesHtml = `<div class="notice-images">${imageItems}${imageCount > 3 ? `<span class="notice-image-more">+${imageCount - 3}</span>` : ""}</div>`;
|
|
4053
|
+
}
|
|
4054
|
+
if (record.message.images && record.message.images.length > 0) {
|
|
4055
|
+
const imageItems = record.message.images.slice(0, 3).map((img) => {
|
|
4056
|
+
const imgUrl = getNoticeImageUrl(img.id);
|
|
4057
|
+
return `<img class="notice-image-preview" src="${imgUrl}" alt="公告图片" onerror="this.style.display='none';" />`;
|
|
4058
|
+
}).join("");
|
|
4059
|
+
imagesHtml = `<div class="notice-images">${imageItems}${imageCount > 3 ? `<span class="notice-image-more">+${imageCount - 3}</span>` : ""}</div>`;
|
|
4060
|
+
}
|
|
4061
|
+
return `
|
|
4062
|
+
<div class="notice-item">
|
|
4063
|
+
<div class="notice-column-1">
|
|
4064
|
+
<div class="notice-number">${globalIndex.toString().padStart(2, "0")}</div>
|
|
4065
|
+
<div class="notice-avatar">
|
|
4066
|
+
<img src="${senderAvatarUrl}" alt="头像" />
|
|
4067
|
+
</div>
|
|
4068
|
+
</div>
|
|
4069
|
+
<div class="notice-column-2">
|
|
4070
|
+
<div class="notice-sender">发布者</div>
|
|
4071
|
+
<div class="notice-sender-id"><span class="qq-label">QQ:</span> <span class="qq-number">${record.sender_id}</span></div>
|
|
4072
|
+
</div>
|
|
4073
|
+
<div class="notice-column-3">
|
|
4074
|
+
<div class="notice-content">${contentHtml}</div>
|
|
4075
|
+
${imagesHtml}
|
|
4076
|
+
<div class="notice-meta">
|
|
4077
|
+
<span class="notice-time">⏰ ${timeStr}</span>
|
|
4078
|
+
${imageCount > 0 ? `<span class="notice-image-count">🖼️ ${imageCount}张图</span>` : ""}
|
|
4079
|
+
</div>
|
|
4080
|
+
</div>
|
|
4081
|
+
</div>
|
|
4082
|
+
`;
|
|
4083
|
+
}).join("");
|
|
4084
|
+
}, "generateNoticeListItems");
|
|
4085
|
+
var getSourceHanSerifStyleNoticeHtmlStr = /* @__PURE__ */ __name(async (result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
4086
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: radial-gradient(circle at center, rgba(255,255,255,0.2), rgba(0,0,0,0.05)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : "background: linear-gradient(135deg, #667eea, #764ba2);";
|
|
4087
|
+
const timestamp = generateTimestamp();
|
|
4088
|
+
return `<!DOCTYPE html>
|
|
4089
|
+
<html>
|
|
4090
|
+
<head>
|
|
4091
|
+
<style>
|
|
4092
|
+
${fontBase64 ? `@font-face { font-family: 'SourceHanSerifSC'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
4093
|
+
|
|
4094
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
4095
|
+
body {
|
|
4096
|
+
font-family: ${fontBase64 ? "'SourceHanSerifSC'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
4097
|
+
width: 850px;
|
|
4098
|
+
height: auto;
|
|
4099
|
+
min-height: 100vh;
|
|
4100
|
+
display: flex;
|
|
4101
|
+
align-items: center;
|
|
4102
|
+
justify-content: center;
|
|
4103
|
+
${backgroundStyle}
|
|
4104
|
+
background-repeat: no-repeat;
|
|
4105
|
+
position: relative;
|
|
4106
|
+
box-sizing: border-box;
|
|
4107
|
+
overflow: visible;
|
|
4108
|
+
color: #333;
|
|
4109
|
+
padding: 35px;
|
|
4110
|
+
}
|
|
4111
|
+
|
|
4112
|
+
.card {
|
|
4113
|
+
width: 720px;
|
|
4114
|
+
height: auto;
|
|
4115
|
+
min-height: 400px;
|
|
4116
|
+
background: rgba(255, 255, 255, 0.35);
|
|
4117
|
+
backdrop-filter: blur(20px) saturate(180%);
|
|
4118
|
+
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
4119
|
+
border-radius: 24px;
|
|
4120
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
4121
|
+
position: relative;
|
|
4122
|
+
overflow: visible;
|
|
4123
|
+
display: flex;
|
|
4124
|
+
flex-direction: column;
|
|
4125
|
+
padding: 30px;
|
|
4126
|
+
box-sizing: border-box;
|
|
4127
|
+
}
|
|
4128
|
+
|
|
4129
|
+
.group-header { display: flex; align-items: center; margin-bottom: 18px; padding: 16px; background: rgba(255,255,255,0.4); border: 1px solid rgba(255,255,255,0.5); border-radius: 16px; }
|
|
4130
|
+
.group-avatar { width: 70px; height: 70px; border-radius: 50%; margin-right: 14px; border: 3px solid rgba(255,255,255,0.6); }
|
|
4131
|
+
.group-info { flex: 1; }
|
|
4132
|
+
.group-name { font-size: 26px; font-weight: 800; color: #111; margin-bottom: 4px; text-shadow: 0 1px 2px rgba(255,255,255,0.8); }
|
|
4133
|
+
.group-details { font-size: 16px; color: #444; line-height: 1.3; font-weight: 600; text-shadow: 0 1px 2px rgba(255,255,255,0.7); }
|
|
4134
|
+
|
|
4135
|
+
.title { font-size: 36px; font-weight: 800; margin-bottom: 14px; color: #111; text-align: center; text-shadow: 0 2px 4px rgba(255,255,255,0.8); }
|
|
4136
|
+
.pagination-info { font-size: 15px; color: #555; text-align: center; margin-bottom: 14px; font-weight: 600; }
|
|
4137
|
+
|
|
4138
|
+
.notice-list { width: 100%; display: flex; flex-direction: column; gap: 10px; }
|
|
4139
|
+
|
|
4140
|
+
.notice-item { background: rgba(255,255,255,0.5); border: 1px solid rgba(255,255,255,0.4); border-radius: 12px; padding: 14px; display: flex; align-items: flex-start; transition: all 0.3s ease; min-height: 80px; }
|
|
4141
|
+
.notice-item:hover { background: rgba(255,255,255,0.65); }
|
|
4142
|
+
|
|
4143
|
+
.notice-column-1 { display: flex; flex-direction: row; align-items: center; margin-right: 12px; min-width: 90px; }
|
|
4144
|
+
.notice-avatar img { width: 55px; height: 55px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.6); }
|
|
4145
|
+
.notice-number { font-size: 20px; margin: 0 8px 0 0; font-weight: 800; color: #333; }
|
|
4146
|
+
|
|
4147
|
+
.notice-column-2 { min-width: 100px; margin-right: 14px; }
|
|
4148
|
+
.notice-sender { font-size: 14px; color: #555; margin-bottom: 3px; font-weight: 600; }
|
|
4149
|
+
.notice-sender-id { font-size: 13px; font-weight: 600; }
|
|
4150
|
+
.qq-label { color: #555; font-weight: 600; }
|
|
4151
|
+
.qq-number { color: #111; font-family: 'Courier New', monospace; font-weight: bold; }
|
|
4152
|
+
|
|
4153
|
+
.notice-column-3 { flex: 1; }
|
|
4154
|
+
.notice-content { font-size: 15px; color: #212121; line-height: 1.5; margin-bottom: 8px; word-break: break-all; white-space: pre-wrap; max-height: 120px; overflow: hidden; position: relative; font-weight: 500; }
|
|
4155
|
+
.notice-content::after { content: ''; position: absolute; bottom: 0; right: 0; width: 100%; height: 1.5em; background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.6)); pointer-events: none; }
|
|
4156
|
+
.notice-images { display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
|
|
4157
|
+
.notice-image-preview { width: 60px; height: 60px; object-fit: cover; border-radius: 6px; border: 1px solid rgba(0,0,0,0.1); }
|
|
4158
|
+
.notice-image-more { display: flex; align-items: center; justify-content: center; width: 60px; height: 60px; background: rgba(0,0,0,0.1); border-radius: 6px; font-size: 14px; color: #444; font-weight: 600; }
|
|
4159
|
+
.notice-meta { font-size: 12px; color: #555; display: flex; gap: 14px; flex-wrap: wrap; font-weight: 600; }
|
|
4160
|
+
.notice-time { color: #555; font-weight: 600; }
|
|
4161
|
+
.notice-image-count { color: #1e90ff; font-weight: bold; }
|
|
4162
|
+
|
|
4163
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(128, 128, 128, 0.6); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
4164
|
+
|
|
4165
|
+
body.dark { color: #e0e0e0; }
|
|
4166
|
+
body.dark .card { background: rgba(20,20,20,0.4); box-shadow: 0 20px 60px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.15); }
|
|
4167
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(255,255,255,0.15); }
|
|
4168
|
+
body.dark .group-name { color: #ffffff; }
|
|
4169
|
+
body.dark .group-details { color: #b0b0b0; }
|
|
4170
|
+
body.dark .title { color: #ffffff; text-shadow: 0 2px 4px rgba(0,0,0,0.4); }
|
|
4171
|
+
body.dark .pagination-info { color: #aaa; }
|
|
4172
|
+
body.dark .notice-item { background: rgba(40,40,40,0.5); border-color: rgba(255,255,255,0.1); }
|
|
4173
|
+
body.dark .notice-item:hover { background: rgba(50,50,50,0.6); }
|
|
4174
|
+
body.dark .notice-content::after { background: linear-gradient(to bottom, transparent, rgba(40,40,40,0.8)); }
|
|
4175
|
+
body.dark .notice-number { color: #fff; }
|
|
4176
|
+
body.dark .notice-sender { color: #ddd; }
|
|
4177
|
+
body.dark .qq-label { color: #ccc; }
|
|
4178
|
+
body.dark .qq-number { color: #fff; }
|
|
4179
|
+
body.dark .notice-content { color: #fff; }
|
|
4180
|
+
body.dark .notice-image-preview { border-color: rgba(255,255,255,0.2); }
|
|
4181
|
+
body.dark .notice-image-more { background: rgba(255,255,255,0.1); color: #ddd; }
|
|
4182
|
+
body.dark .timestamp-watermark { color: rgba(160, 160, 160, 0.5); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
4183
|
+
</style>
|
|
4184
|
+
</head>
|
|
4185
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
4186
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
4187
|
+
<div class="card">
|
|
4188
|
+
<div class="group-header">
|
|
4189
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
4190
|
+
<div class="group-info">
|
|
4191
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
4192
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
4193
|
+
</div>
|
|
4194
|
+
</div>
|
|
4195
|
+
<div class="title">📢 群公告列表</div>
|
|
4196
|
+
<div class="pagination-info">第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条公告)</div>
|
|
4197
|
+
<div class="notice-list">
|
|
4198
|
+
${generateNoticeListItems(result.records, result.currentPage, result.pageSize, contextInfo.groupId)}
|
|
4199
|
+
</div>
|
|
4200
|
+
</div>
|
|
4201
|
+
</body>
|
|
4202
|
+
</html>`;
|
|
4203
|
+
}, "getSourceHanSerifStyleNoticeHtmlStr");
|
|
4204
|
+
var getLXGWWenKaiStyleNoticeHtmlStr = /* @__PURE__ */ __name(async (result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
4205
|
+
const timestamp = generateTimestamp();
|
|
4206
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: linear-gradient(45deg, rgba(245,240,230,0.85), rgba(250,245,235,0.85)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : `background: linear-gradient(45deg, #f5f0e6, #faf5eb);`;
|
|
4207
|
+
return `<!DOCTYPE html>
|
|
4208
|
+
<html>
|
|
4209
|
+
<head>
|
|
4210
|
+
<style>
|
|
4211
|
+
${fontBase64 ? `@font-face { font-family: 'LXGWWenKai'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
4212
|
+
|
|
4213
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
4214
|
+
body {
|
|
4215
|
+
font-family: ${fontBase64 ? "'LXGWWenKai'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
4216
|
+
width: 850px;
|
|
4217
|
+
height: auto;
|
|
4218
|
+
min-height: 100vh;
|
|
4219
|
+
display: flex;
|
|
4220
|
+
align-items: center;
|
|
4221
|
+
justify-content: center;
|
|
4222
|
+
${backgroundStyle}
|
|
4223
|
+
position: relative;
|
|
4224
|
+
box-sizing: border-box;
|
|
4225
|
+
overflow: visible;
|
|
4226
|
+
color: #3a2f2a;
|
|
4227
|
+
padding: 35px;
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
body::before { content: ''; position: absolute; top: 16px; left: 16px; right: 16px; bottom: 16px; border: 3px solid #d4af37; border-radius: 20px; background: linear-gradient(135deg, rgba(212,175,55,0.12) 0%, rgba(184,134,11,0.06) 50%, rgba(212,175,55,0.12) 100%); box-shadow: inset 0 0 25px rgba(212,175,55,0.35), 0 0 35px rgba(212,175,55,0.25); z-index: 1; }
|
|
4231
|
+
body::after { content: '◆'; position: absolute; top: 30px; left: 30px; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
4232
|
+
|
|
4233
|
+
.corner-decoration { position: absolute; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
4234
|
+
.corner-decoration.top-right { top: 30px; right: 30px; }
|
|
4235
|
+
.corner-decoration.bottom-left { bottom: 30px; left: 30px; }
|
|
4236
|
+
.corner-decoration.bottom-right { bottom: 30px; right: 30px; }
|
|
4237
|
+
|
|
4238
|
+
.main-container {
|
|
4239
|
+
width: 720px;
|
|
4240
|
+
min-height: 400px;
|
|
4241
|
+
position: relative;
|
|
4242
|
+
z-index: 3;
|
|
4243
|
+
display: flex;
|
|
4244
|
+
flex-direction: column;
|
|
4245
|
+
padding: 32px 28px;
|
|
4246
|
+
box-sizing: border-box;
|
|
4247
|
+
}
|
|
4248
|
+
|
|
4249
|
+
.group-header { display: flex; align-items: center; margin-bottom: 18px; padding: 16px; background: rgba(255,255,255,0.2); border: 1px solid rgba(212,175,55,0.4); border-radius: 16px; box-shadow: 0 4px 16px rgba(212,175,55,0.15); }
|
|
4250
|
+
.group-avatar { width: 64px; height: 64px; border-radius: 9%; margin-right: 14px; border: 3px solid #d4af37; box-shadow: 0 4px 12px rgba(212,175,55,0.3); }
|
|
4251
|
+
.group-info { flex: 1; }
|
|
4252
|
+
.group-name { font-size: 25px; font-weight: 800; color: #5d2e0c; margin-bottom: 4px; text-shadow: 1px 1px 2px rgba(139,69,19,0.3); }
|
|
4253
|
+
.group-details { font-size: 20px; color: #6b3a1a; line-height: 1.4; font-weight: 700; text-shadow: 1px 1px 2px rgba(139,69,19,0.2); }
|
|
4254
|
+
|
|
4255
|
+
.title-section { text-align: center; margin-bottom: 14px; }
|
|
4256
|
+
.main-title { font-size: 46px; font-weight: 800; color: #5d2e0c; margin-bottom: 6px; text-shadow: 2px 2px 4px rgba(139,69,19,0.4); letter-spacing: 2px; }
|
|
4257
|
+
.pagination-info { font-size: 16px; color: #6b3a1a; text-align: center; margin-bottom: 14px; font-weight: 700; }
|
|
4258
|
+
|
|
4259
|
+
.notice-list { width: 100%; display: flex; flex-direction: column; gap: 6px; }
|
|
4260
|
+
|
|
4261
|
+
.notice-item { background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 12px; padding: 14px; display: flex; align-items: flex-start; box-shadow: 0 3px 10px rgba(0,0,0,0.08); transition: all 0.3s ease; backdrop-filter: blur(5px); min-height: 80px; }
|
|
4262
|
+
.notice-item:hover { transform: translateY(-1px); box-shadow: 0 5px 18px rgba(212,175,55,0.25); background: rgba(255,255,255,0.3); }
|
|
4263
|
+
|
|
4264
|
+
.notice-column-1 { display: flex; flex-direction: row; align-items: center; margin-right: 14px; min-width: 90px; }
|
|
4265
|
+
.notice-avatar img { width: 55px; height: 55px; border-radius: 50%; border: 2px solid #d4af37; box-shadow: 0 2px 6px rgba(212,175,55,0.2); }
|
|
4266
|
+
.notice-number { font-size: 24px; margin: 0 10px 0 0; font-weight: 800; color: #5d2e0c; }
|
|
4267
|
+
|
|
4268
|
+
.notice-column-2 { min-width: 100px; margin-right: 14px; }
|
|
4269
|
+
.notice-sender { font-size: 14px; color: #6b3a1a; font-weight: 700; margin-bottom: 3px; }
|
|
4270
|
+
.notice-sender-id { font-size: 13px; font-weight: 700; }
|
|
4271
|
+
.qq-label { color: #6b3a1a; font-weight: 700; }
|
|
4272
|
+
.qq-number { color: #2a1f1a; font-family: 'Courier New', monospace; font-weight: 800; }
|
|
4273
|
+
|
|
4274
|
+
.notice-column-3 { flex: 1; }
|
|
4275
|
+
.notice-content { font-size: 15px; color: #2a1f1a; line-height: 1.5; margin-bottom: 8px; word-break: break-all; white-space: pre-wrap; max-height: 120px; overflow: hidden; position: relative; font-weight: 600; }
|
|
4276
|
+
.notice-content::after { content: ''; position: absolute; bottom: 0; right: 0; width: 100%; height: 1.5em; background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.3)); pointer-events: none; }
|
|
4277
|
+
.notice-item:hover .notice-content::after { background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.4)); }
|
|
4278
|
+
.notice-images { display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
|
|
4279
|
+
.notice-image-preview { width: 60px; height: 60px; object-fit: cover; border-radius: 6px; border: 1px solid rgba(212,175,55,0.3); }
|
|
4280
|
+
.notice-image-more { display: flex; align-items: center; justify-content: center; width: 60px; height: 60px; background: rgba(212,175,55,0.15); border-radius: 6px; font-size: 14px; color: #5d2e0c; font-weight: 700; }
|
|
4281
|
+
.notice-meta { font-size: 12px; color: #6b3a1a; display: flex; gap: 14px; flex-wrap: wrap; font-weight: 700; }
|
|
4282
|
+
.notice-time { color: #6b3a1a; font-weight: 700; }
|
|
4283
|
+
.notice-image-count { color: #5d2e0c; font-weight: 800; }
|
|
4284
|
+
|
|
4285
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(139, 69, 19, 0.4); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
4286
|
+
|
|
4287
|
+
body.dark { background: linear-gradient(45deg, #2c2416, #3a2f1f); color: #e6d7c3; }
|
|
4288
|
+
body.dark::before { border-color: #b8860b; background: linear-gradient(135deg, rgba(184,134,11,0.18) 0%, rgba(139,69,19,0.12) 50%, rgba(184,134,11,0.18) 100%); box-shadow: inset 0 0 25px rgba(184,134,11,0.45), 0 0 35px rgba(184,134,11,0.35); }
|
|
4289
|
+
body.dark::after { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
4290
|
+
body.dark .corner-decoration { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
4291
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(184,134,11,0.5); }
|
|
4292
|
+
body.dark .group-name { color: #daa520; text-shadow: 1px 1px 2px rgba(218,165,32,0.3); }
|
|
4293
|
+
body.dark .group-details { color: #cd853f; }
|
|
4294
|
+
body.dark .main-title { color: #daa520; text-shadow: 2px 2px 4px rgba(218,165,32,0.4); }
|
|
4295
|
+
body.dark .pagination-info { color: #cd853f; }
|
|
4296
|
+
body.dark .notice-item { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
4297
|
+
body.dark .notice-item:hover { box-shadow: 0 5px 18px rgba(184,134,11,0.35); background: rgba(0,0,0,0.4); }
|
|
4298
|
+
body.dark .notice-content::after { background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.4)); }
|
|
4299
|
+
body.dark .notice-item:hover .notice-content::after { background: linear-gradient(to bottom, transparent, rgba(0,0,0,0.5)); }
|
|
4300
|
+
body.dark .notice-number { color: #daa520; }
|
|
4301
|
+
body.dark .notice-sender { color: #cd853f; }
|
|
4302
|
+
body.dark .qq-label { color: #cd853f; }
|
|
4303
|
+
body.dark .qq-number { color: #e6d7c3; }
|
|
4304
|
+
body.dark .notice-content { color: #e6d7c3; }
|
|
4305
|
+
body.dark .notice-image-preview { border-color: rgba(184,134,11,0.4); }
|
|
4306
|
+
body.dark .notice-image-more { background: rgba(184,134,11,0.2); color: #daa520; }
|
|
4307
|
+
body.dark .notice-meta { color: #cd853f; }
|
|
4308
|
+
body.dark .notice-time { color: #cd853f; }
|
|
4309
|
+
body.dark .notice-image-count { color: #daa520; }
|
|
4310
|
+
body.dark .timestamp-watermark { color: rgba(218, 165, 32, 0.4); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
4311
|
+
</style>
|
|
4312
|
+
</head>
|
|
4313
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
4314
|
+
<div class="corner-decoration top-right">◆</div>
|
|
4315
|
+
<div class="corner-decoration bottom-left">◆</div>
|
|
4316
|
+
<div class="corner-decoration bottom-right">◆</div>
|
|
4317
|
+
<div class="main-container">
|
|
4318
|
+
<div class="group-header">
|
|
4319
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
4320
|
+
<div class="group-info">
|
|
4321
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
4322
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
4323
|
+
</div>
|
|
4324
|
+
</div>
|
|
4325
|
+
<div class="title-section">
|
|
4326
|
+
<div class="main-title">「 群公告列表 」</div>
|
|
4327
|
+
</div>
|
|
4328
|
+
<div class="pagination-info">第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条公告)</div>
|
|
4329
|
+
<div class="notice-list">
|
|
4330
|
+
${generateNoticeListItems(result.records, result.currentPage, result.pageSize, contextInfo.groupId)}
|
|
4331
|
+
</div>
|
|
4332
|
+
</div>
|
|
4333
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
4334
|
+
</body>
|
|
4335
|
+
</html>`;
|
|
4336
|
+
}, "getLXGWWenKaiStyleNoticeHtmlStr");
|
|
4337
|
+
var getFlatMinimalStyleNoticeHtmlStr = /* @__PURE__ */ __name(async (result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
4338
|
+
const timestamp = generateTimestamp();
|
|
4339
|
+
const colors = enableDarkMode ? {
|
|
4340
|
+
background: "#000000",
|
|
4341
|
+
cardBackground: "#1a1a1a",
|
|
4342
|
+
textPrimary: "#ffffff",
|
|
4343
|
+
textSecondary: "#b0b0b0",
|
|
4344
|
+
primary: "#00d4ff",
|
|
4345
|
+
border: "#333333",
|
|
4346
|
+
hover: "#2a2a2a"
|
|
4347
|
+
} : {
|
|
4348
|
+
background: "#f5f7fa",
|
|
4349
|
+
cardBackground: "#ffffff",
|
|
4350
|
+
textPrimary: "#2c3e50",
|
|
4351
|
+
textSecondary: "#6c757d",
|
|
4352
|
+
primary: "#007bff",
|
|
4353
|
+
border: "#dee2e6",
|
|
4354
|
+
hover: "#f8f9fa"
|
|
4355
|
+
};
|
|
4356
|
+
return `<!DOCTYPE html>
|
|
4357
|
+
<html>
|
|
4358
|
+
<head>
|
|
4359
|
+
<style>
|
|
4360
|
+
${fontBase64 ? `@font-face { font-family: 'CustomFont'; src: url('data:font/opentype;charset=utf-8;base64,${fontBase64}') format('opentype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
4361
|
+
|
|
4362
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
4363
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; }
|
|
4364
|
+
|
|
4365
|
+
body {
|
|
4366
|
+
font-family: ${fontBase64 ? "'CustomFont'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", sans-serif;
|
|
4367
|
+
width: 850px;
|
|
4368
|
+
min-height: 100vh;
|
|
4369
|
+
background: ${colors.background};
|
|
4370
|
+
color: ${colors.textPrimary};
|
|
4371
|
+
padding: 40px;
|
|
4372
|
+
display: flex;
|
|
4373
|
+
align-items: center;
|
|
4374
|
+
justify-content: center;
|
|
4375
|
+
}
|
|
4376
|
+
|
|
4377
|
+
.container { width: 100%; max-width: 720px; }
|
|
4378
|
+
|
|
4379
|
+
.header {
|
|
4380
|
+
background: ${colors.cardBackground};
|
|
4381
|
+
border: 2px solid ${colors.border};
|
|
4382
|
+
border-radius: 20px;
|
|
4383
|
+
padding: 32px;
|
|
4384
|
+
margin-bottom: 24px;
|
|
4385
|
+
box-shadow: 0 4px 16px rgba(0,0,0,${enableDarkMode ? "0.3" : "0.08"});
|
|
4386
|
+
}
|
|
4387
|
+
|
|
4388
|
+
.group-info-wrapper { display: flex; align-items: center; gap: 24px; margin-bottom: 24px; }
|
|
4389
|
+
.group-avatar { width: 90px; height: 90px; border-radius: 16px; object-fit: cover; border: 3px solid ${colors.primary}; }
|
|
4390
|
+
.group-details { flex: 1; }
|
|
4391
|
+
.group-name { font-size: 26px; font-weight: 800; color: ${colors.textPrimary}; margin-bottom: 8px; }
|
|
4392
|
+
.group-meta { font-size: 16px; color: ${colors.textSecondary}; font-weight: 600; }
|
|
4393
|
+
|
|
4394
|
+
.title { font-size: 36px; font-weight: 800; color: ${colors.primary}; text-align: center; margin-bottom: 8px; }
|
|
4395
|
+
.pagination-info { font-size: 15px; color: ${colors.textSecondary}; text-align: center; font-weight: 600; }
|
|
4396
|
+
|
|
4397
|
+
.notice-list { display: flex; flex-direction: column; gap: 12px; }
|
|
4398
|
+
|
|
4399
|
+
.notice-item {
|
|
4400
|
+
background: ${colors.cardBackground};
|
|
4401
|
+
border: 2px solid ${colors.border};
|
|
4402
|
+
border-radius: 16px;
|
|
4403
|
+
padding: 20px;
|
|
4404
|
+
display: flex;
|
|
4405
|
+
align-items: flex-start;
|
|
4406
|
+
gap: 16px;
|
|
4407
|
+
transition: all 0.2s ease;
|
|
4408
|
+
}
|
|
4409
|
+
.notice-item:hover { border-color: ${colors.primary}; transform: translateY(-2px); }
|
|
4410
|
+
|
|
4411
|
+
.notice-number { font-size: 24px; font-weight: 800; color: ${colors.primary}; min-width: 40px; }
|
|
4412
|
+
.notice-avatar img { width: 50px; height: 50px; border-radius: 50%; border: 2px solid ${colors.border}; }
|
|
4413
|
+
.notice-info { flex: 1; }
|
|
4414
|
+
.notice-sender-id { font-size: 14px; color: ${colors.textSecondary}; margin-bottom: 8px; font-weight: 600; }
|
|
4415
|
+
.notice-content { font-size: 15px; color: ${colors.textPrimary}; line-height: 1.6; margin-bottom: 8px; max-height: 100px; overflow: hidden; font-weight: 500; }
|
|
4416
|
+
.notice-images { display: flex; gap: 6px; margin-bottom: 8px; }
|
|
4417
|
+
.notice-image-preview { width: 50px; height: 50px; object-fit: cover; border-radius: 8px; border: 1px solid ${colors.border}; }
|
|
4418
|
+
.notice-meta { font-size: 12px; color: ${colors.textSecondary}; display: flex; gap: 12px; font-weight: 600; }
|
|
4419
|
+
|
|
4420
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 12px; color: ${enableDarkMode ? "rgba(160,160,160,0.4)" : "rgba(100,100,100,0.4)"}; font-family: 'Courier New', monospace; z-index: 9999; }
|
|
4421
|
+
</style>
|
|
4422
|
+
</head>
|
|
4423
|
+
<body>
|
|
4424
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
4425
|
+
<div class="container">
|
|
4426
|
+
<div class="header">
|
|
4427
|
+
<div class="group-info-wrapper">
|
|
4428
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
4429
|
+
<div class="group-details">
|
|
4430
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
4431
|
+
<div class="group-meta">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
4432
|
+
</div>
|
|
4433
|
+
</div>
|
|
4434
|
+
<div class="title">📢 群公告列表</div>
|
|
4435
|
+
<div class="pagination-info">第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条公告)</div>
|
|
4436
|
+
</div>
|
|
4437
|
+
<div class="notice-list">
|
|
4438
|
+
${result.records.map((record, index) => {
|
|
4439
|
+
const globalIndex = (result.currentPage - 1) * result.pageSize + index + 1;
|
|
4440
|
+
const contentHtml = parseNoticeContentToHtml(record.message.text);
|
|
4441
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
4442
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
4443
|
+
const imageCount = record.message.images?.length || 0;
|
|
4444
|
+
let imagesHtml = "";
|
|
4445
|
+
if (record.message.images && record.message.images.length > 0) {
|
|
4446
|
+
imagesHtml = `<div class="notice-images">${record.message.images.slice(0, 3).map(
|
|
4447
|
+
(img) => `<img class="notice-image-preview" src="${getNoticeImageUrl(img.id)}" alt="图" onerror="this.style.display='none';" />`
|
|
4448
|
+
).join("")}</div>`;
|
|
4449
|
+
}
|
|
4450
|
+
return `
|
|
4451
|
+
<div class="notice-item">
|
|
4452
|
+
<div class="notice-number">${globalIndex.toString().padStart(2, "0")}</div>
|
|
4453
|
+
<img class="notice-avatar" src="${senderAvatarUrl}" alt="头像" style="width:50px;height:50px;border-radius:50%;" />
|
|
4454
|
+
<div class="notice-info">
|
|
4455
|
+
<div class="notice-sender-id">发布者: ${record.sender_id}</div>
|
|
4456
|
+
<div class="notice-content">${contentHtml}</div>
|
|
4457
|
+
${imagesHtml}
|
|
4458
|
+
<div class="notice-meta">
|
|
4459
|
+
<span>⏰ ${timeStr}</span>
|
|
4460
|
+
${imageCount > 0 ? `<span>🖼️ ${imageCount}张图</span>` : ""}
|
|
4461
|
+
</div>
|
|
4462
|
+
</div>
|
|
4463
|
+
</div>
|
|
4464
|
+
`;
|
|
4465
|
+
}).join("")}
|
|
4466
|
+
</div>
|
|
4467
|
+
</div>
|
|
4468
|
+
</body>
|
|
4469
|
+
</html>`;
|
|
4470
|
+
}, "getFlatMinimalStyleNoticeHtmlStr");
|
|
4471
|
+
async function renderGroupNotice(ctx, result, contextInfo, imageStyle, enableDarkMode, imageType, screenshotQuality) {
|
|
4472
|
+
const groupAvatarBase64 = await getGroupAvatarBase64(ctx, contextInfo.groupId.toString());
|
|
4473
|
+
const fontBase64 = await getFontBase64(ctx, imageStyle);
|
|
4474
|
+
let htmlStr;
|
|
4475
|
+
switch (imageStyle) {
|
|
4476
|
+
case IMAGE_STYLES.SOURCE_HAN_SERIF_SC:
|
|
4477
|
+
htmlStr = await getSourceHanSerifStyleNoticeHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
4478
|
+
break;
|
|
4479
|
+
case IMAGE_STYLES.LXGW_WENKAI:
|
|
4480
|
+
htmlStr = await getLXGWWenKaiStyleNoticeHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
4481
|
+
break;
|
|
4482
|
+
case IMAGE_STYLES.FLAT_MINIMAL:
|
|
4483
|
+
htmlStr = await getFlatMinimalStyleNoticeHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
4484
|
+
break;
|
|
4485
|
+
default:
|
|
4486
|
+
htmlStr = await getSourceHanSerifStyleNoticeHtmlStr(result, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
4487
|
+
}
|
|
4488
|
+
const page = await ctx.puppeteer.page();
|
|
4489
|
+
await page.setContent(htmlStr, {
|
|
4490
|
+
waitUntil: "domcontentloaded",
|
|
4491
|
+
timeout: 15e3
|
|
4492
|
+
});
|
|
4493
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
4494
|
+
const bodyHandle = await page.$("body");
|
|
4495
|
+
const boundingBox = await bodyHandle.boundingBox();
|
|
4496
|
+
const contentHeight = Math.ceil(boundingBox.height);
|
|
4497
|
+
const contentWidth = Math.ceil(boundingBox.width);
|
|
4498
|
+
await page.setViewport({
|
|
4499
|
+
width: contentWidth,
|
|
4500
|
+
height: contentHeight,
|
|
4501
|
+
deviceScaleFactor: 2
|
|
4502
|
+
});
|
|
4503
|
+
const screenshotOptions = {
|
|
4504
|
+
fullPage: true,
|
|
4505
|
+
type: imageType,
|
|
4506
|
+
encoding: "base64"
|
|
4507
|
+
};
|
|
4508
|
+
if (imageType !== "png") {
|
|
4509
|
+
screenshotOptions.quality = screenshotQuality;
|
|
4510
|
+
}
|
|
4511
|
+
const screenshot = await page.screenshot(screenshotOptions);
|
|
4512
|
+
await page.close();
|
|
4513
|
+
return screenshot;
|
|
4514
|
+
}
|
|
4515
|
+
__name(renderGroupNotice, "renderGroupNotice");
|
|
4516
|
+
|
|
4517
|
+
// src/commandGroupNotice.ts
|
|
4518
|
+
function paginateNoticeMessages(noticeList, page, pageSize) {
|
|
4519
|
+
const totalCount = noticeList.length;
|
|
4520
|
+
const totalPages = Math.ceil(totalCount / pageSize);
|
|
4521
|
+
const startIndex = (page - 1) * pageSize;
|
|
4522
|
+
const endIndex = startIndex + pageSize;
|
|
4523
|
+
const records = noticeList.slice(startIndex, endIndex);
|
|
4524
|
+
return {
|
|
4525
|
+
records,
|
|
4526
|
+
totalCount,
|
|
4527
|
+
currentPage: page,
|
|
4528
|
+
pageSize,
|
|
4529
|
+
totalPages,
|
|
4530
|
+
hasNext: page < totalPages,
|
|
4531
|
+
hasPrev: page > 1
|
|
4532
|
+
};
|
|
4533
|
+
}
|
|
4534
|
+
__name(paginateNoticeMessages, "paginateNoticeMessages");
|
|
4535
|
+
function parseNoticeText(text) {
|
|
4536
|
+
if (!text) return "";
|
|
4537
|
+
return text.replace(/ /g, "\n").replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'");
|
|
4538
|
+
}
|
|
4539
|
+
__name(parseNoticeText, "parseNoticeText");
|
|
4540
|
+
function formatTimestamp2(timestamp) {
|
|
4541
|
+
const date = new Date(timestamp * 1e3);
|
|
4542
|
+
return date.toLocaleString("zh-CN", {
|
|
4543
|
+
year: "numeric",
|
|
4544
|
+
month: "2-digit",
|
|
4545
|
+
day: "2-digit",
|
|
4546
|
+
hour: "2-digit",
|
|
4547
|
+
minute: "2-digit"
|
|
4548
|
+
});
|
|
4549
|
+
}
|
|
4550
|
+
__name(formatTimestamp2, "formatTimestamp");
|
|
4551
|
+
function formatGroupNoticeAsText(result, contextInfo, config) {
|
|
4552
|
+
let output = `📢 群公告列表
|
|
4553
|
+
`;
|
|
4554
|
+
output += `==================
|
|
4555
|
+
`;
|
|
4556
|
+
output += `📍 群聊: ${contextInfo.groupName} (${contextInfo.groupId})
|
|
4557
|
+
`;
|
|
4558
|
+
output += `📊 第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条公告)
|
|
4559
|
+
`;
|
|
4560
|
+
output += `==================
|
|
4561
|
+
|
|
4562
|
+
`;
|
|
4563
|
+
result.records.forEach((record, index) => {
|
|
4564
|
+
const globalIndex = (result.currentPage - 1) * result.pageSize + index + 1;
|
|
4565
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
4566
|
+
const textContent = parseNoticeText(record.message.text);
|
|
4567
|
+
const imageCount = record.message.images?.length || 0;
|
|
4568
|
+
output += `📌 ${globalIndex}. 发布者: ${record.sender_id}
|
|
4569
|
+
`;
|
|
4570
|
+
output += `⏰ ${timeStr}
|
|
4571
|
+
`;
|
|
4572
|
+
output += `💬 ${textContent.substring(0, 100)}${textContent.length > 100 ? "..." : ""}
|
|
4573
|
+
`;
|
|
4574
|
+
if (imageCount > 0) {
|
|
4575
|
+
output += `🖼️ 包含${imageCount}张图片
|
|
4576
|
+
`;
|
|
4577
|
+
}
|
|
4578
|
+
output += `------------------
|
|
4579
|
+
`;
|
|
4580
|
+
});
|
|
4581
|
+
const pageHints = [];
|
|
4582
|
+
if (result.hasPrev) pageHints.push(`上一页: -p ${result.currentPage - 1}`);
|
|
4583
|
+
if (result.hasNext) pageHints.push(`下一页: -p ${result.currentPage + 1}`);
|
|
4584
|
+
if (pageHints.length > 0) {
|
|
4585
|
+
output += `📖 ${pageHints.join(" | ")}
|
|
4586
|
+
`;
|
|
4587
|
+
}
|
|
4588
|
+
return output;
|
|
4589
|
+
}
|
|
4590
|
+
__name(formatGroupNoticeAsText, "formatGroupNoticeAsText");
|
|
4591
|
+
function formatGroupNoticeAsForward(result, contextInfo, config) {
|
|
4592
|
+
let messages = "";
|
|
4593
|
+
const addMessageBlock = /* @__PURE__ */ __name((userId, nickname, content) => {
|
|
4594
|
+
if (userId) {
|
|
4595
|
+
messages += `<message user-id="${userId}" nickname="${nickname}">${content}</message>
|
|
4596
|
+
`;
|
|
4597
|
+
} else {
|
|
4598
|
+
messages += `<message nickname="${nickname}">${content}</message>
|
|
4599
|
+
`;
|
|
4600
|
+
}
|
|
4601
|
+
}, "addMessageBlock");
|
|
4602
|
+
addMessageBlock(void 0, "📢 群公告", `${contextInfo.groupName}
|
|
4603
|
+
第${result.currentPage}/${result.totalPages}页 (共${result.totalCount}条公告)`);
|
|
4604
|
+
result.records.forEach((record, index) => {
|
|
4605
|
+
const globalIndex = (result.currentPage - 1) * result.pageSize + index + 1;
|
|
4606
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
4607
|
+
const textContent = parseNoticeText(record.message.text);
|
|
4608
|
+
const imageCount = record.message.images?.length || 0;
|
|
4609
|
+
let content = `📌 第${globalIndex}条公告
|
|
4610
|
+
`;
|
|
4611
|
+
content += `⏰ ${timeStr}
|
|
4612
|
+
`;
|
|
4613
|
+
content += `💬 ${textContent}`;
|
|
4614
|
+
if (imageCount > 0) {
|
|
4615
|
+
content += `
|
|
4616
|
+
🖼️ 包含${imageCount}张图片`;
|
|
4617
|
+
}
|
|
4618
|
+
addMessageBlock(String(record.sender_id), `发布者 ${record.sender_id}`, content);
|
|
4619
|
+
});
|
|
4620
|
+
const pageHints = [];
|
|
4621
|
+
if (result.hasPrev) pageHints.push(`上一页: -p ${result.currentPage - 1}`);
|
|
4622
|
+
if (result.hasNext) pageHints.push(`下一页: -p ${result.currentPage + 1}`);
|
|
4623
|
+
if (pageHints.length > 0) {
|
|
4624
|
+
addMessageBlock(void 0, "📖 翻页提示", pageHints.join("\n"));
|
|
4625
|
+
}
|
|
4626
|
+
return `<message forward>
|
|
4627
|
+
${messages}
|
|
4628
|
+
</message>`;
|
|
4629
|
+
}
|
|
4630
|
+
__name(formatGroupNoticeAsForward, "formatGroupNoticeAsForward");
|
|
4631
|
+
function registerGroupNoticeCommand(ctx, config, responseHint) {
|
|
4632
|
+
if (!config.enableGroupNoticeCommand) return;
|
|
4633
|
+
ctx.command(config.groupNoticeCommandName, `获取群公告列表, 发送${responseHint}`).alias("群公告列表").alias("agn").option("page", "-p, --page <page:number> 页码,从1开始", { fallback: 1 }).option("pagesize", "-s, --pagesize <pagesize:number> 每页显示条数", { fallback: config.groupNoticePageSize || 10 }).option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }) => {
|
|
4634
|
+
if (!session.onebot)
|
|
4635
|
+
return session.send("[error]当前会话不支持onebot协议。");
|
|
4636
|
+
if (!session.guildId)
|
|
4637
|
+
return session.send("[error]当前会话不在群聊中。");
|
|
4638
|
+
const page = Math.max(1, options.page || 1);
|
|
4639
|
+
const pageSize = Math.max(1, Math.min(50, options.pagesize || config.groupNoticePageSize || 10));
|
|
4640
|
+
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
4641
|
+
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
4642
|
+
if (options.imageStyleIdx !== void 0) {
|
|
4643
|
+
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
4644
|
+
if (!isIdxValid) {
|
|
4645
|
+
let idxInvalidMsgArr = [
|
|
4646
|
+
`图片样式索引不合法。`,
|
|
4647
|
+
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
4648
|
+
` 当前输入:${options.imageStyleIdx}`,
|
|
4649
|
+
`
|
|
4650
|
+
`,
|
|
4651
|
+
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
4652
|
+
];
|
|
4653
|
+
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
4654
|
+
}
|
|
4655
|
+
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
4656
|
+
}
|
|
4657
|
+
try {
|
|
4658
|
+
const onebotBot = session.onebot;
|
|
4659
|
+
const groupNoticeList = await onebotBot.getGroupNotice(session.guildId);
|
|
4660
|
+
if (!groupNoticeList || groupNoticeList.length === 0) {
|
|
4661
|
+
return session.send("该群暂无公告。");
|
|
4662
|
+
}
|
|
4663
|
+
const totalPages = Math.ceil(groupNoticeList.length / pageSize);
|
|
4664
|
+
if (page > totalPages) {
|
|
4665
|
+
return session.send(`[error]页码超出范围。
|
|
4666
|
+
总共${totalPages}页,当前请求第${page}页。`);
|
|
4667
|
+
}
|
|
4668
|
+
const paginatedResult = paginateNoticeMessages(groupNoticeList, page, pageSize);
|
|
4669
|
+
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
4670
|
+
const contextInfo = {
|
|
4671
|
+
groupId: parseInt(session.guildId),
|
|
4672
|
+
groupName: groupInfoObj.group_name || "未知群聊",
|
|
4673
|
+
memberCount: groupInfoObj.member_count || 0,
|
|
4674
|
+
maxMemberCount: groupInfoObj.max_member_count || 0,
|
|
4675
|
+
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`
|
|
4676
|
+
};
|
|
4677
|
+
if (config.verboseConsoleOutput) {
|
|
4678
|
+
ctx.logger.info(`群公告列表: ${JSON.stringify(paginatedResult)}`);
|
|
4679
|
+
}
|
|
4680
|
+
if (config.sendText) {
|
|
4681
|
+
const textMessage = formatGroupNoticeAsText(paginatedResult, contextInfo, config);
|
|
4682
|
+
await session.send(`${config.enableQuoteWithText ? import_koishi5.h.quote(session.messageId) : ""}${textMessage}`);
|
|
4683
|
+
}
|
|
4684
|
+
if (config.sendImage) {
|
|
4685
|
+
const waitTipMsgId = await session.send(`${import_koishi5.h.quote(session.messageId)}🔄正在渲染群公告列表图片,请稍候⏳...`);
|
|
4686
|
+
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
4687
|
+
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
4688
|
+
const noticeImageBase64 = await renderGroupNotice(
|
|
4689
|
+
ctx,
|
|
4690
|
+
paginatedResult,
|
|
4691
|
+
contextInfo,
|
|
4692
|
+
selectedImageStyle,
|
|
4693
|
+
selectedDarkMode,
|
|
4694
|
+
config.imageType,
|
|
4695
|
+
config.screenshotQuality
|
|
4696
|
+
);
|
|
4697
|
+
let imageMessage = `${config.enableQuoteWithImage ? import_koishi5.h.quote(session.messageId) : ""}${import_koishi5.h.image(`data:image/png;base64,${noticeImageBase64}`)}`;
|
|
4698
|
+
const pageHints = [];
|
|
4699
|
+
if (paginatedResult.hasPrev) pageHints.push(`-p ${paginatedResult.currentPage - 1}`);
|
|
4700
|
+
if (paginatedResult.hasNext) pageHints.push(`-p ${paginatedResult.currentPage + 1}`);
|
|
4701
|
+
imageMessage += `
|
|
4702
|
+
📢 第${page}/${totalPages}页 | 共${groupNoticeList.length}条公告`;
|
|
4703
|
+
if (pageHints.length > 0) {
|
|
4704
|
+
imageMessage += ` | 翻页: ${pageHints.join(" / ")}`;
|
|
4705
|
+
}
|
|
4706
|
+
await session.send(imageMessage);
|
|
4707
|
+
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
4708
|
+
}
|
|
4709
|
+
if (config.sendForward) {
|
|
4710
|
+
const forwardMessage = formatGroupNoticeAsForward(paginatedResult, contextInfo, config);
|
|
4711
|
+
await session.send(import_koishi5.h.unescape(forwardMessage));
|
|
4712
|
+
}
|
|
4713
|
+
} catch (error) {
|
|
4714
|
+
ctx.logger.error(`获取群公告列表失败: ${error}`);
|
|
4715
|
+
await session.send(`[error]获取群公告列表失败: ${error.message}`);
|
|
4716
|
+
}
|
|
4717
|
+
});
|
|
4718
|
+
}
|
|
4719
|
+
__name(registerGroupNoticeCommand, "registerGroupNoticeCommand");
|
|
4720
|
+
|
|
4721
|
+
// src/commandGroupNoticeDetail.ts
|
|
4722
|
+
var import_koishi6 = require("koishi");
|
|
4723
|
+
|
|
4724
|
+
// src/renderGroupNoticeDetail.ts
|
|
4725
|
+
function parseNoticeContentToHtmlFull(text) {
|
|
4726
|
+
if (!text) {
|
|
4727
|
+
return '<span class="empty-msg">[空公告]</span>';
|
|
4728
|
+
}
|
|
4729
|
+
let parsed = parseNoticeText(text);
|
|
4730
|
+
parsed = parsed.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\n/g, "<br/>");
|
|
4731
|
+
return `<span class="notice-text">${parsed}</span>`;
|
|
4732
|
+
}
|
|
4733
|
+
__name(parseNoticeContentToHtmlFull, "parseNoticeContentToHtmlFull");
|
|
4734
|
+
function getNoticeImageUrl2(imageId) {
|
|
4735
|
+
return `https://gdynamic.qpic.cn/gdynamic/${imageId}/0`;
|
|
4736
|
+
}
|
|
4737
|
+
__name(getNoticeImageUrl2, "getNoticeImageUrl");
|
|
4738
|
+
var getSourceHanSerifSCStyleDetailHtmlStr2 = /* @__PURE__ */ __name(async (record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
4739
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: radial-gradient(circle at center, rgba(255,255,255,0.15), rgba(0,0,0,0.1)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : "background: linear-gradient(135deg, #667eea, #764ba2);";
|
|
4740
|
+
const timestamp = generateTimestamp();
|
|
4741
|
+
const contentHtml = parseNoticeContentToHtmlFull(record.message.text);
|
|
4742
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
4743
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
4744
|
+
const imageCount = record.message.images?.length || 0;
|
|
4745
|
+
let imagesHtml = "";
|
|
4746
|
+
if (record.message.images && record.message.images.length > 0) {
|
|
4747
|
+
const imageItems = record.message.images.map((img) => {
|
|
4748
|
+
const imgUrl = getNoticeImageUrl2(img.id);
|
|
4749
|
+
return `<div class="notice-image-item"><img class="notice-image-large" src="${imgUrl}" alt="公告图片" onerror="this.parentElement.innerHTML='<span class=\\'image-error\\'>[图片加载失败]</span>';" /></div>`;
|
|
4750
|
+
}).join("");
|
|
4751
|
+
imagesHtml = `<div class="notice-images-section"><div class="images-title">🖼️ 公告图片 (${imageCount}张)</div><div class="images-container">${imageItems}</div></div>`;
|
|
4752
|
+
}
|
|
4753
|
+
return `<!DOCTYPE html>
|
|
4754
|
+
<html>
|
|
4755
|
+
<head>
|
|
4756
|
+
<style>
|
|
4757
|
+
${fontBase64 ? `@font-face { font-family: 'SourceHanSerifSC'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
4758
|
+
|
|
4759
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
4760
|
+
body {
|
|
4761
|
+
font-family: ${fontBase64 ? "'SourceHanSerifSC'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
4762
|
+
width: 850px;
|
|
4763
|
+
height: auto;
|
|
4764
|
+
min-height: 100vh;
|
|
4765
|
+
display: flex;
|
|
4766
|
+
align-items: center;
|
|
4767
|
+
justify-content: center;
|
|
4768
|
+
${backgroundStyle}
|
|
4769
|
+
background-repeat: no-repeat;
|
|
4770
|
+
position: relative;
|
|
4771
|
+
box-sizing: border-box;
|
|
4772
|
+
overflow: visible;
|
|
4773
|
+
color: #333;
|
|
4774
|
+
padding: 35px;
|
|
4775
|
+
}
|
|
4776
|
+
|
|
4777
|
+
.card {
|
|
4778
|
+
width: 720px;
|
|
4779
|
+
height: auto;
|
|
4780
|
+
min-height: 400px;
|
|
4781
|
+
background: rgba(255, 255, 255, 0.35);
|
|
4782
|
+
backdrop-filter: blur(20px) saturate(180%);
|
|
4783
|
+
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
4784
|
+
border-radius: 24px;
|
|
4785
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(255, 255, 255, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
4786
|
+
position: relative;
|
|
4787
|
+
overflow: visible;
|
|
4788
|
+
display: flex;
|
|
4789
|
+
flex-direction: column;
|
|
4790
|
+
padding: 30px;
|
|
4791
|
+
box-sizing: border-box;
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
.group-header { display: flex; align-items: center; margin-bottom: 18px; padding: 16px; background: rgba(255,255,255,0.4); border: 1px solid rgba(255,255,255,0.5); border-radius: 16px; }
|
|
4795
|
+
.group-avatar { width: 60px; height: 60px; border-radius: 50%; margin-right: 14px; border: 3px solid rgba(255,255,255,0.6); }
|
|
4796
|
+
.group-info { flex: 1; }
|
|
4797
|
+
.group-name { font-size: 22px; font-weight: 800; color: #111; margin-bottom: 4px; text-shadow: 0 1px 2px rgba(255,255,255,0.8); }
|
|
4798
|
+
.group-details { font-size: 15px; color: #444; line-height: 1.3; font-weight: 600; text-shadow: 0 1px 2px rgba(255,255,255,0.7); }
|
|
4799
|
+
|
|
4800
|
+
.title { font-size: 32px; font-weight: 800; margin-bottom: 8px; color: #111; text-align: center; text-shadow: 0 2px 4px rgba(255,255,255,0.8); }
|
|
4801
|
+
.subtitle { font-size: 15px; color: #555; text-align: center; margin-bottom: 18px; font-weight: 600; }
|
|
4802
|
+
|
|
4803
|
+
.sender-section { display: flex; align-items: center; padding: 14px; background: rgba(255,255,255,0.5); border: 1px solid rgba(255,255,255,0.4); border-radius: 14px; margin-bottom: 14px; }
|
|
4804
|
+
.sender-avatar { width: 65px; height: 65px; border-radius: 50%; margin-right: 14px; border: 2px solid rgba(255,255,255,0.6); }
|
|
4805
|
+
.sender-info { flex: 1; }
|
|
4806
|
+
.sender-label { font-size: 14px; color: #555; margin-bottom: 4px; font-weight: 600; }
|
|
4807
|
+
.sender-id { font-size: 18px; font-weight: 800; color: #111; margin-bottom: 4px; }
|
|
4808
|
+
.publish-time { font-size: 13px; color: #444; font-weight: 600; }
|
|
4809
|
+
|
|
4810
|
+
.content-section { background: rgba(255,255,255,0.5); border: 1px solid rgba(255,255,255,0.4); border-radius: 14px; padding: 18px; margin-bottom: 14px; }
|
|
4811
|
+
.content-title { font-size: 13px; color: #555; margin-bottom: 10px; font-weight: 700; }
|
|
4812
|
+
.content-body { font-size: 16px; color: #212121; line-height: 1.7; word-break: break-all; white-space: pre-wrap; font-weight: 500; }
|
|
4813
|
+
|
|
4814
|
+
.notice-images-section { background: rgba(255,255,255,0.5); border: 1px solid rgba(255,255,255,0.4); border-radius: 14px; padding: 18px; margin-bottom: 14px; }
|
|
4815
|
+
.images-title { font-size: 13px; color: #555; margin-bottom: 12px; font-weight: 700; }
|
|
4816
|
+
.images-container { display: flex; flex-wrap: wrap; gap: 10px; }
|
|
4817
|
+
.notice-image-item { }
|
|
4818
|
+
.notice-image-large { max-width: 200px; max-height: 200px; border-radius: 8px; border: 1px solid rgba(0,0,0,0.1); object-fit: cover; }
|
|
4819
|
+
.image-error { color: #999; font-style: italic; font-size: 12px; }
|
|
4820
|
+
|
|
4821
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(128, 128, 128, 0.6); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
4822
|
+
|
|
4823
|
+
body.dark { color: #e0e0e0; }
|
|
4824
|
+
body.dark .card { background: rgba(20,20,20,0.4); box-shadow: 0 20px 60px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.1), inset 0 1px 0 rgba(255,255,255,0.15); }
|
|
4825
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(255,255,255,0.15); }
|
|
4826
|
+
body.dark .group-name { color: #ffffff; }
|
|
4827
|
+
body.dark .group-details { color: #b0b0b0; }
|
|
4828
|
+
body.dark .title { color: #ffffff; text-shadow: 0 2px 4px rgba(0,0,0,0.4); }
|
|
4829
|
+
body.dark .subtitle { color: #aaa; }
|
|
4830
|
+
body.dark .sender-section { background: rgba(40,40,40,0.5); border-color: rgba(255,255,255,0.1); }
|
|
4831
|
+
body.dark .sender-label { color: #aaa; }
|
|
4832
|
+
body.dark .sender-id { color: #ffffff; }
|
|
4833
|
+
body.dark .publish-time { color: #b0b0b0; }
|
|
4834
|
+
body.dark .content-section { background: rgba(40,40,40,0.5); border-color: rgba(255,255,255,0.1); }
|
|
4835
|
+
body.dark .content-title { color: #aaa; }
|
|
4836
|
+
body.dark .content-body { color: #e0e0e0; }
|
|
4837
|
+
body.dark .notice-images-section { background: rgba(40,40,40,0.5); border-color: rgba(255,255,255,0.1); }
|
|
4838
|
+
body.dark .images-title { color: #aaa; }
|
|
4839
|
+
body.dark .notice-image-large { border-color: rgba(255,255,255,0.2); }
|
|
4840
|
+
body.dark .timestamp-watermark { color: rgba(160, 160, 160, 0.5); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
4841
|
+
</style>
|
|
4842
|
+
</head>
|
|
4843
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
4844
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
4845
|
+
<div class="card">
|
|
4846
|
+
<div class="group-header">
|
|
4847
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
4848
|
+
<div class="group-info">
|
|
4849
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
4850
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
4851
|
+
</div>
|
|
4852
|
+
</div>
|
|
4853
|
+
<div class="title">📢 群公告详情</div>
|
|
4854
|
+
<div class="subtitle">第 ${contextInfo.noticeIndex}/${contextInfo.totalNoticeCount} 条公告</div>
|
|
4855
|
+
<div class="sender-section">
|
|
4856
|
+
<img class="sender-avatar" src="${senderAvatarUrl}" alt="发布者头像" />
|
|
4857
|
+
<div class="sender-info">
|
|
4858
|
+
<div class="sender-label">发布者</div>
|
|
4859
|
+
<div class="sender-id">QQ: ${record.sender_id}</div>
|
|
4860
|
+
<div class="publish-time">⏰ ${timeStr}</div>
|
|
4861
|
+
</div>
|
|
4862
|
+
</div>
|
|
4863
|
+
<div class="content-section">
|
|
4864
|
+
<div class="content-title">💬 公告内容</div>
|
|
4865
|
+
<div class="content-body">${contentHtml}</div>
|
|
4866
|
+
</div>
|
|
4867
|
+
${imagesHtml}
|
|
4868
|
+
</div>
|
|
4869
|
+
</body>
|
|
4870
|
+
</html>`;
|
|
4871
|
+
}, "getSourceHanSerifSCStyleDetailHtmlStr");
|
|
4872
|
+
var getLXGWWenKaiStyleDetailHtmlStr2 = /* @__PURE__ */ __name(async (record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
4873
|
+
const timestamp = generateTimestamp();
|
|
4874
|
+
const contentHtml = parseNoticeContentToHtmlFull(record.message.text);
|
|
4875
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
4876
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
4877
|
+
const imageCount = record.message.images?.length || 0;
|
|
4878
|
+
const backgroundStyle = groupAvatarBase64 ? `background-image: linear-gradient(45deg, rgba(245,240,230,0.85), rgba(250,245,235,0.85)), url(data:image/jpeg;base64,${groupAvatarBase64}); background-size: cover; background-position: center center; background-repeat: no-repeat;` : `background: linear-gradient(45deg, #f5f0e6, #faf5eb);`;
|
|
4879
|
+
let imagesHtml = "";
|
|
4880
|
+
if (record.message.images && record.message.images.length > 0) {
|
|
4881
|
+
const imageItems = record.message.images.map((img) => {
|
|
4882
|
+
const imgUrl = getNoticeImageUrl2(img.id);
|
|
4883
|
+
return `<div class="notice-image-item"><img class="notice-image-large" src="${imgUrl}" alt="公告图片" onerror="this.parentElement.innerHTML='<span class=\\'image-error\\'>[图片加载失败]</span>';" /></div>`;
|
|
4884
|
+
}).join("");
|
|
4885
|
+
imagesHtml = `<div class="notice-images-section"><div class="images-title">🖼️ 公告图片 (${imageCount}张)</div><div class="images-container">${imageItems}</div></div>`;
|
|
4886
|
+
}
|
|
4887
|
+
return `<!DOCTYPE html>
|
|
4888
|
+
<html>
|
|
4889
|
+
<head>
|
|
4890
|
+
<style>
|
|
4891
|
+
${fontBase64 ? `@font-face { font-family: 'LXGWWenKai'; src: url('data:font/truetype;charset=utf-8;base64,${fontBase64}') format('truetype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
4892
|
+
|
|
4893
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; min-height: 100vh; }
|
|
4894
|
+
body {
|
|
4895
|
+
font-family: ${fontBase64 ? "'LXGWWenKai'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
4896
|
+
width: 850px;
|
|
4897
|
+
height: auto;
|
|
4898
|
+
min-height: 100vh;
|
|
4899
|
+
display: flex;
|
|
4900
|
+
align-items: center;
|
|
4901
|
+
justify-content: center;
|
|
4902
|
+
${backgroundStyle}
|
|
4903
|
+
position: relative;
|
|
4904
|
+
box-sizing: border-box;
|
|
4905
|
+
overflow: visible;
|
|
4906
|
+
color: #3a2f2a;
|
|
4907
|
+
padding: 35px;
|
|
4908
|
+
}
|
|
4909
|
+
|
|
4910
|
+
body::before { content: ''; position: absolute; top: 16px; left: 16px; right: 16px; bottom: 16px; border: 3px solid #d4af37; border-radius: 20px; background: linear-gradient(135deg, rgba(212,175,55,0.12) 0%, rgba(184,134,11,0.06) 50%, rgba(212,175,55,0.12) 100%); box-shadow: inset 0 0 25px rgba(212,175,55,0.35), 0 0 35px rgba(212,175,55,0.25); z-index: 1; }
|
|
4911
|
+
body::after { content: '◆'; position: absolute; top: 30px; left: 30px; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
4912
|
+
|
|
4913
|
+
.corner-decoration { position: absolute; font-size: 26px; color: #d4af37; z-index: 2; text-shadow: 0 0 12px rgba(212,175,55,0.6); }
|
|
4914
|
+
.corner-decoration.top-right { top: 30px; right: 30px; }
|
|
4915
|
+
.corner-decoration.bottom-left { bottom: 30px; left: 30px; }
|
|
4916
|
+
.corner-decoration.bottom-right { bottom: 30px; right: 30px; }
|
|
4917
|
+
|
|
4918
|
+
.main-container {
|
|
4919
|
+
width: 720px;
|
|
4920
|
+
min-height: 400px;
|
|
4921
|
+
position: relative;
|
|
4922
|
+
z-index: 3;
|
|
4923
|
+
display: flex;
|
|
4924
|
+
flex-direction: column;
|
|
4925
|
+
padding: 32px 28px;
|
|
4926
|
+
box-sizing: border-box;
|
|
4927
|
+
}
|
|
4928
|
+
|
|
4929
|
+
.group-header { display: flex; align-items: center; margin-bottom: 18px; padding: 16px; background: rgba(255,255,255,0.2); border: 1px solid rgba(212,175,55,0.4); border-radius: 16px; box-shadow: 0 4px 16px rgba(212,175,55,0.15); }
|
|
4930
|
+
.group-avatar { width: 60px; height: 60px; border-radius: 9%; margin-right: 14px; border: 3px solid #d4af37; box-shadow: 0 4px 12px rgba(212,175,55,0.3); }
|
|
4931
|
+
.group-info { flex: 1; }
|
|
4932
|
+
.group-name { font-size: 22px; font-weight: 800; color: #5d2e0c; margin-bottom: 4px; text-shadow: 1px 1px 2px rgba(139,69,19,0.3); }
|
|
4933
|
+
.group-details { font-size: 16px; color: #6b3a1a; line-height: 1.3; font-weight: 700; text-shadow: 1px 1px 2px rgba(139,69,19,0.2); }
|
|
4934
|
+
|
|
4935
|
+
.title-section { text-align: center; margin-bottom: 8px; }
|
|
4936
|
+
.main-title { font-size: 40px; font-weight: 800; color: #5d2e0c; margin-bottom: 6px; text-shadow: 2px 2px 4px rgba(139,69,19,0.4); letter-spacing: 2px; }
|
|
4937
|
+
.subtitle { font-size: 16px; color: #6b3a1a; text-align: center; margin-bottom: 18px; font-weight: 700; }
|
|
4938
|
+
|
|
4939
|
+
.sender-section { display: flex; align-items: center; padding: 14px; background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 14px; margin-bottom: 14px; box-shadow: 0 3px 10px rgba(0,0,0,0.08); backdrop-filter: blur(5px); }
|
|
4940
|
+
.sender-avatar { width: 65px; height: 65px; border-radius: 50%; margin-right: 14px; border: 2px solid #d4af37; box-shadow: 0 2px 6px rgba(212,175,55,0.2); }
|
|
4941
|
+
.sender-info { flex: 1; }
|
|
4942
|
+
.sender-label { font-size: 14px; color: #6b3a1a; font-weight: 700; margin-bottom: 4px; }
|
|
4943
|
+
.sender-id { font-size: 18px; font-weight: 800; color: #2a1f1a; margin-bottom: 4px; }
|
|
4944
|
+
.publish-time { font-size: 13px; color: #6b3a1a; font-weight: 600; }
|
|
4945
|
+
|
|
4946
|
+
.content-section { background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 14px; padding: 18px; margin-bottom: 14px; box-shadow: 0 3px 10px rgba(0,0,0,0.08); backdrop-filter: blur(5px); }
|
|
4947
|
+
.content-title { font-size: 14px; color: #6b3a1a; margin-bottom: 10px; font-weight: 700; }
|
|
4948
|
+
.content-body { font-size: 16px; color: #2a1f1a; line-height: 1.7; word-break: break-all; white-space: pre-wrap; font-weight: 600; }
|
|
4949
|
+
|
|
4950
|
+
.notice-images-section { background: rgba(255,255,255,0.25); border: 1px solid rgba(212,175,55,0.4); border-radius: 14px; padding: 18px; margin-bottom: 14px; box-shadow: 0 3px 10px rgba(0,0,0,0.08); backdrop-filter: blur(5px); }
|
|
4951
|
+
.images-title { font-size: 14px; color: #6b3a1a; margin-bottom: 12px; font-weight: 700; }
|
|
4952
|
+
.images-container { display: flex; flex-wrap: wrap; gap: 10px; }
|
|
4953
|
+
.notice-image-item { }
|
|
4954
|
+
.notice-image-large { max-width: 200px; max-height: 200px; border-radius: 8px; border: 1px solid rgba(212,175,55,0.3); object-fit: cover; }
|
|
4955
|
+
.image-error { color: #8b7355; font-style: italic; font-size: 12px; }
|
|
4956
|
+
|
|
4957
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 13px; color: rgba(139, 69, 19, 0.4); font-family: 'Courier New', monospace; z-index: 9999; pointer-events: none; text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); }
|
|
4958
|
+
|
|
4959
|
+
body.dark { background: linear-gradient(45deg, #2c2416, #3a2f1f); color: #e6d7c3; }
|
|
4960
|
+
body.dark::before { border-color: #b8860b; background: linear-gradient(135deg, rgba(184,134,11,0.18) 0%, rgba(139,69,19,0.12) 50%, rgba(184,134,11,0.18) 100%); box-shadow: inset 0 0 25px rgba(184,134,11,0.45), 0 0 35px rgba(184,134,11,0.35); }
|
|
4961
|
+
body.dark::after { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
4962
|
+
body.dark .corner-decoration { color: #b8860b; text-shadow: 0 0 12px rgba(184,134,11,0.6); }
|
|
4963
|
+
body.dark .group-header { background: rgba(0,0,0,0.3); border-color: rgba(184,134,11,0.5); }
|
|
4964
|
+
body.dark .group-name { color: #daa520; text-shadow: 1px 1px 2px rgba(218,165,32,0.3); }
|
|
4965
|
+
body.dark .group-details { color: #cd853f; }
|
|
4966
|
+
body.dark .main-title { color: #daa520; text-shadow: 2px 2px 4px rgba(218,165,32,0.4); }
|
|
4967
|
+
body.dark .subtitle { color: #cd853f; }
|
|
4968
|
+
body.dark .sender-section { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
4969
|
+
body.dark .sender-label { color: #cd853f; }
|
|
4970
|
+
body.dark .sender-id { color: #e6d7c3; }
|
|
4971
|
+
body.dark .publish-time { color: #cd853f; }
|
|
4972
|
+
body.dark .content-section { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
4973
|
+
body.dark .content-title { color: #cd853f; }
|
|
4974
|
+
body.dark .content-body { color: #e6d7c3; }
|
|
4975
|
+
body.dark .notice-images-section { background: rgba(0,0,0,0.35); border-color: rgba(184,134,11,0.5); }
|
|
4976
|
+
body.dark .images-title { color: #cd853f; }
|
|
4977
|
+
body.dark .notice-image-large { border-color: rgba(184,134,11,0.4); }
|
|
4978
|
+
body.dark .timestamp-watermark { color: rgba(218, 165, 32, 0.4); text-shadow: 0 0 2px rgba(0, 0, 0, 0.8); }
|
|
4979
|
+
</style>
|
|
4980
|
+
</head>
|
|
4981
|
+
<body class="${enableDarkMode ? "dark" : ""}">
|
|
4982
|
+
<div class="corner-decoration top-right">◆</div>
|
|
4983
|
+
<div class="corner-decoration bottom-left">◆</div>
|
|
4984
|
+
<div class="corner-decoration bottom-right">◆</div>
|
|
4985
|
+
<div class="main-container">
|
|
4986
|
+
<div class="group-header">
|
|
4987
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
4988
|
+
<div class="group-info">
|
|
4989
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
4990
|
+
<div class="group-details">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
4991
|
+
</div>
|
|
4992
|
+
</div>
|
|
4993
|
+
<div class="title-section">
|
|
4994
|
+
<div class="main-title">「 群公告详情 」</div>
|
|
4995
|
+
</div>
|
|
4996
|
+
<div class="subtitle">第 ${contextInfo.noticeIndex}/${contextInfo.totalNoticeCount} 条公告</div>
|
|
4997
|
+
<div class="sender-section">
|
|
4998
|
+
<img class="sender-avatar" src="${senderAvatarUrl}" alt="发布者头像" />
|
|
4999
|
+
<div class="sender-info">
|
|
5000
|
+
<div class="sender-label">发布者</div>
|
|
5001
|
+
<div class="sender-id">QQ: ${record.sender_id}</div>
|
|
5002
|
+
<div class="publish-time">⏰ ${timeStr}</div>
|
|
5003
|
+
</div>
|
|
5004
|
+
</div>
|
|
5005
|
+
<div class="content-section">
|
|
5006
|
+
<div class="content-title">💬 公告内容</div>
|
|
5007
|
+
<div class="content-body">${contentHtml}</div>
|
|
5008
|
+
</div>
|
|
5009
|
+
${imagesHtml}
|
|
5010
|
+
</div>
|
|
5011
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
5012
|
+
</body>
|
|
5013
|
+
</html>`;
|
|
5014
|
+
}, "getLXGWWenKaiStyleDetailHtmlStr");
|
|
5015
|
+
var getFlatMinimalStyleDetailHtmlStr2 = /* @__PURE__ */ __name(async (record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode) => {
|
|
5016
|
+
const timestamp = generateTimestamp();
|
|
5017
|
+
const contentHtml = parseNoticeContentToHtmlFull(record.message.text);
|
|
5018
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
5019
|
+
const senderAvatarUrl = `https://q1.qlogo.cn/g?b=qq&nk=${record.sender_id}&s=640`;
|
|
5020
|
+
const imageCount = record.message.images?.length || 0;
|
|
5021
|
+
const colors = enableDarkMode ? {
|
|
5022
|
+
background: "#000000",
|
|
5023
|
+
cardBackground: "#1a1a1a",
|
|
5024
|
+
textPrimary: "#ffffff",
|
|
5025
|
+
textSecondary: "#b0b0b0",
|
|
5026
|
+
primary: "#00d4ff",
|
|
5027
|
+
border: "#333333"
|
|
5028
|
+
} : {
|
|
5029
|
+
background: "#f5f7fa",
|
|
5030
|
+
cardBackground: "#ffffff",
|
|
5031
|
+
textPrimary: "#2c3e50",
|
|
5032
|
+
textSecondary: "#6c757d",
|
|
5033
|
+
primary: "#007bff",
|
|
5034
|
+
border: "#dee2e6"
|
|
5035
|
+
};
|
|
5036
|
+
let imagesHtml = "";
|
|
5037
|
+
if (record.message.images && record.message.images.length > 0) {
|
|
5038
|
+
const imageItems = record.message.images.map((img) => {
|
|
5039
|
+
const imgUrl = getNoticeImageUrl2(img.id);
|
|
5040
|
+
return `<img class="notice-image-large" src="${imgUrl}" alt="公告图片" onerror="this.style.display='none';" />`;
|
|
5041
|
+
}).join("");
|
|
5042
|
+
imagesHtml = `<div class="notice-images-section"><div class="images-title">🖼️ 公告图片 (${imageCount}张)</div><div class="images-container">${imageItems}</div></div>`;
|
|
5043
|
+
}
|
|
5044
|
+
return `<!DOCTYPE html>
|
|
5045
|
+
<html>
|
|
5046
|
+
<head>
|
|
5047
|
+
<style>
|
|
5048
|
+
${fontBase64 ? `@font-face { font-family: 'CustomFont'; src: url('data:font/opentype;charset=utf-8;base64,${fontBase64}') format('opentype'); font-weight: normal; font-style: normal; font-display: swap; }` : ""}
|
|
5049
|
+
|
|
5050
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
5051
|
+
html, body { margin: 0; padding: 0; width: 100%; height: auto; }
|
|
5052
|
+
|
|
5053
|
+
body {
|
|
5054
|
+
font-family: ${fontBase64 ? "'CustomFont'," : ""} -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", sans-serif;
|
|
5055
|
+
width: 850px;
|
|
5056
|
+
min-height: 100vh;
|
|
5057
|
+
background: ${colors.background};
|
|
5058
|
+
color: ${colors.textPrimary};
|
|
5059
|
+
padding: 40px;
|
|
5060
|
+
display: flex;
|
|
5061
|
+
align-items: center;
|
|
5062
|
+
justify-content: center;
|
|
5063
|
+
}
|
|
5064
|
+
|
|
5065
|
+
.container { width: 100%; max-width: 720px; }
|
|
5066
|
+
|
|
5067
|
+
.header {
|
|
5068
|
+
background: ${colors.cardBackground};
|
|
5069
|
+
border: 2px solid ${colors.border};
|
|
5070
|
+
border-radius: 20px;
|
|
5071
|
+
padding: 32px;
|
|
5072
|
+
margin-bottom: 24px;
|
|
5073
|
+
box-shadow: 0 4px 16px rgba(0,0,0,${enableDarkMode ? "0.3" : "0.08"});
|
|
5074
|
+
}
|
|
5075
|
+
|
|
5076
|
+
.group-info-wrapper { display: flex; align-items: center; gap: 24px; margin-bottom: 24px; }
|
|
5077
|
+
.group-avatar { width: 80px; height: 80px; border-radius: 16px; object-fit: cover; border: 3px solid ${colors.primary}; }
|
|
5078
|
+
.group-details { flex: 1; }
|
|
5079
|
+
.group-name { font-size: 24px; font-weight: 800; color: ${colors.textPrimary}; margin-bottom: 8px; }
|
|
5080
|
+
.group-meta { font-size: 15px; color: ${colors.textSecondary}; font-weight: 600; }
|
|
5081
|
+
|
|
5082
|
+
.title { font-size: 32px; font-weight: 800; color: ${colors.primary}; text-align: center; margin-bottom: 8px; }
|
|
5083
|
+
.subtitle { font-size: 15px; color: ${colors.textSecondary}; text-align: center; font-weight: 600; }
|
|
5084
|
+
|
|
5085
|
+
.sender-section {
|
|
5086
|
+
background: ${colors.cardBackground};
|
|
5087
|
+
border: 2px solid ${colors.border};
|
|
5088
|
+
border-radius: 16px;
|
|
5089
|
+
padding: 20px;
|
|
5090
|
+
margin-bottom: 16px;
|
|
5091
|
+
display: flex;
|
|
5092
|
+
align-items: center;
|
|
5093
|
+
gap: 16px;
|
|
1942
5094
|
}
|
|
5095
|
+
.sender-avatar { width: 60px; height: 60px; border-radius: 50%; border: 2px solid ${colors.border}; }
|
|
5096
|
+
.sender-info { flex: 1; }
|
|
5097
|
+
.sender-label { font-size: 13px; color: ${colors.textSecondary}; margin-bottom: 4px; font-weight: 600; }
|
|
5098
|
+
.sender-id { font-size: 18px; font-weight: 800; color: ${colors.textPrimary}; margin-bottom: 4px; }
|
|
5099
|
+
.publish-time { font-size: 13px; color: ${colors.textSecondary}; font-weight: 600; }
|
|
5100
|
+
|
|
5101
|
+
.content-section {
|
|
5102
|
+
background: ${colors.cardBackground};
|
|
5103
|
+
border: 2px solid ${colors.border};
|
|
5104
|
+
border-radius: 16px;
|
|
5105
|
+
padding: 24px;
|
|
5106
|
+
margin-bottom: 16px;
|
|
5107
|
+
}
|
|
5108
|
+
.content-title { font-size: 14px; color: ${colors.textSecondary}; margin-bottom: 12px; font-weight: 700; }
|
|
5109
|
+
.content-body { font-size: 16px; color: ${colors.textPrimary}; line-height: 1.8; word-break: break-all; white-space: pre-wrap; font-weight: 500; }
|
|
5110
|
+
|
|
5111
|
+
.notice-images-section {
|
|
5112
|
+
background: ${colors.cardBackground};
|
|
5113
|
+
border: 2px solid ${colors.border};
|
|
5114
|
+
border-radius: 16px;
|
|
5115
|
+
padding: 24px;
|
|
5116
|
+
margin-bottom: 16px;
|
|
5117
|
+
}
|
|
5118
|
+
.images-title { font-size: 14px; color: ${colors.textSecondary}; margin-bottom: 12px; font-weight: 700; }
|
|
5119
|
+
.images-container { display: flex; flex-wrap: wrap; gap: 12px; }
|
|
5120
|
+
.notice-image-large { max-width: 180px; max-height: 180px; border-radius: 12px; border: 1px solid ${colors.border}; object-fit: cover; }
|
|
5121
|
+
|
|
5122
|
+
.timestamp-watermark { position: fixed; top: 1.3px; left: 1.3px; font-size: 12px; color: ${enableDarkMode ? "rgba(160,160,160,0.4)" : "rgba(100,100,100,0.4)"}; font-family: 'Courier New', monospace; z-index: 9999; }
|
|
5123
|
+
</style>
|
|
5124
|
+
</head>
|
|
5125
|
+
<body>
|
|
5126
|
+
<div class="timestamp-watermark">${timestamp}</div>
|
|
5127
|
+
<div class="container">
|
|
5128
|
+
<div class="header">
|
|
5129
|
+
<div class="group-info-wrapper">
|
|
5130
|
+
<img class="group-avatar" src="data:image/jpeg;base64,${groupAvatarBase64}" alt="群头像" />
|
|
5131
|
+
<div class="group-details">
|
|
5132
|
+
<div class="group-name">${contextInfo.groupName}</div>
|
|
5133
|
+
<div class="group-meta">群号: ${contextInfo.groupId} | 成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}</div>
|
|
5134
|
+
</div>
|
|
5135
|
+
</div>
|
|
5136
|
+
<div class="title">📢 群公告详情</div>
|
|
5137
|
+
<div class="subtitle">第 ${contextInfo.noticeIndex}/${contextInfo.totalNoticeCount} 条公告</div>
|
|
5138
|
+
</div>
|
|
5139
|
+
<div class="sender-section">
|
|
5140
|
+
<img class="sender-avatar" src="${senderAvatarUrl}" alt="发布者头像" />
|
|
5141
|
+
<div class="sender-info">
|
|
5142
|
+
<div class="sender-label">发布者</div>
|
|
5143
|
+
<div class="sender-id">QQ: ${record.sender_id}</div>
|
|
5144
|
+
<div class="publish-time">⏰ ${timeStr}</div>
|
|
5145
|
+
</div>
|
|
5146
|
+
</div>
|
|
5147
|
+
<div class="content-section">
|
|
5148
|
+
<div class="content-title">💬 公告内容</div>
|
|
5149
|
+
<div class="content-body">${contentHtml}</div>
|
|
5150
|
+
</div>
|
|
5151
|
+
${imagesHtml}
|
|
5152
|
+
</div>
|
|
5153
|
+
</body>
|
|
5154
|
+
</html>`;
|
|
5155
|
+
}, "getFlatMinimalStyleDetailHtmlStr");
|
|
5156
|
+
async function renderGroupNoticeDetail(ctx, record, contextInfo, imageStyle, enableDarkMode, imageType, screenshotQuality) {
|
|
5157
|
+
const groupAvatarBase64 = await getGroupAvatarBase64(ctx, contextInfo.groupId.toString());
|
|
5158
|
+
const fontBase64 = await getFontBase64(ctx, imageStyle);
|
|
5159
|
+
let htmlStr;
|
|
5160
|
+
switch (imageStyle) {
|
|
5161
|
+
case IMAGE_STYLES.SOURCE_HAN_SERIF_SC:
|
|
5162
|
+
htmlStr = await getSourceHanSerifSCStyleDetailHtmlStr2(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
5163
|
+
break;
|
|
5164
|
+
case IMAGE_STYLES.LXGW_WENKAI:
|
|
5165
|
+
htmlStr = await getLXGWWenKaiStyleDetailHtmlStr2(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
5166
|
+
break;
|
|
5167
|
+
case IMAGE_STYLES.FLAT_MINIMAL:
|
|
5168
|
+
htmlStr = await getFlatMinimalStyleDetailHtmlStr2(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
5169
|
+
break;
|
|
5170
|
+
default:
|
|
5171
|
+
htmlStr = await getSourceHanSerifSCStyleDetailHtmlStr2(record, contextInfo, groupAvatarBase64, fontBase64, enableDarkMode);
|
|
1943
5172
|
}
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
5173
|
+
const page = await ctx.puppeteer.page();
|
|
5174
|
+
await page.setContent(htmlStr, {
|
|
5175
|
+
waitUntil: "domcontentloaded",
|
|
5176
|
+
timeout: 15e3
|
|
5177
|
+
});
|
|
5178
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
5179
|
+
const bodyHandle = await page.$("body");
|
|
5180
|
+
const boundingBox = await bodyHandle.boundingBox();
|
|
5181
|
+
const contentHeight = Math.ceil(boundingBox.height);
|
|
5182
|
+
const contentWidth = Math.ceil(boundingBox.width);
|
|
5183
|
+
await page.setViewport({
|
|
5184
|
+
width: contentWidth,
|
|
5185
|
+
height: contentHeight,
|
|
5186
|
+
deviceScaleFactor: 2
|
|
5187
|
+
});
|
|
5188
|
+
const screenshotOptions = {
|
|
5189
|
+
fullPage: true,
|
|
5190
|
+
type: imageType,
|
|
5191
|
+
encoding: "base64"
|
|
5192
|
+
};
|
|
5193
|
+
if (imageType !== "png") {
|
|
5194
|
+
screenshotOptions.quality = screenshotQuality;
|
|
5195
|
+
}
|
|
5196
|
+
const screenshot = await page.screenshot(screenshotOptions);
|
|
5197
|
+
await page.close();
|
|
5198
|
+
return screenshot;
|
|
5199
|
+
}
|
|
5200
|
+
__name(renderGroupNoticeDetail, "renderGroupNoticeDetail");
|
|
5201
|
+
|
|
5202
|
+
// src/commandGroupNoticeDetail.ts
|
|
5203
|
+
function formatGroupNoticeDetailAsText(record, contextInfo, config) {
|
|
5204
|
+
const textContent = parseNoticeText(record.message.text);
|
|
5205
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
5206
|
+
const imageCount = record.message.images?.length || 0;
|
|
5207
|
+
let output = `📢 群公告详情
|
|
5208
|
+
`;
|
|
5209
|
+
output += `==================
|
|
5210
|
+
`;
|
|
5211
|
+
output += `📍 群聊: ${contextInfo.groupName} (${contextInfo.groupId})
|
|
5212
|
+
`;
|
|
5213
|
+
output += `📊 第 ${contextInfo.noticeIndex}/${contextInfo.totalNoticeCount} 条公告
|
|
5214
|
+
`;
|
|
5215
|
+
output += `------------------
|
|
5216
|
+
`;
|
|
5217
|
+
output += `👤 发布者QQ: ${record.sender_id}
|
|
5218
|
+
`;
|
|
5219
|
+
output += `⏰ 发布时间: ${timeStr}
|
|
5220
|
+
`;
|
|
5221
|
+
output += `------------------
|
|
5222
|
+
`;
|
|
5223
|
+
output += `💬 公告内容:
|
|
5224
|
+
${textContent}
|
|
5225
|
+
`;
|
|
5226
|
+
if (imageCount > 0) {
|
|
5227
|
+
output += `------------------
|
|
5228
|
+
`;
|
|
5229
|
+
output += `🖼️ 包含 ${imageCount} 张图片
|
|
5230
|
+
`;
|
|
5231
|
+
}
|
|
5232
|
+
output += `==================
|
|
5233
|
+
`;
|
|
5234
|
+
output += `📖 用法: ${config.groupNoticeDetailCommandName} <序号>
|
|
5235
|
+
`;
|
|
5236
|
+
output += `📝 示例: ${config.groupNoticeDetailCommandName} 2 查看第2条公告详情
|
|
5237
|
+
`;
|
|
5238
|
+
return output;
|
|
5239
|
+
}
|
|
5240
|
+
__name(formatGroupNoticeDetailAsText, "formatGroupNoticeDetailAsText");
|
|
5241
|
+
function formatGroupNoticeDetailAsForward(record, contextInfo, config) {
|
|
5242
|
+
const textContent = parseNoticeText(record.message.text);
|
|
5243
|
+
const timeStr = formatTimestamp2(record.publish_time);
|
|
5244
|
+
const imageCount = record.message.images?.length || 0;
|
|
5245
|
+
let messages = "";
|
|
5246
|
+
const addMessageBlock = /* @__PURE__ */ __name((userId, nickname, content) => {
|
|
5247
|
+
if (userId) {
|
|
5248
|
+
messages += `<message user-id="${userId}" nickname="${nickname}">${content}</message>
|
|
5249
|
+
`;
|
|
5250
|
+
} else {
|
|
5251
|
+
messages += `<message nickname="${nickname}">${content}</message>
|
|
5252
|
+
`;
|
|
1954
5253
|
}
|
|
5254
|
+
}, "addMessageBlock");
|
|
5255
|
+
addMessageBlock(void 0, "📢 群公告详情", `第 ${contextInfo.noticeIndex}/${contextInfo.totalNoticeCount} 条公告`);
|
|
5256
|
+
addMessageBlock(void 0, "📍 群聊信息", `${contextInfo.groupName}
|
|
5257
|
+
群号: ${contextInfo.groupId}
|
|
5258
|
+
成员: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}`);
|
|
5259
|
+
addMessageBlock(String(record.sender_id), `发布者 ${record.sender_id}`, `发布者QQ: ${record.sender_id}
|
|
5260
|
+
发布时间: ${timeStr}`);
|
|
5261
|
+
addMessageBlock(String(record.sender_id), `发布者 ${record.sender_id}`, `💬 公告内容:
|
|
5262
|
+
${textContent}`);
|
|
5263
|
+
if (imageCount > 0) {
|
|
5264
|
+
addMessageBlock(void 0, "🖼️ 图片信息", `包含 ${imageCount} 张图片`);
|
|
1955
5265
|
}
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
5266
|
+
const usageText = [
|
|
5267
|
+
`📖 用法: ${config.groupNoticeDetailCommandName} <序号>`,
|
|
5268
|
+
`📝 示例: ${config.groupNoticeDetailCommandName} 2 查看第2条公告详情`
|
|
5269
|
+
].join("\n");
|
|
5270
|
+
addMessageBlock(void 0, "使用帮助", usageText);
|
|
5271
|
+
return `<message forward>
|
|
5272
|
+
${messages}
|
|
5273
|
+
</message>`;
|
|
5274
|
+
}
|
|
5275
|
+
__name(formatGroupNoticeDetailAsForward, "formatGroupNoticeDetailAsForward");
|
|
5276
|
+
function registerGroupNoticeDetailCommand(ctx, config, responseHint) {
|
|
5277
|
+
if (!config.enableGroupNoticeCommand) return;
|
|
5278
|
+
ctx.command(`${config.groupNoticeDetailCommandName} <num:number>`, `获取指定序号的群公告详情, 发送${responseHint}`).alias("群公告详情").alias("agnd").option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }, num) => {
|
|
5279
|
+
if (!session.onebot)
|
|
5280
|
+
return session.send("[error]当前会话不支持onebot协议。");
|
|
5281
|
+
if (!session.guildId)
|
|
5282
|
+
return session.send("[error]当前会话不在群聊中。");
|
|
5283
|
+
if (num === void 0 || num === null || isNaN(num)) {
|
|
5284
|
+
return session.send(`[error]请输入要查看的公告序号。
|
|
5285
|
+
用法: ${config.groupNoticeDetailCommandName} <序号>
|
|
5286
|
+
示例: ${config.groupNoticeDetailCommandName} 2`);
|
|
5287
|
+
}
|
|
5288
|
+
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
5289
|
+
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
5290
|
+
if (options.imageStyleIdx !== void 0) {
|
|
5291
|
+
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
5292
|
+
if (!isIdxValid) {
|
|
5293
|
+
let idxInvalidMsgArr = [
|
|
5294
|
+
`图片样式索引不合法。`,
|
|
5295
|
+
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
5296
|
+
` 当前输入:${options.imageStyleIdx}`,
|
|
5297
|
+
`
|
|
5298
|
+
`,
|
|
5299
|
+
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
5300
|
+
];
|
|
5301
|
+
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
1963
5302
|
}
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
5303
|
+
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
5304
|
+
}
|
|
5305
|
+
try {
|
|
5306
|
+
const onebotBot = session.onebot;
|
|
5307
|
+
const groupNoticeList = await onebotBot.getGroupNotice(session.guildId);
|
|
5308
|
+
if (!groupNoticeList || groupNoticeList.length === 0) {
|
|
5309
|
+
return session.send("该群暂无公告。");
|
|
1970
5310
|
}
|
|
1971
|
-
const
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
try {
|
|
1977
|
-
const response = await this.ctx.http.get(avatarUrl, { responseType: "arraybuffer" });
|
|
1978
|
-
avatarBase64 = Buffer.from(response).toString("base64");
|
|
1979
|
-
} catch (e) {
|
|
1980
|
-
this.ctx.logger("onebot-info-image").warn("获取头像失败:", e);
|
|
5311
|
+
const index = Math.floor(num);
|
|
5312
|
+
if (index < 1 || index > groupNoticeList.length) {
|
|
5313
|
+
return session.send(`[error]序号超出范围。
|
|
5314
|
+
有效范围: 1 - ${groupNoticeList.length}
|
|
5315
|
+
当前输入: ${index}`);
|
|
1981
5316
|
}
|
|
1982
|
-
const
|
|
1983
|
-
|
|
1984
|
-
nickname: loginInfo.nickname || strangerInfo.nickname,
|
|
1985
|
-
sex: strangerInfo.sex || "",
|
|
1986
|
-
age: strangerInfo.age || 0,
|
|
1987
|
-
sign: strangerInfo.sign,
|
|
1988
|
-
level: strangerInfo.level,
|
|
1989
|
-
login_days: strangerInfo.login_days,
|
|
1990
|
-
qid: strangerInfo.qid
|
|
1991
|
-
};
|
|
5317
|
+
const targetRecord = groupNoticeList[index - 1];
|
|
5318
|
+
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
1992
5319
|
const contextInfo = {
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
avatarBase64,
|
|
2001
|
-
"",
|
|
2002
|
-
fontBase64,
|
|
2003
|
-
this.currentDarkMode,
|
|
2004
|
-
// 使用当前选择的主题模式
|
|
2005
|
-
true
|
|
2006
|
-
// hidePhoneNumber: 预览中默认隐藏手机号
|
|
2007
|
-
);
|
|
2008
|
-
return {
|
|
2009
|
-
status: "loaded",
|
|
2010
|
-
msg: "加载成功",
|
|
2011
|
-
htmlContent,
|
|
2012
|
-
currentTemplate: this.currentTemplate,
|
|
2013
|
-
currentFont: this.currentFont,
|
|
2014
|
-
currentDarkMode: this.currentDarkMode
|
|
2015
|
-
};
|
|
2016
|
-
} catch (e) {
|
|
2017
|
-
this.ctx.logger("onebot-info-image").error("获取 Bot 信息失败:", e);
|
|
2018
|
-
return {
|
|
2019
|
-
status: "error",
|
|
2020
|
-
msg: `获取失败: ${e.message || e}`
|
|
5320
|
+
groupId: parseInt(session.guildId),
|
|
5321
|
+
groupName: groupInfoObj.group_name || "未知群聊",
|
|
5322
|
+
memberCount: groupInfoObj.member_count || 0,
|
|
5323
|
+
maxMemberCount: groupInfoObj.max_member_count || 0,
|
|
5324
|
+
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`,
|
|
5325
|
+
noticeIndex: index,
|
|
5326
|
+
totalNoticeCount: groupNoticeList.length
|
|
2021
5327
|
};
|
|
5328
|
+
if (config.verboseConsoleOutput) {
|
|
5329
|
+
ctx.logger.info(`群公告详情: ${JSON.stringify(targetRecord)}`);
|
|
5330
|
+
}
|
|
5331
|
+
if (config.sendText) {
|
|
5332
|
+
const textMessage = formatGroupNoticeDetailAsText(targetRecord, contextInfo, config);
|
|
5333
|
+
await session.send(`${config.enableQuoteWithText ? import_koishi6.h.quote(session.messageId) : ""}${textMessage}`);
|
|
5334
|
+
}
|
|
5335
|
+
if (config.sendImage) {
|
|
5336
|
+
const waitTipMsgId = await session.send(`${import_koishi6.h.quote(session.messageId)}🔄正在渲染群公告详情图片,请稍候⏳...`);
|
|
5337
|
+
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
5338
|
+
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
5339
|
+
const noticeDetailImageBase64 = await renderGroupNoticeDetail(
|
|
5340
|
+
ctx,
|
|
5341
|
+
targetRecord,
|
|
5342
|
+
contextInfo,
|
|
5343
|
+
selectedImageStyle,
|
|
5344
|
+
selectedDarkMode,
|
|
5345
|
+
config.imageType,
|
|
5346
|
+
config.screenshotQuality
|
|
5347
|
+
);
|
|
5348
|
+
let imageMessage = `${config.enableQuoteWithImage ? import_koishi6.h.quote(session.messageId) : ""}${import_koishi6.h.image(`data:image/png;base64,${noticeDetailImageBase64}`)}`;
|
|
5349
|
+
imageMessage += `
|
|
5350
|
+
📢 第 ${index}/${groupNoticeList.length} 条公告 | 📖 ${config.groupNoticeDetailCommandName} <序号>`;
|
|
5351
|
+
await session.send(imageMessage);
|
|
5352
|
+
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
5353
|
+
}
|
|
5354
|
+
if (config.sendForward) {
|
|
5355
|
+
const forwardMessage = formatGroupNoticeDetailAsForward(targetRecord, contextInfo, config);
|
|
5356
|
+
await session.send(import_koishi6.h.unescape(forwardMessage));
|
|
5357
|
+
}
|
|
5358
|
+
} catch (error) {
|
|
5359
|
+
ctx.logger.error(`获取群公告详情失败: ${error}`);
|
|
5360
|
+
await session.send(`[error]获取群公告详情失败: ${error.message}`);
|
|
2022
5361
|
}
|
|
2023
|
-
}
|
|
2024
|
-
}
|
|
5362
|
+
});
|
|
5363
|
+
}
|
|
5364
|
+
__name(registerGroupNoticeDetailCommand, "registerGroupNoticeDetailCommand");
|
|
2025
5365
|
|
|
2026
5366
|
// src/index.ts
|
|
2027
5367
|
var name = "onebot-info-image";
|
|
@@ -2029,7 +5369,7 @@ var inject = {
|
|
|
2029
5369
|
required: ["puppeteer", "http"]
|
|
2030
5370
|
};
|
|
2031
5371
|
var pkg = JSON.parse(
|
|
2032
|
-
(0,
|
|
5372
|
+
(0, import_fs3.readFileSync)((0, import_path3.resolve)(__dirname, "../package.json"), "utf-8")
|
|
2033
5373
|
);
|
|
2034
5374
|
var usage = `
|
|
2035
5375
|
<h1>Koishi 插件:onebot-info-image 获取群员信息 渲染成图像</h1>
|
|
@@ -2064,33 +5404,41 @@ var usage = `
|
|
|
2064
5404
|
<p>如果你觉得插件好用,欢迎在 GitHub 上 ⭐ Star 或通过其他方式给予支持(例如提供服务器、API Key 或直接赞助)!</p>
|
|
2065
5405
|
<p style="color: #e91e63;">感谢所有开源字体与项目的贡献者 ❤️</p>
|
|
2066
5406
|
`;
|
|
2067
|
-
var Config =
|
|
2068
|
-
|
|
2069
|
-
onebotImplName:
|
|
2070
|
-
|
|
2071
|
-
|
|
5407
|
+
var Config = import_koishi7.Schema.intersect([
|
|
5408
|
+
import_koishi7.Schema.object({
|
|
5409
|
+
onebotImplName: import_koishi7.Schema.union([
|
|
5410
|
+
import_koishi7.Schema.const(ONEBOT_IMPL_NAME.LAGRNAGE).description("Lagrange"),
|
|
5411
|
+
import_koishi7.Schema.const(ONEBOT_IMPL_NAME.NAPCAT).description("NapCat")
|
|
2072
5412
|
// Schema.const(ONEBOT_IMPL_NAME.LLONEBOT).description('LLOneBot'),
|
|
2073
5413
|
]).role("radio").default(ONEBOT_IMPL_NAME.LAGRNAGE).description("【重要】OneBot 的具体实现名称(选错了会导致获取到的内容会变少)")
|
|
2074
5414
|
}).description("你的OneBot具体实现平台 是哪一个捏?"),
|
|
2075
|
-
|
|
2076
|
-
enableUserInfoCommand:
|
|
2077
|
-
userinfoCommandName:
|
|
2078
|
-
hidePhoneNumber:
|
|
2079
|
-
enableGroupAdminListCommand:
|
|
2080
|
-
groupAdminListCommandName:
|
|
2081
|
-
|
|
5415
|
+
import_koishi7.Schema.object({
|
|
5416
|
+
enableUserInfoCommand: import_koishi7.Schema.boolean().default(true).description("ℹ️ 是否启用用户信息命令。"),
|
|
5417
|
+
userinfoCommandName: import_koishi7.Schema.string().default("用户信息").description("🔍 用户信息命令名称。"),
|
|
5418
|
+
hidePhoneNumber: import_koishi7.Schema.boolean().default(true).experimental().description("📱 是否隐藏手机号。开启后手机号将显示为【已隐藏】。</br> <i> 保护隐私捏 </i>"),
|
|
5419
|
+
enableGroupAdminListCommand: import_koishi7.Schema.boolean().default(false).description("👥 是否启用群管理员列表命令。"),
|
|
5420
|
+
groupAdminListCommandName: import_koishi7.Schema.string().default("群管理列表").description("👥 群管理员列表命令名称。"),
|
|
5421
|
+
enableGroupEssenceCommand: import_koishi7.Schema.boolean().default(true).description("📌 是否启用群精华消息命令。"),
|
|
5422
|
+
groupEssenceCommandName: import_koishi7.Schema.string().default("群精华").description("📌 群精华消息列表命令名称。"),
|
|
5423
|
+
groupEssenceDetailCommandName: import_koishi7.Schema.string().default("群精华详情").description("🔍 群精华详情命令名称。"),
|
|
5424
|
+
groupEssencePageSize: import_koishi7.Schema.number().min(1).max(20).step(1).default(10).description("📌 群精华消息每页显示条数。"),
|
|
5425
|
+
enableGroupNoticeCommand: import_koishi7.Schema.boolean().default(true).description("📢 是否启用群公告命令。"),
|
|
5426
|
+
groupNoticeCommandName: import_koishi7.Schema.string().default("群公告").description("📢 群公告列表命令名称。"),
|
|
5427
|
+
groupNoticeDetailCommandName: import_koishi7.Schema.string().default("群公告详情").description("🔍 群公告详情命令名称。"),
|
|
5428
|
+
groupNoticePageSize: import_koishi7.Schema.number().min(1).max(20).step(1).default(10).description("📢 群公告每页显示条数。"),
|
|
5429
|
+
inspectStyleCommandName: import_koishi7.Schema.string().default("查看图片样式").description("🎨 查看图片样式列表命令名称。")
|
|
2082
5430
|
}).description("基础配置 ⚙️"),
|
|
2083
|
-
|
|
2084
|
-
sendText:
|
|
2085
|
-
enableQuoteWithText:
|
|
5431
|
+
import_koishi7.Schema.object({
|
|
5432
|
+
sendText: import_koishi7.Schema.boolean().default(false).description("💬 是否启用文本回复。"),
|
|
5433
|
+
enableQuoteWithText: import_koishi7.Schema.boolean().default(false).description("↩️ 回复文本的时候,是否带引用触发指令的消息。")
|
|
2086
5434
|
}).description("发送 文本 配置 📝"),
|
|
2087
|
-
|
|
2088
|
-
sendImage:
|
|
2089
|
-
enableQuoteWithImage:
|
|
2090
|
-
imageStyleDetails:
|
|
2091
|
-
|
|
2092
|
-
styleKey:
|
|
2093
|
-
darkMode:
|
|
5435
|
+
import_koishi7.Schema.object({
|
|
5436
|
+
sendImage: import_koishi7.Schema.boolean().default(true).description("🖼️ 是否启用 Puppeteer 渲染图片。"),
|
|
5437
|
+
enableQuoteWithImage: import_koishi7.Schema.boolean().default(false).description("📸 回复图片的时候,是否带引用触发指令的消息。"),
|
|
5438
|
+
imageStyleDetails: import_koishi7.Schema.array(
|
|
5439
|
+
import_koishi7.Schema.object({
|
|
5440
|
+
styleKey: import_koishi7.Schema.union(IMAGE_STYLE_KEY_ARR.map((key) => import_koishi7.Schema.const(key).description(IMAGE_STYLES[key]))).role("radio").description("🎨 图片样式"),
|
|
5441
|
+
darkMode: import_koishi7.Schema.boolean().description("🌙 启用深色模式")
|
|
2094
5442
|
})
|
|
2095
5443
|
).role("table").default([
|
|
2096
5444
|
{
|
|
@@ -2118,20 +5466,20 @@ var Config = import_koishi.Schema.intersect([
|
|
|
2118
5466
|
darkMode: true
|
|
2119
5467
|
}
|
|
2120
5468
|
]).description("� 图片样式配置。第一行是默认使用的样式,指定样式请使用 -i 参数"),
|
|
2121
|
-
imageType:
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
5469
|
+
imageType: import_koishi7.Schema.union([
|
|
5470
|
+
import_koishi7.Schema.const(IMAGE_TYPES.PNG).description(`🖼️ ${IMAGE_TYPES.PNG}, ❌ 不支持调整quality`),
|
|
5471
|
+
import_koishi7.Schema.const(IMAGE_TYPES.JPEG).description(`🌄 ${IMAGE_TYPES.JPEG}, ✅ 支持调整quality`),
|
|
5472
|
+
import_koishi7.Schema.const(IMAGE_TYPES.WEBP).description(`🌐 ${IMAGE_TYPES.WEBP}, ✅ 支持调整quality`)
|
|
2125
5473
|
]).role("radio").default(IMAGE_TYPES.PNG).description("📤 渲染图片的输出类型。"),
|
|
2126
|
-
screenshotQuality:
|
|
5474
|
+
screenshotQuality: import_koishi7.Schema.number().min(0).max(100).step(1).default(80).description("📏 Puppeteer 截图质量 (0-100)。")
|
|
2127
5475
|
}).description("发送 Puppeteer渲染的图片 配置 🎨"),
|
|
2128
|
-
|
|
2129
|
-
sendForward:
|
|
5476
|
+
import_koishi7.Schema.object({
|
|
5477
|
+
sendForward: import_koishi7.Schema.boolean().default(false).description("➡️ 是否启用转发消息。")
|
|
2130
5478
|
}).description("发送 onebot转发消息 配置 ✉️"),
|
|
2131
|
-
|
|
2132
|
-
verboseSessionOutput:
|
|
2133
|
-
verboseConsoleOutput:
|
|
2134
|
-
verboseFileOutput:
|
|
5479
|
+
import_koishi7.Schema.object({
|
|
5480
|
+
verboseSessionOutput: import_koishi7.Schema.boolean().default(false).description("🗣️ 是否在会话中输出详细信息。(生产环境别开,东西很多)"),
|
|
5481
|
+
verboseConsoleOutput: import_koishi7.Schema.boolean().default(false).description("💻 是否在控制台输出详细信息。"),
|
|
5482
|
+
verboseFileOutput: import_koishi7.Schema.boolean().default(false).description("📄 是否在文件中输出详细信息。(生产环境不要开)")
|
|
2135
5483
|
}).description("调试 (Debug) 配置 🐞")
|
|
2136
5484
|
]);
|
|
2137
5485
|
function apply(ctx, config) {
|
|
@@ -2144,441 +5492,13 @@ function apply(ctx, config) {
|
|
|
2144
5492
|
config.sendImage && "图片消息",
|
|
2145
5493
|
config.sendForward && "合并转发消息"
|
|
2146
5494
|
].filter(Boolean).join("、");
|
|
2147
|
-
ctx
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
await session.send(msg);
|
|
2155
|
-
});
|
|
2156
|
-
if (config.enableUserInfoCommand)
|
|
2157
|
-
ctx.command(`${config.userinfoCommandName} [qqId:string]`, `获取用户信息, 发送${responseHint}`).alias("aui").alias("awa_user_info").option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }, qqId) => {
|
|
2158
|
-
if (!session.onebot)
|
|
2159
|
-
return session.send("[error]当前会话不支持onebot协议。");
|
|
2160
|
-
const IMAGE_STYLE_VALUES = Object.values(IMAGE_STYLES);
|
|
2161
|
-
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
2162
|
-
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
2163
|
-
if (options.imageStyleIdx !== void 0) {
|
|
2164
|
-
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
2165
|
-
if (!isIdxValid) {
|
|
2166
|
-
let idxInvalidMsgArr = [
|
|
2167
|
-
`图片样式索引不合法。`,
|
|
2168
|
-
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
2169
|
-
` 当前输入:${options.imageStyleIdx}`,
|
|
2170
|
-
`
|
|
2171
|
-
`,
|
|
2172
|
-
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
2173
|
-
];
|
|
2174
|
-
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
2175
|
-
}
|
|
2176
|
-
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
2177
|
-
}
|
|
2178
|
-
let targetUserId = session.userId;
|
|
2179
|
-
let isDirectQuery = false;
|
|
2180
|
-
if (qqId) {
|
|
2181
|
-
const userIdRegex = /<at id="([^"]+)"(?: name="[^"]*")?\/>/;
|
|
2182
|
-
const match = qqId.match(userIdRegex);
|
|
2183
|
-
if (match) {
|
|
2184
|
-
targetUserId = match[1];
|
|
2185
|
-
isDirectQuery = true;
|
|
2186
|
-
} else {
|
|
2187
|
-
targetUserId = qqId;
|
|
2188
|
-
isDirectQuery = true;
|
|
2189
|
-
}
|
|
2190
|
-
}
|
|
2191
|
-
if (!isDirectQuery) {
|
|
2192
|
-
for (const e of session.event.message.elements) {
|
|
2193
|
-
if (e.type === "at") {
|
|
2194
|
-
targetUserId = e.attrs.id;
|
|
2195
|
-
break;
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
const userObj = await session.bot.getUser(targetUserId);
|
|
2200
|
-
let userObjMsg = `userObj =
|
|
2201
|
-
${JSON.stringify(userObj)}`;
|
|
2202
|
-
const userAvatarUrl = userObj.avatar;
|
|
2203
|
-
let userInfoArg = {
|
|
2204
|
-
status: null
|
|
2205
|
-
};
|
|
2206
|
-
let contextInfo = {
|
|
2207
|
-
isGroup: false,
|
|
2208
|
-
groupId: null,
|
|
2209
|
-
groupName: null,
|
|
2210
|
-
groupAvatarUrl: null,
|
|
2211
|
-
memberCount: null,
|
|
2212
|
-
maxMemberCount: null
|
|
2213
|
-
};
|
|
2214
|
-
try {
|
|
2215
|
-
const strangerInfoObj = await session.onebot.getStrangerInfo(targetUserId);
|
|
2216
|
-
let strangerInfoObjMsg = `strangerInfoObj =
|
|
2217
|
-
${JSON.stringify(strangerInfoObj)}`;
|
|
2218
|
-
if (config.verboseSessionOutput) await session.send(strangerInfoObjMsg);
|
|
2219
|
-
if (config.verboseConsoleOutput) ctx.logger.info(strangerInfoObjMsg);
|
|
2220
|
-
if (session.guildId && !isDirectQuery) {
|
|
2221
|
-
const groupMemberInfoObj = await session.onebot.getGroupMemberInfo(session.guildId, targetUserId);
|
|
2222
|
-
let groupMemberInfoObjMsg = `groupMemberInfoObj =
|
|
2223
|
-
${JSON.stringify(groupMemberInfoObj)}`;
|
|
2224
|
-
if (config.verboseSessionOutput) await session.send(groupMemberInfoObjMsg);
|
|
2225
|
-
if (config.verboseConsoleOutput) ctx.logger.info(groupMemberInfoObjMsg);
|
|
2226
|
-
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
2227
|
-
let groupInfoObjMsg = `groupInfoObj =
|
|
2228
|
-
${JSON.stringify(groupInfoObj)}`;
|
|
2229
|
-
if (config.verboseSessionOutput) await session.send(groupInfoObjMsg);
|
|
2230
|
-
if (config.verboseConsoleOutput) ctx.logger.info(groupInfoObjMsg);
|
|
2231
|
-
userInfoArg = {
|
|
2232
|
-
...groupMemberInfoObj,
|
|
2233
|
-
...strangerInfoObj,
|
|
2234
|
-
// @ts-ignore - strangerInfoObj 实际包含 age 字段,但类型定义中缺失
|
|
2235
|
-
age: strangerInfoObj.age,
|
|
2236
|
-
// @ts-ignore - strangerInfoObj 实际包含 level 字段,但类型定义中缺失 (here ↓)
|
|
2237
|
-
// node_modules/koishi-plugin-adapter-onebot/lib/types.d.ts: export interface StrangerInfo ...
|
|
2238
|
-
level: strangerInfoObj.level,
|
|
2239
|
-
sex: strangerInfoObj.sex,
|
|
2240
|
-
card: groupMemberInfoObj.card,
|
|
2241
|
-
role: groupMemberInfoObj.role,
|
|
2242
|
-
join_time: groupMemberInfoObj.join_time,
|
|
2243
|
-
last_sent_time: groupMemberInfoObj.last_sent_time,
|
|
2244
|
-
group_level: groupMemberInfoObj.level,
|
|
2245
|
-
title: groupMemberInfoObj.title,
|
|
2246
|
-
avatar: userObj.avatar
|
|
2247
|
-
};
|
|
2248
|
-
contextInfo = {
|
|
2249
|
-
isGroup: true,
|
|
2250
|
-
groupId: session.guildId,
|
|
2251
|
-
//@ts-ignore - groupInfoObj 在lagrange中 实际包含 GroupName 字段,但类型定义中缺失
|
|
2252
|
-
groupName: groupInfoObj.GroupName || groupInfoObj.group_name,
|
|
2253
|
-
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`,
|
|
2254
|
-
memberCount: groupInfoObj.member_count || 0,
|
|
2255
|
-
maxMemberCount: groupInfoObj.max_member_count || 0
|
|
2256
|
-
};
|
|
2257
|
-
} else {
|
|
2258
|
-
userInfoArg = {
|
|
2259
|
-
...strangerInfoObj,
|
|
2260
|
-
// @ts-ignore - userObj 确实有avatar字段
|
|
2261
|
-
avatar: userObj.avatar
|
|
2262
|
-
};
|
|
2263
|
-
contextInfo = {
|
|
2264
|
-
isGroup: false,
|
|
2265
|
-
groupId: null,
|
|
2266
|
-
groupName: null,
|
|
2267
|
-
groupAvatarUrl: null,
|
|
2268
|
-
memberCount: null,
|
|
2269
|
-
maxMemberCount: null
|
|
2270
|
-
};
|
|
2271
|
-
}
|
|
2272
|
-
if (config.onebotImplName === ONEBOT_IMPL_NAME.LAGRNAGE) {
|
|
2273
|
-
} else if (config.onebotImplName === ONEBOT_IMPL_NAME.NAPCAT) {
|
|
2274
|
-
const ncUserStatusObj = await session.onebot._request("nc_get_user_status", { user_id: targetUserId });
|
|
2275
|
-
const napcatStatusData = ncUserStatusObj?.data ?? null;
|
|
2276
|
-
userInfoArg.status = {
|
|
2277
|
-
napcat_origin: ncUserStatusObj,
|
|
2278
|
-
message: getNapcatQQStatusText(napcatStatusData?.status, napcatStatusData?.ext_status)
|
|
2279
|
-
};
|
|
2280
|
-
}
|
|
2281
|
-
let userInfoArgMsg = `userInfoArg =
|
|
2282
|
-
${JSON.stringify(userInfoArg)}`;
|
|
2283
|
-
let contextInfoMsg = `contextInfo =
|
|
2284
|
-
${JSON.stringify(contextInfo)}`;
|
|
2285
|
-
if (config.verboseSessionOutput) {
|
|
2286
|
-
await session.send(userInfoArgMsg);
|
|
2287
|
-
await session.send(contextInfoMsg);
|
|
2288
|
-
}
|
|
2289
|
-
if (config.verboseConsoleOutput) {
|
|
2290
|
-
await ctx.logger.info(userInfoArgMsg);
|
|
2291
|
-
await ctx.logger.info(contextInfoMsg);
|
|
2292
|
-
}
|
|
2293
|
-
const unifiedUserInfo = convertToUnifiedUserInfo(userInfoArg, config.onebotImplName);
|
|
2294
|
-
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2295
|
-
let unifiedUserInfoMsg = `unifiedUserInfo =
|
|
2296
|
-
${JSON.stringify(unifiedUserInfo)}`;
|
|
2297
|
-
let unifiedContextInfoMsg = `unifiedContextInfo =
|
|
2298
|
-
${JSON.stringify(unifiedContextInfo)}`;
|
|
2299
|
-
if (config.verboseSessionOutput) {
|
|
2300
|
-
await session.send(unifiedUserInfoMsg);
|
|
2301
|
-
await session.send(unifiedContextInfoMsg);
|
|
2302
|
-
}
|
|
2303
|
-
if (config.verboseConsoleOutput) {
|
|
2304
|
-
await ctx.logger.info(unifiedUserInfoMsg);
|
|
2305
|
-
await ctx.logger.info(unifiedContextInfoMsg);
|
|
2306
|
-
}
|
|
2307
|
-
if (config.sendText) {
|
|
2308
|
-
ctx.logger.info("text");
|
|
2309
|
-
const formattedText = formatUserInfoDirectText(unifiedUserInfo, unifiedContextInfo);
|
|
2310
|
-
session.send(`${config.enableQuoteWithText ? import_koishi.h.quote(session.messageId) : ""}${formattedText}`);
|
|
2311
|
-
}
|
|
2312
|
-
if (config.sendImage) {
|
|
2313
|
-
const waitTipMsgId = await session.send(`${import_koishi.h.quote(session.messageId)}🔄正在渲染用户信息图片,请稍候⏳...`);
|
|
2314
|
-
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
2315
|
-
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
2316
|
-
const userInfoimageBase64 = await renderUserInfo(ctx, unifiedUserInfo, unifiedContextInfo, selectedImageStyle, selectedDarkMode, config.imageType, config.screenshotQuality, config.hidePhoneNumber);
|
|
2317
|
-
if (config.verboseFileOutput) {
|
|
2318
|
-
try {
|
|
2319
|
-
const tmpDir = (0, import_path2.resolve)(__dirname, "../tmp");
|
|
2320
|
-
(0, import_fs2.mkdirSync)(tmpDir, { recursive: true });
|
|
2321
|
-
const outputPath = (0, import_path2.resolve)(tmpDir, "image_base64.txt");
|
|
2322
|
-
(0, import_fs2.writeFileSync)(outputPath, userInfoimageBase64, "utf-8");
|
|
2323
|
-
ctx.logger.info(`图片 base64 已输出到: ${outputPath}`);
|
|
2324
|
-
} catch (error) {
|
|
2325
|
-
ctx.logger.error(`写入 base64 文件失败: ${error.message}`);
|
|
2326
|
-
}
|
|
2327
|
-
}
|
|
2328
|
-
await session.send(`${config.enableQuoteWithImage ? import_koishi.h.quote(session.messageId) : ""}${import_koishi.h.image(`data:image/png;base64,${userInfoimageBase64}`)}`);
|
|
2329
|
-
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
2330
|
-
}
|
|
2331
|
-
if (config.sendForward) {
|
|
2332
|
-
const forwardMessageContent = formatUserInfoForwardText(session.bot, unifiedUserInfo, unifiedContextInfo);
|
|
2333
|
-
session.send(import_koishi.h.unescape(forwardMessageContent));
|
|
2334
|
-
}
|
|
2335
|
-
} catch (error) {
|
|
2336
|
-
ctx.logger.error(`获取用户信息或渲染图片失败:
|
|
2337
|
-
error=${error}
|
|
2338
|
-
error.stack=${error.stack}`);
|
|
2339
|
-
await session.send(`[error]获取用户信息或渲染图片失败:
|
|
2340
|
-
error.message=${error.message}`);
|
|
2341
|
-
}
|
|
2342
|
-
});
|
|
2343
|
-
if (config.enableGroupAdminListCommand)
|
|
2344
|
-
ctx.command(config.groupAdminListCommandName, `获取群管理员列表, 发送${responseHint}`).alias("al").alias("awa_group_admin_list").option("imageStyleIdx", "-i, --idx, --index <idx:number> 图片样式索引").action(async ({ session, options }) => {
|
|
2345
|
-
if (!session.onebot)
|
|
2346
|
-
return session.send("[error]当前会话不支持onebot协议。");
|
|
2347
|
-
if (!session.guildId)
|
|
2348
|
-
return session.send("[error]当前会话不在群聊中。");
|
|
2349
|
-
const IMAGE_STYLE_VALUES = Object.values(IMAGE_STYLES);
|
|
2350
|
-
const defaultStyleDetailObj = config.imageStyleDetails.length > 0 ? config.imageStyleDetails[0] : { styleKey: IMAGE_STYLE_KEY_ARR[0], darkMode: false };
|
|
2351
|
-
let selectedStyleDetailObj = defaultStyleDetailObj;
|
|
2352
|
-
if (options.imageStyleIdx !== void 0) {
|
|
2353
|
-
const isIdxValid = options.imageStyleIdx >= 0 && options.imageStyleIdx < config.imageStyleDetails.length;
|
|
2354
|
-
if (!isIdxValid) {
|
|
2355
|
-
let idxInvalidMsgArr = [
|
|
2356
|
-
`图片样式索引不合法。`,
|
|
2357
|
-
` 合法范围:[0, ${config.imageStyleDetails.length - 1}]双闭区间。`,
|
|
2358
|
-
` 当前输入:${options.imageStyleIdx}`,
|
|
2359
|
-
`
|
|
2360
|
-
`,
|
|
2361
|
-
`输入指令 ${config.inspectStyleCommandName} 查看图片样式列表。`
|
|
2362
|
-
];
|
|
2363
|
-
return await session.send(idxInvalidMsgArr.join("\n"));
|
|
2364
|
-
}
|
|
2365
|
-
selectedStyleDetailObj = config.imageStyleDetails[options.imageStyleIdx];
|
|
2366
|
-
}
|
|
2367
|
-
try {
|
|
2368
|
-
const groupMemberListObj = await session.onebot.getGroupMemberList(session.guildId);
|
|
2369
|
-
const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
|
|
2370
|
-
const groupAdminMemberListObj = groupMemberListObj.filter((m) => m.role === "admin" || m.role === "owner");
|
|
2371
|
-
let groupAdminMemberListObjMsg = `groupAdminMemberListObj =
|
|
2372
|
-
${JSON.stringify(groupAdminMemberListObj)}`;
|
|
2373
|
-
if (config.verboseSessionOutput) await session.send(groupAdminMemberListObjMsg);
|
|
2374
|
-
if (config.verboseConsoleOutput) ctx.logger.info(groupAdminMemberListObjMsg);
|
|
2375
|
-
if (groupAdminMemberListObj.length === 0) {
|
|
2376
|
-
return session.send("该群没有管理员。");
|
|
2377
|
-
}
|
|
2378
|
-
const adminListArg = [];
|
|
2379
|
-
for (const member of groupAdminMemberListObj) {
|
|
2380
|
-
try {
|
|
2381
|
-
const userObj = await session.bot.getUser(member.user_id);
|
|
2382
|
-
const rawAdminInfo = {
|
|
2383
|
-
user_id: member.user_id,
|
|
2384
|
-
nickname: member.nickname,
|
|
2385
|
-
card: member.card,
|
|
2386
|
-
role: member.role,
|
|
2387
|
-
level: member.level,
|
|
2388
|
-
join_time: member.join_time,
|
|
2389
|
-
last_sent_time: member.last_sent_time,
|
|
2390
|
-
title: member.title,
|
|
2391
|
-
avatar: userObj.avatar || ""
|
|
2392
|
-
};
|
|
2393
|
-
adminListArg.push(convertToUnifiedAdminInfo(rawAdminInfo, config.onebotImplName));
|
|
2394
|
-
} catch (error) {
|
|
2395
|
-
ctx.logger.error(`获取管理员列表信息失败: ${error}`);
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
adminListArg.sort((a, b) => {
|
|
2399
|
-
if (a.role === "owner" && b.role !== "owner") return -1;
|
|
2400
|
-
if (a.role !== "owner" && b.role === "owner") return 1;
|
|
2401
|
-
const cardA = a.card || "";
|
|
2402
|
-
const cardB = b.card || "";
|
|
2403
|
-
return cardB.localeCompare(cardA, "zh");
|
|
2404
|
-
});
|
|
2405
|
-
const contextInfo = {
|
|
2406
|
-
isGroup: true,
|
|
2407
|
-
groupId: parseInt(session.guildId),
|
|
2408
|
-
groupName: groupInfoObj.group_name || "未知群聊",
|
|
2409
|
-
memberCount: groupInfoObj.member_count || 0,
|
|
2410
|
-
maxMemberCount: groupInfoObj.max_member_count || 0,
|
|
2411
|
-
groupAvatarUrl: `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`
|
|
2412
|
-
};
|
|
2413
|
-
if (config.sendText) {
|
|
2414
|
-
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2415
|
-
const formattedText = formatAdminListDirectText(adminListArg, unifiedContextInfo);
|
|
2416
|
-
await session.send(`${config.enableQuoteWithText ? import_koishi.h.quote(session.messageId) : ""}${formattedText}`);
|
|
2417
|
-
}
|
|
2418
|
-
if (config.sendImage) {
|
|
2419
|
-
ctx.logger.info(`context info = ${JSON.stringify(contextInfo)}`);
|
|
2420
|
-
const waitTipMsgId = await session.send(`${import_koishi.h.quote(session.messageId)}🔄正在渲染群管理员列表图片,请稍候⏳...`);
|
|
2421
|
-
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2422
|
-
const selectedImageStyle = IMAGE_STYLES[selectedStyleDetailObj.styleKey];
|
|
2423
|
-
const selectedDarkMode = selectedStyleDetailObj.darkMode;
|
|
2424
|
-
const adminListImageBase64 = await renderAdminList(ctx, adminListArg, unifiedContextInfo, selectedImageStyle, selectedDarkMode, config.imageType, config.screenshotQuality);
|
|
2425
|
-
await session.send(`${config.enableQuoteWithImage ? import_koishi.h.quote(session.messageId) : ""}${import_koishi.h.image(`data:image/png;base64,${adminListImageBase64}`)}`);
|
|
2426
|
-
await session.bot.deleteMessage(session.guildId, String(waitTipMsgId));
|
|
2427
|
-
}
|
|
2428
|
-
if (config.sendForward) {
|
|
2429
|
-
const unifiedContextInfo = convertToUnifiedContextInfo(contextInfo, config.onebotImplName);
|
|
2430
|
-
const forwardMessageContent = formatAdminListForwardText(adminListArg, unifiedContextInfo);
|
|
2431
|
-
await session.send(import_koishi.h.unescape(forwardMessageContent));
|
|
2432
|
-
}
|
|
2433
|
-
} catch (error) {
|
|
2434
|
-
ctx.logger.error(`获取群管理员列表失败: ${error}`);
|
|
2435
|
-
await session.send(`[error]获取群管理员列表失败: ${error.message}`);
|
|
2436
|
-
}
|
|
2437
|
-
});
|
|
2438
|
-
function formatUserInfoDirectText(userInfo, contextInfo) {
|
|
2439
|
-
let output = "";
|
|
2440
|
-
output += `----- 用户信息 (UserInfo) -----
|
|
2441
|
-
`;
|
|
2442
|
-
output += `QQ号 (UserID): ${userInfo.user_id}
|
|
2443
|
-
`;
|
|
2444
|
-
if (userInfo.nickname) output += `昵称 (Nickname): ${userInfo.nickname}
|
|
2445
|
-
`;
|
|
2446
|
-
if (userInfo.card) output += `群昵称 (GroupCard): ${userInfo.card}
|
|
2447
|
-
`;
|
|
2448
|
-
if (userInfo.sex) output += `性别 (Gender): ${userInfo.sex === "male" ? "男 (Male)" : userInfo.sex === "female" ? "女 (Female)" : "未知 (Unknown)"}
|
|
2449
|
-
`;
|
|
2450
|
-
if (userInfo.age) output += `年龄 (Age): ${userInfo.age}
|
|
2451
|
-
`;
|
|
2452
|
-
if (userInfo.level) output += `等级 (Level): ${userInfo.level}
|
|
2453
|
-
`;
|
|
2454
|
-
if (userInfo.sign) output += `个性签名 (Signature): ${userInfo.sign}
|
|
2455
|
-
`;
|
|
2456
|
-
if (userInfo.role) output += `群角色 (GroupRole): ${userInfo.role === "owner" ? "群主 (Owner)" : userInfo.role === "admin" ? "管理员 (Admin)" : "成员 (Member)"}
|
|
2457
|
-
`;
|
|
2458
|
-
if (userInfo.join_time) output += `入群时间 (JoinTime): ${new Date(userInfo.join_time).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
2459
|
-
`;
|
|
2460
|
-
if (userInfo.RegisterTime) output += `注册时间 (RegTime): ${new Date(userInfo.RegisterTime).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
2461
|
-
`;
|
|
2462
|
-
output += `
|
|
2463
|
-
--- 会话信息 (ContextInfo) ---
|
|
2464
|
-
`;
|
|
2465
|
-
output += `是否群聊 (IsGroupChat): ${contextInfo.isGroup ? "是 (Yes)" : "否 (No)"}
|
|
2466
|
-
`;
|
|
2467
|
-
if (contextInfo.isGroup && contextInfo.groupId) output += `群号 (GroupID): ${contextInfo.groupId}
|
|
2468
|
-
`;
|
|
2469
|
-
return output;
|
|
2470
|
-
}
|
|
2471
|
-
__name(formatUserInfoDirectText, "formatUserInfoDirectText");
|
|
2472
|
-
function formatUserInfoForwardText(botSelf, userInfo, contextInfo) {
|
|
2473
|
-
let messages = "";
|
|
2474
|
-
const addMessageBlock = /* @__PURE__ */ __name((authorId, authorName, value) => {
|
|
2475
|
-
messages += `
|
|
2476
|
-
<message>
|
|
2477
|
-
<author ${authorId ? `id="${authorId}"` : ``} ${authorName ? `name="${authorName}"` : ``}/>
|
|
2478
|
-
${value}
|
|
2479
|
-
</message>`;
|
|
2480
|
-
}, "addMessageBlock");
|
|
2481
|
-
addMessageBlock(void 0, "当前时间 (CurrentTime):", `${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`);
|
|
2482
|
-
addMessageBlock(void 0, "信息类型 (InfoType):", "用户信息 (User Info)");
|
|
2483
|
-
addMessageBlock(userInfo.user_id, void 0, `QQ号 (UserID): ${userInfo.user_id}`);
|
|
2484
|
-
if (userInfo.nickname) addMessageBlock(userInfo.user_id, void 0, `昵称 (Nickname): ${userInfo.nickname}`);
|
|
2485
|
-
if (userInfo.card) addMessageBlock(userInfo.user_id, void 0, `群昵称 (GroupCard): ${userInfo.card}`);
|
|
2486
|
-
if (userInfo.sex) addMessageBlock(userInfo.user_id, void 0, `性别 (Gender): ${userInfo.sex === "male" ? "男 (Male)" : userInfo.sex === "female" ? "女 (Female)" : "未知 (Unknown)"}`);
|
|
2487
|
-
if (userInfo.age !== void 0 && userInfo.age !== null) addMessageBlock(userInfo.user_id, void 0, `年龄 (Age): ${userInfo.age}`);
|
|
2488
|
-
if (userInfo.level) addMessageBlock(userInfo.user_id, void 0, `等级 (Level): ${userInfo.level}`);
|
|
2489
|
-
if (userInfo.sign) addMessageBlock(userInfo.user_id, void 0, `个性签名 (Signature): ${userInfo.sign}`);
|
|
2490
|
-
if (userInfo.role) addMessageBlock(userInfo.user_id, void 0, `群角色 (GroupRole): ${userInfo.role === "owner" ? "群主 (Owner)" : userInfo.role === "admin" ? "管理员 (Admin)" : "成员 (Member)"}`);
|
|
2491
|
-
if (userInfo.join_time) addMessageBlock(userInfo.user_id, void 0, `入群时间 (JoinTime): ${new Date(userInfo.join_time).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`);
|
|
2492
|
-
if (userInfo.RegisterTime) addMessageBlock(userInfo.user_id, void 0, `注册时间 (RegTime): ${new Date(userInfo.RegisterTime).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`);
|
|
2493
|
-
addMessageBlock(botSelf.userId, "信息类型 (Info Type):", "会话信息 (Context Info)");
|
|
2494
|
-
addMessageBlock(botSelf.userId, "是否群聊 (Is Group Chat):", `${contextInfo.isGroup ? "是 (Yes)" : "否 (No)"}`);
|
|
2495
|
-
if (contextInfo.isGroup && contextInfo.groupId) addMessageBlock(botSelf.userId, "群号 (Group ID):", `${contextInfo.groupId}`);
|
|
2496
|
-
return `<message forward>
|
|
2497
|
-
${messages}
|
|
2498
|
-
</message>`;
|
|
2499
|
-
}
|
|
2500
|
-
__name(formatUserInfoForwardText, "formatUserInfoForwardText");
|
|
2501
|
-
function formatAdminListDirectText(adminListArg, contextInfo) {
|
|
2502
|
-
let output = "";
|
|
2503
|
-
output += `当前时间 (Current Time): ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
2504
|
-
`;
|
|
2505
|
-
output += `===== 群管理员列表 (Group Admin List) =====
|
|
2506
|
-
`;
|
|
2507
|
-
output += `群名称 (Group Name): ${contextInfo.groupName || "未知群聊"}
|
|
2508
|
-
`;
|
|
2509
|
-
output += `群号 (Group ID): ${contextInfo.groupId}
|
|
2510
|
-
`;
|
|
2511
|
-
output += `成员数 (Member Count): ${contextInfo.memberCount}/${contextInfo.maxMemberCount}
|
|
2512
|
-
`;
|
|
2513
|
-
output += `管理员数量 (Admin Count): ${adminListArg.length}
|
|
2514
|
-
|
|
2515
|
-
`;
|
|
2516
|
-
adminListArg.forEach((admin, index) => {
|
|
2517
|
-
output += `-----No. ${index + 1}. ${admin.role === "owner" ? "群主" : "管理员"} (${admin.role === "owner" ? "Owner" : "Admin"})-----
|
|
2518
|
-
`;
|
|
2519
|
-
output += ` QQ号 (User ID): ${admin.user_id}
|
|
2520
|
-
`;
|
|
2521
|
-
output += ` 昵称 (Nickname): ${admin.nickname || "未知"}
|
|
2522
|
-
`;
|
|
2523
|
-
if (admin.card) output += ` 群名片 (Group Card): ${admin.card}
|
|
2524
|
-
`;
|
|
2525
|
-
if (admin.level) output += ` 等级 (Level): ${admin.level}
|
|
2526
|
-
`;
|
|
2527
|
-
if (admin.join_time) output += ` 入群时间 (Join Time): ${new Date(admin.join_time * 1e3).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}
|
|
2528
|
-
`;
|
|
2529
|
-
if (admin.title) output += ` 头衔 (Title): ${admin.title}
|
|
2530
|
-
`;
|
|
2531
|
-
output += "\n";
|
|
2532
|
-
});
|
|
2533
|
-
return output;
|
|
2534
|
-
}
|
|
2535
|
-
__name(formatAdminListDirectText, "formatAdminListDirectText");
|
|
2536
|
-
function formatAdminListForwardText(adminListArg, contextInfo) {
|
|
2537
|
-
let messages = "";
|
|
2538
|
-
const addMessageBlock = /* @__PURE__ */ __name((authorId, authorName, adminUsrInfoStr) => {
|
|
2539
|
-
messages += `
|
|
2540
|
-
<message>
|
|
2541
|
-
<author ${authorId ? `id="${authorId}"` : ``} name="${authorName}"/>
|
|
2542
|
-
${adminUsrInfoStr}
|
|
2543
|
-
</message>`;
|
|
2544
|
-
}, "addMessageBlock");
|
|
2545
|
-
addMessageBlock(
|
|
2546
|
-
void 0,
|
|
2547
|
-
"群聊基本信息",
|
|
2548
|
-
[
|
|
2549
|
-
`当前时间: ${(/* @__PURE__ */ new Date()).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}`,
|
|
2550
|
-
`=========群聊信息=========`,
|
|
2551
|
-
`群名称: ${contextInfo.groupName || "未知群聊"}`,
|
|
2552
|
-
`群号: ${contextInfo.groupId}`,
|
|
2553
|
-
`成员数: ${contextInfo.memberCount}/${contextInfo.maxMemberCount}`,
|
|
2554
|
-
`管理员数量: ${adminListArg.length}`
|
|
2555
|
-
].join("\n")
|
|
2556
|
-
);
|
|
2557
|
-
for (let i = 0; i < adminListArg.length; i++) {
|
|
2558
|
-
const admin = adminListArg[i];
|
|
2559
|
-
const authorName = admin.card || admin.nickname || `QQ: ${admin.user_id}`;
|
|
2560
|
-
const adminDetails = [
|
|
2561
|
-
`---------No. ${i + 1}---------`,
|
|
2562
|
-
`QQ号: ${admin.user_id}`,
|
|
2563
|
-
`昵称: ${admin.nickname}`,
|
|
2564
|
-
`角色: ${admin.role === "owner" ? "群主" : "管理员"}`,
|
|
2565
|
-
admin.card ? `群昵称: ${admin.card}` : "",
|
|
2566
|
-
admin.level ? `等级: ${admin.level}` : "",
|
|
2567
|
-
admin.title ? `群头衔: ${admin.title}` : "",
|
|
2568
|
-
admin.join_time ? `加入本群时间: ${new Date(admin.join_time * 1e3).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}` : "",
|
|
2569
|
-
admin.last_sent_time ? `最后发言时间: ${new Date(admin.last_sent_time * 1e3).toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" })}` : ""
|
|
2570
|
-
].filter(Boolean).join("\n");
|
|
2571
|
-
addMessageBlock(
|
|
2572
|
-
admin.user_id.toString(),
|
|
2573
|
-
authorName,
|
|
2574
|
-
adminDetails
|
|
2575
|
-
);
|
|
2576
|
-
}
|
|
2577
|
-
return `<message forward>
|
|
2578
|
-
${messages}
|
|
2579
|
-
</message>`;
|
|
2580
|
-
}
|
|
2581
|
-
__name(formatAdminListForwardText, "formatAdminListForwardText");
|
|
5495
|
+
registerInspectStyleCommand(ctx, config);
|
|
5496
|
+
registerUserInfoCommand(ctx, config, responseHint);
|
|
5497
|
+
registerAdminListCommand(ctx, config, responseHint);
|
|
5498
|
+
registerGroupEssenceCommand(ctx, config, responseHint);
|
|
5499
|
+
registerGroupEssenceDetailCommand(ctx, config, responseHint);
|
|
5500
|
+
registerGroupNoticeCommand(ctx, config, responseHint);
|
|
5501
|
+
registerGroupNoticeDetailCommand(ctx, config, responseHint);
|
|
2582
5502
|
}
|
|
2583
5503
|
__name(apply, "apply");
|
|
2584
5504
|
// Annotate the CommonJS export names for ESM import in node:
|