warframe-worldstate-parser
Version:
An Open parser for Warframe's Worldstate in Javascript
539 lines (538 loc) • 17.4 kB
JavaScript
import { n as __decorateMetadata, t as __decorate } from "../decorate-BCC26nnB.mjs";
import { Alert } from "./models/Alert.mjs";
import { Archimedea } from "./models/Archimedea.mjs";
import { Calendar } from "./models/Calendar.mjs";
import { CambionCycle } from "./models/CambionCycle.mjs";
import { CetusCycle } from "./models/CetusCycle.mjs";
import { ClanInitiativeRewards } from "./models/ClanInitiativeRewards.mjs";
import { ConclaveChallenge } from "./models/ConclaveChallenge.mjs";
import { ConstructionProgress } from "./models/ConstructionProgress.mjs";
import { DailyDeal } from "./models/DailyDeal.mjs";
import { DarkSector } from "./models/DarkSector.mjs";
import { DuviriChoice } from "./supporting/DuviriChoice.mjs";
import { DuviriCycle } from "./models/DuviriCycle.mjs";
import { EarthCycle } from "./models/EarthCycle.mjs";
import { Fissure } from "./models/Fissure.mjs";
import { FlashSale } from "./models/FlashSale.mjs";
import { GlobalUpgrade } from "./models/GlobalUpgrade.mjs";
import { Invasion } from "./models/Invasion.mjs";
import { ExternalMission } from "./supporting/ExternalMission.mjs";
import "./supporting/index.mjs";
import { Kuva } from "./models/Kuva.mjs";
import { News } from "./models/News.mjs";
import { Nightwave } from "./models/Nightwave.mjs";
import { PersistentEnemy } from "./models/PersistentEnemy.mjs";
import { Simaris } from "./models/Simaris.mjs";
import { Sortie } from "./models/Sortie.mjs";
import { SteelPathOfferings } from "./models/SteelPathOffering.mjs";
import { SyndicateMission } from "./models/SyndicateMission.mjs";
import { Tmp } from "./models/Tmp.mjs";
import { VallisCycle } from "./models/VallisCycle.mjs";
import { VoidTrader } from "./models/VoidTrader.mjs";
import { WeeklyChallenge } from "./models/WeeklyChallenge.mjs";
import { WorldEvent } from "./models/WorldEvent.mjs";
import { ZarimanCycle } from "./models/ZarimanCycle.mjs";
import "./models/index.mjs";
import { createHash } from "node:crypto";
import { Type } from "class-transformer";
import { IsArray, IsDate, IsOptional, IsString, ValidateNested } from "class-validator";
import wsData from "warframe-worldstate-data";
import { parseDate } from "warframe-worldstate-data/utilities";
//#region lib/WorldState.ts
const { sortie } = wsData;
const safeArray = (arr) => arr ?? [];
const safeObj = (obj) => obj ?? {};
/**
* Default Dependency object
* @type {Dependency}
*/
const defaultDeps = {
sortieData: sortie,
locale: "en",
logger: console
};
/**
*
* @param ParserClass class for parsing data
* @param dataArray array of raw data
* @param deps shared dependency object
* @param uniqueField field to treat as unique
* @returns array of parsed objects
*/
function parseArray(ParserClass, dataArray, deps, uniqueField) {
const arr = (dataArray || []).map((d) => new ParserClass(d, deps));
if (uniqueField) {
const utemp = {};
arr.sort((a, b) => (a.id || "").localeCompare(b.id || ""));
arr.forEach((obj) => {
const key = String(obj[uniqueField]);
utemp[key] = obj;
});
return Array.from(arr).filter((obj) => {
if (obj?.active && typeof obj.active !== "undefined") return obj.active;
return true;
});
}
return arr;
}
/**
* Parse array of objects that requires async parsing
* @param ParserClass class for parsing data - must expose a static build method
* @param dataArray array of raw data
* @param deps shared dependency object
* @param uniqueField field to treat as unique
* @returns array of parsed objects
*/
async function parseAsyncArray(ParserClass, dataArray, deps, uniqueField) {
const arr = [];
for await (const d of dataArray ?? []) arr.push(await ParserClass.build(d, deps));
if (uniqueField) {
const utemp = {};
arr.sort((a, b) => (a.id ?? "").localeCompare(b.id ?? ""));
arr.forEach((obj) => {
const key = String(obj[uniqueField]);
utemp[key] = obj;
});
return Array.from(arr).filter((obj) => {
if (obj?.active && typeof obj.active !== "undefined") return obj.active;
return true;
});
}
return arr;
}
/**
* Parses Warframe Worldstate JSON
*/
var WorldState = class WorldState {
/**
* The date and time at which the World State was generated
*/
timestamp;
/**
* Current Warframe version
*/
buildLabel;
/**
* The in-game news
*/
news;
/**
* The current events
*/
events;
/**
* The current alerts
*/
alerts;
/**
* The current sortie
*/
sortie;
/**
* The current syndicate missions
*/
syndicateMissions;
/**
* The current fissures: 'ActiveMissions' & 'VoidStorms'
*/
fissures;
/**
* The current global upgrades
*/
globalUpgrades;
/**
* The current flash sales
*/
flashSales;
/**
* The current invasions
*/
invasions;
/**
* The state of the dark sectors
*/
darkSectors;
/**
* The state of all Void Traders
*/
voidTraders;
/**
* The first entry for voidTraders
* @deprecated
*/
voidTrader;
/**
* The current daily deals
*/
dailyDeals;
/**
* The state of the sanctuary synthesis targets
*/
simaris;
/**
* The current conclave challenges
*/
conclaveChallenges;
/**
* The currently active persistent enemies
*/
persistentEnemies;
/**
* The current earth cycle
*/
earthCycle;
/**
* The current Cetus cycle
*/
cetusCycle;
/**
* Cambion Drift Cycle
*/
cambionCycle;
/**
* The current Zariman cycle based off current time
*/
zarimanCycle;
/**
* Midrath cycle (soulframe)
* Game seems to desync while you play and appearntly it changes between updates.
*/
/**
* Weekly challenges
*/
weeklyChallenges;
/**
* The Current construction progress for Fomorians/Razorback/etc.
*/
constructionProgress;
/**
* The current Orb Vallis cycle state
*/
vallisCycle;
/**
* The current nightwave season
*/
nightwave;
/**
* Kuva missions array
*/
kuva;
/**
* Arbitration mission
*/
arbitration;
/**
* Current sentient outposts
*/
sentientOutposts;
/**
* Steel path offering rotation
*/
steelPath;
/**
* The current prime resurgence
*/
vaultTrader;
/**
* The current archon hunt
*/
archonHunt;
/**
* Current Duviri circuit choices
*/
duviriCycle;
/**
* Current kinepage message
*/
kinepage;
/**
* The current Archimedea missions and modifiers
*/
archimedeas;
/**
* The current calendar for 1999
*/
calendar;
/**
* Faceoff bonus current state
*/
faceoffBonus;
/**
* Warframe's annual Quest to Conquer Cancer donation count and next tier goal
*/
questToConquerCancer;
/**
* The current week's clan initiative rewards
*/
clanWeeklyInitiative;
/**
* Generates the worldstate json as a string into usable objects
*/
static async build(json, deps = defaultDeps) {
if (typeof json !== "string") throw new TypeError(`json needs to be a string, provided ${typeof json} : ${JSON.stringify(json)}`);
const data = JSON.parse(json);
const ws = new WorldState(data, deps);
ws.events = await parseAsyncArray(WorldEvent, data.Goals, deps);
ws.syndicateMissions = await parseAsyncArray(SyndicateMission, data.SyndicateMissions, deps, "syndicate");
return ws;
}
/**
* @param data The worldstate JSON string
* @param deps The options object
*/
constructor(data, deps = defaultDeps) {
deps = {
...defaultDeps,
...deps
};
this.timestamp = /* @__PURE__ */ new Date(data.Time * 1e3);
this.buildLabel = data.BuildLabel;
this.news = parseArray(News, safeArray(data.Events).filter((e) => typeof e.Messages.find((msg) => msg.LanguageCode === deps.locale) !== "undefined"), deps);
this.events = [];
this.alerts = parseArray(Alert, data.Alerts, deps);
[this.sortie] = parseArray(Sortie, data.Sorties, deps);
this.syndicateMissions = [];
this.fissures = parseArray(Fissure, data.ActiveMissions, deps).concat(parseArray(Fissure, data.VoidStorms, deps));
this.globalUpgrades = parseArray(GlobalUpgrade, data.GlobalUpgrades, deps);
this.flashSales = parseArray(FlashSale, data.FlashSales, deps);
this.invasions = parseArray(Invasion, data.Invasions, deps);
this.darkSectors = parseArray(DarkSector, data.BadlandNodes, deps);
this.voidTraders = parseArray(VoidTrader, data.VoidTraders, deps).sort((a, b) => a.activation.getTime() - b.activation.getTime());
[this.voidTrader] = this.voidTraders;
this.dailyDeals = parseArray(DailyDeal, data.DailyDeals, deps);
this.simaris = new Simaris(safeObj(data.LibraryInfo), deps);
this.conclaveChallenges = parseArray(ConclaveChallenge, data.PVPChallengeInstances, deps);
this.persistentEnemies = parseArray(PersistentEnemy, data.PersistentEnemies, deps);
this.earthCycle = new EarthCycle();
const cetusSynd = safeArray(data.SyndicateMissions).filter((syndicate) => syndicate.Tag === "CetusSyndicate");
const bountyEnd = parseDate(cetusSynd.length > 0 ? cetusSynd[0].Expiry : { $date: { $numberLong: 0 } });
this.cetusCycle = new CetusCycle(bountyEnd);
this.cambionCycle = new CambionCycle(this.cetusCycle);
this.zarimanCycle = new ZarimanCycle(bountyEnd);
this.weeklyChallenges = data.WeeklyChallenges ? new WeeklyChallenge(data.WeeklyChallenges) : void 0;
this.constructionProgress = new ConstructionProgress(data.ProjectPct);
this.vallisCycle = new VallisCycle();
if (data.SeasonInfo) this.nightwave = new Nightwave(data.SeasonInfo, deps);
const externalMissions = new Kuva(deps);
({kuva: this.kuva, arbitration: this.arbitration} = externalMissions);
if (!this.arbitration || !Object.keys(this.arbitration).length) this.arbitration = {
id: createHash("sha256").update("SolNode000", "utf8").digest("hex"),
node: "SolNode000",
nodeKey: "SolNode000",
activation: /* @__PURE__ */ new Date(0),
expiry: /* @__PURE__ */ new Date(864e13),
enemy: "Tenno",
type: "Unknown",
typeKey: "Unknown",
archwing: false,
sharkwing: false,
expired: true
};
this.steelPath = new SteelPathOfferings(deps);
[this.vaultTrader] = parseArray(VoidTrader, data.PrimeVaultTraders, {
...deps,
character: "Varzia"
});
[this.archonHunt] = parseArray(Sortie, data.LiteSorties, deps);
const choices = parseArray(DuviriChoice, safeArray(data.EndlessXpSchedule?.[0]?.CategoryChoices), deps);
this.duviriCycle = new DuviriCycle(choices);
[this.calendar] = parseArray(Calendar, data.KnownCalendarSeasons, deps);
this.archimedeas = parseArray(Archimedea, data.Conquests, deps);
({kinepage: this.kinepage, sentientOutposts: this.sentientOutposts, faceoffBonus: this.faceoffBonus, questToConquerCancer: this.questToConquerCancer} = new Tmp(data.Tmp, deps));
const clanWeeklyInitiative = parseArray(ClanInitiativeRewards, data.WeeklyVaultBonusRewards, deps);
this.clanWeeklyInitiative = clanWeeklyInitiative?.[0];
}
};
__decorate([
IsDate(),
Type(() => Date),
__decorateMetadata("design:type", typeof Date === "undefined" ? Object : Date)
], WorldState.prototype, "timestamp", void 0);
__decorate([IsString(), __decorateMetadata("design:type", String)], WorldState.prototype, "buildLabel", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => News),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "news", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => WorldEvent),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "events", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => Alert),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "alerts", void 0);
__decorate([
ValidateNested(),
Type(() => Sortie),
__decorateMetadata("design:type", typeof Sortie === "undefined" ? Object : Sortie)
], WorldState.prototype, "sortie", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => SyndicateMission),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "syndicateMissions", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => Fissure),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "fissures", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => GlobalUpgrade),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "globalUpgrades", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => FlashSale),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "flashSales", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => Invasion),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "invasions", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => DarkSector),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "darkSectors", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => VoidTrader),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "voidTraders", void 0);
__decorate([
ValidateNested(),
Type(() => VoidTrader),
__decorateMetadata("design:type", typeof VoidTrader === "undefined" ? Object : VoidTrader)
], WorldState.prototype, "voidTrader", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => DailyDeal),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "dailyDeals", void 0);
__decorate([
ValidateNested(),
Type(() => Simaris),
__decorateMetadata("design:type", typeof Simaris === "undefined" ? Object : Simaris)
], WorldState.prototype, "simaris", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => ConclaveChallenge),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "conclaveChallenges", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => PersistentEnemy),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "persistentEnemies", void 0);
__decorate([
ValidateNested(),
Type(() => EarthCycle),
__decorateMetadata("design:type", typeof EarthCycle === "undefined" ? Object : EarthCycle)
], WorldState.prototype, "earthCycle", void 0);
__decorate([
ValidateNested(),
Type(() => CetusCycle),
__decorateMetadata("design:type", typeof CetusCycle === "undefined" ? Object : CetusCycle)
], WorldState.prototype, "cetusCycle", void 0);
__decorate([
ValidateNested(),
Type(() => CambionCycle),
__decorateMetadata("design:type", typeof CambionCycle === "undefined" ? Object : CambionCycle)
], WorldState.prototype, "cambionCycle", void 0);
__decorate([
ValidateNested(),
Type(() => ZarimanCycle),
__decorateMetadata("design:type", typeof ZarimanCycle === "undefined" ? Object : ZarimanCycle)
], WorldState.prototype, "zarimanCycle", void 0);
__decorate([
IsOptional(),
ValidateNested(),
Type(() => WeeklyChallenge),
__decorateMetadata("design:type", typeof WeeklyChallenge === "undefined" ? Object : WeeklyChallenge)
], WorldState.prototype, "weeklyChallenges", void 0);
__decorate([
ValidateNested(),
Type(() => ConstructionProgress),
__decorateMetadata("design:type", typeof ConstructionProgress === "undefined" ? Object : ConstructionProgress)
], WorldState.prototype, "constructionProgress", void 0);
__decorate([
ValidateNested(),
Type(() => VallisCycle),
__decorateMetadata("design:type", typeof VallisCycle === "undefined" ? Object : VallisCycle)
], WorldState.prototype, "vallisCycle", void 0);
__decorate([
IsOptional(),
ValidateNested(),
Type(() => Nightwave),
__decorateMetadata("design:type", typeof Nightwave === "undefined" ? Object : Nightwave)
], WorldState.prototype, "nightwave", void 0);
__decorate([
IsOptional(),
IsArray(),
ValidateNested({ each: true }),
Type(() => ExternalMission),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "kuva", void 0);
__decorate([
IsOptional(),
ValidateNested(),
Type(() => ExternalMission),
__decorateMetadata("design:type", typeof ExternalMission === "undefined" ? Object : ExternalMission)
], WorldState.prototype, "arbitration", void 0);
__decorate([
ValidateNested(),
Type(() => SteelPathOfferings),
__decorateMetadata("design:type", typeof SteelPathOfferings === "undefined" ? Object : SteelPathOfferings)
], WorldState.prototype, "steelPath", void 0);
__decorate([
ValidateNested(),
Type(() => VoidTrader),
__decorateMetadata("design:type", typeof VoidTrader === "undefined" ? Object : VoidTrader)
], WorldState.prototype, "vaultTrader", void 0);
__decorate([
ValidateNested(),
Type(() => Sortie),
__decorateMetadata("design:type", typeof Sortie === "undefined" ? Object : Sortie)
], WorldState.prototype, "archonHunt", void 0);
__decorate([
ValidateNested(),
Type(() => DuviriCycle),
__decorateMetadata("design:type", typeof DuviriCycle === "undefined" ? Object : DuviriCycle)
], WorldState.prototype, "duviriCycle", void 0);
__decorate([
IsArray(),
ValidateNested({ each: true }),
Type(() => Archimedea),
__decorateMetadata("design:type", Array)
], WorldState.prototype, "archimedeas", void 0);
__decorate([
ValidateNested(),
Type(() => Calendar),
__decorateMetadata("design:type", typeof Calendar === "undefined" ? Object : Calendar)
], WorldState.prototype, "calendar", void 0);
__decorate([
ValidateNested(),
Type(() => ClanInitiativeRewards),
__decorateMetadata("design:type", typeof ClanInitiativeRewards === "undefined" ? Object : ClanInitiativeRewards)
], WorldState.prototype, "clanWeeklyInitiative", void 0);
var WorldState_default = async (json, deps) => WorldState.build(json, deps);
//#endregion
export { WorldState, WorldState_default as default, parseArray, parseAsyncArray };