koishi-plugin-noah 2.4.0 → 2.4.2

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/index.cjs CHANGED
@@ -491,9 +491,6 @@ var CardService = class {
491
491
  * @returns 无返回值的Promise
492
492
  */
493
493
  async updateCard(id, partial) {
494
- if (partial.defaultServerId === void 0) {
495
- partial.defaultServerId = 0;
496
- }
497
494
  await this.ctx.database.set(this.tableName, id, partial);
498
495
  }
499
496
  /**
@@ -1115,8 +1112,8 @@ function registerApiRoutes(ctx, apiCtx) {
1115
1112
  "/noah/api/resolve",
1116
1113
  "/noah/api/health"
1117
1114
  ];
1118
- for (const path3 of apiPaths) {
1119
- ctx.server.all(path3, async (kctx, next) => {
1115
+ for (const path4 of apiPaths) {
1116
+ ctx.server.all(path4, async (kctx, next) => {
1120
1117
  setCors(kctx);
1121
1118
  if (kctx.method === "OPTIONS") {
1122
1119
  kctx.status = 204;
@@ -1423,11 +1420,8 @@ __export(command_exports, {
1423
1420
  });
1424
1421
 
1425
1422
  // src/core/commands/bind.ts
1426
- function bind(ctx, config) {
1427
- ctx.command("bind [cardCode:text]", { slash: true }).alias("绑卡").userFields(["defaultCardId", "id"]).action(async ({ session }, cardCode) => {
1428
- const cardService = new CardService(ctx);
1429
- const serverService = new ServerService(ctx);
1430
- const userService = new UserService(ctx);
1423
+ function bind(ctx, config, cardService, serverService, userService) {
1424
+ ctx.command("bind [cardCode:text]", { slash: true }).alias("绑卡").userFields(["id"]).action(async ({ session }, cardCode) => {
1431
1425
  if (!cardCode) {
1432
1426
  await session.send(session.text(".prompt"));
1433
1427
  cardCode = await session.prompt();
@@ -1482,9 +1476,8 @@ __name(bind, "bind");
1482
1476
 
1483
1477
  // src/core/commands/card.ts
1484
1478
  var import_koishi2 = require("koishi");
1485
- function card(ctx, config) {
1479
+ function card(ctx, config, cardService, serverService, userService) {
1486
1480
  ctx.command("card", { slash: true }).alias("卡片管理").userFields(["id"]).channelFields(["id"]).option("detail", "-d <cardCode:text>").action(async ({ session, options }) => {
1487
- const cardService = new CardService(ctx);
1488
1481
  const atGuild = session.guildId != null;
1489
1482
  if (options.detail) {
1490
1483
  const cardCode = processInputCardCode(options.detail);
@@ -1501,8 +1494,6 @@ function card(ctx, config) {
1501
1494
  return session.text(".lookup-error-unknown");
1502
1495
  }
1503
1496
  }
1504
- const serverService = new ServerService(ctx);
1505
- const userService = new UserService(ctx);
1506
1497
  const defaultCard = await cardService.getDefaultCardByUid(session.user.id);
1507
1498
  const defaultCardId = defaultCard ? defaultCard.id : 0;
1508
1499
  const userDefaultServer = await serverService.getDefaultServerByUid(session.user.id);
@@ -1712,14 +1703,6 @@ async function showCardMenu(ctx, session, card2, cardService, serverService, use
1712
1703
  }
1713
1704
  if (selectNum === 3) {
1714
1705
  await cardService.removeCard(card2.id);
1715
- if (userDefaultCardId === card2.id) {
1716
- const res = await cardService.getCardsByUid(uid);
1717
- if (res.length === 0) {
1718
- await userService.updateUserDefaultCard(uid, 0);
1719
- } else {
1720
- await userService.updateUserDefaultCard(uid, res[0].id);
1721
- }
1722
- }
1723
1706
  return session.text(".menu-3-success");
1724
1707
  }
1725
1708
  if (selectNum === 4) {
@@ -1728,10 +1711,7 @@ async function showCardMenu(ctx, session, card2, cardService, serverService, use
1728
1711
  if (!cardName) return session.text("commands.timeout");
1729
1712
  if (cardName === "q") return session.text(".quit");
1730
1713
  if (cardName.includes(" ")) return session.text(".menu-4-error-invalid-name");
1731
- await cardService.updateCard(card2.id, {
1732
- name: cardName,
1733
- defaultServerId: card2.defaultServerId
1734
- });
1714
+ await cardService.updateCard(card2.id, { name: cardName });
1735
1715
  return session.text(".menu-4-success");
1736
1716
  }
1737
1717
  if (selectNum === 5) {
@@ -2048,10 +2028,8 @@ async function promptServerSelect(session, servers, defaultId, prefix) {
2048
2028
  return selectNum;
2049
2029
  }
2050
2030
  __name(promptServerSelect, "promptServerSelect");
2051
- function server(ctx, config) {
2031
+ function server(ctx, config, serverService, userService) {
2052
2032
  ctx.command("server", { slash: true }).alias("服务器管理").option("channel", "-c").userFields(["id"]).channelFields(["id"]).action(async ({ session, options }) => {
2053
- const serverService = new ServerService(ctx);
2054
- const userService = new UserService(ctx);
2055
2033
  const atGuild = session.guildId != null;
2056
2034
  if (options.channel) {
2057
2035
  if (!atGuild) return session.text(".no-channel");
@@ -2258,25 +2236,6 @@ async function showServerMenu(ctx, session, serverService, userService, server2,
2258
2236
  }
2259
2237
  if (selectNum === 3) {
2260
2238
  await serverService.removeServer(server2.id);
2261
- if (from === "user") {
2262
- if (userDefaultServerId === server2.id) {
2263
- const res = await serverService.getServersByUid(uid);
2264
- if (res.length === 0) {
2265
- await userService.updateUserDefaultServer(uid, 0);
2266
- } else {
2267
- await userService.updateUserDefaultServer(uid, res[0].id);
2268
- }
2269
- }
2270
- } else {
2271
- if (channelDefaultServerId === server2.id) {
2272
- const res = await serverService.getServersByCid(cid);
2273
- if (res.length === 0) {
2274
- await userService.updateChannelDefaultServer(session.platform, cid, 0);
2275
- } else {
2276
- await userService.updateChannelDefaultServer(session.platform, cid, res[0].id);
2277
- }
2278
- }
2279
- }
2280
2239
  return session.text(".menu-3-success");
2281
2240
  }
2282
2241
  if (selectNum === 4) {
@@ -2413,10 +2372,13 @@ __name(settings, "settings");
2413
2372
  // src/core/command.ts
2414
2373
  var name2 = "command";
2415
2374
  function apply2(ctx, config) {
2375
+ const cardService = new CardService(ctx);
2376
+ const serverService = new ServerService(ctx);
2377
+ const userService = new UserService(ctx);
2416
2378
  help(ctx, config);
2417
- bind(ctx, config);
2418
- card(ctx, config);
2419
- server(ctx, config);
2379
+ bind(ctx, config, cardService, serverService, userService);
2380
+ card(ctx, config, cardService, serverService, userService);
2381
+ server(ctx, config, serverService, userService);
2420
2382
  locale(ctx, config);
2421
2383
  link(ctx, config);
2422
2384
  maintain(ctx, config);
@@ -2597,7 +2559,7 @@ function guildNameCard(ctx, config) {
2597
2559
  bot.selfId,
2598
2560
  nextNameCard
2599
2561
  );
2600
- ctx.logger("guild-namecard").info(
2562
+ ctx.logger("guild-namecard").debug(
2601
2563
  `更新 ${bot.selfId} 在 ${guild.name} 的群名片: ${currentNameCard} -> ${nextNameCard}`
2602
2564
  );
2603
2565
  try {
@@ -3331,8 +3293,8 @@ var SDVXDrawer = class extends BaseDrawer {
3331
3293
  ["Fredoka One", "fonts/FredokaOne.ttf"]
3332
3294
  ];
3333
3295
  for (const [name15, file] of fonts) {
3334
- const path3 = getAssetPath(this.ctx, file);
3335
- if (fs2.existsSync(path3)) FontLibrary.use(name15, path3);
3296
+ const path4 = getAssetPath(this.ctx, file);
3297
+ if (fs2.existsSync(path4)) FontLibrary.use(name15, path4);
3336
3298
  }
3337
3299
  this.fontsLoaded = true;
3338
3300
  }
@@ -3438,20 +3400,20 @@ var SDVXDrawer = class extends BaseDrawer {
3438
3400
  ctx.save();
3439
3401
  ctx.translate(556, 17);
3440
3402
  ctx.beginPath();
3441
- const r = 16, w = 100, h11 = 200, x0 = 0, y0 = 0;
3403
+ const r = 16, w = 100, h12 = 200, x0 = 0, y0 = 0;
3442
3404
  ctx.moveTo(x0 + r, y0);
3443
3405
  ctx.lineTo(x0 + w - r, y0);
3444
3406
  ctx.arcTo(x0 + w, y0, x0 + w, y0 + r, r);
3445
- ctx.lineTo(x0 + w, y0 + h11 - r);
3446
- ctx.arcTo(x0 + w, y0 + h11, x0 + w - r, y0 + h11, r);
3447
- ctx.lineTo(x0 + r, y0 + h11);
3448
- ctx.arcTo(x0, y0 + h11, x0, y0 + h11 - r, r);
3407
+ ctx.lineTo(x0 + w, y0 + h12 - r);
3408
+ ctx.arcTo(x0 + w, y0 + h12, x0 + w - r, y0 + h12, r);
3409
+ ctx.lineTo(x0 + r, y0 + h12);
3410
+ ctx.arcTo(x0, y0 + h12, x0, y0 + h12 - r, r);
3449
3411
  ctx.lineTo(x0, y0 + r);
3450
3412
  ctx.arcTo(x0, y0, x0 + r, y0, r);
3451
3413
  ctx.closePath();
3452
3414
  const circleRadius = 14;
3453
3415
  const circleX = x0 + w;
3454
- const circleY = y0 + h11 / 2;
3416
+ const circleY = y0 + h12 / 2;
3455
3417
  ctx.moveTo(circleX + circleRadius, circleY);
3456
3418
  ctx.arc(circleX, circleY, circleRadius, 0, Math.PI * 2, true);
3457
3419
  ctx.clip();
@@ -4280,154 +4242,20 @@ __name(apply6, "apply");
4280
4242
  var poke_exports = {};
4281
4243
  __export(poke_exports, {
4282
4244
  apply: () => apply7,
4245
+ logger: () => logger3,
4283
4246
  name: () => name7
4284
4247
  });
4285
- var fs3 = __toESM(require("fs"), 1);
4286
- var path2 = __toESM(require("path"), 1);
4287
- var import_koishi8 = require("koishi");
4288
-
4289
- // src/fun/poke/locales/en-US.yml
4290
- var en_US_default3 = { _config: { $desc: "Poke Module Settings", interval: "最小触发间隔(毫秒)", warning: "频繁触发是否发送警告", prompt: "警告内容", messages: { $desc: "消息内容", content: "消息内容", weight: "权重" } }, commands: { poke: { description: "poke" } } };
4291
-
4292
- // src/fun/poke/locales/zh-CN.yml
4293
- var zh_CN_default3 = { _config: { $desc: "Poke 模块设置", interval: "最小触发间隔(毫秒)", warning: "频繁触发是否发送警告", prompt: { $desc: "警告内容", content: "消息", weight: "权重" }, messages: { $desc: "消息内容", content: "消息", weight: "权重" } }, commands: { poke: { description: "戳一戳" } } };
4248
+ var import_koishi10 = require("koishi");
4294
4249
 
4295
- // src/fun/poke/index.ts
4296
- var name7 = "Noah-Poke";
4297
- function apply7(ctx, config) {
4298
- ;
4299
- [
4300
- ["en-US", en_US_default3],
4301
- ["zh-CN", zh_CN_default3]
4302
- ].forEach(([lang, file]) => ctx.i18n.define(lang, file));
4303
- const cache = /* @__PURE__ */ new Map();
4304
- const pokeConfig2 = config.poke;
4305
- const IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".webp"];
4306
- function isImageFile(filename) {
4307
- const ext = path2.extname(filename).toLowerCase();
4308
- return IMAGE_EXTENSIONS.includes(ext);
4309
- }
4310
- __name(isImageFile, "isImageFile");
4311
- function getMimeType(filename) {
4312
- const ext = path2.extname(filename).toLowerCase();
4313
- switch (ext) {
4314
- case ".png":
4315
- return "image/png";
4316
- case ".jpg":
4317
- case ".jpeg":
4318
- return "image/jpeg";
4319
- case ".gif":
4320
- return "image/gif";
4321
- case ".webp":
4322
- return "image/webp";
4323
- default:
4324
- return "image/png";
4325
- }
4326
- }
4327
- __name(getMimeType, "getMimeType");
4328
- function findMatchingAudio(imagePath) {
4329
- try {
4330
- const dir = path2.dirname(imagePath);
4331
- const filename = path2.basename(imagePath);
4332
- const match = filename.match(/_(\d+)\.(png|jpg|jpeg|gif|webp)$/i);
4333
- if (!match) {
4334
- return null;
4335
- }
4336
- const imageNumber = match[1];
4337
- const audioNumber = parseInt(imageNumber, 10).toString();
4338
- const files = fs3.readdirSync(dir);
4339
- const audioFile = files.find((file) => {
4340
- return file.endsWith(`-${audioNumber}.mp3`);
4341
- });
4342
- return audioFile ? path2.join(dir, audioFile) : null;
4343
- } catch {
4344
- return null;
4345
- }
4346
- }
4347
- __name(findMatchingAudio, "findMatchingAudio");
4348
- async function sendRandomNoahStamp(ctx2, session, voiceOnly = false) {
4349
- try {
4350
- const stampsPath = getAssetPath(ctx2, "stamps/noah_stamp");
4351
- const stampDirs = fs3.readdirSync(stampsPath).filter((dir) => dir.startsWith("stamp_"));
4352
- if (stampDirs.length === 0) {
4353
- await session.sendQueued("No stamps found!");
4354
- return;
4355
- }
4356
- const allStamps = [];
4357
- for (const dir of stampDirs) {
4358
- const stampDirPath = path2.join(stampsPath, dir);
4359
- const stampFiles = fs3.readdirSync(stampDirPath).filter((file) => file.startsWith(dir) && isImageFile(file));
4360
- stampFiles.forEach((file) => {
4361
- allStamps.push({
4362
- path: path2.join(stampDirPath, file),
4363
- dirName: dir
4364
- });
4365
- });
4366
- }
4367
- if (allStamps.length === 0) {
4368
- await session.sendQueued("No stamps found in any directory!");
4369
- return;
4370
- }
4371
- let availableStamps = allStamps;
4372
- if (voiceOnly) {
4373
- availableStamps = allStamps.filter((stamp) => {
4374
- const audioPath2 = findMatchingAudio(stamp.path);
4375
- return audioPath2 && fs3.existsSync(audioPath2);
4376
- });
4377
- if (availableStamps.length === 0) {
4378
- await session.sendQueued("No stamps with voice found!");
4379
- return;
4380
- }
4381
- }
4382
- const randomStamp = availableStamps[Math.floor(Math.random() * availableStamps.length)];
4383
- ctx2.logger("Noah-Poke").debug(`Selected stamp from ${randomStamp.dirName}`);
4384
- if (!fs3.existsSync(randomStamp.path)) {
4385
- await session.sendQueued("Selected stamp not found!");
4386
- return;
4387
- }
4388
- const imageBuffer = fs3.readFileSync(randomStamp.path);
4389
- const audioPath = findMatchingAudio(randomStamp.path);
4390
- await session.sendQueued(import_koishi8.h.image(imageBuffer, getMimeType(randomStamp.path)));
4391
- if (audioPath && fs3.existsSync(audioPath)) {
4392
- ctx2.logger("Noah-Poke").debug(`Found matching audio: ${path2.basename(audioPath)}`);
4393
- const audioBuffer = fs3.readFileSync(audioPath);
4394
- await session.sendQueued(import_koishi8.h.audio(audioBuffer, "audio/mpeg"));
4395
- }
4396
- } catch (error) {
4397
- ctx2.logger("Noah-Poke").error(`Error sending noah stamp: ${error.message}`);
4398
- await session.sendQueued("Failed to send noah stamp.");
4399
- }
4400
- }
4401
- __name(sendRandomNoahStamp, "sendRandomNoahStamp");
4402
- async function sendRandomChatStamp(ctx2) {
4403
- try {
4404
- const stampsPath = getAssetPath(ctx2, "stamps/chat_stamp");
4405
- const stampFiles = fs3.readdirSync(stampsPath).filter((file) => isImageFile(file));
4406
- if (stampFiles.length === 0) {
4407
- return "No chat stamps found!";
4408
- }
4409
- const randomStamp = stampFiles[Math.floor(Math.random() * stampFiles.length)];
4410
- const stampPath = path2.join(stampsPath, randomStamp);
4411
- if (!fs3.existsSync(stampPath)) {
4412
- return "Selected stamp not found!";
4413
- }
4414
- const imageBuffer = fs3.readFileSync(stampPath);
4415
- return import_koishi8.h.image(imageBuffer, getMimeType(stampPath));
4416
- } catch (error) {
4417
- ctx2.logger("Noah-Poke").error(`Error sending chat stamp: ${error.message}`);
4418
- return "Failed to send chat stamp.";
4419
- }
4420
- }
4421
- __name(sendRandomChatStamp, "sendRandomChatStamp");
4422
- ctx.command("stamp").option("type", "-t [type]").option("voice", "-v", { fallback: false }).action(async ({ session, options }) => {
4423
- if (options.type == "noah") {
4424
- await sendRandomNoahStamp(ctx, session, options.voice);
4425
- } else if (options.type == "chat") {
4426
- return sendRandomChatStamp(ctx);
4427
- } else {
4428
- return sendRandomChatStamp(ctx);
4429
- }
4430
- });
4250
+ // src/fun/poke/commands/poke.ts
4251
+ function parsePlatform(target) {
4252
+ const index = target.indexOf(":");
4253
+ const platform = target.slice(0, index);
4254
+ const id = target.slice(index + 1);
4255
+ return [platform, id];
4256
+ }
4257
+ __name(parsePlatform, "parsePlatform");
4258
+ function registerPokeCommand(ctx) {
4431
4259
  ctx.platform("onebot").command("poke [target:user]").action(async ({ session }, target) => {
4432
4260
  if (!session.onebot) {
4433
4261
  return;
@@ -4435,7 +4263,7 @@ function apply7(ctx, config) {
4435
4263
  const params = { user_id: session.userId };
4436
4264
  if (target) {
4437
4265
  const [platform, id] = parsePlatform(target);
4438
- if (platform != "onebot") {
4266
+ if (platform !== "onebot") {
4439
4267
  return;
4440
4268
  }
4441
4269
  params.user_id = id;
@@ -4443,66 +4271,292 @@ function apply7(ctx, config) {
4443
4271
  if (session.isDirect) {
4444
4272
  await session.onebot._request("friend_poke", params);
4445
4273
  } else {
4446
- params["group_id"] = session.guildId;
4274
+ params.group_id = session.guildId;
4447
4275
  await session.onebot._request("group_poke", params);
4448
4276
  }
4449
4277
  });
4450
- ctx.platform("onebot").on("notice", async (session) => {
4451
- if (session.subtype != "poke") {
4278
+ }
4279
+ __name(registerPokeCommand, "registerPokeCommand");
4280
+
4281
+ // src/fun/poke/utils/stamp.ts
4282
+ var fs4 = __toESM(require("fs"), 1);
4283
+ var path3 = __toESM(require("path"), 1);
4284
+ var import_koishi8 = require("koishi");
4285
+
4286
+ // src/fun/poke/utils/file.ts
4287
+ var fs3 = __toESM(require("fs"), 1);
4288
+ var path2 = __toESM(require("path"), 1);
4289
+
4290
+ // src/fun/poke/constants.ts
4291
+ var IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".webp"];
4292
+ var MIME_MAP = {
4293
+ ".png": "image/png",
4294
+ ".jpg": "image/jpeg",
4295
+ ".jpeg": "image/jpeg",
4296
+ ".gif": "image/gif",
4297
+ ".webp": "image/webp"
4298
+ };
4299
+ var DEFAULT_MIME = "image/png";
4300
+ var DEFAULT_LOCALE = "zh-CN";
4301
+ var TIP_POOL = {
4302
+ "zh-CN": [
4303
+ "你知道吗: 《FIN4LE ~終止線の彼方へ~》在发布 337 天后才出现首个 PUC。",
4304
+ "你知道吗: Near 是双子中的姐姐哟~",
4305
+ "你知道吗: Noah 是双子中的妹妹哟~",
4306
+ "你知道吗: 可以看刘海方向来区分 Near 和 Noah。",
4307
+ "你知道吗: Near 和 Noah 就读于ボルテ学園初等部。",
4308
+ "你知道吗: 元气满满的是姐姐 Near,文静的是妹妹 Noah。",
4309
+ "你知道吗: Near 和 Noah 的兔子鞋是烈风刀送给她们的。",
4310
+ "你知道吗: Near 和 Noah 都会飞哟~",
4311
+ "你知道吗: Near 和 Noah 初登场于 BOOTH 代歌曲《freaky freak》。",
4312
+ "你知道吗: Near 和 Noah 的 CV 为 日高里菜。",
4313
+ "你知道吗: Near 和 Noah 的身高是 140 cm。",
4314
+ "你知道吗: Near 和 Noah 的生日是 6 月 10 日。"
4315
+ ],
4316
+ "en-US": [
4317
+ "Do you know: FIN4LE ~終止線の彼方へ~ took 337 days to get its first PUC.",
4318
+ "Do you know: Near is the older sister of the twin.",
4319
+ "Do you know: Noah is the younger sister of the twin.",
4320
+ "Do you know: You can tell Near and Noah apart by their hair direction.",
4321
+ "Do you know: Near and Noah attend ボルテ学園初等部.",
4322
+ "Do you know: The energetic Near is the older sister, while the quiet Noah is the younger sister.",
4323
+ "Do you know: Near and Noah received their rabbit shoes from 烈风刀.",
4324
+ "Do you know: Near and Noah can fly.",
4325
+ 'Do you know: Near and Noah made their debut in the BOOTH song "freaky freak".',
4326
+ "Do you know: Near and Noah's CV is 日高里菜.",
4327
+ "Do you know: Near and Noah's height is 140 cm.",
4328
+ "Do you know: Near and Noah's birthday is June 10th."
4329
+ ]
4330
+ };
4331
+
4332
+ // src/fun/poke/utils/file.ts
4333
+ function isImageFile(filename) {
4334
+ const ext = path2.extname(filename).toLowerCase();
4335
+ return IMAGE_EXTENSIONS.includes(ext);
4336
+ }
4337
+ __name(isImageFile, "isImageFile");
4338
+ function getMimeType(filename) {
4339
+ const ext = path2.extname(filename).toLowerCase();
4340
+ return MIME_MAP[ext] ?? DEFAULT_MIME;
4341
+ }
4342
+ __name(getMimeType, "getMimeType");
4343
+ function findMatchingAudio(imagePath) {
4344
+ try {
4345
+ const dir = path2.dirname(imagePath);
4346
+ const filename = path2.basename(imagePath);
4347
+ const match = filename.match(/_(\d+)\.(png|jpg|jpeg|gif|webp)$/i);
4348
+ if (!match) {
4349
+ return null;
4350
+ }
4351
+ const audioNumber = parseInt(match[1], 10).toString();
4352
+ const files = fs3.readdirSync(dir);
4353
+ const audioFile = files.find((file) => file.endsWith(`-${audioNumber}.mp3`));
4354
+ return audioFile ? path2.join(dir, audioFile) : null;
4355
+ } catch {
4356
+ return null;
4357
+ }
4358
+ }
4359
+ __name(findMatchingAudio, "findMatchingAudio");
4360
+
4361
+ // src/fun/poke/utils/random.ts
4362
+ function randomMessage(items) {
4363
+ if (items.length === 0) {
4364
+ return void 0;
4365
+ }
4366
+ const totalWeight = items.reduce((sum2, cur) => sum2 + cur.weight, 0);
4367
+ const random = Math.random() * totalWeight;
4368
+ let sum = 0;
4369
+ for (const item of items) {
4370
+ sum += item.weight;
4371
+ if (random < sum) return item;
4372
+ }
4373
+ return items[items.length - 1];
4374
+ }
4375
+ __name(randomMessage, "randomMessage");
4376
+ function pickRandom(items) {
4377
+ if (items.length === 0) {
4378
+ return void 0;
4379
+ }
4380
+ return items[Math.floor(Math.random() * items.length)];
4381
+ }
4382
+ __name(pickRandom, "pickRandom");
4383
+
4384
+ // src/fun/poke/utils/stamp.ts
4385
+ var LOGGER_NAME = "Noah-Poke";
4386
+ function collectNoahStamps(stampsPath) {
4387
+ const stampDirs = fs4.readdirSync(stampsPath).filter((dir) => dir.startsWith("stamp_"));
4388
+ const allStamps = [];
4389
+ for (const dir of stampDirs) {
4390
+ const stampDirPath = path3.join(stampsPath, dir);
4391
+ const stampFiles = fs4.readdirSync(stampDirPath).filter((file) => file.startsWith(dir) && isImageFile(file));
4392
+ stampFiles.forEach((file) => {
4393
+ allStamps.push({ path: path3.join(stampDirPath, file), dirName: dir });
4394
+ });
4395
+ }
4396
+ return allStamps;
4397
+ }
4398
+ __name(collectNoahStamps, "collectNoahStamps");
4399
+ async function sendRandomNoahStamp(ctx, session, voiceOnly = false) {
4400
+ const logger6 = ctx.logger(LOGGER_NAME);
4401
+ try {
4402
+ const stampsPath = getAssetPath(ctx, "stamps/noah_stamp");
4403
+ const allStamps = collectNoahStamps(stampsPath);
4404
+ if (allStamps.length === 0) {
4405
+ await session.sendQueued("No stamps found!");
4452
4406
  return;
4453
4407
  }
4454
- if (session.targetId != session.selfId) {
4408
+ const availableStamps = voiceOnly ? allStamps.filter((stamp) => {
4409
+ const audioPath2 = findMatchingAudio(stamp.path);
4410
+ return audioPath2 && fs4.existsSync(audioPath2);
4411
+ }) : allStamps;
4412
+ if (availableStamps.length === 0) {
4413
+ await session.sendQueued("No stamps with voice found!");
4455
4414
  return;
4456
4415
  }
4457
- if (pokeConfig2.interval > 0 && cache.has(session.userId)) {
4416
+ const randomStamp = pickRandom(availableStamps);
4417
+ logger6.debug(`Selected stamp from ${randomStamp.dirName}`);
4418
+ if (!fs4.existsSync(randomStamp.path)) {
4419
+ await session.sendQueued("Selected stamp not found!");
4420
+ return;
4421
+ }
4422
+ const imageBuffer = fs4.readFileSync(randomStamp.path);
4423
+ await session.sendQueued(import_koishi8.h.image(imageBuffer, getMimeType(randomStamp.path)));
4424
+ const audioPath = findMatchingAudio(randomStamp.path);
4425
+ if (audioPath && fs4.existsSync(audioPath)) {
4426
+ logger6.debug(`Found matching audio: ${path3.basename(audioPath)}`);
4427
+ const audioBuffer = fs4.readFileSync(audioPath);
4428
+ await session.sendQueued(import_koishi8.h.audio(audioBuffer, "audio/mpeg"));
4429
+ }
4430
+ } catch (error) {
4431
+ logger6.error(`Error sending noah stamp: ${error.message}`);
4432
+ await session.sendQueued("Failed to send noah stamp.");
4433
+ }
4434
+ }
4435
+ __name(sendRandomNoahStamp, "sendRandomNoahStamp");
4436
+ function getRandomChatStamp(ctx) {
4437
+ const logger6 = ctx.logger(LOGGER_NAME);
4438
+ try {
4439
+ const stampsPath = getAssetPath(ctx, "stamps/chat_stamp");
4440
+ const stampFiles = fs4.readdirSync(stampsPath).filter((file) => isImageFile(file));
4441
+ if (stampFiles.length === 0) {
4442
+ return "No chat stamps found!";
4443
+ }
4444
+ const randomStamp = pickRandom(stampFiles);
4445
+ const stampPath = path3.join(stampsPath, randomStamp);
4446
+ if (!fs4.existsSync(stampPath)) {
4447
+ return "Selected stamp not found!";
4448
+ }
4449
+ const imageBuffer = fs4.readFileSync(stampPath);
4450
+ return import_koishi8.h.image(imageBuffer, getMimeType(stampPath));
4451
+ } catch (error) {
4452
+ logger6.error(`Error sending chat stamp: ${error.message}`);
4453
+ return "Failed to send chat stamp.";
4454
+ }
4455
+ }
4456
+ __name(getRandomChatStamp, "getRandomChatStamp");
4457
+
4458
+ // src/fun/poke/commands/stamp.ts
4459
+ function registerStampCommand(ctx) {
4460
+ ctx.command("stamp").option("type", "-t [type]").option("voice", "-v", { fallback: false }).action(async ({ session, options }) => {
4461
+ if (options.type === "noah") {
4462
+ await sendRandomNoahStamp(ctx, session, options.voice);
4463
+ return;
4464
+ }
4465
+ return getRandomChatStamp(ctx);
4466
+ });
4467
+ }
4468
+ __name(registerStampCommand, "registerStampCommand");
4469
+
4470
+ // src/fun/poke/events/notice.ts
4471
+ var import_koishi9 = require("koishi");
4472
+
4473
+ // src/fun/poke/utils/tip.ts
4474
+ async function pickTip(session) {
4475
+ const user = await session.observeUser(["locales"]);
4476
+ const locales = user.locales ?? [];
4477
+ for (const locale2 of locales) {
4478
+ const tips = TIP_POOL[locale2];
4479
+ if (tips && tips.length > 0) {
4480
+ return pickRandom(tips);
4481
+ }
4482
+ }
4483
+ return pickRandom(TIP_POOL[DEFAULT_LOCALE] ?? []);
4484
+ }
4485
+ __name(pickTip, "pickTip");
4486
+
4487
+ // src/fun/poke/events/notice.ts
4488
+ function registerPokeNotice(ctx, config, cache) {
4489
+ ctx.platform("onebot").on("notice", async (session) => {
4490
+ if (session.subtype !== "poke" || session.targetId !== session.selfId) {
4491
+ return;
4492
+ }
4493
+ if (config.interval > 0 && cache.has(session.userId)) {
4458
4494
  const ts = cache.get(session.userId);
4459
- if (session.timestamp - ts < pokeConfig2.interval) {
4460
- if (pokeConfig2.warning) {
4461
- const msg = randomMessage(pokeConfig2.prompt);
4462
- const content = import_koishi8.h.parse(msg, session);
4463
- session.sendQueued(content);
4495
+ if (session.timestamp - ts < config.interval) {
4496
+ if (config.warning) {
4497
+ const msg2 = randomMessage(config.prompt);
4498
+ if (msg2) {
4499
+ await session.sendQueued(import_koishi9.h.parse(msg2.content, session));
4500
+ }
4464
4501
  }
4465
4502
  return;
4466
4503
  }
4467
4504
  }
4468
4505
  cache.set(session.userId, session.timestamp);
4469
- if (pokeConfig2.messages.length > 0) {
4470
- const msg = randomMessage(pokeConfig2.messages);
4471
- const content = import_koishi8.h.parse(msg, session);
4472
- await session.sendQueued(content);
4506
+ if (config.messages.length === 0) {
4507
+ return;
4508
+ }
4509
+ const msg = randomMessage(config.messages);
4510
+ if (!msg) {
4511
+ return;
4512
+ }
4513
+ if (msg.type === "noah") {
4514
+ await sendRandomNoahStamp(ctx, session);
4515
+ } else if (msg.type === "chat") {
4516
+ await session.sendQueued(getRandomChatStamp(ctx));
4517
+ } else {
4518
+ const tip = await pickTip(session);
4519
+ if (tip) {
4520
+ await session.sendQueued(import_koishi9.h.parse(tip, session));
4521
+ }
4473
4522
  }
4474
4523
  });
4475
4524
  }
4476
- __name(apply7, "apply");
4477
- function randomMessage(messages) {
4478
- const totalWeight = messages.reduce((sum2, cur) => sum2 + cur.weight, 0);
4479
- const random = Math.random() * totalWeight;
4480
- let sum = 0;
4481
- for (const message of messages) {
4482
- sum += message.weight;
4483
- if (random < sum) return message.content;
4484
- }
4485
- }
4486
- __name(randomMessage, "randomMessage");
4487
- function parsePlatform(target) {
4488
- const index = target.indexOf(":");
4489
- const platform = target.slice(0, index);
4490
- const id = target.slice(index + 1);
4491
- return [platform, id];
4525
+ __name(registerPokeNotice, "registerPokeNotice");
4526
+
4527
+ // src/fun/poke/locales/en-US.yml
4528
+ var en_US_default3 = { _config: { $desc: "Poke Module Settings", interval: "最小触发间隔(毫秒)", warning: "频繁触发是否发送警告", prompt: "警告内容", messages: { $desc: "消息内容", type: "Type (text=random tip / noah=voice stamp / chat=chat stamp)", weight: "权重" } }, commands: { poke: { description: "poke" } } };
4529
+
4530
+ // src/fun/poke/locales/zh-CN.yml
4531
+ var zh_CN_default3 = { _config: { $desc: "Poke 模块设置", interval: "最小触发间隔(毫秒)", warning: "频繁触发是否发送警告", prompt: { $desc: "警告内容", content: "消息", weight: "权重" }, messages: { $desc: "消息内容", type: "类型(text=随机提示 / noah=语音表情 / chat=聊天表情)", weight: "权重" } }, commands: { poke: { description: "戳一戳" } } };
4532
+
4533
+ // src/fun/poke/index.ts
4534
+ var name7 = "Noah-Poke";
4535
+ var logger3 = new import_koishi10.Logger("Noah-Poke");
4536
+ function apply7(ctx, config) {
4537
+ ;
4538
+ [
4539
+ ["en-US", en_US_default3],
4540
+ ["zh-CN", zh_CN_default3]
4541
+ ].forEach(([lang, file]) => ctx.i18n.define(lang, file));
4542
+ const cache = /* @__PURE__ */ new Map();
4543
+ registerStampCommand(ctx);
4544
+ registerPokeCommand(ctx);
4545
+ registerPokeNotice(ctx, config.poke, cache);
4492
4546
  }
4493
- __name(parsePlatform, "parsePlatform");
4547
+ __name(apply7, "apply");
4494
4548
 
4495
4549
  // src/games/general/index.ts
4496
4550
  var general_exports = {};
4497
4551
  __export(general_exports, {
4498
4552
  apply: () => apply8,
4499
- logger: () => logger3,
4553
+ logger: () => logger4,
4500
4554
  name: () => name8
4501
4555
  });
4502
- var import_koishi10 = require("koishi");
4556
+ var import_koishi12 = require("koishi");
4503
4557
 
4504
4558
  // src/games/general/events/quote.ts
4505
- var import_koishi9 = require("koishi");
4559
+ var import_koishi11 = require("koishi");
4506
4560
 
4507
4561
  // src/games/general/utils/codeReader.ts
4508
4562
  async function readCode128(ctx, barcodeApiUrl, imageUrl) {
@@ -4528,8 +4582,8 @@ __name(readCode128, "readCode128");
4528
4582
  function quote(ctx, config) {
4529
4583
  ctx.on("message", async (session) => {
4530
4584
  if (session.quote && session.quote.user.id === session.selfId) {
4531
- const images = await import_koishi9.h.select(session.quote.elements, "img");
4532
- const textElements = await import_koishi9.h.select(session.elements, "text");
4585
+ const images = await import_koishi11.h.select(session.quote.elements, "img");
4586
+ const textElements = await import_koishi11.h.select(session.elements, "text");
4533
4587
  const allText = textElements.map((el) => el.attrs?.content || "").join(" ");
4534
4588
  if (images.length === 1) {
4535
4589
  const imageUrl = images[0].attrs.src;
@@ -4555,7 +4609,7 @@ __name(quote, "quote");
4555
4609
 
4556
4610
  // src/games/general/index.ts
4557
4611
  var name8 = "Noah-General";
4558
- var logger3 = new import_koishi10.Logger("Noah-General");
4612
+ var logger4 = new import_koishi12.Logger("Noah-General");
4559
4613
  async function apply8(ctx, config) {
4560
4614
  quote(ctx, config.general);
4561
4615
  }
@@ -4566,10 +4620,10 @@ var sdvx_exports = {};
4566
4620
  __export(sdvx_exports, {
4567
4621
  apply: () => apply13,
4568
4622
  inject: () => inject3,
4569
- logger: () => logger4,
4623
+ logger: () => logger5,
4570
4624
  name: () => name13
4571
4625
  });
4572
- var import_koishi19 = require("koishi");
4626
+ var import_koishi21 = require("koishi");
4573
4627
 
4574
4628
  // src/servers/index.ts
4575
4629
  var servers_exports = {};
@@ -4581,7 +4635,7 @@ __export(servers_exports, {
4581
4635
  });
4582
4636
 
4583
4637
  // src/servers/Asphyxia/index.ts
4584
- var import_koishi11 = require("koishi");
4638
+ var import_koishi13 = require("koishi");
4585
4639
  var Asphyxia = class {
4586
4640
  static {
4587
4641
  __name(this, "Asphyxia");
@@ -4589,11 +4643,11 @@ var Asphyxia = class {
4589
4643
  name = "asphyxia";
4590
4644
  supportedGames = ["sdvx", "iidx"];
4591
4645
  gameServices = {};
4592
- logger = new import_koishi11.Logger("Noah-Asphyxia");
4646
+ logger = new import_koishi13.Logger("Noah-Asphyxia");
4593
4647
  };
4594
4648
 
4595
4649
  // src/servers/Mao/index.ts
4596
- var import_koishi12 = require("koishi");
4650
+ var import_koishi14 = require("koishi");
4597
4651
  var Mao = class {
4598
4652
  static {
4599
4653
  __name(this, "Mao");
@@ -4601,11 +4655,11 @@ var Mao = class {
4601
4655
  name = "mao";
4602
4656
  supportedGames = ["sdvx"];
4603
4657
  gameServices = {};
4604
- logger = new import_koishi12.Logger("Noah-Mao");
4658
+ logger = new import_koishi14.Logger("Noah-Mao");
4605
4659
  };
4606
4660
 
4607
4661
  // src/servers/Official/index.ts
4608
- var import_koishi13 = require("koishi");
4662
+ var import_koishi15 = require("koishi");
4609
4663
  var Official = class {
4610
4664
  static {
4611
4665
  __name(this, "Official");
@@ -4613,7 +4667,7 @@ var Official = class {
4613
4667
  name = "official";
4614
4668
  supportedGames = ["sdvx"];
4615
4669
  gameServices = {};
4616
- logger = new import_koishi13.Logger("Noah-Official");
4670
+ logger = new import_koishi15.Logger("Noah-Official");
4617
4671
  };
4618
4672
 
4619
4673
  // src/servers/ServerFactory.ts
@@ -4981,13 +5035,13 @@ var AsphyxiaSDVXService = class _AsphyxiaSDVXService {
4981
5035
  logger;
4982
5036
  config;
4983
5037
  cachedModel = null;
4984
- constructor(logger5, config) {
4985
- this.logger = logger5;
5038
+ constructor(logger6, config) {
5039
+ this.logger = logger6;
4986
5040
  this.config = config;
4987
5041
  }
4988
- static getInstance(logger5, config) {
5042
+ static getInstance(logger6, config) {
4989
5043
  if (!_AsphyxiaSDVXService.instance) {
4990
- _AsphyxiaSDVXService.instance = new _AsphyxiaSDVXService(logger5, config);
5044
+ _AsphyxiaSDVXService.instance = new _AsphyxiaSDVXService(logger6, config);
4991
5045
  }
4992
5046
  return _AsphyxiaSDVXService.instance;
4993
5047
  }
@@ -5134,12 +5188,12 @@ var MaoSDVXService = class _MaoSDVXService {
5134
5188
  }
5135
5189
  static instance;
5136
5190
  logger;
5137
- constructor(logger5) {
5138
- this.logger = logger5;
5191
+ constructor(logger6) {
5192
+ this.logger = logger6;
5139
5193
  }
5140
- static getInstance(logger5) {
5194
+ static getInstance(logger6) {
5141
5195
  if (!_MaoSDVXService.instance) {
5142
- _MaoSDVXService.instance = new _MaoSDVXService(logger5);
5196
+ _MaoSDVXService.instance = new _MaoSDVXService(logger6);
5143
5197
  }
5144
5198
  return _MaoSDVXService.instance;
5145
5199
  }
@@ -5484,12 +5538,12 @@ var OfficialSDVXService = class _OfficialSDVXService {
5484
5538
  }
5485
5539
  static instance;
5486
5540
  logger;
5487
- constructor(logger5) {
5488
- this.logger = logger5;
5541
+ constructor(logger6) {
5542
+ this.logger = logger6;
5489
5543
  }
5490
- static getInstance(logger5) {
5544
+ static getInstance(logger6) {
5491
5545
  if (!_OfficialSDVXService.instance) {
5492
- _OfficialSDVXService.instance = new _OfficialSDVXService(logger5);
5546
+ _OfficialSDVXService.instance = new _OfficialSDVXService(logger6);
5493
5547
  }
5494
5548
  return _OfficialSDVXService.instance;
5495
5549
  }
@@ -5594,15 +5648,15 @@ var OfficialSDVXService = class _OfficialSDVXService {
5594
5648
  };
5595
5649
 
5596
5650
  // src/games/sdvx/adapters/index.ts
5597
- function registerSDVXAdapters(logger5, config) {
5651
+ function registerSDVXAdapters(logger6, config) {
5598
5652
  const serverManager = ServerManager.getInstance();
5599
5653
  serverManager.registerGameService(
5600
5654
  "asphyxia",
5601
5655
  "sdvx",
5602
- AsphyxiaSDVXService.getInstance(logger5, config)
5656
+ AsphyxiaSDVXService.getInstance(logger6, config)
5603
5657
  );
5604
- serverManager.registerGameService("mao", "sdvx", MaoSDVXService.getInstance(logger5));
5605
- serverManager.registerGameService("official", "sdvx", OfficialSDVXService.getInstance(logger5));
5658
+ serverManager.registerGameService("mao", "sdvx", MaoSDVXService.getInstance(logger6));
5659
+ serverManager.registerGameService("official", "sdvx", OfficialSDVXService.getInstance(logger6));
5606
5660
  }
5607
5661
  __name(registerSDVXAdapters, "registerSDVXAdapters");
5608
5662
 
@@ -5614,7 +5668,7 @@ __export(command_exports2, {
5614
5668
  });
5615
5669
 
5616
5670
  // src/games/sdvx/commands/calculate.ts
5617
- var import_koishi14 = require("koishi");
5671
+ var import_koishi16 = require("koishi");
5618
5672
 
5619
5673
  // src/games/sdvx/utils/param-parser.ts
5620
5674
  function parseNumberWithSuffix(str) {
@@ -6133,7 +6187,7 @@ function parseQueryInput(input) {
6133
6187
  __name(parseQueryInput, "parseQueryInput");
6134
6188
 
6135
6189
  // src/games/sdvx/commands/calculate.ts
6136
- function calculate(ctx, config, logger5) {
6190
+ function calculate(ctx, config, logger6) {
6137
6191
  ctx.command("sdvx.calculate <query:text>").alias("sdvx.cal").action(async ({ session, options }, query) => {
6138
6192
  try {
6139
6193
  let queryInput = query;
@@ -6167,7 +6221,7 @@ function calculate(ctx, config, logger5) {
6167
6221
  lossless: true
6168
6222
  }
6169
6223
  );
6170
- return import_koishi14.h.image(imageBuffer, "image/png");
6224
+ return import_koishi16.h.image(imageBuffer, "image/png");
6171
6225
  } catch (error) {
6172
6226
  ctx.logger("SDVX-Calculate").warn(error);
6173
6227
  return session.text(".error");
@@ -6177,7 +6231,7 @@ function calculate(ctx, config, logger5) {
6177
6231
  __name(calculate, "calculate");
6178
6232
 
6179
6233
  // src/games/sdvx/commands/chart.ts
6180
- var import_koishi15 = require("koishi");
6234
+ var import_koishi17 = require("koishi");
6181
6235
  function mapArrangementToken(tok) {
6182
6236
  const t = tok.toLowerCase();
6183
6237
  if (t === "ran" || t === "random") return "random";
@@ -6260,7 +6314,7 @@ function getHighestDifstr(diffs) {
6260
6314
  return diffs[diffs.length - 1].difstr;
6261
6315
  }
6262
6316
  __name(getHighestDifstr, "getHighestDifstr");
6263
- function chart(ctx, config, logger5) {
6317
+ function chart(ctx, config, logger6) {
6264
6318
  ctx.command("sdvx.chart [query:text]").alias("sdvx.c").action(async ({ session }, query) => {
6265
6319
  if (!query) {
6266
6320
  await session.send(session.text(".prompt"));
@@ -6323,7 +6377,7 @@ function chart(ctx, config, logger5) {
6323
6377
  const res = await ctx.http.post(`${config.sdvx_data_url}/chart`, payload, {
6324
6378
  headers: { "Content-Type": "application/json" }
6325
6379
  });
6326
- return import_koishi15.h.image(res, "image/png");
6380
+ return import_koishi17.h.image(res, "image/png");
6327
6381
  } else {
6328
6382
  const {
6329
6383
  diffStr: parsedDiff,
@@ -6339,7 +6393,7 @@ function chart(ctx, config, logger5) {
6339
6393
  const picked = musicInfo[0];
6340
6394
  const music_id = Number(picked?.id);
6341
6395
  if (!Number.isFinite(music_id)) {
6342
- logger5.warn("search result missing id", picked);
6396
+ logger6.warn("search result missing id", picked);
6343
6397
  return session.text(".error");
6344
6398
  }
6345
6399
  let difstr = null;
@@ -6373,10 +6427,10 @@ function chart(ctx, config, logger5) {
6373
6427
  const res = await ctx.http.post(`${config.sdvx_data_url}/chart`, payload, {
6374
6428
  headers: { "Content-Type": "application/json" }
6375
6429
  });
6376
- return import_koishi15.h.image(res, "image/png");
6430
+ return import_koishi17.h.image(res, "image/png");
6377
6431
  }
6378
6432
  } catch (err) {
6379
- logger5.warn(err);
6433
+ logger6.warn(err);
6380
6434
  return session.text(".error");
6381
6435
  }
6382
6436
  });
@@ -6384,7 +6438,7 @@ function chart(ctx, config, logger5) {
6384
6438
  __name(chart, "chart");
6385
6439
 
6386
6440
  // src/core/utils/selector.ts
6387
- var import_koishi16 = require("koishi");
6441
+ var import_koishi18 = require("koishi");
6388
6442
  async function selectCard(session, cardService, uid) {
6389
6443
  const userCards = await cardService.getCardsByUid(uid);
6390
6444
  if (userCards.length === 0) {
@@ -6400,7 +6454,7 @@ async function selectCard(session, cardService, uid) {
6400
6454
  cardListMsg += `<p>${i + 1}. ${userCards[i].name}</p>`;
6401
6455
  }
6402
6456
  }
6403
- const msg = import_koishi16.h.unescape(session.text("selector.menu-select", { card_list: cardListMsg }));
6457
+ const msg = import_koishi18.h.unescape(session.text("selector.menu-select", { card_list: cardListMsg }));
6404
6458
  await session.send(msg);
6405
6459
  const select = await session.prompt();
6406
6460
  if (!select) return { ok: false, message: session.text("commands.timeout") };
@@ -6428,7 +6482,7 @@ async function selectServer(session, serverService, uid, channelId) {
6428
6482
  serverListMsg += `<p>${i + 1}. ${servers[i].name} (${servers[i].type})</p>`;
6429
6483
  }
6430
6484
  }
6431
- const msg = import_koishi16.h.unescape(
6485
+ const msg = import_koishi18.h.unescape(
6432
6486
  session.text("selector.server-menu-select", { server_list: serverListMsg })
6433
6487
  );
6434
6488
  await session.send(msg);
@@ -6526,17 +6580,18 @@ var ScoreService = class _ScoreService {
6526
6580
  calcSongRadarContribution(score, category) {
6527
6581
  const { difficulty_data } = score;
6528
6582
  if (!difficulty_data?.radar || !difficulty_data.max_exscore) return 0;
6529
- const L = Math.floor(difficulty_data.difnum);
6583
+ const L = Math.max(1, Math.min(20, Math.floor(difficulty_data.difnum)));
6530
6584
  const R = difficulty_data.radar[category];
6531
6585
  const S = score.music.score;
6532
6586
  const E = score.music.exscore;
6533
6587
  const Emax = difficulty_data.max_exscore;
6534
- const P = Math.min(2 * (L + 31), 100);
6588
+ const P = Math.min(100, Math.max(0, 60 + 2 * L));
6535
6589
  const B = Math.floor(3 * S * R / (4 * 1e7));
6536
- const H = Math.floor((20 - L) / 2);
6537
- const G = Math.max(1e3 + 2 * 2 ** H * (E - Emax), 0);
6590
+ const H = Math.floor(Math.max(1, 21 - L) / 2);
6591
+ const G = Emax > 0 && E <= Emax ? Math.max(0, 1e3 + 2 * (E - Emax) * (1 << H)) : 0;
6538
6592
  const X = Math.floor(R * G / 4e3);
6539
- return P * (B + X);
6593
+ const completedAxis = Math.min(R, B + X);
6594
+ return P * completedAxis;
6540
6595
  }
6541
6596
  /**
6542
6597
  * 计算玩家六维雷达(显示值,如 200.00)
@@ -6565,8 +6620,8 @@ var ScoreService = class _ScoreService {
6565
6620
  };
6566
6621
 
6567
6622
  // src/games/sdvx/commands/radar.ts
6568
- function radar(ctx, config, logger5) {
6569
- ctx.command("sdvx.radar").userFields(["defaultCardId", "defaultServerId", "id"]).channelFields(["defaultServerId", "id"]).option("card", "-c").option("server", "-s").action(async ({ session, options }) => {
6623
+ function radar(ctx, config, logger6) {
6624
+ ctx.command("sdvx.radar").userFields(["id"]).channelFields(["id"]).option("card", "-c").option("server", "-s").action(async ({ session, options }) => {
6570
6625
  const atGuild = session.guildId != null;
6571
6626
  const cardService = new CardService(ctx);
6572
6627
  const serverService = new ServerService(ctx);
@@ -6631,17 +6686,17 @@ function radar(ctx, config, logger5) {
6631
6686
  one_hand: radarResult.one_hand.toFixed(2)
6632
6687
  });
6633
6688
  } catch (error) {
6634
- logger5.warn(error);
6635
- return session.text(".error");
6689
+ logger6.warn(error);
6690
+ return session.text(".error", { card: card2.name, server: server2.name });
6636
6691
  }
6637
6692
  });
6638
6693
  }
6639
6694
  __name(radar, "radar");
6640
6695
 
6641
6696
  // src/games/sdvx/commands/recent.ts
6642
- var import_koishi17 = require("koishi");
6643
- function recent(ctx, config, logger5) {
6644
- ctx.command("sdvx.recent [count:number]").alias("sdvx.r").userFields(["defaultCardId", "defaultServerId", "id"]).channelFields(["defaultServerId", "id"]).option("lossless", "-l").option("card", "-c").option("server", "-s").action(async ({ session, options }, count) => {
6697
+ var import_koishi19 = require("koishi");
6698
+ function recent(ctx, config, logger6) {
6699
+ ctx.command("sdvx.recent [count:number]").alias("sdvx.r").userFields(["id"]).channelFields(["id"]).option("lossless", "-l").option("card", "-c").option("server", "-s").action(async ({ session, options }, count) => {
6645
6700
  const atGuild = session.guildId != null;
6646
6701
  if (!count) count = 1;
6647
6702
  const cardService = new CardService(ctx);
@@ -6710,19 +6765,19 @@ function recent(ctx, config, logger5) {
6710
6765
  }
6711
6766
  );
6712
6767
  if (options.lossless) {
6713
- return import_koishi17.h.image(imageBuffer, "image/png");
6768
+ return import_koishi19.h.image(imageBuffer, "image/png");
6714
6769
  }
6715
- return import_koishi17.h.image(imageBuffer, "image/jpg");
6770
+ return import_koishi19.h.image(imageBuffer, "image/jpg");
6716
6771
  } catch (error) {
6717
- logger5.warn(error);
6718
- return session.text(".error");
6772
+ logger6.warn(error);
6773
+ return session.text(".error", { card: card2.name, server: server2.name });
6719
6774
  }
6720
6775
  });
6721
6776
  }
6722
6777
  __name(recent, "recent");
6723
6778
 
6724
6779
  // src/games/sdvx/commands/sync.ts
6725
- function sync(ctx, config, logger5) {
6780
+ function sync(ctx, config, logger6) {
6726
6781
  ctx.command("sdvx.sync").userFields(["id"]).channelFields(["id"]).action(async ({ session }) => {
6727
6782
  const serverService = new ServerService(ctx);
6728
6783
  const cardService = new CardService(ctx);
@@ -6797,7 +6852,7 @@ function sync(ctx, config, logger5) {
6797
6852
  const maoSdvxService = serverManager.getGameService("mao", "sdvx");
6798
6853
  const maoVerifyUrl = "https://maomani.cn";
6799
6854
  if (!maoSdvxService || typeof maoSdvxService.verifyPin !== "function") {
6800
- logger5.warn("Mao SDVX service does not support PIN verification");
6855
+ logger6.warn("Mao SDVX service does not support PIN verification");
6801
6856
  return session.text(".pin-verify-error");
6802
6857
  }
6803
6858
  const existingPin = await ctx.database.get("sdvx_pin_verified", {
@@ -6818,7 +6873,7 @@ function sync(ctx, config, logger5) {
6818
6873
  pinVerified = true;
6819
6874
  }
6820
6875
  } catch (error) {
6821
- logger5.warn(error);
6876
+ logger6.warn(error);
6822
6877
  }
6823
6878
  }
6824
6879
  if (!pinVerified) {
@@ -6854,7 +6909,7 @@ function sync(ctx, config, logger5) {
6854
6909
  })
6855
6910
  );
6856
6911
  } catch (error) {
6857
- logger5.warn(error);
6912
+ logger6.warn(error);
6858
6913
  await session.send(session.text(".pin-verify-error"));
6859
6914
  }
6860
6915
  }
@@ -6876,8 +6931,11 @@ function sync(ctx, config, logger5) {
6876
6931
  config
6877
6932
  );
6878
6933
  } catch (error) {
6879
- logger5.warn(error);
6880
- return session.text(".fetch-error");
6934
+ logger6.warn(error);
6935
+ return session.text(".fetch-error", {
6936
+ card: sourceCard.name,
6937
+ server: sourceServer.name
6938
+ });
6881
6939
  }
6882
6940
  if (!scoreList || scoreList.length === 0) {
6883
6941
  return session.text(".no-scores");
@@ -6898,12 +6956,15 @@ function sync(ctx, config, logger5) {
6898
6956
  scoreList
6899
6957
  );
6900
6958
  if (!ok) {
6901
- logger5.warn("Mao SDVX uploadScore returned falsy result");
6959
+ logger6.warn("Mao SDVX uploadScore returned falsy result");
6902
6960
  return session.text(".sync-failed");
6903
6961
  }
6904
6962
  } catch (error) {
6905
- logger5.warn(error);
6906
- return session.text(".sync-error");
6963
+ logger6.warn(error);
6964
+ return session.text(".sync-error", {
6965
+ card: targetCard.name,
6966
+ server: maoServer.name
6967
+ });
6907
6968
  }
6908
6969
  return session.text(".selected-summary", {
6909
6970
  source_server_name: sourceServer.name,
@@ -6917,8 +6978,8 @@ function sync(ctx, config, logger5) {
6917
6978
  __name(sync, "sync");
6918
6979
 
6919
6980
  // src/games/sdvx/commands/vf.ts
6920
- var fs4 = __toESM(require("fs"), 1);
6921
- var import_koishi18 = require("koishi");
6981
+ var fs5 = __toESM(require("fs"), 1);
6982
+ var import_koishi20 = require("koishi");
6922
6983
 
6923
6984
  // src/games/sdvx/utils/filter.ts
6924
6985
  function parseFilterQuery(query) {
@@ -6971,8 +7032,8 @@ function parseFilterQuery(query) {
6971
7032
  __name(parseFilterQuery, "parseFilterQuery");
6972
7033
 
6973
7034
  // src/games/sdvx/commands/vf.ts
6974
- function vf(ctx, config, logger5) {
6975
- ctx.command("vf").userFields(["defaultCardId", "defaultServerId", "id"]).channelFields(["defaultServerId", "id"]).option("lossless", "-l").option("card", "-c").option("server", "-s").option("filter", "-f <query:text>").action(async ({ session, options }) => {
7035
+ function vf(ctx, config, logger6) {
7036
+ ctx.command("vf").userFields(["id"]).channelFields(["id"]).option("lossless", "-l").option("card", "-c").option("server", "-s").option("filter", "-f <query:text>").action(async ({ session, options }) => {
6976
7037
  const atGuild = session.guildId != null;
6977
7038
  const cardService = new CardService(ctx);
6978
7039
  const serverService = new ServerService(ctx);
@@ -7046,9 +7107,9 @@ function vf(ctx, config, logger5) {
7046
7107
  }
7047
7108
  );
7048
7109
  if (options.lossless) {
7049
- session.send(import_koishi18.h.file(imageBuffer, "image/png"));
7110
+ session.send(import_koishi20.h.file(imageBuffer, "image/png"));
7050
7111
  } else {
7051
- session.send(import_koishi18.h.image(imageBuffer, "image/jpg"));
7112
+ session.send(import_koishi20.h.image(imageBuffer, "image/jpg"));
7052
7113
  }
7053
7114
  const sortedScores = [...best50ScoreList].sort((a, b) => b.extra.volforce - a.extra.volforce).slice(0, 50);
7054
7115
  const total = sortedScores.reduce((sum, score) => sum + score.extra.volforce, 0);
@@ -7075,21 +7136,21 @@ function vf(ctx, config, logger5) {
7075
7136
  ctx,
7076
7137
  "stamps/noah_stamp/stamp_0385/stamp_0385_02.png"
7077
7138
  );
7078
- if (fs4.existsSync(audioPath)) {
7079
- const audioBuffer = fs4.readFileSync(audioPath);
7080
- session.send(import_koishi18.h.audio(audioBuffer, "audio/mpeg"));
7139
+ if (fs5.existsSync(audioPath)) {
7140
+ const audioBuffer = fs5.readFileSync(audioPath);
7141
+ session.send(import_koishi20.h.audio(audioBuffer, "audio/mpeg"));
7081
7142
  }
7082
- if (fs4.existsSync(imagePath)) {
7083
- const imageBuffer2 = fs4.readFileSync(imagePath);
7084
- session.send(import_koishi18.h.image(imageBuffer2, "image/png"));
7143
+ if (fs5.existsSync(imagePath)) {
7144
+ const imageBuffer2 = fs5.readFileSync(imagePath);
7145
+ session.send(import_koishi20.h.image(imageBuffer2, "image/png"));
7085
7146
  }
7086
7147
  } catch (error) {
7087
- logger5.warn(`Failed to send celebration files: ${error.message}`);
7148
+ logger6.warn(`Failed to send celebration files: ${error.message}`);
7088
7149
  }
7089
7150
  }
7090
7151
  } catch (error) {
7091
- logger5.warn(error);
7092
- return session.text(".error");
7152
+ logger6.warn(error);
7153
+ return session.text(".error", { card: card2.name, server: server2.name });
7093
7154
  }
7094
7155
  return;
7095
7156
  });
@@ -7100,12 +7161,12 @@ __name(vf, "vf");
7100
7161
  var name10 = "command";
7101
7162
  function apply10(ctx, config) {
7102
7163
  ctx.command("sdvx").alias("s");
7103
- vf(ctx, config, logger4);
7104
- recent(ctx, config, logger4);
7105
- chart(ctx, config, logger4);
7106
- calculate(ctx, config, logger4);
7107
- sync(ctx, config, logger4);
7108
- radar(ctx, config, logger4);
7164
+ vf(ctx, config, logger5);
7165
+ recent(ctx, config, logger5);
7166
+ chart(ctx, config, logger5);
7167
+ calculate(ctx, config, logger5);
7168
+ sync(ctx, config, logger5);
7169
+ radar(ctx, config, logger5);
7109
7170
  }
7110
7171
  __name(apply10, "apply");
7111
7172
 
@@ -7145,22 +7206,22 @@ function apply12(ctx) {
7145
7206
  __name(apply12, "apply");
7146
7207
 
7147
7208
  // src/games/sdvx/locales/en-US.yml
7148
- var en_US_default4 = { _config: { $desc: "SDVX Module Settings", sdvx_data_url: "<p>The URL of the SDVX data service</p>", sdvx_search_url: "<p>The URL of the SDVX search service</p>", official_support_url: "<p>The URL of the SDVX official support service</p>" }, commands: { vf: { description: "Show Noah help information", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing {name} [{difstr}], please wait patiently~</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "server-menu-select": "<p>Please select the server you want to use:</p>\n{server_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>" } }, sdvx: { recent: { description: "Show recent scores", messages: { "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "server-menu-select": "<p>Please select the server you want to use:</p>\n{server_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", quit: "<p>Exited~</p>" } }, chart: { description: "Show SDVX chart", messages: { prompt: "<p>Which song's chart would you like to view?</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", "no-result": "<p>Aww, Noah couldn’t find that song~ try another keyword, okay?</p>" } }, calculate: { description: "Calculate volforce value or score", messages: { "invalid-query": "<p>Invalid query parameters, please check your input~</p>", "no-results": "<p>No results found~</p>", "too-many-results": "<p>Too many results! Found {0} results, please narrow down your query (current limit: 500 results)</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", error: "<p>An error occurred(っ °Д °;)っ</p>" } }, radar: { description: "Show player radar stats", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "server-menu-select": "<p>Please select the server you want to use:</p>\n{server_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>", result: "<p>{name}'s Radar</p>\n<p>NOTES: {notes}</p>\n<p>PEAK: {peak}</p>\n<p>TSUMAMI: {tsumami}</p>\n<p>TRICKY: {tricky}</p>\n<p>HAND-TRIP: {hand_trip}</p>\n<p>ONE-HAND: {one_hand}</p>" } }, sync: { description: "Sync scores to Mao", messages: { "mao-not-found": "<p>Mao server not found. Please add a Mao server first, then try syncing again.</p>", "source-server-not-found": "<p>No available source servers. Please add a server first.</p>", "source-server-select": "<p>Please choose the source server:</p>\n{server_list}\n<p>q. Exit</p>", "card-not-found": "<p>You haven't bound any card yet. Please bind a card first.</p>", "source-card-select": "<p>Please choose the source card:</p>\n{card_list}\n<p>q. Exit</p>", "target-card-select": "<p>Please choose the target card (sync to Mao):</p>\n{card_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Sync cancelled.</p>", "same-card-error": "<p>When the source server is Mao, the source card and target card cannot be the same. Please choose again.</p>", "dm-only": "<p>For security, please use this command in a private chat.</p>", "pin-prompt": "<p>Please enter the Mao PIN (4 digits):</p>\n<p>q. Exit</p>", "pin-invalid": "<p>Invalid PIN format. Please enter 4 digits.</p>", "pin-verify-failed": "<p>PIN verification failed: {message}</p>", "pin-verify-error": "<p>PIN verification error. Please try again later.</p>", "pin-too-many": "<p>Too many PIN attempts. Please try again later.</p>", "fetch-error": "<p>Failed to fetch scores from the source server. Please try again later.</p>", "no-scores": "<p>No scores available for sync.</p>", "confirm-sync": "<p>Found {score_count} scores. Start sync?</p>\n<p>Type y to confirm, any other key to cancel.</p>", "sync-error": "<p>Error occurred during sync(っ °Д °;)っ</p>", "sync-failed": "<p>Sync failed(っ °Д °;)っ</p>", "selected-summary": "<p>Sync completedヾ(≧▽≦*)o</p>\n<p>Source server: {source_server_name} ({source_server_type})</p>\n<p>Source card: {source_card_name}</p>\n<p>Target card: {target_card_name}</p>\n<p>Tracks synced: {score_count}</p>" } } } } };
7209
+ var en_US_default4 = { _config: { $desc: "SDVX Module Settings", sdvx_data_url: "<p>The URL of the SDVX data service</p>", sdvx_search_url: "<p>The URL of the SDVX search service</p>", official_support_url: "<p>The URL of the SDVX official support service</p>" }, commands: { vf: { description: "Show Noah help information", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred while using card: {card}, server: {server} (っ °Д °;)っ</p>", drawing: "<p>Noah is drawing {name} [{difstr}], please wait patiently~</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "server-menu-select": "<p>Please select the server you want to use:</p>\n{server_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>" } }, sdvx: { recent: { description: "Show recent scores", messages: { "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "server-menu-select": "<p>Please select the server you want to use:</p>\n{server_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred while using card: {card}, server: {server} (っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", quit: "<p>Exited~</p>" } }, chart: { description: "Show SDVX chart", messages: { prompt: "<p>Which song's chart would you like to view?</p>", error: "<p>An error occurred(っ °Д °;)っ</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", "no-result": "<p>Aww, Noah couldn’t find that song~ try another keyword, okay?</p>" } }, calculate: { description: "Calculate volforce value or score", messages: { "invalid-query": "<p>Invalid query parameters, please check your input~</p>", "no-results": "<p>No results found~</p>", "too-many-results": "<p>Too many results! Found {0} results, please narrow down your query (current limit: 500 results)</p>", drawing: "<p>Noah is drawing, please wait patiently~</p>", error: "<p>An error occurred(っ °Д °;)っ</p>" } }, radar: { description: "Show player radar stats", messages: { "card-not-found": "<p>You haven't bound a card yet, go bind a card first~</p>", "server-not-found": "<p>No available servers, add one yourself~</p>", "no-scores-found": "<p>No scores found, please check your data.</p>", error: "<p>An error occurred while using card: {card}, server: {server} (っ °Д °;)っ</p>", "menu-select": "<p>Please select the card you want to use:</p>\n{card_list}\n<p>q. Exit</p>", "server-menu-select": "<p>Please select the server you want to use:</p>\n{server_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Exited~</p>", result: "<p>{name}'s Radar</p>\n<p>NOTES: {notes}</p>\n<p>PEAK: {peak}</p>\n<p>TSUMAMI: {tsumami}</p>\n<p>TRICKY: {tricky}</p>\n<p>HAND-TRIP: {hand_trip}</p>\n<p>ONE-HAND: {one_hand}</p>" } }, sync: { description: "Sync scores to Mao", messages: { "mao-not-found": "<p>Mao server not found. Please add a Mao server first, then try syncing again.</p>", "source-server-not-found": "<p>No available source servers. Please add a server first.</p>", "source-server-select": "<p>Please choose the source server:</p>\n{server_list}\n<p>q. Exit</p>", "card-not-found": "<p>You haven't bound any card yet. Please bind a card first.</p>", "source-card-select": "<p>Please choose the source card:</p>\n{card_list}\n<p>q. Exit</p>", "target-card-select": "<p>Please choose the target card (sync to Mao):</p>\n{card_list}\n<p>q. Exit</p>", "invalid-select": "<p>No such option!</p>", quit: "<p>Sync cancelled.</p>", "same-card-error": "<p>When the source server is Mao, the source card and target card cannot be the same. Please choose again.</p>", "dm-only": "<p>For security, please use this command in a private chat.</p>", "pin-prompt": "<p>Please enter the Mao PIN (4 digits):</p>\n<p>q. Exit</p>", "pin-invalid": "<p>Invalid PIN format. Please enter 4 digits.</p>", "pin-verify-failed": "<p>PIN verification failed: {message}</p>", "pin-verify-error": "<p>PIN verification error. Please try again later.</p>", "pin-too-many": "<p>Too many PIN attempts. Please try again later.</p>", "fetch-error": "<p>An error occurred while using card: {card}, server: {server} (っ °Д °;)っ</p>", "no-scores": "<p>No scores available for sync.</p>", "confirm-sync": "<p>Found {score_count} scores. Start sync?</p>\n<p>Type y to confirm, any other key to cancel.</p>", "sync-error": "<p>An error occurred while using card: {card}, server: {server} (っ °Д °;)っ</p>", "sync-failed": "<p>Sync failed(っ °Д °;)っ</p>", "selected-summary": "<p>Sync completedヾ(≧▽≦*)o</p>\n<p>Source server: {source_server_name} ({source_server_type})</p>\n<p>Source card: {source_card_name}</p>\n<p>Target card: {target_card_name}</p>\n<p>Tracks synced: {score_count}</p>" } } } } };
7149
7210
 
7150
7211
  // src/games/sdvx/locales/zh-CN.yml
7151
- var zh_CN_default4 = { _config: { $desc: "SDVX 模块设置", sdvx_data_url: "<p>SDVX 数据服务的 URL</p>", sdvx_search_url: "<p>SDVX 搜索服务的 URL</p>", official_support_url: "<p>SDVX 官方支持服务的 URL</p>" }, commands: { vf: { description: "查询 SDVX VOLFORCE", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "server-menu-select": "<p>请选择你要使用的服务器:</p>\n{server_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>" } }, sdvx: { recent: { description: "查询最近分数", messages: { "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "server-menu-select": "<p>请选择你要使用的服务器:</p>\n{server_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", quit: "<p>已退出~</p>" } }, chart: { description: "查询 SDVX 谱面", messages: { prompt: "<p>要查哪首歌的铺面呢?</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在绘制 {name} [{difstr}],请耐心等待~</p>", "no-result": "<p>Noah 没有找到这首歌,换个关键词试试吧~</p>" } }, calculate: { description: "计算 volforce 值或分数", messages: { "invalid-query": "<p>查询参数无效,请检查你的输入~</p>", "no-results": "<p>没有找到符合条件的结果~</p>", "too-many-results": "<p>结果太多啦!共找到 {0} 条结果,请缩小查询范围(当前限制:500 条)</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>" } }, radar: { description: "查询玩家六维雷达", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "server-menu-select": "<p>请选择你要使用的服务器:</p>\n{server_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", result: "<p>{name} 的雷达</p>\n<p>NOTES: {notes}</p>\n<p>PEAK: {peak}</p>\n<p>TSUMAMI: {tsumami}</p>\n<p>TRICKY: {tricky}</p>\n<p>HAND-TRIP: {hand_trip}</p>\n<p>ONE-HAND: {one_hand}</p>" } }, sync: { description: "同步成绩到猫网", messages: { "mao-not-found": "<p>没有找到猫网服务器,请先添加猫网服务器后再尝试同步。</p>", "source-server-not-found": "<p>没有可作为来源的服务器,请先添加服务器。</p>", "source-server-select": "<p>请选择来源服务器:</p>\n{server_list}\n<p>q. 退出</p>", "card-not-found": "<p>你还没有绑定任何卡片哦~</p>", "source-card-select": "<p>请选择来源卡片:</p>\n{card_list}\n<p>q. 退出</p>", "target-card-select": "<p>请选择目标卡片(同步到猫网):</p>\n{card_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出同步。</p>", "same-card-error": "<p>来源服务器为猫网时,来源卡片和目标卡片不能相同,请重新选择。</p>", "dm-only": "<p>出于安全考虑,请在私聊中使用该指令。</p>", "pin-prompt": "<p>请输入猫网 PIN 码(4 位数字):</p>\n<p>q. 退出</p>", "pin-invalid": "<p>PIN 码格式不正确,请输入 4 位数字。</p>", "pin-verify-failed": "<p>PIN 验证失败:{message}</p>", "pin-verify-error": "<p>PIN 验证时出现错误,请稍后重试。</p>", "pin-too-many": "<p>PIN 验证次数过多,请稍后再试。</p>", "fetch-error": "<p>获取来源服务器成绩失败,请稍后再试。</p>", "no-scores": "<p>没有可同步的成绩。</p>", "confirm-sync": "<p>共找到 {score_count} 条成绩,是否开始同步?</p>\n<p>输入 y 确认,其他任意键取消。</p>", "sync-error": "<p>同步过程中出现了错误(っ °Д °;)っ</p>", "sync-failed": "<p>同步失败(っ °Д °;)っ</p>", "selected-summary": "<p>同步完成ヾ(≧▽≦*)o</p>\n<p>来源服务器:{source_server_name} ({source_server_type})</p>\n<p>来源卡片:{source_card_name}</p>\n<p>目标卡片:{target_card_name}</p>\n<p>同步曲目数量:{score_count}</p>" } } } } };
7212
+ var zh_CN_default4 = { _config: { $desc: "SDVX 模块设置", sdvx_data_url: "<p>SDVX 数据服务的 URL</p>", sdvx_search_url: "<p>SDVX 搜索服务的 URL</p>", official_support_url: "<p>SDVX 官方支持服务的 URL</p>" }, commands: { vf: { description: "查询 SDVX VOLFORCE", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 在使用卡片:{card},服务器:{server} 时遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "server-menu-select": "<p>请选择你要使用的服务器:</p>\n{server_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>" } }, sdvx: { recent: { description: "查询最近分数", messages: { "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "server-menu-select": "<p>请选择你要使用的服务器:</p>\n{server_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 在使用卡片:{card},服务器:{server} 时遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", quit: "<p>已退出~</p>" } }, chart: { description: "查询 SDVX 谱面", messages: { prompt: "<p>要查哪首歌的铺面呢?</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>", drawing: "<p>Noah 正在绘制 {name} [{difstr}],请耐心等待~</p>", "no-result": "<p>Noah 没有找到这首歌,换个关键词试试吧~</p>" } }, calculate: { description: "计算 volforce 值或分数", messages: { "invalid-query": "<p>查询参数无效,请检查你的输入~</p>", "no-results": "<p>没有找到符合条件的结果~</p>", "too-many-results": "<p>结果太多啦!共找到 {0} 条结果,请缩小查询范围(当前限制:500 条)</p>", drawing: "<p>Noah 正在画啦,请耐心等待~</p>", error: "<p>Noah 遇到了错误(っ °Д °;)っ</p>" } }, radar: { description: "查询玩家六维雷达", messages: { "card-not-found": "<p>你还没绑卡,去绑个卡再来吧~</p>", "server-not-found": "<p>没有可用的服务器哦,自己添加一个吧~</p>", "no-scores-found": "<p>没有找到你的分数数据哦~</p>", error: "<p>Noah 在使用卡片:{card},服务器:{server} 时遇到了错误(っ °Д °;)っ</p>", "menu-select": "<p>请选择你要使用的卡片:</p>\n{card_list}\n<p>q. 退出</p>", "server-menu-select": "<p>请选择你要使用的服务器:</p>\n{server_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出~</p>", result: "<p>{name} 的雷达</p>\n<p>NOTES: {notes}</p>\n<p>PEAK: {peak}</p>\n<p>TSUMAMI: {tsumami}</p>\n<p>TRICKY: {tricky}</p>\n<p>HAND-TRIP: {hand_trip}</p>\n<p>ONE-HAND: {one_hand}</p>" } }, sync: { description: "同步成绩到猫网", messages: { "mao-not-found": "<p>没有找到猫网服务器,请先添加猫网服务器后再尝试同步。</p>", "source-server-not-found": "<p>没有可作为来源的服务器,请先添加服务器。</p>", "source-server-select": "<p>请选择来源服务器:</p>\n{server_list}\n<p>q. 退出</p>", "card-not-found": "<p>你还没有绑定任何卡片哦~</p>", "source-card-select": "<p>请选择来源卡片:</p>\n{card_list}\n<p>q. 退出</p>", "target-card-select": "<p>请选择目标卡片(同步到猫网):</p>\n{card_list}\n<p>q. 退出</p>", "invalid-select": "<p>没有该选项!</p>", quit: "<p>已退出同步。</p>", "same-card-error": "<p>来源服务器为猫网时,来源卡片和目标卡片不能相同,请重新选择。</p>", "dm-only": "<p>出于安全考虑,请在私聊中使用该指令。</p>", "pin-prompt": "<p>请输入猫网 PIN 码(4 位数字):</p>\n<p>q. 退出</p>", "pin-invalid": "<p>PIN 码格式不正确,请输入 4 位数字。</p>", "pin-verify-failed": "<p>PIN 验证失败:{message}</p>", "pin-verify-error": "<p>PIN 验证时出现错误,请稍后重试。</p>", "pin-too-many": "<p>PIN 验证次数过多,请稍后再试。</p>", "fetch-error": "<p>Noah 在使用卡片:{card},服务器:{server} 时遇到了错误(っ °Д °;)っ</p>", "no-scores": "<p>没有可同步的成绩。</p>", "confirm-sync": "<p>共找到 {score_count} 条成绩,是否开始同步?</p>\n<p>输入 y 确认,其他任意键取消。</p>", "sync-error": "<p>Noah 在使用卡片:{card},服务器:{server} 时遇到了错误(っ °Д °;)っ</p>", "sync-failed": "<p>同步失败(っ °Д °;)っ</p>", "selected-summary": "<p>同步完成ヾ(≧▽≦*)o</p>\n<p>来源服务器:{source_server_name} ({source_server_type})</p>\n<p>来源卡片:{source_card_name}</p>\n<p>目标卡片:{target_card_name}</p>\n<p>同步曲目数量:{score_count}</p>" } } } } };
7152
7213
 
7153
7214
  // src/games/sdvx/index.ts
7154
7215
  var name13 = "Noah-SDVX";
7155
7216
  var inject3 = ["database", "globalConfig"];
7156
- var logger4 = new import_koishi19.Logger("Noah-SDVX");
7217
+ var logger5 = new import_koishi21.Logger("Noah-SDVX");
7157
7218
  async function apply13(ctx, config) {
7158
7219
  ;
7159
7220
  [
7160
7221
  ["en-US", en_US_default4],
7161
7222
  ["zh-CN", zh_CN_default4]
7162
7223
  ].forEach(([lang, file]) => ctx.i18n.define(lang, file));
7163
- registerSDVXAdapters(logger4, config.sdvx);
7224
+ registerSDVXAdapters(logger5, config.sdvx);
7164
7225
  ctx.plugin(database_exports2, config.sdvx);
7165
7226
  ctx.plugin(command_exports2, config.sdvx);
7166
7227
  ctx.plugin(event_exports2, config.sdvx);
@@ -7168,50 +7229,50 @@ async function apply13(ctx, config) {
7168
7229
  __name(apply13, "apply");
7169
7230
 
7170
7231
  // src/config.ts
7171
- var import_koishi27 = require("koishi");
7232
+ var import_koishi29 = require("koishi");
7172
7233
 
7173
7234
  // src/asset/config.ts
7174
- var import_koishi20 = require("koishi");
7175
- var assetConfig = import_koishi20.Schema.object({
7176
- data_path: import_koishi20.Schema.string().default("noah_assets"),
7177
- auto_update: import_koishi20.Schema.boolean().default(true),
7178
- update_url: import_koishi20.Schema.string().default("https://github.com/logthm/noah/releases/latest/download/"),
7179
- update_interval: import_koishi20.Schema.number().default(24 * 60 * 60 * 1e3),
7235
+ var import_koishi22 = require("koishi");
7236
+ var assetConfig = import_koishi22.Schema.object({
7237
+ data_path: import_koishi22.Schema.string().default("noah_assets"),
7238
+ auto_update: import_koishi22.Schema.boolean().default(true),
7239
+ update_url: import_koishi22.Schema.string().default("https://github.com/logthm/noah/releases/latest/download/"),
7240
+ update_interval: import_koishi22.Schema.number().default(24 * 60 * 60 * 1e3),
7180
7241
  // 24 hours in milliseconds
7181
- github_token: import_koishi20.Schema.string().description("GitHub token for accessing private repositories").role("secret")
7242
+ github_token: import_koishi22.Schema.string().description("GitHub token for accessing private repositories").role("secret")
7182
7243
  }).i18n({
7183
7244
  "en-US": en_US_default._config,
7184
7245
  "zh-CN": zh_CN_default._config
7185
7246
  });
7186
7247
 
7187
7248
  // src/core/config.ts
7188
- var import_koishi21 = require("koishi");
7189
- var coreConfig = import_koishi21.Schema.object({
7190
- adminUsers: import_koishi21.Schema.array(String).role("table"),
7191
- guildNameCards: import_koishi21.Schema.array(String).role("table").default(["Noah | /help 获取食用指南"]),
7192
- tokenTtl: import_koishi21.Schema.number().default(1800),
7193
- frontendUrl: import_koishi21.Schema.string().default(""),
7194
- corsOrigin: import_koishi21.Schema.string().default("*")
7249
+ var import_koishi23 = require("koishi");
7250
+ var coreConfig = import_koishi23.Schema.object({
7251
+ adminUsers: import_koishi23.Schema.array(String).role("table"),
7252
+ guildNameCards: import_koishi23.Schema.array(String).role("table").default(["Noah | /help 获取食用指南"]),
7253
+ tokenTtl: import_koishi23.Schema.number().default(1800),
7254
+ frontendUrl: import_koishi23.Schema.string().default(""),
7255
+ corsOrigin: import_koishi23.Schema.string().default("*")
7195
7256
  }).i18n({
7196
7257
  "en-US": en_US_default2._config,
7197
7258
  "zh-CN": zh_CN_default2._config
7198
7259
  });
7199
7260
 
7200
7261
  // src/fun/poke/config.ts
7201
- var import_koishi22 = require("koishi");
7202
- var pokeConfig = import_koishi22.Schema.object({
7203
- interval: import_koishi22.Schema.number().default(1e3).step(100),
7204
- warning: import_koishi22.Schema.boolean().default(false),
7205
- prompt: import_koishi22.Schema.array(
7206
- import_koishi22.Schema.object({
7207
- content: import_koishi22.Schema.string().required(),
7208
- weight: import_koishi22.Schema.number().min(0).max(100).default(50)
7262
+ var import_koishi24 = require("koishi");
7263
+ var pokeConfig = import_koishi24.Schema.object({
7264
+ interval: import_koishi24.Schema.number().default(1e3).step(100),
7265
+ warning: import_koishi24.Schema.boolean().default(false),
7266
+ prompt: import_koishi24.Schema.array(
7267
+ import_koishi24.Schema.object({
7268
+ content: import_koishi24.Schema.string().required(),
7269
+ weight: import_koishi24.Schema.number().min(0).max(100).default(50)
7209
7270
  })
7210
7271
  ).role("table"),
7211
- messages: import_koishi22.Schema.array(
7212
- import_koishi22.Schema.object({
7213
- content: import_koishi22.Schema.string().required(),
7214
- weight: import_koishi22.Schema.number().min(0).max(100).default(50)
7272
+ messages: import_koishi24.Schema.array(
7273
+ import_koishi24.Schema.object({
7274
+ type: import_koishi24.Schema.union(["text", "noah", "chat"]).default("text"),
7275
+ weight: import_koishi24.Schema.number().min(0).max(100).default(50)
7215
7276
  })
7216
7277
  ).role("table")
7217
7278
  }).i18n({
@@ -7220,7 +7281,7 @@ var pokeConfig = import_koishi22.Schema.object({
7220
7281
  });
7221
7282
 
7222
7283
  // src/games/general/config.ts
7223
- var import_koishi23 = require("koishi");
7284
+ var import_koishi25 = require("koishi");
7224
7285
 
7225
7286
  // src/games/general/locales/en-US.yml
7226
7287
  var en_US_default5 = { _config: { $desc: "General Module Settings", barcode_api_url: "<p>The URL of the barcode API</p>" } };
@@ -7229,33 +7290,33 @@ var en_US_default5 = { _config: { $desc: "General Module Settings", barcode_api_
7229
7290
  var zh_CN_default5 = { _config: { $desc: "通用工具模块设置", barcode_api_url: "<p>条形码 API 地址</p>" } };
7230
7291
 
7231
7292
  // src/games/general/config.ts
7232
- var generalConfig = import_koishi23.Schema.object({
7233
- barcode_api_url: import_koishi23.Schema.string().required()
7293
+ var generalConfig = import_koishi25.Schema.object({
7294
+ barcode_api_url: import_koishi25.Schema.string().required()
7234
7295
  }).i18n({
7235
7296
  "en-US": en_US_default5._config,
7236
7297
  "zh-CN": zh_CN_default5._config
7237
7298
  });
7238
7299
 
7239
7300
  // src/games/sdvx/config.ts
7240
- var import_koishi24 = require("koishi");
7241
- var sdvxConfig = import_koishi24.Schema.object({
7242
- sdvx_data_url: import_koishi24.Schema.string().required(),
7243
- sdvx_search_url: import_koishi24.Schema.string().required()
7301
+ var import_koishi26 = require("koishi");
7302
+ var sdvxConfig = import_koishi26.Schema.object({
7303
+ sdvx_data_url: import_koishi26.Schema.string().required(),
7304
+ sdvx_search_url: import_koishi26.Schema.string().required()
7244
7305
  }).i18n({
7245
7306
  "en-US": en_US_default4._config,
7246
7307
  "zh-CN": zh_CN_default4._config
7247
7308
  });
7248
7309
 
7249
7310
  // src/global/config.ts
7250
- var import_koishi25 = require("koishi");
7251
- var globalConfig = import_koishi25.Schema.object({
7252
- official_support_url: import_koishi25.Schema.string().default("https://noah.logthm.com"),
7253
- maoServerUrl: import_koishi25.Schema.string().default("http://maomani.cn:577"),
7254
- maoApiKey: import_koishi25.Schema.string().role("secret").default("")
7311
+ var import_koishi27 = require("koishi");
7312
+ var globalConfig = import_koishi27.Schema.object({
7313
+ official_support_url: import_koishi27.Schema.string().default("https://noah.logthm.com"),
7314
+ maoServerUrl: import_koishi27.Schema.string().default("http://maomani.cn:577"),
7315
+ maoApiKey: import_koishi27.Schema.string().role("secret").default("")
7255
7316
  });
7256
7317
 
7257
7318
  // src/slash/config.ts
7258
- var import_koishi26 = require("koishi");
7319
+ var import_koishi28 = require("koishi");
7259
7320
 
7260
7321
  // src/slash/locales/en-US.yml
7261
7322
  var en_US_default6 = { _config: { $desc: "Slash Module Settings", test_guilds: "**Guilds To Sync**", auto_sync_on_start: "**Auto Sync on Connect**" } };
@@ -7264,16 +7325,16 @@ var en_US_default6 = { _config: { $desc: "Slash Module Settings", test_guilds: "
7264
7325
  var zh_CN_default6 = { _config: { $desc: "Slash 模块设置", test_guilds: "**默认同步 Guild 列表**", auto_sync_on_start: "**连接后自动同步**" } };
7265
7326
 
7266
7327
  // src/slash/config.ts
7267
- var slashConfig = import_koishi26.Schema.object({
7268
- test_guilds: import_koishi26.Schema.array(String).default([]),
7269
- auto_sync_on_start: import_koishi26.Schema.boolean().default(true)
7328
+ var slashConfig = import_koishi28.Schema.object({
7329
+ test_guilds: import_koishi28.Schema.array(String).default([]),
7330
+ auto_sync_on_start: import_koishi28.Schema.boolean().default(true)
7270
7331
  }).i18n({
7271
7332
  "en-US": en_US_default6._config,
7272
7333
  "zh-CN": zh_CN_default6._config
7273
7334
  });
7274
7335
 
7275
7336
  // src/config.ts
7276
- var Config = import_koishi27.Schema.object({
7337
+ var Config = import_koishi29.Schema.object({
7277
7338
  global: globalConfig,
7278
7339
  core: coreConfig,
7279
7340
  sdvx: sdvxConfig,