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 +2 -0
- package/lib/index.js +47 -2
- package/lib/matcher.d.ts +2 -0
- package/lib/types.d.ts +1 -1
- package/package.json +1 -1
package/lib/game.d.ts
CHANGED
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
|
|
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
|
-
|
|
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;
|