Add launch section to manifest
This commit is contained in:
parent
cb242f6433
commit
a046c18ad4
7 changed files with 266804 additions and 373 deletions
266899
data/manifest.yaml
266899
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 Pit](https://www.pcgamingwiki.com/wiki/?curid=145079)
|
||||||
* [Demon Queen Melissa](https://www.pcgamingwiki.com/wiki/?curid=130672)
|
* [Demon Queen Melissa](https://www.pcgamingwiki.com/wiki/?curid=130672)
|
||||||
* [Demon Robot Runner](https://www.pcgamingwiki.com/wiki/?curid=88150)
|
* [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 Truck](https://www.pcgamingwiki.com/wiki/?curid=41495)
|
||||||
* [Demon Turf](https://www.pcgamingwiki.com/wiki/?curid=161608)
|
* [Demon Turf](https://www.pcgamingwiki.com/wiki/?curid=161608)
|
||||||
* [Demon Turf: Neon Splash](https://www.pcgamingwiki.com/wiki/?curid=177760)
|
* [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 Sinker](https://www.pcgamingwiki.com/wiki/?curid=77255)
|
||||||
* [Dragon Skies VR](https://www.pcgamingwiki.com/wiki/?curid=52622)
|
* [Dragon Skies VR](https://www.pcgamingwiki.com/wiki/?curid=52622)
|
||||||
* [Dragon Slayer](https://www.pcgamingwiki.com/wiki/?curid=149592)
|
* [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 Souls](https://www.pcgamingwiki.com/wiki/?curid=53491)
|
||||||
* [Dragon Spear](https://www.pcgamingwiki.com/wiki/?curid=108568)
|
* [Dragon Spear](https://www.pcgamingwiki.com/wiki/?curid=108568)
|
||||||
* [Dragon Spirits](https://www.pcgamingwiki.com/wiki/?curid=154322)
|
* [Dragon Spirits](https://www.pcgamingwiki.com/wiki/?curid=154322)
|
||||||
|
@ -11247,6 +11249,7 @@
|
||||||
* [Final Dusk](https://www.pcgamingwiki.com/wiki/?curid=49125)
|
* [Final Dusk](https://www.pcgamingwiki.com/wiki/?curid=49125)
|
||||||
* [Final Fantasy Awakening](https://www.pcgamingwiki.com/wiki/?curid=26745)
|
* [Final Fantasy Awakening](https://www.pcgamingwiki.com/wiki/?curid=26745)
|
||||||
* [Final Fantasy III](https://www.pcgamingwiki.com/wiki/?curid=169624)
|
* [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 Fantasy XI](https://www.pcgamingwiki.com/wiki/?curid=788)
|
||||||
* [Final Fleet](https://www.pcgamingwiki.com/wiki/?curid=38791)
|
* [Final Fleet](https://www.pcgamingwiki.com/wiki/?curid=38791)
|
||||||
* [Final Hope](https://www.pcgamingwiki.com/wiki/?curid=110158)
|
* [Final Hope](https://www.pcgamingwiki.com/wiki/?curid=110158)
|
||||||
|
@ -12526,6 +12529,7 @@
|
||||||
* [Gene](https://www.pcgamingwiki.com/wiki/?curid=48845)
|
* [Gene](https://www.pcgamingwiki.com/wiki/?curid=48845)
|
||||||
* [Gene Rain](https://www.pcgamingwiki.com/wiki/?curid=100434)
|
* [Gene Rain](https://www.pcgamingwiki.com/wiki/?curid=100434)
|
||||||
* [Gene Rain: Wind Tower](https://www.pcgamingwiki.com/wiki/?curid=149099)
|
* [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 Coco](https://www.pcgamingwiki.com/wiki/?curid=149368)
|
||||||
* [General Horse and the Package of Doom](https://www.pcgamingwiki.com/wiki/?curid=113264)
|
* [General Horse and the Package of Doom](https://www.pcgamingwiki.com/wiki/?curid=113264)
|
||||||
* [General Practitioner](https://www.pcgamingwiki.com/wiki/?curid=114154)
|
* [General Practitioner](https://www.pcgamingwiki.com/wiki/?curid=114154)
|
||||||
|
@ -15872,6 +15876,7 @@
|
||||||
* [IStorm](https://www.pcgamingwiki.com/wiki/?curid=60281)
|
* [IStorm](https://www.pcgamingwiki.com/wiki/?curid=60281)
|
||||||
* [Istrolid](https://www.pcgamingwiki.com/wiki/?curid=38179)
|
* [Istrolid](https://www.pcgamingwiki.com/wiki/?curid=38179)
|
||||||
* [Isyium](https://www.pcgamingwiki.com/wiki/?curid=54806)
|
* [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 Around - A Kinetic Novel](https://www.pcgamingwiki.com/wiki/?curid=50737)
|
||||||
* [It comes from hell](https://www.pcgamingwiki.com/wiki/?curid=132678)
|
* [It comes from hell](https://www.pcgamingwiki.com/wiki/?curid=132678)
|
||||||
* [It Could Have Been Me](https://www.pcgamingwiki.com/wiki/?curid=135399)
|
* [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)
|
* [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 a Prank](https://www.pcgamingwiki.com/wiki/?curid=139203)
|
||||||
* [Not Dying Today](https://www.pcgamingwiki.com/wiki/?curid=55764)
|
* [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 Heaven](https://www.pcgamingwiki.com/wiki/?curid=121145)
|
||||||
* [Not in Heaven](https://www.pcgamingwiki.com/wiki/?curid=121041)
|
* [Not in Heaven](https://www.pcgamingwiki.com/wiki/?curid=121041)
|
||||||
* [Not My Day!](https://www.pcgamingwiki.com/wiki/?curid=120965)
|
* [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 Small Fire at a Time](https://www.pcgamingwiki.com/wiki/?curid=33858)
|
||||||
* [One Sole Purpose](https://www.pcgamingwiki.com/wiki/?curid=52634)
|
* [One Sole Purpose](https://www.pcgamingwiki.com/wiki/?curid=52634)
|
||||||
* [One Star](https://www.pcgamingwiki.com/wiki/?curid=60928)
|
* [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 Strike](https://www.pcgamingwiki.com/wiki/?curid=74195)
|
||||||
* [One Synth](https://www.pcgamingwiki.com/wiki/?curid=127726)
|
* [One Synth](https://www.pcgamingwiki.com/wiki/?curid=127726)
|
||||||
* [One Tank to Rule Them All](https://www.pcgamingwiki.com/wiki/?curid=82105)
|
* [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 City VR](https://www.pcgamingwiki.com/wiki/?curid=124016)
|
||||||
* [Paradise Cleaning!](https://www.pcgamingwiki.com/wiki/?curid=146078)
|
* [Paradise Cleaning!](https://www.pcgamingwiki.com/wiki/?curid=146078)
|
||||||
* [Paradise Cracked](https://www.pcgamingwiki.com/wiki/?curid=57943)
|
* [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 (PolyAmorous)](https://www.pcgamingwiki.com/wiki/?curid=137402)
|
||||||
* [Paradise Lost: FPS Cosmic Horror Game](https://www.pcgamingwiki.com/wiki/?curid=76601)
|
* [Paradise Lost: FPS Cosmic Horror Game](https://www.pcgamingwiki.com/wiki/?curid=76601)
|
||||||
* [Paradox Escape Route](https://www.pcgamingwiki.com/wiki/?curid=148613)
|
* [Paradox Escape Route](https://www.pcgamingwiki.com/wiki/?curid=148613)
|
||||||
|
@ -22235,6 +22243,7 @@
|
||||||
* [PARANOIHELL](https://www.pcgamingwiki.com/wiki/?curid=150723)
|
* [PARANOIHELL](https://www.pcgamingwiki.com/wiki/?curid=150723)
|
||||||
* [Paranormal Detective: Escape from the 80's](https://www.pcgamingwiki.com/wiki/?curid=142066)
|
* [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 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 Psychosis](https://www.pcgamingwiki.com/wiki/?curid=34527)
|
||||||
* [Paranormal Pursuit: The Gifted One](https://www.pcgamingwiki.com/wiki/?curid=55289)
|
* [Paranormal Pursuit: The Gifted One](https://www.pcgamingwiki.com/wiki/?curid=55289)
|
||||||
* [Paranormal Teens](https://www.pcgamingwiki.com/wiki/?curid=55690)
|
* [Paranormal Teens](https://www.pcgamingwiki.com/wiki/?curid=55690)
|
||||||
|
@ -24150,6 +24159,7 @@
|
||||||
* [RACE Injection](https://www.pcgamingwiki.com/wiki/?curid=40857)
|
* [RACE Injection](https://www.pcgamingwiki.com/wiki/?curid=40857)
|
||||||
* [RACE On](https://www.pcgamingwiki.com/wiki/?curid=41218)
|
* [RACE On](https://www.pcgamingwiki.com/wiki/?curid=41218)
|
||||||
* [Race Race Racer](https://www.pcgamingwiki.com/wiki/?curid=152751)
|
* [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 with Ryan](https://www.pcgamingwiki.com/wiki/?curid=145134)
|
||||||
* [Race! Make 'm finish...](https://www.pcgamingwiki.com/wiki/?curid=155914)
|
* [Race! Make 'm finish...](https://www.pcgamingwiki.com/wiki/?curid=155914)
|
||||||
* [Race.a.bit](https://www.pcgamingwiki.com/wiki/?curid=34099)
|
* [Race.a.bit](https://www.pcgamingwiki.com/wiki/?curid=34099)
|
||||||
|
@ -28385,6 +28395,7 @@
|
||||||
* [Split Bullet](https://www.pcgamingwiki.com/wiki/?curid=51863)
|
* [Split Bullet](https://www.pcgamingwiki.com/wiki/?curid=51863)
|
||||||
* [Split or Steal](https://www.pcgamingwiki.com/wiki/?curid=150576)
|
* [Split or Steal](https://www.pcgamingwiki.com/wiki/?curid=150576)
|
||||||
* [Split Signal](https://www.pcgamingwiki.com/wiki/?curid=157323)
|
* [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)
|
* [Splitmind](https://www.pcgamingwiki.com/wiki/?curid=55610)
|
||||||
* [Splitter Critters](https://www.pcgamingwiki.com/wiki/?curid=81749)
|
* [Splitter Critters](https://www.pcgamingwiki.com/wiki/?curid=81749)
|
||||||
* [Splody](https://www.pcgamingwiki.com/wiki/?curid=40169)
|
* [Splody](https://www.pcgamingwiki.com/wiki/?curid=40169)
|
||||||
|
@ -29881,6 +29892,7 @@
|
||||||
* [Synthesis Universe -Episode 00-](https://www.pcgamingwiki.com/wiki/?curid=150505)
|
* [Synthesis Universe -Episode 00-](https://www.pcgamingwiki.com/wiki/?curid=150505)
|
||||||
* [Synthetic Dreams](https://www.pcgamingwiki.com/wiki/?curid=66444)
|
* [Synthetic Dreams](https://www.pcgamingwiki.com/wiki/?curid=66444)
|
||||||
* [Synthetic Love](https://www.pcgamingwiki.com/wiki/?curid=146136)
|
* [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)
|
* [Synthrally](https://www.pcgamingwiki.com/wiki/?curid=91224)
|
||||||
* [Synthrun](https://www.pcgamingwiki.com/wiki/?curid=127359)
|
* [Synthrun](https://www.pcgamingwiki.com/wiki/?curid=127359)
|
||||||
* [Synthwave Dream '85](https://www.pcgamingwiki.com/wiki/?curid=107712)
|
* [Synthwave Dream '85](https://www.pcgamingwiki.com/wiki/?curid=107712)
|
||||||
|
|
|
@ -6,11 +6,25 @@ definitions:
|
||||||
$ref: "#/definitions/Os"
|
$ref: "#/definitions/Os"
|
||||||
store:
|
store:
|
||||||
$ref: "#/definitions/Store"
|
$ref: "#/definitions/Store"
|
||||||
|
LaunchConstraint:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
bit:
|
||||||
|
$ref: "#/definitions/Bit"
|
||||||
|
os:
|
||||||
|
$ref: "#/definitions/Os"
|
||||||
|
store:
|
||||||
|
$ref: "#/definitions/Store"
|
||||||
RegistryConstraint:
|
RegistryConstraint:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
store:
|
store:
|
||||||
$ref: "#/definitions/Store"
|
$ref: "#/definitions/Store"
|
||||||
|
Bit:
|
||||||
|
type: integer
|
||||||
|
enum:
|
||||||
|
- 32
|
||||||
|
- 64
|
||||||
Os:
|
Os:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
|
@ -53,6 +67,21 @@ additionalProperties:
|
||||||
$ref: "#/definitions/FileConstraint"
|
$ref: "#/definitions/FileConstraint"
|
||||||
installDir:
|
installDir:
|
||||||
type: object
|
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:
|
registry:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
|
|
@ -6,11 +6,22 @@ definitions:
|
||||||
$ref: "#/definitions/Os"
|
$ref: "#/definitions/Os"
|
||||||
store:
|
store:
|
||||||
$ref: "#/definitions/Store"
|
$ref: "#/definitions/Store"
|
||||||
|
LaunchConstraint:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
bit:
|
||||||
|
$ref: "#/definitions/Bit"
|
||||||
|
os:
|
||||||
|
$ref: "#/definitions/Os"
|
||||||
|
store:
|
||||||
|
$ref: "#/definitions/Store"
|
||||||
RegistryConstraint:
|
RegistryConstraint:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
store:
|
store:
|
||||||
$ref: "#/definitions/Store"
|
$ref: "#/definitions/Store"
|
||||||
|
Bit:
|
||||||
|
type: integer
|
||||||
Os:
|
Os:
|
||||||
type: string
|
type: string
|
||||||
Store:
|
Store:
|
||||||
|
@ -37,6 +48,21 @@ additionalProperties:
|
||||||
$ref: "#/definitions/FileConstraint"
|
$ref: "#/definitions/FileConstraint"
|
||||||
installDir:
|
installDir:
|
||||||
type: object
|
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:
|
registry:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
|
|
@ -43,6 +43,7 @@ async function main() {
|
||||||
"tooBroad",
|
"tooBroad",
|
||||||
"tooBroadUntagged",
|
"tooBroadUntagged",
|
||||||
"steam",
|
"steam",
|
||||||
|
"local",
|
||||||
],
|
],
|
||||||
string: [
|
string: [
|
||||||
"skipUntil",
|
"skipUntil",
|
||||||
|
@ -53,7 +54,7 @@ async function main() {
|
||||||
wikiCache.load();
|
wikiCache.load();
|
||||||
const wikiMetaCache = new WikiMetaCacheFile();
|
const wikiMetaCache = new WikiMetaCacheFile();
|
||||||
wikiMetaCache.load();
|
wikiMetaCache.load();
|
||||||
const steamCache = new SteamGameCacheFile(await getSteamClient());
|
const steamCache = new SteamGameCacheFile(getSteamClient);
|
||||||
steamCache.load();
|
steamCache.load();
|
||||||
const manifest = new ManifestFile();
|
const manifest = new ManifestFile();
|
||||||
manifest.load();
|
manifest.load();
|
||||||
|
@ -107,6 +108,7 @@ async function main() {
|
||||||
},
|
},
|
||||||
args.limit ?? 25,
|
args.limit ?? 25,
|
||||||
steamCache,
|
steamCache,
|
||||||
|
args.local,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +117,9 @@ async function main() {
|
||||||
steamCache.save();
|
steamCache.save();
|
||||||
manifest.save();
|
manifest.save();
|
||||||
saveMissingGames(wikiCache.data, manifest.data);
|
saveMissingGames(wikiCache.data, manifest.data);
|
||||||
|
if (steamCache.steamClient) {
|
||||||
steamCache.steamClient.logOff();
|
steamCache.steamClient.logOff();
|
||||||
|
}
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
wikiCache.save();
|
wikiCache.save();
|
||||||
|
@ -123,7 +127,9 @@ async function main() {
|
||||||
steamCache.save();
|
steamCache.save();
|
||||||
manifest.save();
|
manifest.save();
|
||||||
saveMissingGames(wikiCache.data, manifest.data);
|
saveMissingGames(wikiCache.data, manifest.data);
|
||||||
|
if (steamCache.steamClient) {
|
||||||
steamCache.steamClient.logOff();
|
steamCache.steamClient.logOff();
|
||||||
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
155
src/manifest.ts
155
src/manifest.ts
|
@ -1,9 +1,11 @@
|
||||||
import { DELAY_BETWEEN_GAMES_MS, REPO, YamlFile } from ".";
|
import { DELAY_BETWEEN_GAMES_MS, REPO, YamlFile } from ".";
|
||||||
import { SteamGameCacheFile } from "./steam";
|
import { SteamGameCache, SteamGameCacheFile } from "./steam";
|
||||||
import { WikiGameCache, getGame, pathIsTooBroad } from "./wiki";
|
import { WikiGameCache, getGame, pathIsTooBroad } from "./wiki";
|
||||||
|
|
||||||
export type Os = "dos" | "linux" | "mac" | "windows";
|
export type Os = "dos" | "linux" | "mac" | "windows";
|
||||||
|
|
||||||
|
export type Bit = 32 | 64;
|
||||||
|
|
||||||
export type Store = "epic" | "gog" | "microsoft" | "steam" | "uplay" | "origin";
|
export type Store = "epic" | "gog" | "microsoft" | "steam" | "uplay" | "origin";
|
||||||
|
|
||||||
export type Tag = "config" | "save";
|
export type Tag = "config" | "save";
|
||||||
|
@ -15,16 +17,23 @@ export interface Manifest {
|
||||||
export interface Game {
|
export interface Game {
|
||||||
files?: {
|
files?: {
|
||||||
[path: string]: {
|
[path: string]: {
|
||||||
when?: Array<Constraint>,
|
when?: Array<Omit<Constraint, "bit">>,
|
||||||
tags?: Array<Tag>,
|
tags?: Array<Tag>,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
installDir?: {
|
installDir?: {
|
||||||
[name: string]: {}
|
[name: string]: {}
|
||||||
};
|
};
|
||||||
|
launch?: {
|
||||||
|
[path: string]: Array<{
|
||||||
|
arguments?: string;
|
||||||
|
workingDir?: string;
|
||||||
|
when?: Array<Constraint>,
|
||||||
|
}>
|
||||||
|
},
|
||||||
registry?: {
|
registry?: {
|
||||||
[path: string]: {
|
[path: string]: {
|
||||||
when?: Array<Omit<Constraint, "os">>,
|
when?: Array<Omit<Constraint, "bit" | "os">>,
|
||||||
tags?: Array<Tag>,
|
tags?: Array<Tag>,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -35,9 +44,120 @@ export interface Game {
|
||||||
|
|
||||||
export interface Constraint {
|
export interface Constraint {
|
||||||
os?: Os;
|
os?: Os;
|
||||||
|
bit?: Bit;
|
||||||
store?: Store;
|
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> {
|
export class ManifestFile extends YamlFile<Manifest> {
|
||||||
path = `${REPO}/data/manifest.yaml`;
|
path = `${REPO}/data/manifest.yaml`;
|
||||||
defaultData = {};
|
defaultData = {};
|
||||||
|
@ -62,6 +182,7 @@ export class ManifestFile extends YamlFile<Manifest> {
|
||||||
},
|
},
|
||||||
limit: number | undefined,
|
limit: number | undefined,
|
||||||
steamCache: SteamGameCacheFile,
|
steamCache: SteamGameCacheFile,
|
||||||
|
local: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let foundSkipUntil = false;
|
let foundSkipUntil = false;
|
||||||
|
@ -125,18 +246,20 @@ export class ManifestFile extends YamlFile<Manifest> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
|
||||||
if (limit > 0 && i > limit) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.renamedFrom) {
|
if (info.renamedFrom) {
|
||||||
for (const oldName of info.renamedFrom) {
|
for (const oldName of info.renamedFrom) {
|
||||||
delete this.data[oldName];
|
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;
|
delete wikiCache[verifiedTitle].recentlyChanged;
|
||||||
|
|
||||||
if (verifiedTitle !== title) {
|
if (verifiedTitle !== title) {
|
||||||
|
@ -149,16 +272,18 @@ export class ManifestFile extends YamlFile<Manifest> {
|
||||||
}
|
}
|
||||||
if (game.steam?.id !== undefined) {
|
if (game.steam?.id !== undefined) {
|
||||||
const appInfo = await steamCache.getAppInfo(game.steam.id);
|
const appInfo = await steamCache.getAppInfo(game.steam.id);
|
||||||
if (appInfo.installDir !== undefined) {
|
integrateSteamData(game, appInfo);
|
||||||
if (game.installDir === undefined) {
|
|
||||||
game.installDir = {}
|
|
||||||
}
|
|
||||||
game.installDir[appInfo.installDir] = {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.data[verifiedTitle] = game;
|
this.data[verifiedTitle] = game;
|
||||||
|
|
||||||
|
if (!local) {
|
||||||
await new Promise(resolve => setTimeout(resolve, DELAY_BETWEEN_GAMES_MS));
|
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 { DELAY_BETWEEN_GAMES_MS, REPO, YamlFile } from ".";
|
||||||
import * as SteamUser from "steam-user";
|
import * as SteamUser from "steam-user";
|
||||||
|
|
||||||
type SteamGameCache = {
|
export type SteamGameCache = {
|
||||||
[appId: string]: {
|
[appId: string]: {
|
||||||
installDir?: string,
|
installDir?: string,
|
||||||
unknown?: boolean,
|
unknown?: boolean,
|
||||||
nameLocalized?: Map<string, string>;
|
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;
|
irregular?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -14,8 +25,9 @@ type SteamGameCache = {
|
||||||
export class SteamGameCacheFile extends YamlFile<SteamGameCache> {
|
export class SteamGameCacheFile extends YamlFile<SteamGameCache> {
|
||||||
path = `${REPO}/data/steam-game-cache.yaml`;
|
path = `${REPO}/data/steam-game-cache.yaml`;
|
||||||
defaultData = {};
|
defaultData = {};
|
||||||
|
steamClient: SteamUser | null = null;
|
||||||
|
|
||||||
constructor(public steamClient: SteamUser) {
|
constructor(private makeSteamClient: () => Promise<SteamUser>) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +45,10 @@ export class SteamGameCacheFile extends YamlFile<SteamGameCache> {
|
||||||
return this.data[key];
|
return this.data[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.steamClient === null) {
|
||||||
|
this.steamClient = await this.makeSteamClient();
|
||||||
|
}
|
||||||
|
|
||||||
const info: SteamProductInfoResponse = await this.steamClient.getProductInfo([appId], []);
|
const info: SteamProductInfoResponse = await this.steamClient.getProductInfo([appId], []);
|
||||||
|
|
||||||
if (info.unknownApps.includes(appId)) {
|
if (info.unknownApps.includes(appId)) {
|
||||||
|
|
Reference in a new issue