Add script for populating id-gt from XIVAPI
This commit is contained in:
parent
a687833764
commit
3aa9a44cae
3 changed files with 120 additions and 3 deletions
|
|
@ -1,7 +1,10 @@
|
||||||
# ffxiv-wiki-edb-id-script
|
# ffxiv-wiki-scripts
|
||||||
|
|
||||||
Wiki bot for https://ffxiv.consolegameswiki.com that attempts to fix items in [Category:Missing EDB ID](https://ffxiv.consolegameswiki.com/wiki/Category:Missing_EDB_ID) by looking them up in Eorzea Database and adding the appropriate `id-edb` infobox parameter.
|
Wiki bot scripts for https://ffxiv.consolegameswiki.com.
|
||||||
|
|
||||||
|
- `bin/add-edb-ids`: Attempts to fix items in [Category:Missing EDB ID](https://ffxiv.consolegameswiki.com/wiki/Category:Missing_EDB_ID) by looking them up in Eorzea Database and adding the appropriate `id-edb` infobox parameter.
|
||||||
|
- `bin/add-gt-ids`: The same for [Category:Missing internal ID](https://ffxiv.consolegameswiki.com/wiki/Category:Missing_EDB_ID), looking up internal IDs via [XIVAPI](https://v2.xivapi.com) and populating the `id-gt` parameter.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
You'll need a recent version of Node.js (22+). Install dependencies via `npm ci`, set the `MW_USERNAME` and `MW_PASSWORD` environment variables to your account username and [bot password](https://www.mediawiki.org/wiki/Manual:Bot_passwords) respectively, then run `bin/add-edb-ids`.
|
You'll need a recent version of Node.js (22+). Install dependencies via `npm ci`, set the `MW_USERNAME` and `MW_PASSWORD` environment variables to your account username and [bot password](https://www.mediawiki.org/wiki/Manual:Bot_passwords) respectively, then run the scripts in the `bin` folder.
|
||||||
|
|
|
||||||
89
bin/add-gt-ids
Executable file
89
bin/add-gt-ids
Executable file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import {findItemGTID} from '../lib/api/xivapi.js';
|
||||||
|
import {getMediawikiClient} from '../lib/config.js';
|
||||||
|
import {diff} from '../lib/util/diff.js';
|
||||||
|
import {
|
||||||
|
addParameterBesideExistingParameter,
|
||||||
|
setEmptyParameter,
|
||||||
|
} from '../lib/util/template-parameters.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the `id-gt` item infobox parameter into the given page contents.
|
||||||
|
* @param {string} pageContent
|
||||||
|
* @param {string} gtID
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function insertInfoboxGTBID (pageContent, gtID) {
|
||||||
|
if (pageContent.includes(`id-gt = ${gtID}`)) {
|
||||||
|
console.log('what????', pageContent);
|
||||||
|
throw new Error('Page seems to already contain its own GT ID??');
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = setEmptyParameter(pageContent, 'id-gt', gtID)
|
||||||
|
?? addParameterBesideExistingParameter(pageContent, 'id-gt', gtID, 'after', 'id-edb')
|
||||||
|
?? addParameterBesideExistingParameter(pageContent, 'id-gt', gtID, 'after', 'release')
|
||||||
|
?? addParameterBesideExistingParameter(pageContent, 'id-gt', gtID, 'after', 'patch');
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
throw new Error('Dunno how to insert the parameter into this page');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mw = await getMediawikiClient();
|
||||||
|
|
||||||
|
// Get pages in the "Missing internal ID" category from the main article namespace
|
||||||
|
const itemPagesWithoutGTIDs = await mw.listCategoryPages('Category:Missing internal ID', [0], +process.env.LIMIT || 500);
|
||||||
|
console.log('Processing', itemPagesWithoutGTIDs.length, 'item pages from [[Category:Missing internal ID]]\n');
|
||||||
|
|
||||||
|
for (const {title} of itemPagesWithoutGTIDs) {
|
||||||
|
console.log('Page:', title);
|
||||||
|
// look up on XIVAPI
|
||||||
|
let gtID;
|
||||||
|
try {
|
||||||
|
gtID = await findItemGTID(title);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error looking up item ID:', error);
|
||||||
|
}
|
||||||
|
if (!gtID) {
|
||||||
|
console.log('No ID found for this item, skipping');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log('GT ID:', gtID, `(https://garlandtools.org/db/#item/${encodeURIComponent(gtID)})`);
|
||||||
|
|
||||||
|
let originalText;
|
||||||
|
try {
|
||||||
|
originalText = await mw.readPage(title);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error reading page:', error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rewrite wiki page to include id-edb infobox parameter
|
||||||
|
let updatedText;
|
||||||
|
try {
|
||||||
|
updatedText = insertInfoboxGTBID(originalText, gtID);
|
||||||
|
diff(originalText, updatedText);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error inserting parameter:', error);
|
||||||
|
console.group('Bad page content:');
|
||||||
|
console.log(originalText);
|
||||||
|
console.groupEnd();
|
||||||
|
console.log();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the new stuff back to the wiki
|
||||||
|
try {
|
||||||
|
await mw.editPage(title, updatedText, "Add GT item ID", true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
console.error('writes should not fail, this seems bad, dying now');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log('Written.');
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('done!');
|
||||||
25
lib/api/xivapi.js
Normal file
25
lib/api/xivapi.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Escapes any quotation marks in the given string with backslashes.
|
||||||
|
const backslashEscapeQuotes = (str) => str
|
||||||
|
.replace(/\\/g, '\\\\') // replace all \ with \\
|
||||||
|
.replace(/"/g, '\\"'); // replace all " with \"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal ID of the named item from XIVAPI.
|
||||||
|
* @param {string} name
|
||||||
|
* @returns {Promise<number | null>}
|
||||||
|
*/
|
||||||
|
export async function findItemGTID (name) {
|
||||||
|
const query = `Name~"${backslashEscapeQuotes(name)}"`;
|
||||||
|
const apiURL = `https://v2.xivapi.com/api/search?${new URLSearchParams({
|
||||||
|
sheets: 'Item',
|
||||||
|
query,
|
||||||
|
fields: 'Name',
|
||||||
|
})}`;
|
||||||
|
const response = await fetch(apiURL);
|
||||||
|
const data = await response.json();
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`XIVAPI request failed: ${data.code} ${data.message}`);
|
||||||
|
}
|
||||||
|
const item = data.results.find(item => item.fields.Name.toLowerCase() === name.toLowerCase());
|
||||||
|
return item?.row_id ?? null;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue