diff --git a/README.md b/README.md
index 1df867f..135a496 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,10 @@
- [x] 支持自定义参数
- [ ] 广播
+## 拓展
+1. 结合Timeline插件 __构建个人观影时间线__,请参照[结合timeline插件实现时间线效果](./doc/Obsidian-Douban-TimeLine.md))
+2. 结合DataView插件,__构建个人电子书架(书库数据)__,请参照[结合dateview插件实现个人书架效果](./doc/Obsidian-Douban-DataView.md))
+
## 如何使用
### 同步
diff --git a/doc/Obsidian-Douban-DataView.md b/doc/Obsidian-Douban-DataView.md
new file mode 100644
index 0000000..c46dc4d
--- /dev/null
+++ b/doc/Obsidian-Douban-DataView.md
@@ -0,0 +1,69 @@
+## 效果如下
+
+## 适用人群
+1. 在豆瓣有标记/评论/评分的习惯的人
+比如看完电影,会在豆瓣进行评分或评论。或者阅读完的书籍,进行评分或评论。支持包含:电影、书籍、电视剧、音乐、游戏
+## 实现步骤
+1. 安装[obsidian-dataview](https://github.com/blacksmithgu/obsidian-dataview)插件
+2. 安装[Obsidian-Douban](https://github.com/Wanxp/obsidian-douban)插件(本插件)
+3. 在Obsidian-Douban插件配置中登录Douban
+4. 配置同步需要的模板 电影/书籍的模板中的frontmatter,在frontmatter中 **增加** 特定tags(根据自己的需要指定),用于需要过滤成为timeline的笔记,如增加tags:`书籍`
+````markdown
+---
+tags: 书籍
+---
+````
+5. 同时,在电影/书籍... 模板中的 **最后增加** timeline插件需要的html标签如下:
+
+```
+
+```
+6. 选择上述模板导入 电影/书籍...,操作方式是打开obsidian命令窗口,输入豆瓣,找到导入功能,在导入界面配置 选择模板进行导入
+7. 导入需要一定时间,每条内容导入需要15-30s左右,所有有导入完成后会有导入汇总
+8. 导入完成后,新建一个笔记,笔记内容加入DataView的代码块,指定搜索上面指定的tags的内容,如`书籍`,代码块如下:
+````markdown
+```dataview
+table file.name
+```
+````
+9. 预览这个笔记就能看出已经出现了时间线
+## 模板参考
+### 电影
+````markdown
+---
+doubanId: {{id}}
+title: {{title}}
+type: {{type}}
+score: {{score}}
+myRate: {{myRate}}
+originalTitle: {{originalTitle}}
+genre: {{genre}}
+datePublished: {{datePublished}}
+director: {{director}}
+actor: {{actor}}
+author: {{author}}
+tags: {{type}}, 我看过的电影, {{myTags}}
+state: {{myState}}
+url: {{url}}
+coverUrl: {{imageData.url}}
+createTime: {{currentDate}} {{currentTime}}
+collectionDate: {{myCollectionDate}}
+desc: {{desc}}
+---
+
+
+
+Comment:
+---
+{{myComment}}
+
+
+{{myComment}} |简介: {{desc}}
+
+````
+### 书籍、电视剧、音乐、游戏
+请参照电影模板
+## 更多
+参照讨论 [结合timeline插件的妙用](https://github.com/Wanxp/obsidian-douban/issues/19#issuecomment-1428307130)
diff --git a/doc/Obsidian-Douban-TimeLine.md b/doc/Obsidian-Douban-TimeLine.md
index 03ab3a9..34ac899 100644
--- a/doc/Obsidian-Douban-TimeLine.md
+++ b/doc/Obsidian-Douban-TimeLine.md
@@ -48,6 +48,7 @@ author: {{author}}
tags: {{type}}, 我看过的电影, {{myTags}}
state: {{myState}}
url: {{url}}
+coverUrl: {{imageData.url}}
createTime: {{currentDate}} {{currentTime}}
collectionDate: {{myCollectionDate}}
desc: {{desc}}
diff --git a/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts
index e294447..741642a 100644
--- a/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts
+++ b/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts
@@ -25,6 +25,7 @@ import DoubanLoginModel from "../../component/DoubanLoginModel";
import DoubanHumanCheckModel from "../../component/DoubanHumanCheckModel";
import DoubanMovieSubject from "../model/DoubanMovieSubject";
import {Person} from "schema-dts";
+import HttpUtil from "../../../utils/HttpUtil";
export default abstract class DoubanAbstractLoadHandler implements DoubanSubjectLoadHandler {
@@ -143,14 +144,7 @@ export default abstract class DoubanAbstractLoadHandler
headers.Cookie = context.settings.loginCookiesContent;
context.plugin.settingsManager.debug(`开始请求地址:${url}`)
context.plugin.settingsManager.debug(`(注意:请勿向任何人透露你的Cookie,此处若需要截图请**打码**)请求cookie:${context.settings.loginCookiesContent}`)
- const requestUrlParam: RequestUrlParam = {
- url: url,
- method: "GET",
- headers: headers,
- throw: true
- };
- await request(requestUrlParam)
- .then(s => this.humanCheck(s, url))
+ await HttpUtil.httpRequestGet(url, headers, context.plugin.settingsManager)
.then(load)
.then(data => this.analysisUserState(data, context))
.then(({data, userState}) => {
@@ -487,20 +481,8 @@ export default abstract class DoubanAbstractLoadHandler
abstract getHighQuantityImageUrl(fileName:string):string;
- private async humanCheck(html:any, url:string):Promise {
- this.doubanPlugin.settingsManager.debug(html);
- if (html && html.indexOf("禁止访问") != -1) {
- const loginModel = new DoubanHumanCheckModel(url);
- await loginModel.load();
- return '';
- }else {
- return html;
- }
-
- }
-
handlePersonNameByMeta(html: CheerioAPI, movie: DoubanSubject, context: HandleContext,
metaProperty:string, objectProperty:string) {
let metaProperties: string[] = html(`head > meta[property='${metaProperty}']`).get()
diff --git a/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts
index 5671ae8..70bb085 100644
--- a/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts
+++ b/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts
@@ -83,7 +83,7 @@ export default class DoubanTheaterLoadHandler extends DoubanAbstractLoadHandler<
const result: DoubanMovieSubject = {
id: id ? id[0] : '',
title: title,
- type: 'Movie',
+ type: 'Theater',
score: obj.aggregateRating ? obj.aggregateRating.ratingValue : undefined,
originalTitle: originalTitle,
desc: obj.description,
diff --git a/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts b/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts
index 1867868..133c94c 100644
--- a/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts
+++ b/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts
@@ -10,6 +10,7 @@ import {DoubanListHandler} from "./DoubanListHandler";
import {SyncConfig} from "../../model/SyncConfig";
import { sleepRange} from "../../../../utils/TimeUtil";
import {ALL} from "../../../../constant/DoubanUserState";
+import HttpUtil from "../../../../utils/HttpUtil";
export default abstract class DoubanAbstractListHandler implements DoubanListHandler{
@@ -47,13 +48,7 @@ export default abstract class DoubanAbstractListHandler implements DoubanListHan
async getPageList(url: string, context: HandleContext):Promise {
let headers = JSON.parse(context.settings.searchHeaders);
headers.Cookie = context.settings.loginCookiesContent;
- const requestUrlParam: RequestUrlParam = {
- url: url,
- method: "GET",
- headers: headers,
- throw: true
- };
- return request(requestUrlParam)
+ return HttpUtil.httpRequestGet(url, headers, context.plugin.settingsManager)
.then(load)
.then(data => this.parseSubjectFromHtml(data, context))
.catch(e => log
diff --git a/src/org/wanxp/douban/user/UserComponent.ts b/src/org/wanxp/douban/user/UserComponent.ts
index 8ac6512..e6e6334 100644
--- a/src/org/wanxp/douban/user/UserComponent.ts
+++ b/src/org/wanxp/douban/user/UserComponent.ts
@@ -1,5 +1,5 @@
import SettingsManager from "../setting/SettingsManager";
-import {request, RequestUrlParam} from "obsidian";
+import {RequestUrlParam} from "obsidian";
import {CheerioAPI, load} from "cheerio";
import {log} from "../../utils/Logutil";
import {i18nHelper} from "../../lang/helper";
@@ -7,6 +7,8 @@ import User from "./User";
import StringUtil from "../../utils/StringUtil";
import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings";
import {doubanHeaders} from "../../constant/Douban";
+import { request } from "https";
+import HttpUtil from "../../utils/HttpUtil";
export default class UserComponent {
private settingsManager: SettingsManager;
@@ -79,39 +81,17 @@ export default class UserComponent {
async loadUserInfo(cookie: any): Promise {
- const headers1 = {
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
- 'Accept-Language': 'zh-CN,zh;q=0.9',
- 'Cookie': cookie,
- 'Referer': 'https://accounts.douban.com/',
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
- }
- // Object.assign(headers, doubanHeaders, {'Cookie': cookie}, {'Referer': 'https://accounts.douban.com/'})
- let requestUrlParam: RequestUrlParam = {
- url: 'https://www.douban.com/mine/',
- method: "GET",
- headers: headers1,
- throw: true
- };
- this.settingsManager.debug('loadUserInfo:尝试获取用户信息:https://www.douban.com/mine/');
- return request(requestUrlParam)
- .then(requestUrlResponse => {
- if (requestUrlResponse.indexOf('https://sec.douban.com/a') > 0) {
- this.settingsManager.debug(`loadUserInfo:登录Douban获取异常网页如下:\n${requestUrlResponse}`);
- log.notice(i18nHelper.getMessage('130105'))
- }
- this.settingsManager.debug(`loadUserInfo:登录Douban获取网页如下:\n${requestUrlResponse}`);
- return requestUrlResponse;
- })
+ const headers1 = {
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
+ 'Accept-Language': 'zh-CN,zh;q=0.9',
+ 'Cookie': cookie,
+ 'Referer': 'https://accounts.douban.com/',
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
+ }
+ // const headers1 = StringUtil.parseHeaders(cookie)
+ return HttpUtil.httpRequestGet('https://www.douban.com/mine/', headers1, this.settingsManager)
.then(load)
- .then(this.getUserInfo)
- .catch(e => {
- if(e.toString().indexOf('403') > 0) {
- throw log.error(i18nHelper.getMessage('130105'), e)
- }else {
- throw log.error(i18nHelper.getMessage('130101').replace('{0}', e.toString()), e)
- }
- });
+ .then(this.getUserInfo);
};
diff --git a/src/org/wanxp/utils/HttpUtil.ts b/src/org/wanxp/utils/HttpUtil.ts
new file mode 100644
index 0000000..aa7a992
--- /dev/null
+++ b/src/org/wanxp/utils/HttpUtil.ts
@@ -0,0 +1,90 @@
+import axios from "axios";
+import {log} from "./Logutil";
+import {i18nHelper} from "../lang/helper";
+import SettingsManager from "../douban/setting/SettingsManager";
+import {request, RequestUrlParam} from "obsidian";
+import DoubanHumanCheckModel from "../douban/component/DoubanHumanCheckModel";
+
+export default class HttpUtil {
+ /**
+ * get请求
+ * @param url 请求地址
+ * @param headers 请求参数
+ * @param settingsManager 设置管理器
+ */
+ public static httpRequestGet(url: string, headers:any, settingsManager?:SettingsManager): Promise {
+ let requestUrlParam: RequestUrlParam = {
+ url: url,
+ method: "GET",
+ headers: headers,
+ throw: true
+ };
+ return request(requestUrlParam)
+ // .then(res => res.text)
+ .then(data => {
+ if (data && data.indexOf('https://sec.douban.com/a') > 0) {
+ log.notice(i18nHelper.getMessage('130105'))
+ if (settingsManager) {
+ settingsManager.debug(`Obsidian-Douban:获取异常网页如下:\n${data}`);
+ }
+ }
+ settingsManager.debug(`Obsidian-Douban:获取网页如下:\n${data}`);
+ return data;
+ })
+ .then(s => this.humanCheck(s, url, settingsManager))
+ .catch(e => {
+ if(e.toString().indexOf('403') > 0) {
+ throw log.error(i18nHelper.getMessage('130105'), e)
+ }else {
+ throw log.error(i18nHelper.getMessage('130101').replace('{0}', e.toString()), e)
+ }
+ })
+
+
+ }
+
+
+ public static async humanCheck(html:any, url:string, settingsManager?: SettingsManager):Promise {
+ if (settingsManager) {
+ settingsManager.debug(html);
+ }
+ if (html && html.indexOf("禁止访问") != -1) {
+ const loginModel = new DoubanHumanCheckModel(url);
+ await loginModel.load();
+ return '';
+ }else {
+ return html;
+ }
+
+
+
+ }
+
+ /**
+ * get请求
+ * @param url 请求地址
+ * @param settingsManager 设置管理器
+ */
+ public static httpRequestGetUrl(url: string, settingsManager?:SettingsManager): Promise {
+ return axios.get(url)
+ .then(res => res.data)
+ .then(data => {
+ if (data && data.indexOf('https://sec.douban.com/a') > 0) {
+ log.notice(i18nHelper.getMessage('130105'))
+ if (settingsManager) {
+ settingsManager.debug(`Obsidian-Douban:获取异常网页如下:\n${data}`);
+ }
+ }
+ settingsManager.debug(`Obsidian-Douban:获取网页如下:\n${data}`);
+ return data;
+ })
+ .catch(e => {
+ if(e.toString().indexOf('403') > 0) {
+ throw log.error(i18nHelper.getMessage('130105'), e)
+ }else {
+ throw log.error(i18nHelper.getMessage('130101').replace('{0}', e.toString()), e)
+ }
+ })
+ }
+
+}