import fs from "node:fs/promises"; import type { Book } from "./library"; import type { Browser } from "./browser"; import type { Database } from "./database"; import { GooglePlayBooks } from "./platforms/google-play-books"; import { DmmBooks } from "./platforms/dmm-books"; import { DlsiteManiax } from "./platforms/dlsite-maniax"; import { FanzaDoujin } from "./platforms/fanza-doujin"; export const platforms = { "google-play-books": GooglePlayBooks, "dmm-books": DmmBooks, "dlsite-maniax": DlsiteManiax, "fanza-doujin": FanzaDoujin, }; export type TPlatform = keyof typeof platforms; export function site(url: string): TPlatform { for (const [platform, { siteUrl }] of Object.entries(platforms)) { if (siteUrl(new URL(url))) return platform as TPlatform; } throw new Error(`Unsupported URL: ${url}`); } export function createPlatform(opts: { platform: TPlatform; db: Database; browser: Browser; }) { if (!(opts.platform in platforms)) { throw new Error( `The value must be a platform type: ${[...Object.keys(platforms)].join( ", ", )}.`, ); } const platform = platforms[opts.platform](opts.browser); return { ...platform, async download(dir: string, book: Book): Promise { await fs.mkdir(dir, { recursive: true }); const files: Array<() => Promise> = await platform.getFiles(book); const digits = String(files.length).length; function pad(n: string) { return n.padStart(digits, "0"); } const supportedTypes = { "image/png": "png", "image/jpeg": "jpg", "application/zip": "zip", "application/vnd.comicbook+zip": "cbz", }; for (const [n, getBlob] of Object.entries(files)) { const blob = await getBlob(); const extension = supportedTypes[blob.type]; if (!extension) { throw new Error( `It was ${blob.type}. The image must be a file of type: ${[ ...Object.keys(supportedTypes), ].join(", ")}.`, ); } const buffer = Buffer.from(await blob.arrayBuffer()); await fs.writeFile(`${dir}/${pad(n)}.${extension}`, buffer); } process.stderr.write(`\n`); }, async login() { const ctx = await opts.browser.newContext(); const page = await ctx.newPage(); for (const loginEndpoint of platform.loginEndpoints) { await page.goto(loginEndpoint); await page.waitForURL(platform.loginSuccessUrl, { timeout: 0 }); } await opts.browser.saveBrowserContext(opts.platform, ctx); }, async logout() { try { const ctx = await opts.browser.loadBrowserContext(opts.platform); const page = await ctx.newPage(); for (const logoutEndpoint of platform.logoutEndpoints) { await page.goto(logoutEndpoint); } } catch (error) { process.stderr.write(`Warning: ${(error as Error).message}\n`); } await opts.db.run( `update platforms set secrets = 'null' where name = ?`, opts.platform, ); }, }; }