Fix handling for irregular paths, P vs Path template invocation, and variadic uses of P template

This commit is contained in:
mtkennerly 2020-07-15 21:21:57 -04:00
parent 1c1ed6c525
commit 9b87fb9356
5 changed files with 143 additions and 67 deletions

View file

@ -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:

View file

@ -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:

View file

@ -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,
}, },

View file

@ -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;
} }

View file

@ -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;
} }