feature: theater

function: HttpUtil
This commit is contained in:
wanxp 2023-09-20 09:54:29 +08:00
parent 198cffaada
commit 44697ac05a
8 changed files with 182 additions and 61 deletions

@ -44,6 +44,10 @@
- [x] 支持自定义参数 - [x] 支持自定义参数
- [ ] 广播 - [ ] 广播
## 拓展
1. 结合Timeline插件 __构建个人观影时间线__,请参照[结合timeline插件实现时间线效果](./doc/Obsidian-Douban-TimeLine.md))
2. 结合DataView插件__构建个人电子书架书库数据__请参照[结合dateview插件实现个人书架效果](./doc/Obsidian-Douban-DataView.md))
## 如何使用 ## 如何使用
### 同步 ### 同步

@ -0,0 +1,69 @@
## 效果如下
![](./img/obsidian-douban-time-preview-example.gif)
## 适用人群
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}}
---
![image]({{image}})
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;
@ -79,39 +81,17 @@ export default class UserComponent {
async loadUserInfo(cookie: any): Promise<User> { async loadUserInfo(cookie: any): Promise<User> {
const headers1 = { 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': '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', 'Accept-Language': 'zh-CN,zh;q=0.9',
'Cookie': cookie, 'Cookie': cookie,
'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)
}
});
}; };

@ -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)
}
})
}
}