mirror of
https://github.com/lifegpc/bookdownload.git
synced 2026-07-08 01:31:31 +08:00
Add support to get book info from book info page
This commit is contained in:
1
build.js
1
build.js
@@ -91,4 +91,5 @@ async function buildTsx(names, tsnames) {
|
|||||||
fs.rmSync('dist', { recursive: true, force: true });
|
fs.rmSync('dist', { recursive: true, force: true });
|
||||||
fs.mkdirSync('dist', { recursive: true });
|
fs.mkdirSync('dist', { recursive: true });
|
||||||
await build('qdchapter');
|
await build('qdchapter');
|
||||||
|
await build('qdbook');
|
||||||
await buildTsx(['popup', 'settings'], ['background']);
|
await buildTsx(['popup', 'settings'], ['background']);
|
||||||
|
|||||||
3
inject/qdbook.js
Normal file
3
inject/qdbook.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
window.addEventListener('load', function() {
|
||||||
|
window.postMessage({'@type': 'g_data', g_data}, '*');
|
||||||
|
})
|
||||||
@@ -41,6 +41,27 @@
|
|||||||
],
|
],
|
||||||
"run_at": "document_start",
|
"run_at": "document_start",
|
||||||
"world": "MAIN"
|
"world": "MAIN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"http://*.qidian.com/book/*",
|
||||||
|
"https://*.qidian.com/book/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"dist/qdbook.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matches": [
|
||||||
|
"http://*.qidian.com/book/*",
|
||||||
|
"https://*.qidian.com/book/*"
|
||||||
|
],
|
||||||
|
"js": [
|
||||||
|
"inject/qdbook.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_start",
|
||||||
|
"world": "MAIN"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"options_ui": {
|
"options_ui": {
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ function PopupBody() {
|
|||||||
});
|
});
|
||||||
setResult(msg);
|
setResult(msg);
|
||||||
}
|
}
|
||||||
|
if (params.page === 'qdbook') {
|
||||||
|
const msg = await sendMessageToTab(tab.id, {
|
||||||
|
type: 'GetQdBookInfo',
|
||||||
|
});
|
||||||
|
setResult(msg);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e instanceof Error ? e.message : 'Unknown error');
|
setError(e instanceof Error ? e.message : 'Unknown error');
|
||||||
return;
|
return;
|
||||||
@@ -63,6 +69,9 @@ function PopupBody() {
|
|||||||
delete body.type;
|
delete body.type;
|
||||||
return <QdChapterInfoModel info={body} />;
|
return <QdChapterInfoModel info={body} />;
|
||||||
}
|
}
|
||||||
|
if (result.ok && result.body?.type === 'QdBookInfo') {
|
||||||
|
return <Result status="success" title={result.body.bookName} subTitle={`Book ID: ${result.body.id}`} />;
|
||||||
|
}
|
||||||
return <Result status="error" title="错误" subTitle={result.msg || '未知错误'} />;
|
return <Result status="error" title="错误" subTitle={result.msg || '未知错误'} />;
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
103
src/qdbook.ts
Normal file
103
src/qdbook.ts
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import type { BookGData, QdBookTag } from "./qdtypes";
|
||||||
|
import type { SendMessage, Message } from "./types";
|
||||||
|
import { QdBookTagType } from "./qdtypes";
|
||||||
|
|
||||||
|
let g_data: BookGData | undefined;
|
||||||
|
|
||||||
|
function get_book_name() {
|
||||||
|
const bookName = document.getElementById('bookName') as HTMLHeadingElement | null;
|
||||||
|
if (!bookName) {
|
||||||
|
throw new Error('Failed to find book name element');
|
||||||
|
}
|
||||||
|
return bookName.innerText.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_book_tags() {
|
||||||
|
const tags: QdBookTag[] = [];
|
||||||
|
const attribute = document.querySelector('p.book-attribute');
|
||||||
|
if (attribute) {
|
||||||
|
for (const children of attribute.children) {
|
||||||
|
if (children instanceof HTMLSpanElement) {
|
||||||
|
if (children.classList.contains("dot")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tags.push({
|
||||||
|
type: QdBookTagType.System,
|
||||||
|
name: children.innerText.trim(),
|
||||||
|
});
|
||||||
|
} else if (children instanceof HTMLAnchorElement) {
|
||||||
|
tags.push({
|
||||||
|
type: QdBookTagType.Category,
|
||||||
|
name: children.innerText.trim(),
|
||||||
|
url: children.href,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown tag element: ${children.outerHTML}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const allLabel = document.querySelector('p.all-label');
|
||||||
|
if (allLabel) {
|
||||||
|
for (const label of allLabel.children) {
|
||||||
|
if (label instanceof HTMLAnchorElement) {
|
||||||
|
tags.push({
|
||||||
|
type: QdBookTagType.User,
|
||||||
|
name: label.innerText.trim(),
|
||||||
|
url: label.href,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unknown user tag element: ${label.outerHTML}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', (event) => {
|
||||||
|
const data = event.data;
|
||||||
|
if (data && data['@type'] === 'g_data') {
|
||||||
|
g_data = data.g_data;
|
||||||
|
console.log('Received g_data:', g_data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
const m = message as SendMessage;
|
||||||
|
try {
|
||||||
|
if (m.type === 'GetQdBookInfo') {
|
||||||
|
if (!g_data) {
|
||||||
|
const msg: Message = {
|
||||||
|
ok: false,
|
||||||
|
code: 404,
|
||||||
|
msg: '没有找到g_data,可能是页面数据还没有加载完成,请稍后再试或者尝试刷新页面',
|
||||||
|
for: m.type,
|
||||||
|
};
|
||||||
|
sendResponse(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bookName = get_book_name();
|
||||||
|
const msg: Message = {
|
||||||
|
ok: true,
|
||||||
|
code: 0,
|
||||||
|
body: {
|
||||||
|
type: 'QdBookInfo',
|
||||||
|
bookInfo: g_data,
|
||||||
|
bookName,
|
||||||
|
id: g_data.pageJson.bookId,
|
||||||
|
tags: get_book_tags(),
|
||||||
|
},
|
||||||
|
for: m.type,
|
||||||
|
};
|
||||||
|
sendResponse(msg);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
const msg: Message = {
|
||||||
|
ok: false,
|
||||||
|
code: 500,
|
||||||
|
msg: e instanceof Error ? e.message : 'Unknown error',
|
||||||
|
for: m.type,
|
||||||
|
};
|
||||||
|
sendResponse(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -166,3 +166,45 @@ export type PageContext = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BookGData = {
|
||||||
|
chanId: number;
|
||||||
|
checkLevel8: boolean;
|
||||||
|
firstChapterId: number;
|
||||||
|
imgUrl: string;
|
||||||
|
isBookAlbum: boolean;
|
||||||
|
isCatelog: boolean;
|
||||||
|
isPublication: number;
|
||||||
|
pageJson: {
|
||||||
|
authorInfo: {
|
||||||
|
authorId: string;
|
||||||
|
authorName: string;
|
||||||
|
avatar: string;
|
||||||
|
},
|
||||||
|
bookId: number;
|
||||||
|
bookType: number;
|
||||||
|
isLogin: boolean;
|
||||||
|
isPublication: boolean;
|
||||||
|
isSign: number;
|
||||||
|
isVip: number;
|
||||||
|
salesMode: number;
|
||||||
|
signStatus: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Volume = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum QdBookTagType {
|
||||||
|
System,
|
||||||
|
Category,
|
||||||
|
User,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QdBookTag = {
|
||||||
|
name: string;
|
||||||
|
type: QdBookTagType;
|
||||||
|
url?: string;
|
||||||
|
}
|
||||||
|
|||||||
17
src/types.ts
17
src/types.ts
@@ -1,4 +1,4 @@
|
|||||||
import * as QdTypes from "./qdtypes";
|
import type * as QdTypes from "./qdtypes";
|
||||||
|
|
||||||
export type DiscriminatedUnion<
|
export type DiscriminatedUnion<
|
||||||
K extends PropertyKey,
|
K extends PropertyKey,
|
||||||
@@ -22,8 +22,17 @@ export type QdChapterInfo = {
|
|||||||
hash?: string;
|
hash?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type QDBookInfo = {
|
||||||
|
bookInfo: QdTypes.BookGData;
|
||||||
|
bookName: string;
|
||||||
|
/**Book ID */
|
||||||
|
id: number;
|
||||||
|
tags: QdTypes.QdBookTag[];
|
||||||
|
}
|
||||||
|
|
||||||
export type SendMessageMap = {
|
export type SendMessageMap = {
|
||||||
GetQdChapterInfo: {};
|
GetQdChapterInfo: {};
|
||||||
|
GetQdBookInfo: {};
|
||||||
SaveQdChapterInfo: {
|
SaveQdChapterInfo: {
|
||||||
info: QdChapterInfo;
|
info: QdChapterInfo;
|
||||||
};
|
};
|
||||||
@@ -33,6 +42,7 @@ export type SendMessage = DiscriminatedUnion<"type", SendMessageMap>;
|
|||||||
|
|
||||||
export type MessageMap = {
|
export type MessageMap = {
|
||||||
QdChapterInfo: QdChapterInfo,
|
QdChapterInfo: QdChapterInfo,
|
||||||
|
QdBookInfo: QDBookInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MessageBody = DiscriminatedUnion<"type", MessageMap>;
|
export type MessageBody = DiscriminatedUnion<"type", MessageMap>;
|
||||||
@@ -51,8 +61,13 @@ export type QdChapterUrlParams = {
|
|||||||
chapterId: string;
|
chapterId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type QdBookUrlParams = {
|
||||||
|
bookId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type UrlParamsMap = {
|
export type UrlParamsMap = {
|
||||||
qdchapter: QdChapterUrlParams;
|
qdchapter: QdChapterUrlParams;
|
||||||
|
qdbook: QdBookUrlParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UrlParams = DiscriminatedUnion<"page", UrlParamsMap>;
|
export type UrlParams = DiscriminatedUnion<"page", UrlParamsMap>;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { UrlParams, SendMessage, Message } from "./types";
|
import type { UrlParams, SendMessage, Message } from "./types";
|
||||||
|
|
||||||
export const QD_CHAPTER_URLPATH_REGEX = /^\/chapter\/(\d+)\/(\d+)\/?$/;
|
export const QD_CHAPTER_URLPATH_REGEX = /^\/chapter\/(\d+)\/(\d+)\/?$/;
|
||||||
|
export const QD_BOOK_URLPATH_REGEX = /^\/book\/(\d+)\/?$/;
|
||||||
|
|
||||||
export function parseUrlParams(url: string | URL): UrlParams | undefined {
|
export function parseUrlParams(url: string | URL): UrlParams | undefined {
|
||||||
const u = url instanceof URL ? url : new URL(url);
|
const u = url instanceof URL ? url : new URL(url);
|
||||||
@@ -14,6 +15,14 @@ export function parseUrlParams(url: string | URL): UrlParams | undefined {
|
|||||||
chapterId,
|
chapterId,
|
||||||
} as UrlParams;
|
} as UrlParams;
|
||||||
}
|
}
|
||||||
|
const bookMatch = u.pathname.match(QD_BOOK_URLPATH_REGEX);
|
||||||
|
if (bookMatch) {
|
||||||
|
const [, bookId] = bookMatch;
|
||||||
|
return {
|
||||||
|
page: 'qdbook',
|
||||||
|
bookId,
|
||||||
|
} as UrlParams;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user