mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 08:38:41 +08:00
add douban login
This commit is contained in:
parent
53ca2ec446
commit
1f30482542
@ -35,7 +35,7 @@ If you want some features or have any questions about this plugin, create issues
|
||||
|
||||
---
|
||||
| 字段 | 电影 | 电视剧 | 书籍 | 音乐 | 日记 | 游戏 | 广播 |
|
||||
| ------------- | -------------------- | -------------------- | -------------------- | ------------------ | ------------------ | ---------------- | ---- |
|
||||
| ----------- | -------------------- | -------------------- |-------------------| ------------------ | ------------------ | ---------------- | ---- |
|
||||
| id | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | - |
|
||||
| title | 电影名称 | 电视剧名称 | 书名 | 音乐名 | 日记标题 | 游戏名称 | - |
|
||||
| type | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | - |
|
||||
@ -58,6 +58,7 @@ If you want some features or have any questions about this plugin, create issues
|
||||
| 扩展8 | | | menu:目录 | | | | |
|
||||
| 扩展9 | | | price:定价 | | | | |
|
||||
| 扩展7 | | | binding:装帧 | | | | |
|
||||
| 扩展8 | | | producer: 出品方 | | | | |
|
||||
|
||||
## How to use
|
||||
### Search
|
||||
|
||||
10
main.ts
10
main.ts
@ -15,12 +15,16 @@ import HandleResult from "@App/data/model/HandleResult";
|
||||
import {FileUtil} from "./src/utils/FileUtil";
|
||||
import { DoubanPluginSetting } from "@App/setting/model/DoubanPluginSetting";
|
||||
import {DEFAULT_SETTINGS} from "./src/constant/DefaultSettings";
|
||||
import UserComponent from "@App/user/UserComponent";
|
||||
import SettingsManager from "@App/setting/SettingsManager";
|
||||
|
||||
export default class DoubanPlugin extends Plugin {
|
||||
public settings: DoubanPluginSetting;
|
||||
public doubanExtractHandler: DoubanSearchChooseItemHandler;
|
||||
public doubanStatusBar: HTMLElement;
|
||||
public fileHandler: FileHandler;
|
||||
public userComponent: UserComponent;
|
||||
public settingsManager: SettingsManager;
|
||||
|
||||
|
||||
async putToObsidian(context: HandleContext, extract: DoubanSubject) {
|
||||
@ -124,6 +128,12 @@ export default class DoubanPlugin extends Plugin {
|
||||
editorCallback: (editor: Editor) =>
|
||||
this.getDoubanTextForSearchTerm({mode: SearchHandleMode.FOR_REPLACE, settings: this.settings, editor: editor}),
|
||||
});
|
||||
this.settingsManager = new SettingsManager(app, this);
|
||||
this.userComponent = new UserComponent(this.settingsManager);
|
||||
|
||||
if (this.userComponent.needLogin()) {
|
||||
this.userComponent.loginByCookie();
|
||||
}
|
||||
|
||||
this.addSettingTab(new DoubanSettingTab(this.app, this));
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ score: {{score}}
|
||||
datePublished: {{datePublished}}
|
||||
translator: {{translator}}
|
||||
publisher: {{publisher}}
|
||||
producer: {{producer}}
|
||||
isbn: {{isbn}}
|
||||
url: {{url}}
|
||||
totalPage: {{totalPage}}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
import {Notice} from "obsidian";
|
||||
|
||||
export const ensureStatusCode = (expected: any) => {
|
||||
if (!Array.isArray(expected))
|
||||
expected = [expected];
|
||||
return (res: any) => {
|
||||
const {statusCode} = res;
|
||||
if (!expected.includes(statusCode)) {
|
||||
new Notice(`Request Douban failed, Status code must be "${expected}" but actually "${statusCode}"`)
|
||||
}
|
||||
return res;
|
||||
};
|
||||
};
|
||||
@ -3,7 +3,7 @@ import { log } from 'src/utils/Logutil';
|
||||
import {i18nHelper} from "../../lang/helper";
|
||||
import {DoubanSettingTab} from "@App/setting/DoubanSettingTab";
|
||||
import SettingsManager from "@App/setting/SettingsManager";
|
||||
import {constructDoubanTokenSettingsUI, constructLoginSettingsUI} from "@App/setting/BasicSettingsHelper";
|
||||
import {constructDoubanTokenSettingsUI} from "@App/setting/BasicSettingsHelper";
|
||||
|
||||
// Credits go to zhaohongxuan's Weread Plugin : https://github.com/zhaohongxuan/obsidian-weread-plugin
|
||||
|
||||
@ -35,12 +35,12 @@ export default class DoubanLoginModel {
|
||||
const filter = {
|
||||
urls: ['https://www.douban.com/']
|
||||
};
|
||||
session.webRequest.onSendHeaders(filter, (details:any) => {
|
||||
session.webRequest.onSendHeaders(filter, async (details:any) => {
|
||||
const cookies = details.requestHeaders['Cookie'];
|
||||
const cookieArr = this.parseCookies(cookies);
|
||||
// const wr_name = cookieArr.find((cookie) => cookie.name == 'wr_name').value;
|
||||
if (cookieArr) {
|
||||
this.settingsManager.updateSetting('loginCookiesContent', cookieArr);
|
||||
let user = await settingsManager.plugin.userComponent.loginCookie(cookieArr);
|
||||
constructDoubanTokenSettingsUI(containerEl, settingsManager);
|
||||
this.modal.close();
|
||||
} else {
|
||||
|
||||
@ -9,9 +9,9 @@ import {log} from "../../utils/Logutil";
|
||||
|
||||
export default class DoubanLogoutModel {
|
||||
private modal: any;
|
||||
private containerEl: HTMLElement;
|
||||
private settingsManager: SettingsManager;
|
||||
constructor(containerEl: HTMLElement, settingsManager: SettingsManager) {
|
||||
this.settingsManager = settingsManager;
|
||||
const { remote } = require('electron');
|
||||
const { BrowserWindow: RemoteBrowserWindow } = remote;
|
||||
this.modal = new RemoteBrowserWindow({
|
||||
@ -26,12 +26,11 @@ export default class DoubanLogoutModel {
|
||||
});
|
||||
const session = this.modal.webContents.session;
|
||||
const filter = {
|
||||
urls: ['https://www.douban.com/accounts/logout']
|
||||
urls: ['https://www.douban.com/']
|
||||
};
|
||||
session.webRequest.onCompleted(filter, (details:any) => {
|
||||
log.info('已请求登出成功:');
|
||||
if (details.statusCode == 200) {
|
||||
this.settingsManager.updateSetting('loginCookiesContent', '');
|
||||
this.settingsManager.plugin.userComponent.logout();
|
||||
constructDoubanTokenSettingsUI(containerEl, settingsManager);
|
||||
this.modal.close();
|
||||
}
|
||||
@ -39,7 +38,7 @@ export default class DoubanLogoutModel {
|
||||
}
|
||||
|
||||
async doLogout() {
|
||||
await this.modal.loadURL('https://www.douban.com/logout');
|
||||
await this.modal.loadURL('https://www.douban.com/');
|
||||
}
|
||||
|
||||
onClose() {
|
||||
|
||||
@ -4,13 +4,13 @@ import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings";
|
||||
import SettingsManager from "@App/setting/SettingsManager";
|
||||
import DoubanLoginModel from "@App/component/DoubanLoginModel";
|
||||
import DoubanLogoutModel from "@App/component/DoubanLogoutModel";
|
||||
import { log } from "src/utils/Logutil";
|
||||
import User from "@App/user/User";
|
||||
|
||||
export function constructBasicUI(containerEl: HTMLElement, manager: SettingsManager) {
|
||||
containerEl.createEl('h3', { text: i18nHelper.getMessage('1210') });
|
||||
// containerEl.createDiv('login-setting', (loginSettingEl) => {
|
||||
// constructDoubanTokenSettingsUI(loginSettingEl, manager);
|
||||
// });
|
||||
containerEl.createDiv('login-setting', async (loginSettingEl) => {
|
||||
constructDoubanTokenSettingsUI(loginSettingEl, manager);
|
||||
});
|
||||
|
||||
new Setting(containerEl).setName(i18nHelper.getMessage('120501')).then((setting) => {
|
||||
setting.addMomentFormat((mf) => {
|
||||
@ -97,16 +97,16 @@ export function constructBasicUI(containerEl: HTMLElement, manager: SettingsMana
|
||||
}
|
||||
|
||||
export function constructDoubanTokenSettingsUI(containerEl: HTMLElement, manager: SettingsManager) {
|
||||
let cookie = manager.getSetting('loginCookiesContent');
|
||||
containerEl.empty();
|
||||
let login = manager.plugin.userComponent.isLogin();
|
||||
if (Platform.isDesktopApp) {
|
||||
if(cookie) {
|
||||
if(login) {
|
||||
constructHasLoginSettingsUI(containerEl, manager);
|
||||
}else {
|
||||
constructLoginSettingsUI(containerEl, manager);
|
||||
}
|
||||
} else {
|
||||
if(cookie) {
|
||||
if(login) {
|
||||
showMobileLogout(containerEl, manager);
|
||||
}else {
|
||||
showMobileLogin(containerEl, manager);
|
||||
@ -131,9 +131,16 @@ export function constructLoginSettingsUI(containerEl: HTMLElement, manager: Sett
|
||||
}
|
||||
|
||||
export function constructHasLoginSettingsUI(containerEl: HTMLElement, manager: SettingsManager) {
|
||||
const user: User = manager.plugin.userComponent.getUser();
|
||||
let userDom = new DocumentFragment();
|
||||
userDom.createDiv().innerHTML =
|
||||
`已登录<br>
|
||||
豆瓣ID: <a href="https://www.douban.com/people/${user.id}/">${user.id}</a><br>
|
||||
昵称: ${user.name}`;
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('豆瓣用户信息')
|
||||
.setDesc('已登录')
|
||||
.setDesc(userDom)
|
||||
.addButton((button) => {
|
||||
return button
|
||||
.setButtonText('登出')
|
||||
@ -142,6 +149,7 @@ export function constructHasLoginSettingsUI(containerEl: HTMLElement, manager: S
|
||||
button.setDisabled(true);
|
||||
const loginModel = new DoubanLogoutModel(containerEl, manager);
|
||||
await loginModel.doLogout();
|
||||
button.setDisabled(false);
|
||||
// manager.updateSetting('loginCookiesContent', '');
|
||||
});
|
||||
});
|
||||
|
||||
@ -22,7 +22,7 @@ export class DoubanSettingTab extends PluginSettingTab {
|
||||
constructor(app: App, plugin: DoubanPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
this.settingsManager = new SettingsManager(app, plugin);
|
||||
this.settingsManager = plugin.settingsManager;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
|
||||
@ -236,6 +236,17 @@ ${i18nHelper.getMessage('122004')}
|
||||
<td>${i18nHelper.getMessage('310617')}</th>
|
||||
<td>${i18nHelper.getMessage('310717')}</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>${i18nHelper.getMessage('320108')}</th>
|
||||
<td>${i18nHelper.getMessage('310118')}</th>
|
||||
<td>${i18nHelper.getMessage('310218')}</th>
|
||||
<td>${i18nHelper.getMessage('310318')}</th>
|
||||
<td>${i18nHelper.getMessage('310418')}</th>
|
||||
<td>${i18nHelper.getMessage('310518')}</th>
|
||||
<td>${i18nHelper.getMessage('310618')}</th>
|
||||
<td>${i18nHelper.getMessage('310718')}</th>
|
||||
</tr>
|
||||
</table>`;
|
||||
|
||||
|
||||
|
||||
11
src/douban/user/User.ts
Normal file
11
src/douban/user/User.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export default class User {
|
||||
uid?: string
|
||||
name?: string;
|
||||
avatar?: string;
|
||||
alt?: string;
|
||||
id?: string;
|
||||
type?: string;
|
||||
url?: string;
|
||||
imageUrl?: string;
|
||||
login: boolean;
|
||||
}
|
||||
109
src/douban/user/UserComponent.ts
Normal file
109
src/douban/user/UserComponent.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import SettingsManager from "@App/setting/SettingsManager";
|
||||
import {DoubanPluginSetting} from "@App/setting/model/DoubanPluginSetting";
|
||||
import DoubanSearchResultSubject from "@App/data/model/DoubanSearchResultSubject";
|
||||
import {request, RequestUrlParam} from "obsidian";
|
||||
import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings";
|
||||
import {CheerioAPI, load} from "cheerio";
|
||||
import SearchParserHandler from "@App/data/search/SearchParser";
|
||||
import {log} from "../../utils/Logutil";
|
||||
import {i18nHelper} from "../../lang/helper";
|
||||
import User from "@App/user/User";
|
||||
import DoubanGameSubject from "@App/data/model/DoubanGameSubject";
|
||||
|
||||
export default class UserComponent {
|
||||
private settingsManager: SettingsManager;
|
||||
private user: User;
|
||||
|
||||
constructor(settingsManager: SettingsManager) {
|
||||
this.settingsManager = settingsManager;
|
||||
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.user;
|
||||
}
|
||||
|
||||
|
||||
isLogin() {
|
||||
return this.user && this.user.login;
|
||||
}
|
||||
|
||||
logout() {
|
||||
if (this.user) {
|
||||
this.user.login = false;
|
||||
}
|
||||
this.user = null;
|
||||
this.settingsManager.updateSetting('loginCookiesContent', '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
needLogin() {
|
||||
const cookie:any = this.settingsManager.getSetting('loginCookiesContent') ;
|
||||
if(!cookie) {
|
||||
return false;
|
||||
}
|
||||
return !this.isLogin();
|
||||
}
|
||||
|
||||
async loginByCookie():Promise<User> {
|
||||
let cookie = this.settingsManager.getSetting('loginCookiesContent');
|
||||
if(!cookie) {
|
||||
return new User();
|
||||
}
|
||||
await this.loadUserInfo(cookie).then(user => {
|
||||
this.user = user;
|
||||
});
|
||||
return this.user;
|
||||
}
|
||||
|
||||
async loginCookie(cookie: any):Promise<User> {
|
||||
if(!cookie) {
|
||||
return new User();
|
||||
}
|
||||
await this.loadUserInfo(cookie).then(user => {
|
||||
this.user = user;
|
||||
});
|
||||
this.settingsManager.updateSetting('loginCookiesContent', cookie);
|
||||
return this.user;
|
||||
}
|
||||
|
||||
async loadUserInfo(cookie: any): Promise<User> {
|
||||
let requestUrlParam: RequestUrlParam = {
|
||||
url: 'https://www.douban.com/mine/',
|
||||
method: "GET",
|
||||
headers: {'Cookie': cookie},
|
||||
throw: true
|
||||
};
|
||||
return request(requestUrlParam)
|
||||
.then(load)
|
||||
.then(this.getUserInfo)
|
||||
.catch(e => log.error(i18nHelper.getMessage('130101')))
|
||||
;
|
||||
};
|
||||
|
||||
|
||||
private getUserInfo(dataHtml: CheerioAPI): User {
|
||||
let elements = dataHtml("#db-usr-profile > div.pic > a");
|
||||
if (!elements) {
|
||||
return new User();
|
||||
}
|
||||
let name = dataHtml(dataHtml("head > title").get(0)).text().trim();
|
||||
let userUrl = dataHtml(elements.get(0)).attr("href");
|
||||
let idPattern = /(\d){5,10}/g;
|
||||
let idP = idPattern.exec(userUrl);
|
||||
let id = idP ? idP[0] : "";
|
||||
if (!id) {
|
||||
return new User();
|
||||
}
|
||||
const result: User = {
|
||||
id: id,
|
||||
name: name,
|
||||
url: userUrl,
|
||||
login: true
|
||||
}
|
||||
return result;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -215,6 +215,7 @@ export default {
|
||||
'310215': `-`,
|
||||
'310216': `-`,
|
||||
'310217': `-`,
|
||||
'310218': `-`,
|
||||
|
||||
|
||||
//电视剧
|
||||
@ -235,6 +236,7 @@ export default {
|
||||
'310315': `-`,
|
||||
'310316': `-`,
|
||||
'310317': `-`,
|
||||
'310318': `-`,
|
||||
|
||||
|
||||
|
||||
@ -256,6 +258,7 @@ export default {
|
||||
'310415': `barcode:条形码`,
|
||||
'310416': `-`,
|
||||
'310417': `-`,
|
||||
'310418': `-`,
|
||||
|
||||
//日记
|
||||
'310501': `豆瓣ID`,
|
||||
@ -275,6 +278,7 @@ export default {
|
||||
'310515': `-`,
|
||||
'310516': `-`,
|
||||
'310517': `-`,
|
||||
'310518': `-`,
|
||||
|
||||
//游戏
|
||||
'310601': `豆瓣ID`,
|
||||
@ -294,6 +298,7 @@ export default {
|
||||
'310615': `-`,
|
||||
'310616': `-`,
|
||||
'310617': `-`,
|
||||
'310618': `-`,
|
||||
|
||||
//广播
|
||||
'310701': `待开发`,
|
||||
@ -313,6 +318,7 @@ export default {
|
||||
'310715': `-`,
|
||||
'310716': `-`,
|
||||
'310717': `-`,
|
||||
'310718': `-`,
|
||||
|
||||
'320101': `扩展1`,
|
||||
'320102': `扩展2`,
|
||||
@ -324,6 +330,7 @@ export default {
|
||||
'320108': `扩展8`,
|
||||
'320109': `扩展9`,
|
||||
'320110': `扩展10`,
|
||||
'320111': `扩展11`,
|
||||
|
||||
'330101': `今日日期`,
|
||||
'330102': `当前时间`,
|
||||
|
||||
@ -212,6 +212,7 @@ export default {
|
||||
'310115': `subTitle:副标题`,
|
||||
'310116': `totalPage:页数`,
|
||||
'310117': `binding:装帧`,
|
||||
'310118': `producer:出品方`,
|
||||
|
||||
//电影
|
||||
'310201': `豆瓣ID`,
|
||||
@ -231,6 +232,7 @@ export default {
|
||||
'310215': `-`,
|
||||
'310216': `-`,
|
||||
'310217': `-`,
|
||||
'310218': `-`,
|
||||
|
||||
|
||||
//电视剧
|
||||
@ -251,6 +253,7 @@ export default {
|
||||
'310315': `-`,
|
||||
'310316': `-`,
|
||||
'310317': `-`,
|
||||
'310318': `-`,
|
||||
|
||||
|
||||
|
||||
@ -272,6 +275,7 @@ export default {
|
||||
'310415': `barcode:条形码`,
|
||||
'310416': `-`,
|
||||
'310417': `-`,
|
||||
'310418': `-`,
|
||||
|
||||
//日记
|
||||
'310501': `豆瓣ID`,
|
||||
@ -291,6 +295,7 @@ export default {
|
||||
'310515': `-`,
|
||||
'310516': `-`,
|
||||
'310517': `-`,
|
||||
'310518': `-`,
|
||||
|
||||
//游戏
|
||||
'310601': `豆瓣ID`,
|
||||
@ -310,6 +315,7 @@ export default {
|
||||
'310615': `-`,
|
||||
'310616': `-`,
|
||||
'310617': `-`,
|
||||
'310618': `-`,
|
||||
|
||||
//广播
|
||||
'310701': `待开发`,
|
||||
@ -329,6 +335,7 @@ export default {
|
||||
'310715': `-`,
|
||||
'310716': `-`,
|
||||
'310717': `-`,
|
||||
'310718': `-`,
|
||||
|
||||
'320101': `扩展1`,
|
||||
'320102': `扩展2`,
|
||||
@ -340,6 +347,7 @@ export default {
|
||||
'320108': `扩展8`,
|
||||
'320109': `扩展9`,
|
||||
'320110': `扩展10`,
|
||||
'320111': `扩展11`,
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user