diff --git a/package-lock.json b/package-lock.json index 7add984..1dda66f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-weread-plugin", - "version": "0.6.0", + "version": "0.6.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "obsidian-weread-plugin", - "version": "0.6.0", + "version": "0.6.1", "license": "MIT", "dependencies": { "@types/crypto-js": "^4.1.2", diff --git a/src/api.ts b/src/api.ts index 0a951b8..8cbbc52 100644 --- a/src/api.ts +++ b/src/api.ts @@ -3,7 +3,12 @@ import { settingsStore } from './settings'; import { get } from 'svelte/store'; import { getCookieString } from './utils/cookiesUtil'; import { Cookie, parse, splitCookiesString } from 'set-cookie-parser'; -import { HighlightResponse, BookReviewResponse, ChapterResponse } from './models'; +import { + HighlightResponse, + BookReviewResponse, + ChapterResponse, + BookReadInfoResponse +} from './models'; export default class ApiManager { readonly baseUrl: string = 'https://i.weread.qq.com'; @@ -209,6 +214,19 @@ export default class ApiManager { console.error('get book chapters error' + bookId, e); } } + async getBookReadInfo(bookId: string): Promise { + try { + const url = `${this.baseUrl}/book/readinfo?bookId=${bookId}&readingDetail=1&readingBookIndex=1&finishedDate=1`; + const req: RequestUrlParam = { url: url, method: 'GET', headers: this.getHeaders() }; + const resp = await requestUrl(req); + return resp.json; + } catch (e) { + new Notice( + 'Failed to fetch weread notebook read info . Please check your Cookies and try again.' + ); + console.error('get book read info error' + bookId, e); + } + } private updateCookies(respCookie: string) { let refreshCookies: Cookie[]; diff --git a/src/models.ts b/src/models.ts index 7284fb9..c85e3c0 100644 --- a/src/models.ts +++ b/src/models.ts @@ -119,6 +119,80 @@ export type ChapterResponse = { }[]; }; +export type BookReadInfoResponse = { + finishedBookCount: number; + finishedBookIndex: number; + finishedDate: number; + readingBookCount: number; + readingBookDate: number; + readingProgress: number; + readingReviewId: string; + canCancelReadstatus: number; + markedStatus: number; + readingTime: number; + totalReadDay: number; + recordReadingTime: number; + continueReadDays: number; + continueBeginDate: number; + continueEndDate: number; + showSummary: number; + showDetail: number; + readDetail: { + totalReadingTime: number; + totalReadDay: number; + continueReadDays: number; + continueBeginDate: number; + continueEndDate: number; + beginReadingDate: number; + lastReadingDate: number; + longestReadingDate: number; + avgReadingTime: number; + longestReadingTime: number; + data: { + readDate: number; + readTime: number; + }[]; + }; + bookInfo: { + bookId: string; + title: string; + author: string; + translator: string; + intro: string; + cover: string; + version: number; + format: string; + type: number; + soldout: number; + bookStatus: number; + payType: number; + finished: number; + maxFreeChapter: number; + free: number; + mcardDiscount: number; + ispub: number; + extra_type: number; + cpid: number; + publishTime: string; + lastChapterIdx: number; + paperBook: { + skuId: string; + }; + centPrice: number; + readingCount: number; + maxfreeInfo: { + maxfreeChapterIdx: number; + maxfreeChapterUid: number; + maxfreeChapterRatio: number; + }; + blockSaveImg: number; + language: string; + hideUpdateTime: boolean; + isEPUBComics: number; + webBookControl: number; + }; +}; + export type Chapter = { chapterUid: number; chapterIdx: number; @@ -154,6 +228,19 @@ export type Metadata = { file?: AnnotationFile; totalWords?: number; rating?: string; + readInfo?: { + markedStatus: number; + readingTime: number; + totalReadDay: number; + continueReadDays: number; + readingBookCount: number; + readingBookIndex: number; + readingBookDate: number; + finishedBookCount: number; + finishedBookIndex: number; + finishedDate: number; + readingProgress: number; + }; }; export type Highlight = { diff --git a/src/syncNotebooks.ts b/src/syncNotebooks.ts index a6523a8..2a877a7 100644 --- a/src/syncNotebooks.ts +++ b/src/syncNotebooks.ts @@ -60,15 +60,21 @@ export default class SyncNotebooks { private async convertToNotebook(metaData: Metadata): Promise { const bookDetail = await this.apiManager.getBook(metaData.bookId); if (bookDetail) { - metaData['category'] = bookDetail['category']; - metaData['publisher'] = bookDetail['publisher']; - metaData['isbn'] = bookDetail['isbn']; - metaData['intro'] = bookDetail['intro']; - metaData['totalWords'] = bookDetail['totalWords']; + metaData.category = bookDetail['category']; + metaData.publisher = bookDetail['publisher']; + metaData.isbn = bookDetail['isbn']; + metaData.intro = bookDetail['intro']; + metaData.totalWords = bookDetail['totalWords']; const newRating = parseInt(bookDetail['newRating']); - metaData['rating'] = `${newRating / 10}%`; + metaData.rating = `${newRating / 10}%`; } + const readInfo = await this.apiManager.getBookReadInfo(metaData.bookId); + if (readInfo) { + metaData.readInfo = Object.assign({}, readInfo); + } + console.log('meta read info', readInfo); + const highlightResp = await this.apiManager.getNotebookHighlights(metaData.bookId); const reviewResp = await this.apiManager.getNotebookReviews(metaData.bookId); const chapterResp = await this.apiManager.getChapters(metaData.bookId); diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts new file mode 100644 index 0000000..dfa5edc --- /dev/null +++ b/src/utils/dateUtil.ts @@ -0,0 +1,12 @@ +export const formatTimeDuration = (duration: number): string => { + const hours = Math.floor(duration / 60); + const minutes = duration % 60; + + const formattedDuration = `${hours}小时${minutes}分钟`; + + return formattedDuration; +}; + +export const formatTimestampToDate = (readingBookDate: number): string => { + return window.moment(readingBookDate * 1000).format('YYYY-MM-DD'); +}; diff --git a/src/utils/frontmatter.ts b/src/utils/frontmatter.ts index e2f24aa..b71ff9e 100644 --- a/src/utils/frontmatter.ts +++ b/src/utils/frontmatter.ts @@ -1,5 +1,6 @@ import { Notice, parseYaml, stringifyYaml, TFile } from 'obsidian'; import type { Notebook } from '../models'; +import { formatTimeDuration, formatTimestampToDate } from './dateUtil'; type FrontMatterContent = { doc_type: string; @@ -8,10 +9,23 @@ type FrontMatterContent = { cover: string; noteCount: number; reviewCount: number; + readingStatus?: string; + progress?: string; + readingTime?: string; + totalReadDay?: number; + readingDate?: string; + finishedDate?: string; }; export const frontMatterDocType = 'weread-highlights-reviews'; +enum ReadingStatus { + '未标记' = 1, + '在读' = 2, + '读过' = 3, + '读完' = 4 +} + export const buildFrontMatter = ( markdownContent: string, noteBook: Notebook, @@ -25,6 +39,18 @@ export const buildFrontMatter = ( reviewCount: noteBook.metaData.reviewCount, noteCount: noteBook.metaData.noteCount }; + + const readInfo = noteBook.metaData.readInfo; + if (readInfo) { + frontMatter.readingStatus = ReadingStatus[readInfo.markedStatus]; + frontMatter.progress = readInfo.readingProgress + '%'; + frontMatter.totalReadDay = readInfo.totalReadDay; + frontMatter.readingTime = formatTimeDuration(readInfo.readingTime); + frontMatter.readingDate = formatTimestampToDate(readInfo.readingBookDate); + if (readInfo.finishedDate) { + frontMatter.finishedDate = formatTimestampToDate(readInfo.finishedDate); + } + } let existFrontMatter = Object(); if (existFile) { const cache = app.metadataCache.getFileCache(existFile);