diff --git a/build.js b/build.js
index fd47972..c3ad43a 100644
--- a/build.js
+++ b/build.js
@@ -91,4 +91,5 @@ async function buildTsx(names, tsnames) {
fs.rmSync('dist', { recursive: true, force: true });
fs.mkdirSync('dist', { recursive: true });
await build('qdchapter');
+await build('qdbook');
await buildTsx(['popup', 'settings'], ['background']);
diff --git a/inject/qdbook.js b/inject/qdbook.js
new file mode 100644
index 0000000..6fea686
--- /dev/null
+++ b/inject/qdbook.js
@@ -0,0 +1,3 @@
+window.addEventListener('load', function() {
+ window.postMessage({'@type': 'g_data', g_data}, '*');
+})
diff --git a/manifest.json b/manifest.json
index 8b648b7..39107d2 100644
--- a/manifest.json
+++ b/manifest.json
@@ -41,6 +41,27 @@
],
"run_at": "document_start",
"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": {
diff --git a/src/popup.tsx b/src/popup.tsx
index 19f8cf6..91583e2 100644
--- a/src/popup.tsx
+++ b/src/popup.tsx
@@ -42,6 +42,12 @@ function PopupBody() {
});
setResult(msg);
}
+ if (params.page === 'qdbook') {
+ const msg = await sendMessageToTab(tab.id, {
+ type: 'GetQdBookInfo',
+ });
+ setResult(msg);
+ }
} catch (e) {
setError(e instanceof Error ? e.message : 'Unknown error');
return;
@@ -63,6 +69,9 @@ function PopupBody() {
delete body.type;
return ;
}
+ if (result.ok && result.body?.type === 'QdBookInfo') {
+ return ;
+ }
return ;
}
if (error) {
diff --git a/src/qdbook.ts b/src/qdbook.ts
new file mode 100644
index 0000000..9f6c05b
--- /dev/null
+++ b/src/qdbook.ts
@@ -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);
+ }
+});
diff --git a/src/qdtypes.ts b/src/qdtypes.ts
index 418e3ad..a48e9e6 100644
--- a/src/qdtypes.ts
+++ b/src/qdtypes.ts
@@ -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;
+}
diff --git a/src/types.ts b/src/types.ts
index 69bc4a8..9b98680 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,4 +1,4 @@
-import * as QdTypes from "./qdtypes";
+import type * as QdTypes from "./qdtypes";
export type DiscriminatedUnion<
K extends PropertyKey,
@@ -22,8 +22,17 @@ export type QdChapterInfo = {
hash?: string;
}
+export type QDBookInfo = {
+ bookInfo: QdTypes.BookGData;
+ bookName: string;
+ /**Book ID */
+ id: number;
+ tags: QdTypes.QdBookTag[];
+}
+
export type SendMessageMap = {
GetQdChapterInfo: {};
+ GetQdBookInfo: {};
SaveQdChapterInfo: {
info: QdChapterInfo;
};
@@ -33,6 +42,7 @@ export type SendMessage = DiscriminatedUnion<"type", SendMessageMap>;
export type MessageMap = {
QdChapterInfo: QdChapterInfo,
+ QdBookInfo: QDBookInfo,
};
export type MessageBody = DiscriminatedUnion<"type", MessageMap>;
@@ -51,8 +61,13 @@ export type QdChapterUrlParams = {
chapterId: string;
}
+export type QdBookUrlParams = {
+ bookId: string;
+}
+
export type UrlParamsMap = {
qdchapter: QdChapterUrlParams;
+ qdbook: QdBookUrlParams;
}
export type UrlParams = DiscriminatedUnion<"page", UrlParamsMap>;
diff --git a/src/utils.ts b/src/utils.ts
index f750a43..4333870 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,6 +1,7 @@
import type { UrlParams, SendMessage, Message } from "./types";
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 {
const u = url instanceof URL ? url : new URL(url);
@@ -14,6 +15,14 @@ export function parseUrlParams(url: string | URL): UrlParams | undefined {
chapterId,
} as UrlParams;
}
+ const bookMatch = u.pathname.match(QD_BOOK_URLPATH_REGEX);
+ if (bookMatch) {
+ const [, bookId] = bookMatch;
+ return {
+ page: 'qdbook',
+ bookId,
+ } as UrlParams;
+ }
}
}