koishi-plugin-warframe 1.16.1 → 1.16.3
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 +39 -9
- package/lib/index.js +328 -237
- package/lib/index.tsbuildinfo +1 -1
- package/lib/warframe/assets/en.json +1 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1542,15 +1542,6 @@ function levenshtein(a, b) {
|
|
|
1542
1542
|
return dp[a.length][b.length];
|
|
1543
1543
|
}
|
|
1544
1544
|
__name(levenshtein, "levenshtein");
|
|
1545
|
-
function tokenSimilarity(a, b) {
|
|
1546
|
-
const tokenize = /* @__PURE__ */ __name((s) => s.replace(/[^\w\u4E00-\u9FA5]+/g, " ").split(/\s+/).filter(Boolean), "tokenize");
|
|
1547
|
-
const A = new Set(tokenize(a));
|
|
1548
|
-
const B = new Set(tokenize(b));
|
|
1549
|
-
const intersection = [...A].filter((x) => B.has(x)).length;
|
|
1550
|
-
const union = (/* @__PURE__ */ new Set([...A, ...B])).size;
|
|
1551
|
-
return intersection / union;
|
|
1552
|
-
}
|
|
1553
|
-
__name(tokenSimilarity, "tokenSimilarity");
|
|
1554
1545
|
|
|
1555
1546
|
// src/warframe/utils/time.ts
|
|
1556
1547
|
function toTimeStamp(timeStr) {
|
|
@@ -1619,7 +1610,7 @@ async function getHotRivenWeapons2() {
|
|
|
1619
1610
|
__name(getHotRivenWeapons2, "getHotRivenWeapons");
|
|
1620
1611
|
|
|
1621
1612
|
// src/warframe/services/wf-service/wf-service.alert.ts
|
|
1622
|
-
var
|
|
1613
|
+
var import_warframe_public_export_plus6 = require("warframe-public-export-plus");
|
|
1623
1614
|
|
|
1624
1615
|
// src/warframe/assets/index.ts
|
|
1625
1616
|
var {
|
|
@@ -2098,6 +2089,9 @@ async function globalWorldStateFactory(json) {
|
|
|
2098
2089
|
__name(globalWorldStateFactory, "globalWorldStateFactory");
|
|
2099
2090
|
var globalWorldState = createAsyncCache(globalWorldStateFactory, -1);
|
|
2100
2091
|
|
|
2092
|
+
// src/warframe/infrastructure/wf/alert-adapter.ts
|
|
2093
|
+
var import_warframe_public_export_plus5 = require("warframe-public-export-plus");
|
|
2094
|
+
|
|
2101
2095
|
// src/warframe/infrastructure/wf/bounty-adapter.ts
|
|
2102
2096
|
var import_warframe_public_export_plus4 = require("warframe-public-export-plus");
|
|
2103
2097
|
var bountyLocationTag = {
|
|
@@ -2506,6 +2500,56 @@ function adaptOracleBountyBoard(location, cycle) {
|
|
|
2506
2500
|
}
|
|
2507
2501
|
__name(adaptOracleBountyBoard, "adaptOracleBountyBoard");
|
|
2508
2502
|
|
|
2503
|
+
// src/warframe/infrastructure/wf/alert-adapter.ts
|
|
2504
|
+
var alertTranslations = createAsyncCache(async () => {
|
|
2505
|
+
const { default: worldstateData } = await import("warframe-worldstate-data");
|
|
2506
|
+
const { languageString } = await import("warframe-worldstate-data/utilities");
|
|
2507
|
+
const entries = Object.entries({ ...dictZhExtra, ...import_warframe_public_export_plus5.dict_zh });
|
|
2508
|
+
const byKey = new Map(entries.map(([key, value]) => [key.toLowerCase(), value]));
|
|
2509
|
+
const byEnglish = /* @__PURE__ */ new Map();
|
|
2510
|
+
for (const [key, english] of Object.entries({ ...dictEnExtra, ...import_warframe_public_export_plus5.dict_en })) {
|
|
2511
|
+
const chinese = byKey.get(key.toLowerCase());
|
|
2512
|
+
if (chinese) {
|
|
2513
|
+
byEnglish.set(english.toLowerCase(), chinese);
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
for (const [key, entry] of Object.entries(worldstateData.languages)) {
|
|
2517
|
+
const chinese = byKey.get(key.toLowerCase()) ?? worldstateData.zh?.languages[key]?.value;
|
|
2518
|
+
if (chinese && chinese !== entry.value) {
|
|
2519
|
+
byEnglish.set(entry.value.toLowerCase(), chinese);
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
const aliases2 = /* @__PURE__ */ new Map();
|
|
2523
|
+
for (const [key, chinese] of entries) {
|
|
2524
|
+
if (!/\/Alerts\/|\/[^/]*Alert(?:Title|Desc)$/i.test(key)) {
|
|
2525
|
+
continue;
|
|
2526
|
+
}
|
|
2527
|
+
const english = languageString(key, "en").toLowerCase();
|
|
2528
|
+
aliases2.set(english, aliases2.has(english) && aliases2.get(english) !== chinese ? void 0 : chinese);
|
|
2529
|
+
}
|
|
2530
|
+
for (const [english, chinese] of aliases2) {
|
|
2531
|
+
if (chinese && !byEnglish.has(english)) {
|
|
2532
|
+
byEnglish.set(english, chinese);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return { byKey, byEnglish };
|
|
2536
|
+
}, -1);
|
|
2537
|
+
async function translateAlertText(source) {
|
|
2538
|
+
const { byKey, byEnglish } = await alertTranslations.get();
|
|
2539
|
+
const translated = byKey.get(source.toLowerCase()) ?? byEnglish.get(source.toLowerCase());
|
|
2540
|
+
if (translated) {
|
|
2541
|
+
return translated;
|
|
2542
|
+
}
|
|
2543
|
+
if (source.startsWith("/Lotus/")) {
|
|
2544
|
+
const itemName = resolveExportItemNameZh(source);
|
|
2545
|
+
if (itemName !== source.split("/").pop() && !itemName.startsWith("/Lotus/")) {
|
|
2546
|
+
return itemName;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
return source;
|
|
2550
|
+
}
|
|
2551
|
+
__name(translateAlertText, "translateAlertText");
|
|
2552
|
+
|
|
2509
2553
|
// src/warframe/services/wf-service/wf-service.alert.ts
|
|
2510
2554
|
var ALERT_TITLE_KEY = "/Lotus/Language/Menu/AlertPopup_Alert";
|
|
2511
2555
|
var ALERT_NIGHTMARE_KEY = "/Lotus/Language/Menu/NightmareModeName";
|
|
@@ -2517,13 +2561,14 @@ async function adaptAlerts(alerts = [], now = Date.now()) {
|
|
|
2517
2561
|
continue;
|
|
2518
2562
|
}
|
|
2519
2563
|
const mission = raw.mission ?? {};
|
|
2520
|
-
const typeKey = mission.typeKey
|
|
2564
|
+
const typeKey = mission.typeKey || mission.type || "";
|
|
2521
2565
|
const receivedType = await getMissionTypeKey(typeKey);
|
|
2522
|
-
const
|
|
2566
|
+
const missionType = import_warframe_public_export_plus6.ExportMissionTypes[typeKey] ?? import_warframe_public_export_plus6.ExportMissionTypes[receivedType];
|
|
2567
|
+
const nodeKey = mission.nodeKey || mission.node || "";
|
|
2523
2568
|
const solNodeKey = await getSolNodeKey(nodeKey);
|
|
2524
|
-
const region =
|
|
2525
|
-
const short = region ? regionToShort(region,
|
|
2526
|
-
name: nodeKey,
|
|
2569
|
+
const region = import_warframe_public_export_plus6.ExportRegions[nodeKey] ?? import_warframe_public_export_plus6.ExportRegions[solNodeKey];
|
|
2570
|
+
const short = region ? regionToShort(region, import_warframe_public_export_plus6.dict_zh) : {
|
|
2571
|
+
name: await translateAlertText(nodeKey),
|
|
2527
2572
|
system: "",
|
|
2528
2573
|
type: "",
|
|
2529
2574
|
faction: "",
|
|
@@ -2532,19 +2577,26 @@ async function adaptAlerts(alerts = [], now = Date.now()) {
|
|
|
2532
2577
|
};
|
|
2533
2578
|
const reward = mission.reward;
|
|
2534
2579
|
const rewards = [];
|
|
2580
|
+
const mirroredItems = (reward?.countedItems ?? []).filter((item) => item.uniqueName && item.count === 1).map((item) => [item.uniqueName, item.key, item.type]);
|
|
2535
2581
|
for (const item of reward?.items ?? []) {
|
|
2582
|
+
const mirrored = mirroredItems.findIndex((names) => names.includes(item));
|
|
2583
|
+
if (mirrored >= 0) {
|
|
2584
|
+
mirroredItems.splice(mirrored, 1);
|
|
2585
|
+
continue;
|
|
2586
|
+
}
|
|
2536
2587
|
rewards.push({
|
|
2537
|
-
name:
|
|
2588
|
+
name: await translateAlertText(item),
|
|
2538
2589
|
count: 1
|
|
2539
2590
|
});
|
|
2540
2591
|
}
|
|
2541
2592
|
for (const item of reward?.countedItems ?? []) {
|
|
2542
|
-
const source = item.key
|
|
2593
|
+
const source = item.uniqueName || item.key || item.type || "";
|
|
2543
2594
|
if (!source) {
|
|
2544
2595
|
continue;
|
|
2545
2596
|
}
|
|
2597
|
+
const name2 = await translateAlertText(source);
|
|
2546
2598
|
rewards.push({
|
|
2547
|
-
name: source
|
|
2599
|
+
name: name2 === source ? await translateAlertText(item.key || item.type || source) : name2,
|
|
2548
2600
|
count: item.count ?? 1
|
|
2549
2601
|
});
|
|
2550
2602
|
}
|
|
@@ -2554,9 +2606,10 @@ async function adaptAlerts(alerts = [], now = Date.now()) {
|
|
|
2554
2606
|
count: 1
|
|
2555
2607
|
});
|
|
2556
2608
|
}
|
|
2557
|
-
const nightmare = mission.nightmare ?
|
|
2609
|
+
const nightmare = mission.nightmare ? import_warframe_public_export_plus6.dict_zh[ALERT_NIGHTMARE_KEY] ?? dictZhExtra[ALERT_NIGHTMARE_KEY] : void 0;
|
|
2558
2610
|
adapted.push({
|
|
2559
|
-
|
|
2611
|
+
description: await translateAlertText(raw.description || mission.description || ""),
|
|
2612
|
+
type: import_warframe_public_export_plus6.dict_zh[missionType?.name ?? ""] ?? await translateAlertText(typeKey),
|
|
2560
2613
|
node: {
|
|
2561
2614
|
...short,
|
|
2562
2615
|
minLevel: mission.minEnemyLevel ?? 0,
|
|
@@ -2569,7 +2622,7 @@ async function adaptAlerts(alerts = [], now = Date.now()) {
|
|
|
2569
2622
|
});
|
|
2570
2623
|
}
|
|
2571
2624
|
return {
|
|
2572
|
-
title:
|
|
2625
|
+
title: import_warframe_public_export_plus6.dict_zh[ALERT_TITLE_KEY] ?? dictZhExtra[ALERT_TITLE_KEY] ?? ALERT_TITLE_KEY,
|
|
2573
2626
|
alerts: adapted
|
|
2574
2627
|
};
|
|
2575
2628
|
}
|
|
@@ -2592,7 +2645,7 @@ async function getAlerts() {
|
|
|
2592
2645
|
__name(getAlerts, "getAlerts");
|
|
2593
2646
|
|
|
2594
2647
|
// src/warframe/services/wf-service/wf-service.arbitration.ts
|
|
2595
|
-
var
|
|
2648
|
+
var import_warframe_public_export_plus7 = require("warframe-public-export-plus");
|
|
2596
2649
|
|
|
2597
2650
|
// src/warframe/data/wf/arbitrationSchedule.ts
|
|
2598
2651
|
var arbitrationSchedule = arbitrationScheduleText.split("\n").map((line) => line.split(",")).filter((arr) => arr.length === 2).map((arr) => {
|
|
@@ -2620,7 +2673,7 @@ function getArbitrations(day = 3) {
|
|
|
2620
2673
|
return {
|
|
2621
2674
|
ok: true,
|
|
2622
2675
|
data: weekArbys.filter((a) => arbyRewards[a.node]).map((a) => {
|
|
2623
|
-
const obj = regionToShort(
|
|
2676
|
+
const obj = regionToShort(import_warframe_public_export_plus7.ExportRegions[a.node], import_warframe_public_export_plus7.dict_zh);
|
|
2624
2677
|
return {
|
|
2625
2678
|
...obj,
|
|
2626
2679
|
time: new Date(a.time * 1e3).toLocaleString("zh-cn", {
|
|
@@ -2685,7 +2738,7 @@ async function getBounty(location) {
|
|
|
2685
2738
|
__name(getBounty, "getBounty");
|
|
2686
2739
|
|
|
2687
2740
|
// src/warframe/infrastructure/wf/calendar-adapter.ts
|
|
2688
|
-
var
|
|
2741
|
+
var import_warframe_public_export_plus8 = require("warframe-public-export-plus");
|
|
2689
2742
|
var CALENDAR_SEASON_HEADER_KEY = "/Lotus/Language/1999/CalendarSeasonHeader";
|
|
2690
2743
|
var CALENDAR_HEADER_KEY = "/Lotus/Language/1999/CalendarHeader";
|
|
2691
2744
|
var SEASON_KEYS = {
|
|
@@ -2722,7 +2775,7 @@ function calendarTimestampMs(value) {
|
|
|
2722
2775
|
}
|
|
2723
2776
|
__name(calendarTimestampMs, "calendarTimestampMs");
|
|
2724
2777
|
function translate(key, fallback = key) {
|
|
2725
|
-
return stripLotusMarkup(
|
|
2778
|
+
return stripLotusMarkup(import_warframe_public_export_plus8.dict_zh[key] ?? dictZhExtra[key] ?? fallback);
|
|
2726
2779
|
}
|
|
2727
2780
|
__name(translate, "translate");
|
|
2728
2781
|
function seasonLabel(season) {
|
|
@@ -2756,7 +2809,7 @@ function stripLotusMarkup(text) {
|
|
|
2756
2809
|
}
|
|
2757
2810
|
__name(stripLotusMarkup, "stripLotusMarkup");
|
|
2758
2811
|
function adaptChallenge(path) {
|
|
2759
|
-
const exported =
|
|
2812
|
+
const exported = import_warframe_public_export_plus8.ExportChallenges[path];
|
|
2760
2813
|
if (!exported?.name) {
|
|
2761
2814
|
return { name: pathLeaf(path) };
|
|
2762
2815
|
}
|
|
@@ -2800,7 +2853,7 @@ function plotCharacterName(id) {
|
|
|
2800
2853
|
}
|
|
2801
2854
|
for (const keyId of keyIds) {
|
|
2802
2855
|
const key = `/Lotus/Language/1999/Messenger${keyId}Name`;
|
|
2803
|
-
const text =
|
|
2856
|
+
const text = import_warframe_public_export_plus8.dict_zh[key] ?? dictZhExtra[key];
|
|
2804
2857
|
if (text) {
|
|
2805
2858
|
return stripLotusMarkup(text);
|
|
2806
2859
|
}
|
|
@@ -2890,14 +2943,14 @@ async function getCalendar() {
|
|
|
2890
2943
|
__name(getCalendar, "getCalendar");
|
|
2891
2944
|
|
|
2892
2945
|
// src/warframe/services/wf-service/wf-service.circuit.ts
|
|
2893
|
-
var
|
|
2946
|
+
var import_warframe_public_export_plus9 = require("warframe-public-export-plus");
|
|
2894
2947
|
function getCircuitWeek() {
|
|
2895
2948
|
const EPOCH = 1734307200 * 1e3;
|
|
2896
2949
|
const week = Math.trunc((Date.now() - EPOCH) / 6048e5);
|
|
2897
2950
|
const index1 = (week + 1) % incarnons.length;
|
|
2898
2951
|
const index2 = (week + 8) % warframes.length;
|
|
2899
|
-
const incarnons2 = incarnons.map((v) => v.map((i) =>
|
|
2900
|
-
const warframes2 = warframes.map((v) => v.map((i) =>
|
|
2952
|
+
const incarnons2 = incarnons.map((v) => v.map((i) => import_warframe_public_export_plus9.dict_zh[i]));
|
|
2953
|
+
const warframes2 = warframes.map((v) => v.map((i) => import_warframe_public_export_plus9.dict_zh[i]));
|
|
2901
2954
|
return {
|
|
2902
2955
|
currentIncarnons: index1,
|
|
2903
2956
|
currentWarframes: index2,
|
|
@@ -2940,10 +2993,10 @@ ${zariman}`;
|
|
|
2940
2993
|
__name(getEnvironment, "getEnvironment");
|
|
2941
2994
|
|
|
2942
2995
|
// src/warframe/services/wf-service/wf-service.event.ts
|
|
2943
|
-
var
|
|
2996
|
+
var import_warframe_public_export_plus10 = require("warframe-public-export-plus");
|
|
2944
2997
|
var EVENT_TITLE_KEY = "/Lotus/Language/Menu/WorldStatePanel_Event";
|
|
2945
2998
|
function translate2(key, fallback = key) {
|
|
2946
|
-
return stripLotusMarkup(
|
|
2999
|
+
return stripLotusMarkup(import_warframe_public_export_plus10.dict_zh[key] ?? dictZhExtra[key] ?? fallback);
|
|
2947
3000
|
}
|
|
2948
3001
|
__name(translate2, "translate");
|
|
2949
3002
|
function mongoDateMs2(value) {
|
|
@@ -3023,7 +3076,7 @@ function adaptEvents(rawEvents = [], now = Date.now()) {
|
|
|
3023
3076
|
const maximumScore = raw.Goal ?? 0;
|
|
3024
3077
|
const currentScore = raw.Count ?? 0;
|
|
3025
3078
|
const progress = maximumScore > 0 ? Math.min(1, Math.max(0, currentScore / maximumScore)) : typeof raw.HealthPct === "number" ? Math.min(1, Math.max(0, raw.HealthPct)) : void 0;
|
|
3026
|
-
const region = raw.Node &&
|
|
3079
|
+
const region = raw.Node && import_warframe_public_export_plus10.ExportRegions[raw.Node] ? regionToShort(import_warframe_public_export_plus10.ExportRegions[raw.Node], import_warframe_public_export_plus10.dict_zh) : void 0;
|
|
3027
3080
|
adapted.push({
|
|
3028
3081
|
id: raw._id?.$oid ?? raw._id?.$id ?? raw.Tag ?? name2,
|
|
3029
3082
|
name: name2,
|
|
@@ -3091,7 +3144,7 @@ async function getRailjackFissures() {
|
|
|
3091
3144
|
__name(getRailjackFissures, "getRailjackFissures");
|
|
3092
3145
|
|
|
3093
3146
|
// src/warframe/services/wf-service/wf-service.invasion.ts
|
|
3094
|
-
var
|
|
3147
|
+
var import_warframe_public_export_plus11 = require("warframe-public-export-plus");
|
|
3095
3148
|
var INVASION_TITLE_KEY = "/Lotus/Language/Menu/WorldStatePanel_Invasions";
|
|
3096
3149
|
var INFESTED_INVASION_BOSS_TAG = "/Lotus/Language/Menu/InfestedInvasionBoss";
|
|
3097
3150
|
function invasionProgress(count, goal, vsInfested) {
|
|
@@ -3121,9 +3174,9 @@ function invasionSide(faction, reward) {
|
|
|
3121
3174
|
})),
|
|
3122
3175
|
...reward.credits && reward.credits > 0 ? [{ name: resolveExportItemNameZh(`/${reward.credits}Credits`), count: 1 }] : []
|
|
3123
3176
|
];
|
|
3124
|
-
const nameKey = faction ?
|
|
3177
|
+
const nameKey = faction ? import_warframe_public_export_plus11.ExportFactions[faction]?.name ?? faction : void 0;
|
|
3125
3178
|
return {
|
|
3126
|
-
faction: nameKey ?
|
|
3179
|
+
faction: nameKey ? import_warframe_public_export_plus11.dict_zh[nameKey] ?? dictZhExtra[nameKey] ?? "" : "",
|
|
3127
3180
|
tone: invasionTone(faction),
|
|
3128
3181
|
rewards
|
|
3129
3182
|
};
|
|
@@ -3144,9 +3197,9 @@ async function adaptInvasions(rawInvasions) {
|
|
|
3144
3197
|
raw.DefenderMissionInfo?.faction
|
|
3145
3198
|
].some((faction) => /infest/i.test(faction ?? ""));
|
|
3146
3199
|
const nodeId = raw.Node;
|
|
3147
|
-
const solNodeKey =
|
|
3148
|
-
const region = solNodeKey ?
|
|
3149
|
-
const short = region ? regionToShort(region,
|
|
3200
|
+
const solNodeKey = import_warframe_public_export_plus11.ExportRegions[nodeId] ? nodeId : await getSolNodeKey(nodeId);
|
|
3201
|
+
const region = solNodeKey ? import_warframe_public_export_plus11.ExportRegions[solNodeKey] : void 0;
|
|
3202
|
+
const short = region ? regionToShort(region, import_warframe_public_export_plus11.dict_zh) : void 0;
|
|
3150
3203
|
const locTag = raw.LocTag ?? "";
|
|
3151
3204
|
drafts.push({
|
|
3152
3205
|
id: raw._id?.$oid ?? raw._id?.$id ?? raw.Node,
|
|
@@ -3154,7 +3207,7 @@ async function adaptInvasions(rawInvasions) {
|
|
|
3154
3207
|
node: short?.name ?? "",
|
|
3155
3208
|
systemIndex: region?.systemIndex ?? Number.MAX_SAFE_INTEGER,
|
|
3156
3209
|
locTag,
|
|
3157
|
-
campaign: locTag ?
|
|
3210
|
+
campaign: locTag ? import_warframe_public_export_plus11.dict_zh[locTag] ?? dictZhExtra[locTag] ?? await translateLanguageString(locTag) : "",
|
|
3158
3211
|
count,
|
|
3159
3212
|
goal,
|
|
3160
3213
|
attacker: invasionSide(raw.DefenderMissionInfo?.faction ?? raw.Faction, raw.AttackerReward),
|
|
@@ -3169,7 +3222,7 @@ async function adaptInvasions(rawInvasions) {
|
|
|
3169
3222
|
groups.set(key, [...groups.get(key) ?? [], draft]);
|
|
3170
3223
|
}
|
|
3171
3224
|
return {
|
|
3172
|
-
title:
|
|
3225
|
+
title: import_warframe_public_export_plus11.dict_zh[INVASION_TITLE_KEY] ?? dictZhExtra[INVASION_TITLE_KEY] ?? INVASION_TITLE_KEY,
|
|
3173
3226
|
planets: [...groups.values()].sort((a, b) => a[0].systemIndex - b[0].systemIndex).map((list) => {
|
|
3174
3227
|
const boss = list.filter((draft) => draft.locTag === INFESTED_INVASION_BOSS_TAG);
|
|
3175
3228
|
const ordered = [...boss, ...list.filter((draft) => draft.locTag !== INFESTED_INVASION_BOSS_TAG)];
|
|
@@ -3224,7 +3277,7 @@ async function getInvasions() {
|
|
|
3224
3277
|
__name(getInvasions, "getInvasions");
|
|
3225
3278
|
|
|
3226
3279
|
// src/warframe/infrastructure/wf/nightwave-adapter.ts
|
|
3227
|
-
var
|
|
3280
|
+
var import_warframe_public_export_plus12 = require("warframe-public-export-plus");
|
|
3228
3281
|
var RADIO_LEGION_TITLE_KEY = "/Lotus/Language/Syndicates/RadioLegionTitle";
|
|
3229
3282
|
function timestampMs(value) {
|
|
3230
3283
|
const raw = value?.$date?.$numberLong;
|
|
@@ -3240,11 +3293,11 @@ function remainingLabel(expiry, now) {
|
|
|
3240
3293
|
}
|
|
3241
3294
|
__name(remainingLabel, "remainingLabel");
|
|
3242
3295
|
function translate3(key) {
|
|
3243
|
-
return
|
|
3296
|
+
return import_warframe_public_export_plus12.dict_zh[key] ?? dictZhExtra[key] ?? key;
|
|
3244
3297
|
}
|
|
3245
3298
|
__name(translate3, "translate");
|
|
3246
3299
|
function seasonTitle(affiliationTag) {
|
|
3247
|
-
const syndicate =
|
|
3300
|
+
const syndicate = import_warframe_public_export_plus12.ExportSyndicates[affiliationTag];
|
|
3248
3301
|
if (syndicate?.name) {
|
|
3249
3302
|
return translate3(syndicate.name);
|
|
3250
3303
|
}
|
|
@@ -3279,7 +3332,7 @@ function adaptChallenge2(raw, now) {
|
|
|
3279
3332
|
}
|
|
3280
3333
|
const kind = classifyChallenge(path, raw);
|
|
3281
3334
|
const remaining = remainingLabel(expiry, now);
|
|
3282
|
-
const exported =
|
|
3335
|
+
const exported = import_warframe_public_export_plus12.ExportNightwave.challenges[path];
|
|
3283
3336
|
if (!exported) {
|
|
3284
3337
|
return {
|
|
3285
3338
|
name: challengeFallbackName(path),
|
|
@@ -3337,12 +3390,12 @@ async function getNightwave() {
|
|
|
3337
3390
|
__name(getNightwave, "getNightwave");
|
|
3338
3391
|
|
|
3339
3392
|
// src/warframe/data/wf/relics.ts
|
|
3340
|
-
var
|
|
3393
|
+
var import_warframe_public_export_plus13 = require("warframe-public-export-plus");
|
|
3341
3394
|
var relics = (() => {
|
|
3342
3395
|
const result = {};
|
|
3343
|
-
for (const key in
|
|
3344
|
-
const exportRelic =
|
|
3345
|
-
const exportRewards =
|
|
3396
|
+
for (const key in import_warframe_public_export_plus13.ExportRelics) {
|
|
3397
|
+
const exportRelic = import_warframe_public_export_plus13.ExportRelics[key];
|
|
3398
|
+
const exportRewards = import_warframe_public_export_plus13.ExportRewards[exportRelic.rewardManifest];
|
|
3346
3399
|
const era = `/Lotus/Language/Relics/Era_${exportRelic.era.toUpperCase()}`;
|
|
3347
3400
|
const relicKey = normalizeName(exportRelic.era + exportRelic.category);
|
|
3348
3401
|
const rewards = (exportRewards[0] ?? []).map((r) => {
|
|
@@ -3410,7 +3463,7 @@ async function getRelic(input) {
|
|
|
3410
3463
|
__name(getRelic, "getRelic");
|
|
3411
3464
|
|
|
3412
3465
|
// src/warframe/infrastructure/wf/riven-export-adapter.ts
|
|
3413
|
-
var
|
|
3466
|
+
var import_warframe_public_export_plus14 = require("warframe-public-export-plus");
|
|
3414
3467
|
var rivenDefinitionTypes = {
|
|
3415
3468
|
LotusRifleRandomModRare: "Rifle",
|
|
3416
3469
|
LotusShotgunRandomModRare: "Shotgun",
|
|
@@ -3504,7 +3557,7 @@ function adaptRivenDefinitions(definitions) {
|
|
|
3504
3557
|
const englishName = tag === "WeaponMeleeDamageMod" ? "Damage" : tag === "WeaponFireRateMod" ? "Fire Rate / Attack Speed" : templateName;
|
|
3505
3558
|
const name2 = splicedNames[tag] ?? traditionalNames[tag] ?? englishName;
|
|
3506
3559
|
const unit = tag.includes("FactionDamage") ? "multiply" : raw.locTag.includes("%") ? "percent" : /\|s\b/.test(raw.locTag) ? "seconds" : "";
|
|
3507
|
-
const metadata =
|
|
3560
|
+
const metadata = import_warframe_public_export_plus14.ExportUpgrades[definition.uniqueName]?.upgradeEntries?.find((x) => x.tag === tag);
|
|
3508
3561
|
const baseValue = raw.value * 90 * (unit === "percent" ? 100 : 1) * (raw.reverseValueSymbol ? -1 : 1);
|
|
3509
3562
|
result[type].push({
|
|
3510
3563
|
gameRef: tag,
|
|
@@ -3537,9 +3590,9 @@ var rivenAttrValueDict = Object.fromEntries(
|
|
|
3537
3590
|
);
|
|
3538
3591
|
|
|
3539
3592
|
// src/warframe/data/wf/rivenDisposition.ts
|
|
3540
|
-
var
|
|
3593
|
+
var import_warframe_public_export_plus15 = require("warframe-public-export-plus");
|
|
3541
3594
|
var weaponTypes = {};
|
|
3542
|
-
for (const [path, definition] of Object.entries(
|
|
3595
|
+
for (const [path, definition] of Object.entries(import_warframe_public_export_plus15.ExportUpgrades)) {
|
|
3543
3596
|
const type = rivenDefinitionTypes[path.split("/").pop()];
|
|
3544
3597
|
if (!type)
|
|
3545
3598
|
continue;
|
|
@@ -3577,7 +3630,7 @@ __name(buildWeaponRivenDispositionDict, "buildWeaponRivenDispositionDict");
|
|
|
3577
3630
|
for (const weapon of rivenPublicExport.weapons) {
|
|
3578
3631
|
if (weaponTypes[weapon.uniqueName])
|
|
3579
3632
|
continue;
|
|
3580
|
-
const metadata =
|
|
3633
|
+
const metadata = import_warframe_public_export_plus15.ExportWeapons[weapon.uniqueName];
|
|
3581
3634
|
const category = weapon.productCategory;
|
|
3582
3635
|
const type = category === "Melee" ? "Melee" : category === "SpaceGuns" ? "Archgun" : category === "Pistols" ? "Pistol" : category === "LongGuns" && metadata?.holsterCategory ? metadata.holsterCategory === "SHOTGUN" ? "Shotgun" : "Rifle" : void 0;
|
|
3583
3636
|
if (type)
|
|
@@ -3744,8 +3797,8 @@ async function getTextFromTencentOCR(image, secret) {
|
|
|
3744
3797
|
const OcrClient = tencentcloud.ocr.v20181119.Client;
|
|
3745
3798
|
const clientConfig = {
|
|
3746
3799
|
credential: {
|
|
3747
|
-
secretId: secret.id,
|
|
3748
|
-
secretKey: secret.key
|
|
3800
|
+
secretId: secret.id.trim(),
|
|
3801
|
+
secretKey: secret.key.trim()
|
|
3749
3802
|
},
|
|
3750
3803
|
region: "",
|
|
3751
3804
|
profile: {
|
|
@@ -3758,10 +3811,17 @@ async function getTextFromTencentOCR(image, secret) {
|
|
|
3758
3811
|
const { TextDetections } = await client.GeneralAccurateOCR({
|
|
3759
3812
|
ImageBase64: image
|
|
3760
3813
|
});
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3814
|
+
return (TextDetections ?? []).flatMap((t2) => {
|
|
3815
|
+
const text = t2.DetectedText;
|
|
3816
|
+
if (!text?.trim())
|
|
3817
|
+
return [];
|
|
3818
|
+
const box = t2.ItemPolygon;
|
|
3819
|
+
return [{
|
|
3820
|
+
text,
|
|
3821
|
+
confidence: t2.Confidence,
|
|
3822
|
+
box: box ? { x: box.X, y: box.Y, width: box.Width, height: box.Height } : void 0
|
|
3823
|
+
}];
|
|
3824
|
+
});
|
|
3765
3825
|
}
|
|
3766
3826
|
__name(getTextFromTencentOCR, "getTextFromTencentOCR");
|
|
3767
3827
|
async function extractTextFromImage(image, secret) {
|
|
@@ -3778,6 +3838,172 @@ async function extractTextFromImage(image, secret) {
|
|
|
3778
3838
|
}
|
|
3779
3839
|
__name(extractTextFromImage, "extractTextFromImage");
|
|
3780
3840
|
|
|
3841
|
+
// src/warframe/services/riven/ocr.ts
|
|
3842
|
+
function cleanText(text) {
|
|
3843
|
+
return fullWidthToHalfWidth(text).trim().replace(/−/g, "-").replace(/×/g, "x");
|
|
3844
|
+
}
|
|
3845
|
+
__name(cleanText, "cleanText");
|
|
3846
|
+
function validBox(box) {
|
|
3847
|
+
return !!box && Object.values(box).every(Number.isFinite) && box.width > 0 && box.height > 0;
|
|
3848
|
+
}
|
|
3849
|
+
__name(validBox, "validBox");
|
|
3850
|
+
function restoreRows(input) {
|
|
3851
|
+
const blocks = input.map((b) => typeof b === "string" ? { text: b } : b).map((b) => ({ ...b, text: cleanText(b.text) })).filter((b) => b.text);
|
|
3852
|
+
const positioned = blocks.filter((b) => validBox(b.box)).length;
|
|
3853
|
+
if (positioned > 0 && positioned !== blocks.length)
|
|
3854
|
+
return void 0;
|
|
3855
|
+
if (!positioned)
|
|
3856
|
+
return blocks.map((b) => ({ text: b.text, fragmented: false }));
|
|
3857
|
+
const rows = [];
|
|
3858
|
+
for (const block of [...blocks].sort((a, b) => a.box.y + a.box.height / 2 - b.box.y - b.box.height / 2)) {
|
|
3859
|
+
const box = block.box;
|
|
3860
|
+
const row = rows.find((r) => {
|
|
3861
|
+
const anchor = r[0].box;
|
|
3862
|
+
return Math.abs(box.y + box.height / 2 - anchor.y - anchor.height / 2) <= Math.min(box.height, anchor.height) * 0.6 || /^\d+%$/.test(block.text) && box.height < anchor.height * 0.65 && box.y >= anchor.y && box.y + box.height <= anchor.y + anchor.height;
|
|
3863
|
+
});
|
|
3864
|
+
if (row)
|
|
3865
|
+
row.push(block);
|
|
3866
|
+
else
|
|
3867
|
+
rows.push([block]);
|
|
3868
|
+
}
|
|
3869
|
+
const result = [];
|
|
3870
|
+
for (const row of rows) {
|
|
3871
|
+
const parts = row.sort((a, b) => a.box.x - b.box.x);
|
|
3872
|
+
const first = parts[0];
|
|
3873
|
+
const last = parts.at(-1);
|
|
3874
|
+
const fragmented = parts.length > 1 && /^[+\-x]?\d+(?:\.\d+)?%?$/i.test(first.text) && /\p{L}/u.test(last.text);
|
|
3875
|
+
const kept = parts.filter((b, i) => !(fragmented && i > 0 && i < parts.length - 1 && /^\d+%$/.test(b.text) && b.box.height < Math.min(first.box.height, last.box.height) * 0.65));
|
|
3876
|
+
if (fragmented && kept.slice(1).some((b) => /^[+\-x]?\d/i.test(b.text)))
|
|
3877
|
+
return void 0;
|
|
3878
|
+
for (let i = 1; i < kept.length; i++) {
|
|
3879
|
+
const left = kept[i - 1].box;
|
|
3880
|
+
const right = kept[i].box;
|
|
3881
|
+
if (!isMetadata(first.text) && right.x - left.x - left.width > Math.max(left.height, right.height) * 4)
|
|
3882
|
+
return void 0;
|
|
3883
|
+
}
|
|
3884
|
+
result.push({ text: kept.map((b) => b.text).join(" "), fragmented });
|
|
3885
|
+
}
|
|
3886
|
+
return result;
|
|
3887
|
+
}
|
|
3888
|
+
__name(restoreRows, "restoreRows");
|
|
3889
|
+
var weaponNames = [...new Map(Object.values(weaponRivenDispositionDict).flatMap(
|
|
3890
|
+
(weapon) => [weapon.name.zh, weapon.name.en].map((display) => {
|
|
3891
|
+
const name2 = display.replace(/\s*\((?:Primary|Secondary)\)|([主副]武器)/g, "");
|
|
3892
|
+
return [normalizeName(name2), { name: name2, type: weapon.calc.riventype }];
|
|
3893
|
+
})
|
|
3894
|
+
)).entries()].sort((a, b) => b[0].length - a[0].length);
|
|
3895
|
+
var rivenNameParts = [...new Set(rivenPublicExport.upgrades.flatMap((d) => d.upgradeEntries.flatMap((e) => [e.prefixTag, e.suffixTag]).filter((s) => !!s && /^[a-z]+$/.test(s))))];
|
|
3896
|
+
var rivenNamePattern = new RegExp(`^(?:${rivenNameParts.join("|")}){1,3}$`, "i");
|
|
3897
|
+
function isRivenName(text) {
|
|
3898
|
+
return rivenNamePattern.test(normalizeName(text));
|
|
3899
|
+
}
|
|
3900
|
+
__name(isRivenName, "isRivenName");
|
|
3901
|
+
function findWeapon(text) {
|
|
3902
|
+
const normalized = normalizeName(text);
|
|
3903
|
+
for (const [key, weapon] of weaponNames) {
|
|
3904
|
+
if (normalized === key)
|
|
3905
|
+
return weapon;
|
|
3906
|
+
const remainder = normalized.slice(key.length);
|
|
3907
|
+
if (normalized.startsWith(key) && isRivenName(remainder) && !weaponNames.some(([name2]) => name2 === remainder))
|
|
3908
|
+
return weapon;
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
__name(findWeapon, "findWeapon");
|
|
3912
|
+
function normalizeStat(text) {
|
|
3913
|
+
return normalizeName(text).replace(/的/g, "").replace(/暴击率/g, "暴击几率").replace(/弹药最大值/g, "弹药上限").replace(/触发时间/g, "触发持续时间").replace(/触发伤害/g, "异常状态伤害").replace(/orokin/g, "奥罗金").replace(/techrot/g, "科腐者").replace(/scaldra/g, "炽蛇军");
|
|
3914
|
+
}
|
|
3915
|
+
__name(normalizeStat, "normalizeStat");
|
|
3916
|
+
var elemental = /Weapon(?:Electricity|Fire|Freeze|Toxin|Impact|ArmorPiercing|Slash|Blast|Corrosive|Gas|Magnetic|Radiation|Viral)DamageMod/;
|
|
3917
|
+
function aliases(stat) {
|
|
3918
|
+
const names = stat.aliases.flatMap((name2) => name2.split("/"));
|
|
3919
|
+
if (elemental.test(stat.gameRef))
|
|
3920
|
+
names.push(`${stat.name}伤害`);
|
|
3921
|
+
if (stat.gameRef === "WeaponDamageAmountMod" || stat.gameRef === "WeaponMeleeDamageMod")
|
|
3922
|
+
names.push("伤害");
|
|
3923
|
+
return [...new Set(names.map(normalizeStat))];
|
|
3924
|
+
}
|
|
3925
|
+
__name(aliases, "aliases");
|
|
3926
|
+
function matchStat(label, stats, fragmented) {
|
|
3927
|
+
const input = normalizeStat(label);
|
|
3928
|
+
const candidates = stats.map((stat) => ({ stat, names: aliases(stat) }));
|
|
3929
|
+
const exact = candidates.filter((c) => c.names.includes(input));
|
|
3930
|
+
if (exact.length)
|
|
3931
|
+
return exact.length === 1 ? exact[0].stat : void 0;
|
|
3932
|
+
const icon = candidates.filter((c) => elemental.test(c.stat.gameRef) && /^[入人]/.test(input) && c.names.includes(input.slice(1)));
|
|
3933
|
+
if (icon.length === 1)
|
|
3934
|
+
return icon[0].stat;
|
|
3935
|
+
if (fragmented && /^[\u4E00-\u9FFF]{3,}$/.test(input)) {
|
|
3936
|
+
const suffix = candidates.filter((c) => c.names.some((name2) => name2.endsWith(input) && name2.length - input.length <= 3));
|
|
3937
|
+
if (suffix.length)
|
|
3938
|
+
return suffix.length === 1 ? suffix[0].stat : void 0;
|
|
3939
|
+
}
|
|
3940
|
+
const ranked = candidates.map((c) => ({ stat: c.stat, score: Math.max(...c.names.map((name2) => normalSimilarity(name2, input))) })).sort((a, b) => b.score - a.score);
|
|
3941
|
+
if (candidates.some((c) => c.names.some((name2) => name2.length >= 3 && input !== name2 && (input.endsWith(name2) || name2.endsWith(input)))))
|
|
3942
|
+
return void 0;
|
|
3943
|
+
return ranked[0]?.score >= 0.8 && ranked[0].score - (ranked[1]?.score ?? 0) >= 0.15 ? ranked[0].stat : void 0;
|
|
3944
|
+
}
|
|
3945
|
+
__name(matchStat, "matchStat");
|
|
3946
|
+
function isRank(text) {
|
|
3947
|
+
return /^(?:段位|等级|循环)\s*\d|^\d+\s*(?:段位|等级|次|循环)/.test(text);
|
|
3948
|
+
}
|
|
3949
|
+
__name(isRank, "isRank");
|
|
3950
|
+
function isMetadata(text) {
|
|
3951
|
+
return isRank(text) || /^\d[\d\s~\-]*$/.test(text);
|
|
3952
|
+
}
|
|
3953
|
+
__name(isMetadata, "isMetadata");
|
|
3954
|
+
function parseRivenOcr(input) {
|
|
3955
|
+
const rows = restoreRows(input);
|
|
3956
|
+
if (!rows?.length)
|
|
3957
|
+
return void 0;
|
|
3958
|
+
const titles = rows.map((r, index) => ({ weapon: findWeapon(r.text), index })).filter((t2) => t2.weapon);
|
|
3959
|
+
if (titles.length !== 1)
|
|
3960
|
+
return void 0;
|
|
3961
|
+
const title = titles[0];
|
|
3962
|
+
if (rows.slice(0, title.index).some((r) => /^6?[+\-x]\d|^\d+(?:\.\d+)?%/i.test(r.text)))
|
|
3963
|
+
return void 0;
|
|
3964
|
+
const weapon = title.weapon;
|
|
3965
|
+
const stats = rivenStatsByType[weapon.type];
|
|
3966
|
+
if (!stats)
|
|
3967
|
+
return void 0;
|
|
3968
|
+
const attributes = [];
|
|
3969
|
+
let footer = false;
|
|
3970
|
+
for (let i = title.index + 1; i < rows.length; i++) {
|
|
3971
|
+
const row = rows[i];
|
|
3972
|
+
let text = row.text.replace(/\s/g, "");
|
|
3973
|
+
if (isRank(text)) {
|
|
3974
|
+
footer = true;
|
|
3975
|
+
continue;
|
|
3976
|
+
}
|
|
3977
|
+
if (footer && /^\d+$/.test(text))
|
|
3978
|
+
continue;
|
|
3979
|
+
if (!attributes.length && isRivenName(text))
|
|
3980
|
+
continue;
|
|
3981
|
+
text = text.replace(/^[6🔒]([+\-])/u, "$1");
|
|
3982
|
+
if (text.includes("(") && !text.includes(")") && rows[i + 1] && !/^[+\-x\d]/i.test(rows[i + 1].text)) {
|
|
3983
|
+
text += rows[++i].text.replace(/\s/g, "");
|
|
3984
|
+
}
|
|
3985
|
+
text = text.replace(/\((?:弓类武器效果加倍|重击时x2|x2forBows|x2forHeavyAttacks)\)/gi, "");
|
|
3986
|
+
const match = text.match(/^([+\-x]?)(\d+(?:\.\d+)?)(%|s)?([\p{L}/]+)$/iu);
|
|
3987
|
+
if (!match)
|
|
3988
|
+
return void 0;
|
|
3989
|
+
const [, symbol, number, unit, label] = match;
|
|
3990
|
+
if (!symbol && input.some((b) => typeof b !== "string"))
|
|
3991
|
+
return void 0;
|
|
3992
|
+
const attr = matchStat(label, stats, row.fragmented);
|
|
3993
|
+
if (!attr || attributes.some((a) => a.attr.gameRef === attr.gameRef))
|
|
3994
|
+
return void 0;
|
|
3995
|
+
const prefix = symbol.toLowerCase();
|
|
3996
|
+
if (prefix === "x" !== (attr.unit === "multiply") || unit === "%" && attr.unit !== "percent" || unit === "s" && attr.unit !== "seconds")
|
|
3997
|
+
return void 0;
|
|
3998
|
+
const value = Number(number) * (prefix === "-" ? -1 : 1);
|
|
3999
|
+
if (!Number.isFinite(value) || value === 0)
|
|
4000
|
+
return void 0;
|
|
4001
|
+
attributes.push({ attr, value, prefix });
|
|
4002
|
+
}
|
|
4003
|
+
return attributes.length >= 2 && attributes.length <= 4 ? { name: weapon.name, attributes } : void 0;
|
|
4004
|
+
}
|
|
4005
|
+
__name(parseRivenOcr, "parseRivenOcr");
|
|
4006
|
+
|
|
3781
4007
|
// src/warframe/services/wf-service/wf-service.riven.ts
|
|
3782
4008
|
async function getAnalyzedRiven(secret, url, variant) {
|
|
3783
4009
|
const img = await fetchAsyncImage(url);
|
|
@@ -3912,138 +4138,7 @@ function getWeaponRivenDisposition(name2) {
|
|
|
3912
4138
|
}
|
|
3913
4139
|
__name(getWeaponRivenDisposition, "getWeaponRivenDisposition");
|
|
3914
4140
|
async function parseOCRResult(ocrResult) {
|
|
3915
|
-
|
|
3916
|
-
const list = ocrResult;
|
|
3917
|
-
if (!list.length) {
|
|
3918
|
-
return;
|
|
3919
|
-
}
|
|
3920
|
-
function normalizeStatName(text) {
|
|
3921
|
-
return normalizeName(text).replace(/的/g, "").replace(/暴击率/g, "暴击几率").replace(/弹药最大值/g, "弹药上限").replace(/^伤害$/, "基础伤害").replace(/触发伤害/g, "异常状态伤害").replace(/orokin/g, "奥罗金").replace(/techrot/g, "科腐者").replace(/scaldra/g, "炽蛇军");
|
|
3922
|
-
}
|
|
3923
|
-
__name(normalizeStatName, "normalizeStatName");
|
|
3924
|
-
function similarity(standard, input) {
|
|
3925
|
-
standard = normalizeStatName(standard);
|
|
3926
|
-
input = normalizeStatName(input);
|
|
3927
|
-
if (!standard || !input)
|
|
3928
|
-
return 0;
|
|
3929
|
-
if (standard === input)
|
|
3930
|
-
return 2;
|
|
3931
|
-
if (input.startsWith(standard))
|
|
3932
|
-
return 1 + standard.length / input.length * 0.5;
|
|
3933
|
-
if (standard.split("/").includes(input))
|
|
3934
|
-
return 1.8;
|
|
3935
|
-
if (standard.split("/").some((x) => input.startsWith(x)))
|
|
3936
|
-
return 1.2;
|
|
3937
|
-
return Math.max(tokenSimilarity(standard, input), normalSimilarity(standard, input));
|
|
3938
|
-
}
|
|
3939
|
-
__name(similarity, "similarity");
|
|
3940
|
-
const texts = list;
|
|
3941
|
-
const attributes = [];
|
|
3942
|
-
const statLines = [];
|
|
3943
|
-
for (const t2 of texts) {
|
|
3944
|
-
if (!t2 || !/^[x×+−-]|^\d/i.test(t2)) {
|
|
3945
|
-
continue;
|
|
3946
|
-
}
|
|
3947
|
-
if (/^(?:\d+\s*(?:段位|等级|次|循环)|(?:段位|等级|循环)\s*\d+)$/.test(t2.trim()))
|
|
3948
|
-
continue;
|
|
3949
|
-
const prefix = /^[x×+−-]/i.test(t2) ? t2[0] : "";
|
|
3950
|
-
const attrNamePart = removeSpace(t2).replace(/^[xX×+−-]?\d+(?:\.\d+)?[%s]?/, "");
|
|
3951
|
-
if (!attrNamePart || !/[A-Z\u4E00-\u9FA5]/i.test(attrNamePart))
|
|
3952
|
-
continue;
|
|
3953
|
-
if (!prefix && /^[a-z]{1,2}$/i.test(attrNamePart))
|
|
3954
|
-
continue;
|
|
3955
|
-
const matches = globalRivenCalculationAttributeList.map((attr2) => ({
|
|
3956
|
-
attr: attr2,
|
|
3957
|
-
score: Math.max(...attr2.aliases.map((name2) => similarity(name2, attrNamePart)))
|
|
3958
|
-
})).sort((a, b) => b.score - a.score);
|
|
3959
|
-
const best = matches[0];
|
|
3960
|
-
if (!best || best.score < 0.8)
|
|
3961
|
-
return void 0;
|
|
3962
|
-
const attr = best.attr;
|
|
3963
|
-
statLines.push(t2);
|
|
3964
|
-
const value = (/* @__PURE__ */ __name((function extractStatValue(text) {
|
|
3965
|
-
const t3 = text.replace(/\s+/g, "").replace(/×/g, "x").replace(/−/g, "-");
|
|
3966
|
-
const multMatch = t3.match(/^x(\d+(?:\.\d+)?)/i);
|
|
3967
|
-
if (multMatch) {
|
|
3968
|
-
return {
|
|
3969
|
-
value: Number.parseFloat(multMatch[1]),
|
|
3970
|
-
type: "multiply"
|
|
3971
|
-
};
|
|
3972
|
-
}
|
|
3973
|
-
const percentMatch = t3.match(/^([+-]?\d+(?:\.\d+)?)%/);
|
|
3974
|
-
if (percentMatch) {
|
|
3975
|
-
return {
|
|
3976
|
-
value: Number.parseFloat(percentMatch[1]),
|
|
3977
|
-
type: "percent"
|
|
3978
|
-
};
|
|
3979
|
-
}
|
|
3980
|
-
const numMatch = t3.match(/^([+-]?\d+(?:\.\d+)?)/);
|
|
3981
|
-
if (numMatch) {
|
|
3982
|
-
return {
|
|
3983
|
-
value: Number.parseFloat(numMatch[1]),
|
|
3984
|
-
type: "number"
|
|
3985
|
-
};
|
|
3986
|
-
}
|
|
3987
|
-
return void 0;
|
|
3988
|
-
}), "extractStatValue"))(t2);
|
|
3989
|
-
if (!value) {
|
|
3990
|
-
return void 0;
|
|
3991
|
-
}
|
|
3992
|
-
attributes.push({ attr, value: value.value, prefix });
|
|
3993
|
-
}
|
|
3994
|
-
const weaponName = (/* @__PURE__ */ __name((function extractWeaponName(ocrData) {
|
|
3995
|
-
const rejectPatterns = [
|
|
3996
|
-
/%/,
|
|
3997
|
-
/x\d/i,
|
|
3998
|
-
/\d/,
|
|
3999
|
-
// numbers, %, multipliers
|
|
4000
|
-
/伤害/,
|
|
4001
|
-
/暴击/,
|
|
4002
|
-
/射速/,
|
|
4003
|
-
/攻击/,
|
|
4004
|
-
/后坐力/,
|
|
4005
|
-
/段位/,
|
|
4006
|
-
/加倍/,
|
|
4007
|
-
/效/,
|
|
4008
|
-
/武器/,
|
|
4009
|
-
/果/,
|
|
4010
|
-
/\)/,
|
|
4011
|
-
/\(/
|
|
4012
|
-
// junk OCR fragments
|
|
4013
|
-
];
|
|
4014
|
-
const exact = ocrData.find(
|
|
4015
|
-
(text) => getWeaponRivenDisposition(text.trim()) || getWeaponRivenDisposition(`${text.trim()} (Primary)`) || getWeaponRivenDisposition(`${text.trim()} (Secondary)`) || getWeaponRivenDisposition(`${text.trim()}(主武器)`) || getWeaponRivenDisposition(`${text.trim()}(副武器)`)
|
|
4016
|
-
);
|
|
4017
|
-
if (exact)
|
|
4018
|
-
return exact.trim();
|
|
4019
|
-
const candidates = ocrData.filter((str) => {
|
|
4020
|
-
const s = str.trim();
|
|
4021
|
-
if (/^\d+$/.test(s))
|
|
4022
|
-
return false;
|
|
4023
|
-
if (/[+%]/.test(s))
|
|
4024
|
-
return false;
|
|
4025
|
-
if (!/[A-Z\u4E00-\u9FA5]/i.test(s))
|
|
4026
|
-
return false;
|
|
4027
|
-
if (rejectPatterns.some((p) => p.test(s)))
|
|
4028
|
-
return false;
|
|
4029
|
-
return true;
|
|
4030
|
-
});
|
|
4031
|
-
const merged = candidates.join("");
|
|
4032
|
-
function removeRivenSuffix(name2) {
|
|
4033
|
-
const s = name2.replace(/\s+/g, "");
|
|
4034
|
-
const rivenPattern = /(?:[A-Z]+-[A-Z]+|[A-Z]{2,})$/i;
|
|
4035
|
-
return s.replace(rivenPattern, "");
|
|
4036
|
-
}
|
|
4037
|
-
__name(removeRivenSuffix, "removeRivenSuffix");
|
|
4038
|
-
return merged ? removeRivenSuffix(merged) : null;
|
|
4039
|
-
}), "extractWeaponName"))(texts.filter((t2) => !statLines.includes(t2)));
|
|
4040
|
-
if (!weaponName || !attributes.length) {
|
|
4041
|
-
return void 0;
|
|
4042
|
-
}
|
|
4043
|
-
return {
|
|
4044
|
-
name: weaponName,
|
|
4045
|
-
attributes
|
|
4046
|
-
};
|
|
4141
|
+
return parseRivenOcr(ocrResult);
|
|
4047
4142
|
}
|
|
4048
4143
|
__name(parseOCRResult, "parseOCRResult");
|
|
4049
4144
|
function analyzeRivenStat(parseResult, variant) {
|
|
@@ -4065,6 +4160,7 @@ function analyzeRivenStat(parseResult, variant) {
|
|
|
4065
4160
|
return failure("riven.statTypeError");
|
|
4066
4161
|
}
|
|
4067
4162
|
const entries = [];
|
|
4163
|
+
const notes = [];
|
|
4068
4164
|
for (const entry of parseResult.attributes) {
|
|
4069
4165
|
const stat = stats.find((s) => s.gameRef === entry.attr.gameRef) ?? stats.find((s) => s.key === normalizeName(entry.attr.i18n?.en?.name ?? ""));
|
|
4070
4166
|
if (!stat || !Number.isFinite(entry.value) || !stat.baseValue)
|
|
@@ -4073,8 +4169,11 @@ function analyzeRivenStat(parseResult, variant) {
|
|
|
4073
4169
|
return failure("riven.unverifiedStat", false, { stat: stat.name });
|
|
4074
4170
|
const value = stat.unit === "multiply" ? entry.value - 1 : entry.value;
|
|
4075
4171
|
const positive = value / stat.baseValue > 0;
|
|
4076
|
-
|
|
4172
|
+
const observedShotgunZoom = weaponRiven.calc.riventype === "Shotgun" && stat.gameRef === "WeaponZoomFovMod" && !positive;
|
|
4173
|
+
if (value === 0 || (positive ? !stat.canBeBuff : !stat.canBeCurse && !observedShotgunZoom))
|
|
4077
4174
|
return failure("riven.statTypeError");
|
|
4175
|
+
if (observedShotgunZoom)
|
|
4176
|
+
notes.push("霰弹枪负变焦按现有卡片兼容解析,范围使用导出基础值作参考;不代表当前可洗出该词条。");
|
|
4078
4177
|
if (entries.some((e) => e.stat.gameRef === stat.gameRef))
|
|
4079
4178
|
return failure("riven.statTypeError");
|
|
4080
4179
|
entries.push({ stat, value, displayedValue: entry.value, positive });
|
|
@@ -4097,21 +4196,23 @@ function analyzeRivenStat(parseResult, variant) {
|
|
|
4097
4196
|
max: Math.max(standard * 0.9, standard * 1.1) + offset
|
|
4098
4197
|
};
|
|
4099
4198
|
}, "analyze");
|
|
4199
|
+
if (entries.some((e) => e.stat.spliced))
|
|
4200
|
+
notes.push("融合词条为参考范围;实际融合数值的继承方式尚未验证。");
|
|
4100
4201
|
return { ok: true, data: {
|
|
4101
4202
|
name: weaponRiven.name.zh,
|
|
4102
4203
|
disposition,
|
|
4103
4204
|
buffs: buffs.map(analyze),
|
|
4104
4205
|
curses: curses.map(analyze),
|
|
4105
|
-
notes:
|
|
4206
|
+
notes: notes.length ? notes : void 0
|
|
4106
4207
|
} };
|
|
4107
4208
|
}
|
|
4108
4209
|
__name(analyzeRivenStat, "analyzeRivenStat");
|
|
4109
4210
|
|
|
4110
4211
|
// src/warframe/services/wf-service/wf-service.sortie.ts
|
|
4111
|
-
var
|
|
4212
|
+
var import_warframe_public_export_plus17 = require("warframe-public-export-plus");
|
|
4112
4213
|
|
|
4113
4214
|
// src/warframe/data/wf/sortie.ts
|
|
4114
|
-
var
|
|
4215
|
+
var import_warframe_public_export_plus16 = require("warframe-public-export-plus");
|
|
4115
4216
|
var MODE_NAME_KEY = "/Lotus/Language/Menu/SortieMissionName";
|
|
4116
4217
|
var SORTIE_ENEMY_LEVELS = [
|
|
4117
4218
|
{ minLevel: 50, maxLevel: 60 },
|
|
@@ -4119,7 +4220,7 @@ var SORTIE_ENEMY_LEVELS = [
|
|
|
4119
4220
|
{ minLevel: 80, maxLevel: 100 }
|
|
4120
4221
|
];
|
|
4121
4222
|
function getSortieModeName() {
|
|
4122
|
-
return
|
|
4223
|
+
return import_warframe_public_export_plus16.dict_zh[MODE_NAME_KEY] ?? dictZhExtra[MODE_NAME_KEY] ?? MODE_NAME_KEY;
|
|
4123
4224
|
}
|
|
4124
4225
|
__name(getSortieModeName, "getSortieModeName");
|
|
4125
4226
|
function getSortieEnemyLevels(index) {
|
|
@@ -4143,13 +4244,13 @@ async function adaptSortie(source, dates) {
|
|
|
4143
4244
|
(source.Variants ?? []).map(async (variant, index) => {
|
|
4144
4245
|
const missionType = variant.missionType ?? "";
|
|
4145
4246
|
const receivedType = await getMissionTypeKey(missionType) || missionType;
|
|
4146
|
-
const type =
|
|
4247
|
+
const type = import_warframe_public_export_plus17.dict_zh[import_warframe_public_export_plus17.ExportMissionTypes[receivedType]?.name ?? ""] ?? missionType;
|
|
4147
4248
|
const nodeId = variant.node ?? "";
|
|
4148
4249
|
const solNodeKey = await getSolNodeKey(nodeId) || nodeId;
|
|
4149
|
-
const region = solNodeKey ?
|
|
4250
|
+
const region = solNodeKey ? import_warframe_public_export_plus17.ExportRegions[solNodeKey] : void 0;
|
|
4150
4251
|
const levels = getSortieEnemyLevels(index);
|
|
4151
4252
|
const node = region ? {
|
|
4152
|
-
...regionToShort(region,
|
|
4253
|
+
...regionToShort(region, import_warframe_public_export_plus17.dict_zh),
|
|
4153
4254
|
minLevel: levels.minLevel,
|
|
4154
4255
|
maxLevel: levels.maxLevel
|
|
4155
4256
|
} : {
|
|
@@ -4210,7 +4311,7 @@ async function getSortie() {
|
|
|
4210
4311
|
__name(getSortie, "getSortie");
|
|
4211
4312
|
|
|
4212
4313
|
// src/warframe/services/wf-service/wf-service.steel-essence.ts
|
|
4213
|
-
var
|
|
4314
|
+
var import_warframe_public_export_plus18 = require("warframe-public-export-plus");
|
|
4214
4315
|
var STEEL_ESSENCE_TESHIN_KEY = "/Lotus/Language/Bosses/Teshin";
|
|
4215
4316
|
var STEEL_ESSENCE_KEY = "/Lotus/Language/Resources/SteelEssence";
|
|
4216
4317
|
var STEEL_ESSENCE_EPOCH_MS = Date.parse("2020-11-16T00:00:00.000Z");
|
|
@@ -4257,8 +4358,8 @@ async function adaptSteelEssence(raw = {}, now = Date.now()) {
|
|
|
4257
4358
|
};
|
|
4258
4359
|
const upcoming = rotationZh.length > 1 ? rotationZh.map((_, offset) => rotationZh[(index + offset + 1) % rotationZh.length]).filter((item) => item !== void 0).slice(0, rotationZh.length - 1) : [];
|
|
4259
4360
|
const expiry = raw.expiry?.getTime() ?? steelEssenceWeekExpiryUtc(now);
|
|
4260
|
-
const teshin =
|
|
4261
|
-
const essence =
|
|
4361
|
+
const teshin = import_warframe_public_export_plus18.dict_zh[STEEL_ESSENCE_TESHIN_KEY] ?? dictZhExtra[STEEL_ESSENCE_TESHIN_KEY] ?? STEEL_ESSENCE_TESHIN_KEY;
|
|
4362
|
+
const essence = import_warframe_public_export_plus18.dict_zh[STEEL_ESSENCE_KEY] ?? dictZhExtra[STEEL_ESSENCE_KEY] ?? STEEL_ESSENCE_KEY;
|
|
4262
4363
|
return {
|
|
4263
4364
|
title: `${teshin} · ${essence}商店`,
|
|
4264
4365
|
costLabel: essence,
|
|
@@ -4311,10 +4412,10 @@ async function getVoidTrader() {
|
|
|
4311
4412
|
__name(getVoidTrader, "getVoidTrader");
|
|
4312
4413
|
|
|
4313
4414
|
// src/warframe/services/wf-service/wf-service.weekly.ts
|
|
4314
|
-
var
|
|
4415
|
+
var import_warframe_public_export_plus20 = require("warframe-public-export-plus");
|
|
4315
4416
|
|
|
4316
4417
|
// src/warframe/data/wf/archonHunt.ts
|
|
4317
|
-
var
|
|
4418
|
+
var import_warframe_public_export_plus19 = require("warframe-public-export-plus");
|
|
4318
4419
|
var MODE_NAME_KEY2 = "/Lotus/Language/WorldStateWindow/LiteSortieMissionName";
|
|
4319
4420
|
var HUNT_ENEMY_LEVELS = [
|
|
4320
4421
|
{ minLevel: 130, maxLevel: 135 },
|
|
@@ -4322,7 +4423,7 @@ var HUNT_ENEMY_LEVELS = [
|
|
|
4322
4423
|
{ minLevel: 145, maxLevel: 150 }
|
|
4323
4424
|
];
|
|
4324
4425
|
function getArchonHuntModeName() {
|
|
4325
|
-
return
|
|
4426
|
+
return import_warframe_public_export_plus19.dict_zh[MODE_NAME_KEY2] ?? dictZhExtra[MODE_NAME_KEY2] ?? MODE_NAME_KEY2;
|
|
4326
4427
|
}
|
|
4327
4428
|
__name(getArchonHuntModeName, "getArchonHuntModeName");
|
|
4328
4429
|
function getArchonHuntEnemyLevels(index) {
|
|
@@ -4332,15 +4433,15 @@ __name(getArchonHuntEnemyLevels, "getArchonHuntEnemyLevels");
|
|
|
4332
4433
|
|
|
4333
4434
|
// src/warframe/services/wf-service/wf-service.weekly.ts
|
|
4334
4435
|
async function adaptArchonHunt(source) {
|
|
4335
|
-
const name2 =
|
|
4436
|
+
const name2 = import_warframe_public_export_plus20.dict_zh[`/Lotus/Language/Narmer/${removeSpace(source.boss)}`] ?? source.boss;
|
|
4336
4437
|
const missions = await Promise.all(
|
|
4337
4438
|
(source.missions ?? []).map(async (mission, index) => {
|
|
4338
4439
|
const receivedType = await getMissionTypeKey(mission.type);
|
|
4339
|
-
const type =
|
|
4440
|
+
const type = import_warframe_public_export_plus20.dict_zh[import_warframe_public_export_plus20.ExportMissionTypes[receivedType]?.name ?? ""] ?? mission.type;
|
|
4340
4441
|
const solNodeKey = await getSolNodeKey(mission.nodeKey);
|
|
4341
|
-
const region = solNodeKey ?
|
|
4442
|
+
const region = solNodeKey ? import_warframe_public_export_plus20.ExportRegions[solNodeKey] : void 0;
|
|
4342
4443
|
const levels = getArchonHuntEnemyLevels(index);
|
|
4343
|
-
const node = region ? regionToShort(region,
|
|
4444
|
+
const node = region ? regionToShort(region, import_warframe_public_export_plus20.dict_zh) : {
|
|
4344
4445
|
name: mission.node ?? mission.nodeKey,
|
|
4345
4446
|
system: "",
|
|
4346
4447
|
type: "",
|
|
@@ -4393,7 +4494,7 @@ async function getWeekly() {
|
|
|
4393
4494
|
const deepArchimMissions = await Promise.all(
|
|
4394
4495
|
deepArchim.missions.map(async (m) => {
|
|
4395
4496
|
const receivedType = await getMissionTypeKey(m.missionType);
|
|
4396
|
-
const type =
|
|
4497
|
+
const type = import_warframe_public_export_plus20.dict_zh[import_warframe_public_export_plus20.ExportMissionTypes[receivedType]?.name ?? ""] ?? m.missionType;
|
|
4397
4498
|
const deviation = stringToDebuff(
|
|
4398
4499
|
m.deviation.key,
|
|
4399
4500
|
m.deviation.name,
|
|
@@ -4421,7 +4522,7 @@ async function getWeekly() {
|
|
|
4421
4522
|
const temporalArchimMissions = await Promise.all(
|
|
4422
4523
|
temporalArchim.missions.map(async (m) => {
|
|
4423
4524
|
const receivedType = await getMissionTypeKey(m.missionType);
|
|
4424
|
-
const type =
|
|
4525
|
+
const type = import_warframe_public_export_plus20.dict_zh[import_warframe_public_export_plus20.ExportMissionTypes[receivedType]?.name ?? ""] ?? receivedType;
|
|
4425
4526
|
const deviation = stringToDebuff(
|
|
4426
4527
|
m.deviation.key,
|
|
4427
4528
|
m.deviation.name,
|
|
@@ -4457,7 +4558,7 @@ async function getWeekly() {
|
|
|
4457
4558
|
__name(getWeekly, "getWeekly");
|
|
4458
4559
|
|
|
4459
4560
|
// src/warframe/services/wfm-service/index.ts
|
|
4460
|
-
var
|
|
4561
|
+
var import_warframe_public_export_plus21 = require("warframe-public-export-plus");
|
|
4461
4562
|
|
|
4462
4563
|
// src/warframe/data/wfm/globalDucatnator.ts
|
|
4463
4564
|
async function globalDucatnatorIDDictFactory(data) {
|
|
@@ -4664,10 +4765,10 @@ var wfmItemMatcher = (() => {
|
|
|
4664
4765
|
const headSuffixLookup = [neuropticsSuffix, cerebrumSuffix];
|
|
4665
4766
|
const warframeAliasDict = ((aliasObject) => {
|
|
4666
4767
|
const transformedObject = {};
|
|
4667
|
-
for (const [key,
|
|
4768
|
+
for (const [key, aliases2] of Object.entries(aliasObject)) {
|
|
4668
4769
|
const normalizedKey = normalizeName(key);
|
|
4669
4770
|
transformedObject[normalizedKey] = normalizedKey;
|
|
4670
|
-
for (const alias of
|
|
4771
|
+
for (const alias of aliases2) {
|
|
4671
4772
|
if (typeof alias !== "string" || alias.length === 0) {
|
|
4672
4773
|
continue;
|
|
4673
4774
|
}
|
|
@@ -5310,7 +5411,7 @@ async function getRivenOrders(input) {
|
|
|
5310
5411
|
}
|
|
5311
5412
|
__name(getRivenOrders, "getRivenOrders");
|
|
5312
5413
|
async function applyRelicData(relic) {
|
|
5313
|
-
const tier =
|
|
5414
|
+
const tier = import_warframe_public_export_plus21.dict_zh[relic.tierKey] ?? relic.tier;
|
|
5314
5415
|
const { globalItemGameRefDict } = await globalItemData.get();
|
|
5315
5416
|
const wfmDict = await globalDucatnatorIDDict.get();
|
|
5316
5417
|
const loadedItems = relic.items.map((element) => {
|
|
@@ -5399,7 +5500,7 @@ var primedModHistory = createAsyncCache(async () => {
|
|
|
5399
5500
|
}, 432e5);
|
|
5400
5501
|
|
|
5401
5502
|
// src/warframe/services/world-state-refresh.ts
|
|
5402
|
-
var
|
|
5503
|
+
var import_warframe_public_export_plus22 = require("warframe-public-export-plus");
|
|
5403
5504
|
var ALLOWED_FISSURE_MISSION_TYPES = /* @__PURE__ */ new Set(["MT_EXTERMINATION", "MT_DEFENSE", "MT_ARTIFACT"]);
|
|
5404
5505
|
function time(value) {
|
|
5405
5506
|
return value?.getTime() ?? 0;
|
|
@@ -5418,7 +5519,7 @@ function fissureId(value) {
|
|
|
5418
5519
|
__name(fissureId, "fissureId");
|
|
5419
5520
|
async function fissureMissionType(fissure) {
|
|
5420
5521
|
const nodeKey = await getSolNodeKey(fissure.nodeKey);
|
|
5421
|
-
return
|
|
5522
|
+
return import_warframe_public_export_plus22.ExportRegions[nodeKey]?.missionType;
|
|
5422
5523
|
}
|
|
5423
5524
|
__name(fissureMissionType, "fissureMissionType");
|
|
5424
5525
|
function dailyDealId(value) {
|
|
@@ -5446,21 +5547,6 @@ function traderId(value) {
|
|
|
5446
5547
|
].join(":");
|
|
5447
5548
|
}
|
|
5448
5549
|
__name(traderId, "traderId");
|
|
5449
|
-
function alertReward(alert) {
|
|
5450
|
-
const reward = alert.mission?.reward;
|
|
5451
|
-
if (!reward) {
|
|
5452
|
-
return "";
|
|
5453
|
-
}
|
|
5454
|
-
const values = [
|
|
5455
|
-
...reward.items,
|
|
5456
|
-
...reward.countedItems.map((item) => `${item.key} x${item.count}`)
|
|
5457
|
-
];
|
|
5458
|
-
if (reward.credits) {
|
|
5459
|
-
values.push(`${reward.credits} 现金`);
|
|
5460
|
-
}
|
|
5461
|
-
return values.join("、");
|
|
5462
|
-
}
|
|
5463
|
-
__name(alertReward, "alertReward");
|
|
5464
5550
|
async function diffWorldStates(previous, current) {
|
|
5465
5551
|
const notifications = [];
|
|
5466
5552
|
const previousFissures = new Set(previous.raw.fissures.map(fissureId));
|
|
@@ -5518,13 +5604,17 @@ async function diffWorldStates(previous, current) {
|
|
|
5518
5604
|
for (const alert of current.raw.alerts) {
|
|
5519
5605
|
const id = alertId(alert);
|
|
5520
5606
|
if (!previousAlerts.has(id)) {
|
|
5607
|
+
const { alerts: [mapped] } = await adaptAlerts([alert], currentTimestamp);
|
|
5608
|
+
if (!mapped) {
|
|
5609
|
+
continue;
|
|
5610
|
+
}
|
|
5521
5611
|
notifications.push({
|
|
5522
5612
|
type: "alert",
|
|
5523
5613
|
id,
|
|
5524
|
-
description:
|
|
5525
|
-
node:
|
|
5526
|
-
missionType:
|
|
5527
|
-
reward:
|
|
5614
|
+
description: mapped.description ?? "",
|
|
5615
|
+
node: mapped.node.system ? `${mapped.node.name} (${mapped.node.system})` : mapped.node.name,
|
|
5616
|
+
missionType: mapped.type,
|
|
5617
|
+
reward: mapped.rewards.map((item) => item.count > 1 ? `${item.name} x${item.count}` : item.name).join("、"),
|
|
5528
5618
|
expiry: time(alert.expiry)
|
|
5529
5619
|
});
|
|
5530
5620
|
}
|
|
@@ -7443,6 +7533,7 @@ function AlertComponent(board) {
|
|
|
7443
7533
|
const timeLeft = entry.expiry - Date.now();
|
|
7444
7534
|
const timeColor = timeLeft > 36e5 ? "var(--wf-success)" : timeLeft > 6e5 ? "var(--wf-info)" : "var(--wf-danger)";
|
|
7445
7535
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: missionCardStyle, children: [
|
|
7536
|
+
entry.description ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: "font-size:14px;font-weight:600;margin-bottom:4px;color:var(--wf-text-primary);", children: entry.description }) : null,
|
|
7446
7537
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: "font-size:13px;font-weight:600;margin-bottom:4px;color:var(--wf-text-body);", children: [
|
|
7447
7538
|
entry.type,
|
|
7448
7539
|
entry.nightmare ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: "margin-left:8px;font-size:12px;color:var(--wf-accent);", children: entry.nightmare }) : null
|