koishi-plugin-ai-puzzle 0.0.21 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/game.d.ts CHANGED
@@ -84,6 +84,8 @@ export declare class GameOrchestrator {
84
84
  private pvpCheckAllGuessed;
85
85
  private pvpPenalize;
86
86
  private pvpNextPuzzle;
87
+ /** 无 session 的合并转发谜题详情 */
88
+ private sendPvpForwardOrFallback;
87
89
  private pvpEnd;
88
90
  private updateHistory;
89
91
  }
package/lib/index.js CHANGED
@@ -36,7 +36,7 @@ var require_package = __commonJS({
36
36
  module2.exports = {
37
37
  name: "koishi-plugin-ai-puzzle",
38
38
  description: "使用AI生成猜谜谜题,支持多模式游戏、模糊匹配、图片渲染",
39
- version: "0.0.21",
39
+ version: "0.1.0",
40
40
  main: "lib/index.js",
41
41
  typings: "lib/index.d.ts",
42
42
  files: [
@@ -617,7 +617,13 @@ var AnswerMatcher = class {
617
617
  return { matched: false };
618
618
  }
619
619
  normalize(text) {
620
- return text.trim().replace(/[!-~]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 65248)).replace(/ /g, " ");
620
+ let t = text.trim().replace(/[!-~]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 65248)).replace(/ /g, " ");
621
+ t = this.stripPunctuation(t);
622
+ return t.replace(/\s+/g, " ").trim();
623
+ }
624
+ /** 去除标点符号 */
625
+ stripPunctuation(text) {
626
+ return text.replace(/[·《》:「」『』【】〔〕〖〗〘〙〚〛、。,;:?!…—~‖|〃々〆〇〈〉《》「」『』【】〒〓〔〕〖〗〘〙〚〛ゝゞヽヾ・ー -〿＀-￯\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]/g, "");
621
627
  }
622
628
  exactMatch(input, puzzle) {
623
629
  const candidates = [
@@ -1825,14 +1831,53 @@ var GameOrchestrator = class {
1825
1831
  clearTimeout(pvp.autoTimer);
1826
1832
  pvp.autoTimer = null;
1827
1833
  }
1834
+ const currentPuzzle = pvp.puzzles[pvp.currentPuzzleIndex];
1835
+ pvp.status = "transition";
1836
+ if (currentPuzzle) {
1837
+ await this.sendPvpForwardOrFallback(channelId, currentPuzzle.puzzle);
1838
+ }
1828
1839
  pvp.currentPuzzleIndex++;
1829
1840
  pvp.currentClueIndex = 0;
1830
1841
  if (pvp.currentPuzzleIndex >= pvp.puzzleCount) {
1831
1842
  await this.pvpEnd(channelId);
1832
1843
  } else {
1844
+ const sendBot = Object.values(this.ctx.bots)[0];
1845
+ if (sendBot) await sendBot.sendMessage(channelId, "5秒后开始下一题...").catch(() => {
1846
+ });
1847
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
1848
+ pvp.status = "playing";
1833
1849
  await this.pvpThrowClue(channelId);
1834
1850
  }
1835
1851
  }
1852
+ /** 无 session 的合并转发谜题详情 */
1853
+ async sendPvpForwardOrFallback(channelId, puzzle) {
1854
+ try {
1855
+ const bot = Object.values(this.ctx.bots)[0];
1856
+ if (!bot?.internal?.sendGroupForwardMsg) throw new Error("no forward API");
1857
+ const botName = "AI谜题";
1858
+ const nodes = [
1859
+ { type: "node", data: { name: botName, uin: "", content: `谜底揭晓:「${puzzle.name}」` } },
1860
+ { type: "node", data: { name: botName, uin: "", content: `名字:${puzzle.name}` } }
1861
+ ];
1862
+ if (puzzle.enName) nodes.push({ type: "node", data: { name: botName, uin: "", content: `英文名:${puzzle.enName}` } });
1863
+ if (puzzle.aliases.length) nodes.push({ type: "node", data: { name: botName, uin: "", content: `别名:${puzzle.aliases.join("、")}` } });
1864
+ if (puzzle.description) nodes.push({ type: "node", data: { name: botName, uin: "", content: `介绍:${puzzle.description}` } });
1865
+ nodes.push({ type: "node", data: { name: botName, uin: "", content: `全部线索(共 ${puzzle.clues.length} 条):` } });
1866
+ for (let i = 0; i < puzzle.clues.length; i++) {
1867
+ const cleanC = puzzle.clues[i].replace(/^等级\d+[::]/, "");
1868
+ let content = `线索 ${i + 1}:${cleanC}`;
1869
+ if (puzzle.explanations[i]) content += `
1870
+ ↳ ${puzzle.explanations[i]}`;
1871
+ nodes.push({ type: "node", data: { name: botName, uin: "", content } });
1872
+ }
1873
+ await bot.internal.sendGroupForwardMsg(channelId, nodes);
1874
+ } catch {
1875
+ const text = this.buildFullTextResult(puzzle, puzzle.clues.length - 1);
1876
+ const sendBot = Object.values(this.ctx.bots)[0];
1877
+ if (sendBot) await sendBot.sendMessage(channelId, text).catch(() => {
1878
+ });
1879
+ }
1880
+ }
1836
1881
  async pvpEnd(channelId) {
1837
1882
  const pvp = this.pvpStates.get(channelId);
1838
1883
  pvp.status = "ended";
package/lib/matcher.d.ts CHANGED
@@ -10,6 +10,8 @@ export declare class AnswerMatcher {
10
10
  constructor(logger?: Logger);
11
11
  match(input: string, puzzle: PuzzleData, config: TemplateConfig): MatchResult;
12
12
  private normalize;
13
+ /** 去除标点符号 */
14
+ private stripPunctuation;
13
15
  private exactMatch;
14
16
  private fuzzyMatch;
15
17
  levenshteinSimilarity(a: string, b: string): number;
package/lib/types.d.ts CHANGED
@@ -88,7 +88,7 @@ export interface PromptVars {
88
88
  exclusionText: string;
89
89
  extensionRule: string;
90
90
  }
91
- export type PvpStatus = 'lobby' | 'generating' | 'retry' | 'ready' | 'playing' | 'ended';
91
+ export type PvpStatus = 'lobby' | 'generating' | 'retry' | 'ready' | 'playing' | 'transition' | 'ended';
92
92
  export interface PvpPuzzle {
93
93
  puzzle: PuzzleData;
94
94
  templateConfig: TemplateConfig;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ai-puzzle",
3
3
  "description": "使用AI生成猜谜谜题,支持多模式游戏、模糊匹配、图片渲染",
4
- "version": "0.0.21",
4
+ "version": "0.1.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [