parent
4f2ce0091a
commit
58a7557dc0
2 changed files with 110 additions and 27 deletions
|
@ -2,19 +2,19 @@ import axios from 'axios';
|
||||||
import { linkSync, mkdirSync, readFileSync, rmSync } from 'fs';
|
import { linkSync, mkdirSync, readFileSync, rmSync } from 'fs';
|
||||||
import { basename } from 'path';
|
import { basename } from 'path';
|
||||||
|
|
||||||
import { type Book } from './types';
|
import { type Book, type ReadList, type Series } from './types';
|
||||||
|
|
||||||
|
|
||||||
const API = JSON.parse(
|
|
||||||
readFileSync(`${process.env.FLAKE}/apps/list2series/.env`, { encoding: 'utf-8' }),
|
|
||||||
).API;
|
|
||||||
|
|
||||||
// Examples of calling this script:
|
// Examples of calling this script:
|
||||||
// $ just l2s copy 0K65Q482KK7SD
|
// $ just l2s copy 0K65Q482KK7SD
|
||||||
// $ just l2s meta 0K65Q482KK7SD
|
// $ just l2s meta 0K65Q482KK7SD
|
||||||
|
const API = JSON.parse(
|
||||||
|
readFileSync(`${process.env.FLAKE}/apps/list2series/.env`, { encoding: 'utf-8' }),
|
||||||
|
).API;
|
||||||
|
|
||||||
const LIST_ID = process.argv[3];
|
const LIST_ID = process.argv[3];
|
||||||
|
|
||||||
const getListInfo = async() => {
|
const getListInfo = async(): Promise<ReadList> => {
|
||||||
const res = await axios.request({
|
const res = await axios.request({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
|
@ -28,8 +28,8 @@ const getListInfo = async() => {
|
||||||
return res.data;
|
return res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSeriesBooks = async(listName: string, seriesPath: string): Promise<Book[]> => {
|
const getSeries = async(seriesTitle: string, operator = true): Promise<Series[]> => {
|
||||||
const series = await axios.request({
|
return (await axios.request({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
url: 'https://komga.nelim.org/api/v1/series/list?unpaged=true',
|
url: 'https://komga.nelim.org/api/v1/series/list?unpaged=true',
|
||||||
|
@ -41,14 +41,16 @@ const getSeriesBooks = async(listName: string, seriesPath: string): Promise<Book
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
condition: {
|
condition: {
|
||||||
title: {
|
title: {
|
||||||
operator: 'isNot',
|
operator: operator ? 'is' : 'isNot',
|
||||||
value: '',
|
value: seriesTitle,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
})).data.content;
|
||||||
|
};
|
||||||
|
|
||||||
const thisSeries = (series.data.content as Book[]).find((s) => s.url === seriesPath);
|
const getSeriesBooks = async(listName: string, seriesPath: string): Promise<Book[]> => {
|
||||||
|
const thisSeries = (await getSeries('', false)).find((s) => s.url === seriesPath);
|
||||||
|
|
||||||
if (!thisSeries) {
|
if (!thisSeries) {
|
||||||
throw new Error('Series could not be found');
|
throw new Error('Series could not be found');
|
||||||
|
@ -115,7 +117,7 @@ const getSeriesBooks = async(listName: string, seriesPath: string): Promise<Book
|
||||||
return books.data.content;
|
return books.data.content;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBookInfo = async(id: string) => {
|
const getBookInfo = async(id: string): Promise<Book> => {
|
||||||
const res = await axios.request({
|
const res = await axios.request({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
|
@ -129,8 +131,9 @@ const getBookInfo = async(id: string) => {
|
||||||
return res.data;
|
return res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const scanLibrary = async() => {
|
// There doesn't seem to be a way to wait for the scan to be done
|
||||||
return await axios.request({
|
const scanLibrary = (): void => {
|
||||||
|
axios.request({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
url: 'https://komga.nelim.org/api/v1/libraries/0K4QG58XA29DZ/scan',
|
url: 'https://komga.nelim.org/api/v1/libraries/0K4QG58XA29DZ/scan',
|
||||||
|
@ -140,14 +143,19 @@ const scanLibrary = async() => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const setBookMetadata = async(i: number, source: Book, target: Book) => {
|
const setBookMetadata = async(i: number, source: Book, target: Book): Promise<void> => {
|
||||||
source.metadata.title = `${source.seriesTitle} Issue #${source.metadata.number}`;
|
const thisSeries = (await getSeries(source.seriesTitle))[0];
|
||||||
|
|
||||||
|
source.metadata.title = thisSeries.booksCount !== 1 ?
|
||||||
|
`${source.seriesTitle} Issue #${source.metadata.number}` :
|
||||||
|
source.metadata.title = source.seriesTitle;
|
||||||
|
|
||||||
source.metadata.number = i.toString();
|
source.metadata.number = i.toString();
|
||||||
source.metadata.numberSort = i;
|
source.metadata.numberSort = i;
|
||||||
|
|
||||||
const metadata = JSON.stringify(source.metadata);
|
const metadata = JSON.stringify(source.metadata);
|
||||||
|
|
||||||
const res = await axios.request({
|
axios.request({
|
||||||
method: 'patch',
|
method: 'patch',
|
||||||
maxBodyLength: Infinity,
|
maxBodyLength: Infinity,
|
||||||
url: `https://komga.nelim.org/api/v1/books/${target.id}/metadata`,
|
url: `https://komga.nelim.org/api/v1/books/${target.id}/metadata`,
|
||||||
|
@ -157,13 +165,11 @@ const setBookMetadata = async(i: number, source: Book, target: Book) => {
|
||||||
},
|
},
|
||||||
data: metadata,
|
data: metadata,
|
||||||
});
|
});
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const main = async() => {
|
const main = async(): Promise<void> => {
|
||||||
const list = await getListInfo();
|
const list = await getListInfo();
|
||||||
const ids = list.bookIds as string[];
|
const ids = list.bookIds;
|
||||||
const seriesPath = `/data/comics/[List] ${list.name}`;
|
const seriesPath = `/data/comics/[List] ${list.name}`;
|
||||||
|
|
||||||
const listBooks = [] as Book[];
|
const listBooks = [] as Book[];
|
||||||
|
@ -186,7 +192,7 @@ const main = async() => {
|
||||||
linkSync(bookPath, inListPath);
|
linkSync(bookPath, inListPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
await scanLibrary();
|
scanLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (process.argv[2] === 'meta') {
|
else if (process.argv[2] === 'meta') {
|
||||||
|
|
|
@ -13,7 +13,22 @@ export interface Author {
|
||||||
role: string
|
role: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Metadata {
|
export interface Link {
|
||||||
|
label: string
|
||||||
|
url: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShortBookMetadata {
|
||||||
|
authors: Author[]
|
||||||
|
tags: unknown[]
|
||||||
|
releaseDate: string
|
||||||
|
summary: string
|
||||||
|
summaryNumber: string
|
||||||
|
created: string
|
||||||
|
lastModified: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BookMetadata {
|
||||||
title: string
|
title: string
|
||||||
titleLock: boolean
|
titleLock: boolean
|
||||||
summary: string
|
summary: string
|
||||||
|
@ -26,11 +41,11 @@ export interface Metadata {
|
||||||
releaseDateLock: boolean
|
releaseDateLock: boolean
|
||||||
authors: Author[]
|
authors: Author[]
|
||||||
authorsLock: boolean
|
authorsLock: boolean
|
||||||
tags: []
|
tags: unknown[]
|
||||||
tagsLock: boolean
|
tagsLock: boolean
|
||||||
isbn: string
|
isbn: string
|
||||||
isbnLock: boolean
|
isbnLock: boolean
|
||||||
links: unknown[]
|
links: Link[]
|
||||||
linksLock: boolean
|
linksLock: boolean
|
||||||
created: string
|
created: string
|
||||||
lastModified: string
|
lastModified: string
|
||||||
|
@ -50,9 +65,71 @@ export interface Book {
|
||||||
sizeBytes: number
|
sizeBytes: number
|
||||||
size: string
|
size: string
|
||||||
media: Media
|
media: Media
|
||||||
metadata: Metadata
|
metadata: BookMetadata
|
||||||
readProgress: null | unknown
|
readProgress: null | unknown
|
||||||
deleted: boolean
|
deleted: boolean
|
||||||
fileHash: string
|
fileHash: string
|
||||||
oneshot: boolean
|
oneshot: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SeriesMetadata {
|
||||||
|
status: string
|
||||||
|
statusLock: boolean
|
||||||
|
title: string
|
||||||
|
titleLock: boolean
|
||||||
|
titleSort: string
|
||||||
|
titleSortLock: boolean
|
||||||
|
summary: string
|
||||||
|
summaryLock: boolean
|
||||||
|
readingDirection: string
|
||||||
|
readingDirectionLock: boolean
|
||||||
|
publisher: string
|
||||||
|
publisherLock: boolean
|
||||||
|
ageRating: null | string
|
||||||
|
ageRatingLock: boolean
|
||||||
|
language: string
|
||||||
|
languageLock: boolean
|
||||||
|
genres: string[]
|
||||||
|
genresLock: boolean
|
||||||
|
tags: unknown[]
|
||||||
|
tagsLock: boolean
|
||||||
|
totalBookCount: null | number
|
||||||
|
totalBookCountLock: boolean
|
||||||
|
sharingLabels: unknown[]
|
||||||
|
sharingLabelsLock: boolean
|
||||||
|
links: Link[]
|
||||||
|
linksLock: boolean
|
||||||
|
alternateTitles: string[]
|
||||||
|
alternateTitlesLock: boolean
|
||||||
|
created: string
|
||||||
|
lastModified: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Series {
|
||||||
|
id: string
|
||||||
|
libraryId: string
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
created: string
|
||||||
|
lastModified: string
|
||||||
|
fileLastModified: string
|
||||||
|
booksCount: number
|
||||||
|
booksReadCount: number
|
||||||
|
booksUnreadCount: number
|
||||||
|
booksInProgressCount: number
|
||||||
|
metadata: SeriesMetadata
|
||||||
|
booksMetadata: ShortBookMetadata
|
||||||
|
deleted: boolean
|
||||||
|
oneshot: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadList {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
summary: string
|
||||||
|
ordered: boolean
|
||||||
|
bookIds: string[]
|
||||||
|
createdDate: string
|
||||||
|
lastModifiedDate: string
|
||||||
|
filtered: boolean
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue