koishi-plugin-rocom 1.0.11 → 1.0.13
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/client.d.ts +17 -1
- package/lib/client.js +121 -21
- package/lib/commands/merchant.js +409 -61
- package/lib/commands/query.js +95 -27
- package/lib/index.d.ts +4 -0
- package/lib/index.js +600 -127
- package/lib/render-templates/home/img/rocomuid/a_title.png +0 -0
- package/lib/render-templates/home/img/rocomuid/banner_bg.png +0 -0
- package/lib/render-templates/home/img/rocomuid/bg.jpg +0 -0
- package/lib/render-templates/home/img/rocomuid/img_head.png +0 -0
- package/lib/render-templates/home/img/rocomuid/jindu_bar.png +0 -0
- package/lib/render-templates/home/img/rocomuid/jindu_tc.png +0 -0
- package/lib/render-templates/home/img/rocomuid/level_icon.png +0 -0
- package/lib/render-templates/home/img/rocomuid/pet_bg.png +0 -0
- package/lib/render-templates/home/img/rocomuid/plant_bg.png +0 -0
- package/lib/render-templates/home/img/rocomuid/star_1.png +0 -0
- package/lib/render-templates/home/img/rocomuid/star_8.png +0 -0
- package/lib/render-templates/home/img/rocomuid/star_9.png +0 -0
- package/lib/render-templates/home/img/rocomuid/title_fg.png +0 -0
- package/lib/render-templates/home/img/rocomuid/top_bg.png +0 -0
- package/lib/render-templates/home/img/rocomuid/touxiang_mask.png +0 -0
- package/lib/render-templates/home/index.html +81 -97
- package/lib/render-templates/home/style.css +316 -375
- package/lib/render-templates/yuanxing-shangren/CHANGELOG.md +138 -0
- package/lib/render-templates/yuanxing-shangren/README.md +86 -0
- package/lib/render-templates/yuanxing-shangren/img/coin.png +0 -0
- package/lib/render-templates/yuanxing-shangren/img//345/272/225/351/203/250/344/277/241/346/201/257/346/241/206.png +0 -0
- package/lib/render-templates/yuanxing-shangren/img//346/240/207/351/242/230.png +0 -0
- package/lib/render-templates/yuanxing-shangren/img//347/203/255/351/224/200.png +0 -0
- package/lib/render-templates/yuanxing-shangren/img//347/274/226/345/217/267/350/203/214/346/231/257/346/241/206.png +0 -0
- package/lib/render-templates/yuanxing-shangren/index.html +233 -148
- package/lib/render-templates/yuanxing-shangren/index.html.backup +356 -0
- package/lib/render-templates/yuanxing-shangren/merchant.html +461 -0
- package/lib/render-templates/yuanxing-shangren/style.css +201 -256
- package/lib/render-templates/yuanxing-shangren/today.html +461 -0
- package/lib/render-templates/yuanxing-shangren/today.style.css +366 -0
- package/lib/render.js +11 -4
- package/lib/subscription-send.js +4 -5
- package/lib/ttf/rocom_skill_origin.ttf +0 -0
- package/lib/ttf//351/200/240/345/255/227/345/267/245/346/210/277/345/220/257/351/273/221/344/275/223.ttf +0 -0
- package/lib/types.d.ts +4 -0
- package/package.json +1 -1
package/lib/commands/query.js
CHANGED
|
@@ -258,16 +258,28 @@ function normalizeDurationSeconds(value) {
|
|
|
258
258
|
function formatHomeRemaining(targetTs, nowTs = Math.floor(Date.now() / 1000)) {
|
|
259
259
|
if (!targetTs)
|
|
260
260
|
return '未开始';
|
|
261
|
-
|
|
262
|
-
if (remain <= 0)
|
|
261
|
+
if (nowTs >= targetTs)
|
|
263
262
|
return '已完成';
|
|
264
|
-
const
|
|
263
|
+
const remain = Math.max(0, targetTs - nowTs);
|
|
264
|
+
const days = Math.floor(remain / 86400);
|
|
265
|
+
const hours = Math.floor((remain % 86400) / 3600);
|
|
265
266
|
const minutes = Math.floor((remain % 3600) / 60);
|
|
266
|
-
|
|
267
|
-
|
|
267
|
+
const seconds = remain % 60;
|
|
268
|
+
if (days > 0)
|
|
269
|
+
return hours > 0 ? `${days}天${hours}小时` : `${days}天`;
|
|
268
270
|
if (hours > 0)
|
|
269
271
|
return `${hours}小时${minutes}分钟`;
|
|
270
|
-
|
|
272
|
+
if (minutes > 0)
|
|
273
|
+
return `${minutes}分${seconds}秒`;
|
|
274
|
+
return `${seconds}秒`;
|
|
275
|
+
}
|
|
276
|
+
function formatEggRemaining(targetTs, nowTs = Math.floor(Date.now() / 1000)) {
|
|
277
|
+
if (!targetTs || nowTs >= targetTs)
|
|
278
|
+
return '0分钟';
|
|
279
|
+
const remain = Math.max(0, targetTs - nowTs);
|
|
280
|
+
const totalHours = Math.floor(remain / 3600);
|
|
281
|
+
const minutes = Math.floor((remain % 3600) / 60);
|
|
282
|
+
return `${totalHours}小时${minutes}分钟`;
|
|
271
283
|
}
|
|
272
284
|
function homeInfoPayload(res) {
|
|
273
285
|
const payload = res || {};
|
|
@@ -815,7 +827,7 @@ function panelPetDetailData(uid, pet, updatedAtText) {
|
|
|
815
827
|
};
|
|
816
828
|
}
|
|
817
829
|
async function refreshPanelPets(deps, uid, userId = '') {
|
|
818
|
-
const res = await deps.client.ingameHomeInfo(deps.ctx, uid, 20000);
|
|
830
|
+
const res = await deps.client.ingameHomeInfo(deps.ctx, uid, { waitMs: 20000, timeoutMs: 30000 });
|
|
819
831
|
if (res) {
|
|
820
832
|
const homeInfo = homeInfoPayload(res);
|
|
821
833
|
const pets = buildPanelPetList(homeInfo);
|
|
@@ -848,7 +860,7 @@ function formatPanelUpdatedAt(ts) {
|
|
|
848
860
|
return new Date().toLocaleString('zh-CN');
|
|
849
861
|
return new Date(value * 1000).toLocaleString('zh-CN');
|
|
850
862
|
}
|
|
851
|
-
function extractHomePet(raw, index, guard = false) {
|
|
863
|
+
function extractHomePet(deps, raw, index, guard = false) {
|
|
852
864
|
if (!raw || typeof raw !== 'object')
|
|
853
865
|
return null;
|
|
854
866
|
const homePet = raw.home_pet_info && typeof raw.home_pet_info === 'object' ? raw.home_pet_info : raw;
|
|
@@ -856,31 +868,64 @@ function extractHomePet(raw, index, guard = false) {
|
|
|
856
868
|
const petId = homePet.pet_cfg_id || homePet.pet_id || homePet.pet_base_id || raw.pet_cfg_id || raw.pet_id || raw.id;
|
|
857
869
|
if (['', '0'].includes(String(petId || '0')) && !guard)
|
|
858
870
|
return null;
|
|
859
|
-
const feedInfo = homePet.feed_info && typeof homePet.feed_info === 'object' ? homePet.feed_info : {};
|
|
860
|
-
const beginTime = normalizeEpochSeconds(feedInfo.begin_time);
|
|
861
|
-
const timeCost = normalizeDurationSeconds(feedInfo.time_cost);
|
|
862
|
-
let readyAt = normalizeEpochSeconds(homePet.pet_rip_time || raw.pet_rip_time || raw.rip_time);
|
|
863
|
-
if (!readyAt && beginTime && timeCost)
|
|
864
|
-
readyAt = beginTime + timeCost;
|
|
865
871
|
const nowTs = Math.floor(Date.now() / 1000);
|
|
866
|
-
const
|
|
867
|
-
const
|
|
868
|
-
const
|
|
869
|
-
const
|
|
870
|
-
const
|
|
872
|
+
const hasEgg = Boolean(raw.have_egg);
|
|
873
|
+
const predictedEggTime = normalizeEpochSeconds(raw.predicted_egg_time);
|
|
874
|
+
const eggReady = hasEgg || (predictedEggTime > 0 && nowTs >= predictedEggTime);
|
|
875
|
+
const feedRound = Number(homePet.feed_round || raw.feed_round || 0) || 0;
|
|
876
|
+
const gender = Number(display.gender || raw.gender || 0) || 0;
|
|
877
|
+
const mutationType = Number(display.mutation_type || raw.mutation_type || homePet.mutation_type || 0) || 0;
|
|
878
|
+
const isMale = gender === 1;
|
|
879
|
+
const status = homePet.status ?? raw.status;
|
|
880
|
+
const isGuard = guard || Boolean(raw.is_guard || raw.guard) || ['2', 'guard', '守卫'].includes(String(status).toLowerCase());
|
|
881
|
+
const hasInspiration = feedRound > 0;
|
|
882
|
+
const inspireReady = hasInspiration;
|
|
883
|
+
const statusText = isGuard && !hasInspiration ? '守卫中'
|
|
884
|
+
: (inspireReady ? '可收取灵感'
|
|
885
|
+
: (hasInspiration ? '灵感收集中'
|
|
886
|
+
: '未喂食'));
|
|
887
|
+
const statusClass = isGuard && !hasInspiration ? 'guard'
|
|
888
|
+
: (eggReady ? 'ready'
|
|
889
|
+
: (inspireReady ? 'progress'
|
|
890
|
+
: (hasInspiration ? 'progress'
|
|
891
|
+
: 'idle')));
|
|
892
|
+
let note;
|
|
893
|
+
if (isGuard && String(petId) === '0') {
|
|
894
|
+
note = '家园守卫位';
|
|
895
|
+
}
|
|
896
|
+
else if (eggReady) {
|
|
897
|
+
note = '可收取';
|
|
898
|
+
}
|
|
899
|
+
else if (predictedEggTime > 0) {
|
|
900
|
+
note = `${formatEggRemaining(predictedEggTime, nowTs)}后生蛋`;
|
|
901
|
+
}
|
|
902
|
+
else if (feedRound > 0) {
|
|
903
|
+
note = isMale ? '' : '等待生蛋';
|
|
904
|
+
}
|
|
905
|
+
else if (isGuard) {
|
|
906
|
+
note = '家园守卫位';
|
|
907
|
+
}
|
|
908
|
+
else {
|
|
909
|
+
note = '未喂食';
|
|
910
|
+
}
|
|
871
911
|
return {
|
|
872
912
|
id: String(petId || ''),
|
|
873
913
|
pos: raw.pos || raw.position || index + 1,
|
|
874
914
|
name: String(homePet.name || homePet.pet_name || raw.name || raw.pet_name || `精灵 ${petId || ''}`),
|
|
875
915
|
level: display.level || raw.level || homePet.level || '--',
|
|
876
916
|
iconUrl: homePetIcon(petId, raw.icon_url || raw.pet_img_url || raw.petIcon || ''),
|
|
877
|
-
|
|
917
|
+
starIconUrl: [1, 8, 9].includes(mutationType)
|
|
918
|
+
? deps.renderer.resourceUrl(`render-templates/home/img/rocomuid/star_${mutationType}.png`)
|
|
919
|
+
: '',
|
|
920
|
+
badge: isGuard ? '守' : (hasEgg ? '蛋' : ''),
|
|
921
|
+
mutationType,
|
|
878
922
|
isGuard,
|
|
879
923
|
statusText,
|
|
880
924
|
statusClass,
|
|
881
|
-
note
|
|
882
|
-
inspireReady,
|
|
883
|
-
readyAt,
|
|
925
|
+
note,
|
|
926
|
+
inspireReady: eggReady,
|
|
927
|
+
readyAt: predictedEggTime || 0,
|
|
928
|
+
gender,
|
|
884
929
|
};
|
|
885
930
|
}
|
|
886
931
|
function homePetSources(homeInfo) {
|
|
@@ -998,7 +1043,7 @@ function buildHomeRenderData(deps, res, uid) {
|
|
|
998
1043
|
const indoorPets = [];
|
|
999
1044
|
const guardPets = [];
|
|
1000
1045
|
indoorSources.forEach((raw, index) => {
|
|
1001
|
-
const item = extractHomePet(raw, index);
|
|
1046
|
+
const item = extractHomePet(deps, raw, index);
|
|
1002
1047
|
if (!item)
|
|
1003
1048
|
return;
|
|
1004
1049
|
if (item.isGuard)
|
|
@@ -1007,10 +1052,22 @@ function buildHomeRenderData(deps, res, uid) {
|
|
|
1007
1052
|
indoorPets.push(item);
|
|
1008
1053
|
});
|
|
1009
1054
|
guardSources.forEach((raw, index) => {
|
|
1010
|
-
const item = extractHomePet(raw, index, true);
|
|
1055
|
+
const item = extractHomePet(deps, raw, index, true);
|
|
1011
1056
|
if (item)
|
|
1012
1057
|
guardPets.push(item);
|
|
1013
1058
|
});
|
|
1059
|
+
indoorPets.sort((a, b) => {
|
|
1060
|
+
if (a.gender === 2 && b.gender !== 2)
|
|
1061
|
+
return -1;
|
|
1062
|
+
if (a.gender !== 2 && b.gender === 2)
|
|
1063
|
+
return 1;
|
|
1064
|
+
if (a.gender === 2) {
|
|
1065
|
+
const ta = a.readyAt || Number.MAX_SAFE_INTEGER;
|
|
1066
|
+
const tb = b.readyAt || Number.MAX_SAFE_INTEGER;
|
|
1067
|
+
return ta - tb;
|
|
1068
|
+
}
|
|
1069
|
+
return 0;
|
|
1070
|
+
});
|
|
1014
1071
|
const gardenPlots = extractHomePlants(deps, homeInfo);
|
|
1015
1072
|
const createdAt = normalizeEpochSeconds(res?.meta?.created_at);
|
|
1016
1073
|
return {
|
|
@@ -1268,7 +1325,7 @@ async function checkHomeSubscriptions(deps) {
|
|
|
1268
1325
|
continue;
|
|
1269
1326
|
checkedCount++;
|
|
1270
1327
|
if (!cache.has(sub.uid)) {
|
|
1271
|
-
cache.set(sub.uid, await deps.client.ingameHomeInfo(deps.ctx, sub.uid));
|
|
1328
|
+
cache.set(sub.uid, await deps.client.ingameHomeInfo(deps.ctx, sub.uid, { timeoutMs: 30000 }));
|
|
1272
1329
|
}
|
|
1273
1330
|
const res = cache.get(sub.uid);
|
|
1274
1331
|
if (!res)
|
|
@@ -1757,7 +1814,18 @@ function register(deps) {
|
|
|
1757
1814
|
}
|
|
1758
1815
|
if (!targetUid)
|
|
1759
1816
|
return '请提供玩家 UID,或先完成绑定后使用 洛克.家园。';
|
|
1760
|
-
|
|
1817
|
+
let queuedNotified = false;
|
|
1818
|
+
const res = await client.ingameHomeInfo(ctx, targetUid, {
|
|
1819
|
+
waitMs: deps.config.homeQueryWaitMs,
|
|
1820
|
+
intervalMs: deps.config.homeQueryPollIntervalMs,
|
|
1821
|
+
timeoutMs: deps.config.homeQueryTimeoutMs,
|
|
1822
|
+
onQueued: async () => {
|
|
1823
|
+
if (queuedNotified)
|
|
1824
|
+
return;
|
|
1825
|
+
queuedNotified = true;
|
|
1826
|
+
await session?.send?.(`UID ${targetUid} 的家园查询已进入队列,正在等待游戏侧返回,请稍候…`);
|
|
1827
|
+
},
|
|
1828
|
+
});
|
|
1761
1829
|
if (!res)
|
|
1762
1830
|
return `家园查询失败:${client.getLastErrorBrief()}`;
|
|
1763
1831
|
await sendImage(deps, session, 'home', buildHomeRenderData(deps, res, targetUid), `【洛克家园】UID ${targetUid}`);
|
package/lib/index.d.ts
CHANGED
|
@@ -12,12 +12,16 @@ export interface Config {
|
|
|
12
12
|
autoRefreshTime: string[];
|
|
13
13
|
merchantSubscriptionEnabled: boolean;
|
|
14
14
|
merchantSubscriptionItems: string[];
|
|
15
|
+
merchantUiStyle: 'new' | 'old';
|
|
15
16
|
merchantPrivateSubscriptionEnabled: boolean;
|
|
16
17
|
merchantCheckMode: 'interval' | 'times';
|
|
17
18
|
merchantCheckInterval: number;
|
|
18
19
|
merchantCheckTimes: string[];
|
|
19
20
|
homeSubscriptionEnabled: boolean;
|
|
20
21
|
homeSubscriptionIntervalMinutes: number;
|
|
22
|
+
homeQueryWaitMs: number;
|
|
23
|
+
homeQueryPollIntervalMs: number;
|
|
24
|
+
homeQueryTimeoutMs: number;
|
|
21
25
|
imageCompressionEnabled: boolean;
|
|
22
26
|
imageCompressionMinBytes: number;
|
|
23
27
|
imageCompressionLevel: number;
|