koishi-plugin-rocom 1.0.19 → 1.0.24
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/atlas-service.js +1 -1
- package/lib/client.d.ts +10 -0
- package/lib/client.js +44 -8
- package/lib/commands/egg.js +1 -1
- package/lib/commands/merchant.d.ts +105 -0
- package/lib/commands/merchant.js +474 -54
- package/lib/commands/query.d.ts +18 -0
- package/lib/commands/query.js +446 -37
- package/lib/commands/share-code.js +47 -2
- package/lib/commands/tools.js +1 -1
- package/lib/commands/wiki.js +1 -1
- package/lib/egg-service.js +1 -1
- package/lib/element-colors.d.ts +3 -0
- package/lib/element-colors.js +34 -0
- package/lib/icon-metrics.d.ts +32 -0
- package/lib/icon-metrics.js +255 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +11857 -188
- package/lib/merchant-catalog.d.ts +47 -0
- package/lib/merchant-catalog.js +193 -0
- package/lib/merchant-price-log.d.ts +63 -0
- package/lib/merchant-price-log.js +187 -0
- package/lib/merchant-service.d.ts +17 -3
- package/lib/merchant-service.js +79 -11
- package/lib/pet-data-service.d.ts +13 -0
- package/lib/pet-data-service.js +111 -2
- package/lib/player-service.js +2 -2
- package/lib/ranking-service.js +1 -1
- package/lib/render-templates/home/style.css +15 -14
- package/lib/render-templates/home-pets/index.html +80 -0
- package/lib/render-templates/home-pets/style.css +338 -0
- package/lib/render-templates/pet-detail-classic/index.html +151 -0
- package/lib/render-templates/pet-detail-classic/style.css +503 -0
- package/lib/render-templates/pet-detail-classic/texture2D/a_title.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/bg.jpg +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/footer.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/icon.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/img_head.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/jinhua_bg.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/level_icon.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/line.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/mask_bar.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/pet_bg.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/pet_rocom.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/pet_rocom_bg.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/poro_bar.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/right_jinhua.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/skill_bg.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/skill_mask.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/star.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/star_1.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/star_8.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/star_9.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/table.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/tags.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/title.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/top_bg.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/xuancai_overlay.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/yise_overlay.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D/ys_bar.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/10.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/11.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/12.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/13.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/14.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/15.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/16.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/17.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/18.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/19.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/2.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/20.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/23.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/3.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/4.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/5.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/6.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/8.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247/9.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//345/205/211.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//345/206/260.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//345/234/260.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//345/271/273.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//345/271/275.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/201/266.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/227/240.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/231/256/351/200/232.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/234/272/346/242/260.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/255/246.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/257/222.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//346/260/264.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//347/201/253.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//347/224/265.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//347/277/274.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//350/215/211.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//350/220/214.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//350/231/253.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//345/261/236/346/200/247//351/276/231.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/1.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/10.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/11.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/12.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/13.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/14.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/15.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/16.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/17.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/18.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/19.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/2.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/21.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/23.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/24.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/3.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/4.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/5.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/6.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/7.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/8.png +0 -0
- package/lib/render-templates/pet-detail-classic/texture2D//350/241/200/350/204/211/9.png +0 -0
- package/lib/render-templates/share-code-classic/assets/eit-logo.png +0 -0
- package/lib/render-templates/share-code-classic/assets/img_xingxingdi.png +0 -0
- package/lib/render-templates/share-code-classic/assets/roco_icon.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/255/227/344/275/223/Rocofontblack-Regular .ttf +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//345/205/211.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//345/206/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//345/234/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//345/271/273.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//345/271/275.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/201/266.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/227/240.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/231/256/351/200/232.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/234/272/346/242/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/255/246.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/257/222.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//346/260/264.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//347/201/253.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//347/224/265.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//347/277/274.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//350/215/211.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//350/220/214.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//350/231/253.png +0 -0
- package/lib/render-templates/share-code-classic/assets//345/256/240/347/211/251/345/261/236/346/200/247//351/276/231.png +0 -0
- package/lib/render-templates/share-code-classic/assets//347/201/253/346/274/206/345/215/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//347/253/213/347/273/230/350/203/214/346/231/257/346/241/206.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//345/205/211.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//345/206/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//345/234/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//345/245/207/345/274/202.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//345/271/273.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//345/271/275.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/201/266.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/231/256/351/200/232.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/234/272/346/242/260.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/255/246.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/257/222.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/260/264.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//346/261/241/346/237/223.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//347/201/253.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//347/224/265.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//347/277/274.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//350/215/211.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//350/220/214.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//350/231/253.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//351/246/226/351/242/206.png +0 -0
- package/lib/render-templates/share-code-classic/assets//350/241/200/350/204/211//351/276/231.png +0 -0
- package/lib/render-templates/share-code-classic/index.html +119 -0
- package/lib/render-templates/share-code-classic/style.css +646 -0
- package/lib/render-templates/yuanxing-shangren/merchant.html +479 -461
- package/lib/render-templates/yuanxing-shangren/today.html +407 -461
- package/lib/render.d.ts +3 -0
- package/lib/render.js +19 -3
- package/lib/send-image.js +10 -0
- package/lib/share-code-service.d.ts +36 -0
- package/lib/share-code-service.js +73 -0
- package/lib/ttf/rocom_origin.ttf +0 -0
- package/lib/types.d.ts +9 -1
- package/lib/user.d.ts +6 -0
- package/lib/wiki-catalog.js +1 -1
- package/lib/wiki-service.js +1 -1
- package/package.json +2 -1
- package/readme.md +3 -23
- package/lib/ttf/rocom_skill_origin.ttf +0 -0
package/lib/commands/query.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.extractHomeEggStatus = extractHomeEggStatus;
|
|
6
7
|
exports.register = register;
|
|
7
8
|
const koishi_1 = require("koishi");
|
|
8
9
|
const account_1 = require("./account");
|
|
@@ -831,7 +832,7 @@ function extractHomePet(deps, raw, index, guard = false) {
|
|
|
831
832
|
const feedRound = Number(homePet.feed_round || raw.feed_round || 0) || 0;
|
|
832
833
|
const gender = Number(display.gender || raw.gender || 0) || 0;
|
|
833
834
|
let mutationType = Number(display.mutation_type || raw.mutation_type || homePet.mutation_type || 0) || 0;
|
|
834
|
-
//
|
|
835
|
+
// mutation_type 缺失时按 real_speciality_ids 识别变体(103=异色、502=炫彩、两者兼有=异色炫彩)。
|
|
835
836
|
if (!mutationType) {
|
|
836
837
|
const specialityValues = [];
|
|
837
838
|
for (const value of [homePet.real_speciality_ids, raw.real_speciality_ids, homePet.speciality_id, raw.speciality_id]) {
|
|
@@ -1117,13 +1118,13 @@ function buildPlayerSearchRenderData(payload, uid, cardImageUrl = '') {
|
|
|
1117
1118
|
copyright: 'Koishi & WeGame Locke Kingdom Plugin',
|
|
1118
1119
|
};
|
|
1119
1120
|
}
|
|
1120
|
-
function buildShopRenderData(payload, shopId) {
|
|
1121
|
+
function buildShopRenderData(payload, shopId, options = {}) {
|
|
1121
1122
|
const sections = [];
|
|
1122
1123
|
const detailItems = [];
|
|
1123
1124
|
const summaryCards = [{ label: '商店 ID', value: shopId }];
|
|
1124
1125
|
const shop = payload?.shop || {};
|
|
1125
1126
|
if (Array.isArray(payload?.goods)) {
|
|
1126
|
-
const items = (0, merchant_service_1.normalizeLiveMerchant)(payload);
|
|
1127
|
+
const items = (0, merchant_service_1.normalizeLiveMerchant)(payload, Date.now(), { assetBaseUrl: options.assetBaseUrl });
|
|
1127
1128
|
summaryCards.push({ label: '商品数量', value: String(items.length) });
|
|
1128
1129
|
const shopName = String(shop.name || shop.title || '').trim();
|
|
1129
1130
|
if (shopName)
|
|
@@ -1293,7 +1294,7 @@ const HOME_SUB_TEXT = {
|
|
|
1293
1294
|
needUidHint: '请提供玩家 UID,或先完成绑定后再订阅家园生蛋。',
|
|
1294
1295
|
},
|
|
1295
1296
|
};
|
|
1296
|
-
async function subscribeHome(deps, session, uid, kind) {
|
|
1297
|
+
async function subscribeHome(deps, session, uid, kind, mentionAll = null) {
|
|
1297
1298
|
const target = sessionTarget(session);
|
|
1298
1299
|
if (!target.userId && !canManageGroupSubscription(deps, session))
|
|
1299
1300
|
return '此指令仅限群管理员或机器人管理员使用。';
|
|
@@ -1315,10 +1316,275 @@ async function subscribeHome(deps, session, uid, kind) {
|
|
|
1315
1316
|
guild_id: session?.guildId || '',
|
|
1316
1317
|
user_id: target.userId,
|
|
1317
1318
|
updated_by: session?.userId || '',
|
|
1319
|
+
// 群订阅支持命中后 @全体;未显式指定时沿用上次设置。
|
|
1320
|
+
mention_all: target.userId ? false : (mentionAll ?? existing?.mention_all ?? false),
|
|
1318
1321
|
notify_state: existing?.notify_state || {},
|
|
1319
1322
|
updated_at: Math.floor(Date.now() / 1000),
|
|
1320
1323
|
});
|
|
1321
|
-
|
|
1324
|
+
const finalMentionAll = target.userId ? false : (mentionAll ?? existing?.mention_all ?? false);
|
|
1325
|
+
const mentionHint = target.userId ? '' : (finalMentionAll ? '命中后会尝试 @全体。' : '命中后不会 @全体。');
|
|
1326
|
+
return [`已订阅 UID ${targetUid} ${HOME_SUB_TEXT[kind].subscribedHint}`, mentionHint].filter(Boolean).join('');
|
|
1327
|
+
}
|
|
1328
|
+
// 订阅家园 的 @全体 写法与 UID 解析。
|
|
1329
|
+
const HOME_MENTION_ALL_ALIASES = new Set(['@全体', '全体', '@所有人', 'at全体', 'at所有人']);
|
|
1330
|
+
function parseHomeSubscribeArgs(args) {
|
|
1331
|
+
const tokens = String(args || '').split(/\s+/).filter(Boolean);
|
|
1332
|
+
let mentionAll = null;
|
|
1333
|
+
const uids = [];
|
|
1334
|
+
for (const token of tokens) {
|
|
1335
|
+
if (HOME_MENTION_ALL_ALIASES.has(token.toLowerCase())) {
|
|
1336
|
+
mentionAll = true;
|
|
1337
|
+
continue;
|
|
1338
|
+
}
|
|
1339
|
+
uids.push(token);
|
|
1340
|
+
}
|
|
1341
|
+
return { mentionAll, uid: uids[0] || '' };
|
|
1342
|
+
}
|
|
1343
|
+
function pickEggStatusPayload(payload) {
|
|
1344
|
+
const candidates = [payload?.data, payload?.result, payload?.data?.data, payload?.result?.data, payload];
|
|
1345
|
+
for (const candidate of candidates) {
|
|
1346
|
+
if (candidate && typeof candidate === 'object' && !Array.isArray(candidate))
|
|
1347
|
+
return candidate;
|
|
1348
|
+
}
|
|
1349
|
+
return {};
|
|
1350
|
+
}
|
|
1351
|
+
function extractHomeEggPet(item, nowTs) {
|
|
1352
|
+
const petInfo = item?.home_pet_info && typeof item.home_pet_info === 'object' ? item.home_pet_info : item;
|
|
1353
|
+
const petId = petInfo?.pet_cfg_id || petInfo?.pet_id || item?.pet_cfg_id || item?.pet_id;
|
|
1354
|
+
const name = String(petInfo?.name || petInfo?.pet_name || item?.name || item?.pet_name || '').trim();
|
|
1355
|
+
if (!Number(petId) && !name)
|
|
1356
|
+
return null;
|
|
1357
|
+
const hasEgg = Boolean(item?.have_egg ?? petInfo?.have_egg);
|
|
1358
|
+
const predictedEggTime = normalizeEpochSeconds(item?.predicted_egg_time ?? petInfo?.predicted_egg_time ?? item?.egg_ready_time);
|
|
1359
|
+
const ready = hasEgg || (predictedEggTime > 0 && nowTs >= predictedEggTime);
|
|
1360
|
+
const remaining = ready ? '' : (predictedEggTime > 0 ? formatEggRemaining(predictedEggTime, nowTs) : '未知');
|
|
1361
|
+
return {
|
|
1362
|
+
petId: String(petId || ''),
|
|
1363
|
+
name: name || `精灵 ${petId || ''}`,
|
|
1364
|
+
ready,
|
|
1365
|
+
remaining,
|
|
1366
|
+
predictedEggTime,
|
|
1367
|
+
hasEgg,
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
/**
|
|
1371
|
+
* 从 home/eggs 轻量接口响应中提取蛋状态。
|
|
1372
|
+
* 接口仍在开发中,这里对多种可能的字段名做兼容。
|
|
1373
|
+
*/
|
|
1374
|
+
function extractHomeEggStatus(payload) {
|
|
1375
|
+
const data = pickEggStatusPayload(payload);
|
|
1376
|
+
const nowTs = Math.floor(Date.now() / 1000);
|
|
1377
|
+
const eggLists = [
|
|
1378
|
+
data?.eggs,
|
|
1379
|
+
data?.egg_list,
|
|
1380
|
+
data?.egg_info,
|
|
1381
|
+
data?.home_eggs,
|
|
1382
|
+
data?.home_egg_list,
|
|
1383
|
+
data?.home_pets,
|
|
1384
|
+
data?.pet_list,
|
|
1385
|
+
].filter(Array.isArray);
|
|
1386
|
+
const pets = [];
|
|
1387
|
+
for (const list of eggLists) {
|
|
1388
|
+
for (const item of list) {
|
|
1389
|
+
const pet = extractHomeEggPet(item, nowTs);
|
|
1390
|
+
if (pet)
|
|
1391
|
+
pets.push(pet);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
const readyCount = pets.length > 0
|
|
1395
|
+
? pets.filter(pet => pet.ready).length
|
|
1396
|
+
: Number(data?.ready_egg_count ?? data?.readyEggCount ?? data?.egg_ready_count ?? 0) || 0;
|
|
1397
|
+
const totalEggs = pets.length > 0
|
|
1398
|
+
? pets.length
|
|
1399
|
+
: Number(data?.total_egg_count ?? data?.totalEggCount ?? data?.egg_count ?? 0) || 0;
|
|
1400
|
+
return { readyCount, totalEggs, pets };
|
|
1401
|
+
}
|
|
1402
|
+
// 与全量家园信息的蛋状态口径一致:只统计参与生蛋的精灵(有蛋或已排期)。
|
|
1403
|
+
function homeEggSubscriptionState(payload) {
|
|
1404
|
+
const status = extractHomeEggStatus(payload);
|
|
1405
|
+
const items = status.pets.filter(pet => pet.hasEgg || pet.predictedEggTime > 0);
|
|
1406
|
+
const readyItems = items.filter(pet => pet.ready);
|
|
1407
|
+
return { items, readyItems, names: readyItems.map(pet => pet.name) };
|
|
1408
|
+
}
|
|
1409
|
+
function buildHomeEggStatusText(uid, status) {
|
|
1410
|
+
const lines = [
|
|
1411
|
+
`家园蛋状态 - UID ${uid}`,
|
|
1412
|
+
`可收蛋精灵:${status.readyCount} 只 / 共检测 ${status.totalEggs} 只`,
|
|
1413
|
+
];
|
|
1414
|
+
const tracked = status.pets.filter(pet => pet.hasEgg || pet.predictedEggTime > 0);
|
|
1415
|
+
if (tracked.length > 0) {
|
|
1416
|
+
lines.push('');
|
|
1417
|
+
for (const pet of tracked.slice(0, 30)) {
|
|
1418
|
+
lines.push(`${pet.name} ${pet.ready ? '✅ 可收蛋' : `⏳ ${pet.remaining}`}`);
|
|
1419
|
+
}
|
|
1420
|
+
if (tracked.length > 30)
|
|
1421
|
+
lines.push(`…等共 ${tracked.length} 只`);
|
|
1422
|
+
}
|
|
1423
|
+
lines.push('');
|
|
1424
|
+
lines.push(`更新时间:${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`);
|
|
1425
|
+
return lines.join('\n');
|
|
1426
|
+
}
|
|
1427
|
+
// 家园精灵一览(home/pet-data),汇总体重、声音、变异与生蛋状态。
|
|
1428
|
+
function collectHomePetsViewSources(homeInfo, payload) {
|
|
1429
|
+
const containers = [homeInfo?.friend_cell_home_brief_info, homeCellInfo(homeInfo), homeInfo?.cell_info, homeInfo, payload?.friend_cell_home_brief_info];
|
|
1430
|
+
const result = [];
|
|
1431
|
+
const seen = new Set();
|
|
1432
|
+
for (const container of containers) {
|
|
1433
|
+
if (!container || typeof container !== 'object' || !Array.isArray(container.home_pets))
|
|
1434
|
+
continue;
|
|
1435
|
+
for (const item of container.home_pets) {
|
|
1436
|
+
const info = item?.home_pet_info && typeof item.home_pet_info === 'object' ? item.home_pet_info : item;
|
|
1437
|
+
const key = String(info?.pet_gid || info?.furniture_guid || `${info?.pet_cfg_id || ''}:${info?.name || ''}`);
|
|
1438
|
+
if (key && seen.has(key))
|
|
1439
|
+
continue;
|
|
1440
|
+
if (key)
|
|
1441
|
+
seen.add(key);
|
|
1442
|
+
result.push(item);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
return result;
|
|
1446
|
+
}
|
|
1447
|
+
function homePetsViewPetFromNpc(raw) {
|
|
1448
|
+
const npcPet = raw?.npc_pet && typeof raw.npc_pet === 'object' ? raw.npc_pet : {};
|
|
1449
|
+
const pet = npcPet?.pet && typeof npcPet.pet === 'object' ? npcPet.pet : (raw?.pet && typeof raw.pet === 'object' ? raw.pet : raw?.display_info);
|
|
1450
|
+
const petId = raw?.pet_cfg_id || raw?.pet_id || pet?.base_conf_id || pet?.pet_id || pet?.id;
|
|
1451
|
+
return {
|
|
1452
|
+
home_pet_info: {
|
|
1453
|
+
pet_gid: raw?.pet_gid || pet?.pet_gid,
|
|
1454
|
+
npc_id: raw?.npc_id || raw?.npcId,
|
|
1455
|
+
pet_cfg_id: petId,
|
|
1456
|
+
furniture_guid: raw?.furniture_guid,
|
|
1457
|
+
name: raw?.name || pet?.name,
|
|
1458
|
+
speciality_id: raw?.speciality_id || pet?.speciality_id,
|
|
1459
|
+
real_speciality_ids: raw?.real_speciality_ids || pet?.real_speciality_ids || [],
|
|
1460
|
+
status: raw?.status,
|
|
1461
|
+
},
|
|
1462
|
+
display_info: pet,
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
function isHomePetsViewGuard(homePetInfo, displayInfo, pet) {
|
|
1466
|
+
const status = String(homePetInfo?.status ?? pet?.status ?? displayInfo?.status ?? '').toLowerCase();
|
|
1467
|
+
const zeroCfgWithName = String(homePetInfo?.pet_cfg_id || '0') === '0'
|
|
1468
|
+
&& Boolean(String(homePetInfo?.name || homePetInfo?.pet_name || '').trim());
|
|
1469
|
+
return zeroCfgWithName
|
|
1470
|
+
|| Boolean(homePetInfo?.is_guard || homePetInfo?.guard || pet?.is_guard || pet?.guard || displayInfo?.is_guard || displayInfo?.guard)
|
|
1471
|
+
|| status === '2' || status === 'guard';
|
|
1472
|
+
}
|
|
1473
|
+
// ingame 数据体重可能以克或千克记录:大数值按克换算成千克展示。
|
|
1474
|
+
function homePetsWeightText(value) {
|
|
1475
|
+
const num = Number(value);
|
|
1476
|
+
if (!Number.isFinite(num) || num <= 0)
|
|
1477
|
+
return '--';
|
|
1478
|
+
const kg = num >= 1000 ? num / 1000 : num;
|
|
1479
|
+
const text = kg.toFixed(2).replace(/0+$/, '').replace(/\.$/, '');
|
|
1480
|
+
return `${text}kg`;
|
|
1481
|
+
}
|
|
1482
|
+
function buildHomePetsViewData(deps, res, uid) {
|
|
1483
|
+
const raw = res || {};
|
|
1484
|
+
const payload = raw.result && typeof raw.result === 'object' ? raw.result : raw;
|
|
1485
|
+
const homeInfo = homeInfoPayload(raw);
|
|
1486
|
+
const homePets = collectHomePetsViewSources(homeInfo, payload);
|
|
1487
|
+
const npcPets = Array.isArray(payload.npc_pets) ? payload.npc_pets : [];
|
|
1488
|
+
const npcMap = new Map();
|
|
1489
|
+
for (const entry of npcPets) {
|
|
1490
|
+
const npcPet = entry?.npc_pet && typeof entry.npc_pet === 'object' ? entry.npc_pet : {};
|
|
1491
|
+
const pet = npcPet?.pet && typeof npcPet.pet === 'object' ? npcPet.pet : entry?.pet;
|
|
1492
|
+
const gid = String(entry?.pet_gid || entry?.petGid || npcPet?.pet_gid || pet?.pet_gid || '').trim();
|
|
1493
|
+
if (gid)
|
|
1494
|
+
npcMap.set(gid, entry);
|
|
1495
|
+
}
|
|
1496
|
+
const nowTs = Math.floor(Date.now() / 1000);
|
|
1497
|
+
const petSources = homePets.length > 0 ? homePets : npcPets.map(entry => homePetsViewPetFromNpc(entry));
|
|
1498
|
+
const pets = [];
|
|
1499
|
+
for (const hp of petSources) {
|
|
1500
|
+
const homePetInfo = hp?.home_pet_info && typeof hp.home_pet_info === 'object' ? hp.home_pet_info : hp;
|
|
1501
|
+
const displayInfo = hp?.display_info && typeof hp.display_info === 'object' ? hp.display_info : {};
|
|
1502
|
+
const petGid = String(homePetInfo?.pet_gid || displayInfo?.pet_gid || '').trim();
|
|
1503
|
+
const npcRaw = npcMap.get(petGid) || {};
|
|
1504
|
+
const npcPetObj = npcRaw?.npc_pet && typeof npcRaw.npc_pet === 'object' ? npcRaw.npc_pet : {};
|
|
1505
|
+
const npcFullPet = npcPetObj?.pet && typeof npcPetObj.pet === 'object' ? npcPetObj.pet
|
|
1506
|
+
: (npcRaw?.pet && typeof npcRaw.pet === 'object' ? npcRaw.pet : npcRaw?.display_info);
|
|
1507
|
+
const npcStatus = String(npcRaw?.status || '');
|
|
1508
|
+
const hasFull = npcFullPet && typeof npcFullPet === 'object' && Object.keys(npcFullPet).length > 0 && npcStatus !== 'error';
|
|
1509
|
+
const pet = hasFull ? npcFullPet : displayInfo;
|
|
1510
|
+
const petId = pet?.base_conf_id || pet?.pet_id || pet?.id || displayInfo?.base_conf_id || homePetInfo?.pet_cfg_id;
|
|
1511
|
+
if (isHomePetsViewGuard(homePetInfo, displayInfo, pet) || !Number(petId))
|
|
1512
|
+
continue;
|
|
1513
|
+
const name = String(pet?.name || homePetInfo?.name || homePetInfo?.pet_name || `精灵 ${petId}`).trim();
|
|
1514
|
+
const gender = Number(pet?.gender ?? displayInfo?.gender ?? 0) || 0;
|
|
1515
|
+
const genderText = gender === 1 ? '♂ 雄性' : gender === 2 ? '♀ 雌性' : '未知';
|
|
1516
|
+
let mutationType = Number(pet?.mutation_type ?? displayInfo?.mutation_type ?? 0) || 0;
|
|
1517
|
+
if (!mutationType) {
|
|
1518
|
+
// 与 extractHomePet 相同的变体兜底(real_speciality_ids 103=异色、502=炫彩)。
|
|
1519
|
+
const specialityValues = [];
|
|
1520
|
+
for (const value of [homePetInfo.real_speciality_ids, npcRaw.real_speciality_ids, homePetInfo.speciality_id, npcRaw.speciality_id]) {
|
|
1521
|
+
if (Array.isArray(value))
|
|
1522
|
+
specialityValues.push(...value);
|
|
1523
|
+
else if (value !== undefined && value !== null && value !== '')
|
|
1524
|
+
specialityValues.push(value);
|
|
1525
|
+
}
|
|
1526
|
+
const specialityIds = new Set(specialityValues.map(value => String(value).trim()).filter(Boolean));
|
|
1527
|
+
if (specialityIds.has('103') && specialityIds.has('502'))
|
|
1528
|
+
mutationType = 9;
|
|
1529
|
+
else if (specialityIds.has('103'))
|
|
1530
|
+
mutationType = 1;
|
|
1531
|
+
else if (specialityIds.has('502'))
|
|
1532
|
+
mutationType = 8;
|
|
1533
|
+
}
|
|
1534
|
+
const variantText = String(pet?.mutation_name || displayInfo?.mutation_name || '')
|
|
1535
|
+
|| (mutationType === 9 ? '异色炫彩' : mutationType === 1 ? '异色' : mutationType === 8 ? '炫彩' : '');
|
|
1536
|
+
const hasEgg = Boolean(hp?.have_egg ?? pet?.have_egg);
|
|
1537
|
+
const predictedEggTime = normalizeEpochSeconds(hp?.predicted_egg_time ?? pet?.predicted_egg_time);
|
|
1538
|
+
const eggReady = hasEgg || (predictedEggTime > 0 && nowTs >= predictedEggTime);
|
|
1539
|
+
const eggText = eggReady ? '可收蛋' : (predictedEggTime > 0 ? `${formatEggRemaining(predictedEggTime, nowTs)}后生蛋` : '');
|
|
1540
|
+
pets.push({
|
|
1541
|
+
id: String(petId || ''),
|
|
1542
|
+
name,
|
|
1543
|
+
level: pet?.level ?? displayInfo?.level ?? homePetInfo?.level ?? '--',
|
|
1544
|
+
genderText,
|
|
1545
|
+
weightText: homePetsWeightText(pet?.weight ?? displayInfo?.weight ?? homePetInfo?.weight ?? pet?.pet_weight),
|
|
1546
|
+
voiceText: (0, pet_data_service_1.petDataVoiceInfo)(pet?.voice ?? displayInfo?.voice).value,
|
|
1547
|
+
variantText,
|
|
1548
|
+
eggReady,
|
|
1549
|
+
eggText,
|
|
1550
|
+
iconUrl: homePetIcon(petId, pet?.pet_icon_url || displayInfo?.pet_icon_url || npcRaw?.icon_url || ''),
|
|
1551
|
+
starIconUrl: [1, 8, 9].includes(mutationType)
|
|
1552
|
+
? deps.renderer.resourceUrl(`render-templates/home/img/rocomuid/star_${mutationType}.png`)
|
|
1553
|
+
: '',
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
pets.sort((a, b) => (a.eggReady === b.eggReady ? 0 : (a.eggReady ? -1 : 1)));
|
|
1557
|
+
const brief = homeBriefInfo(homeInfo);
|
|
1558
|
+
const homeName = String(brief?.home_name || brief?.name || payload?.player_info?.name || '').trim() || '洛克玩家';
|
|
1559
|
+
return {
|
|
1560
|
+
title: '家园精灵',
|
|
1561
|
+
homeName,
|
|
1562
|
+
uid,
|
|
1563
|
+
pets,
|
|
1564
|
+
total: pets.length,
|
|
1565
|
+
eggCount: pets.filter(pet => pet.eggReady).length,
|
|
1566
|
+
emptyText: '未获取到家园精灵信息。请确认目标玩家在线、家园可访问,或稍后重试。',
|
|
1567
|
+
updatedAt: new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }),
|
|
1568
|
+
};
|
|
1569
|
+
}
|
|
1570
|
+
function buildHomePetsViewText(data) {
|
|
1571
|
+
const lines = [
|
|
1572
|
+
`【家园精灵】UID ${data.uid}(${data.homeName})`,
|
|
1573
|
+
`共 ${data.total} 只精灵,可收蛋 ${data.eggCount} 只`,
|
|
1574
|
+
];
|
|
1575
|
+
for (const pet of (data.pets || []).slice(0, 12)) {
|
|
1576
|
+
const bits = [pet.name, `Lv.${pet.level}`, pet.genderText, pet.weightText, pet.voiceText];
|
|
1577
|
+
if (pet.variantText)
|
|
1578
|
+
bits.push(pet.variantText);
|
|
1579
|
+
if (pet.eggText)
|
|
1580
|
+
bits.push(pet.eggText);
|
|
1581
|
+
lines.push(`- ${bits.join(' ')}`);
|
|
1582
|
+
}
|
|
1583
|
+
if ((data.pets || []).length > 12)
|
|
1584
|
+
lines.push(`…等共 ${data.pets.length} 只`);
|
|
1585
|
+
if (!data.pets?.length)
|
|
1586
|
+
lines.push(data.emptyText);
|
|
1587
|
+
return lines.join('\n');
|
|
1322
1588
|
}
|
|
1323
1589
|
function homeSubscriptionState(data, kind) {
|
|
1324
1590
|
if (kind === 'garden') {
|
|
@@ -1349,27 +1615,49 @@ function homeSubscriptionMessage(uid, kind, level, totalCount, readyItems, names
|
|
|
1349
1615
|
}
|
|
1350
1616
|
async function checkHomeSubscriptions(deps, signal) {
|
|
1351
1617
|
const subs = deps.homeSubMgr.getAll();
|
|
1352
|
-
const
|
|
1618
|
+
const fullCache = new Map();
|
|
1619
|
+
const eggsCache = new Map();
|
|
1620
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
1353
1621
|
let checkedCount = 0;
|
|
1354
1622
|
let pushedCount = 0;
|
|
1623
|
+
const fetchFull = async (uid) => {
|
|
1624
|
+
if (!fullCache.has(uid)) {
|
|
1625
|
+
fullCache.set(uid, await deps.client.ingameHomeInfo(deps.ctx, uid, { timeoutMs: 30000, signal }).catch(() => null));
|
|
1626
|
+
}
|
|
1627
|
+
return fullCache.get(uid);
|
|
1628
|
+
};
|
|
1355
1629
|
for (const [key, sub] of Object.entries(subs)) {
|
|
1356
1630
|
if (signal?.aborted)
|
|
1357
1631
|
break;
|
|
1358
1632
|
if (!sub.uid || !['garden', 'inspiration', 'egg'].includes(sub.kind))
|
|
1359
1633
|
continue;
|
|
1360
1634
|
checkedCount++;
|
|
1361
|
-
|
|
1362
|
-
|
|
1635
|
+
const modified = () => JSON.stringify(deps.homeSubMgr.getAll()[key]) !== JSON.stringify(sub);
|
|
1636
|
+
let state = null;
|
|
1637
|
+
if (sub.kind === 'egg') {
|
|
1638
|
+
// 蛋状态订阅走轻量 home/eggs 接口,降低轮询开销。
|
|
1639
|
+
if (!eggsCache.has(sub.uid)) {
|
|
1640
|
+
eggsCache.set(sub.uid, await deps.client.ingameHomeEggs(deps.ctx, sub.uid, { timeoutMs: 30000, signal }).catch(() => null));
|
|
1641
|
+
}
|
|
1642
|
+
if (signal?.aborted)
|
|
1643
|
+
break;
|
|
1644
|
+
if (modified())
|
|
1645
|
+
continue;
|
|
1646
|
+
const payload = eggsCache.get(sub.uid);
|
|
1647
|
+
if (payload)
|
|
1648
|
+
state = homeEggSubscriptionState(payload);
|
|
1363
1649
|
}
|
|
1364
|
-
if (
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1650
|
+
if (!state) {
|
|
1651
|
+
const res = await fetchFull(sub.uid);
|
|
1652
|
+
if (signal?.aborted)
|
|
1653
|
+
break;
|
|
1654
|
+
if (modified())
|
|
1655
|
+
continue;
|
|
1656
|
+
if (!res)
|
|
1657
|
+
continue;
|
|
1658
|
+
state = homeSubscriptionState(buildHomeRenderData(deps, res, sub.uid), sub.kind);
|
|
1659
|
+
}
|
|
1660
|
+
const { items, readyItems, names } = state;
|
|
1373
1661
|
const totalCount = items.length;
|
|
1374
1662
|
if (totalCount <= 0)
|
|
1375
1663
|
continue;
|
|
@@ -1388,7 +1676,7 @@ async function checkHomeSubscriptions(deps, signal) {
|
|
|
1388
1676
|
notifyState.all = false;
|
|
1389
1677
|
}
|
|
1390
1678
|
if (!pushLevels.length) {
|
|
1391
|
-
deps.homeSubMgr.upsert(key, { ...sub, notify_state: notifyState });
|
|
1679
|
+
deps.homeSubMgr.upsert(key, { ...sub, notify_state: notifyState, last_check_time: nowSec });
|
|
1392
1680
|
continue;
|
|
1393
1681
|
}
|
|
1394
1682
|
const owned = deps.userMgr.getUserBindings(sub.updated_by).find(binding => binding.role_id === sub.uid);
|
|
@@ -1396,13 +1684,18 @@ async function checkHomeSubscriptions(deps, signal) {
|
|
|
1396
1684
|
const notifyUser = owned && sub.notify_user_id === sub.updated_by ? sub.notify_user_id : '';
|
|
1397
1685
|
const messages = pushLevels.map(level => homeSubscriptionMessage(label, sub.kind, level, totalCount, readyItems, names));
|
|
1398
1686
|
try {
|
|
1687
|
+
const body = messages.join('\n\n');
|
|
1688
|
+
// 群订阅 mention_all 开启时命中后 @全体。
|
|
1689
|
+
const content = !sub.user_id && sub.mention_all
|
|
1690
|
+
? [(0, koishi_1.h)('at', { type: 'all' }), koishi_1.h.text('\n' + body)]
|
|
1691
|
+
: (!sub.user_id && notifyUser ? [koishi_1.h.at(notifyUser), koishi_1.h.text('\n' + body)] : body);
|
|
1399
1692
|
const sent = await (0, subscription_send_1.sendScheduledMessage)(deps.ctx, {
|
|
1400
1693
|
platform: sub.platform,
|
|
1401
1694
|
channelId: sub.channel_id || sub.guild_id || sub.user_id || '',
|
|
1402
1695
|
guildId: sub.guild_id || '',
|
|
1403
1696
|
userId: sub.user_id || '',
|
|
1404
1697
|
selfId: sub.self_id || '',
|
|
1405
|
-
},
|
|
1698
|
+
}, content, signal);
|
|
1406
1699
|
if (!sent || signal?.aborted || JSON.stringify(deps.homeSubMgr.getAll()[key]) !== JSON.stringify(sub))
|
|
1407
1700
|
continue;
|
|
1408
1701
|
}
|
|
@@ -1413,7 +1706,7 @@ async function checkHomeSubscriptions(deps, signal) {
|
|
|
1413
1706
|
for (const level of pushLevels)
|
|
1414
1707
|
notifyState[level] = true;
|
|
1415
1708
|
pushedCount += pushLevels.length;
|
|
1416
|
-
deps.homeSubMgr.upsert(key, { ...sub, notify_state: notifyState, last_push_time: Math.floor(Date.now() / 1000) });
|
|
1709
|
+
deps.homeSubMgr.upsert(key, { ...sub, notify_state: notifyState, last_push_time: Math.floor(Date.now() / 1000), last_check_time: nowSec });
|
|
1417
1710
|
}
|
|
1418
1711
|
return { subscriptions: Object.keys(subs).length, checked: checkedCount, pushed: pushedCount };
|
|
1419
1712
|
}
|
|
@@ -1580,7 +1873,7 @@ function register(deps) {
|
|
|
1580
1873
|
profileStatusText,
|
|
1581
1874
|
profileStatusClass: profileStatusText === '是' ? 'online' : 'offline',
|
|
1582
1875
|
commandHint: '洛克.背包 <筛选> <页码> | 洛克.战绩 <页码> | 洛克 查看菜单',
|
|
1583
|
-
copyright: '
|
|
1876
|
+
copyright: 'Koishi & WeGame Roco Kingdom Plugin',
|
|
1584
1877
|
};
|
|
1585
1878
|
if (recentBattle) {
|
|
1586
1879
|
data.hasBattleData = true;
|
|
@@ -1594,7 +1887,7 @@ function register(deps) {
|
|
|
1594
1887
|
icon: pet.pet_img_url?.replace('/image.png', '/icon.png') || '',
|
|
1595
1888
|
}));
|
|
1596
1889
|
}
|
|
1597
|
-
const fallback = `【${role.name}的档案】Lv.${role.level} UID:${role.id}\n评分:${ev.score || '0'} 收藏:${cl.current_collection_count || 0}/${cl.total_collection_count || 0}`;
|
|
1890
|
+
const fallback = `【${role.name || '洛克玩家'}的档案】Lv.${role.level || '--'} UID:${role.id || '--'}\n评分:${ev.score || '0'} 收藏:${cl.current_collection_count || 0}/${cl.total_collection_count || 0}`;
|
|
1598
1891
|
await sendImage(deps, session, 'personal-card', data, fallback);
|
|
1599
1892
|
});
|
|
1600
1893
|
ctx.command('洛克').subcommand('.战绩 [page:number]', '查看对战战绩')
|
|
@@ -1634,7 +1927,7 @@ function register(deps) {
|
|
|
1634
1927
|
});
|
|
1635
1928
|
const data = {
|
|
1636
1929
|
userAvatarDisplay: role.avatar_url || '',
|
|
1637
|
-
userName: role.name,
|
|
1930
|
+
userName: role.name || '洛克玩家',
|
|
1638
1931
|
userLevel: role.level || 1,
|
|
1639
1932
|
userUid: role.id || '',
|
|
1640
1933
|
winRate: `${bo.win_rate || 0}%`,
|
|
@@ -1643,7 +1936,7 @@ function register(deps) {
|
|
|
1643
1936
|
commandHint: '洛克.战绩 <页码>',
|
|
1644
1937
|
copyright: 'Koishi & WeGame 洛克王国插件',
|
|
1645
1938
|
};
|
|
1646
|
-
await sendImage(deps, session, 'record', data, `【${role.name}的战绩】胜率:${bo.win_rate || 0}% 场次:${bo.total_match || 0}`);
|
|
1939
|
+
await sendImage(deps, session, 'record', data, `【${role.name || '洛克玩家'}的战绩】胜率:${bo.win_rate || 0}% 场次:${bo.total_match || 0}`);
|
|
1647
1940
|
});
|
|
1648
1941
|
ctx.command('洛克').subcommand('.背包 [arg1:string] [arg2:string]', '查看精灵背包')
|
|
1649
1942
|
.alias('洛克背包')
|
|
@@ -1935,7 +2228,9 @@ function register(deps) {
|
|
|
1935
2228
|
].join('\n');
|
|
1936
2229
|
}
|
|
1937
2230
|
const lowBandwidth = Boolean(deps.config.lowBandwidthMode);
|
|
1938
|
-
//
|
|
2231
|
+
// classic 样式走 pet-detail-classic 模板(立绘 + 属性表 + 技能栏),
|
|
2232
|
+
// 不需要精灵体重范围(sizeLookup)。
|
|
2233
|
+
const useClassic = deps.config.homeDetailUiStyle !== 'panel';
|
|
1939
2234
|
const [optionsPayload, skillLookup, sizeLookup] = await Promise.all([
|
|
1940
2235
|
deps.wikiService.getOptionsPayload().catch(() => ({})),
|
|
1941
2236
|
(async () => {
|
|
@@ -1949,6 +2244,8 @@ function register(deps) {
|
|
|
1949
2244
|
return lookup;
|
|
1950
2245
|
})(),
|
|
1951
2246
|
(async () => {
|
|
2247
|
+
if (useClassic)
|
|
2248
|
+
return {};
|
|
1952
2249
|
const lookup = {};
|
|
1953
2250
|
const ids = (0, pet_data_service_1.petDataPetIdsFromPayload)(res);
|
|
1954
2251
|
await Promise.all(ids.map(async (id) => {
|
|
@@ -1959,7 +2256,16 @@ function register(deps) {
|
|
|
1959
2256
|
return lookup;
|
|
1960
2257
|
})(),
|
|
1961
2258
|
]);
|
|
1962
|
-
const
|
|
2259
|
+
const classicData = useClassic
|
|
2260
|
+
? (0, pet_data_service_1.buildPetDetailClassicView)(res, targetUid || '当前绑定', {
|
|
2261
|
+
optionsPayload,
|
|
2262
|
+
skillLookup,
|
|
2263
|
+
baseUrl: deps.config.apiBaseUrl.replace(/\/$/, ''),
|
|
2264
|
+
loadSkillIcons: !lowBandwidth,
|
|
2265
|
+
variantIconPath: mutationType => `render-templates/pet-detail-classic/texture2D/star_${mutationType}.png`,
|
|
2266
|
+
})
|
|
2267
|
+
: null;
|
|
2268
|
+
const data = classicData || (0, pet_data_service_1.buildPetDataRenderData)(res, targetUid || '当前绑定', {
|
|
1963
2269
|
optionsPayload,
|
|
1964
2270
|
skillLookup,
|
|
1965
2271
|
sizeLookup,
|
|
@@ -1968,22 +2274,95 @@ function register(deps) {
|
|
|
1968
2274
|
baseUrl: deps.config.apiBaseUrl.replace(/\/$/, ''),
|
|
1969
2275
|
});
|
|
1970
2276
|
const fallbackLines = [
|
|
1971
|
-
`家园详情 - UID ${data.uid}
|
|
1972
|
-
data.notice,
|
|
2277
|
+
`家园详情 - UID ${data.uid}${data.onlineText ? `(${data.onlineText})` : ''}`,
|
|
2278
|
+
data.notice || '',
|
|
1973
2279
|
];
|
|
1974
2280
|
for (const pet of (data.pets || []).slice(0, 8)) {
|
|
1975
|
-
|
|
2281
|
+
const bits = [
|
|
2282
|
+
pet.index ? `${pet.index}.` : '',
|
|
2283
|
+
`${pet.name} Lv.${pet.level}`,
|
|
2284
|
+
pet.variantText,
|
|
2285
|
+
`分贝 ${pet.voiceText || '--'}`,
|
|
2286
|
+
].filter(Boolean);
|
|
2287
|
+
fallbackLines.push(bits.join(' '));
|
|
1976
2288
|
}
|
|
1977
2289
|
if (!data.pets?.length)
|
|
1978
2290
|
fallbackLines.push(data.emptyText);
|
|
1979
2291
|
fallbackLines.push('');
|
|
1980
2292
|
fallbackLines.push('若服务器带宽过小导致生成超时,请在配置项打开低带宽模式。');
|
|
1981
2293
|
fallbackLines.push('低带宽模式开启后,家园详情将不再加载技能图标。');
|
|
1982
|
-
await sendImage(deps, session, 'pet-data', data, fallbackLines.join('\n'), {
|
|
2294
|
+
await sendImage(deps, session, classicData ? 'pet-detail-classic' : 'pet-data', data, fallbackLines.join('\n'), {
|
|
1983
2295
|
...(lowBandwidth ? render_1.lowBandwidthRenderOptions : {}),
|
|
1984
2296
|
timeoutMs: deps.config.renderTimeout || 30000,
|
|
1985
2297
|
});
|
|
1986
2298
|
});
|
|
2299
|
+
// 家园精灵一览(home/pet-data),体重、声音、变异与生蛋状态。
|
|
2300
|
+
ctx.command('洛克').subcommand('.家园精灵 [uid:string]', '查看家园精灵列表(体重、声音、生蛋状态)')
|
|
2301
|
+
.alias('洛克家园精灵')
|
|
2302
|
+
.alias('家园精灵')
|
|
2303
|
+
.action(async ({ session }, uid = '') => {
|
|
2304
|
+
let targetUid = String(uid || '').trim();
|
|
2305
|
+
if (!targetUid) {
|
|
2306
|
+
const binding = deps.userMgr.getPrimaryBinding(session.userId);
|
|
2307
|
+
targetUid = String(binding?.role_id || '');
|
|
2308
|
+
}
|
|
2309
|
+
const fwToken = await (0, account_1.getPrimaryToken)(deps, session.userId);
|
|
2310
|
+
if (!targetUid && !fwToken)
|
|
2311
|
+
return '请提供玩家 UID,或先完成绑定后使用 洛克.家园精灵。';
|
|
2312
|
+
let queuedNotified = false;
|
|
2313
|
+
const res = await client.ingameHomePetData(ctx, targetUid, {
|
|
2314
|
+
auth: { fwToken, userIdentifier: session.userId },
|
|
2315
|
+
waitMs: deps.config.homeQueryWaitMs,
|
|
2316
|
+
intervalMs: deps.config.homeQueryPollIntervalMs,
|
|
2317
|
+
timeoutMs: deps.config.homeQueryTimeoutMs,
|
|
2318
|
+
onQueued: async () => {
|
|
2319
|
+
if (queuedNotified)
|
|
2320
|
+
return;
|
|
2321
|
+
queuedNotified = true;
|
|
2322
|
+
await session?.send?.(`UID ${targetUid} 的家园精灵查询已进入队列,正在等待游戏侧返回,请稍候…`);
|
|
2323
|
+
},
|
|
2324
|
+
});
|
|
2325
|
+
if (!res) {
|
|
2326
|
+
return [
|
|
2327
|
+
`家园精灵查询失败:${client.getLastErrorBrief()}`,
|
|
2328
|
+
'提示:该接口需要目标玩家在线,且目标家园可访问。',
|
|
2329
|
+
].join('\n');
|
|
2330
|
+
}
|
|
2331
|
+
const data = buildHomePetsViewData(deps, res, targetUid || '当前绑定');
|
|
2332
|
+
await sendImage(deps, session, 'home-pets', data, buildHomePetsViewText(data), {
|
|
2333
|
+
timeoutMs: deps.config.renderTimeout || 30000,
|
|
2334
|
+
});
|
|
2335
|
+
});
|
|
2336
|
+
// 立即查询指定 UID 的家园蛋状态。
|
|
2337
|
+
ctx.command('洛克').subcommand('.家园状态 [uid:string]', '查询家园蛋状态(可收蛋精灵与倒计时)')
|
|
2338
|
+
.alias('洛克家园状态')
|
|
2339
|
+
.alias('家园状态')
|
|
2340
|
+
.action(async ({ session }, uid = '') => {
|
|
2341
|
+
let targetUid = String(uid || '').trim();
|
|
2342
|
+
if (!targetUid) {
|
|
2343
|
+
const binding = deps.userMgr.getPrimaryBinding(session.userId);
|
|
2344
|
+
targetUid = String(binding?.role_id || '');
|
|
2345
|
+
}
|
|
2346
|
+
const fwToken = await (0, account_1.getPrimaryToken)(deps, session.userId);
|
|
2347
|
+
if (!targetUid && !fwToken)
|
|
2348
|
+
return `请提供玩家 UID,或先完成绑定后使用 洛克.家园状态。`;
|
|
2349
|
+
let queuedNotified = false;
|
|
2350
|
+
const res = await client.ingameHomeEggs(ctx, targetUid, {
|
|
2351
|
+
auth: { fwToken, userIdentifier: session.userId },
|
|
2352
|
+
waitMs: deps.config.homeQueryWaitMs,
|
|
2353
|
+
intervalMs: deps.config.homeQueryPollIntervalMs,
|
|
2354
|
+
timeoutMs: deps.config.homeQueryTimeoutMs,
|
|
2355
|
+
onQueued: async () => {
|
|
2356
|
+
if (queuedNotified)
|
|
2357
|
+
return;
|
|
2358
|
+
queuedNotified = true;
|
|
2359
|
+
await session?.send?.(`UID ${targetUid} 的家园蛋状态查询已进入队列,正在等待游戏侧返回,请稍候…`);
|
|
2360
|
+
},
|
|
2361
|
+
});
|
|
2362
|
+
if (!res)
|
|
2363
|
+
return `家园蛋状态查询失败:${client.getLastErrorBrief()}`;
|
|
2364
|
+
return buildHomeEggStatusText(targetUid, extractHomeEggStatus(res));
|
|
2365
|
+
});
|
|
1987
2366
|
ctx.command('洛克').subcommand('.刷新面板 [uid:string]', '刷新指定 UID 的精灵面板缓存')
|
|
1988
2367
|
.alias('洛克刷新面板')
|
|
1989
2368
|
.alias('刷新面板')
|
|
@@ -2074,7 +2453,7 @@ function register(deps) {
|
|
|
2074
2453
|
const res = await client.ingameMerchantInfo(ctx, targetShopId);
|
|
2075
2454
|
if (!res)
|
|
2076
2455
|
return `商店查询失败:${client.getLastErrorBrief()}`;
|
|
2077
|
-
await sendImage(deps, session, 'ingame-shop', buildShopRenderData(res, targetShopId), `【洛克商店】shop_id=${targetShopId}`);
|
|
2456
|
+
await sendImage(deps, session, 'ingame-shop', buildShopRenderData(res, targetShopId, { assetBaseUrl: client.wikiAssetBaseUrl }), `【洛克商店】shop_id=${targetShopId}`);
|
|
2078
2457
|
});
|
|
2079
2458
|
ctx.command('洛克').subcommand('.好友关系 <userIds:string>', '查询好友关系')
|
|
2080
2459
|
.alias('洛克好友关系')
|
|
@@ -2089,15 +2468,45 @@ function register(deps) {
|
|
|
2089
2468
|
return `好友关系查询失败:${client.getLastErrorBrief()}`;
|
|
2090
2469
|
await sendImage(deps, session, 'friendship', buildFriendshipRenderData(res, userIds), `【好友关系】${userIds}`);
|
|
2091
2470
|
});
|
|
2092
|
-
ctx.command('订阅家园菜园 [
|
|
2471
|
+
ctx.command('订阅家园菜园 [args:text]', '订阅指定 UID 的家园菜园成熟提醒')
|
|
2472
|
+
.userFields(['authority'])
|
|
2473
|
+
.action(async ({ session }, args = '') => {
|
|
2474
|
+
const parsed = parseHomeSubscribeArgs(args);
|
|
2475
|
+
return subscribeHome(deps, session, parsed.uid, 'garden', parsed.mentionAll);
|
|
2476
|
+
});
|
|
2477
|
+
ctx.command('订阅家园灵感 [args:text]', '订阅指定 UID 的家园精灵灵感完成提醒')
|
|
2093
2478
|
.userFields(['authority'])
|
|
2094
|
-
.action(async ({ session },
|
|
2095
|
-
|
|
2479
|
+
.action(async ({ session }, args = '') => {
|
|
2480
|
+
const parsed = parseHomeSubscribeArgs(args);
|
|
2481
|
+
return subscribeHome(deps, session, parsed.uid, 'inspiration', parsed.mentionAll);
|
|
2482
|
+
});
|
|
2483
|
+
ctx.command('订阅家园生蛋 [args:text]', '订阅指定 UID 的家园精灵生蛋提醒')
|
|
2096
2484
|
.userFields(['authority'])
|
|
2097
|
-
.action(async ({ session },
|
|
2098
|
-
|
|
2485
|
+
.action(async ({ session }, args = '') => {
|
|
2486
|
+
const parsed = parseHomeSubscribeArgs(args);
|
|
2487
|
+
return subscribeHome(deps, session, parsed.uid, 'egg', parsed.mentionAll);
|
|
2488
|
+
});
|
|
2489
|
+
// 查看当前会话的家园订阅列表。
|
|
2490
|
+
ctx.command('我的家园订阅', '查看当前会话的家园订阅列表')
|
|
2099
2491
|
.userFields(['authority'])
|
|
2100
|
-
.action(async ({ session }
|
|
2492
|
+
.action(async ({ session }) => {
|
|
2493
|
+
const target = sessionTarget(session);
|
|
2494
|
+
const kindLabel = { garden: '菜园', inspiration: '灵感', egg: '生蛋' };
|
|
2495
|
+
const subs = Object.values(deps.homeSubMgr.getAll()).filter(sub => sub.platform === target.platform
|
|
2496
|
+
&& (sub.channel_id || '') === (target.channelId || '')
|
|
2497
|
+
&& (sub.user_id || '') === (target.userId || ''));
|
|
2498
|
+
if (!subs.length)
|
|
2499
|
+
return (0, permissions_1.isDirectSession)(session) ? '你当前没有家园订阅。' : '本群当前没有家园订阅。';
|
|
2500
|
+
const formatTime = (ts) => (ts ? new Date(ts * 1000).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }) : '从未');
|
|
2501
|
+
const lines = [`当前家园订阅(共 ${subs.length} 个):`, ''];
|
|
2502
|
+
for (const sub of subs) {
|
|
2503
|
+
const mentionText = sub.mention_all && !sub.user_id ? ',命中后 @全体' : '';
|
|
2504
|
+
lines.push(`UID ${sub.uid}(${kindLabel[sub.kind] || sub.kind}${mentionText}):上次检查 ${formatTime(sub.last_check_time)},上次推送 ${formatTime(sub.last_push_time)}`);
|
|
2505
|
+
}
|
|
2506
|
+
lines.push('');
|
|
2507
|
+
lines.push('发送 取消订阅家园 [菜园/灵感/生蛋] [UID] 取消订阅');
|
|
2508
|
+
return lines.join('\n');
|
|
2509
|
+
});
|
|
2101
2510
|
ctx.command('取消订阅家园 [kind:string] [uid:string]', '取消当前会话的家园订阅')
|
|
2102
2511
|
.userFields(['authority'])
|
|
2103
2512
|
.action(async ({ session }, kind = '全部', uid = '') => {
|