diff --git a/bin/add-edb-ids b/bin/add-edb-ids index 7ed04e7..f48a2ff 100755 --- a/bin/add-edb-ids +++ b/bin/add-edb-ids @@ -1,6 +1,6 @@ #!/usr/bin/env node -import {findItemEDBID} from '../lib/api/lodestone.js'; +import {findEDBEntryID} from '../lib/api/lodestone.js'; import {getMediawikiClient} from '../lib/config.js'; import {diff} from '../lib/util/diff.js'; import { @@ -34,22 +34,29 @@ function insertInfoboxEDBID (pageContent, edbID) { const mw = await getMediawikiClient(); // Get pages in the "Missing EDB ID" category from the main article namespace -const itemPagesWithoutEDBIDs = await mw.listCategoryPages('Category:Missing EDB ID', [0], +process.env.LIMIT || 500); +const [itemPagesWithoutEDBIDs, questPagesWithoutEDBIDs] = await Promise.all([ + mw.listCategoryPages('Category:Missing EDB ID', [0], +process.env.LIMIT || 500), + mw.listCategoryPages('Category:Missing quest EDB ID', [0], +process.env.LIMIT || 500), +]); console.log('Processing', itemPagesWithoutEDBIDs.length, 'item pages from [[Category:Missing EDB ID]]\n'); +console.log('Processing', questPagesWithoutEDBIDs.length, 'item pages from [[Category:Missing quest EDB ID]]\n'); -for (const {title} of itemPagesWithoutEDBIDs) { +for (const {title, type} of [ + ...itemPagesWithoutEDBIDs.map(({title}) => ({title, type: 'item'})), + ...questPagesWithoutEDBIDs.map(({title}) => ({title, type: 'quest'})), +]) { // this runs serially with an artificial delay between requests to decrease // the chance of sqenix sending ninjas to my house await new Promise(resolve => setTimeout(resolve, 1000)); console.log('Page:', title); // look up on EDB - const edbID = await findItemEDBID(title); + const edbID = await findEDBEntryID(type, title); if (!edbID) { - console.log('No EDB ID found for this item, skipping'); + console.log(`No EDB ID found for this ${type}, skipping`); continue; } - console.log('EDB ID:', edbID, `(https://na.finalfantasyxiv.com/lodestone/playguide/db/item/${encodeURIComponent(edbID)})`); + console.log('EDB ID:', edbID, `(https://na.finalfantasyxiv.com/lodestone/playguide/db/${encodeURIComponent(type)}/${encodeURIComponent(edbID)})`); let originalText; try { @@ -75,7 +82,7 @@ for (const {title} of itemPagesWithoutEDBIDs) { // write the new stuff back to the wiki try { - await mw.editPage(title, updatedText, "Add EDB item ID", true); + await mw.editPage(title, updatedText, `Add EDB ${type} ID`, true); } catch (error) { console.error(error); console.error('writes should not fail, this seems bad, dying now'); diff --git a/lib/api/lodestone.js b/lib/api/lodestone.js index fcd2738..9e970f2 100644 --- a/lib/api/lodestone.js +++ b/lib/api/lodestone.js @@ -3,25 +3,28 @@ import {regExpEscape} from '../util/regexp.js'; /** - * Creates a regular expression that matches a link to the named item and - * captures its EDB ID from the matched link's `href` attribute. + * Creates a regular expression that matches a link to the database entry of the + * given type and name, and captures its EDB ID from the matched link's `href` + * attribute. + * @param {'item' | 'quest'} type * @param {string} name * @returns {RegExp} */ -const itemLinkRegExp = name => new RegExp(`]*>(?${regExpEscape(name)})`, 'i'); +const edbEntryLinkRegExp = (type, name) => new RegExp(`]*>(?${regExpEscape(name)})`, 'i'); /** - * Gets the ID of the named item in Eorzea Database. + * Gets the ID of the Eorzea Database entry with the given type and name. + * @param {'item' | 'quest'} type * @param {string} name * @returns {Promise} */ -export async function findItemEDBID (name) { - // execute a search for the item's name - const searchURL = `https://na.finalfantasyxiv.com/lodestone/playguide/db/item/?q=${encodeURIComponent(name.replace(/\([^)]+\)|[&-]/g, ' '))}`; +export async function findEDBEntryID (type, name) { + // execute a search for the entry's name and type + const searchURL = `https://na.finalfantasyxiv.com/lodestone/playguide/db/${type}/?q=${encodeURIComponent(name.replace(/\([^)]+\)|[&-]/g, ' '))}`; const response = await fetch(searchURL); const body = await response.text(); // find an `` in the HTML response whose text exactly matches the name - const match = body.match(itemLinkRegExp(name)); + const match = body.match(edbEntryLinkRegExp(type, name)); // return the ID parsed from the URL in the `href` attribute return match?.groups.id; }