@zhin.js/plugin-word-riddle 1.1.18 → 1.1.19

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.
@@ -1,17 +1,18 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { replyGameOperation, gamePlayerFromInput, normalizeRiddleAction } from '@zhin.js/game-kit';
2
3
  import { defineCommand } from 'zhin.js/command';
3
- import { messageFromCommandInput, normalizeRiddleAction } from '@zhin.js/game-kit';
4
4
  import { getRiddleHelp, runRiddleCommand } from "../../../lib/riddle-command.js";
5
5
  import { resolveGameServices } from "../../../lib/runtime-store.js";
6
6
  export default defineCommand({
7
7
  description: 'Word Riddle',
8
8
  params: { action: { type: 'string', default: '' } },
9
- async execute({ params, input, use, locale, formatCommand }) {
9
+ async execute({ params, input, use, locale, formatCommand, session }) {
10
10
  const action = normalizeRiddleAction(String(params.action ?? ''));
11
11
  if (!action || action === 'help')
12
12
  return getRiddleHelp({ locale, formatCommand });
13
13
  const services = resolveGameServices({ use });
14
- const message = messageFromCommandInput(input, { locale, formatCommand });
15
- return runRiddleCommand(services, message, action);
14
+ const message = gamePlayerFromInput(input, { locale, formatCommand });
15
+ await replyGameOperation({ session: services, player: message, reply: session?.reply,
16
+ run: () => runRiddleCommand(services, message, action) });
16
17
  },
17
18
  });
@@ -1,16 +1,17 @@
1
+ import { replyGameOperation, gamePlayerFromInput, normalizeRiddleAction } from '@zhin.js/game-kit';
1
2
  import { defineCommand } from 'zhin.js/command';
2
- import { messageFromCommandInput, normalizeRiddleAction } from '@zhin.js/game-kit';
3
3
  import { getRiddleHelp, runRiddleCommand } from '../../../src/riddle-command.js';
4
4
  import { resolveGameServices } from '../../../src/runtime-store.js';
5
5
 
6
6
  export default defineCommand({
7
7
  description: 'Word Riddle',
8
8
  params: { action: { type: 'string', default: '' } },
9
- async execute({ params, input, use, locale, formatCommand }) {
9
+ async execute({ params, input, use, locale, formatCommand, session }) {
10
10
  const action = normalizeRiddleAction(String(params.action ?? ''));
11
11
  if (!action || action === 'help') return getRiddleHelp({ locale, formatCommand });
12
12
  const services = resolveGameServices({ use });
13
- const message = messageFromCommandInput(input, { locale, formatCommand });
14
- return runRiddleCommand(services, message, action);
13
+ const message = gamePlayerFromInput(input, { locale, formatCommand });
14
+ await replyGameOperation({ session: services, player: message, reply: session?.reply,
15
+ run: () => runRiddleCommand(services, message, action) });
15
16
  },
16
17
  });
@@ -1,9 +1,9 @@
1
- import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
1
+ import { type GamePlayer, type GameReply } from '@zhin.js/game-kit';
2
2
  import { RIDDLE_PREFIX } from './engine.js';
3
3
  import type { RiddleType } from './riddles-catalog.js';
4
4
  import { type SessionService } from './session-service.js';
5
- export declare function startGame(services: SessionService, message: GameMessageLike, mode: RiddleType): Promise<GameReply | undefined>;
6
- export declare function continueGame(services: SessionService, message: GameMessageLike): Promise<GameReply>;
7
- export declare function processAnswerText(services: SessionService, message: GameMessageLike, raw: string): Promise<GameReply | null>;
8
- export declare function handleChoice(services: SessionService, message: GameMessageLike, sessionId: string, choiceId: string): Promise<GameReply | null>;
5
+ export declare function startGame(services: SessionService, message: GamePlayer, mode: RiddleType): Promise<GameReply | undefined>;
6
+ export declare function continueGame(services: SessionService, message: GamePlayer): Promise<GameReply>;
7
+ export declare function processAnswerText(services: SessionService, message: GamePlayer, raw: string): Promise<GameReply | null>;
8
+ export declare function handleChoice(services: SessionService, message: GamePlayer, sessionId: string, choiceId: string): Promise<GameReply | null>;
9
9
  export { RIDDLE_PREFIX };
package/lib/game-flow.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createMessages, resolveLocale } from 'zhin.js/i18n';
2
+ import { channelKey } from '@zhin.js/game-kit';
2
3
  import { answersFor, checkAnswer, getRiddleById, normalizeAnswer, RIDDLE_PREFIX, typeLabel, } from './engine.js';
3
4
  import { currentRiddleId, parseQueue, } from './session-service.js';
4
5
  import { buildRiddleView, MAX_WRONG } from './view.js';
@@ -8,7 +9,7 @@ import { buildRiddleView, MAX_WRONG } from './view.js';
8
9
  * and the text middleware return fresh text each turn.
9
10
  */
10
11
  function renderView(message, session, eventLines = []) {
11
- return buildRiddleView(session, eventLines, message.$channel.type);
12
+ return buildRiddleView(session, eventLines, message.target.kind);
12
13
  }
13
14
  async function advanceQuestion(services, session) {
14
15
  const queue = parseQueue(session.queue);
@@ -22,111 +23,119 @@ async function advanceQuestion(services, session) {
22
23
  return (await services.getById(session.id));
23
24
  }
24
25
  export async function startGame(services, message, mode) {
25
- const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
26
- const active = await services.getActiveByChannel(ch);
27
- const locale = resolveLocale(active ? active.locale : message.locale);
28
- if (active) {
29
- if (active.player_id === message.$sender.id) {
30
- return messages(locale, 'text1', { p0: typeLabel(active.mode, locale) });
31
- }
32
- return messages(locale, 'text2', { p0: active.player_name });
33
- }
34
- const session = await services.createSession(message, mode);
35
- return renderView(message, session);
26
+ return services.runInScope({ scope: channelKey(message), run: async () => {
27
+ const ch = channelKey(message);
28
+ const active = await services.getActiveByChannel(ch);
29
+ const locale = resolveLocale(active ? active.locale : message.locale);
30
+ if (active) {
31
+ if (active.player_id === message.sender.id) {
32
+ return messages(locale, 'text1', { p0: typeLabel(active.mode, locale) });
33
+ }
34
+ return messages(locale, 'text2', { p0: active.player_name });
35
+ }
36
+ const session = await services.createSession(message, mode);
37
+ return renderView(message, session);
38
+ } });
36
39
  }
37
40
  export async function continueGame(services, message) {
38
- const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
39
- const locale = resolveLocale(session ? session.locale : message.locale);
40
- if (!session)
41
- return messages(locale, 'text3');
42
- return renderView(message, session);
41
+ return services.runInScope({ scope: channelKey(message), run: async () => {
42
+ const session = await services.getActiveForUser(channelKey(message), message.sender.id);
43
+ const locale = resolveLocale(session ? session.locale : message.locale);
44
+ if (!session)
45
+ return messages(locale, 'text3');
46
+ return renderView(message, session);
47
+ } });
43
48
  }
44
49
  export async function processAnswerText(services, message, raw) {
45
- const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
46
- const session = await services.getActiveForUser(ch, message.$sender.id);
47
- const locale = resolveLocale(session ? session.locale : message.locale);
48
- if (!session || session.status !== 'active')
49
- return null;
50
- const riddleId = currentRiddleId(session);
51
- const entry = riddleId ? getRiddleById(riddleId) : undefined;
52
- if (!entry)
53
- return null;
54
- // 格式不合规(字数与答案不符)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
55
- const normalized = normalizeAnswer(raw);
56
- if (!answersFor(entry).some((a) => a.length === normalized.length)) {
57
- return messages(locale, 'text4', { p0: entry.answer.length });
58
- }
59
- if (checkAnswer(entry, raw)) {
60
- const streak = session.streak + 1;
61
- const best = Math.max(session.best_streak, streak);
62
- await services.updateSession(session.id, {
63
- score: session.score + 10 + Math.min(streak, 5),
64
- streak,
65
- best_streak: best,
66
- wrong_count: 0,
67
- });
68
- const after = await advanceQuestion(services, (await services.getById(session.id)));
69
- const explain = entry.explanation ? `\n📖 ${entry.explanation}` : '';
70
- return renderView(message, after, [
71
- messages(locale, 'text5', { p0: entry.answer, p1: explain }),
72
- messages(locale, 'text6', { p0: 10 + Math.min(streak, 5) }),
73
- ]);
74
- }
75
- const wrong = session.wrong_count + 1;
76
- if (wrong >= MAX_WRONG) {
77
- await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
78
- const after = await advanceQuestion(services, (await services.getById(session.id)));
79
- return renderView(message, after, [
80
- messages(locale, 'text7', { p0: entry.answer }),
81
- messages(locale, 'text8'),
82
- ]);
83
- }
84
- await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
85
- const updated = (await services.getById(session.id));
86
- return renderView(message, updated, [messages(locale, 'text9')]);
50
+ return services.runInScope({ scope: channelKey(message), run: async () => {
51
+ const ch = channelKey(message);
52
+ const session = await services.getActiveForUser(ch, message.sender.id);
53
+ const locale = resolveLocale(session ? session.locale : message.locale);
54
+ if (!session || session.status !== 'active')
55
+ return null;
56
+ const riddleId = currentRiddleId(session);
57
+ const entry = riddleId ? getRiddleById(riddleId) : undefined;
58
+ if (!entry)
59
+ return null;
60
+ // 格式不合规(字数与答案不符)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
61
+ const normalized = normalizeAnswer(raw);
62
+ if (!answersFor(entry).some((a) => a.length === normalized.length)) {
63
+ return messages(locale, 'text4', { p0: entry.answer.length });
64
+ }
65
+ if (checkAnswer(entry, raw)) {
66
+ const streak = session.streak + 1;
67
+ const best = Math.max(session.best_streak, streak);
68
+ await services.updateSession(session.id, {
69
+ score: session.score + 10 + Math.min(streak, 5),
70
+ streak,
71
+ best_streak: best,
72
+ wrong_count: 0,
73
+ });
74
+ const after = await advanceQuestion(services, (await services.getById(session.id)));
75
+ const explain = entry.explanation ? `\n📖 ${entry.explanation}` : '';
76
+ return renderView(message, after, [
77
+ messages(locale, 'text5', { p0: entry.answer, p1: explain }),
78
+ messages(locale, 'text6', { p0: 10 + Math.min(streak, 5) }),
79
+ ]);
80
+ }
81
+ const wrong = session.wrong_count + 1;
82
+ if (wrong >= MAX_WRONG) {
83
+ await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
84
+ const after = await advanceQuestion(services, (await services.getById(session.id)));
85
+ return renderView(message, after, [
86
+ messages(locale, 'text7', { p0: entry.answer }),
87
+ messages(locale, 'text8'),
88
+ ]);
89
+ }
90
+ await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
91
+ const updated = (await services.getById(session.id));
92
+ return renderView(message, updated, [messages(locale, 'text9')]);
93
+ } });
87
94
  }
88
95
  export async function handleChoice(services, message, sessionId, choiceId) {
89
- const session = await services.getById(sessionId);
90
- const locale = resolveLocale(session ? session.locale : message.locale);
91
- if (!session)
92
- return messages(locale, 'text10');
93
- if (session.player_id !== message.$sender.id)
94
- return messages(locale, 'text11');
95
- if (choiceId === 'restart_char') {
96
- await services.updateSession(session.id, { status: 'aborted' });
97
- return (await startGame(services, message, 'char')) ?? null;
98
- }
99
- if (choiceId === 'restart_idiom') {
100
- await services.updateSession(session.id, { status: 'aborted' });
101
- return (await startGame(services, message, 'idiom')) ?? null;
102
- }
103
- if (session.status !== 'active')
104
- return messages(locale, 'text12');
105
- const riddleId = currentRiddleId(session);
106
- const entry = riddleId ? getRiddleById(riddleId) : undefined;
107
- if (!entry)
108
- return messages(locale, 'text13');
109
- if (choiceId === 'hint') {
110
- const hint = entry.hint ?? messages(locale, 'text14', { p0: entry.answer.length });
111
- await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
112
- const updated = (await services.getById(session.id));
113
- return renderView(message, updated, [
114
- messages(locale, 'text15', { p0: hint }),
115
- messages(locale, 'text16'),
116
- ]);
117
- }
118
- if (choiceId === 'skip') {
119
- await services.updateSession(session.id, { streak: 0 });
120
- const after = await advanceQuestion(services, session);
121
- return renderView(message, after, [
122
- messages(locale, 'text17', { p0: entry.answer }),
123
- ]);
124
- }
125
- if (choiceId === 'quit') {
126
- await services.updateSession(session.id, { status: 'aborted' });
127
- return messages(locale, 'text18');
128
- }
129
- return messages(locale, 'text19');
96
+ return services.runInScope({ scope: channelKey(message), run: async () => {
97
+ const session = await services.getById(sessionId);
98
+ const locale = resolveLocale(session ? session.locale : message.locale);
99
+ if (!session)
100
+ return messages(locale, 'text10');
101
+ if (session.player_id !== message.sender.id)
102
+ return messages(locale, 'text11');
103
+ if (choiceId === 'restart_char') {
104
+ await services.updateSession(session.id, { status: 'aborted' });
105
+ return (await startGame(services, message, 'char')) ?? null;
106
+ }
107
+ if (choiceId === 'restart_idiom') {
108
+ await services.updateSession(session.id, { status: 'aborted' });
109
+ return (await startGame(services, message, 'idiom')) ?? null;
110
+ }
111
+ if (session.status !== 'active')
112
+ return messages(locale, 'text12');
113
+ const riddleId = currentRiddleId(session);
114
+ const entry = riddleId ? getRiddleById(riddleId) : undefined;
115
+ if (!entry)
116
+ return messages(locale, 'text13');
117
+ if (choiceId === 'hint') {
118
+ const hint = entry.hint ?? messages(locale, 'text14', { p0: entry.answer.length });
119
+ await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
120
+ const updated = (await services.getById(session.id));
121
+ return renderView(message, updated, [
122
+ messages(locale, 'text15', { p0: hint }),
123
+ messages(locale, 'text16'),
124
+ ]);
125
+ }
126
+ if (choiceId === 'skip') {
127
+ await services.updateSession(session.id, { streak: 0 });
128
+ const after = await advanceQuestion(services, session);
129
+ return renderView(message, after, [
130
+ messages(locale, 'text17', { p0: entry.answer }),
131
+ ]);
132
+ }
133
+ if (choiceId === 'quit') {
134
+ await services.updateSession(session.id, { status: 'aborted' });
135
+ return messages(locale, 'text18');
136
+ }
137
+ return messages(locale, 'text19');
138
+ } });
130
139
  }
131
140
  export { RIDDLE_PREFIX };
132
141
  const messages = createMessages({
@@ -1 +1 @@
1
- {"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
1
+ import { type GamePlayer, type GameReply } from '@zhin.js/game-kit';
2
2
  import type { SessionService } from './session-service.js';
3
- export declare function getRiddleHelp(message?: Pick<GameMessageLike, 'locale' | 'formatCommand'>): string;
3
+ export declare function getRiddleHelp(message?: Pick<GamePlayer, 'locale' | 'formatCommand'>): string;
4
4
  export declare const RIDDLE_HELP: string;
5
- export declare function runRiddleCommand(services: SessionService, message: GameMessageLike, action: string): Promise<GameReply>;
5
+ export declare function runRiddleCommand(services: SessionService, message: GamePlayer, action: string): Promise<GameReply>;
@@ -15,7 +15,7 @@ const messages = createMessages({
15
15
  export function getRiddleHelp(message = {}) {
16
16
  const locale = message.locale ?? 'zh-CN';
17
17
  const command = message.formatCommand?.('riddle');
18
- return [formatGameHelp(message, { 'zh-CN': '🧩 猜谜(字谜 + 猜成语)', en: '🧩 Chinese Character and Idiom Riddles' }, 'riddle', ['start', 'continue', 'quit']),
18
+ return [formatGameHelp({ presentation: message, title: { 'zh-CN': '🧩 猜谜(字谜 + 猜成语)', en: '🧩 Chinese Character and Idiom Riddles' }, commandPath: 'riddle', actions: ['start', 'continue', 'quit'] }),
19
19
  messages(locale, 'counts', { chars: counts.char.toLocaleString(locale), idioms: counts.idiom.toLocaleString(locale) }),
20
20
  ...(command ? [messages(locale, 'char', { command: command + ' char' }), messages(locale, 'idiom', { command: command + ' idiom' })] : []),
21
21
  messages(locale, 'instructions'),
@@ -32,32 +32,34 @@ function parseMode(action) {
32
32
  return null;
33
33
  }
34
34
  export async function runRiddleCommand(services, message, action) {
35
- const ch = channelKey(message);
36
- const userId = message.$sender.id;
37
- if (!action || action === 'help') {
38
- const active = await services.getActiveByChannel(ch);
39
- const lines = [getRiddleHelp(message), ''];
40
- if (active) {
41
- lines.push(messages(active.locale ?? undefined, 'active', { mode: typeLabel(active.mode, active.locale ?? undefined), score: active.score, streak: active.streak }));
42
- }
43
- else {
44
- lines.push(gameCommandFeedback(message, 'noGame'), gameCommandHint(message, 'riddle'));
45
- }
46
- return lines.join('\n');
47
- }
48
- const mode = parseMode(action);
49
- if (mode)
50
- return (await startGame(services, message, mode)) ?? '';
51
- if (action === 'continue' || action === '继续') {
52
- return continueGame(services, message);
53
- }
54
- if (action === 'quit' || action === '放弃') {
55
- const row = await services.getActiveForUser(ch, userId);
56
- if (!row)
57
- return gameCommandFeedback(message, 'noGame');
58
- await services.updateSession(row.id, { status: 'aborted' });
59
- return messages(row.locale ?? undefined, 'quit');
60
- }
61
- return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getRiddleHelp(message);
35
+ return services.runInScope({ scope: channelKey(message), run: async () => {
36
+ const ch = channelKey(message);
37
+ const userId = message.sender.id;
38
+ if (!action || action === 'help') {
39
+ const active = await services.getActiveByChannel(ch);
40
+ const lines = [getRiddleHelp(message), ''];
41
+ if (active) {
42
+ lines.push(messages(active.locale ?? undefined, 'active', { mode: typeLabel(active.mode, active.locale ?? undefined), score: active.score, streak: active.streak }));
43
+ }
44
+ else {
45
+ lines.push(gameCommandFeedback(message, 'noGame'), gameCommandHint(message, 'riddle'));
46
+ }
47
+ return lines.join('\n');
48
+ }
49
+ const mode = parseMode(action);
50
+ if (mode)
51
+ return (await startGame(services, message, mode)) ?? '';
52
+ if (action === 'continue' || action === '继续') {
53
+ return continueGame(services, message);
54
+ }
55
+ if (action === 'quit' || action === '放弃') {
56
+ const row = await services.getActiveForUser(ch, userId);
57
+ if (!row)
58
+ return gameCommandFeedback(message, 'noGame');
59
+ await services.updateSession(row.id, { status: 'aborted' });
60
+ return messages(row.locale ?? undefined, 'quit');
61
+ }
62
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getRiddleHelp(message);
63
+ } });
62
64
  }
63
65
  //# sourceMappingURL=riddle-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"riddle-command.js","sourceRoot":"","sources":["../src/riddle-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"riddle-command.js","sourceRoot":"","sources":["../src/riddle-command.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import type { Database, Models } from '@zhin.js/core';
2
- import { BaseSessionService, type GameMessageLike } from '@zhin.js/game-kit';
2
+ import { BaseSessionService, type GamePlayer } from '@zhin.js/game-kit';
3
3
  import { type RiddleType } from './riddles-catalog.js';
4
4
  import type { RiddleSessionRow } from './models.js';
5
5
  export type RiddleDatabase = Database<unknown, Models, string>;
6
6
  export declare function parseQueue(value: string | string[] | unknown): string[];
7
7
  export declare class SessionService extends BaseSessionService<RiddleSessionRow> {
8
8
  constructor(db: RiddleDatabase);
9
- createSession(message: GameMessageLike, mode: RiddleType): Promise<RiddleSessionRow>;
9
+ createSession(message: GamePlayer, mode: RiddleType): Promise<RiddleSessionRow>;
10
10
  }
11
11
  export declare function createServices(db: RiddleDatabase): SessionService;
12
12
  export declare function currentRiddleId(session: RiddleSessionRow): string | null;
@@ -1,4 +1,4 @@
1
- import { BaseSessionService, channelKey, generateSessionId, } from '@zhin.js/game-kit';
1
+ import { BaseSessionService, generateSessionId, } from '@zhin.js/game-kit';
2
2
  import { pickRoundQueue } from './riddles-catalog.js';
3
3
  export function parseQueue(value) {
4
4
  if (Array.isArray(value))
@@ -27,13 +27,8 @@ export class SessionService extends BaseSessionService {
27
27
  const row = {
28
28
  id: generateSessionId(),
29
29
  locale: message.locale ?? 'zh-CN',
30
- adapter: String(message.$adapter),
31
- endpoint: message.$endpoint,
32
- channel_type: message.$channel.type,
33
- channel_id: message.$channel.id,
34
- channel_key: channelKey(message),
35
- player_id: message.$sender.id,
36
- player_name: message.$sender.name?.trim() || message.$sender.id,
30
+ player_id: message.sender.id,
31
+ player_name: message.sender.name?.trim() || message.sender.id,
37
32
  mode,
38
33
  queue: JSON.stringify(queue),
39
34
  index: 0,
@@ -46,7 +41,7 @@ export class SessionService extends BaseSessionService {
46
41
  updated_at: now,
47
42
  created_at: now,
48
43
  };
49
- return this.createRow(row);
44
+ return this.createRow({ target: message.target, fields: row });
50
45
  }
51
46
  }
52
47
  export function createServices(db) {
@@ -1 +1 @@
1
- {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAKvE,MAAM,UAAU,UAAU,CAAC,KAAkC;IAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IACzF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,cAAe,SAAQ,kBAAoC;IACtE,YAAY,EAAkB;QAC5B,KAAK,CAAC,EAAsD,EAAE;YAC5D,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,sBAAsB;YAC7B,UAAU,EAAE,CAAC,WAAW,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAwB,EAAE,IAAgB;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,GAAG,GAAqB;YAC5B,EAAE,EAAE,iBAAiB,EAAE;YACvB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO;YACjC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjC,QAAQ,EAAE,OAAO,CAAC,SAAS;YAC3B,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;YACnC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE;YAC/B,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC;YAChC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAC/D,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAkB;IAC/C,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAGD,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAKvE,MAAM,UAAU,UAAU,CAAC,KAAkC;IAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IACzF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,cAAe,SAAQ,kBAAoC;IACtE,YAAY,EAAkB;QAC5B,KAAK,CAAC,EAAsD,EAAE;YAC5D,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,sBAAsB;YAC7B,UAAU,EAAE,CAAC,WAAW,CAAC;SAC1B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAmB,EAAE,IAAgB;QACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,GAAG,GAAmG;YAC1G,EAAE,EAAE,iBAAiB,EAAE;YACvB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO;YACjC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE;YAC5B,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE;YAC7D,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC5B,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,MAAM,EAAE,QAAQ;YAChB,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;SAChB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACjE,CAAC;CACF;AAED,MAAM,UAAU,cAAc,CAAC,EAAkB;IAC/C,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAGD,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACtC,CAAC"}
@@ -1,20 +1,24 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
- import { defineGameCommandAliasMiddleware, isRiddleAction, messageFromCommandInput, normalizeRiddleAction, } from '@zhin.js/game-kit';
2
+ import { replyGameOperation, defineGameCommandAliasMiddleware, isRiddleAction, gamePlayerFromInput, normalizeRiddleAction, } from '@zhin.js/game-kit';
3
3
  import { getRiddleHelp, runRiddleCommand } from "../../lib/riddle-command.js";
4
4
  import { resolveGameServices } from "../../lib/runtime-store.js";
5
5
  export default defineGameCommandAliasMiddleware({
6
6
  aliases: ['猜谜', 'riddle'],
7
7
  async run(action, input, context) {
8
- const message = messageFromCommandInput(input, {
9
- formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
10
- });
8
+ const presentation = { locale: context.input.locale,
9
+ formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id) };
11
10
  const normalized = normalizeRiddleAction(String(action ?? ''));
12
- if (normalized === 'help')
13
- return getRiddleHelp(message);
11
+ if (normalized === 'help') {
12
+ await context.input.$reply(getRiddleHelp(presentation));
13
+ return true;
14
+ }
14
15
  // action 无法识别:放行给后续中间件,避免劫持普通聊天
15
16
  if (!isRiddleAction(normalized))
16
- return null;
17
+ return false;
18
+ const message = gamePlayerFromInput(input, presentation);
17
19
  const services = resolveGameServices(context);
18
- return runRiddleCommand(services, message, normalized);
20
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
21
+ run: () => runRiddleCommand(services, message, normalized) });
22
+ return true;
19
23
  },
20
24
  });
@@ -1,7 +1,8 @@
1
1
  import {
2
+ replyGameOperation,
2
3
  defineGameCommandAliasMiddleware,
3
4
  isRiddleAction,
4
- messageFromCommandInput,
5
+ gamePlayerFromInput,
5
6
  normalizeRiddleAction,
6
7
  } from '@zhin.js/game-kit';
7
8
  import { getRiddleHelp, runRiddleCommand } from '../../src/riddle-command.js';
@@ -10,14 +11,17 @@ import { resolveGameServices } from '../../src/runtime-store.js';
10
11
  export default defineGameCommandAliasMiddleware({
11
12
  aliases: ['猜谜', 'riddle'],
12
13
  async run(action, input, context) {
13
- const message = messageFromCommandInput(input, {
14
- formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
15
- });
14
+ const presentation = { locale: context.input.locale,
15
+ formatCommand: (path: string) => context.input.formatCommand?.(path, context.owner.id) };
16
+
16
17
  const normalized = normalizeRiddleAction(String(action ?? ''));
17
- if (normalized === 'help') return getRiddleHelp(message);
18
+ if (normalized === 'help') { await context.input.$reply(getRiddleHelp(presentation)); return true; }
18
19
  // action 无法识别:放行给后续中间件,避免劫持普通聊天
19
- if (!isRiddleAction(normalized)) return null;
20
+ if (!isRiddleAction(normalized)) return false;
21
+ const message = gamePlayerFromInput(input, presentation);
20
22
  const services = resolveGameServices(context);
21
- return runRiddleCommand(services, message, normalized);
23
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
24
+ run: () => runRiddleCommand(services, message, normalized) });
25
+ return true;
22
26
  },
23
27
  });
@@ -1,6 +1,6 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { replyGameOperation, buildChoiceFallbackMap, channelKey, gamePlayerFromInput, parseChoicePayload, resolveGameTextPayload, } from '@zhin.js/game-kit';
2
3
  import { defineMiddleware } from 'zhin.js/middleware';
3
- import { buildChoiceFallbackMap, channelKey, messageFromCommandInput, parseChoicePayload, resolveGameTextPayload, } from '@zhin.js/game-kit';
4
4
  import { resolveGameServices } from "../../lib/runtime-store.js";
5
5
  import { handleChoice, processAnswerText, RIDDLE_PREFIX } from "../../lib/game-flow.js";
6
6
  /**
@@ -10,13 +10,17 @@ import { handleChoice, processAnswerText, RIDDLE_PREFIX } from "../../lib/game-f
10
10
  export default defineMiddleware({
11
11
  target: 'inbound',
12
12
  async handle(context, next) {
13
+ if (!context.input.sender?.id) {
14
+ await next();
15
+ return;
16
+ }
13
17
  const raw = context.input.content?.trim() ?? '';
14
18
  if (!raw) {
15
19
  await next();
16
20
  return;
17
21
  }
18
22
  const services = resolveGameServices(context);
19
- const message = messageFromCommandInput(context.input);
23
+ const message = gamePlayerFromInput(context.input);
20
24
  const ch = channelKey(message);
21
25
  // 直接 payload(QQ 指令预填 / Sandbox action→text)
22
26
  const payloadFromText = resolveGameTextPayload(raw);
@@ -25,16 +29,15 @@ export default defineMiddleware({
25
29
  if (parsed) {
26
30
  const session = await services.getById(parsed.sessionId);
27
31
  if (session?.channel_key === ch) {
28
- const reply = await handleChoice(services, message, parsed.sessionId, parsed.choiceId);
29
- if (reply)
30
- await context.input.$reply(reply);
32
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
33
+ run: () => handleChoice(services, message, parsed.sessionId, parsed.choiceId) });
31
34
  return;
32
35
  }
33
36
  }
34
37
  await next();
35
38
  return;
36
39
  }
37
- const session = await services.getActiveForUser(ch, message.$sender.id);
40
+ const session = await services.getActiveForUser(ch, message.sender.id);
38
41
  if (!session) {
39
42
  await next();
40
43
  return;
@@ -48,17 +51,15 @@ export default defineMiddleware({
48
51
  const payload = resolveGameTextPayload(raw, map);
49
52
  const parsed = payload ? parseChoicePayload(payload, RIDDLE_PREFIX) : null;
50
53
  if (parsed?.sessionId === session.id) {
51
- const reply = await handleChoice(services, message, session.id, parsed.choiceId);
52
- if (reply)
53
- await context.input.$reply(reply);
54
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
55
+ run: () => handleChoice(services, message, session.id, parsed.choiceId) });
54
56
  return;
55
57
  }
56
58
  }
57
59
  // 仅把 1-8 个汉字的纯文本当谜底作答,其余放行
58
60
  if (/^[\u4e00-\u9fff]{1,8}$/.test(raw)) {
59
- const reply = await processAnswerText(services, message, raw);
60
- if (reply)
61
- await context.input.$reply(reply);
61
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
62
+ run: () => processAnswerText(services, message, raw) });
62
63
  return;
63
64
  }
64
65
  await next();
@@ -1,12 +1,13 @@
1
- import { defineMiddleware } from 'zhin.js/middleware';
2
- import type { Message } from '@zhin.js/core/runtime';
3
1
  import {
2
+ replyGameOperation,
4
3
  buildChoiceFallbackMap,
5
4
  channelKey,
6
- messageFromCommandInput,
5
+ gamePlayerFromInput,
7
6
  parseChoicePayload,
8
7
  resolveGameTextPayload,
9
8
  } from '@zhin.js/game-kit';
9
+ import { defineMiddleware } from 'zhin.js/middleware';
10
+ import type { Message } from '@zhin.js/core/runtime';
10
11
  import { resolveGameServices } from '../../src/runtime-store.js';
11
12
  import { handleChoice, processAnswerText, RIDDLE_PREFIX } from '../../src/game-flow.js';
12
13
 
@@ -17,13 +18,14 @@ import { handleChoice, processAnswerText, RIDDLE_PREFIX } from '../../src/game-f
17
18
  export default defineMiddleware<Message>({
18
19
  target: 'inbound',
19
20
  async handle(context, next) {
21
+ if (!context.input.sender?.id) { await next(); return; }
20
22
  const raw = context.input.content?.trim() ?? '';
21
23
  if (!raw) {
22
24
  await next();
23
25
  return;
24
26
  }
25
27
  const services = resolveGameServices(context);
26
- const message = messageFromCommandInput(context.input);
28
+ const message = gamePlayerFromInput(context.input);
27
29
  const ch = channelKey(message);
28
30
 
29
31
  // 直接 payload(QQ 指令预填 / Sandbox action→text)
@@ -33,8 +35,8 @@ export default defineMiddleware<Message>({
33
35
  if (parsed) {
34
36
  const session = await services.getById(parsed.sessionId);
35
37
  if (session?.channel_key === ch) {
36
- const reply = await handleChoice(services, message, parsed.sessionId, parsed.choiceId);
37
- if (reply) await context.input.$reply(reply);
38
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
39
+ run: () => handleChoice(services, message, parsed.sessionId, parsed.choiceId) });
38
40
  return;
39
41
  }
40
42
  }
@@ -42,7 +44,7 @@ export default defineMiddleware<Message>({
42
44
  return;
43
45
  }
44
46
 
45
- const session = await services.getActiveForUser(ch, message.$sender.id);
47
+ const session = await services.getActiveForUser(ch, message.sender.id);
46
48
  if (!session) {
47
49
  await next();
48
50
  return;
@@ -57,16 +59,16 @@ export default defineMiddleware<Message>({
57
59
  const payload = resolveGameTextPayload(raw, map);
58
60
  const parsed = payload ? parseChoicePayload(payload, RIDDLE_PREFIX) : null;
59
61
  if (parsed?.sessionId === session.id) {
60
- const reply = await handleChoice(services, message, session.id, parsed.choiceId);
61
- if (reply) await context.input.$reply(reply);
62
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
63
+ run: () => handleChoice(services, message, session.id, parsed.choiceId) });
62
64
  return;
63
65
  }
64
66
  }
65
67
 
66
68
  // 仅把 1-8 个汉字的纯文本当谜底作答,其余放行
67
69
  if (/^[\u4e00-\u9fff]{1,8}$/.test(raw)) {
68
- const reply = await processAnswerText(services, message, raw);
69
- if (reply) await context.input.$reply(reply);
70
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
71
+ run: () => processAnswerText(services, message, raw) });
70
72
  return;
71
73
  }
72
74
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-word-riddle",
3
- "version": "1.1.18",
3
+ "version": "1.1.19",
4
4
  "description": "Zhin.js 猜谜 — 字谜与猜成语 (Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -24,13 +24,13 @@
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
26
  "chinese-idiom-chengyu": "^1.1.0",
27
- "@zhin.js/core": "1.1.53",
28
- "@zhin.js/game-kit": "1.1.18"
27
+ "@zhin.js/core": "1.1.54",
28
+ "@zhin.js/game-kit": "1.1.19"
29
29
  },
30
30
  "devDependencies": {
31
31
  "typescript": "^6.0.3",
32
32
  "vitest": "^4.1.10",
33
- "zhin.js": "1.1.18"
33
+ "zhin.js": "1.1.19"
34
34
  },
35
35
  "repository": {
36
36
  "type": "git",
@@ -67,9 +67,9 @@
67
67
  "plugins": []
68
68
  },
69
69
  "peerDependencies": {
70
- "@zhin.js/command": "^1.1.11",
71
- "@zhin.js/middleware": "^1.1.10",
72
- "zhin.js": "^1.1.18"
70
+ "@zhin.js/command": "^1.1.12",
71
+ "@zhin.js/middleware": "^1.1.11",
72
+ "zhin.js": "^1.1.19"
73
73
  },
74
74
  "peerDependenciesMeta": {
75
75
  "@zhin.js/command": {
package/src/game-flow.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createMessages, resolveLocale } from 'zhin.js/i18n';
2
- import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
2
+ import { channelKey, type GamePlayer, type GameReply } from '@zhin.js/game-kit';
3
3
  import {
4
4
  answersFor,
5
5
  checkAnswer,
@@ -23,11 +23,11 @@ import { buildRiddleView, MAX_WRONG } from './view.js';
23
23
  * and the text middleware return fresh text each turn.
24
24
  */
25
25
  function renderView(
26
- message: GameMessageLike,
26
+ message: GamePlayer,
27
27
  session: RiddleSessionRow,
28
28
  eventLines: string[] = [],
29
29
  ): GameReply {
30
- return buildRiddleView(session, eventLines, message.$channel.type);
30
+ return buildRiddleView(session, eventLines, message.target.kind);
31
31
  }
32
32
 
33
33
  async function advanceQuestion(
@@ -46,138 +46,146 @@ async function advanceQuestion(
46
46
 
47
47
  export async function startGame(
48
48
  services: SessionService,
49
- message: GameMessageLike,
49
+ message: GamePlayer,
50
50
  mode: RiddleType,
51
51
  ): Promise<GameReply | undefined> {
52
- const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
53
- const active = await services.getActiveByChannel(ch);
54
- const locale = resolveLocale(active ? active.locale : message.locale);
55
- if (active) {
56
- if (active.player_id === message.$sender.id) {
57
- return messages(locale, 'text1', { p0: typeLabel(active.mode as RiddleType, locale) });
52
+ return services.runInScope({ scope: channelKey(message), run: async () => {
53
+ const ch = channelKey(message);
54
+ const active = await services.getActiveByChannel(ch);
55
+ const locale = resolveLocale(active ? active.locale : message.locale);
56
+ if (active) {
57
+ if (active.player_id === message.sender.id) {
58
+ return messages(locale, 'text1', { p0: typeLabel(active.mode as RiddleType, locale) });
59
+ }
60
+ return messages(locale, 'text2', { p0: active.player_name });
58
61
  }
59
- return messages(locale, 'text2', { p0: active.player_name });
60
- }
61
62
 
62
- const session = await services.createSession(message, mode);
63
- return renderView(message, session);
63
+ const session = await services.createSession(message, mode);
64
+ return renderView(message, session);
65
+ } });
64
66
  }
65
67
 
66
68
  export async function continueGame(
67
69
  services: SessionService,
68
- message: GameMessageLike,
70
+ message: GamePlayer,
69
71
  ): Promise<GameReply> {
70
- const session = await services.getActiveForUser(
71
- `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
72
- message.$sender.id,
73
- );
74
- const locale = resolveLocale(session ? session.locale : message.locale);
75
- if (!session) return messages(locale, 'text3');
76
- return renderView(message, session);
72
+ return services.runInScope({ scope: channelKey(message), run: async () => {
73
+ const session = await services.getActiveForUser(
74
+ channelKey(message),
75
+ message.sender.id,
76
+ );
77
+ const locale = resolveLocale(session ? session.locale : message.locale);
78
+ if (!session) return messages(locale, 'text3');
79
+ return renderView(message, session);
80
+ } });
77
81
  }
78
82
 
79
83
  export async function processAnswerText(
80
84
  services: SessionService,
81
- message: GameMessageLike,
85
+ message: GamePlayer,
82
86
  raw: string,
83
87
  ): Promise<GameReply | null> {
84
- const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
85
- const session = await services.getActiveForUser(ch, message.$sender.id);
86
- const locale = resolveLocale(session ? session.locale : message.locale);
87
- if (!session || session.status !== 'active') return null;
88
-
89
- const riddleId = currentRiddleId(session);
90
- const entry = riddleId ? getRiddleById(riddleId) : undefined;
91
- if (!entry) return null;
92
-
93
- // 格式不合规(字数与答案不符)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
94
- const normalized = normalizeAnswer(raw);
95
- if (!answersFor(entry).some((a) => a.length === normalized.length)) {
96
- return messages(locale, 'text4', { p0: entry.answer.length });
97
- }
88
+ return services.runInScope({ scope: channelKey(message), run: async () => {
89
+ const ch = channelKey(message);
90
+ const session = await services.getActiveForUser(ch, message.sender.id);
91
+ const locale = resolveLocale(session ? session.locale : message.locale);
92
+ if (!session || session.status !== 'active') return null;
93
+
94
+ const riddleId = currentRiddleId(session);
95
+ const entry = riddleId ? getRiddleById(riddleId) : undefined;
96
+ if (!entry) return null;
97
+
98
+ // 格式不合规(字数与答案不符)只提示、不扣失误:避免闲聊(「好的」「谢谢」)被累计判负
99
+ const normalized = normalizeAnswer(raw);
100
+ if (!answersFor(entry).some((a) => a.length === normalized.length)) {
101
+ return messages(locale, 'text4', { p0: entry.answer.length });
102
+ }
98
103
 
99
- if (checkAnswer(entry, raw)) {
100
- const streak = session.streak + 1;
101
- const best = Math.max(session.best_streak, streak);
102
- await services.updateSession(session.id, {
103
- score: session.score + 10 + Math.min(streak, 5),
104
- streak,
105
- best_streak: best,
106
- wrong_count: 0,
107
- });
108
- const after = await advanceQuestion(services, (await services.getById(session.id))!);
109
- const explain = entry.explanation ? `\n📖 ${entry.explanation}` : '';
110
- return renderView(message, after, [
111
- messages(locale, 'text5', { p0: entry.answer, p1: explain }),
112
- messages(locale, 'text6', { p0: 10 + Math.min(streak, 5) }),
113
- ]);
114
- }
104
+ if (checkAnswer(entry, raw)) {
105
+ const streak = session.streak + 1;
106
+ const best = Math.max(session.best_streak, streak);
107
+ await services.updateSession(session.id, {
108
+ score: session.score + 10 + Math.min(streak, 5),
109
+ streak,
110
+ best_streak: best,
111
+ wrong_count: 0,
112
+ });
113
+ const after = await advanceQuestion(services, (await services.getById(session.id))!);
114
+ const explain = entry.explanation ? `\n📖 ${entry.explanation}` : '';
115
+ return renderView(message, after, [
116
+ messages(locale, 'text5', { p0: entry.answer, p1: explain }),
117
+ messages(locale, 'text6', { p0: 10 + Math.min(streak, 5) }),
118
+ ]);
119
+ }
115
120
 
116
- const wrong = session.wrong_count + 1;
117
- if (wrong >= MAX_WRONG) {
118
- await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
119
- const after = await advanceQuestion(services, (await services.getById(session.id))!);
120
- return renderView(message, after, [
121
- messages(locale, 'text7', { p0: entry.answer }),
122
- messages(locale, 'text8'),
123
- ]);
124
- }
121
+ const wrong = session.wrong_count + 1;
122
+ if (wrong >= MAX_WRONG) {
123
+ await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
124
+ const after = await advanceQuestion(services, (await services.getById(session.id))!);
125
+ return renderView(message, after, [
126
+ messages(locale, 'text7', { p0: entry.answer }),
127
+ messages(locale, 'text8'),
128
+ ]);
129
+ }
125
130
 
126
- await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
127
- const updated = (await services.getById(session.id))!;
128
- return renderView(message, updated, [messages(locale, 'text9')]);
131
+ await services.updateSession(session.id, { wrong_count: wrong, streak: 0 });
132
+ const updated = (await services.getById(session.id))!;
133
+ return renderView(message, updated, [messages(locale, 'text9')]);
134
+ } });
129
135
  }
130
136
 
131
137
  export async function handleChoice(
132
138
  services: SessionService,
133
- message: GameMessageLike,
139
+ message: GamePlayer,
134
140
  sessionId: string,
135
141
  choiceId: string,
136
142
  ): Promise<GameReply | null> {
137
- const session = await services.getById(sessionId);
138
- const locale = resolveLocale(session ? session.locale : message.locale);
139
- if (!session) return messages(locale, 'text10');
140
- if (session.player_id !== message.$sender.id) return messages(locale, 'text11');
141
-
142
- if (choiceId === 'restart_char') {
143
- await services.updateSession(session.id, { status: 'aborted' });
144
- return (await startGame(services, message, 'char')) ?? null;
145
- }
146
- if (choiceId === 'restart_idiom') {
147
- await services.updateSession(session.id, { status: 'aborted' });
148
- return (await startGame(services, message, 'idiom')) ?? null;
149
- }
143
+ return services.runInScope({ scope: channelKey(message), run: async () => {
144
+ const session = await services.getById(sessionId);
145
+ const locale = resolveLocale(session ? session.locale : message.locale);
146
+ if (!session) return messages(locale, 'text10');
147
+ if (session.player_id !== message.sender.id) return messages(locale, 'text11');
148
+
149
+ if (choiceId === 'restart_char') {
150
+ await services.updateSession(session.id, { status: 'aborted' });
151
+ return (await startGame(services, message, 'char')) ?? null;
152
+ }
153
+ if (choiceId === 'restart_idiom') {
154
+ await services.updateSession(session.id, { status: 'aborted' });
155
+ return (await startGame(services, message, 'idiom')) ?? null;
156
+ }
150
157
 
151
- if (session.status !== 'active') return messages(locale, 'text12');
158
+ if (session.status !== 'active') return messages(locale, 'text12');
152
159
 
153
- const riddleId = currentRiddleId(session);
154
- const entry = riddleId ? getRiddleById(riddleId) : undefined;
155
- if (!entry) return messages(locale, 'text13');
160
+ const riddleId = currentRiddleId(session);
161
+ const entry = riddleId ? getRiddleById(riddleId) : undefined;
162
+ if (!entry) return messages(locale, 'text13');
156
163
 
157
- if (choiceId === 'hint') {
158
- const hint = entry.hint ?? messages(locale, 'text14', { p0: entry.answer.length });
159
- await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
160
- const updated = (await services.getById(session.id))!;
161
- return renderView(message, updated, [
162
- messages(locale, 'text15', { p0: hint }),
163
- messages(locale, 'text16'),
164
- ]);
165
- }
164
+ if (choiceId === 'hint') {
165
+ const hint = entry.hint ?? messages(locale, 'text14', { p0: entry.answer.length });
166
+ await services.updateSession(session.id, { hints_used: session.hints_used + 1, streak: 0 });
167
+ const updated = (await services.getById(session.id))!;
168
+ return renderView(message, updated, [
169
+ messages(locale, 'text15', { p0: hint }),
170
+ messages(locale, 'text16'),
171
+ ]);
172
+ }
166
173
 
167
- if (choiceId === 'skip') {
168
- await services.updateSession(session.id, { streak: 0 });
169
- const after = await advanceQuestion(services, session);
170
- return renderView(message, after, [
171
- messages(locale, 'text17', { p0: entry.answer }),
172
- ]);
173
- }
174
+ if (choiceId === 'skip') {
175
+ await services.updateSession(session.id, { streak: 0 });
176
+ const after = await advanceQuestion(services, session);
177
+ return renderView(message, after, [
178
+ messages(locale, 'text17', { p0: entry.answer }),
179
+ ]);
180
+ }
174
181
 
175
- if (choiceId === 'quit') {
176
- await services.updateSession(session.id, { status: 'aborted' });
177
- return messages(locale, 'text18');
178
- }
182
+ if (choiceId === 'quit') {
183
+ await services.updateSession(session.id, { status: 'aborted' });
184
+ return messages(locale, 'text18');
185
+ }
179
186
 
180
- return messages(locale, 'text19');
187
+ return messages(locale, 'text19');
188
+ } });
181
189
  }
182
190
 
183
191
  export { RIDDLE_PREFIX };
@@ -1,4 +1,4 @@
1
- import { formatGameHelp, gameCommandFeedback, gameCommandHint, channelKey, type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
1
+ import { formatGameHelp, gameCommandFeedback, gameCommandHint, channelKey, type GamePlayer, type GameReply } from '@zhin.js/game-kit';
2
2
  import { createMessages } from 'zhin.js/i18n';
3
3
  import { continueGame, startGame } from './game-flow.js';
4
4
  import { riddleCount, type RiddleType } from './riddles-catalog.js';
@@ -18,10 +18,10 @@ const messages = createMessages({
18
18
  quit: { 'zh-CN': '已放弃猜谜。', en: 'You quit the riddle game.' },
19
19
  });
20
20
 
21
- export function getRiddleHelp(message: Pick<GameMessageLike, 'locale' | 'formatCommand'> = {}): string {
21
+ export function getRiddleHelp(message: Pick<GamePlayer, 'locale' | 'formatCommand'> = {}): string {
22
22
  const locale = message.locale ?? 'zh-CN';
23
23
  const command = message.formatCommand?.('riddle');
24
- return [formatGameHelp(message, { 'zh-CN': '🧩 猜谜(字谜 + 猜成语)', en: '🧩 Chinese Character and Idiom Riddles' }, 'riddle', ['start', 'continue', 'quit']),
24
+ return [formatGameHelp({ presentation: message, title: { 'zh-CN': '🧩 猜谜(字谜 + 猜成语)', en: '🧩 Chinese Character and Idiom Riddles' }, commandPath: 'riddle', actions: ['start', 'continue', 'quit'] }),
25
25
  messages(locale, 'counts', { chars: counts.char.toLocaleString(locale), idioms: counts.idiom.toLocaleString(locale) }),
26
26
  ...(command ? [messages(locale, 'char', { command: command + ' char' }), messages(locale, 'idiom', { command: command + ' idiom' })] : []),
27
27
  messages(locale, 'instructions'),
@@ -38,36 +38,38 @@ function parseMode(action: string): RiddleType | null {
38
38
 
39
39
  export async function runRiddleCommand(
40
40
  services: SessionService,
41
- message: GameMessageLike,
41
+ message: GamePlayer,
42
42
  action: string,
43
43
  ): Promise<GameReply> {
44
- const ch = channelKey(message);
45
- const userId = message.$sender.id;
44
+ return services.runInScope({ scope: channelKey(message), run: async () => {
45
+ const ch = channelKey(message);
46
+ const userId = message.sender.id;
46
47
 
47
- if (!action || action === 'help') {
48
- const active = await services.getActiveByChannel(ch);
49
- const lines = [getRiddleHelp(message), ''];
50
- if (active) {
51
- lines.push(messages(active.locale ?? undefined, 'active', { mode: typeLabel(active.mode as RiddleType, active.locale ?? undefined), score: active.score, streak: active.streak }));
52
- } else {
53
- lines.push(gameCommandFeedback(message, 'noGame'), gameCommandHint(message, 'riddle'));
48
+ if (!action || action === 'help') {
49
+ const active = await services.getActiveByChannel(ch);
50
+ const lines = [getRiddleHelp(message), ''];
51
+ if (active) {
52
+ lines.push(messages(active.locale ?? undefined, 'active', { mode: typeLabel(active.mode as RiddleType, active.locale ?? undefined), score: active.score, streak: active.streak }));
53
+ } else {
54
+ lines.push(gameCommandFeedback(message, 'noGame'), gameCommandHint(message, 'riddle'));
55
+ }
56
+ return lines.join('\n');
54
57
  }
55
- return lines.join('\n');
56
- }
57
58
 
58
- const mode = parseMode(action);
59
- if (mode) return (await startGame(services, message, mode)) ?? '';
59
+ const mode = parseMode(action);
60
+ if (mode) return (await startGame(services, message, mode)) ?? '';
60
61
 
61
- if (action === 'continue' || action === '继续') {
62
- return continueGame(services, message);
63
- }
62
+ if (action === 'continue' || action === '继续') {
63
+ return continueGame(services, message);
64
+ }
64
65
 
65
- if (action === 'quit' || action === '放弃') {
66
- const row = await services.getActiveForUser(ch, userId);
67
- if (!row) return gameCommandFeedback(message, 'noGame');
68
- await services.updateSession(row.id, { status: 'aborted' });
69
- return messages(row.locale ?? undefined, 'quit');
70
- }
66
+ if (action === 'quit' || action === '放弃') {
67
+ const row = await services.getActiveForUser(ch, userId);
68
+ if (!row) return gameCommandFeedback(message, 'noGame');
69
+ await services.updateSession(row.id, { status: 'aborted' });
70
+ return messages(row.locale ?? undefined, 'quit');
71
+ }
71
72
 
72
- return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getRiddleHelp(message);
73
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getRiddleHelp(message);
74
+ } });
73
75
  }
@@ -1,9 +1,8 @@
1
1
  import type { Database, Models } from '@zhin.js/core';
2
2
  import {
3
3
  BaseSessionService,
4
- channelKey,
5
4
  generateSessionId,
6
- type GameMessageLike,
5
+ type GamePlayer,
7
6
  type GameSessionDatabase,
8
7
  } from '@zhin.js/game-kit';
9
8
  import { pickRoundQueue, type RiddleType } from './riddles-catalog.js';
@@ -31,19 +30,14 @@ export class SessionService extends BaseSessionService<RiddleSessionRow> {
31
30
  });
32
31
  }
33
32
 
34
- async createSession(message: GameMessageLike, mode: RiddleType): Promise<RiddleSessionRow> {
33
+ async createSession(message: GamePlayer, mode: RiddleType): Promise<RiddleSessionRow> {
35
34
  const now = Date.now();
36
35
  const queue = pickRoundQueue(mode).map((r) => r.id);
37
- const row: RiddleSessionRow = {
36
+ const row: Omit<RiddleSessionRow, 'channel_key' | 'adapter' | 'endpoint' | 'channel_type' | 'channel_id'> = {
38
37
  id: generateSessionId(),
39
38
  locale: message.locale ?? 'zh-CN',
40
- adapter: String(message.$adapter),
41
- endpoint: message.$endpoint,
42
- channel_type: message.$channel.type,
43
- channel_id: message.$channel.id,
44
- channel_key: channelKey(message),
45
- player_id: message.$sender.id,
46
- player_name: message.$sender.name?.trim() || message.$sender.id,
39
+ player_id: message.sender.id,
40
+ player_name: message.sender.name?.trim() || message.sender.id,
47
41
  mode,
48
42
  queue: JSON.stringify(queue),
49
43
  index: 0,
@@ -56,7 +50,7 @@ export class SessionService extends BaseSessionService<RiddleSessionRow> {
56
50
  updated_at: now,
57
51
  created_at: now,
58
52
  };
59
- return this.createRow(row);
53
+ return this.createRow({ target: message.target, fields: row });
60
54
  }
61
55
  }
62
56