koishi-plugin-prism-neo 0.0.24 → 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.d.ts +1 -0
- package/lib/index.js +615 -202
- 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.d.ts
CHANGED
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";
|
|
@@ -187,6 +251,9 @@ var Config = import_koishi.Schema.object({
|
|
|
187
251
|
broadcasts: import_koishi.Schema.array(
|
|
188
252
|
import_koishi.Schema.string()
|
|
189
253
|
),
|
|
254
|
+
pmOnLogout: import_koishi.Schema.array(
|
|
255
|
+
import_koishi.Schema.string()
|
|
256
|
+
),
|
|
190
257
|
currency: import_koishi.Schema.string().default("月饼").description("货币名称"),
|
|
191
258
|
autoLockOnLogin: import_koishi.Schema.boolean().default(true).description("登录时自动获取门锁密码"),
|
|
192
259
|
logoutConfirmation: import_koishi.Schema.boolean().default(true).description("登出时需要二次确认"),
|
|
@@ -194,7 +261,7 @@ var Config = import_koishi.Schema.object({
|
|
|
194
261
|
});
|
|
195
262
|
async function getUserName(session, userId) {
|
|
196
263
|
if (userId) {
|
|
197
|
-
return
|
|
264
|
+
return "dummy";
|
|
198
265
|
} else {
|
|
199
266
|
return "匿名用户";
|
|
200
267
|
}
|
|
@@ -211,15 +278,22 @@ var handleAction = /* @__PURE__ */ __name((action) => {
|
|
|
211
278
|
if (apiMessage) {
|
|
212
279
|
message = apiMessage;
|
|
213
280
|
} else {
|
|
214
|
-
message =
|
|
281
|
+
message = e.message;
|
|
215
282
|
}
|
|
216
283
|
}
|
|
284
|
+
if (!message) return;
|
|
217
285
|
if (argv.session?.messageId) {
|
|
218
286
|
message = (0, import_koishi.h)("quote", { id: argv.session.messageId }) + message;
|
|
219
287
|
}
|
|
220
288
|
return message;
|
|
221
289
|
};
|
|
222
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");
|
|
223
297
|
var formatDateTime = /* @__PURE__ */ __name((dateStr) => {
|
|
224
298
|
if (!dateStr) return "永不过期";
|
|
225
299
|
const date = new Date(dateStr);
|
|
@@ -308,7 +382,7 @@ var formatBilling = /* @__PURE__ */ __name((res, currency) => {
|
|
|
308
382
|
}
|
|
309
383
|
return message.join("\n");
|
|
310
384
|
}, "formatBilling");
|
|
311
|
-
async function executeWithAutoRegister(context, userArg,
|
|
385
|
+
async function executeWithAutoRegister(context, userArg, action, formatter) {
|
|
312
386
|
try {
|
|
313
387
|
const res = await action();
|
|
314
388
|
return await formatter(res);
|
|
@@ -341,7 +415,7 @@ async function getTargetUserId(context, user) {
|
|
|
341
415
|
if (!await context.ctx.permissions.check(context.config.admin, context.session)) {
|
|
342
416
|
return { error: "权限不足" };
|
|
343
417
|
}
|
|
344
|
-
return { userId: user.split(":")[1] };
|
|
418
|
+
return { userId: user.split(":")[1] ?? user };
|
|
345
419
|
}
|
|
346
420
|
return { userId: context.session.userId };
|
|
347
421
|
}
|
|
@@ -349,37 +423,46 @@ __name(getTargetUserId, "getTargetUserId");
|
|
|
349
423
|
async function handleRegisterCmd(context, user) {
|
|
350
424
|
const { error, userId } = await getTargetUserId(context, user);
|
|
351
425
|
if (error) return error;
|
|
352
|
-
await register(
|
|
426
|
+
await context.prism.register(userId);
|
|
353
427
|
return user ? `为用户 ${userId} 注册成功` : "注册成功";
|
|
354
428
|
}
|
|
355
429
|
__name(handleRegisterCmd, "handleRegisterCmd");
|
|
356
430
|
async function handleLoginCmd(context, user) {
|
|
357
431
|
const { error, userId } = await getTargetUserId(context, user);
|
|
358
432
|
if (error) return error;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
+
);
|
|
366
446
|
}
|
|
367
447
|
__name(handleLoginCmd, "handleLoginCmd");
|
|
368
448
|
async function handleLogoutCmd(context, user) {
|
|
369
449
|
const { error, userId: targetUserId } = await getTargetUserId(context, user);
|
|
370
450
|
if (error) return error;
|
|
371
451
|
if (!context.config.logoutConfirmation) {
|
|
372
|
-
const res = await logout(
|
|
373
|
-
let
|
|
452
|
+
const res = await context.prism.logout(targetUserId);
|
|
453
|
+
let name2 = await getUserName(context.session, targetUserId);
|
|
454
|
+
let message = user ? `✅ 已为用户 ${name2} 退场` : "✅ 退场成功";
|
|
374
455
|
message += "\n";
|
|
375
456
|
message += formatBilling(res, context.config.currency);
|
|
457
|
+
await context.session.bot.broadcast(context.config.pmOnLogout, `${name2}
|
|
458
|
+
${message}`);
|
|
376
459
|
return message;
|
|
377
460
|
}
|
|
378
461
|
const pendingLogout = kv.get(targetUserId);
|
|
379
462
|
const now = Date.now();
|
|
380
463
|
if (pendingLogout && now - pendingLogout < 60 * 1e3) {
|
|
381
464
|
kv.delete(targetUserId);
|
|
382
|
-
const res = await logout(
|
|
465
|
+
const res = await context.prism.logout(targetUserId);
|
|
383
466
|
const messagePrefix = user ? `✅ 已为用户 ${await getUserName(context.session, targetUserId)} 退场` : "✅ 退场成功";
|
|
384
467
|
return [
|
|
385
468
|
messagePrefix,
|
|
@@ -388,7 +471,7 @@ async function handleLogoutCmd(context, user) {
|
|
|
388
471
|
`消费: ${res.session.finalCost} ${context.config.currency}`
|
|
389
472
|
].join("\n");
|
|
390
473
|
} else {
|
|
391
|
-
const billingRes = await billing(
|
|
474
|
+
const billingRes = await context.prism.billing(targetUserId);
|
|
392
475
|
const billingMessage = formatBilling(billingRes, context.config.currency);
|
|
393
476
|
kv.set(targetUserId, now);
|
|
394
477
|
if (user) {
|
|
@@ -407,9 +490,9 @@ ${billingMessage}
|
|
|
407
490
|
}
|
|
408
491
|
__name(handleLogoutCmd, "handleLogoutCmd");
|
|
409
492
|
async function handleListCmd(context, user) {
|
|
410
|
-
const users = await list(
|
|
493
|
+
const users = await context.prism.list();
|
|
411
494
|
if (!users || users.length === 0) {
|
|
412
|
-
return "窝里目前没有玩家呢";
|
|
495
|
+
return "🫥 窝里目前没有玩家呢";
|
|
413
496
|
}
|
|
414
497
|
const tasks = users.map((user2) => {
|
|
415
498
|
const entryDate = formatDateTime(user2.sessions[0].createdAt);
|
|
@@ -422,7 +505,7 @@ async function handleListCmd(context, user) {
|
|
|
422
505
|
return `玩家: ${u}
|
|
423
506
|
入场时间: ${tasks[idx].entryDate}`;
|
|
424
507
|
});
|
|
425
|
-
return
|
|
508
|
+
return `👥 窝里目前共有 ${users.length} 人
|
|
426
509
|
|
|
427
510
|
${userReports.join("\n\n")}`;
|
|
428
511
|
}
|
|
@@ -430,10 +513,10 @@ __name(handleListCmd, "handleListCmd");
|
|
|
430
513
|
async function handleWalletCmd(context, user) {
|
|
431
514
|
const { error, userId } = await getTargetUserId(context, user);
|
|
432
515
|
if (error) return error;
|
|
433
|
-
const res = await wallet(
|
|
516
|
+
const res = await context.prism.wallet(userId);
|
|
434
517
|
const message = [];
|
|
435
518
|
const targetUserId = user ? userId : void 0;
|
|
436
|
-
message.push(targetUserId ?
|
|
519
|
+
message.push(targetUserId ? `💰 --- 用户 ${await getUserName(context.session, targetUserId)} 的钱包余额 ---` : "💰 --- 钱包余额 ---");
|
|
437
520
|
message.push(
|
|
438
521
|
`可用: ${res.total.available} ${context.config.currency} (共 ${res.total.all})`,
|
|
439
522
|
` - 付费: ${res.paid.available}`,
|
|
@@ -472,10 +555,38 @@ async function handleWalletCmd(context, user) {
|
|
|
472
555
|
return message.join("\n");
|
|
473
556
|
}
|
|
474
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");
|
|
475
586
|
async function handleBillingCmd(context, user) {
|
|
476
587
|
const { error, userId } = await getTargetUserId(context, user);
|
|
477
588
|
if (error) return error;
|
|
478
|
-
const res = await billing(
|
|
589
|
+
const res = await context.prism.billing(userId);
|
|
479
590
|
const billingMessage = formatBilling(res, context.config.currency);
|
|
480
591
|
if (user) {
|
|
481
592
|
return `用户 ${await getUserName(context.session, userId)} 的账单:
|
|
@@ -486,9 +597,9 @@ ${billingMessage}`;
|
|
|
486
597
|
}
|
|
487
598
|
__name(handleBillingCmd, "handleBillingCmd");
|
|
488
599
|
async function handleLockCmd(context) {
|
|
489
|
-
const res = await getLock(context
|
|
600
|
+
const res = await context.prism.getLock(context.session.userId);
|
|
490
601
|
return [
|
|
491
|
-
"获取密码成功",
|
|
602
|
+
"🔑 获取密码成功",
|
|
492
603
|
`你的门锁密码是: ${res.password}`,
|
|
493
604
|
`输入完成后按 # 结束`,
|
|
494
605
|
"注意! 门锁密码有效期为三分钟"
|
|
@@ -498,11 +609,11 @@ __name(handleLockCmd, "handleLockCmd");
|
|
|
498
609
|
async function handleItemsCmd(context, user) {
|
|
499
610
|
const { error, userId } = await getTargetUserId(context, user);
|
|
500
611
|
if (error) return error;
|
|
501
|
-
const userAssets = await assets(
|
|
612
|
+
const userAssets = await context.prism.assets(userId);
|
|
502
613
|
if (!userAssets || userAssets.length === 0) {
|
|
503
614
|
return user ? `用户 ${await getUserName(context.session, userId)} 没有任何物品。` : "您当前没有任何物品。";
|
|
504
615
|
}
|
|
505
|
-
const header = user ?
|
|
616
|
+
const header = user ? `🎒 --- 用户 ${await getUserName(context.session, userId)} 拥有的物品 ---` : "🎒 --- 您拥有的物品 ---";
|
|
506
617
|
const itemsList = userAssets.map((asset) => {
|
|
507
618
|
let line = `- ${asset.asset.name} (x${asset.count})`;
|
|
508
619
|
if (asset.expireAt) {
|
|
@@ -518,26 +629,32 @@ async function handleItemsCmd(context, user) {
|
|
|
518
629
|
}
|
|
519
630
|
__name(handleItemsCmd, "handleItemsCmd");
|
|
520
631
|
async function handleMachineOn(context, alias) {
|
|
521
|
-
if (!alias)
|
|
632
|
+
if (!alias) {
|
|
633
|
+
await context.session.execute("help on");
|
|
634
|
+
return "";
|
|
635
|
+
}
|
|
522
636
|
let isAdmin = await context.ctx.permissions.check(context.config.admin, context.session);
|
|
523
|
-
const res = await machinePowerOn(
|
|
524
|
-
return
|
|
637
|
+
const res = await context.prism.machinePowerOn(alias, context.session.userId, !isAdmin);
|
|
638
|
+
return `✅ ${res.machine} 启动成功`;
|
|
525
639
|
}
|
|
526
640
|
__name(handleMachineOn, "handleMachineOn");
|
|
527
641
|
async function handleMachineOff(context, alias) {
|
|
528
|
-
if (!alias)
|
|
642
|
+
if (!alias) {
|
|
643
|
+
await context.session.execute("help off");
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
529
646
|
let isAdmin = await context.ctx.permissions.check(context.config.admin, context.session);
|
|
530
|
-
const res = await machinePowerOff(
|
|
531
|
-
if (alias === "all") return
|
|
532
|
-
return
|
|
647
|
+
const res = await context.prism.machinePowerOff(alias, context.session.userId, !isAdmin);
|
|
648
|
+
if (alias === "all") return `🛑 全部机器关闭成功`;
|
|
649
|
+
return `🛑 ${res.machine} 关闭成功`;
|
|
533
650
|
}
|
|
534
651
|
__name(handleMachineOff, "handleMachineOff");
|
|
535
652
|
async function handleMachineShow(context, alias) {
|
|
536
653
|
if (alias) {
|
|
537
|
-
const res = await getMachinePower(
|
|
654
|
+
const res = await context.prism.getMachinePower(alias);
|
|
538
655
|
return `${res.machine}: ${res.state.state}`;
|
|
539
656
|
} else {
|
|
540
|
-
const res = await getAllMachinePower(
|
|
657
|
+
const res = await context.prism.getAllMachinePower();
|
|
541
658
|
return res.map(
|
|
542
659
|
(e) => {
|
|
543
660
|
return `${e.machine}: ${e.state.state}`;
|
|
@@ -547,14 +664,16 @@ async function handleMachineShow(context, alias) {
|
|
|
547
664
|
}
|
|
548
665
|
__name(handleMachineShow, "handleMachineShow");
|
|
549
666
|
async function handleWalletAdd(context, user, amount) {
|
|
667
|
+
if (!user || !amount) {
|
|
668
|
+
await context.session.execute("help add");
|
|
669
|
+
return "";
|
|
670
|
+
}
|
|
550
671
|
const { error, userId } = await getTargetUserId(context, user);
|
|
551
672
|
if (error) return error;
|
|
552
|
-
if (!amount) return "请输入数量";
|
|
553
673
|
return executeWithAutoRegister(
|
|
554
674
|
context,
|
|
555
675
|
user,
|
|
556
|
-
userId,
|
|
557
|
-
() => walletAdd(context, parseInt(amount), userId),
|
|
676
|
+
() => context.prism.walletAdd(parseFloat(amount), userId),
|
|
558
677
|
async (res) => {
|
|
559
678
|
return [
|
|
560
679
|
`为用户 ${await getUserName(context.session, userId)} 增加${context.config.currency}成功`,
|
|
@@ -566,14 +685,16 @@ async function handleWalletAdd(context, user, amount) {
|
|
|
566
685
|
}
|
|
567
686
|
__name(handleWalletAdd, "handleWalletAdd");
|
|
568
687
|
async function handleWalletDeduct(context, user, amount) {
|
|
688
|
+
if (!user || !amount) {
|
|
689
|
+
await context.session.execute("help del");
|
|
690
|
+
return "";
|
|
691
|
+
}
|
|
569
692
|
const { error, userId } = await getTargetUserId(context, user);
|
|
570
693
|
if (error) return error;
|
|
571
|
-
if (!amount) return "请输入数量";
|
|
572
694
|
return executeWithAutoRegister(
|
|
573
695
|
context,
|
|
574
696
|
user,
|
|
575
|
-
userId,
|
|
576
|
-
() => walletDel(context, parseInt(amount), userId),
|
|
697
|
+
() => context.prism.walletDel(parseInt(amount), userId),
|
|
577
698
|
(res) => {
|
|
578
699
|
return [
|
|
579
700
|
`为用户 ${userId} 扣除${context.config.currency}成功`,
|
|
@@ -585,27 +706,31 @@ async function handleWalletDeduct(context, user, amount) {
|
|
|
585
706
|
}
|
|
586
707
|
__name(handleWalletDeduct, "handleWalletDeduct");
|
|
587
708
|
async function handleCostOverwrite(context, user, amount) {
|
|
709
|
+
if (!user || !amount) {
|
|
710
|
+
await context.session.execute("help overwrite");
|
|
711
|
+
return "";
|
|
712
|
+
}
|
|
588
713
|
const { error, userId } = await getTargetUserId(context, user);
|
|
589
714
|
if (error) return error;
|
|
590
|
-
if (!amount) return "请输入数量";
|
|
591
715
|
return executeWithAutoRegister(
|
|
592
716
|
context,
|
|
593
717
|
user,
|
|
594
|
-
userId,
|
|
595
|
-
() => costOverwrite(context, amount, userId),
|
|
718
|
+
() => context.prism.costOverwrite(amount, userId),
|
|
596
719
|
() => `为用户 ${userId} 调价成功`
|
|
597
720
|
);
|
|
598
721
|
}
|
|
599
722
|
__name(handleCostOverwrite, "handleCostOverwrite");
|
|
600
723
|
async function handleRedeem(context, code) {
|
|
724
|
+
if (!code) {
|
|
725
|
+
await context.session.execute("help redeem");
|
|
726
|
+
return "";
|
|
727
|
+
}
|
|
601
728
|
const { error, userId } = await getTargetUserId(context, null);
|
|
602
729
|
if (error) return error;
|
|
603
|
-
if (!code) return "请输入兑换码";
|
|
604
730
|
return executeWithAutoRegister(
|
|
605
731
|
context,
|
|
606
732
|
void 0,
|
|
607
|
-
userId,
|
|
608
|
-
() => redeem(context, code, userId),
|
|
733
|
+
() => context.prism.redeem(code, userId),
|
|
609
734
|
(res) => {
|
|
610
735
|
const items = res;
|
|
611
736
|
if (!items || items.length === 0) {
|
|
@@ -626,19 +751,290 @@ async function handleRedeem(context, code) {
|
|
|
626
751
|
}
|
|
627
752
|
__name(handleRedeem, "handleRedeem");
|
|
628
753
|
async function handleCoin(context, alias) {
|
|
629
|
-
if (!alias)
|
|
754
|
+
if (!alias) {
|
|
755
|
+
await context.session.execute("help coin");
|
|
756
|
+
return "";
|
|
757
|
+
}
|
|
630
758
|
let isAdmin = await context.ctx.permissions.check(context.config.admin, context.session);
|
|
631
|
-
const res = await insertCoin(
|
|
632
|
-
return
|
|
759
|
+
const res = await context.prism.insertCoin(alias, context.session.userId, isAdmin);
|
|
760
|
+
return `🪙 已为 ${res.machineName} 投入 ${res.count} 个币`;
|
|
633
761
|
}
|
|
634
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");
|
|
635
1028
|
function apply(ctx, config) {
|
|
1029
|
+
const prism = new PrismService(ctx, config);
|
|
636
1030
|
const createAction = /* @__PURE__ */ __name((handler) => {
|
|
637
1031
|
const actionFn = /* @__PURE__ */ __name((argv, ...args) => {
|
|
638
1032
|
const context = {
|
|
639
1033
|
ctx,
|
|
640
1034
|
config,
|
|
641
|
-
session: argv.session
|
|
1035
|
+
session: argv.session,
|
|
1036
|
+
options: argv.options,
|
|
1037
|
+
prism
|
|
642
1038
|
};
|
|
643
1039
|
return handler(context, ...args);
|
|
644
1040
|
}, "actionFn");
|
|
@@ -649,6 +1045,7 @@ function apply(ctx, config) {
|
|
|
649
1045
|
ctx.command("logout [user:user]").action(createAction(handleLogoutCmd));
|
|
650
1046
|
ctx.command("list").action(createAction(handleListCmd));
|
|
651
1047
|
ctx.command("wallet [user:user]").action(createAction(handleWalletCmd));
|
|
1048
|
+
ctx.command("history [arg1] [arg2]").action(createAction(handleHistoriesCmd));
|
|
652
1049
|
ctx.command("billing [user:user]").action(createAction(handleBillingCmd));
|
|
653
1050
|
ctx.command("lock").action(createAction(handleLockCmd));
|
|
654
1051
|
ctx.command("items [user:user]").action(createAction(handleItemsCmd));
|
|
@@ -660,19 +1057,35 @@ function apply(ctx, config) {
|
|
|
660
1057
|
ctx.command("add <user:user> <amount>").action(createAction(handleWalletAdd));
|
|
661
1058
|
ctx.command("del <user:user> <amount>").action(createAction(handleWalletDeduct));
|
|
662
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);
|
|
663
1076
|
ctx.setInterval(
|
|
664
1077
|
async () => {
|
|
665
|
-
let
|
|
666
|
-
if (
|
|
667
|
-
let machines = await getAllMachinePower(
|
|
1078
|
+
let list = await prism.list();
|
|
1079
|
+
if (list.length < 1) {
|
|
1080
|
+
let machines = await prism.getAllMachinePower();
|
|
668
1081
|
let turnOff = false;
|
|
669
1082
|
machines.forEach((m) => {
|
|
670
|
-
if (m.state.state
|
|
1083
|
+
if (m.state.state !== "off") {
|
|
671
1084
|
turnOff = true;
|
|
672
1085
|
}
|
|
673
1086
|
});
|
|
674
1087
|
if (turnOff) {
|
|
675
|
-
let res = await machinePowerOff(
|
|
1088
|
+
let res = await prism.machinePowerOff("all", "system", false);
|
|
676
1089
|
ctx.broadcast(config.broadcasts, "窝里目前有 0 人,自动关闭所有机器");
|
|
677
1090
|
}
|
|
678
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