Add launch section to manifest
This commit is contained in:
parent
cb242f6433
commit
a046c18ad4
7 changed files with 266804 additions and 373 deletions
266919
data/manifest.yaml
266919
data/manifest.yaml
File diff suppressed because it is too large
Load diff
|
@ -8096,6 +8096,7 @@
|
|||
* [Demon Pit](https://www.pcgamingwiki.com/wiki/?curid=145079)
|
||||
* [Demon Queen Melissa](https://www.pcgamingwiki.com/wiki/?curid=130672)
|
||||
* [Demon Robot Runner](https://www.pcgamingwiki.com/wiki/?curid=88150)
|
||||
* [Demon Slayer -Kimetsu no Yaiba- The Hinokami Chronicles](https://www.pcgamingwiki.com/wiki/?curid=166446)
|
||||
* [Demon Truck](https://www.pcgamingwiki.com/wiki/?curid=41495)
|
||||
* [Demon Turf](https://www.pcgamingwiki.com/wiki/?curid=161608)
|
||||
* [Demon Turf: Neon Splash](https://www.pcgamingwiki.com/wiki/?curid=177760)
|
||||
|
@ -9040,6 +9041,7 @@
|
|||
* [Dragon Sinker](https://www.pcgamingwiki.com/wiki/?curid=77255)
|
||||
* [Dragon Skies VR](https://www.pcgamingwiki.com/wiki/?curid=52622)
|
||||
* [Dragon Slayer](https://www.pcgamingwiki.com/wiki/?curid=149592)
|
||||
* [Dragon Slayer: The Legend of Heroes II](https://www.pcgamingwiki.com/wiki/?curid=174909)
|
||||
* [Dragon Souls](https://www.pcgamingwiki.com/wiki/?curid=53491)
|
||||
* [Dragon Spear](https://www.pcgamingwiki.com/wiki/?curid=108568)
|
||||
* [Dragon Spirits](https://www.pcgamingwiki.com/wiki/?curid=154322)
|
||||
|
@ -11247,6 +11249,7 @@
|
|||
* [Final Dusk](https://www.pcgamingwiki.com/wiki/?curid=49125)
|
||||
* [Final Fantasy Awakening](https://www.pcgamingwiki.com/wiki/?curid=26745)
|
||||
* [Final Fantasy III](https://www.pcgamingwiki.com/wiki/?curid=169624)
|
||||
* [Final Fantasy IV](https://www.pcgamingwiki.com/wiki/?curid=169625)
|
||||
* [Final Fantasy XI](https://www.pcgamingwiki.com/wiki/?curid=788)
|
||||
* [Final Fleet](https://www.pcgamingwiki.com/wiki/?curid=38791)
|
||||
* [Final Hope](https://www.pcgamingwiki.com/wiki/?curid=110158)
|
||||
|
@ -12526,6 +12529,7 @@
|
|||
* [Gene](https://www.pcgamingwiki.com/wiki/?curid=48845)
|
||||
* [Gene Rain](https://www.pcgamingwiki.com/wiki/?curid=100434)
|
||||
* [Gene Rain: Wind Tower](https://www.pcgamingwiki.com/wiki/?curid=149099)
|
||||
* [Geneforge](https://www.pcgamingwiki.com/wiki/?curid=10284)
|
||||
* [General Coco](https://www.pcgamingwiki.com/wiki/?curid=149368)
|
||||
* [General Horse and the Package of Doom](https://www.pcgamingwiki.com/wiki/?curid=113264)
|
||||
* [General Practitioner](https://www.pcgamingwiki.com/wiki/?curid=114154)
|
||||
|
@ -15872,6 +15876,7 @@
|
|||
* [IStorm](https://www.pcgamingwiki.com/wiki/?curid=60281)
|
||||
* [Istrolid](https://www.pcgamingwiki.com/wiki/?curid=38179)
|
||||
* [Isyium](https://www.pcgamingwiki.com/wiki/?curid=54806)
|
||||
* [It Came from Space and Ate Our Brains](https://www.pcgamingwiki.com/wiki/?curid=38329)
|
||||
* [It Comes Around - A Kinetic Novel](https://www.pcgamingwiki.com/wiki/?curid=50737)
|
||||
* [It comes from hell](https://www.pcgamingwiki.com/wiki/?curid=132678)
|
||||
* [It Could Have Been Me](https://www.pcgamingwiki.com/wiki/?curid=135399)
|
||||
|
@ -21169,6 +21174,7 @@
|
|||
* [Nostradamus - The Four Horsemen of the Apocalypse](https://www.pcgamingwiki.com/wiki/?curid=80418)
|
||||
* [Not a Prank](https://www.pcgamingwiki.com/wiki/?curid=139203)
|
||||
* [Not Dying Today](https://www.pcgamingwiki.com/wiki/?curid=55764)
|
||||
* [Not for Broadcast](https://www.pcgamingwiki.com/wiki/?curid=150852)
|
||||
* [Not Heaven](https://www.pcgamingwiki.com/wiki/?curid=121145)
|
||||
* [Not in Heaven](https://www.pcgamingwiki.com/wiki/?curid=121041)
|
||||
* [Not My Day!](https://www.pcgamingwiki.com/wiki/?curid=120965)
|
||||
|
@ -21613,6 +21619,7 @@
|
|||
* [One Small Fire at a Time](https://www.pcgamingwiki.com/wiki/?curid=33858)
|
||||
* [One Sole Purpose](https://www.pcgamingwiki.com/wiki/?curid=52634)
|
||||
* [One Star](https://www.pcgamingwiki.com/wiki/?curid=60928)
|
||||
* [One Step from Eden](https://www.pcgamingwiki.com/wiki/?curid=122848)
|
||||
* [One Strike](https://www.pcgamingwiki.com/wiki/?curid=74195)
|
||||
* [One Synth](https://www.pcgamingwiki.com/wiki/?curid=127726)
|
||||
* [One Tank to Rule Them All](https://www.pcgamingwiki.com/wiki/?curid=82105)
|
||||
|
@ -22212,6 +22219,7 @@
|
|||
* [Paradise City VR](https://www.pcgamingwiki.com/wiki/?curid=124016)
|
||||
* [Paradise Cleaning!](https://www.pcgamingwiki.com/wiki/?curid=146078)
|
||||
* [Paradise Cracked](https://www.pcgamingwiki.com/wiki/?curid=57943)
|
||||
* [Paradise Lost](https://www.pcgamingwiki.com/wiki/?curid=161803)
|
||||
* [Paradise Lost (PolyAmorous)](https://www.pcgamingwiki.com/wiki/?curid=137402)
|
||||
* [Paradise Lost: FPS Cosmic Horror Game](https://www.pcgamingwiki.com/wiki/?curid=76601)
|
||||
* [Paradox Escape Route](https://www.pcgamingwiki.com/wiki/?curid=148613)
|
||||
|
@ -22235,6 +22243,7 @@
|
|||
* [PARANOIHELL](https://www.pcgamingwiki.com/wiki/?curid=150723)
|
||||
* [Paranormal Detective: Escape from the 80's](https://www.pcgamingwiki.com/wiki/?curid=142066)
|
||||
* [Paranormal Files: Hook Man's Legend](https://www.pcgamingwiki.com/wiki/?curid=149382)
|
||||
* [Paranormal HK](https://www.pcgamingwiki.com/wiki/?curid=153800)
|
||||
* [Paranormal Psychosis](https://www.pcgamingwiki.com/wiki/?curid=34527)
|
||||
* [Paranormal Pursuit: The Gifted One](https://www.pcgamingwiki.com/wiki/?curid=55289)
|
||||
* [Paranormal Teens](https://www.pcgamingwiki.com/wiki/?curid=55690)
|
||||
|
@ -24150,6 +24159,7 @@
|
|||
* [RACE Injection](https://www.pcgamingwiki.com/wiki/?curid=40857)
|
||||
* [RACE On](https://www.pcgamingwiki.com/wiki/?curid=41218)
|
||||
* [Race Race Racer](https://www.pcgamingwiki.com/wiki/?curid=152751)
|
||||
* [Race to Mars](https://www.pcgamingwiki.com/wiki/?curid=15682)
|
||||
* [Race with Ryan](https://www.pcgamingwiki.com/wiki/?curid=145134)
|
||||
* [Race! Make 'm finish...](https://www.pcgamingwiki.com/wiki/?curid=155914)
|
||||
* [Race.a.bit](https://www.pcgamingwiki.com/wiki/?curid=34099)
|
||||
|
@ -28385,6 +28395,7 @@
|
|||
* [Split Bullet](https://www.pcgamingwiki.com/wiki/?curid=51863)
|
||||
* [Split or Steal](https://www.pcgamingwiki.com/wiki/?curid=150576)
|
||||
* [Split Signal](https://www.pcgamingwiki.com/wiki/?curid=157323)
|
||||
* [Splitgate](https://www.pcgamingwiki.com/wiki/?curid=130533)
|
||||
* [Splitmind](https://www.pcgamingwiki.com/wiki/?curid=55610)
|
||||
* [Splitter Critters](https://www.pcgamingwiki.com/wiki/?curid=81749)
|
||||
* [Splody](https://www.pcgamingwiki.com/wiki/?curid=40169)
|
||||
|
@ -29881,6 +29892,7 @@
|
|||
* [Synthesis Universe -Episode 00-](https://www.pcgamingwiki.com/wiki/?curid=150505)
|
||||
* [Synthetic Dreams](https://www.pcgamingwiki.com/wiki/?curid=66444)
|
||||
* [Synthetic Love](https://www.pcgamingwiki.com/wiki/?curid=146136)
|
||||
* [Synthetik: Legion Rising](https://www.pcgamingwiki.com/wiki/?curid=81934)
|
||||
* [Synthrally](https://www.pcgamingwiki.com/wiki/?curid=91224)
|
||||
* [Synthrun](https://www.pcgamingwiki.com/wiki/?curid=127359)
|
||||
* [Synthwave Dream '85](https://www.pcgamingwiki.com/wiki/?curid=107712)
|
||||
|
|
|
@ -6,11 +6,25 @@ definitions:
|
|||
$ref: "#/definitions/Os"
|
||||
store:
|
||||
$ref: "#/definitions/Store"
|
||||
LaunchConstraint:
|
||||
type: object
|
||||
properties:
|
||||
bit:
|
||||
$ref: "#/definitions/Bit"
|
||||
os:
|
||||
$ref: "#/definitions/Os"
|
||||
store:
|
||||
$ref: "#/definitions/Store"
|
||||
RegistryConstraint:
|
||||
type: object
|
||||
properties:
|
||||
store:
|
||||
$ref: "#/definitions/Store"
|
||||
Bit:
|
||||
type: integer
|
||||
enum:
|
||||
- 32
|
||||
- 64
|
||||
Os:
|
||||
type: string
|
||||
enum:
|
||||
|
@ -53,6 +67,21 @@ additionalProperties:
|
|||
$ref: "#/definitions/FileConstraint"
|
||||
installDir:
|
||||
type: object
|
||||
launch:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
arguments:
|
||||
type: string
|
||||
workingDir:
|
||||
type: string
|
||||
when:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/LaunchConstraint"
|
||||
registry:
|
||||
type: object
|
||||
additionalProperties:
|
||||
|
|
|
@ -6,11 +6,22 @@ definitions:
|
|||
$ref: "#/definitions/Os"
|
||||
store:
|
||||
$ref: "#/definitions/Store"
|
||||
LaunchConstraint:
|
||||
type: object
|
||||
properties:
|
||||
bit:
|
||||
$ref: "#/definitions/Bit"
|
||||
os:
|
||||
$ref: "#/definitions/Os"
|
||||
store:
|
||||
$ref: "#/definitions/Store"
|
||||
RegistryConstraint:
|
||||
type: object
|
||||
properties:
|
||||
store:
|
||||
$ref: "#/definitions/Store"
|
||||
Bit:
|
||||
type: integer
|
||||
Os:
|
||||
type: string
|
||||
Store:
|
||||
|
@ -37,6 +48,21 @@ additionalProperties:
|
|||
$ref: "#/definitions/FileConstraint"
|
||||
installDir:
|
||||
type: object
|
||||
launch:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
arguments:
|
||||
type: string
|
||||
workingDir:
|
||||
type: string
|
||||
when:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/LaunchConstraint"
|
||||
registry:
|
||||
type: object
|
||||
additionalProperties:
|
||||
|
|
12
src/bin.ts
12
src/bin.ts
|
@ -43,6 +43,7 @@ async function main() {
|
|||
"tooBroad",
|
||||
"tooBroadUntagged",
|
||||
"steam",
|
||||
"local",
|
||||
],
|
||||
string: [
|
||||
"skipUntil",
|
||||
|
@ -53,7 +54,7 @@ async function main() {
|
|||
wikiCache.load();
|
||||
const wikiMetaCache = new WikiMetaCacheFile();
|
||||
wikiMetaCache.load();
|
||||
const steamCache = new SteamGameCacheFile(await getSteamClient());
|
||||
const steamCache = new SteamGameCacheFile(getSteamClient);
|
||||
steamCache.load();
|
||||
const manifest = new ManifestFile();
|
||||
manifest.load();
|
||||
|
@ -107,6 +108,7 @@ async function main() {
|
|||
},
|
||||
args.limit ?? 25,
|
||||
steamCache,
|
||||
args.local,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -115,7 +117,9 @@ async function main() {
|
|||
steamCache.save();
|
||||
manifest.save();
|
||||
saveMissingGames(wikiCache.data, manifest.data);
|
||||
steamCache.steamClient.logOff();
|
||||
if (steamCache.steamClient) {
|
||||
steamCache.steamClient.logOff();
|
||||
}
|
||||
process.exit(0);
|
||||
} catch (e) {
|
||||
wikiCache.save();
|
||||
|
@ -123,7 +127,9 @@ async function main() {
|
|||
steamCache.save();
|
||||
manifest.save();
|
||||
saveMissingGames(wikiCache.data, manifest.data);
|
||||
steamCache.steamClient.logOff();
|
||||
if (steamCache.steamClient) {
|
||||
steamCache.steamClient.logOff();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
157
src/manifest.ts
157
src/manifest.ts
|
@ -1,9 +1,11 @@
|
|||
import { DELAY_BETWEEN_GAMES_MS, REPO, YamlFile } from ".";
|
||||
import { SteamGameCacheFile } from "./steam";
|
||||
import { SteamGameCache, SteamGameCacheFile } from "./steam";
|
||||
import { WikiGameCache, getGame, pathIsTooBroad } from "./wiki";
|
||||
|
||||
export type Os = "dos" | "linux" | "mac" | "windows";
|
||||
|
||||
export type Bit = 32 | 64;
|
||||
|
||||
export type Store = "epic" | "gog" | "microsoft" | "steam" | "uplay" | "origin";
|
||||
|
||||
export type Tag = "config" | "save";
|
||||
|
@ -15,16 +17,23 @@ export interface Manifest {
|
|||
export interface Game {
|
||||
files?: {
|
||||
[path: string]: {
|
||||
when?: Array<Constraint>,
|
||||
when?: Array<Omit<Constraint, "bit">>,
|
||||
tags?: Array<Tag>,
|
||||
}
|
||||
};
|
||||
installDir?: {
|
||||
[name: string]: {}
|
||||
};
|
||||
launch?: {
|
||||
[path: string]: Array<{
|
||||
arguments?: string;
|
||||
workingDir?: string;
|
||||
when?: Array<Constraint>,
|
||||
}>
|
||||
},
|
||||
registry?: {
|
||||
[path: string]: {
|
||||
when?: Array<Omit<Constraint, "os">>,
|
||||
when?: Array<Omit<Constraint, "bit" | "os">>,
|
||||
tags?: Array<Tag>,
|
||||
}
|
||||
};
|
||||
|
@ -35,9 +44,120 @@ export interface Game {
|
|||
|
||||
export interface Constraint {
|
||||
os?: Os;
|
||||
bit?: Bit;
|
||||
store?: Store;
|
||||
}
|
||||
|
||||
function normalizeLaunchPath(raw: string): string | undefined {
|
||||
if (raw.includes("://")) {
|
||||
return raw;
|
||||
}
|
||||
const standardized = raw
|
||||
.replace(/\\/g, "/")
|
||||
.replace(/\/\//g, "/")
|
||||
.replace(/\/(?=$)/g, "")
|
||||
.replace(/^.\//, "")
|
||||
.replace(/^\/+/, "")
|
||||
.trim();
|
||||
if (standardized.length === 0 || standardized === ".") {
|
||||
return undefined;
|
||||
}
|
||||
return `<base>/${standardized}`;
|
||||
}
|
||||
|
||||
function doLaunchPathsMatch(fromSteam: string | undefined, fromManifest: string | undefined): boolean {
|
||||
if (fromSteam === undefined) {
|
||||
return fromManifest === undefined;
|
||||
} else {
|
||||
return normalizeLaunchPath(fromSteam) === fromManifest;
|
||||
}
|
||||
}
|
||||
|
||||
function integrateSteamData(game: Game, appInfo: SteamGameCache[""]) {
|
||||
if (appInfo.installDir !== undefined) {
|
||||
game.installDir = {[appInfo.installDir]: {}};
|
||||
}
|
||||
if (appInfo.launch !== undefined) {
|
||||
delete game.launch;
|
||||
for (const incoming of appInfo.launch) {
|
||||
if (
|
||||
incoming.executable === undefined ||
|
||||
incoming.executable.includes("://") ||
|
||||
![undefined, "default", "none"].includes(incoming.type) ||
|
||||
incoming.config?.betakey !== undefined ||
|
||||
incoming.config?.ownsdlc !== undefined
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const os: Os | undefined = {
|
||||
"windows": "windows",
|
||||
"macos": "mac",
|
||||
"macosx": "mac",
|
||||
"linux": "linux",
|
||||
}[incoming.config?.oslist] as Os;
|
||||
const bit: Bit | undefined = {
|
||||
"32": 32,
|
||||
"64": 64,
|
||||
}[incoming.config?.osarch] as Bit;
|
||||
const when: Constraint = {os, bit, store: "steam"};
|
||||
if (when.os === undefined) {
|
||||
delete when.os;
|
||||
}
|
||||
if (when.bit === undefined) {
|
||||
delete when.bit;
|
||||
}
|
||||
|
||||
let foundExisting = false;
|
||||
for (const [existingExecutable, existingOptions] of Object.entries(game.launch ?? {})) {
|
||||
for (const existing of existingOptions) {
|
||||
if (
|
||||
incoming.arguments === existing.arguments &&
|
||||
doLaunchPathsMatch(incoming.executable, existingExecutable) &&
|
||||
doLaunchPathsMatch(incoming.workingdir, existing.workingDir)
|
||||
) {
|
||||
foundExisting = true;
|
||||
if (existing.when === undefined) {
|
||||
existing.when = [];
|
||||
}
|
||||
if (existing.when.every(x => x.os !== os && x.bit !== bit && x.store !== "steam")) {
|
||||
existing.when.push(when);
|
||||
}
|
||||
if (existing.when.length === 0) {
|
||||
delete existing.when;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundExisting) {
|
||||
const key = normalizeLaunchPath(incoming.executable);
|
||||
if (key === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const candidate: Game["launch"][""][0] = {when: [when]};
|
||||
if (incoming.arguments !== undefined) {
|
||||
candidate.arguments = incoming.arguments;
|
||||
}
|
||||
if (incoming.workingdir !== undefined) {
|
||||
const workingDir = normalizeLaunchPath(incoming.workingdir);
|
||||
if (workingDir !== undefined) {
|
||||
candidate.workingDir = workingDir;
|
||||
}
|
||||
}
|
||||
|
||||
if (game.launch === undefined) {
|
||||
game.launch = {};
|
||||
}
|
||||
if (game.launch[key] === undefined) {
|
||||
game.launch[key] = [];
|
||||
}
|
||||
game.launch[key].push(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ManifestFile extends YamlFile<Manifest> {
|
||||
path = `${REPO}/data/manifest.yaml`;
|
||||
defaultData = {};
|
||||
|
@ -62,6 +182,7 @@ export class ManifestFile extends YamlFile<Manifest> {
|
|||
},
|
||||
limit: number | undefined,
|
||||
steamCache: SteamGameCacheFile,
|
||||
local: boolean,
|
||||
): Promise<void> {
|
||||
let i = 0;
|
||||
let foundSkipUntil = false;
|
||||
|
@ -125,18 +246,20 @@ export class ManifestFile extends YamlFile<Manifest> {
|
|||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
if (limit > 0 && i > limit) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (info.renamedFrom) {
|
||||
for (const oldName of info.renamedFrom) {
|
||||
delete this.data[oldName];
|
||||
}
|
||||
}
|
||||
|
||||
const [verifiedTitle, game] = await getGame(title, wikiCache);
|
||||
let verifiedTitle: string;
|
||||
let game: Game;
|
||||
if (local) {
|
||||
[verifiedTitle, game] = [title, this.data[title] ?? {}];
|
||||
} else {
|
||||
[verifiedTitle, game] = await getGame(title, wikiCache);
|
||||
}
|
||||
|
||||
delete wikiCache[verifiedTitle].recentlyChanged;
|
||||
|
||||
if (verifiedTitle !== title) {
|
||||
|
@ -149,16 +272,18 @@ export class ManifestFile extends YamlFile<Manifest> {
|
|||
}
|
||||
if (game.steam?.id !== undefined) {
|
||||
const appInfo = await steamCache.getAppInfo(game.steam.id);
|
||||
if (appInfo.installDir !== undefined) {
|
||||
if (game.installDir === undefined) {
|
||||
game.installDir = {}
|
||||
}
|
||||
game.installDir[appInfo.installDir] = {}
|
||||
}
|
||||
integrateSteamData(game, appInfo);
|
||||
}
|
||||
this.data[verifiedTitle] = game;
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, DELAY_BETWEEN_GAMES_MS));
|
||||
if (!local) {
|
||||
await new Promise(resolve => setTimeout(resolve, DELAY_BETWEEN_GAMES_MS));
|
||||
}
|
||||
|
||||
i++;
|
||||
if (limit > 0 && i > limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
22
src/steam.ts
22
src/steam.ts
|
@ -1,12 +1,23 @@
|
|||
import { DELAY_BETWEEN_GAMES_MS, REPO, YamlFile } from ".";
|
||||
import * as SteamUser from "steam-user";
|
||||
|
||||
type SteamGameCache = {
|
||||
export type SteamGameCache = {
|
||||
[appId: string]: {
|
||||
installDir?: string,
|
||||
unknown?: boolean,
|
||||
nameLocalized?: Map<string, string>;
|
||||
launch?: Array<object>;
|
||||
launch?: Array<{
|
||||
executable?: string;
|
||||
arguments?: string;
|
||||
workingdir?: string;
|
||||
type?: string;
|
||||
config?: {
|
||||
betakey?: string;
|
||||
osarch?: string;
|
||||
oslist?: string;
|
||||
ownsdlc?: string;
|
||||
},
|
||||
}>;
|
||||
irregular?: boolean;
|
||||
};
|
||||
};
|
||||
|
@ -14,8 +25,9 @@ type SteamGameCache = {
|
|||
export class SteamGameCacheFile extends YamlFile<SteamGameCache> {
|
||||
path = `${REPO}/data/steam-game-cache.yaml`;
|
||||
defaultData = {};
|
||||
steamClient: SteamUser | null = null;
|
||||
|
||||
constructor(public steamClient: SteamUser) {
|
||||
constructor(private makeSteamClient: () => Promise<SteamUser>) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
@ -33,6 +45,10 @@ export class SteamGameCacheFile extends YamlFile<SteamGameCache> {
|
|||
return this.data[key];
|
||||
}
|
||||
|
||||
if (this.steamClient === null) {
|
||||
this.steamClient = await this.makeSteamClient();
|
||||
}
|
||||
|
||||
const info: SteamProductInfoResponse = await this.steamClient.getProductInfo([appId], []);
|
||||
|
||||
if (info.unknownApps.includes(appId)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue