mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-28 01:48:11 +03:00
port a bunch of seeds scripts to v3 (#1744)
This commit is contained in:
@@ -1,65 +0,0 @@
|
||||
import { FormatGame } from "../../common/src/index.ts";
|
||||
|
||||
import { CreateFolderID, MutateCollection } from "../util.js";
|
||||
|
||||
export default function AddLevelVersionFolders(name, game, playtypes, version, levels) {
|
||||
const ptFolders = {};
|
||||
|
||||
MutateCollection("folders.json", (folders) => {
|
||||
for (const level of levels) {
|
||||
const folder = {
|
||||
data: {
|
||||
level,
|
||||
versions: version,
|
||||
},
|
||||
game,
|
||||
inactive: false,
|
||||
searchTerms: [],
|
||||
title: `Level ${level} (${name})`,
|
||||
type: "charts",
|
||||
};
|
||||
|
||||
for (const playtype of playtypes) {
|
||||
const folderID = CreateFolderID(folder.data, folder.game, playtype);
|
||||
|
||||
const realFolder = Object.assign({ folderID, playtype }, folder);
|
||||
|
||||
if (ptFolders[playtype]) {
|
||||
ptFolders[playtype].push(realFolder);
|
||||
} else {
|
||||
ptFolders[playtype] = [realFolder];
|
||||
}
|
||||
|
||||
folders.push(realFolder);
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
});
|
||||
|
||||
MutateCollection("tables.json", (tables) => {
|
||||
for (const playtype of playtypes) {
|
||||
tables.push({
|
||||
default: false,
|
||||
description: `Levels for ${FormatGame(game, playtype)} in ${name}.`,
|
||||
folders: ptFolders[playtype].map((e) => e.folderID),
|
||||
game,
|
||||
inactive: false,
|
||||
playtype,
|
||||
tableID: `${game}-${playtype}-${version}-levels`,
|
||||
title: `${FormatGame(game, playtype)} (${name})`,
|
||||
});
|
||||
}
|
||||
|
||||
return tables;
|
||||
});
|
||||
}
|
||||
|
||||
// usage:
|
||||
|
||||
// const levels = [];
|
||||
// for (let i = 1; i <= 12; i++) {
|
||||
// levels.push(i.toString())
|
||||
// }
|
||||
//
|
||||
// AddLevelVersionFolders("CastHour", "iidx", ["SP", "DP"], "29", levels);
|
||||
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
CreateTableID,
|
||||
FormatGame,
|
||||
SEEDS_FolderDocument,
|
||||
SEEDS_TableDocument,
|
||||
V3Game,
|
||||
} from "tachi-common";
|
||||
import { CreateFolderID, CreateRandomLegacyFolderID, MutateCollection } from "../util.js";
|
||||
|
||||
export default function AddLevelVersionFolders(
|
||||
name: string,
|
||||
shortName: string,
|
||||
game: V3Game,
|
||||
version: string,
|
||||
levels: string[],
|
||||
) {
|
||||
const slugs: string[] = [];
|
||||
|
||||
MutateCollection("folders.json", (foldersCol: SEEDS_FolderDocument[]) => {
|
||||
for (const level of levels) {
|
||||
const slug = `${level}-${shortName}`;
|
||||
const folder: SEEDS_FolderDocument = {
|
||||
game,
|
||||
id: CreateFolderID(),
|
||||
inactive: false,
|
||||
legacyFolderID: CreateRandomLegacyFolderID(),
|
||||
searchTerms: [],
|
||||
slug,
|
||||
title: `Level ${level} (${name})`,
|
||||
versionFilter: [version],
|
||||
where: `chart.level = '${level}'`,
|
||||
};
|
||||
|
||||
slugs.push(slug);
|
||||
foldersCol.push(folder);
|
||||
}
|
||||
|
||||
return foldersCol;
|
||||
});
|
||||
|
||||
MutateCollection("tables.json", (tables: SEEDS_TableDocument[]) => {
|
||||
tables.push({
|
||||
default: false,
|
||||
description: `Levels for ${FormatGame(game)} in ${name}.`,
|
||||
folders: slugs,
|
||||
game,
|
||||
inactive: false,
|
||||
id: CreateTableID(),
|
||||
legacyTableID: `${game}-${shortName}-levels`,
|
||||
title: `${FormatGame(game)} (${name})`,
|
||||
});
|
||||
|
||||
return tables;
|
||||
});
|
||||
}
|
||||
|
||||
// usage:
|
||||
|
||||
// const levels = [];
|
||||
// for (let i = 1; i <= 12; i++) {
|
||||
// levels.push(i.toString())
|
||||
// }
|
||||
//
|
||||
// AddLevelVersionFolders("CastHour", "casthour", "iidx-sp", "29", levels);
|
||||
@@ -1,85 +0,0 @@
|
||||
import { CreateFolderID, MutateCollection } from "../util.js";
|
||||
|
||||
// Change these for whatever table you are adding.
|
||||
const GAME = "ddr";
|
||||
const PLAYTYPES = ["SP", "DP"];
|
||||
const PREFIX = "Level ";
|
||||
const TITLE = "DDR A3";
|
||||
const SHORTTITLE = "a3"; // this is used in the tableID
|
||||
const DESCRIPTION = "All songs in DDR A3";
|
||||
const LEVELS = [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
"17",
|
||||
"18",
|
||||
"19",
|
||||
];
|
||||
|
||||
const ptFolders = {};
|
||||
|
||||
MutateCollection("folders.json", (foldersCol) => {
|
||||
for (const level of LEVELS) {
|
||||
const folder = {
|
||||
data: {
|
||||
"data¬tableFolders": {
|
||||
"~elemMatch": {
|
||||
level,
|
||||
table: PREFIX,
|
||||
},
|
||||
},
|
||||
},
|
||||
game: GAME,
|
||||
inactive: false,
|
||||
searchTerms: [],
|
||||
title: `${PREFIX}${level}`,
|
||||
type: "charts",
|
||||
};
|
||||
|
||||
for (const playtype of PLAYTYPES) {
|
||||
const folderID = CreateFolderID(folder.data, folder.game, playtype);
|
||||
|
||||
const realFolder = Object.assign({ folderID, playtype }, folder);
|
||||
|
||||
if (ptFolders[playtype]) {
|
||||
ptFolders[playtype].push(realFolder);
|
||||
} else {
|
||||
ptFolders[playtype] = [realFolder];
|
||||
}
|
||||
|
||||
foldersCol.push(realFolder);
|
||||
}
|
||||
}
|
||||
|
||||
return foldersCol;
|
||||
});
|
||||
|
||||
MutateCollection("tables.json", (tables) => {
|
||||
for (const playtype of PLAYTYPES) {
|
||||
tables.push({
|
||||
default: false,
|
||||
description: DESCRIPTION,
|
||||
folders: ptFolders[playtype].map((e) => e.folderID),
|
||||
game: GAME,
|
||||
inactive: false,
|
||||
playtype,
|
||||
tableID: `${GAME}-${playtype}-${SHORTTITLE}`,
|
||||
title: TITLE,
|
||||
});
|
||||
}
|
||||
|
||||
return tables;
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import { CreateTableID, SEEDS_FolderDocument, SEEDS_TableDocument } from "tachi-common";
|
||||
import { CreateFolderID, CreateRandomLegacyFolderID, MutateCollection } from "../util.js";
|
||||
|
||||
// The original intention was for you to
|
||||
// change these for whatever table you are adding.
|
||||
// But it would be better if you only used this as a reference
|
||||
// and made a dedicated rerunner.
|
||||
const GAME = "ddr-sp";
|
||||
const PREFIX = "Level ";
|
||||
const TITLE = "DDR A3";
|
||||
const SHORTTITLE = "a3"; // this is used in the tableID
|
||||
const VERSION = "a3";
|
||||
const DESCRIPTION = "All songs in DDR A3";
|
||||
const LEVELS = [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
"17",
|
||||
"18",
|
||||
"19",
|
||||
];
|
||||
|
||||
const slugs: string[] = [];
|
||||
|
||||
MutateCollection("folders.json", (foldersCol: SEEDS_FolderDocument[]) => {
|
||||
for (const level of LEVELS) {
|
||||
const slug = `${level}-${SHORTTITLE}`;
|
||||
const folder: SEEDS_FolderDocument = {
|
||||
game: GAME,
|
||||
id: CreateFolderID(),
|
||||
inactive: false,
|
||||
legacyFolderID: CreateRandomLegacyFolderID(),
|
||||
searchTerms: [],
|
||||
slug,
|
||||
title: `${PREFIX}${level}`,
|
||||
versionFilter: [VERSION],
|
||||
where: `chart.level = '${level}'`,
|
||||
};
|
||||
|
||||
slugs.push(slug);
|
||||
foldersCol.push(folder);
|
||||
}
|
||||
|
||||
return foldersCol;
|
||||
});
|
||||
|
||||
MutateCollection("tables.json", (tables: SEEDS_TableDocument[]) => {
|
||||
tables.push({
|
||||
default: false,
|
||||
description: DESCRIPTION,
|
||||
folders: slugs,
|
||||
game: GAME,
|
||||
inactive: false,
|
||||
id: CreateTableID(),
|
||||
legacyTableID: `${GAME}-${SHORTTITLE}`,
|
||||
title: TITLE,
|
||||
});
|
||||
|
||||
return tables;
|
||||
});
|
||||
@@ -52,7 +52,7 @@ to adjust the constants for the version you're adding.
|
||||
3. Deactivate old tables using `seeds/scripts/rerunners/toggle-table-inactive.js`:
|
||||
|
||||
```
|
||||
bun toggle-table-inactive.js -t chunithm-Single-<VERSION>-levels
|
||||
bun toggle-table-inactive.ts -t chunithm-Single-<VERSION>-levels
|
||||
```
|
||||
|
||||
Keep tables for the current and last (aka n-1) versions.
|
||||
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
import crypto from "crypto";
|
||||
import { log as logger } from "../log.ts";
|
||||
import { CreateFolderID, MutateCollection } from "../util.js";
|
||||
import { CreateFolderID, CreateRandomLegacyFolderID, MutateCollection } from "../util.js";
|
||||
import { SEEDS_FolderDocument } from "tachi-common";
|
||||
|
||||
MutateCollection("folders.json", (folders) => {
|
||||
MutateCollection("folders.json", (folders: SEEDS_FolderDocument[]) => {
|
||||
logger.info("Updating Folders.");
|
||||
|
||||
for (const folder of folders) {
|
||||
if (folder.id === undefined || !folder.id.startsWith("F")) {
|
||||
folder.id = CreateFolderID();
|
||||
folder.legacyFolderID = `F${crypto.randomBytes(32).toString("hex")}`;
|
||||
folder.legacyFolderID = CreateRandomLegacyFolderID();
|
||||
logger.info(`Updating ${folder.slug}`);
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -1,15 +1,16 @@
|
||||
import { SEEDS_GoalDocument, SEEDS_QuestDocument } from "tachi-common";
|
||||
import { log as logger } from "../log.ts";
|
||||
import { CreateGoalID, MutateCollection, ReadCollection, WriteCollection } from "../util.js";
|
||||
|
||||
const translateMap = new Map();
|
||||
|
||||
const origGoals = ReadCollection("goals.json", true);
|
||||
const origGoals = ReadCollection<SEEDS_GoalDocument>("goals.json", true);
|
||||
|
||||
MutateCollection("goals.json", (goals) => {
|
||||
MutateCollection("goals.json", (goals: SEEDS_GoalDocument[]) => {
|
||||
logger.info("Updating goals.");
|
||||
|
||||
for (const goal of goals) {
|
||||
const expectedGoalID = CreateGoalID(goal.charts, goal.criteria, goal.game, goal.playtype);
|
||||
const expectedGoalID = CreateGoalID(goal.charts, goal.criteria, goal.game);
|
||||
|
||||
if (expectedGoalID !== goal.goalID) {
|
||||
translateMap.set(goal.goalID, expectedGoalID);
|
||||
@@ -21,7 +22,7 @@ MutateCollection("goals.json", (goals) => {
|
||||
});
|
||||
|
||||
try {
|
||||
MutateCollection("quests.json", (quests) => {
|
||||
MutateCollection("quests.json", (quests: SEEDS_QuestDocument[]) => {
|
||||
logger.info("Updating Quests.");
|
||||
|
||||
for (const quest of quests) {
|
||||
@@ -52,6 +53,6 @@ try {
|
||||
return quests;
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("Failed to update tables.json, reverting all auto-folder fixes.", { err });
|
||||
logger.error("Failed to update tables.json, reverting all auto-folder fixes. %s", { err });
|
||||
WriteCollection("goals.json", origGoals);
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
* Run: bun typescript/seeds-scripts/rerunners/fix-goals.ts
|
||||
*/
|
||||
|
||||
import { type V3Game } from "tachi-common";
|
||||
import { SEEDS_GoalDocument, SEEDS_QuestDocument, type V3Game } from "tachi-common";
|
||||
|
||||
import {
|
||||
buildGoalTitleContext,
|
||||
@@ -14,10 +14,10 @@ import { log as logger } from "../log.ts";
|
||||
import { CreateGoalID, MutateCollection, ReadCollection, WriteCollection } from "../util.js";
|
||||
|
||||
const translateMap = new Map<string, string>();
|
||||
const origGoals = ReadCollection("goals.json", true);
|
||||
const origGoals = ReadCollection<SEEDS_GoalDocument>("goals.json", true);
|
||||
const ctx = buildGoalTitleContext();
|
||||
|
||||
MutateCollection("goals.json", (goals) => {
|
||||
MutateCollection("goals.json", (goals: SEEDS_GoalDocument[]) => {
|
||||
logger.info("Re-deriving goalID and name for all goals.");
|
||||
|
||||
let idUpdates = 0;
|
||||
@@ -56,7 +56,7 @@ MutateCollection("goals.json", (goals) => {
|
||||
|
||||
if (translateMap.size > 0) {
|
||||
try {
|
||||
MutateCollection("quests.json", (quests) => {
|
||||
MutateCollection("quests.json", (quests: SEEDS_QuestDocument[]) => {
|
||||
logger.info("Updating quest goalID references.");
|
||||
|
||||
let patched = 0;
|
||||
@@ -76,8 +76,8 @@ if (translateMap.size > 0) {
|
||||
|
||||
return quests;
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("Failed to update quests.json, reverting goals.json.", { err });
|
||||
} catch (err: unknown) {
|
||||
logger.error("Failed to update quests.json, reverting goals.json. %s", { err });
|
||||
WriteCollection("goals.json", origGoals);
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Command } from "commander";
|
||||
import fs from "fs";
|
||||
import { type GoalDocument, type QuestDocument } from "tachi-common";
|
||||
import { SEEDS_GoalDocument, type GoalDocument, type QuestDocument } from "tachi-common";
|
||||
|
||||
import { CreateGoalID, CreateQuestID, MutateCollection } from "../util";
|
||||
|
||||
const program = new Command();
|
||||
program.option("-f, --file <quests.json>");
|
||||
program.requiredOption("-f, --file <quests.json>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
@@ -78,7 +78,7 @@ const newQuests = data.map(HydrateQuest);
|
||||
|
||||
MutateCollection("quests.json", (quests) => [...quests, ...newQuests]);
|
||||
|
||||
MutateCollection("goals.json", (goals) => {
|
||||
MutateCollection("goals.json", (goals: SEEDS_GoalDocument[]) => {
|
||||
// don't duplicate goals
|
||||
const goalIDs = new Set(goals.map((e) => e.goalID));
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ to adjust the constants for the version you're adding.
|
||||
3. Deactivate old tables using `seeds/scripts/rerunners/toggle-table-inactive.js`:
|
||||
|
||||
```
|
||||
bun toggle-table-inactive.js -t maimaidx-Single-<VERSION>-levels
|
||||
bun toggle-table-inactive.ts -t maimaidx-Single-<VERSION>-levels
|
||||
```
|
||||
|
||||
Keep tables for the current and last (aka n-1) versions.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { spawnSync } from "child_process";
|
||||
import { Command } from "commander";
|
||||
import fs from "fs";
|
||||
import { type QuestDocument, type QuestlineDocument } from "tachi-common";
|
||||
import { SEEDS_QuestDocument, SEEDS_QuestlineDocument } from "tachi-common";
|
||||
|
||||
import { MutateCollection, ReadCollection } from "../util";
|
||||
|
||||
@@ -16,19 +16,16 @@ import { MutateCollection, ReadCollection } from "../util";
|
||||
*/
|
||||
|
||||
const program = new Command();
|
||||
program.requiredOption("-g, --game <game>").requiredOption("-p, --playtype <playtype>");
|
||||
program.requiredOption("-g, --game <game>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
const { game } = options;
|
||||
|
||||
const { game, playtype } = options;
|
||||
|
||||
const quests = ReadCollection("quests.json").filter(
|
||||
(e) => e.game === game && e.playtype === playtype,
|
||||
) as Array<QuestDocument>;
|
||||
const quests = ReadCollection<SEEDS_QuestDocument>("quests.json").filter((e) => e.game === game);
|
||||
|
||||
if (quests.length === 0) {
|
||||
console.log(`No quests found for game ${game} and playtype ${playtype}.`);
|
||||
console.log(`No quests found for game ${game}.`);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -51,7 +48,7 @@ ${quests.map((e) => `${e.questID} ${e.name}`).join("\n")}
|
||||
);
|
||||
|
||||
try {
|
||||
const r = spawnSync(process.env.EDITOR || "nano", [file], {
|
||||
const r = spawnSync(process.env.EDITOR || "vim", [file], {
|
||||
stdio: "inherit",
|
||||
});
|
||||
|
||||
@@ -109,9 +106,8 @@ if (questIDs.length === 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const questline: QuestlineDocument = {
|
||||
const questline: SEEDS_QuestlineDocument = {
|
||||
game,
|
||||
playtype,
|
||||
desc,
|
||||
name,
|
||||
quests: questIDs,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
3. Parse song durations
|
||||
1. Download `vgmstream-cli` and put it in `seeds/scripts/personal`.
|
||||
2. Put opts in `seeds/scripts/personal`.
|
||||
3. Run `bun parse-song-duration.ts -v /tachi/typescript/seeds-scripts/personal/vgmstream-cli -d ../../personal/vgmstream-cli -g ongeki`.
|
||||
3. Run `bun parse-song-duration.ts -v /tachi/typescript/seeds-scripts/personal/vgmstream-cli -d ../../personal/opts -g ongeki`.
|
||||
4. Scrape sdvx.in links (optional)
|
||||
1. Run `bun scrape-sdvx-in.ts`.
|
||||
2. Fix any missing entries manually in `seeds/collections/charts-ongeki.json` (refer to `songs-ongeki.json` for `songID`s).
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { Command } from "commander";
|
||||
import { GetGameConfig } from "tachi-common";
|
||||
import { SEEDS_FolderDocument, SEEDS_TableDocument } from "tachi-common/types/seeds-documents-zod";
|
||||
import crypto from "crypto";
|
||||
|
||||
import { CreateFolderID, CreateTableID, MutateCollection } from "../../util";
|
||||
import {
|
||||
CreateFolderID,
|
||||
CreateRandomLegacyFolderID,
|
||||
CreateTableID,
|
||||
MutateCollection,
|
||||
} from "../../util";
|
||||
|
||||
const LEVELS = [
|
||||
"0",
|
||||
@@ -73,7 +77,7 @@ for (const level of LEVELS) {
|
||||
game: "ongeki",
|
||||
id: CreateFolderID(),
|
||||
inactive: false,
|
||||
legacyFolderID: `F${crypto.randomBytes(32).toString("hex")}`,
|
||||
legacyFolderID: CreateRandomLegacyFolderID(),
|
||||
searchTerms: [],
|
||||
slug,
|
||||
title: `Level ${level} (${versionName})`,
|
||||
@@ -89,7 +93,7 @@ for (const [fullName, safeName] of DIFFICULTIES) {
|
||||
game: "ongeki",
|
||||
id: CreateFolderID(),
|
||||
inactive: false,
|
||||
legacyFolderID: `F${crypto.randomBytes(32).toString("hex")}`,
|
||||
legacyFolderID: CreateRandomLegacyFolderID(),
|
||||
searchTerms: [],
|
||||
slug,
|
||||
title: `${fullName} (${versionName})`,
|
||||
@@ -105,7 +109,7 @@ for (const [fullName, safeName] of GENRES) {
|
||||
game: "ongeki",
|
||||
id: CreateFolderID(),
|
||||
inactive: false,
|
||||
legacyFolderID: `F${crypto.randomBytes(32).toString("hex")}`,
|
||||
legacyFolderID: CreateRandomLegacyFolderID(),
|
||||
searchTerms: [],
|
||||
slug,
|
||||
title: `${fullName} (${versionName})`,
|
||||
@@ -115,8 +119,8 @@ for (const [fullName, safeName] of GENRES) {
|
||||
genreFolderSlugs.push(slug);
|
||||
}
|
||||
|
||||
MutateCollection("tables.json", (ts) => {
|
||||
(ts as SEEDS_TableDocument[]).push(
|
||||
MutateCollection("tables.json", (ts: SEEDS_TableDocument[]) => {
|
||||
ts.push(
|
||||
{
|
||||
default: false,
|
||||
description: `Levels for O.N.G.E.K.I. in ${versionName}.`,
|
||||
|
||||
@@ -137,8 +137,8 @@ const main = async () => {
|
||||
if (game !== "ongeki" && game !== "chunithm") {
|
||||
throw new InvalidArgumentError("Bad game");
|
||||
}
|
||||
const charts = ReadCollection(`charts-${game}.json`);
|
||||
const songs = ReadCollection(`songs-${game}.json`);
|
||||
const charts = ReadCollection<SEEDS_ChartDocument<"ongeki">>(`charts-${game}.json`);
|
||||
const songs = ReadCollection<SEEDS_SongDocument<"ongeki">>(`songs-${game}.json`);
|
||||
const dir = await fs.readdir(optPath);
|
||||
const promises: Promise<void>[] = [];
|
||||
for (const opt of dir) {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import { Command } from "commander";
|
||||
|
||||
import { MutateCollection, ReadCollection, WriteCollection } from "../util.js";
|
||||
|
||||
const program = new Command();
|
||||
program.requiredOption("-t, --tableID <tableID>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
|
||||
const tables = ReadCollection("tables.json");
|
||||
|
||||
let table;
|
||||
|
||||
for (const findTable of tables) {
|
||||
if (findTable.tableID === options.tableID) {
|
||||
table = findTable;
|
||||
findTable.inactive = !findTable.inactive;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!table) {
|
||||
throw new Error(`No such table ${options.tableID} exists.`);
|
||||
}
|
||||
|
||||
MutateCollection("folders.json", (folders) => {
|
||||
for (const folder of folders) {
|
||||
const id = folder.folderID ?? folder.id;
|
||||
const matchesRef =
|
||||
(folder.slug !== undefined && table.folders.includes(folder.slug)) ||
|
||||
(id !== undefined && table.folders.includes(id));
|
||||
|
||||
if (matchesRef) {
|
||||
folder.inactive = !folder.inactive;
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
});
|
||||
|
||||
WriteCollection("tables.json", tables);
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Command } from "commander";
|
||||
import { MutateCollection, ReadCollection, WriteCollection } from "../util.js";
|
||||
import { SEEDS_FolderDocument, SEEDS_TableDocument } from "tachi-common";
|
||||
import { log as logger } from "../log.ts";
|
||||
|
||||
const program = new Command();
|
||||
program.requiredOption("-t, --tableID <id>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
|
||||
const tables = ReadCollection<SEEDS_TableDocument>("tables.json");
|
||||
|
||||
let table;
|
||||
|
||||
let toggleValue: boolean;
|
||||
|
||||
for (const findTable of tables) {
|
||||
let targetID;
|
||||
if (/^T[0-9a-fA-F]+$/u.test(options.tableID)) {
|
||||
targetID = findTable.id;
|
||||
} else {
|
||||
targetID = findTable.legacyTableID;
|
||||
}
|
||||
|
||||
if (options.tableID === targetID) {
|
||||
table = findTable;
|
||||
findTable.inactive = !findTable.inactive;
|
||||
toggleValue = findTable.inactive;
|
||||
logger.info(`Toggling table ${table.id} (${table.title}) to inactive=${toggleValue}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!table) {
|
||||
throw new Error(`No such table ${options.tableID} exists.`);
|
||||
}
|
||||
|
||||
MutateCollection("folders.json", (folders: SEEDS_FolderDocument[]) => {
|
||||
for (const folder of folders) {
|
||||
const matchesRef =
|
||||
(folder.slug !== undefined && table.folders.includes(folder.slug)) ||
|
||||
(folder.id !== undefined && table.folders.includes(folder.id));
|
||||
|
||||
if (matchesRef) {
|
||||
folder.inactive = toggleValue;
|
||||
logger.info(`Toggling folder ${folder.id} (${folder.title})`);
|
||||
}
|
||||
}
|
||||
|
||||
return folders;
|
||||
});
|
||||
|
||||
if (table.default === true && toggleValue! === true) {
|
||||
logger.warn(`${table.id} has been deactivated, but it is currently the default table.`);
|
||||
}
|
||||
|
||||
WriteCollection("tables.json", tables);
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
CreateSongID,
|
||||
CreateTableID,
|
||||
} from "tachi-common";
|
||||
import crypto from "crypto";
|
||||
|
||||
import DeterministicCollectionSort from "./sort-seeds.js";
|
||||
|
||||
@@ -37,6 +38,12 @@ export function IterateCollections(cb) {
|
||||
DeterministicCollectionSort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} name
|
||||
* @param {boolean} throwIfNotFound
|
||||
* @returns {T[]}
|
||||
*/
|
||||
export function ReadCollection(name, throwIfNotFound = false) {
|
||||
const p = path.join(COLLECTIONS_DIR, name);
|
||||
if (!fs.existsSync(p)) {
|
||||
@@ -62,8 +69,9 @@ export function WriteCollection(name, data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} name
|
||||
* @param {(collection: unknown) => unknown} cb
|
||||
* @param {(collection: T[]) => T[]} cb
|
||||
*/
|
||||
export function MutateCollection(name, cb) {
|
||||
const data = cb(ReadCollection(name));
|
||||
@@ -82,6 +90,10 @@ export function CreateLegacyFolderID(query, game, playtype) {
|
||||
return `F${fjsh.hash(Object.assign({ game, playtype }, query), "SHA256")}`;
|
||||
}
|
||||
|
||||
export function CreateRandomLegacyFolderID() {
|
||||
return `F${crypto.randomBytes(32).toString("hex")}`;
|
||||
}
|
||||
|
||||
export function CreateLegacyFolderIDFromFolder(folder) {
|
||||
return CreateLegacyFolderID(folder.data, folder.game, folder.playtype);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user