mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-05 01:28:46 +08:00
add book search
This commit is contained in:
parent
382d79ec73
commit
ee2dead393
@ -24,9 +24,10 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
|
|||||||
abstract support(extract: DoubanSubject): boolean;
|
abstract support(extract: DoubanSubject): boolean;
|
||||||
|
|
||||||
handle(url:string, editor:Editor):void {
|
handle(url:string, editor:Editor):void {
|
||||||
Promise.resolve().then(() => get(url + "/", {headers: JSON.parse(this.doubanPlugin.settings.searchHeaders)}))
|
Promise.resolve().then(() => get(log.traceN("GET URL", url + "/"), log.traceN("GET HEAD", {headers: JSON.parse(this.doubanPlugin.settings.searchHeaders)})))
|
||||||
.then(readStream)
|
.then(readStream)
|
||||||
.then(cheerio.load)
|
.then(cheerio.load)
|
||||||
|
.then(log.trace)
|
||||||
.then(this.parseSubjectFromHtml)
|
.then(this.parseSubjectFromHtml)
|
||||||
.then(content => this.toEditor(editor, content))
|
.then(content => this.toEditor(editor, content))
|
||||||
// .then(content => content ? editor.replaceSelection(content) : content)
|
// .then(content => content ? editor.replaceSelection(content) : content)
|
||||||
|
|||||||
68
douban/handler/DoubanBookLoadHandler.ts
Normal file
68
douban/handler/DoubanBookLoadHandler.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { Editor, moment, renderResults } from "obsidian";
|
||||||
|
import cheerio, { CheerioAPI } from 'cheerio';
|
||||||
|
import { get, readStream } from "tiny-network";
|
||||||
|
|
||||||
|
import DoubanAbstractLoadHandler from "./DoubanAbstractLoadHandler";
|
||||||
|
import DoubanBookSubject from "douban/model/DoubanBookSubject";
|
||||||
|
import DoubanPlugin from "main";
|
||||||
|
import { DoubanPluginSettings } from "douban/Douban";
|
||||||
|
import DoubanSubject from "douban/model/DoubanSubject";
|
||||||
|
import SchemaOrg from "utils/SchemaOrg";
|
||||||
|
import { log } from "utils/Logutil";
|
||||||
|
|
||||||
|
export default class DoubanBookLoadHandler extends DoubanAbstractLoadHandler<DoubanBookSubject> {
|
||||||
|
|
||||||
|
parseText(extract: DoubanBookSubject, settings:DoubanPluginSettings): string {
|
||||||
|
return settings.movieTemplate ? settings.movieTemplate.replaceAll("{{id}}", extract.id)
|
||||||
|
.replaceAll("{{type}}", extract.type ? extract.type : "")
|
||||||
|
.replaceAll("{{title}}", extract.title ? extract.title : "")
|
||||||
|
.replaceAll("{{desc}}", extract.desc ? extract.desc : "")
|
||||||
|
.replaceAll("{{image}}", extract.image ? extract.image : "")
|
||||||
|
// .replaceAll("{{director}}", extract.director ? extract.director.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
|
||||||
|
// .replaceAll("{{actor}}", extract.actor ? extract.actor.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
|
||||||
|
.replaceAll("{{author}}", extract.author ? extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
|
||||||
|
.replaceAll("{{datePublished}}", extract.datePublished ? moment(extract.datePublished).format(settings.dateFormat) : "")
|
||||||
|
.replaceAll("{{url}}", extract.url ? extract.url : "")
|
||||||
|
.replaceAll("{{score}}", extract.aggregateRating && extract.aggregateRating.ratingValue ? extract.aggregateRating.ratingValue + "" : "")
|
||||||
|
: undefined; }
|
||||||
|
support(extract: DoubanSubject): boolean {
|
||||||
|
return extract && extract.type && (extract.type.contains("书籍") || extract.type.contains("Book") || extract.type.contains("book"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(doubanPlugin:DoubanPlugin) {
|
||||||
|
super(doubanPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseSubjectFromHtml(data: CheerioAPI): DoubanBookSubject {
|
||||||
|
return data('script')
|
||||||
|
.get()
|
||||||
|
.filter(scd => "application/ld+json" == data(scd).attr("type"))
|
||||||
|
.map(i => {
|
||||||
|
var item = data(i).text();
|
||||||
|
item = super.html_decode(item);
|
||||||
|
var obj = JSON.parse(item.replace(/[\r\n\s+]/g, ''));
|
||||||
|
var idPattern = /(\d){5,10}/g;
|
||||||
|
var id = idPattern.exec(obj.url);
|
||||||
|
const result:DoubanBookSubject = {
|
||||||
|
id: id?id[0]:'',
|
||||||
|
type: 'Book',
|
||||||
|
title: obj.name,
|
||||||
|
desc: obj.description,
|
||||||
|
url: "https://book.douban.com" + obj.url,
|
||||||
|
author: obj.author,
|
||||||
|
aggregateRating: obj.aggregateRating,
|
||||||
|
datePublished: obj.datePublished ? new Date(obj.datePublished) : undefined,
|
||||||
|
image:obj.image
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ import { DoubanPluginSettings } from "douban/Douban";
|
|||||||
import DoubanSubject from "../model/DoubanSubject";
|
import DoubanSubject from "../model/DoubanSubject";
|
||||||
import DoubanSubjectLoadHandler from "./DoubanSubjectLoadHandler";
|
import DoubanSubjectLoadHandler from "./DoubanSubjectLoadHandler";
|
||||||
|
|
||||||
export class DoubanEtractHandler {
|
export class DoubanSearchChooseItemHandler {
|
||||||
|
|
||||||
private _app:App;
|
private _app:App;
|
||||||
private _doubanPlugin:DoubanPlugin;
|
private _doubanPlugin:DoubanPlugin;
|
||||||
@ -32,10 +32,7 @@ export class DoubanEtractHandler {
|
|||||||
var doubanSubjectHandlers:DoubanSubjectLoadHandler<DoubanSubject>[] = this._doubanSubjectHandlers
|
var doubanSubjectHandlers:DoubanSubjectLoadHandler<DoubanSubject>[] = this._doubanSubjectHandlers
|
||||||
.filter(h => h.support(searchExtract));
|
.filter(h => h.support(searchExtract));
|
||||||
if(doubanSubjectHandlers && doubanSubjectHandlers.length > 0) {
|
if(doubanSubjectHandlers && doubanSubjectHandlers.length > 0) {
|
||||||
var result = doubanSubjectHandlers.map(h => h.handle(searchExtract.url, editor))
|
doubanSubjectHandlers[0].handle(searchExtract.url, editor);
|
||||||
if(result && result.length > 0) {
|
|
||||||
return result[0];
|
|
||||||
}
|
|
||||||
}else {
|
}else {
|
||||||
this._doubanSubjectHandlerDefault.handle(searchExtract.url, editor);
|
this._doubanSubjectHandlerDefault.handle(searchExtract.url, editor);
|
||||||
}
|
}
|
||||||
10
douban/model/DoubanBookSubject.ts
Normal file
10
douban/model/DoubanBookSubject.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import {AggregateRating, Person, WithContext} from 'schema-dts';
|
||||||
|
|
||||||
|
import DoubanSubject from "./DoubanSubject";
|
||||||
|
|
||||||
|
export default class DoubanMovieSubject extends DoubanSubject {
|
||||||
|
author:Person[];
|
||||||
|
aggregateRating:AggregateRating;
|
||||||
|
datePublished:Date;
|
||||||
|
image:string
|
||||||
|
}
|
||||||
@ -33,6 +33,7 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
|||||||
}
|
}
|
||||||
|
|
||||||
onChooseItem(item: DoubanSearchResultSubject, evt: MouseEvent | KeyboardEvent): void {
|
onChooseItem(item: DoubanSearchResultSubject, evt: MouseEvent | KeyboardEvent): void {
|
||||||
|
log.trace(`you chosen : ${JSON.stringify(item)}`)
|
||||||
this.plugin.doubanEtractHandler.handle(item, this.editor);
|
this.plugin.doubanEtractHandler.handle(item, this.editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export default class Searcher {
|
|||||||
// return Promise.resolve();
|
// return Promise.resolve();
|
||||||
return Promise
|
return Promise
|
||||||
.resolve()
|
.resolve()
|
||||||
.then(() => get(doubanSettings.searchUrl + searchItem, JSON.parse(doubanSettings.searchHeaders)))
|
.then(() => get(log.traceN("GET", doubanSettings.searchUrl + searchItem), JSON.parse(doubanSettings.searchHeaders)))
|
||||||
.then(ensureStatusCode(200))
|
.then(ensureStatusCode(200))
|
||||||
.then(readStream)
|
.then(readStream)
|
||||||
.then(cheerio.load)
|
.then(cheerio.load)
|
||||||
|
|||||||
16
main.ts
16
main.ts
@ -1,9 +1,9 @@
|
|||||||
import { DEFAULT_SETTINGS, DoubanPluginSettings } from "./douban/Douban";
|
import { DEFAULT_SETTINGS, DoubanPluginSettings } from "./douban/Douban";
|
||||||
import { Editor, Plugin } from "obsidian";
|
import { Editor, Plugin } from "obsidian";
|
||||||
|
|
||||||
import { DoubanEtractHandler } from "douban/handler/DoubanExtractHandler";
|
|
||||||
import { DoubanFuzzySuggester } from "douban/search/DoubanSearchFuzzySuggestModal";
|
import { DoubanFuzzySuggester } from "douban/search/DoubanSearchFuzzySuggestModal";
|
||||||
import DoubanMovieSubject from "douban/model/DoubanMovieSubject";
|
import DoubanMovieSubject from "douban/model/DoubanMovieSubject";
|
||||||
|
import { DoubanSearchChooseItemHandler } from "douban/handler/DoubanSearchChooseItemHandler";
|
||||||
import { DoubanSearchModal } from "douban/search/DoubanSearchModal";
|
import { DoubanSearchModal } from "douban/search/DoubanSearchModal";
|
||||||
import { DoubanSettingTab } from "douban/DoubanSettingTab";
|
import { DoubanSettingTab } from "douban/DoubanSettingTab";
|
||||||
import DoubanSubject from "douban/model/DoubanSubject";
|
import DoubanSubject from "douban/model/DoubanSubject";
|
||||||
@ -13,12 +13,14 @@ import { log } from "utils/Logutil";
|
|||||||
|
|
||||||
export default class DoubanPlugin extends Plugin {
|
export default class DoubanPlugin extends Plugin {
|
||||||
public settings: DoubanPluginSettings;
|
public settings: DoubanPluginSettings;
|
||||||
public doubanEtractHandler: DoubanEtractHandler;
|
public doubanEtractHandler: DoubanSearchChooseItemHandler;
|
||||||
|
|
||||||
async putToEditor(editor:Editor, extract:DoubanSubject) {
|
async putToEditor(editor:Editor, extract:DoubanSubject) {
|
||||||
if(!editor || !extract) {
|
if(!editor || !extract) {
|
||||||
|
log.trace(`chosen item can not load data`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
log.trace(`you choose item load data success: ${JSON.stringify(extract)}`);
|
||||||
var content:string = this.doubanEtractHandler.parseText(extract, this.settings)
|
var content:string = this.doubanEtractHandler.parseText(extract, this.settings)
|
||||||
if(content) {
|
if(content) {
|
||||||
editor.replaceSelection(content);
|
editor.replaceSelection(content);
|
||||||
@ -33,7 +35,7 @@ export default class DoubanPlugin extends Plugin {
|
|||||||
new DoubanFuzzySuggester(this, editor).showSearchList(resultList);
|
new DoubanFuzzySuggester(this, editor).showSearchList(resultList);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDoubanMovieTextForActiveFile(editor: Editor) {
|
async getDoubanTextForActiveFile(editor: Editor) {
|
||||||
const activeFile = await this.app.workspace.getActiveFile();
|
const activeFile = await this.app.workspace.getActiveFile();
|
||||||
if (activeFile) {
|
if (activeFile) {
|
||||||
const searchTerm = activeFile.basename;
|
const searchTerm = activeFile.basename;
|
||||||
@ -43,7 +45,7 @@ export default class DoubanPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async geDoubanMovieTextForSearchTerm(editor: Editor) {
|
async geDoubanTextForSearchTerm(editor: Editor) {
|
||||||
new DoubanSearchModal(this.app, this, editor).open();
|
new DoubanSearchModal(this.app, this, editor).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ export default class DoubanPlugin extends Plugin {
|
|||||||
id: "search-douban-by-current-file-name",
|
id: "search-douban-by-current-file-name",
|
||||||
name: i18nHelper.getMessage("search douban by current file name"),
|
name: i18nHelper.getMessage("search douban by current file name"),
|
||||||
editorCallback: (editor: Editor) =>
|
editorCallback: (editor: Editor) =>
|
||||||
this.getDoubanMovieTextForActiveFile(editor),
|
this.getDoubanTextForActiveFile(editor),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ export default class DoubanPlugin extends Plugin {
|
|||||||
id: "search-douban-and-input-current-file",
|
id: "search-douban-and-input-current-file",
|
||||||
name: i18nHelper.getMessage("search douban and import to current file"),
|
name: i18nHelper.getMessage("search douban and import to current file"),
|
||||||
editorCallback: (editor: Editor) =>
|
editorCallback: (editor: Editor) =>
|
||||||
this.geDoubanMovieTextForSearchTerm(editor),
|
this.geDoubanTextForSearchTerm(editor),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addSettingTab(new DoubanSettingTab(this.app, this));
|
this.addSettingTab(new DoubanSettingTab(this.app, this));
|
||||||
@ -70,7 +72,7 @@ export default class DoubanPlugin extends Plugin {
|
|||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||||
this.doubanEtractHandler = new DoubanEtractHandler(this.app, this);
|
this.doubanEtractHandler = new DoubanSearchChooseItemHandler(this.app, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSettings() {
|
async saveSettings() {
|
||||||
|
|||||||
@ -19,9 +19,15 @@ class Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public trace(e:any):any {
|
public trace(e:any):any {
|
||||||
return e;
|
|
||||||
// console.log(`Douban Plugin trace: ${typeof e == 'string' ? e : JSON.stringify(e)}`);
|
|
||||||
// return e;
|
// return e;
|
||||||
|
console.log(`Douban Plugin trace: ${typeof e == 'string' ? e : JSON.stringify(e)}`);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public traceN(notion:string, e:any):any {
|
||||||
|
// return e;
|
||||||
|
console.log(`${notion} ${typeof e == 'string' ? e : JSON.stringify(e)}`);
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user