feat: initial commit

This commit is contained in:
oxypomme
2025-12-30 19:52:07 +01:00
commit 6514dc165b
10 changed files with 372 additions and 0 deletions

76
bin/reorder-all-series.ts Normal file
View File

@@ -0,0 +1,76 @@
import {
fetchLibraryMangas,
fetchMangaChapters,
updateMetadata,
} from '~/lib/komga.ts';
const getChapterSort = (chapter: any) => {
const volumeNumber = /vol(?:ume)?.?([0-9]+)/i.exec(chapter.name)?.[1] || '1';
const chapterNumber =
/ch(?:apter)?.?([0-9.]+)/i.exec(chapter.name)?.[1] || '';
const chapterFloat = Number.parseFloat(chapterNumber);
if (!chapterNumber || Number.isNaN(chapterFloat)) {
throw new Error(
`Ch. ${chapterNumber} cannot be parsed from ${chapter.name}`
);
}
return {
title: `Ch. ${chapterNumber} - Vol. ${volumeNumber}`,
numberSort: chapterFloat,
};
};
const sanitiseMetadata = (chapter: any, chaptersSeen: Set<number>) => {
const data = getChapterSort(chapter);
const isDuplicate = chaptersSeen.has(data.numberSort);
if (isDuplicate) {
console.log(`⚠️ Ch. ${data.numberSort} already seen, marking as duplicate`);
}
chaptersSeen.add(data.numberSort);
return {
...data,
numberSortLock: true,
tags: isDuplicate
? [...chapter.metadata.tags, 'oxy.DUPLICATE']
: chapter.metadata.tags.filter((tag: string) => tag !== 'oxy.DUPLICATE'),
};
};
// Main
console.log(
`== Sorting library ${Deno.env.get('LIBRARY_ID')} (${new Date().toISOString()}) ==`
);
for (const manga of await fetchLibraryMangas(Deno.env.get('LIBRARY_ID'))) {
console.log(`Sorting ${manga.name} (${manga.booksCount} chapters)...`);
console.group();
const chapters = await fetchMangaChapters(manga.id);
const chaptersSeen = new Set<number>();
const metadata = new Map(
chapters.map((chap) => [chap.id, sanitiseMetadata(chap, chaptersSeen)])
);
const updates = [...metadata].toSorted(
([, a], [, b]) => a.numberSort - b.numberSort
);
let updateCount = 0;
for (const [id, metadata] of updates) {
await updateMetadata(id, {
...metadata,
number: updateCount,
});
updateCount += 1;
}
console.log(`✔ Updated ${updateCount} chapters !`);
console.groupEnd();
}