mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 16:48:44 +08:00
feature: theater
function: HttpUtil
This commit is contained in:
parent
198cffaada
commit
44697ac05a
@ -44,6 +44,10 @@
|
|||||||
- [x] 支持自定义参数
|
- [x] 支持自定义参数
|
||||||
- [ ] 广播
|
- [ ] 广播
|
||||||
|
|
||||||
|
## 拓展
|
||||||
|
1. 结合Timeline插件 __构建个人观影时间线__,请参照[结合timeline插件实现时间线效果](./doc/Obsidian-Douban-TimeLine.md))
|
||||||
|
2. 结合DataView插件,__构建个人电子书架(书库数据)__,请参照[结合dateview插件实现个人书架效果](./doc/Obsidian-Douban-DataView.md))
|
||||||
|
|
||||||
|
|
||||||
## 如何使用
|
## 如何使用
|
||||||
### 同步
|
### 同步
|
||||||
|
|||||||
69
doc/Obsidian-Douban-DataView.md
Normal file
69
doc/Obsidian-Douban-DataView.md
Normal file
@ -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}}
|
||||||
|
|
||||||
|
|
||||||
|
<span class='ob-timelines' data-date='{{myCollectionDate}}'
|
||||||
|
data-title='{{title}}' data-img='{{image}}'
|
||||||
|
data-class = "custom-my-movie-time-line">{{myComment}} |简介: {{desc}}
|
||||||
|
</span>
|
||||||
|
````
|
||||||
|
### 书籍、电视剧、音乐、游戏
|
||||||
|
请参照电影模板
|
||||||
|
## 更多
|
||||||
|
参照讨论 [结合timeline插件的妙用](https://github.com/Wanxp/obsidian-douban/issues/19#issuecomment-1428307130)
|
||||||
@ -48,6 +48,7 @@ author: {{author}}
|
|||||||
tags: {{type}}, 我看过的电影, {{myTags}}
|
tags: {{type}}, 我看过的电影, {{myTags}}
|
||||||
state: {{myState}}
|
state: {{myState}}
|
||||||
url: {{url}}
|
url: {{url}}
|
||||||
|
coverUrl: {{imageData.url}}
|
||||||
createTime: {{currentDate}} {{currentTime}}
|
createTime: {{currentDate}} {{currentTime}}
|
||||||
collectionDate: {{myCollectionDate}}
|
collectionDate: {{myCollectionDate}}
|
||||||
desc: {{desc}}
|
desc: {{desc}}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import DoubanLoginModel from "../../component/DoubanLoginModel";
|
|||||||
import DoubanHumanCheckModel from "../../component/DoubanHumanCheckModel";
|
import DoubanHumanCheckModel from "../../component/DoubanHumanCheckModel";
|
||||||
import DoubanMovieSubject from "../model/DoubanMovieSubject";
|
import DoubanMovieSubject from "../model/DoubanMovieSubject";
|
||||||
import {Person} from "schema-dts";
|
import {Person} from "schema-dts";
|
||||||
|
import HttpUtil from "../../../utils/HttpUtil";
|
||||||
|
|
||||||
export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject> implements DoubanSubjectLoadHandler<T> {
|
export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject> implements DoubanSubjectLoadHandler<T> {
|
||||||
|
|
||||||
@ -143,14 +144,7 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
|
|||||||
headers.Cookie = context.settings.loginCookiesContent;
|
headers.Cookie = context.settings.loginCookiesContent;
|
||||||
context.plugin.settingsManager.debug(`开始请求地址:${url}`)
|
context.plugin.settingsManager.debug(`开始请求地址:${url}`)
|
||||||
context.plugin.settingsManager.debug(`(注意:请勿向任何人透露你的Cookie,此处若需要截图请**打码**)请求cookie:${context.settings.loginCookiesContent}`)
|
context.plugin.settingsManager.debug(`(注意:请勿向任何人透露你的Cookie,此处若需要截图请**打码**)请求cookie:${context.settings.loginCookiesContent}`)
|
||||||
const requestUrlParam: RequestUrlParam = {
|
await HttpUtil.httpRequestGet(url, headers, context.plugin.settingsManager)
|
||||||
url: url,
|
|
||||||
method: "GET",
|
|
||||||
headers: headers,
|
|
||||||
throw: true
|
|
||||||
};
|
|
||||||
await request(requestUrlParam)
|
|
||||||
.then(s => this.humanCheck(s, url))
|
|
||||||
.then(load)
|
.then(load)
|
||||||
.then(data => this.analysisUserState(data, context))
|
.then(data => this.analysisUserState(data, context))
|
||||||
.then(({data, userState}) => {
|
.then(({data, userState}) => {
|
||||||
@ -487,20 +481,8 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
|
|||||||
|
|
||||||
abstract getHighQuantityImageUrl(fileName:string):string;
|
abstract getHighQuantityImageUrl(fileName:string):string;
|
||||||
|
|
||||||
private async humanCheck(html:any, url:string):Promise<any> {
|
|
||||||
this.doubanPlugin.settingsManager.debug(html);
|
|
||||||
if (html && html.indexOf("<title>禁止访问</title>") != -1) {
|
|
||||||
const loginModel = new DoubanHumanCheckModel(url);
|
|
||||||
await loginModel.load();
|
|
||||||
return '';
|
|
||||||
}else {
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePersonNameByMeta(html: CheerioAPI, movie: DoubanSubject, context: HandleContext,
|
handlePersonNameByMeta(html: CheerioAPI, movie: DoubanSubject, context: HandleContext,
|
||||||
metaProperty:string, objectProperty:string) {
|
metaProperty:string, objectProperty:string) {
|
||||||
let metaProperties: string[] = html(`head > meta[property='${metaProperty}']`).get()
|
let metaProperties: string[] = html(`head > meta[property='${metaProperty}']`).get()
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export default class DoubanTheaterLoadHandler extends DoubanAbstractLoadHandler<
|
|||||||
const result: DoubanMovieSubject = {
|
const result: DoubanMovieSubject = {
|
||||||
id: id ? id[0] : '',
|
id: id ? id[0] : '',
|
||||||
title: title,
|
title: title,
|
||||||
type: 'Movie',
|
type: 'Theater',
|
||||||
score: obj.aggregateRating ? obj.aggregateRating.ratingValue : undefined,
|
score: obj.aggregateRating ? obj.aggregateRating.ratingValue : undefined,
|
||||||
originalTitle: originalTitle,
|
originalTitle: originalTitle,
|
||||||
desc: obj.description,
|
desc: obj.description,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import {DoubanListHandler} from "./DoubanListHandler";
|
|||||||
import {SyncConfig} from "../../model/SyncConfig";
|
import {SyncConfig} from "../../model/SyncConfig";
|
||||||
import { sleepRange} from "../../../../utils/TimeUtil";
|
import { sleepRange} from "../../../../utils/TimeUtil";
|
||||||
import {ALL} from "../../../../constant/DoubanUserState";
|
import {ALL} from "../../../../constant/DoubanUserState";
|
||||||
|
import HttpUtil from "../../../../utils/HttpUtil";
|
||||||
|
|
||||||
export default abstract class DoubanAbstractListHandler implements DoubanListHandler{
|
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<SubjectListItem[]> {
|
async getPageList(url: string, context: HandleContext):Promise<SubjectListItem[]> {
|
||||||
let headers = JSON.parse(context.settings.searchHeaders);
|
let headers = JSON.parse(context.settings.searchHeaders);
|
||||||
headers.Cookie = context.settings.loginCookiesContent;
|
headers.Cookie = context.settings.loginCookiesContent;
|
||||||
const requestUrlParam: RequestUrlParam = {
|
return HttpUtil.httpRequestGet(url, headers, context.plugin.settingsManager)
|
||||||
url: url,
|
|
||||||
method: "GET",
|
|
||||||
headers: headers,
|
|
||||||
throw: true
|
|
||||||
};
|
|
||||||
return request(requestUrlParam)
|
|
||||||
.then(load)
|
.then(load)
|
||||||
.then(data => this.parseSubjectFromHtml(data, context))
|
.then(data => this.parseSubjectFromHtml(data, context))
|
||||||
.catch(e => log
|
.catch(e => log
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import SettingsManager from "../setting/SettingsManager";
|
import SettingsManager from "../setting/SettingsManager";
|
||||||
import {request, RequestUrlParam} from "obsidian";
|
import {RequestUrlParam} from "obsidian";
|
||||||
import {CheerioAPI, load} from "cheerio";
|
import {CheerioAPI, load} from "cheerio";
|
||||||
import {log} from "../../utils/Logutil";
|
import {log} from "../../utils/Logutil";
|
||||||
import {i18nHelper} from "../../lang/helper";
|
import {i18nHelper} from "../../lang/helper";
|
||||||
@ -7,6 +7,8 @@ import User from "./User";
|
|||||||
import StringUtil from "../../utils/StringUtil";
|
import StringUtil from "../../utils/StringUtil";
|
||||||
import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings";
|
import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings";
|
||||||
import {doubanHeaders} from "../../constant/Douban";
|
import {doubanHeaders} from "../../constant/Douban";
|
||||||
|
import { request } from "https";
|
||||||
|
import HttpUtil from "../../utils/HttpUtil";
|
||||||
|
|
||||||
export default class UserComponent {
|
export default class UserComponent {
|
||||||
private settingsManager: SettingsManager;
|
private settingsManager: SettingsManager;
|
||||||
@ -86,32 +88,10 @@ export default class UserComponent {
|
|||||||
'Referer': 'https://accounts.douban.com/',
|
'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'
|
'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/'})
|
// const headers1 = StringUtil.parseHeaders(cookie)
|
||||||
let requestUrlParam: RequestUrlParam = {
|
return HttpUtil.httpRequestGet('https://www.douban.com/mine/', headers1, this.settingsManager)
|
||||||
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;
|
|
||||||
})
|
|
||||||
.then(load)
|
.then(load)
|
||||||
.then(this.getUserInfo)
|
.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)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
90
src/org/wanxp/utils/HttpUtil.ts
Normal file
90
src/org/wanxp/utils/HttpUtil.ts
Normal file
@ -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<string> {
|
||||||
|
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<any> {
|
||||||
|
if (settingsManager) {
|
||||||
|
settingsManager.debug(html);
|
||||||
|
}
|
||||||
|
if (html && html.indexOf("<title>禁止访问</title>") != -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<string> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user