koishi-plugin-prism-neo 0.0.25 → 0.0.26
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/lib/index.js +607 -200
- package/lib/model.d.ts +14 -0
- package/lib/service.d.ts +60 -31
- package/lib/types.d.ts +3 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -28,154 +28,218 @@ module.exports = __toCommonJS(src_exports);
|
|
|
28
28
|
var import_koishi = require("koishi");
|
|
29
29
|
|
|
30
30
|
// src/service.ts
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
var PrismService = class {
|
|
32
|
+
constructor(ctx, config) {
|
|
33
|
+
this.ctx = ctx;
|
|
34
|
+
this.config = config;
|
|
35
|
+
this.apiBase = `${config.url.trimEnd().replace(/\/+$/, "")}/api`;
|
|
36
|
+
}
|
|
37
|
+
static {
|
|
38
|
+
__name(this, "PrismService");
|
|
39
|
+
}
|
|
40
|
+
apiBase;
|
|
41
|
+
url(endpoint) {
|
|
42
|
+
return `${this.apiBase}/${endpoint.trimStart().replace(/^\/+/, "")}`;
|
|
43
|
+
}
|
|
44
|
+
async register(userId) {
|
|
45
|
+
return await this.ctx.http.post(
|
|
46
|
+
this.url("/users"),
|
|
47
|
+
[
|
|
48
|
+
{
|
|
49
|
+
"binds": [
|
|
50
|
+
{
|
|
51
|
+
"type": "QQ",
|
|
52
|
+
"bid": userId
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
async login(userId) {
|
|
60
|
+
return await this.ctx.http.post(
|
|
61
|
+
this.url(`/users/QQ:${userId}/login`)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
async history(userId, limit) {
|
|
65
|
+
return await this.ctx.http.get(
|
|
66
|
+
this.url(`/users/QQ:${userId}/sortedsessions?limit=${limit}`)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
async logout(userId) {
|
|
70
|
+
return await this.ctx.http.post(
|
|
71
|
+
this.url(`/users/QQ:${userId}/logout`)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
async billing(userId) {
|
|
75
|
+
return await this.ctx.http.get(
|
|
76
|
+
this.url(`/users/QQ:${userId}/billing`)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
async list() {
|
|
80
|
+
return await this.ctx.http.get(
|
|
81
|
+
this.url(`/users/logined?binds=true&sessions=true`)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
async wallet(userId) {
|
|
85
|
+
return await this.ctx.http.get(
|
|
86
|
+
this.url(`/users/QQ:${userId}/wallet?details=true`)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
async assets(userId) {
|
|
90
|
+
return await this.ctx.http.get(
|
|
91
|
+
this.url(`/users/QQ:${userId}/assets?details=true`)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
async upsertUserAssets(userId, assets) {
|
|
95
|
+
return await this.ctx.http.post(
|
|
96
|
+
this.url(`/users/QQ:${userId}/assets`),
|
|
97
|
+
assets
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
async deleteUserAsset(userId, userAssetId) {
|
|
101
|
+
return await this.ctx.http.delete(
|
|
102
|
+
this.url(`/users/QQ:${userId}/assets/${userAssetId}`)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
async updateUserAsset(userId, userAssetId, amount) {
|
|
106
|
+
return await this.ctx.http.patch(
|
|
107
|
+
this.url(`/users/QQ:${userId}/assets/${userAssetId}`),
|
|
108
|
+
{ amount }
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
async getLock(userId) {
|
|
112
|
+
return await this.ctx.http.get(
|
|
113
|
+
this.url(`/users/QQ:${userId}/door-password`)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
async machinePowerOn(machineName, userId, needLogin = true) {
|
|
117
|
+
return await this.ctx.http.post(
|
|
118
|
+
this.url(`/machine/power`),
|
|
39
119
|
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
]
|
|
120
|
+
machineName,
|
|
121
|
+
powerState: true,
|
|
122
|
+
userId: `QQ:${userId}`,
|
|
123
|
+
needLogin
|
|
46
124
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
__name(redeem, "redeem");
|
|
169
|
-
async function insertCoin({ ctx, config }, alias, userId, force = false) {
|
|
170
|
-
return await ctx.http.post(
|
|
171
|
-
makeUrl(config.url, `/remote/${alias}/coin`),
|
|
172
|
-
{
|
|
173
|
-
userId: `QQ:${userId}`,
|
|
174
|
-
force
|
|
175
|
-
}
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
__name(insertCoin, "insertCoin");
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
async machinePowerOff(machineName, userId, needLogin = true) {
|
|
128
|
+
return await this.ctx.http.post(
|
|
129
|
+
this.url(`/machine/power`),
|
|
130
|
+
{
|
|
131
|
+
machineName,
|
|
132
|
+
powerState: false,
|
|
133
|
+
userId: `QQ:${userId}`,
|
|
134
|
+
needLogin
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
async getAllMachinePower() {
|
|
139
|
+
return await this.ctx.http.get(
|
|
140
|
+
this.url(`/machine/power`)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
async getMachinePower(machineName) {
|
|
144
|
+
return await this.ctx.http.get(
|
|
145
|
+
this.url(`/machine/power?name=${machineName}`)
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
async walletAdd(amount, userId) {
|
|
149
|
+
return await this.ctx.http.post(
|
|
150
|
+
this.url(`/users/QQ:${userId}/wallet`),
|
|
151
|
+
{
|
|
152
|
+
type: "free",
|
|
153
|
+
action: amount,
|
|
154
|
+
comment: "管理员添加"
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
async walletDel(amount, userId) {
|
|
159
|
+
return await this.ctx.http.post(
|
|
160
|
+
this.url(`/users/QQ:${userId}/wallet`),
|
|
161
|
+
{
|
|
162
|
+
type: "free",
|
|
163
|
+
action: -amount,
|
|
164
|
+
comment: "管理员扣除"
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
async costOverwrite(amount, userId) {
|
|
169
|
+
return await this.ctx.http.post(
|
|
170
|
+
this.url(`/users/QQ:${userId}/billing-overwrite`),
|
|
171
|
+
{
|
|
172
|
+
cost: parseInt(amount)
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
async redeem(code, userId) {
|
|
177
|
+
return await this.ctx.http.post(
|
|
178
|
+
this.url(`/users/QQ:${userId}/redeem`),
|
|
179
|
+
{
|
|
180
|
+
code
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
async insertCoin(alias, userId, force = false) {
|
|
185
|
+
return await this.ctx.http.post(
|
|
186
|
+
this.url(`/remote/${alias}/coin`),
|
|
187
|
+
{
|
|
188
|
+
userId: `QQ:${userId}`,
|
|
189
|
+
force
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
// --- Admin API ---
|
|
194
|
+
async adminListAssets() {
|
|
195
|
+
return await this.ctx.http.get(this.url("/admin/assets"));
|
|
196
|
+
}
|
|
197
|
+
async adminCreateAsset(data) {
|
|
198
|
+
return await this.ctx.http.post(this.url("/admin/assets"), data);
|
|
199
|
+
}
|
|
200
|
+
async adminDeleteAsset(id) {
|
|
201
|
+
return await this.ctx.http.delete(this.url(`/admin/assets/${id}`));
|
|
202
|
+
}
|
|
203
|
+
async adminListCoupons() {
|
|
204
|
+
return await this.ctx.http.get(this.url("/admin/coupons"));
|
|
205
|
+
}
|
|
206
|
+
async adminCreateCoupon(data) {
|
|
207
|
+
return await this.ctx.http.post(this.url("/admin/coupons"), data);
|
|
208
|
+
}
|
|
209
|
+
async adminListGifts() {
|
|
210
|
+
return await this.ctx.http.get(this.url("/admin/gifts"));
|
|
211
|
+
}
|
|
212
|
+
async adminCreateGift(data) {
|
|
213
|
+
return await this.ctx.http.post(this.url("/admin/gifts"), data);
|
|
214
|
+
}
|
|
215
|
+
async adminDeleteGift(id) {
|
|
216
|
+
return await this.ctx.http.delete(this.url(`/admin/gifts/${id}`));
|
|
217
|
+
}
|
|
218
|
+
async adminGenerateGiftCodes(id, count) {
|
|
219
|
+
return await this.ctx.http.post(this.url(`/admin/gifts/${id}/codes`), { count });
|
|
220
|
+
}
|
|
221
|
+
async adminListRules() {
|
|
222
|
+
return await this.ctx.http.get(this.url("/admin/rules"));
|
|
223
|
+
}
|
|
224
|
+
async adminCreateRule(data) {
|
|
225
|
+
return await this.ctx.http.post(this.url("/admin/rules"), data);
|
|
226
|
+
}
|
|
227
|
+
async adminDeleteRule(id) {
|
|
228
|
+
return await this.ctx.http.delete(this.url(`/admin/rules/${id}`));
|
|
229
|
+
}
|
|
230
|
+
async adminUpdateRuleStatus(id, available) {
|
|
231
|
+
return await this.ctx.http(this.url(`/admin/rules/${id}`), {
|
|
232
|
+
method: "PATCH",
|
|
233
|
+
data: { available }
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
async adminAddUserAsset(userId, id, count) {
|
|
237
|
+
return await this.ctx.http.post(this.url(`/users/QQ:${userId}/assets`), {
|
|
238
|
+
id,
|
|
239
|
+
count
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
179
243
|
|
|
180
244
|
// src/index.ts
|
|
181
245
|
var name = "prism-neo";
|
|
@@ -197,7 +261,7 @@ var Config = import_koishi.Schema.object({
|
|
|
197
261
|
});
|
|
198
262
|
async function getUserName(session, userId) {
|
|
199
263
|
if (userId) {
|
|
200
|
-
return
|
|
264
|
+
return "dummy";
|
|
201
265
|
} else {
|
|
202
266
|
return "匿名用户";
|
|
203
267
|
}
|
|
@@ -214,15 +278,22 @@ var handleAction = /* @__PURE__ */ __name((action) => {
|
|
|
214
278
|
if (apiMessage) {
|
|
215
279
|
message = apiMessage;
|
|
216
280
|
} else {
|
|
217
|
-
message =
|
|
281
|
+
message = e.message;
|
|
218
282
|
}
|
|
219
283
|
}
|
|
284
|
+
if (!message) return;
|
|
220
285
|
if (argv.session?.messageId) {
|
|
221
286
|
message = (0, import_koishi.h)("quote", { id: argv.session.messageId }) + message;
|
|
222
287
|
}
|
|
223
288
|
return message;
|
|
224
289
|
};
|
|
225
290
|
}, "handleAction");
|
|
291
|
+
async function checkAdmin(context) {
|
|
292
|
+
if (!await context.ctx.permissions.check(context.config.admin, context.session)) {
|
|
293
|
+
throw new Error("权限不足");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
__name(checkAdmin, "checkAdmin");
|
|
226
297
|
var formatDateTime = /* @__PURE__ */ __name((dateStr) => {
|
|
227
298
|
if (!dateStr) return "永不过期";
|
|
228
299
|
const date = new Date(dateStr);
|
|
@@ -311,7 +382,7 @@ var formatBilling = /* @__PURE__ */ __name((res, currency) => {
|
|
|
311
382
|
}
|
|
312
383
|
return message.join("\n");
|
|
313
384
|
}, "formatBilling");
|
|
314
|
-
async function executeWithAutoRegister(context, userArg,
|
|
385
|
+
async function executeWithAutoRegister(context, userArg, action, formatter) {
|
|
315
386
|
try {
|
|
316
387
|
const res = await action();
|
|
317
388
|
return await formatter(res);
|
|
@@ -344,7 +415,7 @@ async function getTargetUserId(context, user) {
|
|
|
344
415
|
if (!await context.ctx.permissions.check(context.config.admin, context.session)) {
|
|
345
416
|
return { error: "权限不足" };
|
|
346
417
|
}
|
|
347
|
-
return { userId: user.split(":")[1] };
|
|
418
|
+
return { userId: user.split(":")[1] ?? user };
|
|
348
419
|
}
|
|
349
420
|
return { userId: context.session.userId };
|
|
350
421
|
}
|
|
@@ -352,27 +423,33 @@ __name(getTargetUserId, "getTargetUserId");
|
|
|
352
423
|
async function handleRegisterCmd(context, user) {
|
|
353
424
|
const { error, userId } = await getTargetUserId(context, user);
|
|
354
425
|
if (error) return error;
|
|
355
|
-
await register(
|
|
426
|
+
await context.prism.register(userId);
|
|
356
427
|
return user ? `为用户 ${userId} 注册成功` : "注册成功";
|
|
357
428
|
}
|
|
358
429
|
__name(handleRegisterCmd, "handleRegisterCmd");
|
|
359
430
|
async function handleLoginCmd(context, user) {
|
|
360
431
|
const { error, userId } = await getTargetUserId(context, user);
|
|
361
432
|
if (error) return error;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
433
|
+
return executeWithAutoRegister(
|
|
434
|
+
context,
|
|
435
|
+
user,
|
|
436
|
+
() => context.prism.login(userId),
|
|
437
|
+
async (res) => {
|
|
438
|
+
let message = "✅ 入场成功";
|
|
439
|
+
if (context.config.autoLockOnLogin) {
|
|
440
|
+
let lockMessage = await handleLockCmd(context);
|
|
441
|
+
message += "\n\n" + lockMessage;
|
|
442
|
+
}
|
|
443
|
+
return message;
|
|
444
|
+
}
|
|
445
|
+
);
|
|
369
446
|
}
|
|
370
447
|
__name(handleLoginCmd, "handleLoginCmd");
|
|
371
448
|
async function handleLogoutCmd(context, user) {
|
|
372
449
|
const { error, userId: targetUserId } = await getTargetUserId(context, user);
|
|
373
450
|
if (error) return error;
|
|
374
451
|
if (!context.config.logoutConfirmation) {
|
|
375
|
-
const res = await logout(
|
|
452
|
+
const res = await context.prism.logout(targetUserId);
|
|
376
453
|
let name2 = await getUserName(context.session, targetUserId);
|
|
377
454
|
let message = user ? `✅ 已为用户 ${name2} 退场` : "✅ 退场成功";
|
|
378
455
|
message += "\n";
|
|
@@ -385,7 +462,7 @@ ${message}`);
|
|
|
385
462
|
const now = Date.now();
|
|
386
463
|
if (pendingLogout && now - pendingLogout < 60 * 1e3) {
|
|
387
464
|
kv.delete(targetUserId);
|
|
388
|
-
const res = await logout(
|
|
465
|
+
const res = await context.prism.logout(targetUserId);
|
|
389
466
|
const messagePrefix = user ? `✅ 已为用户 ${await getUserName(context.session, targetUserId)} 退场` : "✅ 退场成功";
|
|
390
467
|
return [
|
|
391
468
|
messagePrefix,
|
|
@@ -394,7 +471,7 @@ ${message}`);
|
|
|
394
471
|
`消费: ${res.session.finalCost} ${context.config.currency}`
|
|
395
472
|
].join("\n");
|
|
396
473
|
} else {
|
|
397
|
-
const billingRes = await billing(
|
|
474
|
+
const billingRes = await context.prism.billing(targetUserId);
|
|
398
475
|
const billingMessage = formatBilling(billingRes, context.config.currency);
|
|
399
476
|
kv.set(targetUserId, now);
|
|
400
477
|
if (user) {
|
|
@@ -413,9 +490,9 @@ ${billingMessage}
|
|
|
413
490
|
}
|
|
414
491
|
__name(handleLogoutCmd, "handleLogoutCmd");
|
|
415
492
|
async function handleListCmd(context, user) {
|
|
416
|
-
const users = await list(
|
|
493
|
+
const users = await context.prism.list();
|
|
417
494
|
if (!users || users.length === 0) {
|
|
418
|
-
return "窝里目前没有玩家呢";
|
|
495
|
+
return "🫥 窝里目前没有玩家呢";
|
|
419
496
|
}
|
|
420
497
|
const tasks = users.map((user2) => {
|
|
421
498
|
const entryDate = formatDateTime(user2.sessions[0].createdAt);
|
|
@@ -428,7 +505,7 @@ async function handleListCmd(context, user) {
|
|
|
428
505
|
return `玩家: ${u}
|
|
429
506
|
入场时间: ${tasks[idx].entryDate}`;
|
|
430
507
|
});
|
|
431
|
-
return
|
|
508
|
+
return `👥 窝里目前共有 ${users.length} 人
|
|
432
509
|
|
|
433
510
|
${userReports.join("\n\n")}`;
|
|
434
511
|
}
|
|
@@ -436,10 +513,10 @@ __name(handleListCmd, "handleListCmd");
|
|
|
436
513
|
async function handleWalletCmd(context, user) {
|
|
437
514
|
const { error, userId } = await getTargetUserId(context, user);
|
|
438
515
|
if (error) return error;
|
|
439
|
-
const res = await wallet(
|
|
516
|
+
const res = await context.prism.wallet(userId);
|
|
440
517
|
const message = [];
|
|
441
518
|
const targetUserId = user ? userId : void 0;
|
|
442
|
-
message.push(targetUserId ?
|
|
519
|
+
message.push(targetUserId ? `💰 --- 用户 ${await getUserName(context.session, targetUserId)} 的钱包余额 ---` : "💰 --- 钱包余额 ---");
|
|
443
520
|
message.push(
|
|
444
521
|
`可用: ${res.total.available} ${context.config.currency} (共 ${res.total.all})`,
|
|
445
522
|
` - 付费: ${res.paid.available}`,
|
|
@@ -478,10 +555,38 @@ async function handleWalletCmd(context, user) {
|
|
|
478
555
|
return message.join("\n");
|
|
479
556
|
}
|
|
480
557
|
__name(handleWalletCmd, "handleWalletCmd");
|
|
558
|
+
async function handleHistoriesCmd(context, arg1, arg2) {
|
|
559
|
+
let limit = 10;
|
|
560
|
+
let userArg;
|
|
561
|
+
if (arg1 && /^\d+$/.test(arg1)) {
|
|
562
|
+
limit = parseInt(arg1);
|
|
563
|
+
} else {
|
|
564
|
+
userArg = arg1;
|
|
565
|
+
if (arg2 && /^\d+$/.test(String(arg2))) {
|
|
566
|
+
limit = parseInt(String(arg2));
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
const { error, userId } = await getTargetUserId(context, userArg);
|
|
570
|
+
if (error) return error;
|
|
571
|
+
console.log(userId);
|
|
572
|
+
const res = await context.prism.history(userId, limit);
|
|
573
|
+
if (!res || !res.sessions || res.sessions.length === 0) {
|
|
574
|
+
return "暂无历史记录";
|
|
575
|
+
}
|
|
576
|
+
const message = [`📜 最近 ${res.sessions.length} 条记录:`];
|
|
577
|
+
res.sessions.forEach((s) => {
|
|
578
|
+
const start = formatDateTime(s.createdAt);
|
|
579
|
+
const end = s.closedAt ? formatDateTime(s.closedAt) : "进行中";
|
|
580
|
+
const cost = s.finalCost !== null ? `${s.finalCost} ${context.config.currency}` : "未结算";
|
|
581
|
+
message.push(`- [${s.id}] ${start} -> ${end} (${cost})`);
|
|
582
|
+
});
|
|
583
|
+
return message.join("\n");
|
|
584
|
+
}
|
|
585
|
+
__name(handleHistoriesCmd, "handleHistoriesCmd");
|
|
481
586
|
async function handleBillingCmd(context, user) {
|
|
482
587
|
const { error, userId } = await getTargetUserId(context, user);
|
|
483
588
|
if (error) return error;
|
|
484
|
-
const res = await billing(
|
|
589
|
+
const res = await context.prism.billing(userId);
|
|
485
590
|
const billingMessage = formatBilling(res, context.config.currency);
|
|
486
591
|
if (user) {
|
|
487
592
|
return `用户 ${await getUserName(context.session, userId)} 的账单:
|
|
@@ -492,9 +597,9 @@ ${billingMessage}`;
|
|
|
492
597
|
}
|
|
493
598
|
__name(handleBillingCmd, "handleBillingCmd");
|
|
494
599
|
async function handleLockCmd(context) {
|
|
495
|
-
const res = await getLock(context
|
|
600
|
+
const res = await context.prism.getLock(context.session.userId);
|
|
496
601
|
return [
|
|
497
|
-
"获取密码成功",
|
|
602
|
+
"🔑 获取密码成功",
|
|
498
603
|
`你的门锁密码是: ${res.password}`,
|
|
499
604
|
`输入完成后按 # 结束`,
|
|
500
605
|
"注意! 门锁密码有效期为三分钟"
|
|
@@ -504,11 +609,11 @@ __name(handleLockCmd, "handleLockCmd");
|
|
|
504
609
|
async function handleItemsCmd(context, user) {
|
|
505
610
|
const { error, userId } = await getTargetUserId(context, user);
|
|
506
611
|
if (error) return error;
|
|
507
|
-
const userAssets = await assets(
|
|
612
|
+
const userAssets = await context.prism.assets(userId);
|
|
508
613
|
if (!userAssets || userAssets.length === 0) {
|
|
509
614
|
return user ? `用户 ${await getUserName(context.session, userId)} 没有任何物品。` : "您当前没有任何物品。";
|
|
510
615
|
}
|
|
511
|
-
const header = user ?
|
|
616
|
+
const header = user ? `🎒 --- 用户 ${await getUserName(context.session, userId)} 拥有的物品 ---` : "🎒 --- 您拥有的物品 ---";
|
|
512
617
|
const itemsList = userAssets.map((asset) => {
|
|
513
618
|
let line = `- ${asset.asset.name} (x${asset.count})`;
|
|
514
619
|
if (asset.expireAt) {
|
|
@@ -524,26 +629,32 @@ async function handleItemsCmd(context, user) {
|
|
|
524
629
|
}
|
|
525
630
|
__name(handleItemsCmd, "handleItemsCmd");
|
|
526
631
|
async function handleMachineOn(context, alias) {
|
|
527
|
-
if (!alias)
|
|
632
|
+
if (!alias) {
|
|
633
|
+
await context.session.execute("help on");
|
|
634
|
+
return "";
|
|
635
|
+
}
|
|
528
636
|
let isAdmin = await context.ctx.permissions.check(context.config.admin, context.session);
|
|
529
|
-
const res = await machinePowerOn(
|
|
530
|
-
return
|
|
637
|
+
const res = await context.prism.machinePowerOn(alias, context.session.userId, !isAdmin);
|
|
638
|
+
return `✅ ${res.machine} 启动成功`;
|
|
531
639
|
}
|
|
532
640
|
__name(handleMachineOn, "handleMachineOn");
|
|
533
641
|
async function handleMachineOff(context, alias) {
|
|
534
|
-
if (!alias)
|
|
642
|
+
if (!alias) {
|
|
643
|
+
await context.session.execute("help off");
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
535
646
|
let isAdmin = await context.ctx.permissions.check(context.config.admin, context.session);
|
|
536
|
-
const res = await machinePowerOff(
|
|
537
|
-
if (alias === "all") return
|
|
538
|
-
return
|
|
647
|
+
const res = await context.prism.machinePowerOff(alias, context.session.userId, !isAdmin);
|
|
648
|
+
if (alias === "all") return `🛑 全部机器关闭成功`;
|
|
649
|
+
return `🛑 ${res.machine} 关闭成功`;
|
|
539
650
|
}
|
|
540
651
|
__name(handleMachineOff, "handleMachineOff");
|
|
541
652
|
async function handleMachineShow(context, alias) {
|
|
542
653
|
if (alias) {
|
|
543
|
-
const res = await getMachinePower(
|
|
654
|
+
const res = await context.prism.getMachinePower(alias);
|
|
544
655
|
return `${res.machine}: ${res.state.state}`;
|
|
545
656
|
} else {
|
|
546
|
-
const res = await getAllMachinePower(
|
|
657
|
+
const res = await context.prism.getAllMachinePower();
|
|
547
658
|
return res.map(
|
|
548
659
|
(e) => {
|
|
549
660
|
return `${e.machine}: ${e.state.state}`;
|
|
@@ -553,14 +664,16 @@ async function handleMachineShow(context, alias) {
|
|
|
553
664
|
}
|
|
554
665
|
__name(handleMachineShow, "handleMachineShow");
|
|
555
666
|
async function handleWalletAdd(context, user, amount) {
|
|
667
|
+
if (!user || !amount) {
|
|
668
|
+
await context.session.execute("help add");
|
|
669
|
+
return "";
|
|
670
|
+
}
|
|
556
671
|
const { error, userId } = await getTargetUserId(context, user);
|
|
557
672
|
if (error) return error;
|
|
558
|
-
if (!amount) return "请输入数量";
|
|
559
673
|
return executeWithAutoRegister(
|
|
560
674
|
context,
|
|
561
675
|
user,
|
|
562
|
-
userId,
|
|
563
|
-
() => walletAdd(context, parseInt(amount), userId),
|
|
676
|
+
() => context.prism.walletAdd(parseFloat(amount), userId),
|
|
564
677
|
async (res) => {
|
|
565
678
|
return [
|
|
566
679
|
`为用户 ${await getUserName(context.session, userId)} 增加${context.config.currency}成功`,
|
|
@@ -572,14 +685,16 @@ async function handleWalletAdd(context, user, amount) {
|
|
|
572
685
|
}
|
|
573
686
|
__name(handleWalletAdd, "handleWalletAdd");
|
|
574
687
|
async function handleWalletDeduct(context, user, amount) {
|
|
688
|
+
if (!user || !amount) {
|
|
689
|
+
await context.session.execute("help del");
|
|
690
|
+
return "";
|
|
691
|
+
}
|
|
575
692
|
const { error, userId } = await getTargetUserId(context, user);
|
|
576
693
|
if (error) return error;
|
|
577
|
-
if (!amount) return "请输入数量";
|
|
578
694
|
return executeWithAutoRegister(
|
|
579
695
|
context,
|
|
580
696
|
user,
|
|
581
|
-
userId,
|
|
582
|
-
() => walletDel(context, parseInt(amount), userId),
|
|
697
|
+
() => context.prism.walletDel(parseInt(amount), userId),
|
|
583
698
|
(res) => {
|
|
584
699
|
return [
|
|
585
700
|
`为用户 ${userId} 扣除${context.config.currency}成功`,
|
|
@@ -591,27 +706,31 @@ async function handleWalletDeduct(context, user, amount) {
|
|
|
591
706
|
}
|
|
592
707
|
__name(handleWalletDeduct, "handleWalletDeduct");
|
|
593
708
|
async function handleCostOverwrite(context, user, amount) {
|
|
709
|
+
if (!user || !amount) {
|
|
710
|
+
await context.session.execute("help overwrite");
|
|
711
|
+
return "";
|
|
712
|
+
}
|
|
594
713
|
const { error, userId } = await getTargetUserId(context, user);
|
|
595
714
|
if (error) return error;
|
|
596
|
-
if (!amount) return "请输入数量";
|
|
597
715
|
return executeWithAutoRegister(
|
|
598
716
|
context,
|
|
599
717
|
user,
|
|
600
|
-
userId,
|
|
601
|
-
() => costOverwrite(context, amount, userId),
|
|
718
|
+
() => context.prism.costOverwrite(amount, userId),
|
|
602
719
|
() => `为用户 ${userId} 调价成功`
|
|
603
720
|
);
|
|
604
721
|
}
|
|
605
722
|
__name(handleCostOverwrite, "handleCostOverwrite");
|
|
606
723
|
async function handleRedeem(context, code) {
|
|
724
|
+
if (!code) {
|
|
725
|
+
await context.session.execute("help redeem");
|
|
726
|
+
return "";
|
|
727
|
+
}
|
|
607
728
|
const { error, userId } = await getTargetUserId(context, null);
|
|
608
729
|
if (error) return error;
|
|
609
|
-
if (!code) return "请输入兑换码";
|
|
610
730
|
return executeWithAutoRegister(
|
|
611
731
|
context,
|
|
612
732
|
void 0,
|
|
613
|
-
userId,
|
|
614
|
-
() => redeem(context, code, userId),
|
|
733
|
+
() => context.prism.redeem(code, userId),
|
|
615
734
|
(res) => {
|
|
616
735
|
const items = res;
|
|
617
736
|
if (!items || items.length === 0) {
|
|
@@ -632,19 +751,290 @@ async function handleRedeem(context, code) {
|
|
|
632
751
|
}
|
|
633
752
|
__name(handleRedeem, "handleRedeem");
|
|
634
753
|
async function handleCoin(context, alias) {
|
|
635
|
-
if (!alias)
|
|
754
|
+
if (!alias) {
|
|
755
|
+
await context.session.execute("help coin");
|
|
756
|
+
return "";
|
|
757
|
+
}
|
|
636
758
|
let isAdmin = await context.ctx.permissions.check(context.config.admin, context.session);
|
|
637
|
-
const res = await insertCoin(
|
|
638
|
-
return
|
|
759
|
+
const res = await context.prism.insertCoin(alias, context.session.userId, isAdmin);
|
|
760
|
+
return `🪙 已为 ${res.machineName} 投入 ${res.count} 个币`;
|
|
639
761
|
}
|
|
640
762
|
__name(handleCoin, "handleCoin");
|
|
763
|
+
async function handleAdminListAssets(context) {
|
|
764
|
+
await checkAdmin(context);
|
|
765
|
+
const res = await context.prism.adminListAssets();
|
|
766
|
+
if (!res || res.length === 0) return "暂无资产";
|
|
767
|
+
return res.map((a) => {
|
|
768
|
+
const status = a.valid ? "[有效]" : "[无效]";
|
|
769
|
+
const typeInfo = `${a.type} (ID:${a.assetId})`;
|
|
770
|
+
let timeInfo = "";
|
|
771
|
+
if (a.activeAt || a.expireAt) {
|
|
772
|
+
const start = a.activeAt ? formatDateTime(a.activeAt) : "不限";
|
|
773
|
+
const end = a.expireAt ? formatDateTime(a.expireAt) : "不限";
|
|
774
|
+
timeInfo = `
|
|
775
|
+
有效期: ${start} -> ${end}`;
|
|
776
|
+
}
|
|
777
|
+
const desc = a.description ? `
|
|
778
|
+
描述: ${a.description}` : "";
|
|
779
|
+
return `${status} [${a.id}] ${a.name}
|
|
780
|
+
类型: ${typeInfo}${timeInfo}${desc}`;
|
|
781
|
+
}).join("\n\n");
|
|
782
|
+
}
|
|
783
|
+
__name(handleAdminListAssets, "handleAdminListAssets");
|
|
784
|
+
async function handleAdminAddAsset(context, type, assetId, name2, desc) {
|
|
785
|
+
await checkAdmin(context);
|
|
786
|
+
const opts = context.options || {};
|
|
787
|
+
if (!type || assetId === void 0 || !name2) {
|
|
788
|
+
await context.session.execute("help admin.asset.add");
|
|
789
|
+
return "";
|
|
790
|
+
}
|
|
791
|
+
await context.prism.adminCreateAsset({
|
|
792
|
+
type,
|
|
793
|
+
assetId,
|
|
794
|
+
name: name2,
|
|
795
|
+
description: desc,
|
|
796
|
+
valid: opts.valid,
|
|
797
|
+
activeAt: opts.active,
|
|
798
|
+
expireAt: opts.expire
|
|
799
|
+
});
|
|
800
|
+
return `资产 ${name2} [${type}-${assetId}] 创建成功`;
|
|
801
|
+
}
|
|
802
|
+
__name(handleAdminAddAsset, "handleAdminAddAsset");
|
|
803
|
+
async function handleAdminDelAsset(context, id) {
|
|
804
|
+
await checkAdmin(context);
|
|
805
|
+
if (!id) {
|
|
806
|
+
await context.session.execute("help admin.asset.del");
|
|
807
|
+
return "";
|
|
808
|
+
}
|
|
809
|
+
await context.prism.adminDeleteAsset(parseInt(id));
|
|
810
|
+
return `资产 ${id} 删除成功`;
|
|
811
|
+
}
|
|
812
|
+
__name(handleAdminDelAsset, "handleAdminDelAsset");
|
|
813
|
+
async function handleAdminDelCoupon(context, id) {
|
|
814
|
+
await checkAdmin(context);
|
|
815
|
+
if (!id) {
|
|
816
|
+
await context.session.execute("help admin.coupon.del");
|
|
817
|
+
return "";
|
|
818
|
+
}
|
|
819
|
+
await context.prism.adminDeleteAsset(parseInt(id));
|
|
820
|
+
return `优惠券 ${id} 删除成功`;
|
|
821
|
+
}
|
|
822
|
+
__name(handleAdminDelCoupon, "handleAdminDelCoupon");
|
|
823
|
+
async function handleAdminListCoupons(context) {
|
|
824
|
+
await checkAdmin(context);
|
|
825
|
+
const res = await context.prism.adminListCoupons();
|
|
826
|
+
if (!res || res.length === 0) return "暂无优惠券";
|
|
827
|
+
return res.map((c) => {
|
|
828
|
+
const ef = c.billingEffect;
|
|
829
|
+
if (!ef) return `[${c.id}] ${c.name} (无特效)`;
|
|
830
|
+
const typeStr = ef.type === "RATE" ? `折扣 ${(ef.value * 10).toFixed(1)}折` : `减免 ${ef.value}元`;
|
|
831
|
+
const p = `P${ef.priority}`;
|
|
832
|
+
const flags = [];
|
|
833
|
+
if (ef.consume) flags.push("一次性");
|
|
834
|
+
if (ef.stackable) flags.push("可叠加");
|
|
835
|
+
const limits = [];
|
|
836
|
+
if (ef.maxDiscountAmount) limits.push(`封顶${ef.maxDiscountAmount}元`);
|
|
837
|
+
if (ef.condition?.minCost) limits.push(`满${ef.condition.minCost}元`);
|
|
838
|
+
if (ef.condition?.matchRuleIds?.length) limits.push(`限规则[${ef.condition.matchRuleIds.join(",")}]`);
|
|
839
|
+
return `🎫 [${c.id}] ${c.name}
|
|
840
|
+
效果: ${typeStr}
|
|
841
|
+
属性: ${p} | ${flags.join(", ") || "无特殊属性"}
|
|
842
|
+
限制: ${limits.join(", ") || "无限制"}`;
|
|
843
|
+
}).join("\n\n");
|
|
844
|
+
}
|
|
845
|
+
__name(handleAdminListCoupons, "handleAdminListCoupons");
|
|
846
|
+
async function handleAdminAddCoupon(context, name2, assetId, type, value) {
|
|
847
|
+
await checkAdmin(context);
|
|
848
|
+
const opts = context.options || {};
|
|
849
|
+
if (!name2 || assetId === void 0 || !type || value === void 0) {
|
|
850
|
+
await context.session.execute("help admin.coupon.add");
|
|
851
|
+
return "";
|
|
852
|
+
}
|
|
853
|
+
let t = type.toUpperCase();
|
|
854
|
+
if (t === "FIXED") t = "FIXED_OFF";
|
|
855
|
+
if (t !== "RATE" && t !== "FIXED_OFF") {
|
|
856
|
+
return "类型错误: type 必须是 RATE (折扣) 或 FIXED (减免)";
|
|
857
|
+
}
|
|
858
|
+
await context.prism.adminCreateCoupon({
|
|
859
|
+
name: name2,
|
|
860
|
+
assetId,
|
|
861
|
+
billingEffect: {
|
|
862
|
+
type: t,
|
|
863
|
+
value,
|
|
864
|
+
priority: opts.priority || 0,
|
|
865
|
+
consume: !!opts.consume,
|
|
866
|
+
stackable: !!opts.stackable,
|
|
867
|
+
maxDiscountAmount: opts.max,
|
|
868
|
+
condition: {
|
|
869
|
+
minCost: opts.min,
|
|
870
|
+
matchRuleIds: opts.rules ? String(opts.rules).split(",").map(Number) : void 0
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
return `优惠券 ${name2} 创建成功`;
|
|
875
|
+
}
|
|
876
|
+
__name(handleAdminAddCoupon, "handleAdminAddCoupon");
|
|
877
|
+
async function handleAdminListGifts(context) {
|
|
878
|
+
await checkAdmin(context);
|
|
879
|
+
const res = await context.prism.adminListGifts();
|
|
880
|
+
if (!res || res.length === 0) return "暂无礼包";
|
|
881
|
+
return res.map((g) => {
|
|
882
|
+
const limit = g.oncePerUser ? "🔴 每人限领一次" : "🟢 可重复领取";
|
|
883
|
+
const items = (g.body || []).map((i) => {
|
|
884
|
+
let detail = `${i.name} x${i.count}`;
|
|
885
|
+
if (i.durationMs) {
|
|
886
|
+
const days = (i.durationMs / (1e3 * 60 * 60 * 24)).toFixed(1);
|
|
887
|
+
detail += ` (${days}天)`;
|
|
888
|
+
}
|
|
889
|
+
if (i.mergeStrategy === "EXTEND_TIME") detail += " [续期]";
|
|
890
|
+
if (i.mergeStrategy === "REPLACE") detail += " [覆盖]";
|
|
891
|
+
return detail;
|
|
892
|
+
}).join("\n - ");
|
|
893
|
+
return `[${g.id}] ${g.name}
|
|
894
|
+
限制: ${limit}
|
|
895
|
+
内容:
|
|
896
|
+
- ${items}`;
|
|
897
|
+
}).join("\n\n");
|
|
898
|
+
}
|
|
899
|
+
__name(handleAdminListGifts, "handleAdminListGifts");
|
|
900
|
+
async function handleAdminAddGift(context, name2, content) {
|
|
901
|
+
await checkAdmin(context);
|
|
902
|
+
if (!name2 || !content) {
|
|
903
|
+
await context.session.execute("help admin.gift.add");
|
|
904
|
+
return "";
|
|
905
|
+
}
|
|
906
|
+
try {
|
|
907
|
+
const allAssets = await context.prism.adminListAssets();
|
|
908
|
+
const assetMap = new Map(allAssets.map((a) => [a.assetId, a]));
|
|
909
|
+
const items = content.split(/[,,]/).map((item) => {
|
|
910
|
+
const parts = item.trim().split(/[::]/);
|
|
911
|
+
if (parts.length < 2) throw new Error(`项 "${item}" 格式错误,应为 id:count`);
|
|
912
|
+
const [idStr, countStr] = parts;
|
|
913
|
+
const assetId = parseInt(idStr);
|
|
914
|
+
const count = parseInt(countStr);
|
|
915
|
+
if (isNaN(assetId)) throw new Error(`资产ID "${idStr}" 无效`);
|
|
916
|
+
if (isNaN(count) || count <= 0) throw new Error(`数量 "${countStr}" 无效`);
|
|
917
|
+
const asset = assetMap.get(assetId);
|
|
918
|
+
if (!asset) throw new Error(`Asset ID ${assetId} not found`);
|
|
919
|
+
return { assetId, assetType: asset.type, name: asset.name, mergeStrategy: "STACK", oncePerUser: false, count };
|
|
920
|
+
});
|
|
921
|
+
await context.prism.adminCreateGift({
|
|
922
|
+
name: name2,
|
|
923
|
+
oncePerUser: false,
|
|
924
|
+
body: items
|
|
925
|
+
});
|
|
926
|
+
return `礼包 ${name2} 创建成功`;
|
|
927
|
+
} catch (e) {
|
|
928
|
+
return `创建失败: ${e.message}`;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
__name(handleAdminAddGift, "handleAdminAddGift");
|
|
932
|
+
async function handleAdminDelGift(context, id) {
|
|
933
|
+
await checkAdmin(context);
|
|
934
|
+
if (!id) {
|
|
935
|
+
await context.session.execute("help admin.gift.del");
|
|
936
|
+
return "";
|
|
937
|
+
}
|
|
938
|
+
await context.prism.adminDeleteGift(parseInt(id));
|
|
939
|
+
return `礼包 ${id} 删除成功`;
|
|
940
|
+
}
|
|
941
|
+
__name(handleAdminDelGift, "handleAdminDelGift");
|
|
942
|
+
async function handleAdminGiftCodes(context, id, count) {
|
|
943
|
+
await checkAdmin(context);
|
|
944
|
+
if (!id || !count) {
|
|
945
|
+
await context.session.execute("help admin.gift.codes");
|
|
946
|
+
return "";
|
|
947
|
+
}
|
|
948
|
+
const res = await context.prism.adminGenerateGiftCodes(parseInt(id), parseInt(count));
|
|
949
|
+
return `成功生成 ${res.count} 个兑换码:
|
|
950
|
+
${res.codes.join("\n")}`;
|
|
951
|
+
}
|
|
952
|
+
__name(handleAdminGiftCodes, "handleAdminGiftCodes");
|
|
953
|
+
async function handleAdminListRules(context) {
|
|
954
|
+
await checkAdmin(context);
|
|
955
|
+
const res = await context.prism.adminListRules();
|
|
956
|
+
if (!res || res.length === 0) return "暂无规则";
|
|
957
|
+
return res.map((r) => {
|
|
958
|
+
const tr = r.timeRange;
|
|
959
|
+
const pr = r.pricing;
|
|
960
|
+
const md = r.matchDate || {};
|
|
961
|
+
let dateStr = "每天";
|
|
962
|
+
if (md.specificDates?.length) dateStr = `指定日期(${md.specificDates.length}天)`;
|
|
963
|
+
if (md.weekdays?.length) {
|
|
964
|
+
const days = md.weekdays.map((d) => ["日", "一", "二", "三", "四", "五", "六"][d]).join("");
|
|
965
|
+
dateStr = `每周[${days}]`;
|
|
966
|
+
}
|
|
967
|
+
const status = r.available ? "[✅]" : "[❌]";
|
|
968
|
+
return `${status} [${r.id}] ${r.name} (P${r.priority})
|
|
969
|
+
时间: ${dateStr} ${tr.start}-${tr.end}
|
|
970
|
+
价格: ${pr.unitPrice}元 / ${pr.unitMinutes}分钟
|
|
971
|
+
封顶: ${pr.priceCap}元 (宽限${pr.roundGraceMinutes}分)`;
|
|
972
|
+
}).join("\n\n");
|
|
973
|
+
}
|
|
974
|
+
__name(handleAdminListRules, "handleAdminListRules");
|
|
975
|
+
async function handleAdminDelRule(context, id) {
|
|
976
|
+
await checkAdmin(context);
|
|
977
|
+
if (!id) {
|
|
978
|
+
await context.session.execute("help admin.rule.del");
|
|
979
|
+
return "";
|
|
980
|
+
}
|
|
981
|
+
await context.prism.adminDeleteRule(parseInt(id));
|
|
982
|
+
return `规则 ${id} 删除成功`;
|
|
983
|
+
}
|
|
984
|
+
__name(handleAdminDelRule, "handleAdminDelRule");
|
|
985
|
+
async function handleAdminRuleStatus(context, id, state) {
|
|
986
|
+
await checkAdmin(context);
|
|
987
|
+
if (!id || !state) {
|
|
988
|
+
await context.session.execute("help admin.rule.set");
|
|
989
|
+
return "";
|
|
990
|
+
}
|
|
991
|
+
const available = ["on", "true", "enable", "1", "yes"].includes(state.toLowerCase());
|
|
992
|
+
await context.prism.adminUpdateRuleStatus(parseInt(id), available);
|
|
993
|
+
return `规则 ${id} 已${available ? "启用" : "禁用"}`;
|
|
994
|
+
}
|
|
995
|
+
__name(handleAdminRuleStatus, "handleAdminRuleStatus");
|
|
996
|
+
async function handleAdminUserAssetAdd(context, user, assetId, count) {
|
|
997
|
+
await checkAdmin(context);
|
|
998
|
+
if (!user || !assetId) {
|
|
999
|
+
await context.session.execute("help admin.user.asset.add");
|
|
1000
|
+
return "";
|
|
1001
|
+
}
|
|
1002
|
+
const { error, userId } = await getTargetUserId(context, user);
|
|
1003
|
+
if (error) return error;
|
|
1004
|
+
let res = await context.prism.upsertUserAssets(userId, [{
|
|
1005
|
+
id: assetId,
|
|
1006
|
+
count
|
|
1007
|
+
}]);
|
|
1008
|
+
return `已为用户 ${userId} 添加资产 ${JSON.stringify(res)}`;
|
|
1009
|
+
}
|
|
1010
|
+
__name(handleAdminUserAssetAdd, "handleAdminUserAssetAdd");
|
|
1011
|
+
async function handleAdminUserAssetDel(context, user, userAssetId, count) {
|
|
1012
|
+
await checkAdmin(context);
|
|
1013
|
+
if (!user || !userAssetId) {
|
|
1014
|
+
await context.session.execute("help admin.user.asset.del");
|
|
1015
|
+
return "";
|
|
1016
|
+
}
|
|
1017
|
+
const { error, userId } = await getTargetUserId(context, user);
|
|
1018
|
+
if (error) return error;
|
|
1019
|
+
if (count) {
|
|
1020
|
+
await context.prism.updateUserAsset(userId, userAssetId, -count);
|
|
1021
|
+
return `已为用户 ${userId} 扣除资产(ID:${userAssetId}) 数量 ${count}`;
|
|
1022
|
+
} else {
|
|
1023
|
+
await context.prism.deleteUserAsset(userId, userAssetId);
|
|
1024
|
+
return `已为用户 ${userId} 删除资产(ID:${userAssetId})`;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
__name(handleAdminUserAssetDel, "handleAdminUserAssetDel");
|
|
641
1028
|
function apply(ctx, config) {
|
|
1029
|
+
const prism = new PrismService(ctx, config);
|
|
642
1030
|
const createAction = /* @__PURE__ */ __name((handler) => {
|
|
643
1031
|
const actionFn = /* @__PURE__ */ __name((argv, ...args) => {
|
|
644
1032
|
const context = {
|
|
645
1033
|
ctx,
|
|
646
1034
|
config,
|
|
647
|
-
session: argv.session
|
|
1035
|
+
session: argv.session,
|
|
1036
|
+
options: argv.options,
|
|
1037
|
+
prism
|
|
648
1038
|
};
|
|
649
1039
|
return handler(context, ...args);
|
|
650
1040
|
}, "actionFn");
|
|
@@ -655,6 +1045,7 @@ function apply(ctx, config) {
|
|
|
655
1045
|
ctx.command("logout [user:user]").action(createAction(handleLogoutCmd));
|
|
656
1046
|
ctx.command("list").action(createAction(handleListCmd));
|
|
657
1047
|
ctx.command("wallet [user:user]").action(createAction(handleWalletCmd));
|
|
1048
|
+
ctx.command("history [arg1] [arg2]").action(createAction(handleHistoriesCmd));
|
|
658
1049
|
ctx.command("billing [user:user]").action(createAction(handleBillingCmd));
|
|
659
1050
|
ctx.command("lock").action(createAction(handleLockCmd));
|
|
660
1051
|
ctx.command("items [user:user]").action(createAction(handleItemsCmd));
|
|
@@ -666,11 +1057,27 @@ function apply(ctx, config) {
|
|
|
666
1057
|
ctx.command("add <user:user> <amount>").action(createAction(handleWalletAdd));
|
|
667
1058
|
ctx.command("del <user:user> <amount>").action(createAction(handleWalletDeduct));
|
|
668
1059
|
ctx.command("overwrite <user:user> <amount>").action(createAction(handleCostOverwrite));
|
|
1060
|
+
ctx.command("admin.asset.list", "列出资产").action(createAction(handleAdminListAssets));
|
|
1061
|
+
ctx.command("admin.asset.add <type> <id:number> <name> [desc]", "添加资产").option("valid", "-v [val:boolean]", { fallback: true }).option("active", "--active <date:string>").option("expire", "--expire <date:string>").action(createAction(handleAdminAddAsset));
|
|
1062
|
+
ctx.command("admin.asset.del <id>", "删除资产").action(createAction(handleAdminDelAsset));
|
|
1063
|
+
ctx.command("admin.coupon.list", "列出优惠券").action(createAction(handleAdminListCoupons));
|
|
1064
|
+
ctx.command("admin.user.asset.add <user:user> <assetId:number> [count:number]", "发放资产").action(createAction(handleAdminUserAssetAdd));
|
|
1065
|
+
ctx.command("admin.user.asset.del <user:user> <userAssetId:number> [count:number]", "删除资产(指定数量则扣除)").action(createAction(handleAdminUserAssetDel));
|
|
1066
|
+
ctx.command("admin.coupon.add <name> <assetId:number> <type> <value:number>", "添加优惠券").option("priority", "-p <val:number>", { fallback: 0 }).option("consume", "-c", { fallback: false }).option("stackable", "-s", { fallback: false }).option("min", "--min <val:number>").option("max", "--max <val:number>").option("rules", "--rules <ids:string>").action(createAction(handleAdminAddCoupon));
|
|
1067
|
+
ctx.command("admin.coupon.del <id>", "删除优惠券").action(createAction(handleAdminDelCoupon));
|
|
1068
|
+
ctx.command("admin.gift.list", "列出礼包").action(createAction(handleAdminListGifts));
|
|
1069
|
+
ctx.command("admin.gift.add <name> <content:text>", "添加礼包 (格式: id:count,id:count)").action(createAction(handleAdminAddGift));
|
|
1070
|
+
ctx.command("admin.gift.del <id>", "删除礼包").action(createAction(handleAdminDelGift));
|
|
1071
|
+
ctx.command("admin.gift.codes <id> <count>", "生成礼包码").action(createAction(handleAdminGiftCodes));
|
|
1072
|
+
ctx.command("admin.rule.list", "列出规则").action(createAction(handleAdminListRules));
|
|
1073
|
+
ctx.command("admin.rule.del <id>", "删除规则").action(createAction(handleAdminDelRule));
|
|
1074
|
+
ctx.command("admin.rule.set <id> <state>", "设置规则状态").action(createAction(handleAdminRuleStatus));
|
|
1075
|
+
ctx.command("echo <message>").action((_, message) => message);
|
|
669
1076
|
ctx.setInterval(
|
|
670
1077
|
async () => {
|
|
671
|
-
let
|
|
672
|
-
if (
|
|
673
|
-
let machines = await getAllMachinePower(
|
|
1078
|
+
let list = await prism.list();
|
|
1079
|
+
if (list.length < 1) {
|
|
1080
|
+
let machines = await prism.getAllMachinePower();
|
|
674
1081
|
let turnOff = false;
|
|
675
1082
|
machines.forEach((m) => {
|
|
676
1083
|
if (m.state.state !== "off") {
|
|
@@ -678,7 +1085,7 @@ function apply(ctx, config) {
|
|
|
678
1085
|
}
|
|
679
1086
|
});
|
|
680
1087
|
if (turnOff) {
|
|
681
|
-
let res = await machinePowerOff(
|
|
1088
|
+
let res = await prism.machinePowerOff("all", "system", false);
|
|
682
1089
|
ctx.broadcast(config.broadcasts, "窝里目前有 0 人,自动关闭所有机器");
|
|
683
1090
|
}
|
|
684
1091
|
return;
|
package/lib/model.d.ts
CHANGED
|
@@ -88,6 +88,19 @@ export interface UserAsset {
|
|
|
88
88
|
comment: string;
|
|
89
89
|
count: number;
|
|
90
90
|
}
|
|
91
|
+
export type DiscountType = 'RATE' | 'FIXED_OFF';
|
|
92
|
+
export interface BillingEffectConfig {
|
|
93
|
+
type: DiscountType;
|
|
94
|
+
value: number;
|
|
95
|
+
priority: number;
|
|
96
|
+
consume: boolean;
|
|
97
|
+
stackable: boolean;
|
|
98
|
+
maxDiscountAmount?: number;
|
|
99
|
+
condition?: {
|
|
100
|
+
matchRuleIds?: number[];
|
|
101
|
+
minCost?: number;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
91
104
|
export interface Asset {
|
|
92
105
|
type: string;
|
|
93
106
|
id: number;
|
|
@@ -97,6 +110,7 @@ export interface Asset {
|
|
|
97
110
|
activeAt: Date | null;
|
|
98
111
|
description: string | null;
|
|
99
112
|
valid: boolean;
|
|
113
|
+
billingEffect?: BillingEffectConfig;
|
|
100
114
|
}
|
|
101
115
|
export type UserAssetWithDef = UserAsset & {
|
|
102
116
|
asset: Asset;
|
package/lib/service.d.ts
CHANGED
|
@@ -1,32 +1,61 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Context } from "koishi";
|
|
2
|
+
import { Config } from "./index";
|
|
2
3
|
import { BillingResponse, ListResponse, UserAsset, Wallet } from "./model";
|
|
3
|
-
export declare
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
4
|
+
export declare class PrismService {
|
|
5
|
+
private ctx;
|
|
6
|
+
private config;
|
|
7
|
+
private apiBase;
|
|
8
|
+
constructor(ctx: Context, config: Config);
|
|
9
|
+
private url;
|
|
10
|
+
register(userId: string): Promise<unknown>;
|
|
11
|
+
login(userId: string): Promise<unknown>;
|
|
12
|
+
history(userId: string, limit: number): Promise<any>;
|
|
13
|
+
logout(userId: string): Promise<BillingResponse>;
|
|
14
|
+
billing(userId: string): Promise<BillingResponse>;
|
|
15
|
+
list(): Promise<ListResponse>;
|
|
16
|
+
wallet(userId: string): Promise<Wallet>;
|
|
17
|
+
assets(userId: string): Promise<UserAsset[]>;
|
|
18
|
+
upsertUserAssets(userId: string, assets: {
|
|
19
|
+
id: number;
|
|
20
|
+
count: number;
|
|
21
|
+
}[]): Promise<any>;
|
|
22
|
+
deleteUserAsset(userId: string, userAssetId: number): Promise<any>;
|
|
23
|
+
updateUserAsset(userId: string, userAssetId: number, amount: number): Promise<any>;
|
|
24
|
+
getLock(userId: string): Promise<{
|
|
25
|
+
password: string;
|
|
26
|
+
id: any;
|
|
27
|
+
}>;
|
|
28
|
+
machinePowerOn(machineName: string, userId: string, needLogin?: boolean): Promise<any>;
|
|
29
|
+
machinePowerOff(machineName: string, userId: string, needLogin?: boolean): Promise<any>;
|
|
30
|
+
getAllMachinePower(): Promise<{
|
|
31
|
+
machine: string;
|
|
32
|
+
state: {
|
|
33
|
+
state: string;
|
|
34
|
+
};
|
|
35
|
+
}[]>;
|
|
36
|
+
getMachinePower(machineName: string): Promise<{
|
|
37
|
+
machine: string;
|
|
38
|
+
state: {
|
|
39
|
+
state: string;
|
|
40
|
+
};
|
|
41
|
+
}>;
|
|
42
|
+
walletAdd(amount: number, userId: string): Promise<any>;
|
|
43
|
+
walletDel(amount: number, userId: string): Promise<any>;
|
|
44
|
+
costOverwrite(amount: string, userId: string): Promise<any>;
|
|
45
|
+
redeem(code: string, userId: string): Promise<any>;
|
|
46
|
+
insertCoin(alias: string, userId: string, force?: boolean): Promise<any>;
|
|
47
|
+
adminListAssets(): Promise<any>;
|
|
48
|
+
adminCreateAsset(data: any): Promise<any>;
|
|
49
|
+
adminDeleteAsset(id: number): Promise<any>;
|
|
50
|
+
adminListCoupons(): Promise<any>;
|
|
51
|
+
adminCreateCoupon(data: any): Promise<any>;
|
|
52
|
+
adminListGifts(): Promise<any>;
|
|
53
|
+
adminCreateGift(data: any): Promise<any>;
|
|
54
|
+
adminDeleteGift(id: number): Promise<any>;
|
|
55
|
+
adminGenerateGiftCodes(id: number, count: number): Promise<any>;
|
|
56
|
+
adminListRules(): Promise<any>;
|
|
57
|
+
adminCreateRule(data: any): Promise<any>;
|
|
58
|
+
adminDeleteRule(id: number): Promise<any>;
|
|
59
|
+
adminUpdateRuleStatus(id: number, available: boolean): Promise<import("koishi").HTTP.Response<any>>;
|
|
60
|
+
adminAddUserAsset(userId: string, id: number, count: number): Promise<any>;
|
|
61
|
+
}
|
package/lib/types.d.ts
CHANGED