gadl/platforms/dmm-books.ts

215 lines
5.7 KiB
TypeScript
Raw Permalink Normal View History

2023-11-19 20:47:49 +09:00
import type { Book } from "../library";
2023-12-03 05:54:45 +09:00
import type { Browser, BrowserContext, ImageFile } from "../browser";
2023-12-03 00:48:24 +09:00
2023-11-19 20:47:49 +09:00
var NFBR: any;
2023-12-03 05:54:45 +09:00
export async function getImageFiles(): Promise<Array<ImageFile>> {
2023-11-19 20:47:49 +09:00
const params = new URLSearchParams(location.search);
const model = new NFBR.a6G.Model({
settings: new NFBR.Settings("NFBR.SettingData"),
viewerFontSize: NFBR.a0X.a3K,
viewerFontFace: NFBR.a0X.a3k,
viewerSpreadDouble: true,
viewerSpread: {},
});
const a6l = new NFBR.a6G.a6L(model);
const a2f = new NFBR.a2F();
const a5w = await a2f.a5W({
contentId: params.get(NFBR.a5q.Key.CONTENT_ID),
a6m: params.get(NFBR.a5q.Key.a6M),
preview:
params.get(NFBR.a5q.Key.LOOK_INSIDE) !== NFBR.a5q.LookInsideType.DISABLED,
previewType:
params.get(NFBR.a5q.Key.LOOK_INSIDE) ?? NFBR.a5q.LookInsideType.DISABLED,
contentType: a6l.getContentType(),
title: true,
});
const content = new NFBR.a6i.Content(a5w.url);
const a5n = new NFBR.a5n();
await a5n.a5s(content, "configuration", a6l);
2023-12-03 00:48:24 +09:00
const imageFiles: Array<ImageFile> = [];
2023-11-19 20:47:49 +09:00
for (const index of Object.keys(content.files)) {
const file = content.files[index];
const conf = content.configuration.contents[index];
const {
No,
2023-11-19 23:03:50 +09:00
DummyWidth,
DummyHeight,
2023-11-19 20:47:49 +09:00
Size: { Width, Height },
} = file.FileLinkInfo.PageLinkInfoList[0].Page;
const page = new NFBR.a6i.Page(
`${conf.file}/${No}.jpeg`,
index,
`${conf["original-file-path"]}#-acs-position-${file.PageToBookmark[0][0]}-${file.PageToBookmark[0][1]}`,
);
2023-11-19 23:03:50 +09:00
const w = [...`${conf.file}/${No}`]
.map((c) => c.charCodeAt(0))
2023-11-19 20:47:49 +09:00
.reduce((a, cc) => a + cc, 0);
const pattern = (w % NFBR.a0X.a3h) + 1;
const blocks = NFBR.a3E.a3f(
2023-11-19 23:03:50 +09:00
Width + DummyWidth,
Height + DummyHeight,
2023-11-19 20:47:49 +09:00
NFBR.a0X.a3g,
NFBR.a0X.a3G,
pattern,
);
const url = `${a5w.url}${page.url}`;
2023-12-03 00:48:24 +09:00
imageFiles.push({
2023-11-19 23:03:50 +09:00
url,
blocks,
width: Width,
height: Height,
});
2023-11-19 20:47:49 +09:00
}
2023-12-03 00:48:24 +09:00
return imageFiles;
2023-11-19 20:47:49 +09:00
}
2023-12-02 23:22:33 +09:00
export function DmmBooks(browser: Browser) {
2023-11-20 22:56:09 +09:00
async function* getSeriesBooks(
ctx: BrowserContext,
series: {
seriesId: string;
shopName: string;
title: string;
authors: Array<string>;
},
): AsyncGenerator<Book> {
const endpoint = `https://book.dmm.com/ajax/bff/contents/?shop_name=${series.shopName}&series_id=${series.seriesId}`;
const pager = {
page: 1,
perPage: 0,
totalCount: Infinity,
};
2023-12-03 16:14:38 +09:00
while ((pager.page - 1) * pager.perPage <= pager.totalCount) {
2023-11-20 22:56:09 +09:00
const res = await ctx.request.get(`${endpoint}&page=${pager.page}`);
if (!res.ok()) {
throw new Error(`${res.status()} ${res.statusText()}`);
}
const body: {
volume_books: Array<{
title: string;
purchased?: {
streaming_url: string;
};
}>;
pager: {
page: number;
per_page: number;
total_count: number;
};
} = await res.json();
for (const book of body.volume_books.filter((b) => b.purchased)) {
yield {
id: NaN,
platform: "dmm-books",
readerUrl: book.purchased?.streaming_url!,
title: book.title || series.title || "",
authors: series.authors,
};
process.stderr.write(".");
}
pager.page += 1;
pager.perPage = body.pager.per_page;
pager.totalCount = body.pager.total_count;
}
}
async function* getAllBooks(ctx: BrowserContext): AsyncGenerator<Book> {
const endpoint = "https://book.dmm.com/ajax/bff/library/?shop_name=all";
const pager = {
page: 1,
perPage: 0,
totalCount: Infinity,
};
2023-12-03 16:14:38 +09:00
while ((pager.page - 1) * pager.perPage <= pager.totalCount) {
2023-11-20 22:56:09 +09:00
const res = await ctx.request.get(`${endpoint}&page=${pager.page}`);
if (!res.ok()) {
throw new Error(`${res.status()} ${res.statusText()}`);
}
const body: {
series_books: Array<{
shop_name: string;
series_id: string;
title: string;
author: Array<string>;
}>;
pager: {
page: number;
per_page: number;
total_count: number;
};
} = await res.json();
for (const series of body.series_books) {
yield* getSeriesBooks(ctx, {
seriesId: series.series_id,
shopName: series.shop_name,
title: series.title,
authors: series.author,
});
}
pager.page += 1;
pager.perPage = body.pager.per_page;
pager.totalCount = body.pager.total_count;
}
}
2023-11-19 16:18:00 +09:00
return {
2023-11-20 22:56:09 +09:00
async *pull(): AsyncGenerator<Book> {
2023-12-02 23:22:33 +09:00
const ctx = await browser.loadBrowserContext("dmm-books");
2023-11-20 22:56:09 +09:00
yield* getAllBooks(ctx);
process.stderr.write(`\n`);
},
2023-12-03 16:14:38 +09:00
async getFiles(book: Book): Promise<Array<() => Promise<Blob>>> {
2023-12-02 23:22:33 +09:00
const ctx = await browser.loadBrowserContext("dmm-books");
2023-11-19 20:47:49 +09:00
const page = await ctx.newPage();
await page.goto(book.readerUrl);
2023-12-03 00:48:24 +09:00
const imageFiles = await page.evaluate(getImageFiles);
2023-11-19 20:47:49 +09:00
2023-12-03 00:48:24 +09:00
return imageFiles.map((imageFile) => async () => {
2023-12-03 16:14:38 +09:00
const blob = await browser.drawImage(page, imageFile);
2023-11-19 20:47:49 +09:00
process.stderr.write(".");
2023-12-03 16:14:38 +09:00
return blob;
2023-12-03 00:48:24 +09:00
});
2023-11-19 20:47:49 +09:00
},
2023-12-03 16:14:38 +09:00
loginEndpoints: [
"https://accounts.dmm.com/service/login/password",
"https://www.dmm.com/service/-/exchange",
],
loginSuccessUrl: (url: URL) =>
["https://www.dmm.com/", "https://www.dmm.co.jp/top/"].includes(url.href),
logoutEndpoints: [
"https://accounts.dmm.com/service/logout",
"https://accounts.dmm.co.jp/service/logout",
],
2023-11-19 16:18:00 +09:00
};
}
2023-12-02 23:22:33 +09:00
2023-12-03 05:54:45 +09:00
DmmBooks.siteUrl = (url: URL) =>
["https://book.dmm.com", "https://book.dmm.co.jp"].includes(url.origin);