@zhin.js/plugin-blackjack 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,6 +1,6 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { replyGameOperation, gamePlayerFromInput } from '@zhin.js/game-kit';
2
3
  import { defineCommand } from 'zhin.js/command';
3
- import { messageFromCommandInput } from '@zhin.js/game-kit';
4
4
  import { getBjHelp, runBjCommand } from "../../../lib/bj-command.js";
5
5
  import { resolveGameServices } from "../../../lib/runtime-store.js";
6
6
  function normalizeBjAction(raw) {
@@ -16,12 +16,13 @@ function normalizeBjAction(raw) {
16
16
  export default defineCommand({
17
17
  description: 'Blackjack',
18
18
  params: { action: { type: 'string', default: '' } },
19
- async execute({ params, input, use, locale, formatCommand }) {
19
+ async execute({ params, input, use, locale, formatCommand, session }) {
20
20
  const action = normalizeBjAction(String(params.action ?? ''));
21
21
  if (!action || action === 'help')
22
22
  return getBjHelp({ locale, formatCommand });
23
23
  const services = resolveGameServices({ use });
24
- const message = messageFromCommandInput(input, { locale, formatCommand });
25
- return runBjCommand(services, message, action);
24
+ const message = gamePlayerFromInput(input, { locale, formatCommand });
25
+ await replyGameOperation({ session: services, player: message, reply: session?.reply,
26
+ run: () => runBjCommand(services, message, action) });
26
27
  },
27
28
  });
@@ -1,5 +1,5 @@
1
+ import { replyGameOperation, gamePlayerFromInput } from '@zhin.js/game-kit';
1
2
  import { defineCommand } from 'zhin.js/command';
2
- import { messageFromCommandInput } from '@zhin.js/game-kit';
3
3
  import { getBjHelp, runBjCommand } from '../../../src/bj-command.js';
4
4
  import { resolveGameServices } from '../../../src/runtime-store.js';
5
5
 
@@ -14,11 +14,12 @@ function normalizeBjAction(raw: string): string {
14
14
  export default defineCommand({
15
15
  description: 'Blackjack',
16
16
  params: { action: { type: 'string', default: '' } },
17
- async execute({ params, input, use, locale, formatCommand }) {
17
+ async execute({ params, input, use, locale, formatCommand, session }) {
18
18
  const action = normalizeBjAction(String(params.action ?? ''));
19
19
  if (!action || action === 'help') return getBjHelp({ locale, formatCommand });
20
20
  const services = resolveGameServices({ use });
21
- const message = messageFromCommandInput(input, { locale, formatCommand });
22
- return runBjCommand(services, message, action);
21
+ const message = gamePlayerFromInput(input, { locale, formatCommand });
22
+ await replyGameOperation({ session: services, player: message, reply: session?.reply,
23
+ run: () => runBjCommand(services, message, action) });
23
24
  },
24
25
  });
@@ -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 getBjHelp(message?: Pick<GameMessageLike, 'locale' | 'formatCommand'>): string;
3
+ export declare function getBjHelp(message?: Pick<GamePlayer, 'locale' | 'formatCommand'>): string;
4
4
  export declare const BJ_HELP: string;
5
- export declare function runBjCommand(services: SessionService, message: GameMessageLike, action: string): Promise<GameReply>;
5
+ export declare function runBjCommand(services: SessionService, message: GamePlayer, action: string): Promise<GameReply>;
package/lib/bj-command.js CHANGED
@@ -1,23 +1,25 @@
1
- import { formatGameHelp, gameCommandFeedback } from '@zhin.js/game-kit';
1
+ import { channelKey, formatGameHelp, gameCommandFeedback } from '@zhin.js/game-kit';
2
2
  import { continueGame, handleChoice, startGame } from './game-flow.js';
3
3
  export function getBjHelp(message = {}) {
4
- return formatGameHelp(message, { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" }, 'bj', ['start', 'continue', 'quit'], { 'zh-CN': "尽量让手牌点数接近 21 且不超过,比庄家大即获胜。对局中点击要牌或停牌。", en: "Get as close to 21 as possible without going over, and beat the dealer. Choose Hit or Stand during play." });
4
+ return formatGameHelp({ presentation: message, title: { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" }, commandPath: 'bj', actions: ['start', 'continue', 'quit'], footer: { 'zh-CN': "尽量让手牌点数接近 21 且不超过,比庄家大即获胜。对局中点击要牌或停牌。", en: "Get as close to 21 as possible without going over, and beat the dealer. Choose Hit or Stand during play." } });
5
5
  }
6
6
  export const BJ_HELP = getBjHelp();
7
7
  export async function runBjCommand(services, message, action) {
8
- const a = action.trim().toLowerCase() || 'help';
9
- if (a === 'help' || a === '帮助')
10
- return getBjHelp(message);
11
- if (a === 'start' || a === '开始')
12
- return (await startGame(services, message)) ?? '';
13
- if (a === 'continue' || a === '继续')
14
- return continueGame(services, message);
15
- if (a === 'quit' || a === '放弃') {
16
- const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
17
- if (!session)
18
- return gameCommandFeedback(message, 'noGame');
19
- return (await handleChoice(services, message, session.id, 'quit')) ?? '';
20
- }
21
- return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getBjHelp(message);
8
+ return services.runInScope({ scope: channelKey(message), run: async () => {
9
+ const a = action.trim().toLowerCase() || 'help';
10
+ if (a === 'help' || a === '帮助')
11
+ return getBjHelp(message);
12
+ if (a === 'start' || a === '开始')
13
+ return (await startGame(services, message)) ?? '';
14
+ if (a === 'continue' || a === '继续')
15
+ return continueGame(services, message);
16
+ if (a === 'quit' || a === '放弃') {
17
+ const session = await services.getActiveForUser(channelKey(message), message.sender.id);
18
+ if (!session)
19
+ return gameCommandFeedback(message, 'noGame');
20
+ return (await handleChoice(services, message, session.id, 'quit')) ?? '';
21
+ }
22
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getBjHelp(message);
23
+ } });
22
24
  }
23
25
  //# sourceMappingURL=bj-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bj-command.js","sourceRoot":"","sources":["../src/bj-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAyD,MAAM,mBAAmB,CAAC;AAC/H,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGvE,MAAM,UAAU,SAAS,CAAC,UAA6D,EAAE;IACvF,OAAO,cAAc,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EACpH,EAAE,OAAO,EAAE,uCAAuC,EAAE,EAAE,EAAE,0GAA0G,EAAE,CAAC,CAAC;AAC1K,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAwB,EACxB,OAAwB,EACxB,MAAc;IAEd,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC;IAChD,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACnF,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAC7C,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAC1F,OAAO,CAAC,OAAO,CAAC,EAAE,CACnB,CAAC;QACF,IAAI,CAAC,OAAO;YAAE,OAAO,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC5D,OAAO,CAAC,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC"}
1
+ {"version":3,"file":"bj-command.js","sourceRoot":"","sources":["../src/bj-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,mBAAmB,EAAoD,MAAM,mBAAmB,CAAC;AACtI,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGvE,MAAM,UAAU,SAAS,CAAC,UAAwD,EAAE;IAClF,OAAO,cAAc,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,EAAE,kBAAkB,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,uCAAuC,EAAE,EAAE,EAAE,0GAA0G,EAAE,EAAE,CAAC,CAAC;AACvV,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAwB,EACxB,OAAmB,EACnB,MAAc;IAEd,OAAO,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC;YAChD,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI;gBAAE,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;YAC1D,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI;gBAAE,OAAO,CAAC,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YACnF,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,IAAI;gBAAE,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC3E,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAC7C,UAAU,CAAC,OAAO,CAAC,EACnB,OAAO,CAAC,MAAM,CAAC,EAAE,CAClB,CAAC;gBACF,IAAI,CAAC,OAAO;oBAAE,OAAO,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAC5D,OAAO,CAAC,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3E,CAAC;YACD,OAAO,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QACvF,CAAC,EAAE,CAAC,CAAC;AACP,CAAC"}
@@ -1,7 +1,7 @@
1
- import type { GameMessageLike, GameReply } from '@zhin.js/game-kit';
1
+ import { type GamePlayer, type GameReply } from '@zhin.js/game-kit';
2
2
  import { BJ_PREFIX, handValue, TARGET } from './engine.js';
3
3
  import { type SessionService } from './session-service.js';
4
- export declare function startGame(services: SessionService, message: GameMessageLike): Promise<GameReply | undefined>;
5
- export declare function continueGame(services: SessionService, message: GameMessageLike): Promise<GameReply>;
6
- export declare function handleChoice(services: SessionService, message: GameMessageLike, sessionId: string, choiceId: string): Promise<GameReply | null>;
4
+ export declare function startGame(services: SessionService, message: GamePlayer): Promise<GameReply | undefined>;
5
+ export declare function continueGame(services: SessionService, message: GamePlayer): Promise<GameReply>;
6
+ export declare function handleChoice(services: SessionService, message: GamePlayer, sessionId: string, choiceId: string): Promise<GameReply | null>;
7
7
  export { BJ_PREFIX, handValue, TARGET };
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 { BJ_PREFIX, compareHands, dealerShouldHit, handValue, TARGET, } from './engine.js';
3
4
  import { parseCards, parseDeck } from './session-service.js';
4
5
  import { buildBjView, naturalOutcome, playerBust } from './view.js';
@@ -8,7 +9,7 @@ import { buildBjView, naturalOutcome, playerBust } from './view.js';
8
9
  * and the choice middleware return fresh text each turn.
9
10
  */
10
11
  function renderView(session, message, terminal = false, revealDealer = false) {
11
- return buildBjView(session, terminal, revealDealer, message.$channel.type);
12
+ return buildBjView(session, terminal, revealDealer, message.target.kind);
12
13
  }
13
14
  async function finishRound(services, message, session, status) {
14
15
  await services.updateSession(session.id, { status });
@@ -26,74 +27,80 @@ async function dealerPlay(deck, dealer) {
26
27
  return hand;
27
28
  }
28
29
  export async function startGame(services, message) {
29
- const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
30
- const active = await services.getActiveByChannel(ch);
31
- const locale = resolveLocale(active ? active.locale : message.locale);
32
- if (active) {
33
- if (active.player_id === message.$sender.id) {
34
- return messages(locale, 'text1');
35
- }
36
- return messages(locale, 'text2', { p0: active.player_name });
37
- }
38
- const session = await services.createSession(message);
39
- const natural = naturalOutcome(session);
40
- if (natural) {
41
- return finishRound(services, message, session, natural);
42
- }
43
- return renderView(session, message);
30
+ return services.runInScope({ scope: channelKey(message), run: async () => {
31
+ const ch = channelKey(message);
32
+ const active = await services.getActiveByChannel(ch);
33
+ const locale = resolveLocale(active ? active.locale : message.locale);
34
+ if (active) {
35
+ if (active.player_id === message.sender.id) {
36
+ return messages(locale, 'text1');
37
+ }
38
+ return messages(locale, 'text2', { p0: active.player_name });
39
+ }
40
+ const session = await services.createSession(message);
41
+ const natural = naturalOutcome(session);
42
+ if (natural) {
43
+ return finishRound(services, message, session, natural);
44
+ }
45
+ return renderView(session, message);
46
+ } });
44
47
  }
45
48
  export async function continueGame(services, message) {
46
- const session = await services.getActiveForUser(`${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`, message.$sender.id);
47
- const locale = resolveLocale(session ? session.locale : message.locale);
48
- if (!session)
49
- return messages(locale, 'text3');
50
- return renderView(session, message);
49
+ return services.runInScope({ scope: channelKey(message), run: async () => {
50
+ const session = await services.getActiveForUser(channelKey(message), message.sender.id);
51
+ const locale = resolveLocale(session ? session.locale : message.locale);
52
+ if (!session)
53
+ return messages(locale, 'text3');
54
+ return renderView(session, message);
55
+ } });
51
56
  }
52
57
  export async function handleChoice(services, message, sessionId, choiceId) {
53
- const session = await services.getById(sessionId);
54
- const locale = resolveLocale(session ? session.locale : message.locale);
55
- if (!session)
56
- return messages(locale, 'text4');
57
- if (session.player_id !== message.$sender.id)
58
- return messages(locale, 'text5');
59
- if (session.status !== 'active' && choiceId === 'restart') {
60
- await services.updateSession(session.id, { status: 'aborted' });
61
- return (await startGame(services, message)) ?? null;
62
- }
63
- if (session.status !== 'active')
64
- return messages(locale, 'text6');
65
- if (choiceId === 'quit') {
66
- await services.updateSession(session.id, { status: 'aborted' });
67
- return renderView((await services.getById(session.id)), message, true, true);
68
- }
69
- const deck = parseDeck(session.deck_json);
70
- let player = parseCards(session.player_cards_json);
71
- let dealer = parseCards(session.dealer_cards_json);
72
- if (choiceId === 'hit') {
73
- const card = deck.pop();
74
- if (!card)
75
- return messages(locale, 'text7');
76
- player = [...player, card];
77
- await services.updateSession(session.id, {
78
- deck_json: JSON.stringify(deck),
79
- player_cards_json: JSON.stringify(player),
80
- });
81
- if (playerBust({ ...session, player_cards_json: JSON.stringify(player) })) {
82
- return finishRound(services, message, session, 'lost');
83
- }
84
- const updated = (await services.getById(session.id));
85
- return renderView(updated, message);
86
- }
87
- if (choiceId !== 'stand')
88
- return messages(locale, 'text8');
89
- dealer = await dealerPlay(deck, dealer);
90
- await services.updateSession(session.id, {
91
- deck_json: JSON.stringify(deck),
92
- dealer_cards_json: JSON.stringify(dealer),
93
- });
94
- const outcome = compareHands(player, dealer);
95
- const status = outcome === 'won' ? 'won' : outcome === 'lost' ? 'lost' : 'draw';
96
- return finishRound(services, message, session, status);
58
+ return services.runInScope({ scope: channelKey(message), run: async () => {
59
+ const session = await services.getById(sessionId);
60
+ const locale = resolveLocale(session ? session.locale : message.locale);
61
+ if (!session)
62
+ return messages(locale, 'text4');
63
+ if (session.player_id !== message.sender.id)
64
+ return messages(locale, 'text5');
65
+ if (session.status !== 'active' && choiceId === 'restart') {
66
+ await services.updateSession(session.id, { status: 'aborted' });
67
+ return (await startGame(services, message)) ?? null;
68
+ }
69
+ if (session.status !== 'active')
70
+ return messages(locale, 'text6');
71
+ if (choiceId === 'quit') {
72
+ await services.updateSession(session.id, { status: 'aborted' });
73
+ return renderView((await services.getById(session.id)), message, true, true);
74
+ }
75
+ const deck = parseDeck(session.deck_json);
76
+ let player = parseCards(session.player_cards_json);
77
+ let dealer = parseCards(session.dealer_cards_json);
78
+ if (choiceId === 'hit') {
79
+ const card = deck.pop();
80
+ if (!card)
81
+ return messages(locale, 'text7');
82
+ player = [...player, card];
83
+ await services.updateSession(session.id, {
84
+ deck_json: JSON.stringify(deck),
85
+ player_cards_json: JSON.stringify(player),
86
+ });
87
+ if (playerBust({ ...session, player_cards_json: JSON.stringify(player) })) {
88
+ return finishRound(services, message, session, 'lost');
89
+ }
90
+ const updated = (await services.getById(session.id));
91
+ return renderView(updated, message);
92
+ }
93
+ if (choiceId !== 'stand')
94
+ return messages(locale, 'text8');
95
+ dealer = await dealerPlay(deck, dealer);
96
+ await services.updateSession(session.id, {
97
+ deck_json: JSON.stringify(deck),
98
+ dealer_cards_json: JSON.stringify(dealer),
99
+ });
100
+ const outcome = compareHands(player, dealer);
101
+ const status = outcome === 'won' ? 'won' : outcome === 'lost' ? 'lost' : 'draw';
102
+ return finishRound(services, message, session, status);
103
+ } });
97
104
  }
98
105
  export { BJ_PREFIX, handValue, TARGET };
99
106
  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,10 +1,10 @@
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 { BjSessionRow } from './models.js';
4
4
  export type BjDatabase = Database<unknown, Models, string>;
5
5
  export declare class SessionService extends BaseSessionService<BjSessionRow> {
6
6
  constructor(db: BjDatabase);
7
- createSession(message: GameMessageLike): Promise<BjSessionRow>;
7
+ createSession(message: GamePlayer): Promise<BjSessionRow>;
8
8
  }
9
9
  export declare function createServices(db: BjDatabase): SessionService;
10
10
  export declare function parseCards(json: string | string[]): string[];
@@ -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 { freshDeck } from './engine.js';
3
3
  export class SessionService extends BaseSessionService {
4
4
  constructor(db) {
@@ -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: String(message.$sender.name ?? message.$sender.id),
30
+ player_id: message.sender.id,
31
+ player_name: String(message.sender.name ?? message.sender.id),
37
32
  deck_json: JSON.stringify(deck),
38
33
  player_cards_json: JSON.stringify(playerCards),
39
34
  dealer_cards_json: JSON.stringify(dealerCards),
@@ -41,7 +36,7 @@ export class SessionService extends BaseSessionService {
41
36
  updated_at: now,
42
37
  created_at: now,
43
38
  };
44
- return this.createRow(row);
39
+ return this.createRow({ target: message.target, fields: row });
45
40
  }
46
41
  }
47
42
  export function createServices(db) {
@@ -1 +1 @@
1
- {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-service.js","sourceRoot":"","sources":["../src/session-service.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
- import { defineGameCommandAliasMiddleware, messageFromCommandInput } from '@zhin.js/game-kit';
2
+ import { replyGameOperation, defineGameCommandAliasMiddleware, gamePlayerFromInput } from '@zhin.js/game-kit';
3
3
  import { getBjHelp, runBjCommand } from "../../lib/bj-command.js";
4
4
  import { resolveGameServices } from "../../lib/runtime-store.js";
5
5
  function normalizeBjAction(raw) {
@@ -15,13 +15,17 @@ function normalizeBjAction(raw) {
15
15
  export default defineGameCommandAliasMiddleware({
16
16
  aliases: ['21点', 'bj'],
17
17
  async run(action, input, context) {
18
- const message = messageFromCommandInput(input, {
19
- formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
20
- });
18
+ const presentation = { locale: context.input.locale,
19
+ formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id) };
21
20
  const normalized = normalizeBjAction(String(action ?? ''));
22
- if (!normalized || normalized === 'help')
23
- return getBjHelp(message);
21
+ if (!normalized || normalized === 'help') {
22
+ await context.input.$reply(getBjHelp(presentation));
23
+ return true;
24
+ }
25
+ const message = gamePlayerFromInput(input, presentation);
24
26
  const services = resolveGameServices(context);
25
- return runBjCommand(services, message, normalized);
27
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
28
+ run: () => runBjCommand(services, message, normalized) });
29
+ return true;
26
30
  },
27
31
  });
@@ -1,4 +1,4 @@
1
- import { defineGameCommandAliasMiddleware, messageFromCommandInput } from '@zhin.js/game-kit';
1
+ import { replyGameOperation, defineGameCommandAliasMiddleware, gamePlayerFromInput } from '@zhin.js/game-kit';
2
2
  import { getBjHelp, runBjCommand } from '../../src/bj-command.js';
3
3
  import { resolveGameServices } from '../../src/runtime-store.js';
4
4
 
@@ -13,12 +13,15 @@ function normalizeBjAction(raw: string): string {
13
13
  export default defineGameCommandAliasMiddleware({
14
14
  aliases: ['21点', 'bj'],
15
15
  async run(action, input, context) {
16
- const message = messageFromCommandInput(input, {
17
- formatCommand: (path) => context.input.formatCommand?.(path, context.owner.id),
18
- });
16
+ const presentation = { locale: context.input.locale,
17
+ formatCommand: (path: string) => context.input.formatCommand?.(path, context.owner.id) };
18
+
19
19
  const normalized = normalizeBjAction(String(action ?? ''));
20
- if (!normalized || normalized === 'help') return getBjHelp(message);
20
+ if (!normalized || normalized === 'help') { await context.input.$reply(getBjHelp(presentation)); return true; }
21
+ const message = gamePlayerFromInput(input, presentation);
21
22
  const services = resolveGameServices(context);
22
- return runBjCommand(services, message, normalized);
23
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
24
+ run: () => runBjCommand(services, message, normalized) });
25
+ return true;
23
26
  },
24
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 { BJ_PREFIX, handleChoice } from "../../lib/game-flow.js";
6
6
  /**
@@ -10,13 +10,17 @@ import { BJ_PREFIX, handleChoice } from "../../lib/game-flow.js";
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,9 +29,8 @@ 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
  }
@@ -35,7 +38,7 @@ export default defineMiddleware({
35
38
  return;
36
39
  }
37
40
  // 不按 status 过滤取本频道本人最近一局:终局 session 也要能命中 restart 分支
38
- const session = await services.getLatestForUser(ch, message.$sender.id);
41
+ const session = await services.getLatestForUser(ch, message.sender.id);
39
42
  if (!session) {
40
43
  await next();
41
44
  return;
@@ -47,9 +50,8 @@ export default defineMiddleware({
47
50
  const payload = resolveGameTextPayload(raw, map);
48
51
  const parsed = payload ? parseChoicePayload(payload, BJ_PREFIX) : null;
49
52
  if (parsed?.choiceId === 'restart') {
50
- const reply = await handleChoice(services, message, parsed.sessionId, 'restart');
51
- if (reply)
52
- await context.input.$reply(reply);
53
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
54
+ run: () => handleChoice(services, message, parsed.sessionId, 'restart') });
53
55
  return;
54
56
  }
55
57
  await next();
@@ -66,8 +68,7 @@ export default defineMiddleware({
66
68
  await next();
67
69
  return;
68
70
  }
69
- const reply = await handleChoice(services, message, session.id, parsed.choiceId);
70
- if (reply)
71
- await context.input.$reply(reply);
71
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
72
+ run: () => handleChoice(services, message, session.id, parsed.choiceId) });
72
73
  },
73
74
  });
@@ -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 { BJ_PREFIX, handleChoice } from '../../src/game-flow.js';
12
13
 
@@ -17,13 +18,14 @@ import { BJ_PREFIX, handleChoice } from '../../src/game-flow.js';
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
  }
@@ -43,7 +45,7 @@ export default defineMiddleware<Message>({
43
45
  }
44
46
 
45
47
  // 不按 status 过滤取本频道本人最近一局:终局 session 也要能命中 restart 分支
46
- const session = await services.getLatestForUser(ch, message.$sender.id);
48
+ const session = await services.getLatestForUser(ch, message.sender.id);
47
49
  if (!session) {
48
50
  await next();
49
51
  return;
@@ -56,8 +58,8 @@ export default defineMiddleware<Message>({
56
58
  const payload = resolveGameTextPayload(raw, map);
57
59
  const parsed = payload ? parseChoicePayload(payload, BJ_PREFIX) : null;
58
60
  if (parsed?.choiceId === 'restart') {
59
- const reply = await handleChoice(services, message, parsed.sessionId, 'restart');
60
- if (reply) await context.input.$reply(reply);
61
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
62
+ run: () => handleChoice(services, message, parsed.sessionId, 'restart') });
61
63
  return;
62
64
  }
63
65
  await next();
@@ -76,7 +78,7 @@ export default defineMiddleware<Message>({
76
78
  return;
77
79
  }
78
80
 
79
- const reply = await handleChoice(services, message, session.id, parsed.choiceId);
80
- if (reply) await context.input.$reply(reply);
81
+ await replyGameOperation({ session: services, player: message, reply: content => context.input.$reply(content),
82
+ run: () => handleChoice(services, message, session.id, parsed.choiceId) });
81
83
  },
82
84
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-blackjack",
3
- "version": "1.1.18",
3
+ "version": "1.1.19",
4
4
  "description": "Zhin.js 21 点(Blackjack)(Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -23,13 +23,13 @@
23
23
  ],
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "@zhin.js/core": "1.1.53",
27
- "@zhin.js/game-kit": "1.1.18"
26
+ "@zhin.js/core": "1.1.54",
27
+ "@zhin.js/game-kit": "1.1.19"
28
28
  },
29
29
  "devDependencies": {
30
30
  "typescript": "^6.0.3",
31
31
  "vitest": "^4.1.10",
32
- "zhin.js": "1.1.18"
32
+ "zhin.js": "1.1.19"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",
@@ -66,9 +66,9 @@
66
66
  "plugins": []
67
67
  },
68
68
  "peerDependencies": {
69
- "@zhin.js/command": "^1.1.11",
70
- "@zhin.js/middleware": "^1.1.10",
71
- "zhin.js": "^1.1.18"
69
+ "@zhin.js/command": "^1.1.12",
70
+ "@zhin.js/middleware": "^1.1.11",
71
+ "zhin.js": "^1.1.19"
72
72
  },
73
73
  "peerDependenciesMeta": {
74
74
  "@zhin.js/command": {
package/src/bj-command.ts CHANGED
@@ -1,30 +1,31 @@
1
- import { formatGameHelp, gameCommandFeedback, gameCommandHint, type GameMessageLike, type GameReply } from '@zhin.js/game-kit';
1
+ import { channelKey, formatGameHelp, gameCommandFeedback, gameCommandHint, type GamePlayer, type GameReply } from '@zhin.js/game-kit';
2
2
  import { continueGame, handleChoice, startGame } from './game-flow.js';
3
3
  import type { SessionService } from './session-service.js';
4
4
 
5
- export function getBjHelp(message: Pick<GameMessageLike, 'locale' | 'formatCommand'> = {}): string {
6
- return formatGameHelp(message, { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" }, 'bj', ['start', 'continue', 'quit'],
7
- { 'zh-CN': "尽量让手牌点数接近 21 且不超过,比庄家大即获胜。对局中点击要牌或停牌。", en: "Get as close to 21 as possible without going over, and beat the dealer. Choose Hit or Stand during play." });
5
+ export function getBjHelp(message: Pick<GamePlayer, 'locale' | 'formatCommand'> = {}): string {
6
+ return formatGameHelp({ presentation: message, title: { 'zh-CN': "🃏 **21 点**", en: "🃏 **Blackjack**" }, commandPath: 'bj', actions: ['start', 'continue', 'quit'], footer: { 'zh-CN': "尽量让手牌点数接近 21 且不超过,比庄家大即获胜。对局中点击要牌或停牌。", en: "Get as close to 21 as possible without going over, and beat the dealer. Choose Hit or Stand during play." } });
8
7
  }
9
8
 
10
9
  export const BJ_HELP = getBjHelp();
11
10
 
12
11
  export async function runBjCommand(
13
12
  services: SessionService,
14
- message: GameMessageLike,
13
+ message: GamePlayer,
15
14
  action: string,
16
15
  ): Promise<GameReply> {
17
- const a = action.trim().toLowerCase() || 'help';
18
- if (a === 'help' || a === '帮助') return getBjHelp(message);
19
- if (a === 'start' || a === '开始') return (await startGame(services, message)) ?? '';
20
- if (a === 'continue' || a === '继续') return continueGame(services, message);
21
- if (a === 'quit' || a === '放弃') {
22
- const session = await services.getActiveForUser(
23
- `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
24
- message.$sender.id,
25
- );
26
- if (!session) return gameCommandFeedback(message, 'noGame');
27
- return (await handleChoice(services, message, session.id, 'quit')) ?? '';
28
- }
29
- return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getBjHelp(message);
16
+ return services.runInScope({ scope: channelKey(message), run: async () => {
17
+ const a = action.trim().toLowerCase() || 'help';
18
+ if (a === 'help' || a === '帮助') return getBjHelp(message);
19
+ if (a === 'start' || a === '开始') return (await startGame(services, message)) ?? '';
20
+ if (a === 'continue' || a === '继续') return continueGame(services, message);
21
+ if (a === 'quit' || a === '放弃') {
22
+ const session = await services.getActiveForUser(
23
+ channelKey(message),
24
+ message.sender.id,
25
+ );
26
+ if (!session) return gameCommandFeedback(message, 'noGame');
27
+ return (await handleChoice(services, message, session.id, 'quit')) ?? '';
28
+ }
29
+ return gameCommandFeedback(message, 'unknown', action) + '\n\n' + getBjHelp(message);
30
+ } });
30
31
  }
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
  BJ_PREFIX,
5
5
  compareHands,
@@ -19,16 +19,16 @@ import { buildBjView, naturalOutcome, playerBust } from './view.js';
19
19
  */
20
20
  function renderView(
21
21
  session: BjSessionRow,
22
- message: GameMessageLike,
22
+ message: GamePlayer,
23
23
  terminal = false,
24
24
  revealDealer = false,
25
25
  ): GameReply {
26
- return buildBjView(session, terminal, revealDealer, message.$channel.type);
26
+ return buildBjView(session, terminal, revealDealer, message.target.kind);
27
27
  }
28
28
 
29
29
  async function finishRound(
30
30
  services: SessionService,
31
- message: GameMessageLike,
31
+ message: GamePlayer,
32
32
  session: BjSessionRow,
33
33
  status: BjSessionRow['status'],
34
34
  ): Promise<GameReply> {
@@ -52,91 +52,97 @@ async function dealerPlay(
52
52
 
53
53
  export async function startGame(
54
54
  services: SessionService,
55
- message: GameMessageLike,
55
+ message: GamePlayer,
56
56
  ): Promise<GameReply | undefined> {
57
- const ch = `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`;
58
- const active = await services.getActiveByChannel(ch);
59
- const locale = resolveLocale(active ? active.locale : message.locale);
60
- if (active) {
61
- if (active.player_id === message.$sender.id) {
62
- return messages(locale, 'text1');
57
+ return services.runInScope({ scope: channelKey(message), run: async () => {
58
+ const ch = channelKey(message);
59
+ const active = await services.getActiveByChannel(ch);
60
+ const locale = resolveLocale(active ? active.locale : message.locale);
61
+ if (active) {
62
+ if (active.player_id === message.sender.id) {
63
+ return messages(locale, 'text1');
64
+ }
65
+ return messages(locale, 'text2', { p0: active.player_name });
63
66
  }
64
- return messages(locale, 'text2', { p0: active.player_name });
65
- }
66
- const session = await services.createSession(message);
67
- const natural = naturalOutcome(session);
68
- if (natural) {
69
- return finishRound(services, message, session, natural);
70
- }
71
- return renderView(session, message);
67
+ const session = await services.createSession(message);
68
+ const natural = naturalOutcome(session);
69
+ if (natural) {
70
+ return finishRound(services, message, session, natural);
71
+ }
72
+ return renderView(session, message);
73
+ } });
72
74
  }
73
75
 
74
76
  export async function continueGame(
75
77
  services: SessionService,
76
- message: GameMessageLike,
78
+ message: GamePlayer,
77
79
  ): Promise<GameReply> {
78
- const session = await services.getActiveForUser(
79
- `${message.$adapter}-${message.$endpoint}-${message.$channel.type}:${message.$channel.id}`,
80
- message.$sender.id,
81
- );
82
- const locale = resolveLocale(session ? session.locale : message.locale);
83
- if (!session) return messages(locale, 'text3');
84
- return renderView(session, message);
80
+ return services.runInScope({ scope: channelKey(message), run: async () => {
81
+ const session = await services.getActiveForUser(
82
+ channelKey(message),
83
+ message.sender.id,
84
+ );
85
+ const locale = resolveLocale(session ? session.locale : message.locale);
86
+ if (!session) return messages(locale, 'text3');
87
+ return renderView(session, message);
88
+ } });
85
89
  }
86
90
 
87
91
  export async function handleChoice(
88
92
  services: SessionService,
89
- message: GameMessageLike,
93
+ message: GamePlayer,
90
94
  sessionId: string,
91
95
  choiceId: string,
92
96
  ): Promise<GameReply | null> {
93
- const session = await services.getById(sessionId);
94
- const locale = resolveLocale(session ? session.locale : message.locale);
95
- if (!session) return messages(locale, 'text4');
96
- if (session.player_id !== message.$sender.id) return messages(locale, 'text5');
97
-
98
- if (session.status !== 'active' && choiceId === 'restart') {
99
- await services.updateSession(session.id, { status: 'aborted' });
100
- return (await startGame(services, message)) ?? null;
101
- }
97
+ return services.runInScope({ scope: channelKey(message), run: async () => {
98
+ const session = await services.getById(sessionId);
99
+ const locale = resolveLocale(session ? session.locale : message.locale);
100
+ if (!session) return messages(locale, 'text4');
101
+ if (session.player_id !== message.sender.id) return messages(locale, 'text5');
102
+
103
+ if (session.status !== 'active' && choiceId === 'restart') {
104
+ await services.updateSession(session.id, { status: 'aborted' });
105
+ return (await startGame(services, message)) ?? null;
106
+ }
102
107
 
103
- if (session.status !== 'active') return messages(locale, 'text6');
108
+ if (session.status !== 'active') return messages(locale, 'text6');
104
109
 
105
- if (choiceId === 'quit') {
106
- await services.updateSession(session.id, { status: 'aborted' });
107
- return renderView((await services.getById(session.id))!, message, true, true);
108
- }
110
+ if (choiceId === 'quit') {
111
+ await services.updateSession(session.id, { status: 'aborted' });
112
+ return renderView((await services.getById(session.id))!, message, true, true);
113
+ }
109
114
 
110
- const deck = parseDeck(session.deck_json);
111
- let player = parseCards(session.player_cards_json);
112
- let dealer = parseCards(session.dealer_cards_json);
115
+ const deck = parseDeck(session.deck_json);
116
+ let player = parseCards(session.player_cards_json);
117
+ let dealer = parseCards(session.dealer_cards_json);
118
+
119
+ if (choiceId === 'hit') {
120
+ const card = deck.pop();
121
+ if (!card) return messages(locale, 'text7');
122
+ player = [...player, card];
123
+ await services.updateSession(session.id, {
124
+ deck_json: JSON.stringify(deck),
125
+ player_cards_json: JSON.stringify(player),
126
+ });
127
+ if (playerBust({ ...session, player_cards_json: JSON.stringify(player) })) {
128
+ return finishRound(services, message, session, 'lost');
129
+ }
130
+ const updated = (await services.getById(session.id))!;
131
+ return renderView(updated, message);
132
+ }
113
133
 
114
- if (choiceId === 'hit') {
115
- const card = deck.pop();
116
- if (!card) return messages(locale, 'text7');
117
- player = [...player, card];
134
+ if (choiceId !== 'stand') return messages(locale, 'text8');
135
+
136
+ dealer = await dealerPlay(deck, dealer);
118
137
  await services.updateSession(session.id, {
119
138
  deck_json: JSON.stringify(deck),
120
- player_cards_json: JSON.stringify(player),
139
+ dealer_cards_json: JSON.stringify(dealer),
121
140
  });
122
- if (playerBust({ ...session, player_cards_json: JSON.stringify(player) })) {
123
- return finishRound(services, message, session, 'lost');
124
- }
125
- const updated = (await services.getById(session.id))!;
126
- return renderView(updated, message);
127
- }
128
-
129
- if (choiceId !== 'stand') return messages(locale, 'text8');
130
-
131
- dealer = await dealerPlay(deck, dealer);
132
- await services.updateSession(session.id, {
133
- deck_json: JSON.stringify(deck),
134
- dealer_cards_json: JSON.stringify(dealer),
135
- });
136
- const outcome = compareHands(player, dealer);
137
- const status: BjSessionRow['status'] =
138
- outcome === 'won' ? 'won' : outcome === 'lost' ? 'lost' : 'draw';
139
- return finishRound(services, message, session, status);
141
+ const outcome = compareHands(player, dealer);
142
+ const status: BjSessionRow['status'] =
143
+ outcome === 'won' ? 'won' : outcome === 'lost' ? 'lost' : 'draw';
144
+ return finishRound(services, message, session, status);
145
+ } });
140
146
  }
141
147
 
142
148
  export { BJ_PREFIX, handValue, TARGET };
@@ -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 type { BjSessionRow } from './models.js';
@@ -31,21 +30,16 @@ export class SessionService extends BaseSessionService<BjSessionRow> {
31
30
  });
32
31
  }
33
32
 
34
- async createSession(message: GameMessageLike): Promise<BjSessionRow> {
33
+ async createSession(message: GamePlayer): Promise<BjSessionRow> {
35
34
  const deck = freshDeck();
36
35
  const playerCards = [deck.pop()!, deck.pop()!];
37
36
  const dealerCards = [deck.pop()!, deck.pop()!];
38
37
  const now = Date.now();
39
- const row: BjSessionRow = {
38
+ const row: Omit<BjSessionRow, 'channel_key' | 'adapter' | 'endpoint' | 'channel_type' | 'channel_id'> = {
40
39
  id: generateSessionId(),
41
40
  locale: message.locale ?? 'zh-CN',
42
- adapter: String(message.$adapter),
43
- endpoint: message.$endpoint,
44
- channel_type: message.$channel.type,
45
- channel_id: message.$channel.id,
46
- channel_key: channelKey(message),
47
- player_id: message.$sender.id,
48
- player_name: String(message.$sender.name ?? message.$sender.id),
41
+ player_id: message.sender.id,
42
+ player_name: String(message.sender.name ?? message.sender.id),
49
43
  deck_json: JSON.stringify(deck),
50
44
  player_cards_json: JSON.stringify(playerCards),
51
45
  dealer_cards_json: JSON.stringify(dealerCards),
@@ -53,7 +47,7 @@ export class SessionService extends BaseSessionService<BjSessionRow> {
53
47
  updated_at: now,
54
48
  created_at: now,
55
49
  };
56
- return this.createRow(row);
50
+ return this.createRow({ target: message.target, fields: row });
57
51
  }
58
52
  }
59
53