@zhin.js/plugin-idiom-chain 1.0.3 → 1.0.4
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/commands/chain/[action:string=].ts +2 -2
- package/lib/chain-command.d.ts +2 -4
- package/lib/chain-command.js +4 -8
- package/lib/chain-command.js.map +1 -1
- package/lib/game-flow.d.ts +6 -6
- package/lib/game-flow.js +23 -36
- package/lib/game-flow.js.map +1 -1
- package/lib/session-service.d.ts +3 -2
- package/lib/session-service.js.map +1 -1
- package/middlewares/chain-alias.ts +6 -3
- package/middlewares/chain-text.ts +3 -3
- package/package.json +6 -6
- package/src/chain-command.ts +6 -17
- package/src/game-flow.ts +25 -45
- package/src/session-service.ts +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineCommand } from '@zhin.js/command';
|
|
2
2
|
import { messageFromCommandInput, normalizeChainAction } from '@zhin.js/game-kit';
|
|
3
|
-
import { CHAIN_HELP,
|
|
3
|
+
import { CHAIN_HELP, runChainCommand } from '../../src/chain-command.js';
|
|
4
4
|
import { resolveGameServices } from '../../src/runtime-store.js';
|
|
5
5
|
|
|
6
6
|
export default defineCommand({
|
|
@@ -10,6 +10,6 @@ export default defineCommand({
|
|
|
10
10
|
if (!action || action === 'help') return CHAIN_HELP;
|
|
11
11
|
const services = resolveGameServices({ use, owner });
|
|
12
12
|
const message = messageFromCommandInput(input);
|
|
13
|
-
return
|
|
13
|
+
return runChainCommand(services, message, action);
|
|
14
14
|
},
|
|
15
15
|
});
|
package/lib/chain-command.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type GameMessageLike } from '@zhin.js/game-kit';
|
|
2
2
|
import type { SessionService } from './session-service.js';
|
|
3
3
|
export declare const CHAIN_HELP: string;
|
|
4
|
-
export declare function runChainCommand(
|
|
5
|
-
/** Plugin Runtime / smoke: text-only, no Adapter.editMessage. */
|
|
6
|
-
export declare function runChainCommandText(services: SessionService, message: Message<any>, action: string): Promise<string>;
|
|
4
|
+
export declare function runChainCommand(services: SessionService, message: GameMessageLike, action: string): Promise<string>;
|
package/lib/chain-command.js
CHANGED
|
@@ -13,7 +13,7 @@ export const CHAIN_HELP = [
|
|
|
13
13
|
'进行中:直接回复四字成语',
|
|
14
14
|
'按钮:提示 · 跳过 · 认输(失误 3 次判负)',
|
|
15
15
|
].join('\n');
|
|
16
|
-
export async function runChainCommand(
|
|
16
|
+
export async function runChainCommand(services, message, action) {
|
|
17
17
|
const ch = channelKey(message);
|
|
18
18
|
const userId = message.$sender.id;
|
|
19
19
|
if (!action || action === 'help') {
|
|
@@ -31,11 +31,11 @@ export async function runChainCommand(plugin, services, message, action) {
|
|
|
31
31
|
return lines.join('\n');
|
|
32
32
|
}
|
|
33
33
|
if (action === 'start_pinyin')
|
|
34
|
-
return startGame(
|
|
34
|
+
return (await startGame(services, message, 'pinyin')) ?? '';
|
|
35
35
|
if (action === 'start_char')
|
|
36
|
-
return startGame(
|
|
36
|
+
return (await startGame(services, message, 'char')) ?? '';
|
|
37
37
|
if (action === 'continue')
|
|
38
|
-
return continueGame(
|
|
38
|
+
return continueGame(services, message);
|
|
39
39
|
if (action === 'quit') {
|
|
40
40
|
const row = await services.getActiveForUser(ch, userId);
|
|
41
41
|
if (!row)
|
|
@@ -45,8 +45,4 @@ export async function runChainCommand(plugin, services, message, action) {
|
|
|
45
45
|
}
|
|
46
46
|
return `未知子命令:${action}\n\n${CHAIN_HELP}`;
|
|
47
47
|
}
|
|
48
|
-
/** Plugin Runtime / smoke: text-only, no Adapter.editMessage. */
|
|
49
|
-
export async function runChainCommandText(services, message, action) {
|
|
50
|
-
return (await runChainCommand(null, services, message, action)) ?? '';
|
|
51
|
-
}
|
|
52
48
|
//# sourceMappingURL=chain-command.js.map
|
package/lib/chain-command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chain-command.js","sourceRoot":"","sources":["../src/chain-command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chain-command.js","sourceRoot":"","sources":["../src/chain-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAwB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAC;AAIhF,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,sBAAsB;IACtB,QAAQ,UAAU,EAAE,eAAe;IACnC,iBAAiB;IACjB,8BAA8B;IAC9B,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,EAAE;IACF,cAAc;IACd,2BAA2B;CAC5B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAwB,EACxB,OAAwB,EACxB,MAAc;IAEd,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAElC,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC/B,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,GAAc,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;YACzE,KAAK,CAAC,IAAI,CACR,OAAO,MAAM,CAAC,WAAW,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,CACvH,CAAC;YACF,IAAI,MAAM,CAAC,UAAU;gBAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,MAAM,KAAK,cAAc;QAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3F,IAAI,MAAM,KAAK,YAAY;QAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACvF,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAElE,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG;YAAE,OAAO,YAAY,CAAC;QAC9B,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,SAAS,MAAM,OAAO,UAAU,EAAE,CAAC;AAC5C,CAAC"}
|
package/lib/game-flow.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type GameMessageLike } from '@zhin.js/game-kit';
|
|
2
2
|
import { CHAIN_PREFIX, type MatchMode } from './engine.js';
|
|
3
3
|
import type { ChainSessionRow } from './models.js';
|
|
4
4
|
import { type SessionService } from './session-service.js';
|
|
5
|
-
export declare function sendOrEditView(
|
|
6
|
-
export declare function startGame(
|
|
7
|
-
export declare function continueGame(
|
|
8
|
-
export declare function processIdiomText(
|
|
9
|
-
export declare function handleChoice(
|
|
5
|
+
export declare function sendOrEditView(services: SessionService, message: GameMessageLike, session: ChainSessionRow, eventLines?: string[]): Promise<string>;
|
|
6
|
+
export declare function startGame(services: SessionService, message: GameMessageLike, matchMode?: MatchMode): Promise<string | undefined>;
|
|
7
|
+
export declare function continueGame(services: SessionService, message: GameMessageLike): Promise<string>;
|
|
8
|
+
export declare function processIdiomText(services: SessionService, message: GameMessageLike, raw: string): Promise<string | null>;
|
|
9
|
+
export declare function handleChoice(services: SessionService, message: GameMessageLike, sessionId: string, choiceId: string): Promise<string | null>;
|
|
10
10
|
export { CHAIN_PREFIX };
|
package/lib/game-flow.js
CHANGED
|
@@ -5,28 +5,9 @@ import { buildChainView, MAX_WRONG } from './view.js';
|
|
|
5
5
|
function sessionMode(session) {
|
|
6
6
|
return session.match_mode === 'char' ? 'char' : 'pinyin';
|
|
7
7
|
}
|
|
8
|
-
export async function sendOrEditView(
|
|
8
|
+
export async function sendOrEditView(services, message, session, eventLines = []) {
|
|
9
9
|
const content = buildChainView(session, eventLines, message.$channel.type);
|
|
10
|
-
|
|
11
|
-
return plainTextFromSendContent(content);
|
|
12
|
-
const adapter = plugin.root.inject(message.$adapter);
|
|
13
|
-
if (session.board_message_id) {
|
|
14
|
-
const msgId = await adapter.editMessage({
|
|
15
|
-
messageId: session.board_message_id,
|
|
16
|
-
context: String(message.$adapter),
|
|
17
|
-
endpoint: message.$endpoint,
|
|
18
|
-
id: message.$channel.id,
|
|
19
|
-
type: message.$channel.type,
|
|
20
|
-
content,
|
|
21
|
-
});
|
|
22
|
-
if (msgId !== session.board_message_id) {
|
|
23
|
-
await services.updateSession(session.id, { board_message_id: msgId });
|
|
24
|
-
}
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
const msgId = await message.$reply?.(content);
|
|
28
|
-
if (msgId)
|
|
29
|
-
await services.updateSession(session.id, { board_message_id: msgId });
|
|
10
|
+
return plainTextFromSendContent(content);
|
|
30
11
|
}
|
|
31
12
|
async function botTurn(services, session, used) {
|
|
32
13
|
const mode = sessionMode(session);
|
|
@@ -55,7 +36,7 @@ async function botTurn(services, session, used) {
|
|
|
55
36
|
];
|
|
56
37
|
return { session: updated, lines, playerWon: false };
|
|
57
38
|
}
|
|
58
|
-
export async function startGame(
|
|
39
|
+
export async function startGame(services, message, matchMode = 'pinyin') {
|
|
59
40
|
const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
|
|
60
41
|
const active = await services.getActiveByChannel(ch);
|
|
61
42
|
if (active) {
|
|
@@ -74,22 +55,22 @@ export async function startGame(plugin, services, message, matchMode = 'pinyin')
|
|
|
74
55
|
matchMode,
|
|
75
56
|
});
|
|
76
57
|
const gloss = starter.gloss ?? getGloss(starter.text);
|
|
77
|
-
const text = await sendOrEditView(
|
|
58
|
+
const text = await sendOrEditView(services, message, session, [
|
|
78
59
|
`🎬 ${modeLabel(matchMode)}开局!我先出:**${starter.text}**${gloss ? `(${gloss})` : ''}`,
|
|
79
60
|
promptLine(starter.text, matchMode),
|
|
80
61
|
]);
|
|
81
62
|
return typeof text === 'string' ? text : undefined;
|
|
82
63
|
}
|
|
83
|
-
export async function continueGame(
|
|
64
|
+
export async function continueGame(services, message) {
|
|
84
65
|
const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
|
|
85
66
|
if (!session)
|
|
86
67
|
return '你没有进行中的接龙,发送「接龙 开始」。';
|
|
87
|
-
const text = await sendOrEditView(
|
|
68
|
+
const text = await sendOrEditView(services, message, session);
|
|
88
69
|
if (typeof text === 'string')
|
|
89
70
|
return text;
|
|
90
71
|
return '已刷新接龙界面。';
|
|
91
72
|
}
|
|
92
|
-
export async function processIdiomText(
|
|
73
|
+
export async function processIdiomText(services, message, raw) {
|
|
93
74
|
const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
|
|
94
75
|
const session = await services.getActiveForUser(ch, message.$sender.id);
|
|
95
76
|
if (!session || session.status !== 'active')
|
|
@@ -97,6 +78,10 @@ export async function processIdiomText(plugin, services, message, raw) {
|
|
|
97
78
|
const mode = sessionMode(session);
|
|
98
79
|
const used = parseUsed(session.used_idioms);
|
|
99
80
|
const idiom = normalizeInput(raw);
|
|
81
|
+
// 格式不合规(非四字)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
|
|
82
|
+
if (!/^[\u4e00-\u9fff]{4}$/.test(idiom)) {
|
|
83
|
+
return '接龙请输入**四字成语**(这条不算失误)。';
|
|
84
|
+
}
|
|
100
85
|
const check = validatePlayerIdiom(idiom, session.last_idiom, mode, used);
|
|
101
86
|
if (!check.ok) {
|
|
102
87
|
const wrong = session.wrong_count + 1;
|
|
@@ -108,14 +93,14 @@ export async function processIdiomText(plugin, services, message, raw) {
|
|
|
108
93
|
streak: 0,
|
|
109
94
|
});
|
|
110
95
|
const updated = (await services.getById(session.id));
|
|
111
|
-
return (await sendOrEditView(
|
|
96
|
+
return (await sendOrEditView(services, message, updated, [
|
|
112
97
|
check.reason,
|
|
113
98
|
'失误过多,本局结束。',
|
|
114
99
|
])) ?? null;
|
|
115
100
|
}
|
|
116
101
|
await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
|
|
117
102
|
const updated = (await services.getById(session.id));
|
|
118
|
-
return (await sendOrEditView(
|
|
103
|
+
return (await sendOrEditView(services, message, updated, [check.reason])) ?? null;
|
|
119
104
|
}
|
|
120
105
|
used.add(idiom);
|
|
121
106
|
const streak = session.streak + 1;
|
|
@@ -133,12 +118,12 @@ export async function processIdiomText(plugin, services, message, raw) {
|
|
|
133
118
|
const current = (await services.getById(session.id));
|
|
134
119
|
const userLine = `✅ 你:${idiom}${gloss ? `(${gloss})` : ''}`;
|
|
135
120
|
const botResult = await botTurn(services, current, used);
|
|
136
|
-
return (await sendOrEditView(
|
|
121
|
+
return (await sendOrEditView(services, message, botResult.session, [
|
|
137
122
|
userLine,
|
|
138
123
|
...botResult.lines,
|
|
139
124
|
])) ?? null;
|
|
140
125
|
}
|
|
141
|
-
export async function handleChoice(
|
|
126
|
+
export async function handleChoice(services, message, sessionId, choiceId) {
|
|
142
127
|
const session = await services.getById(sessionId);
|
|
143
128
|
if (!session)
|
|
144
129
|
return '对局不存在。';
|
|
@@ -161,7 +146,7 @@ export async function handleChoice(plugin, services, message, sessionId, choiceI
|
|
|
161
146
|
});
|
|
162
147
|
const updated = (await services.getById(session.id));
|
|
163
148
|
const gloss = starter.gloss ?? getGloss(starter.text);
|
|
164
|
-
return (await sendOrEditView(
|
|
149
|
+
return (await sendOrEditView(services, message, updated, [
|
|
165
150
|
`🎬 新一局!我先出:**${starter.text}**${gloss ? `(${gloss})` : ''}`,
|
|
166
151
|
promptLine(starter.text, mode),
|
|
167
152
|
])) ?? null;
|
|
@@ -173,15 +158,17 @@ export async function handleChoice(plugin, services, message, sessionId, choiceI
|
|
|
173
158
|
if (choiceId === 'hint') {
|
|
174
159
|
const hint = pickHintIdiom(session.last_idiom, mode, used);
|
|
175
160
|
if (!hint) {
|
|
176
|
-
|
|
161
|
+
// 先更新状态再单次发送终局视图,避免旧 session「你赢了」与终局视图双发
|
|
177
162
|
await services.updateSession(session.id, { status: 'won', player_score: session.player_score + 1 });
|
|
178
163
|
const updated = (await services.getById(session.id));
|
|
179
|
-
return (await sendOrEditView(
|
|
164
|
+
return (await sendOrEditView(services, message, updated, [
|
|
165
|
+
'💡 词库中暂无可用提示,你赢了!',
|
|
166
|
+
])) ?? null;
|
|
180
167
|
}
|
|
181
168
|
const gloss = getGloss(hint);
|
|
182
169
|
await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
|
|
183
170
|
const updated = (await services.getById(session.id));
|
|
184
|
-
return (await sendOrEditView(
|
|
171
|
+
return (await sendOrEditView(services, message, updated, [
|
|
185
172
|
`💡 提示:可试 **${hint}**${gloss ? `(${gloss})` : ''}`,
|
|
186
173
|
'(使用提示会清零连击)',
|
|
187
174
|
])) ?? null;
|
|
@@ -193,14 +180,14 @@ export async function handleChoice(plugin, services, message, sessionId, choiceI
|
|
|
193
180
|
streak: 0,
|
|
194
181
|
});
|
|
195
182
|
const updated = (await services.getById(session.id));
|
|
196
|
-
return (await sendOrEditView(
|
|
183
|
+
return (await sendOrEditView(services, message, updated, [
|
|
197
184
|
'⏭️ 你选择跳过,机器人得一分。',
|
|
198
185
|
])) ?? null;
|
|
199
186
|
}
|
|
200
187
|
if (choiceId === 'quit') {
|
|
201
188
|
await services.updateSession(session.id, { status: 'lost', bot_score: session.bot_score + 1 });
|
|
202
189
|
const updated = (await services.getById(session.id));
|
|
203
|
-
return (await sendOrEditView(
|
|
190
|
+
return (await sendOrEditView(services, message, updated, ['🏳️ 你认输了。'])) ?? null;
|
|
204
191
|
}
|
|
205
192
|
return '未知操作。';
|
|
206
193
|
}
|
package/lib/game-flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
|
package/lib/session-service.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Database,
|
|
1
|
+
import type { Database, Models } from '@zhin.js/core';
|
|
2
|
+
import { type GameMessageLike } from '@zhin.js/game-kit';
|
|
2
3
|
import type { MatchMode } from './engine.js';
|
|
3
4
|
import type { ChainSessionRow } from './models.js';
|
|
4
5
|
export type ChainDatabase = Database<unknown, Models, string>;
|
|
@@ -11,7 +12,7 @@ export declare class SessionService {
|
|
|
11
12
|
getActiveForUser(channel: string, userId: string): Promise<ChainSessionRow | null>;
|
|
12
13
|
getById(id: string): Promise<ChainSessionRow | null>;
|
|
13
14
|
getActiveByBoardMessageId(messageId: string): Promise<ChainSessionRow | null>;
|
|
14
|
-
createSession(message:
|
|
15
|
+
createSession(message: GameMessageLike, starter: {
|
|
15
16
|
text: string;
|
|
16
17
|
nextChar: string;
|
|
17
18
|
used: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineGameCommandAliasMiddleware,
|
|
3
|
+
isChainAction,
|
|
3
4
|
messageFromCommandInput,
|
|
4
5
|
normalizeChainAction,
|
|
5
6
|
} from '@zhin.js/game-kit';
|
|
6
|
-
import { CHAIN_HELP,
|
|
7
|
+
import { CHAIN_HELP, runChainCommand } from '../src/chain-command.js';
|
|
7
8
|
import { resolveGameServices } from '../src/runtime-store.js';
|
|
8
9
|
|
|
9
10
|
export default defineGameCommandAliasMiddleware({
|
|
10
11
|
aliases: ['接龙', 'chain'],
|
|
11
12
|
async run(action, input, context) {
|
|
12
13
|
const normalized = normalizeChainAction(String(action ?? ''));
|
|
13
|
-
if (
|
|
14
|
+
if (normalized === 'help') return CHAIN_HELP;
|
|
15
|
+
// action 无法识别:放行给后续中间件,避免劫持普通聊天
|
|
16
|
+
if (!isChainAction(normalized)) return null;
|
|
14
17
|
const services = resolveGameServices(context);
|
|
15
18
|
const message = messageFromCommandInput(input);
|
|
16
|
-
return
|
|
19
|
+
return runChainCommand(services, message, normalized);
|
|
17
20
|
},
|
|
18
21
|
});
|
|
@@ -33,7 +33,7 @@ export default defineMiddleware<Message>({
|
|
|
33
33
|
if (parsed) {
|
|
34
34
|
const session = await services.getById(parsed.sessionId);
|
|
35
35
|
if (session?.channel_key === ch) {
|
|
36
|
-
const reply = await handleChoice(
|
|
36
|
+
const reply = await handleChoice(services, message, parsed.sessionId, parsed.choiceId);
|
|
37
37
|
if (reply) await context.input.$reply(reply);
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
@@ -57,7 +57,7 @@ export default defineMiddleware<Message>({
|
|
|
57
57
|
const payload = resolveGameTextPayload(raw, map);
|
|
58
58
|
const parsed = payload ? parseChoicePayload(payload, CHAIN_PREFIX) : null;
|
|
59
59
|
if (parsed?.sessionId === session.id) {
|
|
60
|
-
const reply = await handleChoice(
|
|
60
|
+
const reply = await handleChoice(services, message, session.id, parsed.choiceId);
|
|
61
61
|
if (reply) await context.input.$reply(reply);
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
@@ -65,7 +65,7 @@ export default defineMiddleware<Message>({
|
|
|
65
65
|
|
|
66
66
|
// 仅把 2-8 个汉字的纯文本当成语作答,其余放行
|
|
67
67
|
if (/^[\u4e00-\u9fff]{2,8}$/.test(raw)) {
|
|
68
|
-
const reply = await processIdiomText(
|
|
68
|
+
const reply = await processIdiomText(services, message, raw);
|
|
69
69
|
if (reply) await context.input.$reply(reply);
|
|
70
70
|
return;
|
|
71
71
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/plugin-idiom-chain",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Zhin.js 成语接龙 — 四字成语文字接龙 (Plugin Runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"chinese-idiom-chengyu": "^1.1.0",
|
|
28
|
-
"@zhin.js/command": "1.0.
|
|
29
|
-
"@zhin.js/core": "1.4.
|
|
30
|
-
"@zhin.js/game-kit": "2.0.
|
|
31
|
-
"@zhin.js/middleware": "1.0.
|
|
32
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
28
|
+
"@zhin.js/command": "1.0.3",
|
|
29
|
+
"@zhin.js/core": "1.4.1",
|
|
30
|
+
"@zhin.js/game-kit": "2.0.1",
|
|
31
|
+
"@zhin.js/middleware": "1.0.3",
|
|
32
|
+
"@zhin.js/plugin-runtime": "1.1.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"typescript": "^6.0.3",
|
package/src/chain-command.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { channelKey } from '@zhin.js/game-kit';
|
|
1
|
+
import { channelKey, type GameMessageLike } from '@zhin.js/game-kit';
|
|
3
2
|
import { continueGame, startGame } from './game-flow.js';
|
|
4
3
|
import { idiomCount, modeLabel, promptLine, type MatchMode } from './engine.js';
|
|
5
4
|
|
|
@@ -19,11 +18,10 @@ export const CHAIN_HELP = [
|
|
|
19
18
|
].join('\n');
|
|
20
19
|
|
|
21
20
|
export async function runChainCommand(
|
|
22
|
-
plugin: Plugin | null,
|
|
23
21
|
services: SessionService,
|
|
24
|
-
message:
|
|
22
|
+
message: GameMessageLike,
|
|
25
23
|
action: string,
|
|
26
|
-
): Promise<string
|
|
24
|
+
): Promise<string> {
|
|
27
25
|
const ch = channelKey(message);
|
|
28
26
|
const userId = message.$sender.id;
|
|
29
27
|
|
|
@@ -42,9 +40,9 @@ export async function runChainCommand(
|
|
|
42
40
|
return lines.join('\n');
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
if (action === 'start_pinyin') return startGame(
|
|
46
|
-
if (action === 'start_char') return startGame(
|
|
47
|
-
if (action === 'continue') return continueGame(
|
|
43
|
+
if (action === 'start_pinyin') return (await startGame(services, message, 'pinyin')) ?? '';
|
|
44
|
+
if (action === 'start_char') return (await startGame(services, message, 'char')) ?? '';
|
|
45
|
+
if (action === 'continue') return continueGame(services, message);
|
|
48
46
|
|
|
49
47
|
if (action === 'quit') {
|
|
50
48
|
const row = await services.getActiveForUser(ch, userId);
|
|
@@ -55,12 +53,3 @@ export async function runChainCommand(
|
|
|
55
53
|
|
|
56
54
|
return `未知子命令:${action}\n\n${CHAIN_HELP}`;
|
|
57
55
|
}
|
|
58
|
-
|
|
59
|
-
/** Plugin Runtime / smoke: text-only, no Adapter.editMessage. */
|
|
60
|
-
export async function runChainCommandText(
|
|
61
|
-
services: SessionService,
|
|
62
|
-
message: Message<any>,
|
|
63
|
-
action: string,
|
|
64
|
-
): Promise<string> {
|
|
65
|
-
return (await runChainCommand(null, services, message, action)) ?? '';
|
|
66
|
-
}
|
package/src/game-flow.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { plainTextFromSendContent } from '@zhin.js/game-kit';
|
|
1
|
+
import { plainTextFromSendContent, type GameMessageLike } from '@zhin.js/game-kit';
|
|
3
2
|
import {
|
|
4
3
|
CHAIN_PREFIX,
|
|
5
4
|
getGloss,
|
|
@@ -22,34 +21,13 @@ function sessionMode(session: ChainSessionRow): MatchMode {
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
export async function sendOrEditView(
|
|
25
|
-
plugin: Plugin | null,
|
|
26
24
|
services: SessionService,
|
|
27
|
-
message:
|
|
25
|
+
message: GameMessageLike,
|
|
28
26
|
session: ChainSessionRow,
|
|
29
27
|
eventLines: string[] = [],
|
|
30
|
-
): Promise<string
|
|
28
|
+
): Promise<string> {
|
|
31
29
|
const content = buildChainView(session, eventLines, message.$channel.type);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const adapter = plugin.root.inject(message.$adapter) as Adapter;
|
|
35
|
-
|
|
36
|
-
if (session.board_message_id) {
|
|
37
|
-
const msgId = await adapter.editMessage({
|
|
38
|
-
messageId: session.board_message_id,
|
|
39
|
-
context: String(message.$adapter),
|
|
40
|
-
endpoint: message.$endpoint,
|
|
41
|
-
id: message.$channel.id,
|
|
42
|
-
type: message.$channel.type,
|
|
43
|
-
content,
|
|
44
|
-
});
|
|
45
|
-
if (msgId !== session.board_message_id) {
|
|
46
|
-
await services.updateSession(session.id, { board_message_id: msgId });
|
|
47
|
-
}
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const msgId = await message.$reply?.(content);
|
|
52
|
-
if (msgId) await services.updateSession(session.id, { board_message_id: msgId });
|
|
30
|
+
return plainTextFromSendContent(content);
|
|
53
31
|
}
|
|
54
32
|
|
|
55
33
|
async function botTurn(
|
|
@@ -86,9 +64,8 @@ async function botTurn(
|
|
|
86
64
|
}
|
|
87
65
|
|
|
88
66
|
export async function startGame(
|
|
89
|
-
plugin: Plugin | null,
|
|
90
67
|
services: SessionService,
|
|
91
|
-
message:
|
|
68
|
+
message: GameMessageLike,
|
|
92
69
|
matchMode: MatchMode = 'pinyin',
|
|
93
70
|
): Promise<string | undefined> {
|
|
94
71
|
const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
|
|
@@ -111,7 +88,7 @@ export async function startGame(
|
|
|
111
88
|
});
|
|
112
89
|
|
|
113
90
|
const gloss = starter.gloss ?? getGloss(starter.text);
|
|
114
|
-
const text = await sendOrEditView(
|
|
91
|
+
const text = await sendOrEditView(services, message, session, [
|
|
115
92
|
`🎬 ${modeLabel(matchMode)}开局!我先出:**${starter.text}**${gloss ? `(${gloss})` : ''}`,
|
|
116
93
|
promptLine(starter.text, matchMode),
|
|
117
94
|
]);
|
|
@@ -119,24 +96,22 @@ export async function startGame(
|
|
|
119
96
|
}
|
|
120
97
|
|
|
121
98
|
export async function continueGame(
|
|
122
|
-
plugin: Plugin | null,
|
|
123
99
|
services: SessionService,
|
|
124
|
-
message:
|
|
100
|
+
message: GameMessageLike,
|
|
125
101
|
): Promise<string> {
|
|
126
102
|
const session = await services.getActiveForUser(
|
|
127
103
|
`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
|
|
128
104
|
message.$sender.id,
|
|
129
105
|
);
|
|
130
106
|
if (!session) return '你没有进行中的接龙,发送「接龙 开始」。';
|
|
131
|
-
const text = await sendOrEditView(
|
|
107
|
+
const text = await sendOrEditView(services, message, session);
|
|
132
108
|
if (typeof text === 'string') return text;
|
|
133
109
|
return '已刷新接龙界面。';
|
|
134
110
|
}
|
|
135
111
|
|
|
136
112
|
export async function processIdiomText(
|
|
137
|
-
plugin: Plugin | null,
|
|
138
113
|
services: SessionService,
|
|
139
|
-
message:
|
|
114
|
+
message: GameMessageLike,
|
|
140
115
|
raw: string,
|
|
141
116
|
): Promise<string | null> {
|
|
142
117
|
const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
|
|
@@ -146,6 +121,10 @@ export async function processIdiomText(
|
|
|
146
121
|
const mode = sessionMode(session);
|
|
147
122
|
const used = parseUsed(session.used_idioms);
|
|
148
123
|
const idiom = normalizeInput(raw);
|
|
124
|
+
// 格式不合规(非四字)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
|
|
125
|
+
if (!/^[\u4e00-\u9fff]{4}$/.test(idiom)) {
|
|
126
|
+
return '接龙请输入**四字成语**(这条不算失误)。';
|
|
127
|
+
}
|
|
149
128
|
const check = validatePlayerIdiom(idiom, session.last_idiom, mode, used);
|
|
150
129
|
if (!check.ok) {
|
|
151
130
|
const wrong = session.wrong_count + 1;
|
|
@@ -157,14 +136,14 @@ export async function processIdiomText(
|
|
|
157
136
|
streak: 0,
|
|
158
137
|
});
|
|
159
138
|
const updated = (await services.getById(session.id))!;
|
|
160
|
-
return (await sendOrEditView(
|
|
139
|
+
return (await sendOrEditView(services, message, updated, [
|
|
161
140
|
check.reason!,
|
|
162
141
|
'失误过多,本局结束。',
|
|
163
142
|
])) ?? null;
|
|
164
143
|
}
|
|
165
144
|
await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
|
|
166
145
|
const updated = (await services.getById(session.id))!;
|
|
167
|
-
return (await sendOrEditView(
|
|
146
|
+
return (await sendOrEditView(services, message, updated, [check.reason!])) ?? null;
|
|
168
147
|
}
|
|
169
148
|
|
|
170
149
|
used.add(idiom);
|
|
@@ -186,16 +165,15 @@ export async function processIdiomText(
|
|
|
186
165
|
const userLine = `✅ 你:${idiom}${gloss ? `(${gloss})` : ''}`;
|
|
187
166
|
|
|
188
167
|
const botResult = await botTurn(services, current, used);
|
|
189
|
-
return (await sendOrEditView(
|
|
168
|
+
return (await sendOrEditView(services, message, botResult.session, [
|
|
190
169
|
userLine,
|
|
191
170
|
...botResult.lines,
|
|
192
171
|
])) ?? null;
|
|
193
172
|
}
|
|
194
173
|
|
|
195
174
|
export async function handleChoice(
|
|
196
|
-
plugin: Plugin | null,
|
|
197
175
|
services: SessionService,
|
|
198
|
-
message:
|
|
176
|
+
message: GameMessageLike,
|
|
199
177
|
sessionId: string,
|
|
200
178
|
choiceId: string,
|
|
201
179
|
): Promise<string | null> {
|
|
@@ -221,7 +199,7 @@ export async function handleChoice(
|
|
|
221
199
|
});
|
|
222
200
|
const updated = (await services.getById(session.id))!;
|
|
223
201
|
const gloss = starter.gloss ?? getGloss(starter.text);
|
|
224
|
-
return (await sendOrEditView(
|
|
202
|
+
return (await sendOrEditView(services, message, updated, [
|
|
225
203
|
`🎬 新一局!我先出:**${starter.text}**${gloss ? `(${gloss})` : ''}`,
|
|
226
204
|
promptLine(starter.text, mode),
|
|
227
205
|
])) ?? null;
|
|
@@ -236,15 +214,17 @@ export async function handleChoice(
|
|
|
236
214
|
if (choiceId === 'hint') {
|
|
237
215
|
const hint = pickHintIdiom(session.last_idiom, mode, used);
|
|
238
216
|
if (!hint) {
|
|
239
|
-
|
|
217
|
+
// 先更新状态再单次发送终局视图,避免旧 session「你赢了」与终局视图双发
|
|
240
218
|
await services.updateSession(session.id, { status: 'won', player_score: session.player_score + 1 });
|
|
241
219
|
const updated = (await services.getById(session.id))!;
|
|
242
|
-
return (await sendOrEditView(
|
|
220
|
+
return (await sendOrEditView(services, message, updated, [
|
|
221
|
+
'💡 词库中暂无可用提示,你赢了!',
|
|
222
|
+
])) ?? null;
|
|
243
223
|
}
|
|
244
224
|
const gloss = getGloss(hint);
|
|
245
225
|
await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
|
|
246
226
|
const updated = (await services.getById(session.id))!;
|
|
247
|
-
return (await sendOrEditView(
|
|
227
|
+
return (await sendOrEditView(services, message, updated, [
|
|
248
228
|
`💡 提示:可试 **${hint}**${gloss ? `(${gloss})` : ''}`,
|
|
249
229
|
'(使用提示会清零连击)',
|
|
250
230
|
])) ?? null;
|
|
@@ -257,7 +237,7 @@ export async function handleChoice(
|
|
|
257
237
|
streak: 0,
|
|
258
238
|
});
|
|
259
239
|
const updated = (await services.getById(session.id))!;
|
|
260
|
-
return (await sendOrEditView(
|
|
240
|
+
return (await sendOrEditView(services, message, updated, [
|
|
261
241
|
'⏭️ 你选择跳过,机器人得一分。',
|
|
262
242
|
])) ?? null;
|
|
263
243
|
}
|
|
@@ -265,7 +245,7 @@ export async function handleChoice(
|
|
|
265
245
|
if (choiceId === 'quit') {
|
|
266
246
|
await services.updateSession(session.id, { status: 'lost', bot_score: session.bot_score + 1 });
|
|
267
247
|
const updated = (await services.getById(session.id))!;
|
|
268
|
-
return (await sendOrEditView(
|
|
248
|
+
return (await sendOrEditView(services, message, updated, ['🏳️ 你认输了。'])) ?? null;
|
|
269
249
|
}
|
|
270
250
|
|
|
271
251
|
return '未知操作。';
|
package/src/session-service.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Database,
|
|
2
|
-
import { channelKey, generateSessionId, boardMessageMatches } from '@zhin.js/game-kit';
|
|
1
|
+
import type { Database, Models, RelatedModel } from '@zhin.js/core';
|
|
2
|
+
import { channelKey, generateSessionId, boardMessageMatches , type GameMessageLike } from '@zhin.js/game-kit';
|
|
3
3
|
import type { MatchMode } from './engine.js';
|
|
4
4
|
import type { ChainSessionRow } from './models.js';
|
|
5
5
|
|
|
@@ -54,7 +54,7 @@ export class SessionService {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
async createSession(
|
|
57
|
-
message:
|
|
57
|
+
message: GameMessageLike,
|
|
58
58
|
starter: { text: string; nextChar: string; used: string[]; matchMode: MatchMode },
|
|
59
59
|
): Promise<ChainSessionRow> {
|
|
60
60
|
const now = Date.now();
|