Add 'name_localized' and 'launch' to Steam cache (part 1)

This commit is contained in:
mtkennerly 2022-05-31 05:06:32 +08:00
parent 1fe83ec8c5
commit dd63a8248f
No known key found for this signature in database
GPG key ID: E764BE00BE6E6408
5 changed files with 138861 additions and 280 deletions

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,8 @@
"schema": "npm run schema:normal && npm run schema:strict", "schema": "npm run schema:normal && npm run schema:strict",
"schema:normal": "ajv validate -s ./data/schema.yaml -d ./data/manifest.yaml", "schema:normal": "ajv validate -s ./data/schema.yaml -d ./data/manifest.yaml",
"schema:strict": "ajv validate -s ./data/schema.strict.yaml -d ./data/manifest.yaml", "schema:strict": "ajv validate -s ./data/schema.strict.yaml -d ./data/manifest.yaml",
"stats": "ts-node ./src/bin.ts --stats" "stats": "ts-node ./src/bin.ts --stats",
"steam": "ts-node ./src/bin.ts --steam"
}, },
"devDependencies": { "devDependencies": {
"@types/js-yaml": "^3.12.4", "@types/js-yaml": "^3.12.4",

View file

@ -23,6 +23,7 @@ interface Cli {
skipUntil?: string, skipUntil?: string,
recent?: boolean, recent?: boolean,
limit?: number, limit?: number,
steam?: boolean,
} }
async function main() { async function main() {
@ -41,7 +42,11 @@ async function main() {
"irregularPathUntagged", "irregularPathUntagged",
"tooBroad", "tooBroad",
"tooBroadUntagged", "tooBroadUntagged",
] "steam",
],
string: [
"skipUntil",
],
}); });
const wikiCache = new WikiGameCacheFile(); const wikiCache = new WikiGameCacheFile();
@ -70,6 +75,15 @@ async function main() {
} }
} }
if (args.steam) {
await steamCache.refresh(
{
skipUntil: args.skipUntil,
},
args.limit ?? 25,
);
}
if (args.manifest) { if (args.manifest) {
await manifest.updateGames( await manifest.updateGames(
wikiCache.data, wikiCache.data,

View file

@ -148,12 +148,12 @@ export class ManifestFile extends YamlFile<Manifest> {
continue; continue;
} }
if (game.steam?.id !== undefined) { if (game.steam?.id !== undefined) {
const installDir = await steamCache.getAppInstallDir(game.steam.id); const appInfo = await steamCache.getAppInfo(game.steam.id);
if (installDir !== undefined) { if (appInfo.installDir !== undefined) {
if (game.installDir === undefined) { if (game.installDir === undefined) {
game.installDir = {} game.installDir = {}
} }
game.installDir[installDir] = {} game.installDir[appInfo.installDir] = {}
} }
} }
this.data[verifiedTitle] = game; this.data[verifiedTitle] = game;

View file

@ -1,10 +1,12 @@
import { 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 = { type SteamGameCache = {
[appId: string]: { [appId: string]: {
installDir?: string, installDir?: string,
unknown?: boolean, unknown?: boolean,
nameLocalized?: Map<string, string>;
launch?: object;
}; };
}; };
@ -16,25 +18,68 @@ export class SteamGameCacheFile extends YamlFile<SteamGameCache> {
super(); super();
} }
async getAppInstallDir(appId: number): Promise<string | undefined> { async getAppInfo(appId: number, update: boolean = false): Promise<SteamGameCache[""] | undefined> {
const key = appId.toString(); const key = appId.toString();
if (this.data.hasOwnProperty(key)) { if (!update && this.data.hasOwnProperty(key)) {
return this.data[key].installDir; return this.data[key];
} else { }
const info: SteamProductInfoResponse = await this.steamClient.getProductInfo([appId], []);
if (info.unknownApps.includes(appId)) { const info: SteamProductInfoResponse = await this.steamClient.getProductInfo([appId], []);
this.data[key] = { unknown: true };
return undefined; if (info.unknownApps.includes(appId)) {
this.data[key] = { unknown: true };
return undefined;
}
this.data[key] = {};
const installDir = info.apps[key].appinfo.config?.installdir;
if (installDir !== undefined) {
this.data[key].installDir = installDir;
}
const nameLocalized = info.apps[key].appinfo.common?.name_localized;
if (nameLocalized !== undefined && Object.keys(nameLocalized).length > 0) {
this.data[key].nameLocalized = nameLocalized;
}
const launch = info.apps[key].appinfo.config?.launch;
if (launch !== undefined) {
const keys = Object.keys(launch).sort((x, y) => parseInt(x) - parseInt(y));
this.data[key].launch = keys.map(x => launch[x]);
}
return this.data[key];
}
async refresh(filter: {skipUntil: string | undefined}, limit: number): Promise<void> {
let i = 0;
let foundSkipUntil = false;
for (const appId of Object.keys(this.data)) {
if (filter.skipUntil && !foundSkipUntil) {
if (appId === filter.skipUntil) {
foundSkipUntil = true;
} else {
continue;
}
} }
const installDir = info.apps[key].appinfo.config?.installdir; console.log(`Refreshing Steam app ${appId}`)
if (installDir !== undefined) { await this.getAppInfo(parseInt(appId), true);
this.data[key] = { installDir };
} else { i++;
this.data[key] = {}; if (limit > 0 && i >= limit) {
break;
} }
return installDir;
// main() will save at the end, but we do a period save as well
// in case something goes wrong or the script gets cancelled:
if (i % 250 === 0) {
this.save();
console.log(":: saved");
}
await new Promise(resolve => setTimeout(resolve, DELAY_BETWEEN_GAMES_MS));
} }
} }
} }
@ -43,11 +88,15 @@ interface SteamProductInfoResponse {
apps: { apps: {
[appId: string]: { [appId: string]: {
appinfo: { appinfo: {
common?: {
name_localized?: Map<string, string>,
},
config?: { config?: {
installdir?: string installdir?: string,
} launch?: object,
} },
} },
},
}, },
unknownApps: Array<number>, unknownApps: Array<number>,
} }
@ -55,7 +104,7 @@ interface SteamProductInfoResponse {
export async function getSteamClient(): Promise<SteamUser> { export async function getSteamClient(): Promise<SteamUser> {
const client = new SteamUser(); const client = new SteamUser();
client.logOn(); client.logOn();
await new Promise(resolve => { await new Promise<void>(resolve => {
client.on("loggedOn", () => { client.on("loggedOn", () => {
resolve(); resolve();
}); });