refactor platform

This commit is contained in:
Nebel 2023-12-03 00:48:24 +09:00
parent 4e6afe7bf0
commit 7f36682b04
Signed by: nebel
GPG key ID: 79807D08C6EF6460
3 changed files with 78 additions and 80 deletions

View file

@ -36,11 +36,48 @@ export function createPlatform(opts: {
return { return {
...platform, ...platform,
async download(dir: string, book: Book): Promise<void> { async download(dir: string, book: Book): Promise<void> {
await fs.mkdir(path.dirname(dir), { recursive: true }); await fs.mkdir(path.dirname(dir), { recursive: true });
await fs.mkdir(dir); await fs.mkdir(dir);
await platform.download(dir, book);
const files: Array<() => Promise<string>> = 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",
};
for (const [n, dataUrl] of Object.entries(files)) {
const [prefix, base64] = (await dataUrl()).split(",", 2);
const [, type, encoding] =
/^data:([^;]*)(;base64)?$/.exec(prefix) ?? [];
const extension = supportedTypes[type];
if (!extension) {
throw new Error(
`It was ${type}. The image must be a file of type: ${[
...Object.keys(supportedTypes),
].join(", ")}.`,
);
}
if (encoding !== ";base64") {
throw new Error("Only base64 is supported.");
}
const buffer = Buffer.from(base64, "base64");
await fs.writeFile(`${dir}/${pad(n)}.${extension}`, buffer);
}
process.stderr.write(`\n`);
}, },
async logout() { async logout() {
await opts.db.run( await opts.db.run(
`update platforms set secrets = 'null' where name = ?`, `update platforms set secrets = 'null' where name = ?`,

View file

@ -1,10 +1,16 @@
import fs from "node:fs/promises";
import type { Book } from "../library"; import type { Book } from "../library";
import type { Browser, BrowserContext } from "../browser"; import type { Browser, BrowserContext } from "../browser";
type ImageFile = {
url: string;
blocks: Array<Record<string, number>>;
width: number;
height: number;
};
var NFBR: any; var NFBR: any;
async function getFiles() { async function getImageFiles(): Promise<Array<ImageFile>> {
const params = new URLSearchParams(location.search); const params = new URLSearchParams(location.search);
const model = new NFBR.a6G.Model({ const model = new NFBR.a6G.Model({
settings: new NFBR.Settings("NFBR.SettingData"), settings: new NFBR.Settings("NFBR.SettingData"),
@ -29,12 +35,7 @@ async function getFiles() {
const a5n = new NFBR.a5n(); const a5n = new NFBR.a5n();
await a5n.a5s(content, "configuration", a6l); await a5n.a5s(content, "configuration", a6l);
const files: Array<{ const imageFiles: Array<ImageFile> = [];
url: string;
blocks: [];
width: number;
height: number;
}> = [];
for (const index of Object.keys(content.files)) { for (const index of Object.keys(content.files)) {
const file = content.files[index]; const file = content.files[index];
@ -67,7 +68,7 @@ async function getFiles() {
const url = `${a5w.url}${page.url}`; const url = `${a5w.url}${page.url}`;
files.push({ imageFiles.push({
url, url,
blocks, blocks,
width: Width, width: Width,
@ -75,24 +76,19 @@ async function getFiles() {
}); });
} }
return files; return imageFiles;
} }
async function drawImage(file: { async function drawImage(imageFile: ImageFile) {
url: string;
blocks: Array<Record<string, number>>;
width: number;
height: number;
}) {
const canvas = Object.assign(document.createElement("canvas"), { const canvas = Object.assign(document.createElement("canvas"), {
width: file.width, width: imageFile.width,
height: file.height, height: imageFile.height,
}); });
const image = (await new Promise((resolve) => { const image = (await new Promise((resolve) => {
Object.assign(new Image(), { Object.assign(new Image(), {
crossOrigin: "use-credentials", crossOrigin: "use-credentials",
src: file.url, src: imageFile.url,
onload() { onload() {
resolve(this); resolve(this);
}, },
@ -101,7 +97,7 @@ async function drawImage(file: {
const ctx = canvas.getContext("2d")!; const ctx = canvas.getContext("2d")!;
for (const q of file.blocks) { for (const q of imageFile.blocks) {
ctx.drawImage( ctx.drawImage(
image, image,
q.destX, q.destX,
@ -241,38 +237,21 @@ export function DmmBooks(browser: Browser) {
process.stderr.write(`\n`); process.stderr.write(`\n`);
}, },
async download(dir: string, book: Book) { async getFiles(book: Book): Promise<Array<() => Promise<string>>> {
const ctx = await browser.loadBrowserContext("dmm-books"); const ctx = await browser.loadBrowserContext("dmm-books");
const page = await ctx.newPage(); const page = await ctx.newPage();
await page.goto(book.readerUrl); await page.goto(book.readerUrl);
const files = await page.evaluate(getFiles); const imageFiles = await page.evaluate(getImageFiles);
const digits = String(files.length).length;
function pad(n: string) { return imageFiles.map((imageFile) => async () => {
return n.padStart(digits, "0"); const dataUrl = await page.evaluate(drawImage, imageFile);
}
for (const [n, file] of Object.entries(files)) {
const dataUrl = await page.evaluate(drawImage, file);
const [prefix, base64] = dataUrl.split(",", 2);
if (!prefix.startsWith("data:image/png;")) {
throw new Error("Only image/png is supported.");
}
if (!prefix.endsWith(";base64")) {
throw new Error("Only base64 is supported.");
}
const buffer = Buffer.from(base64, "base64");
await fs.writeFile(`${dir}/${pad(n)}.png`, buffer);
process.stderr.write("."); process.stderr.write(".");
}
process.stderr.write(`\n`); return dataUrl;
});
}, },
}; };
} }

View file

@ -1,8 +1,11 @@
import fs from "node:fs/promises";
import type { Book } from "../library"; import type { Book } from "../library";
import type { Browser } from "../browser"; import type { Browser } from "../browser";
async function getFiles(): Promise<Array<{ url: string }>> { type ImageFile = {
url: string;
};
async function getImageFiles(): Promise<Array<ImageFile>> {
const pages: NodeListOf<HTMLElement> = await new Promise(async function ( const pages: NodeListOf<HTMLElement> = await new Promise(async function (
resolve, resolve,
reject, reject,
@ -35,12 +38,11 @@ async function getFiles(): Promise<Array<{ url: string }>> {
(el) => el.querySelector("svg image")!, (el) => el.querySelector("svg image")!,
); );
const files = [...images].map((image) => ({ url: image.href.baseVal })); return [...images].map((image) => ({ url: image.href.baseVal }));
return files;
} }
async function drawImage(file: { url: string }): Promise<string> { async function fetchImage(imageFile: ImageFile): Promise<string> {
const res = await fetch(file.url); const res = await fetch(imageFile.url);
const blob = await res.blob(); const blob = await res.blob();
const dataUrl: string = await new Promise((resolve, reject) => { const dataUrl: string = await new Promise((resolve, reject) => {
const fileReader = Object.assign(new FileReader(), { const fileReader = Object.assign(new FileReader(), {
@ -98,7 +100,7 @@ export function GooglePlayBooks(browser: Browser) {
process.stderr.write(`\n`); process.stderr.write(`\n`);
}, },
async download(dir: string, book: Book) { async getFiles(book: Book): Promise<Array<() => Promise<string>>> {
const ctx = await browser.loadBrowserContext("google-play-books"); const ctx = await browser.loadBrowserContext("google-play-books");
const page = await ctx.newPage(); const page = await ctx.newPage();
@ -140,43 +142,23 @@ export function GooglePlayBooks(browser: Browser) {
}); });
} }
const fileMap: Map<string, { url: string; dataUrl: string }> = new Map(); const fileMap: Map<string, () => Promise<string>> = new Map();
while (await next()) { while (await next()) {
const files = await frame.evaluate(getFiles); const imageFiles = await frame.evaluate(getImageFiles);
for (const file of files) { for (const imageFile of imageFiles) {
if (fileMap.has(file.url)) continue; if (fileMap.has(imageFile.url)) continue;
const dataUrl = await frame.evaluate(fetchImage, imageFile);
const dataUrl = await frame.evaluate(drawImage, file);
fileMap.set(file.url, { ...file, dataUrl });
process.stderr.write("."); process.stderr.write(".");
fileMap.set(imageFile.url, async () => dataUrl);
} }
} }
const files = [...fileMap.values()]; return [...fileMap.values()];
const digits = String(files.length).length;
function pad(n: string) {
return n.padStart(digits, "0");
}
for (const [n, file] of Object.entries(files)) {
const [prefix, base64] = file.dataUrl.split(",", 2);
if (!prefix.startsWith("data:image/jpeg;")) {
throw new Error("Only image/jpeg is supported.");
}
if (!prefix.endsWith(";base64")) {
throw new Error("Only base64 is supported.");
}
const buffer = Buffer.from(base64, "base64");
await fs.writeFile(`${dir}/${pad(n)}.jpeg`, buffer);
}
process.stderr.write(`\n`);
}, },
}; };
} }