Fix handling for irregular paths, P vs Path template invocation, and variadic uses of P template
This commit is contained in:
parent
1c1ed6c525
commit
9b87fb9356
5 changed files with 143 additions and 67 deletions
|
@ -1620,7 +1620,7 @@ A Rite from the Stars:
|
||||||
id: 792370
|
id: 792370
|
||||||
A Robot Named Fight!:
|
A Robot Named Fight!:
|
||||||
files:
|
files:
|
||||||
'<home>/.config/unity3d/Matt Bitner/A Robot Named Fight/<ref>{{Refurl|url=https://steamcommunity.com/app/603530/discussions/1/1473096694440794319/#c3377008022026160641/|title=Where is my save file? :: A Robot Named Fight Bug Reporting|date=2019-05-28}}</ref>':
|
<home>/.config/unity3d/Matt Bitner/A Robot Named Fight:
|
||||||
tags:
|
tags:
|
||||||
- save
|
- save
|
||||||
when:
|
when:
|
||||||
|
@ -2522,7 +2522,12 @@ AI War 2:
|
||||||
id: 438020
|
id: 438020
|
||||||
'AI: The Somnium Files':
|
'AI: The Somnium Files':
|
||||||
files:
|
files:
|
||||||
'<winLocalAppData>/SpikeChunsoft/AI The Somnium Files/PSYNCAUTOSAVE<br/><winLocalAppData>/SpikeChunsoft/AI The Somnium Files/PSYNCDEF{{code|XX}}':
|
<winLocalAppData>/SpikeChunsoft/AI The Somnium Files/PSYNCAUTOSAVE:
|
||||||
|
tags:
|
||||||
|
- save
|
||||||
|
when:
|
||||||
|
- os: windows
|
||||||
|
<winLocalAppData>/SpikeChunsoft/AI The Somnium Files/PSYNCDEF*:
|
||||||
tags:
|
tags:
|
||||||
- save
|
- save
|
||||||
when:
|
when:
|
||||||
|
@ -2534,6 +2539,10 @@ AI War 2:
|
||||||
- os: windows
|
- os: windows
|
||||||
installDir:
|
installDir:
|
||||||
AI The Somnium Files: {}
|
AI The Somnium Files: {}
|
||||||
|
registry:
|
||||||
|
HKEY_CURRENT_USER/Software/SpikeChunsoft/AI_TheSomniumFiles:
|
||||||
|
tags:
|
||||||
|
- config
|
||||||
steam:
|
steam:
|
||||||
id: 948740
|
id: 948740
|
||||||
AIDS Simulator:
|
AIDS Simulator:
|
||||||
|
@ -96936,7 +96945,7 @@ Graveyard Keeper:
|
||||||
- save
|
- save
|
||||||
when:
|
when:
|
||||||
- os: mac
|
- os: mac
|
||||||
'<home>/Library/Preferences/{{file|unity.Lazy Bear Games.Graveyard Keeper.plist}}':
|
<home>/Library/Preferences/unity.Lazy Bear Games.Graveyard Keeper.plist:
|
||||||
tags:
|
tags:
|
||||||
- config
|
- config
|
||||||
when:
|
when:
|
||||||
|
@ -104793,13 +104802,9 @@ Her Story:
|
||||||
when:
|
when:
|
||||||
- os: windows
|
- os: windows
|
||||||
<home>/Library/Application Support/unity.Sam Barlow.HerStory:
|
<home>/Library/Application Support/unity.Sam Barlow.HerStory:
|
||||||
tags:
|
|
||||||
- save
|
|
||||||
when:
|
|
||||||
- os: mac
|
|
||||||
'<home>/Library/Application Support/unity.Sam Barlow.HerStory/{{cn|Windows path was for save only, is this legit OS X versions config path?|date=January 15, 2016}}':
|
|
||||||
tags:
|
tags:
|
||||||
- config
|
- config
|
||||||
|
- save
|
||||||
when:
|
when:
|
||||||
- os: mac
|
- os: mac
|
||||||
installDir:
|
installDir:
|
||||||
|
|
|
@ -1653,6 +1653,7 @@ A Rite from the Stars:
|
||||||
pageId: 103285
|
pageId: 103285
|
||||||
revId: 841573
|
revId: 841573
|
||||||
A Robot Named Fight!:
|
A Robot Named Fight!:
|
||||||
|
irregularPath: true
|
||||||
pageId: 66273
|
pageId: 66273
|
||||||
revId: 934101
|
revId: 934101
|
||||||
A Roll-Back Story:
|
A Roll-Back Story:
|
||||||
|
@ -2109,8 +2110,9 @@ AI War 2:
|
||||||
pageId: 44800
|
pageId: 44800
|
||||||
revId: 841706
|
revId: 841706
|
||||||
'AI: The Somnium Files':
|
'AI: The Somnium Files':
|
||||||
|
irregularPath: true
|
||||||
pageId: 132809
|
pageId: 132809
|
||||||
revId: 963156
|
revId: 983332
|
||||||
AIDS Simulator:
|
AIDS Simulator:
|
||||||
pageId: 96877
|
pageId: 96877
|
||||||
revId: 841708
|
revId: 841708
|
||||||
|
@ -47163,7 +47165,7 @@ Graveyard Defender:
|
||||||
revId: 839908
|
revId: 839908
|
||||||
Graveyard Keeper:
|
Graveyard Keeper:
|
||||||
pageId: 58471
|
pageId: 58471
|
||||||
revId: 962811
|
revId: 983342
|
||||||
Graveyard Shift:
|
Graveyard Shift:
|
||||||
pageId: 51951
|
pageId: 51951
|
||||||
revId: 855328
|
revId: 855328
|
||||||
|
@ -50952,6 +50954,7 @@ Her Majesty's Ship:
|
||||||
pageId: 88894
|
pageId: 88894
|
||||||
revId: 887258
|
revId: 887258
|
||||||
Her Story:
|
Her Story:
|
||||||
|
irregularPath: true
|
||||||
pageId: 26295
|
pageId: 26295
|
||||||
revId: 975631
|
revId: 975631
|
||||||
Her War:
|
Her War:
|
||||||
|
|
|
@ -15,6 +15,7 @@ interface Cli {
|
||||||
unchecked?: boolean,
|
unchecked?: boolean,
|
||||||
unsupportedOs?: boolean,
|
unsupportedOs?: boolean,
|
||||||
unsupportedPath?: boolean,
|
unsupportedPath?: boolean,
|
||||||
|
irregularPath?: boolean,
|
||||||
tooBroad?: boolean,
|
tooBroad?: boolean,
|
||||||
tooBroadUntagged?: boolean,
|
tooBroadUntagged?: boolean,
|
||||||
game?: string,
|
game?: string,
|
||||||
|
@ -61,6 +62,7 @@ async function main() {
|
||||||
unsupportedPath: args.unsupportedPath ?? false,
|
unsupportedPath: args.unsupportedPath ?? false,
|
||||||
tooBroad: args.tooBroad ?? false,
|
tooBroad: args.tooBroad ?? false,
|
||||||
tooBroadUntagged: args.tooBroadUntagged ?? false,
|
tooBroadUntagged: args.tooBroadUntagged ?? false,
|
||||||
|
irregularPath: args.irregularPath ?? false,
|
||||||
game: args.game,
|
game: args.game,
|
||||||
recent: args.recent,
|
recent: args.recent,
|
||||||
},
|
},
|
||||||
|
|
|
@ -51,6 +51,7 @@ export class ManifestFile extends YamlFile<Manifest> {
|
||||||
unchecked: boolean,
|
unchecked: boolean,
|
||||||
unsupportedOs: boolean,
|
unsupportedOs: boolean,
|
||||||
unsupportedPath: boolean,
|
unsupportedPath: boolean,
|
||||||
|
irregularPath: boolean,
|
||||||
tooBroad: boolean,
|
tooBroad: boolean,
|
||||||
tooBroadUntagged: boolean,
|
tooBroadUntagged: boolean,
|
||||||
game: string | undefined,
|
game: string | undefined,
|
||||||
|
@ -80,6 +81,9 @@ export class ManifestFile extends YamlFile<Manifest> {
|
||||||
if (filter.unsupportedPath && info.unsupportedPath) {
|
if (filter.unsupportedPath && info.unsupportedPath) {
|
||||||
check = true;
|
check = true;
|
||||||
}
|
}
|
||||||
|
if (filter.irregularPath && (wikiCache[title].irregularPath || Object.keys(this.data[title]?.files ?? []).some(x => x.includes("{{") || x.includes("</") || x.includes("<br>") || x.includes("<br/>")))) {
|
||||||
|
check = true;
|
||||||
|
}
|
||||||
if (filter.game === title) {
|
if (filter.game === title) {
|
||||||
check = true;
|
check = true;
|
||||||
}
|
}
|
||||||
|
|
176
src/wiki.ts
176
src/wiki.ts
|
@ -15,6 +15,7 @@ export type WikiGameCache = {
|
||||||
tooBroad?: boolean,
|
tooBroad?: boolean,
|
||||||
recentlyChanged?: boolean,
|
recentlyChanged?: boolean,
|
||||||
renamedFrom?: Array<string>,
|
renamedFrom?: Array<string>,
|
||||||
|
irregularPath?: boolean,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,7 +177,7 @@ const PATH_ARGS: { [arg: string]: { mapped: string, when?: Constraint, registry?
|
||||||
}
|
}
|
||||||
|
|
||||||
function makePathArgRegex(arg: string): RegExp {
|
function makePathArgRegex(arg: string): RegExp {
|
||||||
const escaped = `{{P|${arg}}}`
|
const escaped = `{{P(ath)?|${arg}}}`
|
||||||
.replace("\\", "\\\\")
|
.replace("\\", "\\\\")
|
||||||
.replace("|", "\\|")
|
.replace("|", "\\|")
|
||||||
.replace("{", "\\{")
|
.replace("{", "\\{")
|
||||||
|
@ -184,6 +185,48 @@ function makePathArgRegex(arg: string): RegExp {
|
||||||
return new RegExp(escaped, "gi");
|
return new RegExp(escaped, "gi");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Examples:
|
||||||
|
// [ [["p"], "linuxhome"], ".config" ]
|
||||||
|
// [ [["cn"], "Is this right?", "date=January 1, 2000"] ]
|
||||||
|
type PathSegment = string | [[string], ...Array<string>];
|
||||||
|
|
||||||
|
function stringifyPathSegment(segment: PathSegment): [string, boolean] {
|
||||||
|
if (typeof segment === "string") {
|
||||||
|
return [segment, true];
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateName = segment[0][0];
|
||||||
|
switch (templateName.toLowerCase()) {
|
||||||
|
case "p":
|
||||||
|
case "path":
|
||||||
|
return [`{{${templateName}|${segment[1]}}}`, true];
|
||||||
|
case "code":
|
||||||
|
case "file":
|
||||||
|
return ["*", false];
|
||||||
|
case "localizedpath":
|
||||||
|
return [segment[1], false];
|
||||||
|
default:
|
||||||
|
return ["", false];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRawPathFromCell(cell: string | Array<PathSegment> | undefined): [string | undefined, boolean] {
|
||||||
|
let regular = true;
|
||||||
|
if (cell === undefined) {
|
||||||
|
return [undefined, regular];
|
||||||
|
} else if (typeof cell === "string") {
|
||||||
|
return [cell.replace(/<ref>.*?<\ref>/, ""), regular];
|
||||||
|
} else {
|
||||||
|
return [cell.map(x => {
|
||||||
|
const [stringified, segmentRegular] = stringifyPathSegment(x);
|
||||||
|
if (!segmentRegular) {
|
||||||
|
regular = false;
|
||||||
|
}
|
||||||
|
return stringified;
|
||||||
|
}).join("").replace(/<ref>.*?<\ref>/, ""), regular];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://www.pcgamingwiki.com/wiki/Template:Path
|
* https://www.pcgamingwiki.com/wiki/Template:Path
|
||||||
*/
|
*/
|
||||||
|
@ -401,6 +444,7 @@ export async function getGame(pageTitle: string, cache: WikiGameCache): Promise<
|
||||||
let unsupportedOs = 0;
|
let unsupportedOs = 0;
|
||||||
let unsupportedPath = 0;
|
let unsupportedPath = 0;
|
||||||
let tooBroad = 0;
|
let tooBroad = 0;
|
||||||
|
let irregularPath = 0;
|
||||||
page.parse().each("template", template => {
|
page.parse().each("template", template => {
|
||||||
if (template.name === "Infobox game") {
|
if (template.name === "Infobox game") {
|
||||||
const steamId = Number(template.parameters["steam appid"]);
|
const steamId = Number(template.parameters["steam appid"]);
|
||||||
|
@ -408,70 +452,82 @@ export async function getGame(pageTitle: string, cache: WikiGameCache): Promise<
|
||||||
game.steam = { id: steamId };
|
game.steam = { id: steamId };
|
||||||
}
|
}
|
||||||
} else if (template.name === "Game data/saves" || template.name === "Game data/config") {
|
} else if (template.name === "Game data/saves" || template.name === "Game data/config") {
|
||||||
const rawPath = typeof template.parameters[2] === "string" ? template.parameters[2] : template.parameters[2]?.toString();
|
for (const cellKey of Object.getOwnPropertyNames(template.parameters)) {
|
||||||
if (rawPath === undefined || rawPath.length === 0) {
|
if (cellKey === "0" || cellKey === "1") {
|
||||||
return;
|
continue;
|
||||||
}
|
|
||||||
try {
|
|
||||||
const [path, pathType] = parsePath(rawPath);
|
|
||||||
if (pathIsTooBroad(path)) {
|
|
||||||
tooBroad += 1;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (pathType === PathType.FileSystem) {
|
const cell = template.parameters[cellKey];
|
||||||
const constraint = getConstraintFromSystem(template.parameters[1], rawPath);
|
const [rawPath, regular] = getRawPathFromCell(cell);
|
||||||
|
|
||||||
if (!game.files.hasOwnProperty(path)) {
|
if (!regular) {
|
||||||
game.files[path] = {
|
irregularPath += 1;
|
||||||
when: [],
|
}
|
||||||
tags: [],
|
|
||||||
};
|
if (rawPath === undefined || rawPath.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [path, pathType] = parsePath(rawPath);
|
||||||
|
if (pathIsTooBroad(path)) {
|
||||||
|
tooBroad += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (pathType === PathType.FileSystem) {
|
||||||
|
const constraint = getConstraintFromSystem(template.parameters[1], rawPath);
|
||||||
|
|
||||||
if (!game.files[path].when.some(x => x.os === constraint.os && x.store === constraint.store)) {
|
if (!game.files.hasOwnProperty(path)) {
|
||||||
if (constraint.os !== undefined && constraint.store !== undefined) {
|
game.files[path] = {
|
||||||
game.files[path].when.push(constraint);
|
when: [],
|
||||||
} else if (constraint.os !== undefined) {
|
tags: [],
|
||||||
game.files[path].when.push({ os: constraint.os });
|
};
|
||||||
} else if (constraint.store !== undefined) {
|
}
|
||||||
game.files[path].when.push({ store: constraint.store });
|
|
||||||
|
if (!game.files[path].when.some(x => x.os === constraint.os && x.store === constraint.store)) {
|
||||||
|
if (constraint.os !== undefined && constraint.store !== undefined) {
|
||||||
|
game.files[path].when.push(constraint);
|
||||||
|
} else if (constraint.os !== undefined) {
|
||||||
|
game.files[path].when.push({ os: constraint.os });
|
||||||
|
} else if (constraint.store !== undefined) {
|
||||||
|
game.files[path].when.push({ store: constraint.store });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tag = getTagFromTemplate(template.name);
|
||||||
|
if (tag !== undefined && !game.files[path].tags.includes(tag)) {
|
||||||
|
game.files[path].tags.push(tag);
|
||||||
|
}
|
||||||
|
} else if (pathType === PathType.Registry) {
|
||||||
|
if (!game.registry.hasOwnProperty(path)) {
|
||||||
|
game.registry[path] = {
|
||||||
|
when: [],
|
||||||
|
tags: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = getStoreConstraintFromPath(rawPath);
|
||||||
|
if (store !== undefined && !game.registry[path].when.some(x => x.store === store)) {
|
||||||
|
game.registry[path].when.push({ store });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tag = getTagFromTemplate(template.name);
|
||||||
|
if (tag !== undefined && !game.registry[path].tags.includes(tag)) {
|
||||||
|
game.registry[path].tags.push(tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(` ${template.toString()}`);
|
||||||
|
console.log(` ${e}`);
|
||||||
|
|
||||||
const tag = getTagFromTemplate(template.name);
|
if (e instanceof UnsupportedOsError) {
|
||||||
if (tag !== undefined && !game.files[path].tags.includes(tag)) {
|
unsupportedOs += 1;
|
||||||
game.files[path].tags.push(tag);
|
continue;
|
||||||
|
} else if (e instanceof UnsupportedPathError) {
|
||||||
|
unsupportedPath += 1;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
} else if (pathType === PathType.Registry) {
|
|
||||||
if (!game.registry.hasOwnProperty(path)) {
|
|
||||||
game.registry[path] = {
|
|
||||||
when: [],
|
|
||||||
tags: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = getStoreConstraintFromPath(rawPath);
|
|
||||||
if (store !== undefined && !game.registry[path].when.some(x => x.store === store)) {
|
|
||||||
game.registry[path].when.push({ store });
|
|
||||||
}
|
|
||||||
|
|
||||||
const tag = getTagFromTemplate(template.name);
|
|
||||||
if (tag !== undefined && !game.registry[path].tags.includes(tag)) {
|
|
||||||
game.registry[path].tags.push(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(` ${template.toString()}`);
|
|
||||||
console.log(` ${e}`);
|
|
||||||
|
|
||||||
if (e instanceof UnsupportedOsError) {
|
|
||||||
unsupportedOs += 1;
|
|
||||||
return;
|
|
||||||
} else if (e instanceof UnsupportedPathError) {
|
|
||||||
unsupportedPath += 1;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,6 +577,12 @@ export async function getGame(pageTitle: string, cache: WikiGameCache): Promise<
|
||||||
delete cache[pageTitle].tooBroad;
|
delete cache[pageTitle].tooBroad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (irregularPath > 0) {
|
||||||
|
cache[pageTitle].irregularPath = true;
|
||||||
|
} else {
|
||||||
|
delete cache[pageTitle].irregularPath;
|
||||||
|
}
|
||||||
|
|
||||||
cache[pageTitle].revId = page.revisions?.[0]?.revid ?? 0;
|
cache[pageTitle].revId = page.revisions?.[0]?.revid ?? 0;
|
||||||
return game;
|
return game;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue