From 1f30482542341af176af556bc09a581770eb0f8a Mon Sep 17 00:00:00 2001 From: wanxp <977741432@qq.com> Date: Mon, 7 Nov 2022 23:08:26 +0800 Subject: [PATCH] add douban login --- README.md | 41 +++---- main.ts | 10 ++ src/constant/DefaultTemplateContent.ts | 1 + src/douban/ResponseHandle.ts | 13 --- src/douban/component/DoubanLoginModel.ts | 6 +- src/douban/component/DoubanLogoutModel.ts | 9 +- src/douban/setting/BasicSettingsHelper.ts | 24 ++-- src/douban/setting/DoubanSettingTab.ts | 2 +- .../setting/TemplateVariableSettingsHelper.ts | 11 ++ src/douban/user/User.ts | 11 ++ src/douban/user/UserComponent.ts | 109 ++++++++++++++++++ src/lang/locale/en.ts | 7 ++ src/lang/locale/zh-cn.ts | 8 ++ 13 files changed, 202 insertions(+), 50 deletions(-) delete mode 100644 src/douban/ResponseHandle.ts create mode 100644 src/douban/user/User.ts create mode 100644 src/douban/user/UserComponent.ts diff --git a/README.md b/README.md index ac5ff37..88d4c66 100644 --- a/README.md +++ b/README.md @@ -34,30 +34,31 @@ If you want some features or have any questions about this plugin, create issues (若有缺少想导入的字段, 欢迎提issues反馈) --- -| 字段 | 电影 | 电视剧 | 书籍 | 音乐 | 日记 | 游戏 | 广播 | -| ------------- | -------------------- | -------------------- | -------------------- | ------------------ | ------------------ | ---------------- | ---- | -| id | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | - | -| title | 电影名称 | 电视剧名称 | 书名 | 音乐名 | 日记标题 | 游戏名称 | - | -| type | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | - | -| score | 评分 | 评分 | 评分 | 评分 | 评分 | 评分 | - | -| image | 封面 | 封面 | 封面 | 封面 | 图片 | 封面 | - | -| url | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | - | -| desc | 简介 | 简介 | 内容简介 | 简介 | 简介 | 简介 | - | -| publisher | - | - | 出版社 | 出版者 | 发布者 | 发行商 | - | +| 字段 | 电影 | 电视剧 | 书籍 | 音乐 | 日记 | 游戏 | 广播 | +| ----------- | -------------------- | -------------------- |-------------------| ------------------ | ------------------ | ---------------- | ---- | +| id | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | - | +| title | 电影名称 | 电视剧名称 | 书名 | 音乐名 | 日记标题 | 游戏名称 | - | +| type | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | - | +| score | 评分 | 评分 | 评分 | 评分 | 评分 | 评分 | - | +| image | 封面 | 封面 | 封面 | 封面 | 图片 | 封面 | - | +| url | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | - | +| desc | 简介 | 简介 | 内容简介 | 简介 | 简介 | 简介 | - | +| publisher | - | - | 出版社 | 出版者 | 发布者 | 发行商 | - | | datePublished | 上映日期 | 上映日期 | 出版年 | 发行时间 | 发布时间 | 发行日期 | - | -| genre | 类型 | 类型 | - | 流派 | - | 类型 | - | -| currentDate | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | | -| currentTime | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | | +| genre | 类型 | 类型 | - | 流派 | - | 类型 | - | +| currentDate | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | | +| currentTime | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | | | 扩展1 | director:导演 | director:导演 | author:原作者 | actor: 表演者 | author:作者 | aliases:别名 | | -| 扩展2 | author:编剧 | author:编剧 | translator:译者 | albumType:专辑类型 | authorUrl:作者网址 | developer:开发商 | | -| 扩展3 | actor:主演 | actor:主演 | isbn:isbn | medium:介质 | content:日记内容 | platform:平台 | | +| 扩展2 | author:编剧 | author:编剧 | translator:译者 | albumType:专辑类型 | authorUrl:作者网址 | developer:开发商 | | +| 扩展3 | actor:主演 | actor:主演 | isbn:isbn | medium:介质 | content:日记内容 | platform:平台 | | | 扩展4 | originalTitle:原作名 | originalTitle:原作名 | originalTitle:原作名 | records:唱片数 | | | | | 扩展5 | | | subTitle:副标题 | barcode:条形码 | | | | -| 扩展6 | | | totalPage:页数 | | | | | -| 扩展7 | | | series:丛书 | | | | | -| 扩展8 | | | menu:目录 | | | | | -| 扩展9 | | | price:定价 | | | | | -| 扩展7 | | | binding:装帧 | | | | | +| 扩展6 | | | totalPage:页数 | | | | | +| 扩展7 | | | series:丛书 | | | | | +| 扩展8 | | | menu:目录 | | | | | +| 扩展9 | | | price:定价 | | | | | +| 扩展7 | | | binding:装帧 | | | | | +| 扩展8 | | | producer: 出品方 | | | | | ## How to use ### Search diff --git a/main.ts b/main.ts index ae1b7a5..d01cad7 100644 --- a/main.ts +++ b/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)); } diff --git a/src/constant/DefaultTemplateContent.ts b/src/constant/DefaultTemplateContent.ts index 0c91fc0..ffba33f 100644 --- a/src/constant/DefaultTemplateContent.ts +++ b/src/constant/DefaultTemplateContent.ts @@ -32,6 +32,7 @@ score: {{score}} datePublished: {{datePublished}} translator: {{translator}} publisher: {{publisher}} +producer: {{producer}} isbn: {{isbn}} url: {{url}} totalPage: {{totalPage}} diff --git a/src/douban/ResponseHandle.ts b/src/douban/ResponseHandle.ts deleted file mode 100644 index 5963d3c..0000000 --- a/src/douban/ResponseHandle.ts +++ /dev/null @@ -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; - }; -}; diff --git a/src/douban/component/DoubanLoginModel.ts b/src/douban/component/DoubanLoginModel.ts index c35d1c1..9e44cb4 100644 --- a/src/douban/component/DoubanLoginModel.ts +++ b/src/douban/component/DoubanLoginModel.ts @@ -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 { diff --git a/src/douban/component/DoubanLogoutModel.ts b/src/douban/component/DoubanLogoutModel.ts index 5da6c04..63efde0 100644 --- a/src/douban/component/DoubanLogoutModel.ts +++ b/src/douban/component/DoubanLogoutModel.ts @@ -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() { diff --git a/src/douban/setting/BasicSettingsHelper.ts b/src/douban/setting/BasicSettingsHelper.ts index e81eed3..d4b6e17 100644 --- a/src/douban/setting/BasicSettingsHelper.ts +++ b/src/douban/setting/BasicSettingsHelper.ts @@ -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 = + `已登录
+豆瓣ID: ${user.id}
+ 昵称: ${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', ''); }); }); diff --git a/src/douban/setting/DoubanSettingTab.ts b/src/douban/setting/DoubanSettingTab.ts index 4f570a1..f8ad2e4 100644 --- a/src/douban/setting/DoubanSettingTab.ts +++ b/src/douban/setting/DoubanSettingTab.ts @@ -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 { diff --git a/src/douban/setting/TemplateVariableSettingsHelper.ts b/src/douban/setting/TemplateVariableSettingsHelper.ts index 4160350..bf5922e 100644 --- a/src/douban/setting/TemplateVariableSettingsHelper.ts +++ b/src/douban/setting/TemplateVariableSettingsHelper.ts @@ -236,6 +236,17 @@ ${i18nHelper.getMessage('122004')} ${i18nHelper.getMessage('310617')} ${i18nHelper.getMessage('310717')} + + + ${i18nHelper.getMessage('320108')} + ${i18nHelper.getMessage('310118')} + ${i18nHelper.getMessage('310218')} + ${i18nHelper.getMessage('310318')} + ${i18nHelper.getMessage('310418')} + ${i18nHelper.getMessage('310518')} + ${i18nHelper.getMessage('310618')} + ${i18nHelper.getMessage('310718')} + `; diff --git a/src/douban/user/User.ts b/src/douban/user/User.ts new file mode 100644 index 0000000..265e26d --- /dev/null +++ b/src/douban/user/User.ts @@ -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; +} diff --git a/src/douban/user/UserComponent.ts b/src/douban/user/UserComponent.ts new file mode 100644 index 0000000..a47b84e --- /dev/null +++ b/src/douban/user/UserComponent.ts @@ -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 { + 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 { + 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 { + 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; + + }; + +} diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 3ba77ee..eb788b8 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -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': `当前时间`, diff --git a/src/lang/locale/zh-cn.ts b/src/lang/locale/zh-cn.ts index 6b516d7..37e26ee 100644 --- a/src/lang/locale/zh-cn.ts +++ b/src/lang/locale/zh-cn.ts @@ -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`,