Add one-off script for patch 7.3 stellar mission name changes
This commit is contained in:
parent
8e89e05756
commit
7b5357c050
2 changed files with 170 additions and 0 deletions
136
bin/7-3-stellar-mission-renames
Executable file
136
bin/7-3-stellar-mission-renames
Executable file
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env node
|
||||
// Renames A-class Stellar Missions to replace A-1, A-2, A-3 difficulty
|
||||
// indicators with the new empty/EX/EX+ naming used in patch 7.3.
|
||||
// https://na.finalfantasyxiv.com/lodestone/topics/detail/907c6d2aa020c0e4458ed1477668521fb4a117ec#:~:text=The%20notation,adjusted%2E
|
||||
|
||||
import {getMediawikiClient} from '../lib/config.js';
|
||||
import {diff} from '../lib/util/diff.js';
|
||||
import {readExistingParameter, setExistingParameter} from '../lib/util/template-parameters.js';
|
||||
|
||||
const mw = await getMediawikiClient();
|
||||
const missions = await mw.listCategoryPages('Category:Stellar Missions', [0], 1000);
|
||||
|
||||
const updateMissionTitle = title => title
|
||||
// "A-1: Aetherochemical Samples I" -> "Aetherochemical Samples I"
|
||||
.replace(/^A-1: /, '')
|
||||
// "A-2: Aetherochemical Samples II" -> "EX: Aetherochemical Samples II"
|
||||
.replace(/^A-2/, 'EX')
|
||||
// "A-3: Aetherochemical Samples III" -> "EX+: Aetherochemical Samples III"
|
||||
.replace(/^A-3/, 'EX+');
|
||||
|
||||
// Move all the mission pages we need to move
|
||||
console.log('Moving pages');
|
||||
await Promise.allSettled(missions.map(async ({title}) => {
|
||||
// Rename this mission page if necessary
|
||||
let newTitle = updateMissionTitle(title);
|
||||
if (title === newTitle) return; // not an A-class mission, nothing to change
|
||||
|
||||
try {
|
||||
await mw.movePage(title, newTitle, {
|
||||
reason: 'A-rank stellar mission difficulties were renamed in patch 7.3',
|
||||
redirect: true,
|
||||
moveTalk: true,
|
||||
moveSubpages: true,
|
||||
});
|
||||
console.log(title, '->', newTitle);
|
||||
} catch (error) {
|
||||
if (error.message.includes('[articleexists]')) {
|
||||
try {
|
||||
await mw.movePage(title, newTitle + ' (Stellar Mission)', {
|
||||
reason: 'A-rank stellar mission difficulties were renamed in patch 7.3',
|
||||
redirect: true,
|
||||
moveTalk: true,
|
||||
moveSubpages: true,
|
||||
});
|
||||
} catch (err2) {
|
||||
console.error('Failed to move', title, 'to', newTitle + '(Stellar Mission)', ':', err2);
|
||||
}
|
||||
} else {
|
||||
console.error('Failed to move', title, 'to', newTitle, ':', error);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
console.log('Done renaming');
|
||||
|
||||
// Fetch the category listing again now that a bunch of titles have changed
|
||||
const movedMissions = await mw.listCategoryPages('Category:Stellar Missions', [0], 1000);
|
||||
|
||||
// Fix `previous`/`next` infobox parameters for sequential missions and use
|
||||
// `rank = A` consistently for all A-class missions
|
||||
for (const {title} of movedMissions) {
|
||||
let pageContent = await mw.readPage(title);
|
||||
const originalPageContent = pageContent;
|
||||
|
||||
for (const parameter of ['previous', 'next']) {
|
||||
const oldValue = readExistingParameter(pageContent, parameter);
|
||||
const newValue = updateMissionTitle(oldValue);
|
||||
|
||||
if (oldValue === newValue) continue; // mission title didn't change
|
||||
|
||||
// Update the value on the page
|
||||
let updatedPageContent = setExistingParameter(pageContent, parameter, newValue);
|
||||
if (updatedPageContent == null) {
|
||||
// something very weird has happened, this shouldn't be able to fail
|
||||
// if we already got the value of the parameter earlier
|
||||
console.error('weird shit happened with', title);
|
||||
continue;
|
||||
}
|
||||
|
||||
pageContent = updatedPageContent;
|
||||
}
|
||||
|
||||
if (readExistingParameter(pageContent, 'rank').match(/A-[123]/)) {
|
||||
pageContent = setExistingParameter(pageContent, 'rank', 'A');
|
||||
}
|
||||
|
||||
console.log('Diff for', title);
|
||||
diff(originalPageContent, pageContent);
|
||||
try {
|
||||
if (originalPageContent === pageContent) {
|
||||
console.log('No changes');
|
||||
} else {
|
||||
await mw.editPage(title, pageContent, 'Update links to mission(s) renamed in 7.3');
|
||||
console.log('Written.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error writing page:', error);
|
||||
console.error('writes should not fail, this seems bad, dying now');
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Also update mission names for all CE item recipes
|
||||
const items = await mw.listCategoryPages('Category:Cosmic Exploration Items', [0], 10000);
|
||||
for (const {title} of items) {
|
||||
let pageContent = await mw.readPage(title);
|
||||
const originalPageContent = pageContent;
|
||||
|
||||
const infoboxes = pageContent.split('{{Recipe');
|
||||
infoboxes.forEach((infobox, i) => {
|
||||
if (i === 0) return; // ignore stuff before first recipe infobox
|
||||
// console.log(infobox);
|
||||
|
||||
const mission = readExistingParameter(infobox, 'mission');
|
||||
const updatedMission = updateMissionTitle(mission);
|
||||
infoboxes[i] = setExistingParameter(infobox, 'mission', updatedMission);
|
||||
});
|
||||
pageContent = infoboxes.join('{{Recipe');
|
||||
|
||||
console.log('Diff for', title);
|
||||
diff(originalPageContent, pageContent);
|
||||
try {
|
||||
if (originalPageContent === pageContent) {
|
||||
console.log('No changes');
|
||||
} else {
|
||||
await mw.editPage(title, pageContent, 'Update links to mission(s) renamed in 7.3');
|
||||
console.log('Written.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error writing page:', error);
|
||||
console.error('writes should not fail, this seems bad, dying now');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Done with content updates');
|
||||
|
|
@ -162,6 +162,40 @@ export class MediaWikiClient {
|
|||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} from The page's current name
|
||||
* @param {string} to The page's new name
|
||||
* @param {object} options
|
||||
* @param {string} options.reason Move reason
|
||||
* @param {boolean} options.redirect Whether to create a redirect from the
|
||||
* old name to the new name
|
||||
* @param {boolean} options.moveTalk Whether to move the page's talk page
|
||||
* from the old name to the new name
|
||||
* @param {boolean} options.moveSubpages Whether to move the page's subpages
|
||||
* from the old name to the new name
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async movePage (from, to, {
|
||||
reason,
|
||||
redirect = true,
|
||||
moveTalk = true,
|
||||
moveSubpages = true,
|
||||
} = {}) {
|
||||
const csrfToken = await this.getCSRFToken();
|
||||
return this.fetchApiPost({
|
||||
action: 'move',
|
||||
from,
|
||||
to,
|
||||
reason,
|
||||
movetalk: moveTalk,
|
||||
movesubpages: moveSubpages,
|
||||
noredirect: !redirect,
|
||||
token: csrfToken,
|
||||
format: 'json',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of wiki pages that belong to the given category.
|
||||
* @param {string} name Category name including the `Category:` namespace.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue