mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 00:28:43 +08:00
fix search error
This commit is contained in:
parent
7bd4b6b96f
commit
96fe6d6771
@ -35,7 +35,7 @@ esbuild.build({
|
||||
'@codemirror/panel',
|
||||
'@codemirror/rangeset',
|
||||
'@codemirror/rectangular-selection',
|
||||
'@codemirror/search',
|
||||
'@codemirror/searcher',
|
||||
'@codemirror/state',
|
||||
'@codemirror/stream-parser',
|
||||
'@codemirror/text',
|
||||
|
||||
34
package-lock.json
generated
34
package-lock.json
generated
@ -1,18 +1,19 @@
|
||||
{
|
||||
"name": "obsidian-douban-plugin",
|
||||
"version": "1.9.3",
|
||||
"version": "1.9.6",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-douban-plugin",
|
||||
"version": "1.9.3",
|
||||
"version": "1.9.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@notable/html2markdown": "^1.1.3",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"cheerio": "^1.0.0-rc.11",
|
||||
"follow-redirects": "^1.15.3",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"schema-dts": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -3290,6 +3291,17 @@
|
||||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
@ -4872,6 +4884,11 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/schema-dts": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.0.tgz",
|
||||
@ -7844,6 +7861,14 @@
|
||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
|
||||
"dev": true
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
@ -9020,6 +9045,11 @@
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"schema-dts": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.0.tgz",
|
||||
|
||||
@ -54,6 +54,7 @@ export const ESTIMATE_TIME_PER_WITH_REQUEST_SLOW: number = ESTIMATE_TIME_PER + B
|
||||
*/
|
||||
export const ESTIMATE_TIME_PER_WITH_REQUEST: number = ESTIMATE_TIME_PER + BasicConst.CALL_DOUBAN_DELAY + BasicConst.CALL_DOUBAN_DELAY_RANGE / 2;
|
||||
|
||||
|
||||
/**
|
||||
* 模板类型
|
||||
*/
|
||||
@ -176,6 +177,20 @@ export enum PropertyName {
|
||||
content = "content",
|
||||
}
|
||||
|
||||
/**
|
||||
* 名称模式选项
|
||||
*/
|
||||
export const SearchTypeRecords: { [key in SupportType]: string } = {
|
||||
[SupportType.ALL]: i18nHelper.getMessage('ALL'),
|
||||
[SupportType.MOVIE]: i18nHelper.getMessage('MOVIE_AND_TELEPLAY'),
|
||||
[SupportType.BOOK]: i18nHelper.getMessage('BOOK'),
|
||||
[SupportType.MUSIC]: i18nHelper.getMessage('MUSIC'),
|
||||
[SupportType.NOTE]: i18nHelper.getMessage('NOTE'),
|
||||
[SupportType.GAME]: i18nHelper.getMessage('GAME'),
|
||||
[SupportType.TELEPLAY]: i18nHelper.getMessage('TELEPLAY'),
|
||||
[SupportType.THEATER]: i18nHelper.getMessage('THEATER'),
|
||||
}
|
||||
|
||||
/**
|
||||
* 名称模式选项
|
||||
*/
|
||||
@ -296,7 +311,7 @@ export const DoubanSearchResultSubjectNextPageNeedLogin: DoubanSearchResultSubje
|
||||
url: NavigateType.nextNeedLogin
|
||||
}
|
||||
|
||||
export const SEARCH_ITEM_PAGE_SIZE: number = 20;
|
||||
export const SEARCH_ITEM_PAGE_SIZE: number = 10;
|
||||
|
||||
/**
|
||||
* 豆瓣默认请求头
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
import {SearchPageInfo} from "./SearchPageInfo";
|
||||
import {SupportType} from "../../../constant/Constsant";
|
||||
|
||||
export class SearchPage extends SearchPageInfo{
|
||||
|
||||
private _list:any[];
|
||||
|
||||
|
||||
constructor(total: number, pageNum: number, pageSize: number, list: any[]) {
|
||||
super(total, pageNum, pageSize);
|
||||
constructor(total: number, pageNum: number, pageSize: number, type:SupportType, list: any[]) {
|
||||
super(total, pageNum, pageSize, type);
|
||||
this._list = list;
|
||||
}
|
||||
|
||||
public get list() {
|
||||
return this._list;
|
||||
}
|
||||
|
||||
public static empty(type:SupportType):SearchPage {
|
||||
return new SearchPage(0, 0, 0, type, []);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
import {SupportType} from "../../../constant/Constsant";
|
||||
|
||||
export class SearchPageInfo {
|
||||
private _total: number;
|
||||
private _pageSize: number;
|
||||
private _pageNum: number;
|
||||
|
||||
private _hasNext: boolean;
|
||||
private _type: SupportType;
|
||||
|
||||
constructor(total: number, pageNum: number, pageSize: number) {
|
||||
constructor(total: number, pageNum: number, pageSize: number, type: SupportType) {
|
||||
this._total = total;
|
||||
this._pageNum = pageNum;
|
||||
this._pageSize = pageSize;
|
||||
this._hasNext = ((pageNum + 1) * pageSize) < total;
|
||||
this._type = type;
|
||||
}
|
||||
|
||||
public nextPage(): SearchPageInfo {
|
||||
@ -17,7 +21,7 @@ export class SearchPageInfo {
|
||||
return this;
|
||||
}
|
||||
return new SearchPageInfo(this.total, this._pageNum + 1,
|
||||
this._pageSize);
|
||||
this._pageSize, this._type);
|
||||
}
|
||||
|
||||
public previousPage(): SearchPageInfo {
|
||||
@ -25,7 +29,12 @@ export class SearchPageInfo {
|
||||
return this;
|
||||
}
|
||||
return new SearchPageInfo(this.total, this._pageNum - 1,
|
||||
this._pageSize);
|
||||
this._pageSize, this._type);
|
||||
}
|
||||
|
||||
public typePage(type: SupportType): SearchPageInfo {
|
||||
return new SearchPageInfo(this.total, 0,
|
||||
this._pageSize, this._type);
|
||||
}
|
||||
|
||||
|
||||
@ -53,4 +62,18 @@ export class SearchPageInfo {
|
||||
get pageNum(): number {
|
||||
return this._pageNum;
|
||||
}
|
||||
|
||||
get type(): SupportType {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
allPage() {
|
||||
if (this._pageNum == 0) {
|
||||
return this;
|
||||
}
|
||||
return new SearchPageInfo(this.total, this._pageNum - 1,
|
||||
this._pageSize, SupportType.ALL);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import {
|
||||
DoubanSearchResultSubjectNextPage,
|
||||
DoubanSearchResultSubjectNextPageNeedLogin,
|
||||
DoubanSearchResultSubjectPreviousPage,
|
||||
NavigateType
|
||||
NavigateType, SEARCH_ITEM_PAGE_SIZE, SupportType
|
||||
} from "../../../constant/Constsant";
|
||||
import {FuzzySuggestModal, RequestUrlParam, request} from "obsidian";
|
||||
|
||||
@ -11,13 +11,9 @@ import DoubanSearchResultSubject from "../model/DoubanSearchResultSubject";
|
||||
import HandleContext from "../model/HandleContext";
|
||||
import {SearchPage} from "../model/SearchPage";
|
||||
import {SearchPageInfo} from "../model/SearchPageInfo";
|
||||
import Searcher from "./Search";
|
||||
import User from "../../user/User";
|
||||
import {flat} from "builtin-modules";
|
||||
import {i18nHelper} from "../../../lang/helper";
|
||||
import {init} from "cjs-module-lexer";
|
||||
import {load} from "cheerio";
|
||||
import {log} from "src/org/wanxp/utils/Logutil";
|
||||
import SearcherV2 from "./SearchV2";
|
||||
|
||||
export {DoubanFuzzySuggester}
|
||||
|
||||
@ -61,6 +57,12 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(this.isTypeSelect(item)) {
|
||||
if (await this.handleTypeSelect(item)) {
|
||||
this.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.plugin.showStatus(i18nHelper.getMessage('140204', item.title));
|
||||
this.context.listItem = item;
|
||||
if (item) {
|
||||
@ -87,29 +89,28 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
break;
|
||||
}
|
||||
if (result) {
|
||||
const searchPageResult: SearchPage =
|
||||
await Searcher.loadSearchItem(this.searchItem, currentPage.start, this.plugin.settings, this.plugin.settingsManager);
|
||||
this.context.searchPage = new SearchPageInfo(searchPageResult.total, currentPage.pageNum, searchPageResult.pageSize);
|
||||
this.updatePageResult(searchPageResult);
|
||||
// const searchPageResult: SearchPage =
|
||||
// await SearcherV2.loadSearchItem(this.searchItem, currentPage.start, SEARCH_ITEM_PAGE_SIZE, this.plugin.settings, this.plugin.settingsManager);
|
||||
// this.context.searchPage = new SearchPageInfo(searchPageResult.total, currentPage.pageNum, searchPageResult.pageSize, item.type);
|
||||
// this.updatePageResult(searchPageResult);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private updatePageResult(searchPageResult: SearchPage) {
|
||||
this.initItems(searchPageResult.list);
|
||||
this.initItems(searchPageResult);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public showSearchList(doubanSearchResultExtractList: DoubanSearchResultSubject[]) {
|
||||
this.initItems(doubanSearchResultExtractList);
|
||||
public showSearchPage(searchPage: SearchPage) {
|
||||
this.initItems(searchPage);
|
||||
this.start();
|
||||
}
|
||||
|
||||
private initItems(doubanSearchResultExtractList: DoubanSearchResultSubject[]) {
|
||||
let doubanList: DoubanSearchResultSubject[] = doubanSearchResultExtractList;
|
||||
const {searchPage} = this.context;
|
||||
private initItems(searchPage: SearchPage) {
|
||||
const doubanList: DoubanSearchResultSubject[] = searchPage.list;
|
||||
if (searchPage.hasNext) {
|
||||
if (this.plugin.userComponent.isLogin()) {
|
||||
doubanList.push(DoubanSearchResultSubjectNextPage)
|
||||
@ -117,6 +118,7 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
doubanList.push(DoubanSearchResultSubjectNextPageNeedLogin)
|
||||
}
|
||||
}
|
||||
this.initTypeSelect(doubanList, searchPage);
|
||||
if (searchPage.hasPrevious) {
|
||||
doubanList.unshift(DoubanSearchResultSubjectPreviousPage);
|
||||
}
|
||||
@ -124,6 +126,12 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
|
||||
}
|
||||
|
||||
private initTypeSelect(doubanList: DoubanSearchResultSubject[], searchPage: SearchPage) {
|
||||
if (SupportType.ALL == searchPage.type) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public start(): void {
|
||||
try {
|
||||
this.open();
|
||||
@ -132,4 +140,29 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
}
|
||||
}
|
||||
|
||||
private isTypeSelect(item: DoubanSearchResultSubject) {
|
||||
return item.type == "type";
|
||||
}
|
||||
|
||||
private async handleTypeSelect(item: DoubanSearchResultSubject) {
|
||||
const {searchPage} = this.context;
|
||||
let currentPage:SearchPageInfo = searchPage;
|
||||
let result:boolean = false;
|
||||
switch (item.url) {
|
||||
case SupportType.ALL:
|
||||
currentPage = searchPage.previousPage();
|
||||
result = true;
|
||||
break;
|
||||
case NavigateType.next:
|
||||
currentPage = searchPage.nextPage();
|
||||
result = true;
|
||||
break;
|
||||
case NavigateType.nextNeedLogin:
|
||||
log.warn(i18nHelper.getMessage("140304"));
|
||||
break;
|
||||
}
|
||||
if (result) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import {App, Modal, TextComponent} from "obsidian";
|
||||
import {App, DropdownComponent, Modal, TextComponent} from "obsidian";
|
||||
|
||||
import DoubanPlugin from "../../../main";
|
||||
import {i18nHelper} from "src/org/wanxp/lang/helper";
|
||||
import HandleContext from "../model/HandleContext";
|
||||
import {SearchTypeRecords, SupportType} from "../../../constant/Constsant";
|
||||
|
||||
export class DoubanSearchModal extends Modal {
|
||||
searchTerm: string;
|
||||
searchType: SupportType = SupportType.ALL;
|
||||
plugin: DoubanPlugin;
|
||||
context: HandleContext
|
||||
|
||||
@ -19,14 +21,25 @@ export class DoubanSearchModal extends Modal {
|
||||
let {contentEl} = this;
|
||||
|
||||
contentEl.createEl("h3", {text: i18nHelper.getMessage('110003')});
|
||||
const content = contentEl.createDiv("content");
|
||||
|
||||
const inputs = contentEl.createDiv("inputs");
|
||||
const typeSelect = content.createDiv("type-select");
|
||||
const typeSelectInput = new DropdownComponent(typeSelect)
|
||||
.addOptions(SearchTypeRecords)
|
||||
.setValue(SupportType.ALL)
|
||||
.onChange((value:SupportType) => {
|
||||
this.searchType = value;
|
||||
});
|
||||
typeSelect.addClass('obsidian_douban_search_input');
|
||||
|
||||
|
||||
const inputs = content.createDiv("inputs");
|
||||
const searchInput = new TextComponent(inputs).onChange((searchTerm) => {
|
||||
this.searchTerm = searchTerm;
|
||||
});
|
||||
searchInput.inputEl.addClass("obsidian_douban_search_input");
|
||||
inputs.addClass("obsidian_douban_search_input");
|
||||
searchInput.inputEl.size = 40;
|
||||
|
||||
searchInput.inputEl.focus();
|
||||
searchInput.inputEl.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
this.close();
|
||||
@ -34,6 +47,9 @@ export class DoubanSearchModal extends Modal {
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const controls = contentEl.createDiv("controls");
|
||||
const searchButton = controls.createEl("button", {
|
||||
text: i18nHelper.getMessage('110004'),
|
||||
@ -48,6 +64,7 @@ export class DoubanSearchModal extends Modal {
|
||||
const cancelButton = controls.createEl("button", {text: i18nHelper.getMessage('110005')});
|
||||
cancelButton.addEventListener("click", this.close.bind(this));
|
||||
cancelButton.addClass("obsidian_douban_search_button");
|
||||
searchInput.inputEl.focus();
|
||||
|
||||
}
|
||||
|
||||
@ -56,7 +73,7 @@ export class DoubanSearchModal extends Modal {
|
||||
let {contentEl} = this;
|
||||
contentEl.empty();
|
||||
if (this.searchTerm) {
|
||||
await this.plugin.search(this.searchTerm, this.context);
|
||||
await this.plugin.search(this.searchTerm, this.searchType, this.context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,9 +11,10 @@ import {i18nHelper} from "../../../lang/helper";
|
||||
import {load} from 'cheerio';
|
||||
import {log} from 'src/org/wanxp/utils/Logutil';
|
||||
import HttpUtil from "../../../utils/HttpUtil";
|
||||
import {SupportType} from "../../../constant/Constsant";
|
||||
|
||||
export default class Searcher {
|
||||
static search(searchItem: string, doubanSettings: DoubanPluginSetting, settingsManager:SettingsManager): Promise<DoubanSearchResultSubject[]> {
|
||||
static search(searchItem: string, type:SupportType, doubanSettings: DoubanPluginSetting, settingsManager:SettingsManager): Promise<DoubanSearchResultSubject[]> {
|
||||
return HttpUtil.httpRequestGet(DEFAULT_SETTINGS.searchUrl + searchItem, settingsManager.getHeaders(), settingsManager)
|
||||
.then(load)
|
||||
.then(SearchParserHandler.parseSearch)
|
||||
@ -23,11 +24,11 @@ export default class Searcher {
|
||||
|
||||
};
|
||||
|
||||
static loadSearchItem(searchItem: string, start:number, doubanSettings: DoubanPluginSetting, settingsManager:SettingsManager): Promise<SearchPage> {
|
||||
static loadSearchItem(searchItem: string, type:SupportType, start:number, doubanSettings: DoubanPluginSetting, settingsManager:SettingsManager): Promise<SearchPage> {
|
||||
const url:string = `https://www.douban.com/j/search?q=${searchItem}&start=${start}&subtype=item`;
|
||||
log.debug(`请求更多页面:${url}`);
|
||||
return HttpUtil.httpRequestGet(url, settingsManager.getHeaders(), settingsManager)
|
||||
.then(e=>SearchParserHandler.parseSearchJson(e, start))
|
||||
.then(e=>SearchParserHandler.parseSearchJson(e, type, start))
|
||||
.catch(e => {
|
||||
throw log.error(i18nHelper.getMessage('130101').replace('{0}', e.toString()), e);
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {CheerioAPI, load} from "cheerio";
|
||||
import DoubanSearchResultSubject from "../model/DoubanSearchResultSubject";
|
||||
import {SearchPage} from "../model/SearchPage";
|
||||
import {SEARCH_ITEM_PAGE_SIZE} from "../../../constant/Constsant";
|
||||
import {SEARCH_ITEM_PAGE_SIZE, SupportType} from "../../../constant/Constsant";
|
||||
import {log} from "../../../utils/Logutil";
|
||||
|
||||
export default class SearchParserHandler {
|
||||
@ -38,7 +38,7 @@ export default class SearchParserHandler {
|
||||
})
|
||||
};
|
||||
|
||||
static parseSearchJson(result: string, start:number): SearchPage {
|
||||
static parseSearchJson(result: string, type:SupportType, start:number): SearchPage {
|
||||
log.debug("解析给多页面结果");
|
||||
const data:{total:number, limit:number, more:boolean, items:string[]} = JSON.parse(result);
|
||||
const list:string[] = data.items;
|
||||
@ -46,7 +46,7 @@ export default class SearchParserHandler {
|
||||
.map(e => load(e))
|
||||
.map(e=>this.parseSearch(e))
|
||||
.map(e => e? e[0]:null);
|
||||
return new SearchPage(data.total, start / data.limit, data.limit, resultList);
|
||||
return new SearchPage(data.total, start / data.limit, data.limit, type, resultList);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
29
src/org/wanxp/douban/data/search/SearchParserV2.ts
Normal file
29
src/org/wanxp/douban/data/search/SearchParserV2.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import DoubanSearchResultSubject from "../model/DoubanSearchResultSubject";
|
||||
|
||||
export default class SearchParserHandlerV2 {
|
||||
|
||||
static itemMapToSearchResult(items:any):DoubanSearchResultSubject[] {
|
||||
if (!items) {
|
||||
return [];
|
||||
}
|
||||
return items.map((i: any) => {
|
||||
const target:any = i.target;
|
||||
const result: DoubanSearchResultSubject = {
|
||||
id: target.id ??'',
|
||||
title: target.title ?? '-',
|
||||
score: target.rating && target.rating.value ? Number(target.rating.value) : null,
|
||||
cast: target.card_subtitle?? '',
|
||||
type: i.type_name ?? '-',
|
||||
desc: '-',
|
||||
url: target.uri? (target.uri.replaceAll('douban://', 'https://')) : 'https://www.douban.com',
|
||||
image: "",
|
||||
imageUrl: "",
|
||||
publisher: "",
|
||||
datePublished: undefined,
|
||||
genre: []
|
||||
};
|
||||
return result;
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
17
src/org/wanxp/douban/data/search/SearchV2.ts
Normal file
17
src/org/wanxp/douban/data/search/SearchV2.ts
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
import {DoubanPluginSetting} from "../../setting/model/DoubanPluginSetting";
|
||||
import {SearchPage} from "../model/SearchPage";
|
||||
import SettingsManager from "../../setting/SettingsManager";
|
||||
import {SupportType} from "../../../constant/Constsant";
|
||||
import {SearchPageFetcher} from "./searcher/SearchPageFetcher";
|
||||
import {SearchResultPageParser} from "./parser/SearchResultPageParser";
|
||||
|
||||
export default class SearcherV2 {
|
||||
static search(searchItem: string, searchType: SupportType, pageNum:number, pageSize:number, doubanSettings: DoubanPluginSetting, settingsManager:SettingsManager): Promise<SearchPage> {
|
||||
return new SearchPageFetcher(settingsManager)
|
||||
.fetch(searchItem, searchType, pageNum, pageSize)
|
||||
.then(e => new SearchResultPageParser()
|
||||
.parse(e, searchType, pageNum, pageSize));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
import {SupportType} from "../../../../constant/Constsant";
|
||||
import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface";
|
||||
import {SearchPage} from "../../model/SearchPage";
|
||||
import SearchParserHandlerV2 from "../SearchParserV2";
|
||||
|
||||
export class FistAllPageSearchResultPageParser implements SearchResultPageParserInterface {
|
||||
support(type:SupportType, pageNum:number):boolean {
|
||||
return pageNum == 1 && type == SupportType.ALL;
|
||||
}
|
||||
parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage {
|
||||
const {subjects} = JSON.parse(source);
|
||||
if (!subjects) {
|
||||
return SearchPage.empty(type);
|
||||
}
|
||||
const {items} = subjects;
|
||||
if (!items ||items.length == 0) {
|
||||
return SearchPage.empty(type);
|
||||
}
|
||||
const doubanSearchResultSubjects = SearchParserHandlerV2.itemMapToSearchResult(items);
|
||||
return new SearchPage(items.length, pageNum, pageSize, type, doubanSearchResultSubjects);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
import {SupportType} from "../../../../constant/Constsant";
|
||||
import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface";
|
||||
import {log} from "../../../../utils/Logutil";
|
||||
import {SearchPage} from "../../model/SearchPage";
|
||||
import SearchParserHandlerV2 from "../SearchParserV2";
|
||||
|
||||
export class OtherAllPageSearchResultPageParser implements SearchResultPageParserInterface {
|
||||
support(type:SupportType, pageNum:number):boolean {
|
||||
return pageNum > 1 && type == SupportType.ALL;
|
||||
}
|
||||
parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage {
|
||||
log.debug("解析给多页面结果");
|
||||
const {contents} = JSON.parse(source);
|
||||
if (!contents) {
|
||||
return new SearchPage(0, 0, 0, type, []);
|
||||
}
|
||||
const data:{total:number, start:number, count:number, items:any[]} = contents;
|
||||
const doubanSearchResultSubjects = SearchParserHandlerV2.itemMapToSearchResult(data.items);
|
||||
return new SearchPage(data.total, pageNum, pageSize, type, doubanSearchResultSubjects);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface";
|
||||
import {FistAllPageSearchResultPageParser} from "./FistAllPageSearchResultPageParser";
|
||||
import {OtherAllPageSearchResultPageParser} from "./OtherAllPageSearchResultPageParser";
|
||||
import {SearchPage} from "../../model/SearchPage";
|
||||
import {SupportType} from "../../../../constant/Constsant";
|
||||
|
||||
export class SearchResultPageParser {
|
||||
|
||||
private parsers:SearchResultPageParserInterface[] = [];
|
||||
|
||||
constructor() {
|
||||
this.parsers.push(new FistAllPageSearchResultPageParser());
|
||||
this.parsers.push(new OtherAllPageSearchResultPageParser());
|
||||
}
|
||||
|
||||
public parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage {
|
||||
for (const parser of this.parsers) {
|
||||
if (parser.support(type, pageNum)) {
|
||||
return parser.parse(source, type, pageNum, pageSize);
|
||||
}
|
||||
}
|
||||
throw new Error(`not support type:${type} pageNum:${pageNum}`);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import {SearchPage} from "../../model/SearchPage";
|
||||
import {SupportType} from "../../../../constant/Constsant";
|
||||
import DoubanSearchResultSubject from "../../model/DoubanSearchResultSubject";
|
||||
|
||||
export interface SearchResultPageParserInterface {
|
||||
support(type:SupportType, pageNum:number):boolean;
|
||||
|
||||
parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage;
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
import { SupportType } from "src/org/wanxp/constant/Constsant";
|
||||
import SettingsManager from "../../../setting/SettingsManager";
|
||||
import {SearchPageFetcherInterface} from "./SearchPageFetcherInterface";
|
||||
import HttpUtil from "../../../../utils/HttpUtil";
|
||||
import {log} from "../../../../utils/Logutil";
|
||||
import {i18nHelper} from "../../../../lang/helper";
|
||||
|
||||
export abstract class AbstractSearchPageFetcher implements SearchPageFetcherInterface {
|
||||
|
||||
protected settingsManager: SettingsManager;
|
||||
|
||||
constructor(settingsManager: SettingsManager) {
|
||||
this.settingsManager = settingsManager;
|
||||
}
|
||||
|
||||
support(type: SupportType): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
fetch(keyword: string, pageNum: number, pageSize: number): Promise<string> {
|
||||
const url:string = this.getUrl(keyword, pageNum, pageSize);
|
||||
if (!url) {
|
||||
return Promise.resolve("");
|
||||
}
|
||||
return HttpUtil.httpRequestGet(url, this.settingsManager.getHeaders(), this.settingsManager)
|
||||
.catch(e => {
|
||||
throw log.error(i18nHelper.getMessage('130101').replace('{0}', e.toString()), e);
|
||||
}); }
|
||||
|
||||
abstract getUrl(keyword: string, pageNum: number, pageSize: number):string;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import {AbstractSearchPageFetcher} from "./AbstractSearchPageFetcher";
|
||||
import { SupportType } from "src/org/wanxp/constant/Constsant";
|
||||
|
||||
export class BookPageSearchPageFetcher extends AbstractSearchPageFetcher {
|
||||
getUrl(keyword: string, pageNum: number, pageSize: number): string {
|
||||
return `https://www.douban.com/j/search?q=${keyword}&start=${pageNum * pageSize}&cat=1001`;
|
||||
}
|
||||
support(type: SupportType): boolean {
|
||||
return type == SupportType.MOVIE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import {AbstractSearchPageFetcher} from "./AbstractSearchPageFetcher";
|
||||
import { SupportType } from "src/org/wanxp/constant/Constsant";
|
||||
|
||||
export class FistAllPageSearchPageFetcher extends AbstractSearchPageFetcher {
|
||||
getUrl(keyword: string, pageNum: number, pageSize: number): string {
|
||||
return `https://m.douban.com/rexxar/api/v2/search?q=${keyword}&start=${pageNum}&count=${pageSize}`;
|
||||
}
|
||||
support(type: SupportType): boolean {
|
||||
return type == SupportType.ALL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
import {AbstractSearchPageFetcher} from "./AbstractSearchPageFetcher";
|
||||
import { SupportType } from "src/org/wanxp/constant/Constsant";
|
||||
|
||||
export class MoviePageSearchPageFetcher extends AbstractSearchPageFetcher {
|
||||
getUrl(keyword: string, pageNum: number, pageSize: number): string {
|
||||
return `https://www.douban.com/j/search?q=${keyword}&start=${pageNum * pageSize}&cat=1002`;
|
||||
}
|
||||
support(type: SupportType): boolean {
|
||||
return type == SupportType.MOVIE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
import {SearchPageFetcherInterface} from "./SearchPageFetcherInterface";
|
||||
import {FistAllPageSearchPageFetcher} from "./FistAllPageSearchPageFetcher";
|
||||
import SettingsManager from "../../../setting/SettingsManager";
|
||||
import {SupportType} from "../../../../constant/Constsant";
|
||||
import {MoviePageSearchPageFetcher} from "./MoviePageSearchPageFetcher";
|
||||
import {BookPageSearchPageFetcher} from "./BookPageSearchPageFetcher";
|
||||
|
||||
export class SearchPageFetcher {
|
||||
|
||||
private fetchers:SearchPageFetcherInterface[] = [];
|
||||
|
||||
constructor(settingsManager:SettingsManager) {
|
||||
this.fetchers.push(new FistAllPageSearchPageFetcher(settingsManager));
|
||||
this.fetchers.push(new MoviePageSearchPageFetcher(settingsManager));
|
||||
this.fetchers.push(new BookPageSearchPageFetcher(settingsManager))
|
||||
}
|
||||
|
||||
fetch(keyword:string, type:SupportType, pageNum:number, pageSize:number):Promise<string> {
|
||||
for (const fetcher of this.fetchers) {
|
||||
if (fetcher.support(type)) {
|
||||
return fetcher.fetch(keyword, pageNum, pageSize);
|
||||
}
|
||||
}
|
||||
throw new Error(`not support type:${type} pageNum:${pageNum}`);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import {SupportType} from "../../../../constant/Constsant";
|
||||
|
||||
export interface SearchPageFetcherInterface {
|
||||
|
||||
support(type:SupportType):boolean;
|
||||
|
||||
fetch(keyword:string, pageNum:number, pageSize:number):Promise<string>;
|
||||
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
//简体中文
|
||||
export default {
|
||||
//main.ts
|
||||
'110001': 'search douban by current file name',
|
||||
'110002': 'search douban and import to current file',
|
||||
'110001': 'searcher douban by current file name',
|
||||
'110002': 'searcher douban and import to current file',
|
||||
'110003': `Enter Search Term:`,
|
||||
'110004': `Search`,
|
||||
'110005': `Cancel`,
|
||||
'110006': `sync douban personal book-movie-music to Obsidian`,
|
||||
'110101': 'search douban and create file',
|
||||
'110101': 'searcher douban and create file',
|
||||
'110201': `{0} already exists`,
|
||||
'110202': `{0} template can not read`,
|
||||
'110103': 'sync personal data from douban',
|
||||
@ -557,6 +557,10 @@ PS: This file could be delete if you want to.
|
||||
'NOTE': `note`,
|
||||
'GAME': `game`,
|
||||
'TELEPLAY': `teleplay`,
|
||||
'THEATER': `theater`,
|
||||
|
||||
'MOVIE_AND_TELEPLAY': `movie&teleplay`,
|
||||
|
||||
|
||||
'DAY': `D`,
|
||||
'HOUR': `H`,
|
||||
|
||||
@ -562,6 +562,9 @@ export default {
|
||||
'NOTE': `笔记`,
|
||||
'GAME': `游戏`,
|
||||
'TELEPLAY': `电视剧`,
|
||||
'THEATER': `戏剧`,
|
||||
'MOVIE_AND_TELEPLAY': `影视剧`,
|
||||
|
||||
|
||||
'DAY': `天`,
|
||||
'HOUR': `时`,
|
||||
|
||||
@ -1,4 +1,12 @@
|
||||
import {Action, BasicConst, SearchHandleMode, SubjectHandledStatus, SyncTypeRecords} from "./constant/Constsant";
|
||||
import {
|
||||
Action,
|
||||
BasicConst,
|
||||
SEARCH_ITEM_PAGE_SIZE,
|
||||
SearchHandleMode,
|
||||
SubjectHandledStatus,
|
||||
SupportType,
|
||||
SyncTypeRecords
|
||||
} from "./constant/Constsant";
|
||||
import {Editor, Notice, Plugin} from "obsidian";
|
||||
|
||||
import {DEFAULT_SETTINGS} from "./constant/DefaultSettings";
|
||||
@ -6,7 +14,6 @@ import {DoubanFuzzySuggester} from "./douban/data/search/DoubanSearchFuzzySugges
|
||||
import {DoubanPluginSetting} from "./douban/setting/model/DoubanPluginSetting";
|
||||
import {DoubanSearchChooseItemHandler} from "./douban/data/handler/DoubanSearchChooseItemHandler";
|
||||
import {DoubanSearchModal} from "./douban/data/search/DoubanSearchModal";
|
||||
import DoubanSearchResultSubject from "./douban/data/model/DoubanSearchResultSubject";
|
||||
import {DoubanSettingTab} from "./douban/setting/DoubanSettingTab";
|
||||
import DoubanSubject from "./douban/data/model/DoubanSubject";
|
||||
import {DoubanSyncModal} from "./douban/component/DoubanSyncModal";
|
||||
@ -16,8 +23,6 @@ import GlobalStatusHolder from "./douban/model/GlobalStatusHolder";
|
||||
import HandleContext from "./douban/data/model/HandleContext";
|
||||
import HandleResult from "./douban/data/model/HandleResult";
|
||||
import NetFileHandler from "./net/NetFileHandler";
|
||||
import {SearchPageInfo} from "./douban/data/model/SearchPageInfo";
|
||||
import Searcher from "./douban/data/search/Search";
|
||||
import SettingsManager from "./douban/setting/SettingsManager";
|
||||
import {SyncConfig} from "./douban/sync/model/SyncConfig";
|
||||
import SyncHandler from "./douban/sync/handler/SyncHandler";
|
||||
@ -26,6 +31,8 @@ import {i18nHelper} from './lang/helper';
|
||||
import {log} from "src/org/wanxp/utils/Logutil";
|
||||
import GithubUtil from "./utils/GithubUtil";
|
||||
import {DoubanPluginOnlineData} from "./douban/setting/model/DoubanPluginOnlineData";
|
||||
import SearcherV2 from "./douban/data/search/SearchV2";
|
||||
import {SearchPage} from "./douban/data/model/SearchPage";
|
||||
|
||||
export default class DoubanPlugin extends Plugin {
|
||||
public settings: DoubanPluginSetting;
|
||||
@ -119,13 +126,13 @@ export default class DoubanPlugin extends Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
async search(searchTerm: string, context: HandleContext) {
|
||||
async search(searchTerm: string, searchType: SupportType, context: HandleContext) {
|
||||
try {
|
||||
this.showStatus(i18nHelper.getMessage('140201', searchTerm));
|
||||
const resultList:DoubanSearchResultSubject[] = await Searcher.search(searchTerm, this.settings, context.plugin.settingsManager);
|
||||
this.showStatus(i18nHelper.getMessage('140202', resultList.length.toString()));
|
||||
context.searchPage = new SearchPageInfo(21,-1,20);
|
||||
new DoubanFuzzySuggester(this, context, searchTerm).showSearchList(resultList);
|
||||
const result:SearchPage = await SearcherV2.search(searchTerm, searchType, 1, SEARCH_ITEM_PAGE_SIZE, this.settings, context.plugin.settingsManager);
|
||||
this.showStatus(i18nHelper.getMessage('140202', result.list.toString()));
|
||||
context.searchPage = result;
|
||||
new DoubanFuzzySuggester(this, context, searchTerm).showSearchPage(result);
|
||||
} catch (e) {
|
||||
log.error(i18nHelper.getMessage('140206').replace('{0}', e.message), e);
|
||||
} finally {
|
||||
@ -138,7 +145,7 @@ export default class DoubanPlugin extends Plugin {
|
||||
if (activeFile) {
|
||||
const searchTerm = activeFile.basename;
|
||||
if (searchTerm) {
|
||||
await this.search(searchTerm, context);
|
||||
await this.search(searchTerm, SupportType.ALL, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -162,7 +169,7 @@ export default class DoubanPlugin extends Plugin {
|
||||
}
|
||||
|
||||
this.addCommand({
|
||||
id: "search-douban-import-and-create-file",
|
||||
id: "searcher-douban-import-and-create-file",
|
||||
name: i18nHelper.getMessage("110101"),
|
||||
callback: () =>
|
||||
this.getDoubanTextForCreateNewNote({plugin: this,
|
||||
@ -175,7 +182,7 @@ export default class DoubanPlugin extends Plugin {
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "search-douban-and-input-current-file",
|
||||
id: "searcher-douban-and-input-current-file",
|
||||
name: i18nHelper.getMessage("110002"),
|
||||
editorCallback: (editor: Editor) =>
|
||||
this.getDoubanTextForSearchTerm({plugin: this,
|
||||
@ -188,7 +195,7 @@ export default class DoubanPlugin extends Plugin {
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "search-douban-by-current-file-name",
|
||||
id: "searcher-douban-by-current-file-name",
|
||||
name: i18nHelper.getMessage("110001"),
|
||||
editorCallback: (editor: Editor) =>
|
||||
this.getDoubanTextForActiveFile({plugin: this,
|
||||
|
||||
@ -19,6 +19,7 @@ export default class HttpUtil {
|
||||
*/
|
||||
// Cookie: 'll="108296"; bid=xHRJLeWBrjQ; _pk_id.100001.8cb4=f8f83e81ec224a1a.1691572669.; __utmv=30149280.13103; __yadk_uid=ce95W7OsgT0iKFceWgbMSUdw1oOqxNTk; __gads=ID=62585f60f3f637d0-2234f63fc6e200a5:T=1691572672:RT=1691572672:S=ALNI_MaIqTxSWHsfpnX9nAmMHcPQEsaezg; __gpi=UID=00000c29a9f98e5b:T=1691572672:RT=1691572672:S=ALNI_MbLAq8XNoKrRPKNqGCMdgXSPZvidw; ap_v=0,6.0; __utma=30149280.135860784.1691572641.1691572641.1694509646.2; __utmc=30149280; __utmz=30149280.1694509646.2.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1694509648%2C%22https%3A%2F%2Fmovie.douban.com%2Ftv%2F%22%5D; _pk_ses.100001.8cb4=1; __utmt=1; dbcl2="131038721:LUssju34QFw"; ck=dCQj; push_noty_num=0; push_doumail_num=0; __utmb=30149280.3.10.1694509646'
|
||||
public static httpRequestGet(url: string, headers: any, settingsManager?: SettingsManager): Promise<string> {
|
||||
settingsManager.debug(`请求地址:${url}`);
|
||||
const {['Accept-Encoding']: acceptEncoding, ...headersInner} = headers;
|
||||
let options = {
|
||||
headers: headersInner
|
||||
@ -48,6 +49,43 @@ export default class HttpUtil {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* get请求
|
||||
* @param url 请求地址
|
||||
* @param headers 请求参数
|
||||
* @param settingsManager 设置管理器
|
||||
*/
|
||||
// Cookie: 'll="108296"; bid=xHRJLeWBrjQ; _pk_id.100001.8cb4=f8f83e81ec224a1a.1691572669.; __utmv=30149280.13103; __yadk_uid=ce95W7OsgT0iKFceWgbMSUdw1oOqxNTk; __gads=ID=62585f60f3f637d0-2234f63fc6e200a5:T=1691572672:RT=1691572672:S=ALNI_MaIqTxSWHsfpnX9nAmMHcPQEsaezg; __gpi=UID=00000c29a9f98e5b:T=1691572672:RT=1691572672:S=ALNI_MbLAq8XNoKrRPKNqGCMdgXSPZvidw; ap_v=0,6.0; __utma=30149280.135860784.1691572641.1691572641.1694509646.2; __utmc=30149280; __utmz=30149280.1694509646.2.2.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1694509648%2C%22https%3A%2F%2Fmovie.douban.com%2Ftv%2F%22%5D; _pk_ses.100001.8cb4=1; __utmt=1; dbcl2="131038721:LUssju34QFw"; ck=dCQj; push_noty_num=0; push_doumail_num=0; __utmb=30149280.3.10.1694509646'
|
||||
public static httpRequestGetJson(url: string, headers: any, settingsManager?: SettingsManager): Promise<any> {
|
||||
const {['Accept-Encoding']: acceptEncoding, ...headersInner} = headers;
|
||||
let options = {
|
||||
headers: headersInner
|
||||
}
|
||||
settingsManager.debug(`Obsidian-Douban:从网络获取json开始:\nurl:${url}\nheaders:${JSON.stringify(headers)}`);
|
||||
return new Promise((resolve, rejects) => {
|
||||
https.get(url, { ...options }, function (response: any) {
|
||||
let chunks: any = [],
|
||||
size = 0;
|
||||
if (response.status == 403) {
|
||||
rejects(new Error(i18nHelper.getMessage('130106')));
|
||||
}
|
||||
response.on("data", function (chunk: any) {
|
||||
chunks.push(chunk)
|
||||
size += chunk.length
|
||||
})
|
||||
|
||||
response.on("end", function () {
|
||||
let data = Buffer.concat(chunks, size)
|
||||
let html = data.toString()
|
||||
if (settingsManager) {
|
||||
settingsManager.debug(`Obsidian-Douban:从网络获取网页完成:\nhtml:\n${html}`);
|
||||
}
|
||||
resolve(html)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* get请求
|
||||
* @param url 请求地址
|
||||
|
||||
@ -34,6 +34,11 @@
|
||||
}
|
||||
|
||||
.obsidian_douban_search_input {
|
||||
margin-left: 5px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.obsidian_douban_search_input_content {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
width: 90%;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user