@zhin.js/plugin-guess-number 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/commands/guess/[action:string=].ts +15 -0
- package/lib/engine.d.ts +0 -1
- package/lib/engine.js +2 -1
- package/lib/engine.js.map +1 -1
- package/lib/game-flow.d.ts +2 -3
- package/lib/game-flow.js +5 -2
- package/lib/game-flow.js.map +1 -1
- package/lib/guess-command.d.ts +1 -2
- package/lib/guess-command.js +1 -1
- package/lib/guess-command.js.map +1 -1
- package/lib/index.d.ts +8 -2
- package/lib/index.js +8 -24
- package/lib/index.js.map +1 -1
- package/lib/memory-db.d.ts +6 -0
- package/lib/memory-db.js +18 -0
- package/lib/memory-db.js.map +1 -0
- package/lib/models.d.ts +5 -4
- package/lib/models.js +2 -2
- package/lib/models.js.map +1 -1
- package/lib/runtime-store.d.ts +6 -0
- package/lib/runtime-store.js +7 -0
- package/lib/runtime-store.js.map +1 -0
- package/lib/session-service.d.ts +1 -3
- package/lib/session-service.js +1 -4
- package/lib/session-service.js.map +1 -1
- package/middlewares/guess-alias.ts +18 -0
- package/middlewares/guess-digit.ts +24 -0
- package/package.json +45 -10
- package/plugin.ts +62 -0
- package/schema.json +6 -0
- package/src/engine.ts +3 -1
- package/src/game-flow.ts +7 -5
- package/src/guess-command.ts +2 -2
- package/src/index.ts +9 -35
- package/src/memory-db.ts +22 -0
- package/src/models.ts +7 -4
- package/src/runtime-store.ts +9 -0
- package/src/session-service.ts +2 -5
- package/lib/commands.d.ts +0 -5
- package/lib/commands.d.ts.map +0 -1
- package/lib/commands.js +0 -38
- package/lib/commands.js.map +0 -1
- package/lib/engine.d.ts.map +0 -1
- package/lib/game-flow.d.ts.map +0 -1
- package/lib/guess-command.d.ts.map +0 -1
- package/lib/hub-register.d.ts +0 -5
- package/lib/hub-register.d.ts.map +0 -1
- package/lib/hub-register.js +0 -28
- package/lib/hub-register.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/models.d.ts.map +0 -1
- package/lib/session-service.d.ts.map +0 -1
- package/plugin.yml +0 -2
- package/src/commands.ts +0 -46
- package/src/hub-register.ts +0 -29
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# @zhin.js/plugin-guess-number
|
|
2
|
+
|
|
3
|
+
猜数字小游戏:在 1~100 范围内七步内猜中神秘数。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
plugins:
|
|
9
|
+
- "@zhin.js/plugin-guess-number"
|
|
10
|
+
database:
|
|
11
|
+
dialect: sqlite
|
|
12
|
+
storage: ./data/zhin.db
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 命令
|
|
16
|
+
|
|
17
|
+
| 命令 | 说明 |
|
|
18
|
+
|------|------|
|
|
19
|
+
| `/猜数` | 帮助与频道状态 |
|
|
20
|
+
| `/猜数 开始` | 开始新局 |
|
|
21
|
+
| `/guess` | 英文别名 |
|
|
22
|
+
|
|
23
|
+
也可通过 `/游戏` 大厅按钮进入。
|
|
24
|
+
|
|
25
|
+
## 开发
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm --filter @zhin.js/plugin-guess-number build
|
|
29
|
+
pnpm vitest run plugins/games/guess-number/tests
|
|
30
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineCommand } from '@zhin.js/command';
|
|
2
|
+
import { messageFromCommandInput, normalizeGuessAction } from '@zhin.js/game-kit';
|
|
3
|
+
import { GUESS_HELP, runGuessCommand } from '../../src/guess-command.js';
|
|
4
|
+
import { resolveGameServices } from '../../src/runtime-store.js';
|
|
5
|
+
|
|
6
|
+
export default defineCommand({
|
|
7
|
+
description: 'Guess Number',
|
|
8
|
+
async execute({ params, input, use, owner }) {
|
|
9
|
+
const action = normalizeGuessAction(String(params.action ?? ''));
|
|
10
|
+
if (!action || action === 'help') return GUESS_HELP;
|
|
11
|
+
const services = resolveGameServices({ use, owner });
|
|
12
|
+
const message = messageFromCommandInput(input);
|
|
13
|
+
return runGuessCommand(services, message, action);
|
|
14
|
+
},
|
|
15
|
+
});
|
package/lib/engine.d.ts
CHANGED
|
@@ -6,4 +6,3 @@ export type GuessResult = 'win' | 'low' | 'high' | 'invalid';
|
|
|
6
6
|
export declare function newSecret(): number;
|
|
7
7
|
export declare function evaluateGuess(secret: number, value: number): GuessResult;
|
|
8
8
|
export declare function hintText(result: Exclude<GuessResult, 'win' | 'invalid'>, rangeMin: number, rangeMax: number): string;
|
|
9
|
-
//# sourceMappingURL=engine.d.ts.map
|
package/lib/engine.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { secureRandomIntInclusive } from '@zhin.js/game-kit';
|
|
1
2
|
export const GUESS_PREFIX = 'guess';
|
|
2
3
|
export const MIN = 1;
|
|
3
4
|
export const MAX = 100;
|
|
4
5
|
export const MAX_ATTEMPTS = 7;
|
|
5
6
|
export function newSecret() {
|
|
6
|
-
return MIN
|
|
7
|
+
return secureRandomIntInclusive(MIN, MAX);
|
|
7
8
|
}
|
|
8
9
|
export function evaluateGuess(secret, value) {
|
|
9
10
|
if (!Number.isInteger(value) || value < MIN || value > MAX)
|
package/lib/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AACpC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACrB,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC;AACvB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAI9B,MAAM,UAAU,SAAS;IACvB,OAAO,
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AACpC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACrB,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC;AACvB,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAI9B,MAAM,UAAU,SAAS;IACvB,OAAO,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,KAAa;IACzD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG;QAAE,OAAO,SAAS,CAAC;IAC7E,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAA+C,EAAE,QAAgB,EAAE,QAAgB;IAC1G,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,kBAAkB,QAAQ,MAAM,QAAQ,EAAE,CAAC;IACxE,OAAO,kBAAkB,QAAQ,MAAM,QAAQ,EAAE,CAAC;AACpD,CAAC"}
|
package/lib/game-flow.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Message } from 'zhin.js';
|
|
2
|
-
import type
|
|
1
|
+
import type { Message } from '@zhin.js/core';
|
|
2
|
+
import { type SessionService } from './session-service.js';
|
|
3
3
|
export declare function startGame(services: SessionService, message: Message<any>): Promise<string>;
|
|
4
4
|
export declare function processGuess(services: SessionService, message: Message<any>, value: number): Promise<string | null>;
|
|
5
|
-
//# sourceMappingURL=game-flow.d.ts.map
|
package/lib/game-flow.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { recordGameOutcome } from '@zhin.js/game-kit';
|
|
1
2
|
import { evaluateGuess, hintText, MAX, MIN } from './engine.js';
|
|
2
3
|
import { formatStatus } from './session-service.js';
|
|
3
4
|
export async function startGame(services, message) {
|
|
@@ -21,20 +22,22 @@ export async function processGuess(services, message, value) {
|
|
|
21
22
|
const attempts = session.attempts + 1;
|
|
22
23
|
if (result === 'win') {
|
|
23
24
|
await services.updateSession(session.id, { attempts, status: 'won' });
|
|
25
|
+
void recordGameOutcome(message, 'guess', 'won', Math.max(1, session.max_attempts - attempts + 1) * 10);
|
|
24
26
|
return [
|
|
25
27
|
'🎉 **猜对了!**',
|
|
26
28
|
'',
|
|
27
29
|
`答案就是 **${session.secret}**,你用了 ${attempts} 次。`,
|
|
28
|
-
'
|
|
30
|
+
'发送 `/猜数 开始` 再来一局。',
|
|
29
31
|
].join('\n');
|
|
30
32
|
}
|
|
31
33
|
if (attempts >= session.max_attempts) {
|
|
32
34
|
await services.updateSession(session.id, { attempts, status: 'lost' });
|
|
35
|
+
void recordGameOutcome(message, 'guess', 'lost');
|
|
33
36
|
return [
|
|
34
37
|
'💀 **机会用完了!**',
|
|
35
38
|
'',
|
|
36
39
|
`正确答案是 **${session.secret}**。`,
|
|
37
|
-
'
|
|
40
|
+
'发送 `/猜数 开始` 再来一局。',
|
|
38
41
|
].join('\n');
|
|
39
42
|
}
|
|
40
43
|
let rangeMin = session.range_min;
|
package/lib/game-flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"game-flow.js","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"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"}
|
package/lib/guess-command.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Message } from 'zhin.js';
|
|
1
|
+
import type { Message } from '@zhin.js/core';
|
|
2
2
|
import { type SessionService } from './session-service.js';
|
|
3
3
|
export declare const GUESS_HELP: string;
|
|
4
4
|
export declare function runGuessCommand(services: SessionService, message: Message<any>, action: string): Promise<string>;
|
|
5
|
-
//# sourceMappingURL=guess-command.d.ts.map
|
package/lib/guess-command.js
CHANGED
package/lib/guess-command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guess-command.js","sourceRoot":"","sources":["../src/guess-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"guess-command.js","sourceRoot":"","sources":["../src/guess-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAuB,MAAM,sBAAsB,CAAC;AAEzE,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,qBAAqB;IACrB,iBAAiB;IACjB,aAAa;IACb,eAAe;IACf,EAAE;IACF,cAAc;CACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAwB,EACxB,OAAqB,EACrB,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,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC/B,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE5D,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,aAAa,CAAC;QAC/B,MAAM,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,SAAS,MAAM,OAAO,UAAU,EAAE,CAAC;AAC5C,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
|
|
1
|
+
export { GUESS_HELP } from './guess-command.js';
|
|
2
|
+
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
+
export { createInMemoryGuessDb, mountGuessMemoryServices } from './memory-db.js';
|
|
4
|
+
/**
|
|
5
|
+
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
6
|
+
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
|
7
|
+
* host DatabaseHost(databaseHostToken)。仍未接:interactive 按钮回调。
|
|
8
|
+
*/
|
package/lib/index.js
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
let services = null;
|
|
10
|
-
useContext('database', (dbFeature) => {
|
|
11
|
-
services = createServices(resolveGameDatabase(dbFeature));
|
|
12
|
-
logger.info(formatCompact({ 模块: '猜数字', 数据模型: '已就绪' }));
|
|
13
|
-
});
|
|
14
|
-
registerGuessHub(() => services);
|
|
15
|
-
registerCommands(plugin, () => services);
|
|
16
|
-
registerGuessMiddleware(plugin, () => services);
|
|
17
|
-
addCron(new Cron('0 */15 * * * *', async () => {
|
|
18
|
-
if (!services)
|
|
19
|
-
return;
|
|
20
|
-
const n = await services.abortStale(30 * 60 * 1000);
|
|
21
|
-
if (n > 0)
|
|
22
|
-
logger.debug(formatCompact({ 猜数字: '清理超时局', count: n }));
|
|
23
|
-
}));
|
|
24
|
-
logger.info(formatCompact({ 模块: '猜数字', 状态: '已加载' }));
|
|
1
|
+
export { GUESS_HELP } from './guess-command.js';
|
|
2
|
+
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
+
export { createInMemoryGuessDb, mountGuessMemoryServices } from './memory-db.js';
|
|
4
|
+
/**
|
|
5
|
+
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
6
|
+
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
|
7
|
+
* host DatabaseHost(databaseHostToken)。仍未接:interactive 按钮回调。
|
|
8
|
+
*/
|
|
25
9
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAEjF;;;;GAIG"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import { type GuessDatabase, type SessionService } from './session-service.js';
|
|
3
|
+
/** In-memory guess_sessions for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
4
|
+
export declare function createInMemoryGuessDb(): GuessDatabase;
|
|
5
|
+
export declare function mountGuessMemoryServices(): SessionService;
|
|
6
|
+
export declare function mountGuessHostServices(host: DatabaseHost): SessionService;
|
package/lib/memory-db.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createHostGameDb, createInMemoryGameDb } from '@zhin.js/game-kit';
|
|
2
|
+
import { defineHostTables } from './models.js';
|
|
3
|
+
import { createServices } from './session-service.js';
|
|
4
|
+
const GUESS_TABLES = ['guess_sessions'];
|
|
5
|
+
/** In-memory guess_sessions for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
6
|
+
export function createInMemoryGuessDb() {
|
|
7
|
+
return createInMemoryGameDb(GUESS_TABLES);
|
|
8
|
+
}
|
|
9
|
+
export function mountGuessMemoryServices() {
|
|
10
|
+
const services = createServices(createInMemoryGuessDb());
|
|
11
|
+
return services;
|
|
12
|
+
}
|
|
13
|
+
export function mountGuessHostServices(host) {
|
|
14
|
+
defineHostTables(host);
|
|
15
|
+
const services = createServices(createHostGameDb(host, GUESS_TABLES));
|
|
16
|
+
return services;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=memory-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-db.js","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAA2C,MAAM,sBAAsB,CAAC;AAE/F,MAAM,YAAY,GAAG,CAAC,gBAAgB,CAAU,CAAC;AAEjD,gFAAgF;AAChF,MAAM,UAAU,qBAAqB;IACnC,OAAO,oBAAoB,CAAC,YAAY,CAA6B,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,MAAM,QAAQ,GAAG,cAAc,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACzD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAkB;IACvD,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,QAAQ,GAAG,cAAc,CAAC,gBAAgB,CAAC,IAAI,EAAE,YAAY,CAA6B,CAAC,CAAC;IAClG,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/lib/models.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Models
|
|
1
|
+
import type { Models } from '@zhin.js/core';
|
|
2
2
|
export type GuessSessionStatus = 'active' | 'won' | 'lost' | 'aborted';
|
|
3
|
-
declare module 'zhin.js' {
|
|
3
|
+
declare module '@zhin.js/core' {
|
|
4
4
|
interface Models {
|
|
5
5
|
guess_sessions: {
|
|
6
6
|
id: string;
|
|
@@ -23,5 +23,6 @@ declare module 'zhin.js' {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
export type GuessSessionRow = Models['guess_sessions'];
|
|
26
|
-
export declare function
|
|
27
|
-
|
|
26
|
+
export declare function defineHostTables(db: {
|
|
27
|
+
define: (name: string, definition: Record<string, unknown>) => void;
|
|
28
|
+
}): void;
|
package/lib/models.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export function
|
|
2
|
-
|
|
1
|
+
export function defineHostTables(db) {
|
|
2
|
+
db.define('guess_sessions', {
|
|
3
3
|
id: { type: 'text', primary: true },
|
|
4
4
|
adapter: { type: 'text', nullable: false },
|
|
5
5
|
endpoint: { type: 'text', nullable: false },
|
package/lib/models.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AA8BA,MAAM,UAAU,gBAAgB,CAC9B,EAA2E;IAE3E,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;QAC1B,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QACnC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC1C,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3C,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC/C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC7C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC9C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5C,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC5C,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1C,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE;QAC5C,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QACzC,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC7C,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;QAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE;KAC5C,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SessionService } from './session-service.js';
|
|
2
|
+
/** Owner-scoped service consumed by discovered commands and middleware. */
|
|
3
|
+
export declare const gameServicesToken: import("@zhin.js/plugin-runtime").Token<SessionService>;
|
|
4
|
+
export declare function resolveGameServices(context: {
|
|
5
|
+
use<T>(token: typeof gameServicesToken): T;
|
|
6
|
+
}): SessionService;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createToken } from '@zhin.js/plugin-runtime';
|
|
2
|
+
/** Owner-scoped service consumed by discovered commands and middleware. */
|
|
3
|
+
export const gameServicesToken = createToken('zhin.game.guess-number.services');
|
|
4
|
+
export function resolveGameServices(context) {
|
|
5
|
+
return context.use(gameServicesToken);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=runtime-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-store.js","sourceRoot":"","sources":["../src/runtime-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAiB,iCAAiC,CAAC,CAAC;AAEhG,MAAM,UAAU,mBAAmB,CAAC,OAAuD;IACzF,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAmB,CAAC;AAC1D,CAAC"}
|
package/lib/session-service.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Database,
|
|
1
|
+
import type { Database, Message, Models } from '@zhin.js/core';
|
|
2
2
|
import type { GuessSessionRow } from './models.js';
|
|
3
3
|
export type GuessDatabase = Database<unknown, Models, string>;
|
|
4
4
|
export declare class SessionService {
|
|
@@ -12,6 +12,4 @@ export declare class SessionService {
|
|
|
12
12
|
abortStale(idleMs: number): Promise<number>;
|
|
13
13
|
}
|
|
14
14
|
export declare function createServices(db: GuessDatabase): SessionService;
|
|
15
|
-
export declare function resolveGameDatabase(feature: DatabaseFeature): GuessDatabase;
|
|
16
15
|
export declare function formatStatus(session: GuessSessionRow): string;
|
|
17
|
-
//# sourceMappingURL=session-service.d.ts.map
|
package/lib/session-service.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { channelKey, generateSessionId } from '@zhin.js/game-
|
|
1
|
+
import { channelKey, generateSessionId } from '@zhin.js/game-kit';
|
|
2
2
|
import { MAX, MAX_ATTEMPTS, MIN, newSecret } from './engine.js';
|
|
3
3
|
function getModel(db) {
|
|
4
4
|
const model = db.models.get('guess_sessions');
|
|
@@ -69,9 +69,6 @@ export class SessionService {
|
|
|
69
69
|
export function createServices(db) {
|
|
70
70
|
return new SessionService(db);
|
|
71
71
|
}
|
|
72
|
-
export function resolveGameDatabase(feature) {
|
|
73
|
-
return feature.db;
|
|
74
|
-
}
|
|
75
72
|
export function formatStatus(session) {
|
|
76
73
|
const left = session.max_attempts - session.attempts;
|
|
77
74
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineGameCommandAliasMiddleware,
|
|
3
|
+
messageFromCommandInput,
|
|
4
|
+
normalizeGuessAction,
|
|
5
|
+
} from '@zhin.js/game-kit';
|
|
6
|
+
import { GUESS_HELP, runGuessCommand } from '../src/guess-command.js';
|
|
7
|
+
import { resolveGameServices } from '../src/runtime-store.js';
|
|
8
|
+
|
|
9
|
+
export default defineGameCommandAliasMiddleware({
|
|
10
|
+
aliases: ['猜数', 'guess'],
|
|
11
|
+
async run(action, input, context) {
|
|
12
|
+
const normalized = normalizeGuessAction(String(action ?? ''));
|
|
13
|
+
if (!normalized || normalized === 'help') return GUESS_HELP;
|
|
14
|
+
const services = resolveGameServices(context);
|
|
15
|
+
const message = messageFromCommandInput(input);
|
|
16
|
+
return runGuessCommand(services, message, normalized);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineMiddleware } from '@zhin.js/middleware';
|
|
2
|
+
import type { Message } from '@zhin.js/core/runtime';
|
|
3
|
+
import { messageFromCommandInput } from '@zhin.js/game-kit';
|
|
4
|
+
import { resolveGameServices } from '../src/runtime-store.js';
|
|
5
|
+
import { processGuess } from '../src/game-flow.js';
|
|
6
|
+
|
|
7
|
+
export default defineMiddleware<Message>({
|
|
8
|
+
target: 'inbound',
|
|
9
|
+
async handle(context, next) {
|
|
10
|
+
const raw = context.input.content?.trim() ?? '';
|
|
11
|
+
if (!/^(\d+)$/.test(raw)) {
|
|
12
|
+
await next();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const services = resolveGameServices(context);
|
|
16
|
+
const message = messageFromCommandInput(context.input) as never;
|
|
17
|
+
const reply = await processGuess(services, message, Number(raw));
|
|
18
|
+
if (reply) {
|
|
19
|
+
await context.input.$reply(reply);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
await next();
|
|
23
|
+
},
|
|
24
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/plugin-guess-number",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Zhin.js 猜数字 — 1~100 七步之内猜中",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Zhin.js 猜数字 — 1~100 七步之内猜中 (Plugin Runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
@@ -14,24 +14,59 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
+
"plugin.ts",
|
|
18
|
+
"schema.json",
|
|
19
|
+
"commands",
|
|
20
|
+
"middlewares",
|
|
17
21
|
"src",
|
|
18
22
|
"lib",
|
|
19
|
-
"plugin.yml",
|
|
20
23
|
"README.md"
|
|
21
24
|
],
|
|
22
25
|
"license": "MIT",
|
|
23
|
-
"peerDependencies": {
|
|
24
|
-
"zhin.js": "4.1.0"
|
|
25
|
-
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@zhin.js/
|
|
27
|
+
"@zhin.js/command": "1.0.1",
|
|
28
|
+
"@zhin.js/core": "1.3.5",
|
|
29
|
+
"@zhin.js/game-kit": "1.0.2",
|
|
30
|
+
"@zhin.js/middleware": "1.0.1",
|
|
31
|
+
"@zhin.js/plugin-runtime": "1.0.1"
|
|
28
32
|
},
|
|
29
33
|
"devDependencies": {
|
|
30
34
|
"typescript": "^6.0.3",
|
|
31
|
-
"
|
|
35
|
+
"vitest": "^4.1.10"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/zhinjs/zhin.git",
|
|
40
|
+
"directory": "plugins/games/guess-number"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"registry": "https://registry.npmjs.org"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
48
|
+
},
|
|
49
|
+
"zhin": {
|
|
50
|
+
"protocol": 1,
|
|
51
|
+
"type": "plugin",
|
|
52
|
+
"entry": "./plugin.ts",
|
|
53
|
+
"engine": "^1.0.0",
|
|
54
|
+
"runtime": "trusted",
|
|
55
|
+
"features": [
|
|
56
|
+
{
|
|
57
|
+
"package": "@zhin.js/command",
|
|
58
|
+
"api": "^1.0.0"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"package": "@zhin.js/middleware",
|
|
62
|
+
"api": "^1.0.0"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"plugins": []
|
|
32
66
|
},
|
|
33
67
|
"scripts": {
|
|
34
|
-
"build": "tsc
|
|
35
|
-
"clean": "rimraf lib"
|
|
68
|
+
"build": "tsc",
|
|
69
|
+
"clean": "rimraf lib",
|
|
70
|
+
"test": "NODE_OPTIONS=--experimental-strip-types vitest run --root ../../.. plugins/games/guess-number/tests"
|
|
36
71
|
}
|
|
37
72
|
}
|
package/plugin.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { definePlugin, databaseHostToken, scheduleHostToken } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import {
|
|
3
|
+
registerRuntimeGame,
|
|
4
|
+
initGameRecordHost,
|
|
5
|
+
DEFAULT_GAME_STALE_CRON,
|
|
6
|
+
DEFAULT_GAME_STALE_IDLE_MS,
|
|
7
|
+
} from '@zhin.js/game-kit';
|
|
8
|
+
import { mountGuessHostServices, mountGuessMemoryServices } from './src/memory-db.js';
|
|
9
|
+
import { gameServicesToken } from './src/runtime-store.js';
|
|
10
|
+
import type { SessionService } from './src/session-service.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Plugin Runtime:
|
|
14
|
+
* - Commands under `commands/` are authoritative (help + start/quit via in-memory DB).
|
|
15
|
+
* - DB: prefer databaseHostToken; else in-memory SessionService.
|
|
16
|
+
* - Digit middleware under `middlewares/` handles bare-number guesses.
|
|
17
|
+
*/
|
|
18
|
+
export default definePlugin({
|
|
19
|
+
name: 'guess-number',
|
|
20
|
+
metadata: {
|
|
21
|
+
displayName: 'Guess Number',
|
|
22
|
+
},
|
|
23
|
+
setup(context) {
|
|
24
|
+
let services: SessionService;
|
|
25
|
+
if (context.resources.has(databaseHostToken)) {
|
|
26
|
+
const host = context.resources.use(databaseHostToken);
|
|
27
|
+
services = mountGuessHostServices(host);
|
|
28
|
+
context.lifecycle.add(initGameRecordHost(host));
|
|
29
|
+
} else {
|
|
30
|
+
services = mountGuessMemoryServices();
|
|
31
|
+
}
|
|
32
|
+
context.resources.provide(gameServicesToken, services);
|
|
33
|
+
const disposeHub = registerRuntimeGame({
|
|
34
|
+
id: 'guess',
|
|
35
|
+
title: '猜数字',
|
|
36
|
+
icon: '🔢',
|
|
37
|
+
description: '1~100 七步猜中神秘数',
|
|
38
|
+
commandPrefix: '/猜数',
|
|
39
|
+
quickStart: '开始',
|
|
40
|
+
aliases: ['guess'],
|
|
41
|
+
menus: [
|
|
42
|
+
{ id: 'start', label: '🎮 开始新局' },
|
|
43
|
+
{ id: 'help', label: '📖 玩法说明' },
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
context.lifecycle.add(disposeHub);
|
|
47
|
+
|
|
48
|
+
if (context.resources.has(scheduleHostToken)) {
|
|
49
|
+
const schedule = context.resources.use(scheduleHostToken);
|
|
50
|
+
const disposeCron = schedule.register({
|
|
51
|
+
id: 'guess/abort-stale',
|
|
52
|
+
cron: DEFAULT_GAME_STALE_CRON,
|
|
53
|
+
description: 'Abort stale guess-number sessions',
|
|
54
|
+
async execute() {
|
|
55
|
+
if (!services.abortStale) return;
|
|
56
|
+
await services.abortStale(DEFAULT_GAME_STALE_IDLE_MS);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
context.lifecycle.add(disposeCron);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
});
|
package/schema.json
ADDED
package/src/engine.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { secureRandomIntInclusive } from '@zhin.js/game-kit';
|
|
2
|
+
|
|
1
3
|
export const GUESS_PREFIX = 'guess';
|
|
2
4
|
export const MIN = 1;
|
|
3
5
|
export const MAX = 100;
|
|
@@ -6,7 +8,7 @@ export const MAX_ATTEMPTS = 7;
|
|
|
6
8
|
export type GuessResult = 'win' | 'low' | 'high' | 'invalid';
|
|
7
9
|
|
|
8
10
|
export function newSecret(): number {
|
|
9
|
-
return MIN
|
|
11
|
+
return secureRandomIntInclusive(MIN, MAX);
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export function evaluateGuess(secret: number, value: number): GuessResult {
|
package/src/game-flow.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Message } from 'zhin.js';
|
|
1
|
+
import type { Message } from '@zhin.js/core';
|
|
2
|
+
import { recordGameOutcome } from '@zhin.js/game-kit';
|
|
2
3
|
import { evaluateGuess, hintText, MAX, MIN } from './engine.js';
|
|
3
|
-
import type
|
|
4
|
-
import { formatStatus } from './session-service.js';
|
|
4
|
+
import { formatStatus, type SessionService } from './session-service.js';
|
|
5
5
|
|
|
6
6
|
export async function startGame(
|
|
7
7
|
services: SessionService,
|
|
@@ -34,21 +34,23 @@ export async function processGuess(
|
|
|
34
34
|
|
|
35
35
|
if (result === 'win') {
|
|
36
36
|
await services.updateSession(session.id, { attempts, status: 'won' });
|
|
37
|
+
void recordGameOutcome(message, 'guess', 'won', Math.max(1, session.max_attempts - attempts + 1) * 10);
|
|
37
38
|
return [
|
|
38
39
|
'🎉 **猜对了!**',
|
|
39
40
|
'',
|
|
40
41
|
`答案就是 **${session.secret}**,你用了 ${attempts} 次。`,
|
|
41
|
-
'
|
|
42
|
+
'发送 `/猜数 开始` 再来一局。',
|
|
42
43
|
].join('\n');
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (attempts >= session.max_attempts) {
|
|
46
47
|
await services.updateSession(session.id, { attempts, status: 'lost' });
|
|
48
|
+
void recordGameOutcome(message, 'guess', 'lost');
|
|
47
49
|
return [
|
|
48
50
|
'💀 **机会用完了!**',
|
|
49
51
|
'',
|
|
50
52
|
`正确答案是 **${session.secret}**。`,
|
|
51
|
-
'
|
|
53
|
+
'发送 `/猜数 开始` 再来一局。',
|
|
52
54
|
].join('\n');
|
|
53
55
|
}
|
|
54
56
|
|
package/src/guess-command.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Message, Plugin } from 'zhin.js';
|
|
2
|
-
import { channelKey } from '@zhin.js/game-
|
|
1
|
+
import type { Message, Plugin } from '@zhin.js/core';
|
|
2
|
+
import { channelKey } from '@zhin.js/game-kit';
|
|
3
3
|
import { startGame } from './game-flow.js';
|
|
4
4
|
import { formatStatus, type SessionService } from './session-service.js';
|
|
5
5
|
|
package/src/index.ts
CHANGED
|
@@ -1,35 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const plugin = usePlugin();
|
|
12
|
-
const { logger, useContext, addCron } = plugin;
|
|
13
|
-
|
|
14
|
-
registerModels(plugin);
|
|
15
|
-
|
|
16
|
-
let services: SessionService | null = null;
|
|
17
|
-
|
|
18
|
-
useContext('database', (dbFeature: DatabaseFeature) => {
|
|
19
|
-
services = createServices(resolveGameDatabase(dbFeature));
|
|
20
|
-
logger.info(formatCompact({ 模块: '猜数字', 数据模型: '已就绪' }));
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
registerGuessHub(() => services);
|
|
24
|
-
registerCommands(plugin, () => services);
|
|
25
|
-
registerGuessMiddleware(plugin, () => services);
|
|
26
|
-
|
|
27
|
-
addCron(
|
|
28
|
-
new Cron('0 */15 * * * *', async () => {
|
|
29
|
-
if (!services) return;
|
|
30
|
-
const n = await services.abortStale(30 * 60 * 1000);
|
|
31
|
-
if (n > 0) logger.debug(formatCompact({ 猜数字: '清理超时局', count: n }));
|
|
32
|
-
}),
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
logger.info(formatCompact({ 模块: '猜数字', 状态: '已加载' }));
|
|
1
|
+
export { GUESS_HELP } from './guess-command.js';
|
|
2
|
+
export { gameServicesToken, resolveGameServices } from './runtime-store.js';
|
|
3
|
+
export { createInMemoryGuessDb, mountGuessMemoryServices } from './memory-db.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 已由 plugin.ts 接线:commands/ 命令、middlewares/ 文本与选项中间件、
|
|
7
|
+
* 游戏大厅注册(registerRuntimeGame)、过期会话 cron(scheduleHostToken)、
|
|
8
|
+
* host DatabaseHost(databaseHostToken)。仍未接:interactive 按钮回调。
|
|
9
|
+
*/
|
package/src/memory-db.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createHostGameDb, createInMemoryGameDb } from '@zhin.js/game-kit';
|
|
2
|
+
import type { DatabaseHost } from '@zhin.js/plugin-runtime';
|
|
3
|
+
import { defineHostTables } from './models.js';
|
|
4
|
+
import { createServices, type GuessDatabase, type SessionService } from './session-service.js';
|
|
5
|
+
|
|
6
|
+
const GUESS_TABLES = ['guess_sessions'] as const;
|
|
7
|
+
|
|
8
|
+
/** In-memory guess_sessions for Plugin Runtime slice-2 (no DatabaseFeature). */
|
|
9
|
+
export function createInMemoryGuessDb(): GuessDatabase {
|
|
10
|
+
return createInMemoryGameDb(GUESS_TABLES) as unknown as GuessDatabase;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function mountGuessMemoryServices(): SessionService {
|
|
14
|
+
const services = createServices(createInMemoryGuessDb());
|
|
15
|
+
return services;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function mountGuessHostServices(host: DatabaseHost): SessionService {
|
|
19
|
+
defineHostTables(host);
|
|
20
|
+
const services = createServices(createHostGameDb(host, GUESS_TABLES) as unknown as GuessDatabase);
|
|
21
|
+
return services;
|
|
22
|
+
}
|
package/src/models.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Models
|
|
1
|
+
import type { Models } from '@zhin.js/core';
|
|
2
2
|
|
|
3
3
|
export type GuessSessionStatus = 'active' | 'won' | 'lost' | 'aborted';
|
|
4
4
|
|
|
5
|
-
declare module 'zhin.js' {
|
|
5
|
+
declare module '@zhin.js/core' {
|
|
6
6
|
interface Models {
|
|
7
7
|
guess_sessions: {
|
|
8
8
|
id: string;
|
|
@@ -27,8 +27,11 @@ declare module 'zhin.js' {
|
|
|
27
27
|
|
|
28
28
|
export type GuessSessionRow = Models['guess_sessions'];
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
|
|
31
|
+
export function defineHostTables(
|
|
32
|
+
db: { define: (name: string, definition: Record<string, unknown>) => void },
|
|
33
|
+
): void {
|
|
34
|
+
db.define('guess_sessions', {
|
|
32
35
|
id: { type: 'text', primary: true },
|
|
33
36
|
adapter: { type: 'text', nullable: false },
|
|
34
37
|
endpoint: { type: 'text', nullable: false },
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createToken } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import type { SessionService } from './session-service.js';
|
|
3
|
+
|
|
4
|
+
/** Owner-scoped service consumed by discovered commands and middleware. */
|
|
5
|
+
export const gameServicesToken = createToken<SessionService>('zhin.game.guess-number.services');
|
|
6
|
+
|
|
7
|
+
export function resolveGameServices(context: { use<T>(token: typeof gameServicesToken): T }): SessionService {
|
|
8
|
+
return context.use(gameServicesToken) as SessionService;
|
|
9
|
+
}
|
package/src/session-service.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Database,
|
|
2
|
-
import { channelKey, generateSessionId } from '@zhin.js/game-
|
|
1
|
+
import type { Database, Message, Models, RelatedModel } from '@zhin.js/core';
|
|
2
|
+
import { channelKey, generateSessionId } from '@zhin.js/game-kit';
|
|
3
3
|
import { MAX, MAX_ATTEMPTS, MIN, newSecret } from './engine.js';
|
|
4
4
|
import type { GuessSessionRow } from './models.js';
|
|
5
5
|
|
|
@@ -79,9 +79,6 @@ export function createServices(db: GuessDatabase): SessionService {
|
|
|
79
79
|
return new SessionService(db);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
export function resolveGameDatabase(feature: DatabaseFeature): GuessDatabase {
|
|
83
|
-
return feature.db;
|
|
84
|
-
}
|
|
85
82
|
|
|
86
83
|
export function formatStatus(session: GuessSessionRow): string {
|
|
87
84
|
const left = session.max_attempts - session.attempts;
|
package/lib/commands.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { type Plugin } from 'zhin.js';
|
|
2
|
-
import type { SessionService } from './session-service.js';
|
|
3
|
-
export declare function registerCommands(plugin: Plugin, getServices: () => SessionService | null): void;
|
|
4
|
-
export declare function registerGuessMiddleware(plugin: Plugin, getServices: () => SessionService | null): void;
|
|
5
|
-
//# sourceMappingURL=commands.d.ts.map
|
package/lib/commands.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAI/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAoB3D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAG/F;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAgBtG"}
|
package/lib/commands.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { MessageCommand } from 'zhin.js';
|
|
2
|
-
import { channelKey, normalizeGuessAction, registerGameTextMiddleware } from '@zhin.js/game-shared';
|
|
3
|
-
import { processGuess } from './game-flow.js';
|
|
4
|
-
import { runGuessCommand } from './guess-command.js';
|
|
5
|
-
function registerPattern(plugin, pattern, desc, getServices) {
|
|
6
|
-
plugin.addCommand(new MessageCommand(pattern)
|
|
7
|
-
.desc(desc)
|
|
8
|
-
.action(async (message, result) => {
|
|
9
|
-
const services = getServices();
|
|
10
|
-
if (!services)
|
|
11
|
-
return '猜数字需要启用 database 配置。';
|
|
12
|
-
const raw = result.params.action ?? '';
|
|
13
|
-
return runGuessCommand(services, message, normalizeGuessAction(raw));
|
|
14
|
-
}));
|
|
15
|
-
}
|
|
16
|
-
export function registerCommands(plugin, getServices) {
|
|
17
|
-
registerPattern(plugin, 'guess [action:word]', '猜数字(guess)', getServices);
|
|
18
|
-
registerPattern(plugin, '猜数 [action:word]', '猜数字(中文)', getServices);
|
|
19
|
-
}
|
|
20
|
-
export function registerGuessMiddleware(plugin, getServices) {
|
|
21
|
-
registerGameTextMiddleware(plugin, async (message, next) => {
|
|
22
|
-
const services = getServices();
|
|
23
|
-
if (!services)
|
|
24
|
-
return next();
|
|
25
|
-
const raw = message.$raw?.trim() ?? '';
|
|
26
|
-
const m = /^(\d+)$/.exec(raw);
|
|
27
|
-
if (!m)
|
|
28
|
-
return next();
|
|
29
|
-
const ch = channelKey(message);
|
|
30
|
-
const session = await services.getActiveForUser(ch, message.$sender.id);
|
|
31
|
-
if (!session)
|
|
32
|
-
return next();
|
|
33
|
-
const reply = await processGuess(services, message, Number(m[1]));
|
|
34
|
-
if (reply)
|
|
35
|
-
await message.$reply?.(reply);
|
|
36
|
-
}, 'guess-number:text');
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=commands.js.map
|
package/lib/commands.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,cAAc,EAAe,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,SAAS,eAAe,CACtB,MAAc,EACd,OAAe,EACf,IAAY,EACZ,WAAwC;IAExC,MAAM,CAAC,UAAU,CACf,IAAI,cAAc,CAAC,OAAO,CAAC;SACxB,IAAI,CAAC,IAAI,CAAC;SACV,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;QAChC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO,sBAAsB,CAAC;QAC7C,MAAM,GAAG,GAAI,MAAM,CAAC,MAAM,CAAC,MAA6B,IAAI,EAAE,CAAC;QAC/D,OAAO,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,WAAwC;IACvF,eAAe,CAAC,MAAM,EAAE,qBAAqB,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAC1E,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,WAAwC;IAC9F,0BAA0B,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QACzD,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,EAAE,CAAC;QAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,EAAE,CAAC;QAEtB,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,EAAE,CAAC;QAE5B,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,KAAK;YAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAC1B,CAAC"}
|
package/lib/engine.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,UAAU,CAAC;AACpC,eAAO,MAAM,GAAG,IAAI,CAAC;AACrB,eAAO,MAAM,GAAG,MAAM,CAAC;AACvB,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAIxE;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,KAAK,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGpH"}
|
package/lib/game-flow.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"game-flow.d.ts","sourceRoot":"","sources":["../src/game-flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GACpB,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6CxB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"guess-command.d.ts","sourceRoot":"","sources":["../src/guess-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAU,MAAM,SAAS,CAAC;AAG/C,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEzE,eAAO,MAAM,UAAU,QAOX,CAAC;AAEb,wBAAsB,eAAe,CACnC,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAyBjB"}
|
package/lib/hub-register.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { GUESS_HELP } from './guess-command.js';
|
|
2
|
-
import type { SessionService } from './session-service.js';
|
|
3
|
-
export declare function registerGuessHub(getServices: () => SessionService | null): () => void;
|
|
4
|
-
export { GUESS_HELP };
|
|
5
|
-
//# sourceMappingURL=hub-register.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hub-register.d.ts","sourceRoot":"","sources":["../src/hub-register.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,cAAc,GAAG,IAAI,GAAG,MAAM,IAAI,CAqBrF;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/lib/hub-register.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { getPlugin } from 'zhin.js';
|
|
2
|
-
import { ensureGameHubService } from '@zhin.js/game-shared';
|
|
3
|
-
import { runGuessCommand, GUESS_HELP } from './guess-command.js';
|
|
4
|
-
export function registerGuessHub(getServices) {
|
|
5
|
-
const plugin = getPlugin();
|
|
6
|
-
ensureGameHubService(plugin);
|
|
7
|
-
return plugin.registerGame({
|
|
8
|
-
id: 'guess',
|
|
9
|
-
title: '猜数字',
|
|
10
|
-
icon: '🔢',
|
|
11
|
-
description: '1~100 七步猜中神秘数',
|
|
12
|
-
commandPrefix: '猜数',
|
|
13
|
-
quickStart: '开始',
|
|
14
|
-
aliases: ['guess'],
|
|
15
|
-
menus: [
|
|
16
|
-
{ id: 'start', label: '🎮 开始新局', style: 'primary' },
|
|
17
|
-
{ id: 'help', label: '📖 玩法说明' },
|
|
18
|
-
],
|
|
19
|
-
runAction: async (actionId, ctx) => {
|
|
20
|
-
const services = getServices();
|
|
21
|
-
if (!services)
|
|
22
|
-
return '猜数字需要启用 database 配置。';
|
|
23
|
-
return runGuessCommand(services, ctx.message, actionId);
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
export { GUESS_HELP };
|
|
28
|
-
//# sourceMappingURL=hub-register.js.map
|
package/lib/hub-register.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hub-register.js","sourceRoot":"","sources":["../src/hub-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGjE,MAAM,UAAU,gBAAgB,CAAC,WAAwC;IACvE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,YAAY,CAAC;QACzB,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,eAAe;QAC5B,aAAa,EAAE,IAAI;QACnB,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,CAAC,OAAO,CAAC;QAClB,KAAK,EAAE;YACL,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACnD,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE;SACjC;QACD,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO,sBAAsB,CAAC;YAC7C,OAAO,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/lib/models.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAEvE,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,MAAM;QACd,cAAc,EAAE;YACd,EAAE,EAAE,MAAM,CAAC;YACX,OAAO,EAAE,MAAM,CAAC;YAChB,QAAQ,EAAE,MAAM,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,UAAU,EAAE,MAAM,CAAC;YACnB,WAAW,EAAE,MAAM,CAAC;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,WAAW,EAAE,MAAM,CAAC;YACpB,MAAM,EAAE,MAAM,CAAC;YACf,SAAS,EAAE,MAAM,CAAC;YAClB,SAAS,EAAE,MAAM,CAAC;YAClB,QAAQ,EAAE,MAAM,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,MAAM,EAAE,kBAAkB,CAAC;YAC3B,UAAU,EAAE,MAAM,CAAC;YACnB,UAAU,EAAE,MAAM,CAAC;SACpB,CAAC;KACH;CACF;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAEvD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAmBnD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session-service.d.ts","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAgB,MAAM,SAAS,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAQ9D,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa;IAExC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAKpE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IASlF,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAIpD,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IAwB9D,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAalD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,cAAc,CAEhE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAE3E;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAU7D"}
|
package/plugin.yml
DELETED
package/src/commands.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Message, MessageCommand, type Plugin } from 'zhin.js';
|
|
2
|
-
import { channelKey, normalizeGuessAction, registerGameTextMiddleware } from '@zhin.js/game-shared';
|
|
3
|
-
import { processGuess } from './game-flow.js';
|
|
4
|
-
import { runGuessCommand } from './guess-command.js';
|
|
5
|
-
import type { SessionService } from './session-service.js';
|
|
6
|
-
|
|
7
|
-
function registerPattern(
|
|
8
|
-
plugin: Plugin,
|
|
9
|
-
pattern: string,
|
|
10
|
-
desc: string,
|
|
11
|
-
getServices: () => SessionService | null,
|
|
12
|
-
): void {
|
|
13
|
-
plugin.addCommand(
|
|
14
|
-
new MessageCommand(pattern)
|
|
15
|
-
.desc(desc)
|
|
16
|
-
.action(async (message, result) => {
|
|
17
|
-
const services = getServices();
|
|
18
|
-
if (!services) return '猜数字需要启用 database 配置。';
|
|
19
|
-
const raw = (result.params.action as string | undefined) ?? '';
|
|
20
|
-
return runGuessCommand(services, message, normalizeGuessAction(raw));
|
|
21
|
-
}),
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function registerCommands(plugin: Plugin, getServices: () => SessionService | null): void {
|
|
26
|
-
registerPattern(plugin, 'guess [action:word]', '猜数字(guess)', getServices);
|
|
27
|
-
registerPattern(plugin, '猜数 [action:word]', '猜数字(中文)', getServices);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function registerGuessMiddleware(plugin: Plugin, getServices: () => SessionService | null): void {
|
|
31
|
-
registerGameTextMiddleware(plugin, async (message, next) => {
|
|
32
|
-
const services = getServices();
|
|
33
|
-
if (!services) return next();
|
|
34
|
-
|
|
35
|
-
const raw = message.$raw?.trim() ?? '';
|
|
36
|
-
const m = /^(\d+)$/.exec(raw);
|
|
37
|
-
if (!m) return next();
|
|
38
|
-
|
|
39
|
-
const ch = channelKey(message);
|
|
40
|
-
const session = await services.getActiveForUser(ch, message.$sender.id);
|
|
41
|
-
if (!session) return next();
|
|
42
|
-
|
|
43
|
-
const reply = await processGuess(services, message, Number(m[1]));
|
|
44
|
-
if (reply) await message.$reply?.(reply);
|
|
45
|
-
}, 'guess-number:text');
|
|
46
|
-
}
|
package/src/hub-register.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { getPlugin } from 'zhin.js';
|
|
2
|
-
import { ensureGameHubService } from '@zhin.js/game-shared';
|
|
3
|
-
import { runGuessCommand, GUESS_HELP } from './guess-command.js';
|
|
4
|
-
import type { SessionService } from './session-service.js';
|
|
5
|
-
|
|
6
|
-
export function registerGuessHub(getServices: () => SessionService | null): () => void {
|
|
7
|
-
const plugin = getPlugin();
|
|
8
|
-
ensureGameHubService(plugin);
|
|
9
|
-
return plugin.registerGame({
|
|
10
|
-
id: 'guess',
|
|
11
|
-
title: '猜数字',
|
|
12
|
-
icon: '🔢',
|
|
13
|
-
description: '1~100 七步猜中神秘数',
|
|
14
|
-
commandPrefix: '猜数',
|
|
15
|
-
quickStart: '开始',
|
|
16
|
-
aliases: ['guess'],
|
|
17
|
-
menus: [
|
|
18
|
-
{ id: 'start', label: '🎮 开始新局', style: 'primary' },
|
|
19
|
-
{ id: 'help', label: '📖 玩法说明' },
|
|
20
|
-
],
|
|
21
|
-
runAction: async (actionId, ctx) => {
|
|
22
|
-
const services = getServices();
|
|
23
|
-
if (!services) return '猜数字需要启用 database 配置。';
|
|
24
|
-
return runGuessCommand(services, ctx.message, actionId);
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export { GUESS_HELP };
|