gadl/main.ts

254 lines
6.1 KiB
TypeScript
Raw Normal View History

2023-12-05 00:20:59 +09:00
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
2023-11-19 02:25:32 +09:00
import util from "node:util";
2023-12-02 23:22:33 +09:00
import { createBrowser } from "./browser";
2023-11-19 02:25:32 +09:00
import { createDatabase } from "./database";
2024-06-30 23:43:40 +09:00
import { createLibrary, type Book } from "./library";
2023-12-03 00:53:57 +09:00
import * as pkg from "./package.json";
2024-06-30 23:43:40 +09:00
import { createPlatform, platforms, type TPlatform } from "./platform";
2023-11-19 02:25:32 +09:00
const options = {
db: {
type: "string",
default: "gadl.db",
2023-12-03 17:35:19 +09:00
toString() {
return `<database_file_path> (default: ${this.default})`;
},
2023-11-19 02:25:32 +09:00
},
2023-11-20 01:22:15 +09:00
"out-dir": {
type: "string",
default: "dist",
2023-12-03 17:35:19 +09:00
toString() {
return `<output_directory_path> (default: ${this.default})`;
},
2023-11-20 01:22:15 +09:00
},
"out-authors-limit": {
type: "string",
default: "3",
2023-12-03 17:35:19 +09:00
toString() {
return `<output_authors_limit> (default: ${this.default})`;
},
},
2024-06-30 23:43:40 +09:00
"no-headless": {
type: "boolean",
default: false,
},
2023-11-19 02:25:32 +09:00
login: {
2023-12-02 23:22:33 +09:00
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return [...Object.keys(platforms)].join("|");
},
2023-11-19 02:25:32 +09:00
async run() {
const db = await createDatabase(args.values.db!);
2023-12-02 23:22:33 +09:00
const browser = await createBrowser({ db, headless: false });
const platform = createPlatform({
platform: args.values.login as TPlatform,
db,
browser,
});
2023-11-19 02:25:32 +09:00
await platform.login();
2023-11-23 01:31:27 +09:00
await browser.close();
2023-11-19 02:25:32 +09:00
},
},
2023-11-19 16:18:00 +09:00
logout: {
2023-12-02 23:22:33 +09:00
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return [...Object.keys(platforms)].join("|");
},
2023-11-19 16:18:00 +09:00
async run() {
2024-06-30 23:43:40 +09:00
const db = await createDatabase(args.values.db!),
headless = !args.values["no-headless"];
const browser = await createBrowser({ db, headless });
2023-12-02 23:22:33 +09:00
const platform = createPlatform({
platform: args.values.logout as TPlatform,
db,
browser,
});
2023-11-19 16:18:00 +09:00
await platform.logout();
2023-11-23 01:31:27 +09:00
await browser.close();
2023-11-19 16:18:00 +09:00
},
},
2023-11-19 02:25:32 +09:00
add: {
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return `<reader_url_or_id>`;
},
2023-11-19 02:25:32 +09:00
async run() {
const db = await createDatabase(args.values.db!);
const library = createLibrary(db);
await library.add(args.values.add!);
},
},
2023-11-19 20:51:29 +09:00
delete: {
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return `<id>`;
},
2023-11-19 20:51:29 +09:00
async run() {
const db = await createDatabase(args.values.db!);
const library = createLibrary(db);
await library.delete(Number(args.values.delete));
},
},
2023-11-19 02:25:32 +09:00
list: {
type: "boolean",
short: "l",
async run() {
const db = await createDatabase(args.values.db!);
const library = createLibrary(db);
const books = await library.getBooks();
2023-11-20 22:56:09 +09:00
console.dir(books, {
depth: null,
maxArrayLength: null,
maxStringLength: null,
});
2023-11-19 02:25:32 +09:00
},
},
2023-11-19 22:04:19 +09:00
view: {
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return `<reader_url_or_id>`;
},
2023-11-19 22:04:19 +09:00
async run() {
const db = await createDatabase(args.values.db!);
const library = createLibrary(db);
2023-12-03 16:14:38 +09:00
const book = await library.get(args.values.view!);
2023-11-19 22:04:19 +09:00
if (!book) {
process.exit(1);
}
2023-11-20 22:56:09 +09:00
console.dir(book, {
depth: null,
maxArrayLength: null,
maxStringLength: null,
});
},
},
pull: {
2023-12-02 23:22:33 +09:00
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return [...Object.keys(platforms)].join("|");
},
2023-11-20 22:56:09 +09:00
async run() {
2024-06-30 23:43:40 +09:00
const db = await createDatabase(args.values.db!),
library = createLibrary(db),
headless = !args.values["no-headless"];
const browser = await createBrowser({ db, headless });
2023-12-02 23:22:33 +09:00
const platform = createPlatform({
platform: args.values.pull as TPlatform,
db,
browser,
});
2023-11-20 22:56:09 +09:00
for await (const book of platform.pull()) {
await library.add(book);
}
2023-11-23 01:31:27 +09:00
await browser.close();
2023-11-19 22:04:19 +09:00
},
},
2023-11-19 20:47:49 +09:00
download: {
type: "string",
2023-12-03 17:35:19 +09:00
toString() {
return `all|<reader_url_or_id>`;
},
2023-11-19 20:47:49 +09:00
async run() {
2024-06-30 23:43:40 +09:00
const db = await createDatabase(args.values.db!),
library = createLibrary(db),
headless = !args.values["no-headless"];
2023-11-23 01:31:27 +09:00
const books: Array<Book> = [];
2023-11-19 22:04:19 +09:00
2023-11-23 01:31:27 +09:00
if (args.values.download === "all") {
books.push(...(await library.getBooks()));
} else {
2023-11-23 01:37:09 +09:00
if (URL.canParse(args.values.download!)) {
await library.add(args.values.download!);
}
2023-12-03 05:54:45 +09:00
const book = await library.get(args.values.download!);
2023-11-23 01:31:27 +09:00
if (!book) {
process.exit(1);
}
books.push(book);
}
for (const book of books) {
2024-06-30 23:43:40 +09:00
const browser = await createBrowser({ db, headless });
2023-12-02 23:22:33 +09:00
const platform = createPlatform({
platform: book.platform,
db,
browser,
});
2023-12-05 00:20:59 +09:00
const dir = await fs.mkdtemp(
path.join(os.tmpdir(), `gadl-${book.id}-`),
);
2023-11-23 01:31:27 +09:00
await platform.download(dir, book);
await library.archive(dir, book, {
outDir: args.values["out-dir"]!,
outAuthorsLimit: Number(args.values["out-authors-limit"]!),
});
2023-12-02 15:42:53 +09:00
await browser.close();
2023-11-19 22:04:19 +09:00
}
2023-11-20 01:37:55 +09:00
},
},
2023-11-21 00:09:06 +09:00
json: {
type: "boolean",
},
2023-12-03 00:53:57 +09:00
version: {
type: "boolean",
short: "v",
run() {
console.log(pkg.version);
},
},
2023-11-19 02:25:32 +09:00
help: {
type: "boolean",
short: "h",
run() {
console.log(
[
2023-12-03 17:35:19 +09:00
"Usage: gadl [options...]",
` $ npx playwright@${pkg.dependencies.playwright} install --with-deps chromium`,
` $ gadl --login=<platform_type>`,
` $ gadl --download=<reader_url>`,
"",
2023-11-19 02:25:32 +09:00
"Available options:",
2023-12-03 01:04:54 +09:00
...Object.entries(options).map((option) =>
[
` --${option[0]}`,
"short" in option[1] && ` -${option[1].short}`,
2023-12-03 17:35:19 +09:00
option[1].type === "string" && `=${option[1]}`,
2023-12-03 01:04:54 +09:00
]
.filter(Boolean)
.join(""),
),
2023-11-19 02:25:32 +09:00
].join("\n"),
);
},
},
} as const;
const args = util.parseArgs({ options });
2023-11-21 00:09:06 +09:00
if (args.values.json) {
console.dir = function dir(arrayOrObject) {
for (const obj of [arrayOrObject].flat()) {
console.log(JSON.stringify(obj));
}
};
}
2023-11-19 02:25:32 +09:00
for (const option of Object.keys(options)) {
if (args.values[option] && typeof options[option].run === "function") {
await options[option].run();
process.exit();
}
}
2023-11-23 01:34:36 +09:00
options.help.run();