koishi-plugin-prism 0.1.3 → 0.1.5

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 CHANGED
@@ -24,7 +24,7 @@
24
24
  | `provider` | `string` | `"qq"` | 当前绑定的账号提供商平台名称(如 `"qq"`,`"discord"`)。 |
25
25
  | `autoRegister` | `boolean` | `true` | 当玩家未注册时,是否在首次操作(如入场/查钱包)时自动在 PRiSM 中创建新玩家。 |
26
26
  | `loginPricingConfigIds` | `string[]` | `[]` | 默认入场计费规则 ID 列表。 |
27
- | `loginSessionLabel` | `string` | - | 默认入场会话的备注文本(如 `"音游区间"`)。 |
27
+ | `loginSessionLabel` | `string` | `"音游区间"` | 默认入场会话的标签文本。后端会按该标签对同一玩家的活跃会话去重,重复入场会被拒绝并提示。留空则不启用去重。 |
28
28
  | `defaultDoorDeviceId` | `string` | - | 默认门锁设备的 ID,用于开门指令。 |
29
29
  | `defaultScanProvider` | `string` | `"aime"` | 默认模拟刷卡时的读卡器协议提供商(如 `"aime"`)。 |
30
30
  | `currencyName` | `string` | `"金币"` | 账户货币在显示时的自定义单位名称。 |
package/lib/index.d.ts CHANGED
@@ -58,6 +58,12 @@ export type KoishiActionContext = {
58
58
  userId: string;
59
59
  senderId?: string;
60
60
  senderName?: string;
61
+ username?: string;
62
+ bot?: {
63
+ getUser?(id: string): Promise<{
64
+ name?: string;
65
+ }>;
66
+ };
61
67
  };
62
68
  };
63
69
  export declare function applyPrismKoishiPlugin(ctx: KoishiLikeContext, config: PrismKoishiPluginConfig): void;
package/lib/index.js CHANGED
@@ -16,7 +16,10 @@ exports.Config = koishi_1.Schema.object({
16
16
  currencyName: koishi_1.Schema.string().default("猫粮").description("代币名称"),
17
17
  defaultDoorDeviceId: koishi_1.Schema.string().default("front-door").description("默认开门设备ID"),
18
18
  defaultScanProvider: koishi_1.Schema.string().default("aime").description("默认刷卡提供商"),
19
+ loginPricingConfigIds: koishi_1.Schema.array(koishi_1.Schema.string()).default([]).description("默认入场绑定的计费策略ID"),
20
+ loginSessionLabel: koishi_1.Schema.string().default("音游区间").description("默认入场场次标签 (防重复入场)"),
19
21
  enableStaffCommands: koishi_1.Schema.boolean().default(false).description("是否启用管理员指令"),
22
+ staffUserIds: koishi_1.Schema.array(koishi_1.Schema.string()).default([]).description("允许执行管理员指令的平台用户ID列表"),
20
23
  powerOffInterval: koishi_1.Schema.number().default(0).description("无人自动关机等待秒数 (0为禁用)"),
21
24
  mahjongTables: koishi_1.Schema.string().description("麻将桌配置"),
22
25
  mahjongTableSize: koishi_1.Schema.number().default(4).description("麻将桌人数限制"),
@@ -64,31 +67,31 @@ function applyPrismKoishiPlugin(ctx, config) {
64
67
  return service.handleCommandError(error);
65
68
  }
66
69
  };
67
- ctx.command("register", "绑定或注册当前平台用户到 PRiSM").action(wrap(async (context) => service.register(service.sender(context))));
68
- ctx.command("login", "开启当前玩家的计费场次").action(async (context) => service.login(service.sender(context)));
69
- ctx.command("入场", "入场 (alias of login)").action(wrap(async (context) => service.login(service.sender(context))));
70
- ctx.command("mahjong <tableId>", "加入指定麻将桌").action(wrap(async (context, tableId) => service.mahjongJoin(service.sender(context), tableId)));
71
- ctx.command("上桌 <tableId>", "加入指定麻将桌").action(wrap(async (context, tableId) => service.mahjongJoin(service.sender(context), tableId)));
72
- ctx.command("下桌 <tableId>", "离开指定麻将桌").action(wrap(async (context, tableId) => service.mahjongLeave(service.sender(context), tableId)));
73
- ctx.command("logout", "结算当前玩家的计费场次").action(wrap(async (context) => service.logout(service.sender(context))));
74
- ctx.command("billing", "预览当前玩家的结账费用").action(wrap(async (context) => service.billing(service.sender(context))));
75
- ctx.command("wallet", "查看当前玩家钱包余额").action(wrap(async (context) => service.wallet(service.sender(context))));
76
- ctx.command("items", "查看当前玩家持有资产").action(wrap(async (context) => service.items(service.sender(context))));
77
- ctx.command("list", "查看当前在线玩家列表").action(wrap(async (context) => service.listActiveSessions(service.sender(context))));
70
+ ctx.command("register", "绑定或注册当前平台用户到 PRiSM").action(wrap(async (context) => service.register(await service.sender(context))));
71
+ ctx.command("login", "开启当前玩家的计费场次").action(wrap(async (context) => service.login(await service.sender(context))));
72
+ ctx.command("入场", "入场 (alias of login)").action(wrap(async (context) => service.login(await service.sender(context))));
73
+ ctx.command("mahjong <tableId>", "加入指定麻将桌").action(wrap(async (context, tableId) => service.mahjongJoin(await service.sender(context), tableId)));
74
+ ctx.command("上桌 <tableId>", "加入指定麻将桌").action(wrap(async (context, tableId) => service.mahjongJoin(await service.sender(context), tableId)));
75
+ ctx.command("下桌 <tableId>", "离开指定麻将桌").action(wrap(async (context, tableId) => service.mahjongLeave(await service.sender(context), tableId)));
76
+ ctx.command("logout", "结算当前玩家的计费场次").action(wrap(async (context) => service.logout(await service.sender(context))));
77
+ ctx.command("billing", "预览当前玩家的结账费用").action(wrap(async (context) => service.billing(await service.sender(context))));
78
+ ctx.command("wallet", "查看当前玩家钱包余额").action(wrap(async (context) => service.wallet(await service.sender(context))));
79
+ ctx.command("items", "查看当前玩家持有资产").action(wrap(async (context) => service.items(await service.sender(context))));
80
+ ctx.command("list", "查看当前在线玩家列表").action(wrap(async (context) => service.listActiveSessions(await service.sender(context))));
78
81
  ctx.command("show [deviceId]", "查看设备电源状态").action(wrap(async (context, deviceId) => service.listDeviceStates(deviceId)));
79
- ctx.command("history", "查看当前玩家历史场次").action(wrap(async (context) => service.history(service.sender(context))));
80
- ctx.command("lock", "向默认门锁设备发送开门指令").action(wrap(async (context) => service.lock(service.sender(context))));
81
- ctx.command("on <deviceId>", "请求启动指定设备电源").action(wrap(async (context, deviceId) => service.powerOn(service.sender(context), deviceId)));
82
- ctx.command("off <deviceId>", "请求关闭指定设备电源").action(wrap(async (context, deviceId) => service.powerOff(service.sender(context), deviceId)));
83
- ctx.command("coin <deviceId> [count]", "请求向指定设备投币").action(wrap(async (context, deviceId, count) => service.coin(service.sender(context), deviceId, count)));
84
- ctx.command("scan <deviceId> <subject>", "请求指定设备模拟刷卡").action(wrap(async (context, deviceId, subject) => service.scan(service.sender(context), deviceId, subject)));
85
- ctx.command("redeem <code>", "兑换 PRiSM 礼物码").action(wrap(async (context, code) => service.redeem(service.sender(context), code)));
82
+ ctx.command("history", "查看当前玩家历史场次").action(wrap(async (context) => service.history(await service.sender(context))));
83
+ ctx.command("lock", "向默认门锁设备发送开门指令").action(wrap(async (context) => service.lock(await service.sender(context))));
84
+ ctx.command("on <deviceId>", "请求启动指定设备电源").action(wrap(async (context, deviceId) => service.powerOn(await service.sender(context), deviceId)));
85
+ ctx.command("off <deviceId>", "请求关闭指定设备电源").action(wrap(async (context, deviceId) => service.powerOff(await service.sender(context), deviceId)));
86
+ ctx.command("coin <deviceId> [count]", "请求向指定设备投币").action(wrap(async (context, deviceId, count) => service.coin(await service.sender(context), deviceId, count)));
87
+ ctx.command("scan <deviceId> <subject>", "请求指定设备模拟刷卡").action(wrap(async (context, deviceId, subject) => service.scan(await service.sender(context), deviceId, subject)));
88
+ ctx.command("redeem <code>", "兑换 PRiSM 礼物码").action(wrap(async (context, code) => service.redeem(await service.sender(context), code)));
86
89
  if (config.enableStaffCommands) {
87
- ctx.command("admin.players", "列出 PRiSM 玩家").action(wrap(async (context) => service.staffPlayers(service.sender(context))));
88
- ctx.command("admin.create-player <displayName>", "创建 PRiSM 玩家").action(wrap(async (context, displayName) => service.staffCreatePlayer(service.sender(context), displayName)));
89
- ctx.command("admin.grant-balance <playerId> <amount>", "给指定玩家发放充值余额").action(wrap(async (context, playerId, amount) => service.staffGrantBalance(service.sender(context), playerId, amount)));
90
- ctx.command("admin.redeem-code <code> <presentId>", "创建单次使用兑换码").action(wrap(async (context, code, presentId) => service.staffRedeemCode(service.sender(context), code, presentId)));
91
- ctx.command("admin.checkout <playerId>", "替指定玩家结账").action(wrap(async (context, playerId) => service.staffCheckout(service.sender(context), playerId)));
90
+ ctx.command("admin.players", "列出 PRiSM 玩家").action(wrap(async (context) => service.staffPlayers(await service.sender(context))));
91
+ ctx.command("admin.create-player <displayName>", "创建 PRiSM 玩家").action(wrap(async (context, displayName) => service.staffCreatePlayer(await service.sender(context), displayName)));
92
+ ctx.command("admin.grant-balance <playerId> <amount>", "给指定玩家发放充值余额").action(wrap(async (context, playerId, amount) => service.staffGrantBalance(await service.sender(context), playerId, amount)));
93
+ ctx.command("admin.redeem-code <code> <presentId>", "创建单次使用兑换码").action(wrap(async (context, code, presentId) => service.staffRedeemCode(await service.sender(context), code, presentId)));
94
+ ctx.command("admin.checkout <playerId>", "替指定玩家结账").action(wrap(async (context, playerId) => service.staffCheckout(await service.sender(context), playerId)));
92
95
  }
93
96
  const intervalMs = (config.powerOffInterval ?? 0) * 1000;
94
97
  if (intervalMs > 0 && typeof ctx.setInterval === "function") {
@@ -351,9 +354,20 @@ class PrismKoishiService {
351
354
  });
352
355
  }
353
356
  }
354
- sender(context) {
357
+ async sender(context) {
355
358
  const id = context.session?.senderId || context.session?.userId || "";
356
- const name = context.session?.senderName || id;
359
+ let name = id;
360
+ try {
361
+ if (context.session?.bot?.getUser) {
362
+ const user = await context.session.bot.getUser(id);
363
+ if (user?.name) {
364
+ name = user.name;
365
+ }
366
+ }
367
+ }
368
+ catch {
369
+ name = context.session?.username || context.session?.senderName || id;
370
+ }
357
371
  return { id, name };
358
372
  }
359
373
  async register(sender) {
@@ -835,6 +849,18 @@ class PrismKoishiService {
835
849
  }
836
850
  }
837
851
  function humanReadableBotError(error) {
852
+ if (error.code === "DUPLICATE_SESSION_LABEL") {
853
+ return "❌ 您已经处于入场状态,请勿重复发送入场命令。";
854
+ }
855
+ if (error.code === "PLAYER_HAS_NO_UNSETTLED_SESSIONS") {
856
+ return "您当前没有未结算的账单,无需结账。";
857
+ }
858
+ if (error.code === "ACTIVE_SESSION_NOT_FOUND") {
859
+ return "您当前没有进行中的计费场次。";
860
+ }
861
+ if (error.code === "PLAYER_IDENTITY_NOT_FOUND") {
862
+ return "未找到您的玩家身份,请先注册或绑定账号。";
863
+ }
838
864
  if (error.code === "INSUFFICIENT_BALANCE") {
839
865
  return "余额不足,暂时不能结账。请先充值,或由店员在后台改价后再结账。";
840
866
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-prism",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "PRiSM Next 计费与设备管理系统的 Koishi 机器人集成插件",
5
5
  "main": "./lib/index.js",
6
6
  "exports": {