From 4d7bd2515ad9c528232e2a6be9c29d7b5b6a3d4e Mon Sep 17 00:00:00 2001 From: ewin Date: Tue, 12 Aug 2025 18:27:59 -0400 Subject: [PATCH] Add one-off script for adding hrothgar/viera headwear compatibility data --- bin/hrothgar-viera-headwear | 69 +++++++++++++++++++++++++++++++++ lib/util/template-parameters.js | 15 +++++++ 2 files changed, 84 insertions(+) create mode 100755 bin/hrothgar-viera-headwear diff --git a/bin/hrothgar-viera-headwear b/bin/hrothgar-viera-headwear new file mode 100755 index 0000000..fef52bb --- /dev/null +++ b/bin/hrothgar-viera-headwear @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +import {readFileSync} from 'node:fs'; +import {join} from 'node:path'; + +import {getMediawikiClient} from '../lib/config.js'; +import {diff} from '../lib/util/diff.js'; +import {addParameterAtBottom, setExistingParameter} from '../lib/util/template-parameters.js'; + +const mw = await getMediawikiClient(); + +// parse CSV +// hats.csv is an export of this google sheet that crye compiled: +// https://docs.google.com/spreadsheets/d/13s_qxWThsensslulLfAxN0-hzQZVCqS9fKaImlLXbVU/edit?gid=38787585#gid=38787585 +const data = readFileSync(join(import.meta.dirname, '../hats.csv'), 'utf-8').split(/\r?\n/g).map(line => line && line.split(',')); +console.log(data.slice(0, 1)); +const headers = data.splice(0, 1)[0]; +const COL_ITEM = headers.findIndex(field => field.toLowerCase() === 'item'); +const COL_VIERA = headers.findIndex(field => field.toLowerCase().includes('viera')); +const COL_HROTH = headers.findIndex(field => field.toLowerCase().includes('hrothgar')); + +console.log('Processing', data.length, 'items'); + +for (const line of data) { + const item = line[COL_ITEM]; + const params = { + 'display-on-viera': line[COL_VIERA].toLowerCase() === 'yes' ? 'y' : 'n', + 'display-on-hrothgar': line[COL_HROTH].toLowerCase() === 'yes' ? 'y' : 'n', + } + console.log(item, params); + + // read and apply updates + const pageContent = await mw.readPage(item); + let newPageContent = pageContent; + try { + for (const [paramName, paramValue] of Object.entries(params)) { + newPageContent = setExistingParameter(newPageContent, paramName, paramValue) + ?? addParameterAtBottom(newPageContent, paramName, paramValue); + + if (!newPageContent) { + console.log(pageContent); + throw new Error('adding parameter to the page failed'); + } + } + } catch (error) { + console.error(error); + console.log('skipping this item'); + continue; + } + + if (newPageContent === pageContent) { + // no changes + console.log('No changes, skipping'); + continue; + } + + diff(pageContent, newPageContent); + + // write + try { + await mw.editPage(item, newPageContent, 'Add Hrothgar/Viera headwear data'); + } catch (error) { + console.error('Failed to write:', error); + process.exit(1); + } + console.log('Written.'); +} + +console.log('done!'); diff --git a/lib/util/template-parameters.js b/lib/util/template-parameters.js index 2298a56..a2c7d18 100644 --- a/lib/util/template-parameters.js +++ b/lib/util/template-parameters.js @@ -49,3 +49,18 @@ export function addParameterBesideExistingParameter (pageContent, newParamName, } return null; } + +/** RegExp that matches the last parameter in an infobox. */ +const existingLastParameterRegExp = /^( *)\|( *)([a-z0-9-_]+)( *)=( *)(.*)(\n *}})$/m; + +/** Inserts a new parameter at the end of the infobox. */ +export function addParameterAtBottom (pageContent, newParamName, value) { + if (pageContent.match(existingLastParameterRegExp)) { + // has science gone too far? + return pageContent.replace( + existingLastParameterRegExp, + `$1|$2$3$4=$5$6\n$1|$2${newParamName}$4=$5${value}$7`, + ); + } + return null; +}