koishi-plugin-prism 0.1.19 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/lib/index.js +38 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,7 +57,9 @@ pricingConfigIds: [pricing-mahjong-a]
|
|
|
57
57
|
* `logout` - 结算当前玩家的计费场次。
|
|
58
58
|
玩家在未产生任何费用时退场,机器人会简洁显示“本次未产生费用”和当前余额;存在收费或优惠明细时仍显示完整结算账单。
|
|
59
59
|
结账成功后,机器人会向 `staffUserIds` 与 `logoutNotifyUserIds` 中的用户私聊同一份账单,账单会明确显示结账玩家身份。
|
|
60
|
+
同一玩家在前一次退场结账尚未完成时重复发送 `/logout` 或 `/退场`,机器人会复用同一次结账请求与账单,避免重复扣款。
|
|
60
61
|
账单和管理员代操作回执均使用“平台昵称(QQ:号码)”称呼玩家;平台暂时无法提供昵称时显示“未知昵称(QQ:号码)”,不会显示内部玩家 ID。
|
|
62
|
+
管理员 `/add` 增加免费余额;`/del` 按结账相同的顺序从可用免费余额、再从付费余额扣除,余额不足时会返回余额不足提示。
|
|
61
63
|
* `billing` - 预览当前玩家本场计费的消费费用。
|
|
62
64
|
* `wallet` - 查看当前玩家的钱包余额。
|
|
63
65
|
* `items` - 查看当前玩家持有的道具或资产。
|
package/lib/index.js
CHANGED
|
@@ -217,10 +217,10 @@ class PrismApiClient {
|
|
|
217
217
|
body: this.identityBody(identity),
|
|
218
218
|
});
|
|
219
219
|
}
|
|
220
|
-
async confirmCheckoutByIdentity(identity) {
|
|
220
|
+
async confirmCheckoutByIdentity(identity, closeSessionsBeforeBalanceCheck = true) {
|
|
221
221
|
return this.request("POST", "/rpc/integration/players/by-identity/checkout/confirm", {
|
|
222
222
|
token: this.config.integrationToken,
|
|
223
|
-
body: this.identityBody(identity),
|
|
223
|
+
body: { ...this.identityBody(identity), closeSessionsBeforeBalanceCheck },
|
|
224
224
|
});
|
|
225
225
|
}
|
|
226
226
|
async redeemCodeByIdentity(identity, code) {
|
|
@@ -280,6 +280,12 @@ class PrismApiClient {
|
|
|
280
280
|
body: { ...this.identityBody(identity), adjustments },
|
|
281
281
|
});
|
|
282
282
|
}
|
|
283
|
+
async adjustWalletByIdentity(identity, amount, reason) {
|
|
284
|
+
return this.request("POST", "/rpc/integration/players/by-identity/wallet/adjustment", {
|
|
285
|
+
token: this.config.integrationToken,
|
|
286
|
+
body: { ...this.identityBody(identity), amount, reason },
|
|
287
|
+
});
|
|
288
|
+
}
|
|
283
289
|
async checkoutWithOverrideByIdentity(identity, total, reason) {
|
|
284
290
|
return this.request("POST", "/rpc/integration/players/by-identity/checkout/override", {
|
|
285
291
|
token: this.config.integrationToken,
|
|
@@ -291,6 +297,7 @@ class PrismApiClient {
|
|
|
291
297
|
class PrismKoishiService {
|
|
292
298
|
config;
|
|
293
299
|
mahjongTables = new Map();
|
|
300
|
+
logoutInFlight = new Map();
|
|
294
301
|
client;
|
|
295
302
|
constructor(ctx, config) {
|
|
296
303
|
this.config = config;
|
|
@@ -370,12 +377,7 @@ class PrismKoishiService {
|
|
|
370
377
|
if (!Number.isFinite(amount) || amount <= 0)
|
|
371
378
|
return "金额必须大于 0";
|
|
372
379
|
const isAddition = direction === 1;
|
|
373
|
-
await this.client.
|
|
374
|
-
assetType: "currency",
|
|
375
|
-
assetCode: "paid",
|
|
376
|
-
quantityDelta: amount * direction,
|
|
377
|
-
reason: isAddition ? "Koishi 管理员增加余额" : "Koishi 管理员扣除余额",
|
|
378
|
-
}]);
|
|
380
|
+
await this.client.adjustWalletByIdentity(this.identity(sender), amount * direction, isAddition ? "Koishi 管理员增加余额" : "Koishi 管理员扣除余额");
|
|
379
381
|
return `✅ 已为用户 ${formatPlayerReference(sender, this.config.provider)}${isAddition ? "增加" : "扣除"} ${formatNumber(amount)} ${this.config.currencyName}`;
|
|
380
382
|
}, bot);
|
|
381
383
|
}
|
|
@@ -489,7 +491,21 @@ class PrismKoishiService {
|
|
|
489
491
|
return this.formatCheckoutPreview(result, sender);
|
|
490
492
|
}
|
|
491
493
|
async logout(sender, bot) {
|
|
492
|
-
const
|
|
494
|
+
const existing = this.logoutInFlight.get(sender.id);
|
|
495
|
+
if (existing)
|
|
496
|
+
return existing;
|
|
497
|
+
const task = this.performLogout(sender, bot);
|
|
498
|
+
this.logoutInFlight.set(sender.id, task);
|
|
499
|
+
try {
|
|
500
|
+
return await task;
|
|
501
|
+
}
|
|
502
|
+
finally {
|
|
503
|
+
if (this.logoutInFlight.get(sender.id) === task)
|
|
504
|
+
this.logoutInFlight.delete(sender.id);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
async performLogout(sender, bot) {
|
|
508
|
+
const result = (await this.client.confirmCheckoutByIdentity(this.identity(sender), false));
|
|
493
509
|
const settlement = result?.playerSettlement ?? result?.settlement ?? {};
|
|
494
510
|
const records = result?.settlements ?? [];
|
|
495
511
|
const sessionPreviews = records.map((rec) => {
|
|
@@ -913,8 +929,19 @@ class PrismKoishiService {
|
|
|
913
929
|
lines.push(`计费总价:${formatNumber(subtotal)}${currency}`);
|
|
914
930
|
if (hasNonZeroAdjustment)
|
|
915
931
|
lines.push(`优惠后价格:${formatNumber(total)}${currency}`);
|
|
916
|
-
if (hasBalance)
|
|
917
|
-
|
|
932
|
+
if (hasBalance) {
|
|
933
|
+
const isPreview = result?.settlementPreview != null && result?.settlement == null;
|
|
934
|
+
if (isPreview) {
|
|
935
|
+
const projectedBalance = balance - toNumber(total);
|
|
936
|
+
lines.push(`当前余额:${formatNumber(balance)}${currency}`);
|
|
937
|
+
lines.push(projectedBalance >= 0
|
|
938
|
+
? `预计结账后余额:${formatNumber(projectedBalance)}${currency}`
|
|
939
|
+
: `预计结账后余额:余额不足(还差 ${formatNumber(-projectedBalance)}${currency})`);
|
|
940
|
+
}
|
|
941
|
+
else {
|
|
942
|
+
lines.push(`扣款后余额:${formatNumber(balance)}${currency}`);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
918
945
|
return lines.join("\n");
|
|
919
946
|
}
|
|
920
947
|
handleCommandError(error) {
|