koishi-plugin-prism 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -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;
|
|
@@ -64,31 +64,31 @@ function applyPrismKoishiPlugin(ctx, config) {
|
|
|
64
64
|
return service.handleCommandError(error);
|
|
65
65
|
}
|
|
66
66
|
};
|
|
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))));
|
|
67
|
+
ctx.command("register", "绑定或注册当前平台用户到 PRiSM").action(wrap(async (context) => service.register(await service.sender(context))));
|
|
68
|
+
ctx.command("login", "开启当前玩家的计费场次").action(wrap(async (context) => service.login(await service.sender(context))));
|
|
69
|
+
ctx.command("入场", "入场 (alias of login)").action(wrap(async (context) => service.login(await service.sender(context))));
|
|
70
|
+
ctx.command("mahjong <tableId>", "加入指定麻将桌").action(wrap(async (context, tableId) => service.mahjongJoin(await service.sender(context), tableId)));
|
|
71
|
+
ctx.command("上桌 <tableId>", "加入指定麻将桌").action(wrap(async (context, tableId) => service.mahjongJoin(await service.sender(context), tableId)));
|
|
72
|
+
ctx.command("下桌 <tableId>", "离开指定麻将桌").action(wrap(async (context, tableId) => service.mahjongLeave(await service.sender(context), tableId)));
|
|
73
|
+
ctx.command("logout", "结算当前玩家的计费场次").action(wrap(async (context) => service.logout(await service.sender(context))));
|
|
74
|
+
ctx.command("billing", "预览当前玩家的结账费用").action(wrap(async (context) => service.billing(await service.sender(context))));
|
|
75
|
+
ctx.command("wallet", "查看当前玩家钱包余额").action(wrap(async (context) => service.wallet(await service.sender(context))));
|
|
76
|
+
ctx.command("items", "查看当前玩家持有资产").action(wrap(async (context) => service.items(await service.sender(context))));
|
|
77
|
+
ctx.command("list", "查看当前在线玩家列表").action(wrap(async (context) => service.listActiveSessions(await service.sender(context))));
|
|
78
78
|
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)));
|
|
79
|
+
ctx.command("history", "查看当前玩家历史场次").action(wrap(async (context) => service.history(await service.sender(context))));
|
|
80
|
+
ctx.command("lock", "向默认门锁设备发送开门指令").action(wrap(async (context) => service.lock(await service.sender(context))));
|
|
81
|
+
ctx.command("on <deviceId>", "请求启动指定设备电源").action(wrap(async (context, deviceId) => service.powerOn(await service.sender(context), deviceId)));
|
|
82
|
+
ctx.command("off <deviceId>", "请求关闭指定设备电源").action(wrap(async (context, deviceId) => service.powerOff(await service.sender(context), deviceId)));
|
|
83
|
+
ctx.command("coin <deviceId> [count]", "请求向指定设备投币").action(wrap(async (context, deviceId, count) => service.coin(await service.sender(context), deviceId, count)));
|
|
84
|
+
ctx.command("scan <deviceId> <subject>", "请求指定设备模拟刷卡").action(wrap(async (context, deviceId, subject) => service.scan(await service.sender(context), deviceId, subject)));
|
|
85
|
+
ctx.command("redeem <code>", "兑换 PRiSM 礼物码").action(wrap(async (context, code) => service.redeem(await service.sender(context), code)));
|
|
86
86
|
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)));
|
|
87
|
+
ctx.command("admin.players", "列出 PRiSM 玩家").action(wrap(async (context) => service.staffPlayers(await service.sender(context))));
|
|
88
|
+
ctx.command("admin.create-player <displayName>", "创建 PRiSM 玩家").action(wrap(async (context, displayName) => service.staffCreatePlayer(await service.sender(context), displayName)));
|
|
89
|
+
ctx.command("admin.grant-balance <playerId> <amount>", "给指定玩家发放充值余额").action(wrap(async (context, playerId, amount) => service.staffGrantBalance(await service.sender(context), playerId, amount)));
|
|
90
|
+
ctx.command("admin.redeem-code <code> <presentId>", "创建单次使用兑换码").action(wrap(async (context, code, presentId) => service.staffRedeemCode(await service.sender(context), code, presentId)));
|
|
91
|
+
ctx.command("admin.checkout <playerId>", "替指定玩家结账").action(wrap(async (context, playerId) => service.staffCheckout(await service.sender(context), playerId)));
|
|
92
92
|
}
|
|
93
93
|
const intervalMs = (config.powerOffInterval ?? 0) * 1000;
|
|
94
94
|
if (intervalMs > 0 && typeof ctx.setInterval === "function") {
|
|
@@ -351,9 +351,20 @@ class PrismKoishiService {
|
|
|
351
351
|
});
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
|
-
sender(context) {
|
|
354
|
+
async sender(context) {
|
|
355
355
|
const id = context.session?.senderId || context.session?.userId || "";
|
|
356
|
-
|
|
356
|
+
let name = id;
|
|
357
|
+
try {
|
|
358
|
+
if (context.session?.bot?.getUser) {
|
|
359
|
+
const user = await context.session.bot.getUser(id);
|
|
360
|
+
if (user?.name) {
|
|
361
|
+
name = user.name;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
name = context.session?.username || context.session?.senderName || id;
|
|
367
|
+
}
|
|
357
368
|
return { id, name };
|
|
358
369
|
}
|
|
359
370
|
async register(sender) {
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-prism",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "PRiSM Next 计费与设备管理系统的 Koishi 机器人集成插件",
|
|
5
|
-
"main": "./
|
|
5
|
+
"main": "./lib/index.js",
|
|
6
6
|
"exports": {
|
|
7
|
-
".": "./
|
|
7
|
+
".": "./lib/index.js",
|
|
8
8
|
"./package.json": "./package.json"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
|
-
"
|
|
11
|
+
"lib",
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
14
|
"koishi": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const bun_test_1 = require("bun:test");
|
|
4
|
-
const src_1 = require("../src");
|
|
5
|
-
function createMockKoishiContext(registered) {
|
|
6
|
-
return {
|
|
7
|
-
command(name, description) {
|
|
8
|
-
const command = { description, action: () => "" };
|
|
9
|
-
registered.set(name, command);
|
|
10
|
-
return {
|
|
11
|
-
action(handler) {
|
|
12
|
-
command.action = handler;
|
|
13
|
-
return this;
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
},
|
|
17
|
-
setInterval() { },
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function createDefaultClient() {
|
|
21
|
-
const calls = [];
|
|
22
|
-
return {
|
|
23
|
-
calls,
|
|
24
|
-
async resolveOrRegisterIdentity(input) {
|
|
25
|
-
calls.push(["resolveOrRegisterIdentity", input]);
|
|
26
|
-
return { id: "player-1", displayName: "Neri", status: "active" };
|
|
27
|
-
},
|
|
28
|
-
async startSessionByIdentity(input, body) {
|
|
29
|
-
calls.push(["startSessionByIdentity", input, body]);
|
|
30
|
-
return {
|
|
31
|
-
session: {
|
|
32
|
-
id: "session-1",
|
|
33
|
-
playerId: "player-1",
|
|
34
|
-
startedAt: "2026-06-07T10:00:00.000Z",
|
|
35
|
-
status: "active",
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
},
|
|
39
|
-
async previewCheckoutByIdentity(input) {
|
|
40
|
-
calls.push(["previewCheckoutByIdentity", input]);
|
|
41
|
-
return {
|
|
42
|
-
settlementPreview: {
|
|
43
|
-
playerId: "player-1",
|
|
44
|
-
subtotal: 25,
|
|
45
|
-
total: 22,
|
|
46
|
-
},
|
|
47
|
-
sessionPreviews: [
|
|
48
|
-
{
|
|
49
|
-
sessionId: "session-1",
|
|
50
|
-
label: "音游区间",
|
|
51
|
-
startedAt: "2026-06-07T18:00:00.000Z",
|
|
52
|
-
endedAt: "2026-06-07T19:00:00.000Z",
|
|
53
|
-
status: "closed",
|
|
54
|
-
subtotal: 25,
|
|
55
|
-
total: 22,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
adjustments: [{ amount: -3 }],
|
|
59
|
-
assetHoldings: [{ assetCode: "paid", quantity: 100 }],
|
|
60
|
-
};
|
|
61
|
-
},
|
|
62
|
-
async confirmCheckoutByIdentity(input) {
|
|
63
|
-
calls.push(["confirmCheckoutByIdentity", input]);
|
|
64
|
-
return {
|
|
65
|
-
settlement: { playerId: "player-1", subtotal: 25, total: 22 },
|
|
66
|
-
settlements: [],
|
|
67
|
-
chargeItems: [],
|
|
68
|
-
adjustments: [],
|
|
69
|
-
assetHoldings: [{ assetCode: "paid", quantity: 78 }],
|
|
70
|
-
};
|
|
71
|
-
},
|
|
72
|
-
async stopSessionByIdentity(input, sessionId) {
|
|
73
|
-
calls.push(["stopSessionByIdentity", input, sessionId]);
|
|
74
|
-
return {};
|
|
75
|
-
},
|
|
76
|
-
async getWalletByIdentity(input) {
|
|
77
|
-
calls.push(["getWalletByIdentity", input]);
|
|
78
|
-
return {
|
|
79
|
-
total: { available: 100, all: 100 },
|
|
80
|
-
paid: { available: 60 },
|
|
81
|
-
free: { available: 40 },
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
async getAssetsByIdentity(input) {
|
|
85
|
-
calls.push(["getAssetsByIdentity", input]);
|
|
86
|
-
return { holdings: [{ assetName: "Monthly pass", quantity: 1, expireAt: null }] };
|
|
87
|
-
},
|
|
88
|
-
async getSessionHistoryByIdentity(input) {
|
|
89
|
-
calls.push(["getSessionHistoryByIdentity", input]);
|
|
90
|
-
return { sessions: [{ sessionId: "session-1", createdAt: "2026-06-07T18:00:00.000Z", closedAt: "2026-06-07T19:00:00.000Z", total: 25 }] };
|
|
91
|
-
},
|
|
92
|
-
async requestDeviceCommandByIdentity(input, command) {
|
|
93
|
-
calls.push(["requestDeviceCommandByIdentity", input, command]);
|
|
94
|
-
return { command: { id: "command-1" } };
|
|
95
|
-
},
|
|
96
|
-
async requestScanByIdentity(input, scan) {
|
|
97
|
-
calls.push(["requestScanByIdentity", input, scan]);
|
|
98
|
-
return { command: { id: "scan-1" } };
|
|
99
|
-
},
|
|
100
|
-
async redeemCodeByIdentity(input, code) {
|
|
101
|
-
calls.push(["redeemCodeByIdentity", input, code]);
|
|
102
|
-
return { holdings: [{ assetName: "Coupon", quantity: 1 }] };
|
|
103
|
-
},
|
|
104
|
-
async listStaffPlayers() {
|
|
105
|
-
calls.push(["listStaffPlayers"]);
|
|
106
|
-
return { players: [{ id: "player-1", displayName: "Neri", status: "active", walletTotal: 100 }] };
|
|
107
|
-
},
|
|
108
|
-
async listActiveSessions() {
|
|
109
|
-
calls.push(["listActiveSessions"]);
|
|
110
|
-
return {
|
|
111
|
-
sessions: [
|
|
112
|
-
{
|
|
113
|
-
id: "session-1",
|
|
114
|
-
playerId: "player-1",
|
|
115
|
-
playerDisplayName: "Player 296",
|
|
116
|
-
startedAt: "2026-07-08T11:38:31.000Z",
|
|
117
|
-
label: "音游区间",
|
|
118
|
-
identities: [{ provider: "qq", subject: "2034994588" }],
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
};
|
|
122
|
-
},
|
|
123
|
-
async listDeviceStates() {
|
|
124
|
-
calls.push(["listDeviceStates"]);
|
|
125
|
-
return { deviceStates: [{ deviceId: "ai-1", label: "maimai", state: { state: "on" } }] };
|
|
126
|
-
},
|
|
127
|
-
async createStaffPlayer(displayName) {
|
|
128
|
-
calls.push(["createStaffPlayer", displayName]);
|
|
129
|
-
return { player: { id: "player-new", displayName } };
|
|
130
|
-
},
|
|
131
|
-
async grantStaffAssets(playerId, grants) {
|
|
132
|
-
calls.push(["grantStaffAssets", playerId, grants]);
|
|
133
|
-
return { holdings: [] };
|
|
134
|
-
},
|
|
135
|
-
async createStaffRedeemCode(input) {
|
|
136
|
-
calls.push(["createStaffRedeemCode", input]);
|
|
137
|
-
return { redeemCode: { id: "code-1", code: "PRISM-2026" } };
|
|
138
|
-
},
|
|
139
|
-
async staffCheckout(playerId) {
|
|
140
|
-
calls.push(["staffCheckout", playerId]);
|
|
141
|
-
return { settlement: { total: 25 } };
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
(0, bun_test_1.describe)("applyPrismKoishiPlugin", () => {
|
|
146
|
-
(0, bun_test_1.it)("registers all player commands and basic flows work", async () => {
|
|
147
|
-
const registered = new Map();
|
|
148
|
-
const ctx = createMockKoishiContext(registered);
|
|
149
|
-
const client = createDefaultClient();
|
|
150
|
-
const config = {
|
|
151
|
-
provider: "qq",
|
|
152
|
-
autoRegister: true,
|
|
153
|
-
loginPricingConfigIds: ["pricing-music-standard"],
|
|
154
|
-
loginSessionLabel: "音游区间",
|
|
155
|
-
defaultDoorDeviceId: "front-door",
|
|
156
|
-
defaultScanProvider: "aime",
|
|
157
|
-
currencyName: "猫粮",
|
|
158
|
-
client: client,
|
|
159
|
-
};
|
|
160
|
-
(0, src_1.applyPrismKoishiPlugin)(ctx, config);
|
|
161
|
-
const expected = [
|
|
162
|
-
"register",
|
|
163
|
-
"login",
|
|
164
|
-
"入场",
|
|
165
|
-
"mahjong <tableId>",
|
|
166
|
-
"上桌 <tableId>",
|
|
167
|
-
"下桌 <tableId>",
|
|
168
|
-
"logout",
|
|
169
|
-
"billing",
|
|
170
|
-
"wallet",
|
|
171
|
-
"items",
|
|
172
|
-
"list",
|
|
173
|
-
"show [deviceId]",
|
|
174
|
-
"history",
|
|
175
|
-
"lock",
|
|
176
|
-
"on <deviceId>",
|
|
177
|
-
"off <deviceId>",
|
|
178
|
-
"coin <deviceId> [count]",
|
|
179
|
-
"scan <deviceId> <subject>",
|
|
180
|
-
"redeem <code>",
|
|
181
|
-
];
|
|
182
|
-
(0, bun_test_1.expect)([...registered.keys()]).toEqual(expected);
|
|
183
|
-
await (0, bun_test_1.expect)(registered.get("login")?.action({ session: { userId: "123456", senderName: "Tester" } })).resolves.toContain("✅ 入场成功");
|
|
184
|
-
await (0, bun_test_1.expect)(registered.get("wallet")?.action({ session: { userId: "123456" } })).resolves.toContain("100 猫粮");
|
|
185
|
-
const billingResult = await registered.get("billing")?.action({ session: { userId: "123456", senderName: "Tester" } });
|
|
186
|
-
(0, bun_test_1.expect)(billingResult).toContain("计费总价:25猫粮");
|
|
187
|
-
(0, bun_test_1.expect)(billingResult).toContain("玩家ID:player-1");
|
|
188
|
-
const listResult = await registered.get("list")?.action({ session: { userId: "123456" } });
|
|
189
|
-
(0, bun_test_1.expect)(listResult).toContain("窝里目前共有 1 人");
|
|
190
|
-
(0, bun_test_1.expect)(listResult).toContain("2034994588");
|
|
191
|
-
});
|
|
192
|
-
(0, bun_test_1.it)("uses platform display name when resolver is provided", async () => {
|
|
193
|
-
const registered = new Map();
|
|
194
|
-
const ctx = createMockKoishiContext(registered);
|
|
195
|
-
const client = createDefaultClient();
|
|
196
|
-
const config = {
|
|
197
|
-
provider: "qq",
|
|
198
|
-
autoRegister: true,
|
|
199
|
-
defaultDoorDeviceId: "front-door",
|
|
200
|
-
defaultScanProvider: "aime",
|
|
201
|
-
currencyName: "猫粮",
|
|
202
|
-
resolveDisplayName: () => Promise.resolve("🎀hanahana🎀"),
|
|
203
|
-
client: client,
|
|
204
|
-
};
|
|
205
|
-
(0, src_1.applyPrismKoishiPlugin)(ctx, config);
|
|
206
|
-
const listResult = await registered.get("list")?.action({ session: { userId: "123456" } });
|
|
207
|
-
(0, bun_test_1.expect)(listResult).toContain("🎀hanahana🎀");
|
|
208
|
-
(0, bun_test_1.expect)(listResult).toContain("2034994588");
|
|
209
|
-
});
|
|
210
|
-
(0, bun_test_1.it)("shows device states and power commands", async () => {
|
|
211
|
-
const registered = new Map();
|
|
212
|
-
const ctx = createMockKoishiContext(registered);
|
|
213
|
-
const client = createDefaultClient();
|
|
214
|
-
const config = {
|
|
215
|
-
provider: "qq",
|
|
216
|
-
autoRegister: true,
|
|
217
|
-
defaultDoorDeviceId: "front-door",
|
|
218
|
-
defaultScanProvider: "aime",
|
|
219
|
-
currencyName: "猫粮",
|
|
220
|
-
client: client,
|
|
221
|
-
};
|
|
222
|
-
(0, src_1.applyPrismKoishiPlugin)(ctx, config);
|
|
223
|
-
const list = await registered.get("show [deviceId]")?.action({ session: { userId: "123456" } });
|
|
224
|
-
(0, bun_test_1.expect)(list).toContain("maimai: on");
|
|
225
|
-
const res = await registered.get("show [deviceId]")?.action({ session: { userId: "123456" } }, "ai-1");
|
|
226
|
-
(0, bun_test_1.expect)(res).toContain("maimai: on");
|
|
227
|
-
const onResult = await registered.get("on <deviceId>")?.action({ session: { userId: "123456" } }, "ai-1");
|
|
228
|
-
(0, bun_test_1.expect)(onResult).toContain("ai-1 启动成功");
|
|
229
|
-
const coinResult = await registered.get("coin <deviceId> [count]")?.action({ session: { userId: "123456" } }, "ai-1", "2");
|
|
230
|
-
(0, bun_test_1.expect)(coinResult).toContain("2 个币");
|
|
231
|
-
const scanResult = await registered.get("scan <deviceId> <subject>")?.action({ session: { userId: "123456" } }, "aime-1", "card-4321");
|
|
232
|
-
(0, bun_test_1.expect)(scanResult).toContain("尾号为 4321");
|
|
233
|
-
const redeemResult = await registered.get("redeem <code>")?.action({ session: { userId: "123456" } }, "PRISM-2026");
|
|
234
|
-
(0, bun_test_1.expect)(redeemResult).toContain("兑换成功");
|
|
235
|
-
});
|
|
236
|
-
(0, bun_test_1.it)("registers and runs mahjong commands", async () => {
|
|
237
|
-
const registered = new Map();
|
|
238
|
-
const ctx = createMockKoishiContext(registered);
|
|
239
|
-
const client = createDefaultClient();
|
|
240
|
-
const config = {
|
|
241
|
-
provider: "qq",
|
|
242
|
-
autoRegister: true,
|
|
243
|
-
defaultDoorDeviceId: "front-door",
|
|
244
|
-
defaultScanProvider: "aime",
|
|
245
|
-
currencyName: "猫粮",
|
|
246
|
-
mahjongTables: "a,四麻A : 🀄️ M.LEAGUE联名比赛专用机 = pricing-mahjong-a",
|
|
247
|
-
mahjongTableSize: 4,
|
|
248
|
-
client: client,
|
|
249
|
-
};
|
|
250
|
-
(0, src_1.applyPrismKoishiPlugin)(ctx, config);
|
|
251
|
-
const joinResult = await registered.get("上桌 <tableId>")?.action({ session: { userId: "2034994588", senderName: "hanahana" } }, "a");
|
|
252
|
-
(0, bun_test_1.expect)(joinResult).toContain("已加入 🀄️ M.LEAGUE联名比赛专用机");
|
|
253
|
-
(0, bun_test_1.expect)(joinResult).toContain("1/4 人");
|
|
254
|
-
const leaveResult = await registered.get("下桌 <tableId>")?.action({ session: { userId: "2034994588", senderName: "hanahana" } }, "a");
|
|
255
|
-
(0, bun_test_1.expect)(leaveResult).toContain("已离开");
|
|
256
|
-
});
|
|
257
|
-
(0, bun_test_1.it)("registers and runs staff admin commands when enabled", async () => {
|
|
258
|
-
const registered = new Map();
|
|
259
|
-
const ctx = createMockKoishiContext(registered);
|
|
260
|
-
const client = createDefaultClient();
|
|
261
|
-
const config = {
|
|
262
|
-
provider: "qq",
|
|
263
|
-
autoRegister: true,
|
|
264
|
-
defaultDoorDeviceId: "front-door",
|
|
265
|
-
defaultScanProvider: "aime",
|
|
266
|
-
currencyName: "猫粮",
|
|
267
|
-
enableStaffCommands: true,
|
|
268
|
-
staffUserIds: [],
|
|
269
|
-
client: client,
|
|
270
|
-
};
|
|
271
|
-
(0, src_1.applyPrismKoishiPlugin)(ctx, config);
|
|
272
|
-
const adminNames = [...registered.keys()].filter((name) => name.startsWith("admin."));
|
|
273
|
-
(0, bun_test_1.expect)(adminNames).toEqual([
|
|
274
|
-
"admin.players",
|
|
275
|
-
"admin.create-player <displayName>",
|
|
276
|
-
"admin.grant-balance <playerId> <amount>",
|
|
277
|
-
"admin.redeem-code <code> <presentId>",
|
|
278
|
-
"admin.checkout <playerId>",
|
|
279
|
-
]);
|
|
280
|
-
await (0, bun_test_1.expect)(registered.get("admin.players")?.action({ session: { userId: "admin" } })).resolves.toContain("Neri");
|
|
281
|
-
await (0, bun_test_1.expect)(registered.get("admin.create-player <displayName>")?.action({ session: { userId: "admin" } }, "Mika")).resolves.toContain("player-new");
|
|
282
|
-
await (0, bun_test_1.expect)(registered.get("admin.grant-balance <playerId> <amount>")?.action({ session: { userId: "admin" } }, "player-1", "100")).resolves.toContain("发放");
|
|
283
|
-
await (0, bun_test_1.expect)(registered.get("admin.redeem-code <code> <presentId>")?.action({ session: { userId: "admin" } }, "PRISM-2026", "present-1")).resolves.toContain("PRISM-2026");
|
|
284
|
-
await (0, bun_test_1.expect)(registered.get("admin.checkout <playerId>")?.action({ session: { userId: "admin" } }, "player-1")).resolves.toContain("25");
|
|
285
|
-
});
|
|
286
|
-
(0, bun_test_1.it)("denies staff commands when not enabled", async () => {
|
|
287
|
-
const registered = new Map();
|
|
288
|
-
const ctx = createMockKoishiContext(registered);
|
|
289
|
-
const client = createDefaultClient();
|
|
290
|
-
const config = {
|
|
291
|
-
provider: "qq",
|
|
292
|
-
autoRegister: true,
|
|
293
|
-
defaultDoorDeviceId: "front-door",
|
|
294
|
-
defaultScanProvider: "aime",
|
|
295
|
-
currencyName: "猫粮",
|
|
296
|
-
client: client,
|
|
297
|
-
};
|
|
298
|
-
(0, src_1.applyPrismKoishiPlugin)(ctx, config);
|
|
299
|
-
const adminNames = [...registered.keys()].filter((name) => name.startsWith("admin."));
|
|
300
|
-
(0, bun_test_1.expect)(adminNames).toEqual([]);
|
|
301
|
-
});
|
|
302
|
-
});
|