fix: restore All search type and initialize login state on startup

- Switch AllPageSearchPageFetcher from m.douban.com/rexxar/api/v2/search
  (returns 403 need_login) to www.douban.com/j/search (works with cookies)
- Update AllFirstPageSearchResultPageParser and OtherAllPageSearchResultPageParser
  to use SearchParserHandler.parseSearchJson() matching the j/search response format,
  replacing the old Rexxar-specific SearchParserHandlerV2 parsing logic
- Add await this.userComponent.login() in onload() so login state is initialized
  on startup, fixing false isLogin()=false causing "need login for next page" errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
YuBai 2026-03-04 18:20:58 +08:00
parent 572907719b
commit c375512903
4 changed files with 11 additions and 25 deletions

@ -3,8 +3,7 @@ import {
} from "../../../../constant/Constsant"; } from "../../../../constant/Constsant";
import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface"; import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface";
import {SearchPage} from "../../model/SearchPage"; import {SearchPage} from "../../model/SearchPage";
import SearchParserHandlerV2 from "../SearchParserV2"; import SearchParserHandler from "../SearchParser";
import StringUtil from "../../../../utils/StringUtil";
import {log} from "../../../../utils/Logutil"; import {log} from "../../../../utils/Logutil";
export class AllFirstPageSearchResultPageParser implements SearchResultPageParserInterface { export class AllFirstPageSearchResultPageParser implements SearchResultPageParserInterface {
@ -12,22 +11,11 @@ export class AllFirstPageSearchResultPageParser implements SearchResultPageParse
return pageNum == 1 && type == SupportType.all; return pageNum == 1 && type == SupportType.all;
} }
parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage { parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage {
if (!source || StringUtil.notJsonString(source)) { log.debug("解析给多页面结果");
//TODO 国际化 if (!source) {
log.notice("Obsidian-Douban:查询结果为空,无匹配结果,请尝试登录获取获取更多数据(已登录则忽略)"); return new SearchPage(0, 0, 0, type, []);
return SearchPage.empty(type);
} }
return SearchParserHandler.parseSearchJson(source, type, pageNum);
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(2000, pageNum, pageSize, type, doubanSearchResultSubjects);
} }

@ -2,7 +2,7 @@ import {SupportType} from "../../../../constant/Constsant";
import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface"; import {SearchResultPageParserInterface} from "./SearchResultPageParserInterface";
import {log} from "../../../../utils/Logutil"; import {log} from "../../../../utils/Logutil";
import {SearchPage} from "../../model/SearchPage"; import {SearchPage} from "../../model/SearchPage";
import SearchParserHandlerV2 from "../SearchParserV2"; import SearchParserHandler from "../SearchParser";
export class OtherAllPageSearchResultPageParser implements SearchResultPageParserInterface { export class OtherAllPageSearchResultPageParser implements SearchResultPageParserInterface {
support(type:SupportType, pageNum:number):boolean { support(type:SupportType, pageNum:number):boolean {
@ -10,13 +10,10 @@ export class OtherAllPageSearchResultPageParser implements SearchResultPageParse
} }
parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage { parse(source:string, type:SupportType, pageNum:number, pageSize:number):SearchPage {
log.debug("解析给多页面结果"); log.debug("解析给多页面结果");
const {contents} = JSON.parse(source); if (!source) {
if (!contents) {
return new SearchPage(0, 0, 0, type, []); return new SearchPage(0, 0, 0, type, []);
} }
const data:{total:number, start:number, count:number, items:any[]} = contents; return SearchParserHandler.parseSearchJson(source, type, pageNum);
const doubanSearchResultSubjects = SearchParserHandlerV2.itemMapToSearchResult(data.items);
return new SearchPage(data.total, pageNum, pageSize, type, doubanSearchResultSubjects);
} }
} }

@ -2,8 +2,8 @@ import {AbstractSearchPageFetcher} from "./AbstractSearchPageFetcher";
import { SupportType } from "src/org/wanxp/constant/Constsant"; import { SupportType } from "src/org/wanxp/constant/Constsant";
export class AllPageSearchPageFetcher extends AbstractSearchPageFetcher { export class AllPageSearchPageFetcher extends AbstractSearchPageFetcher {
getUrl(keyword: string, pageNum: number, pageSize: number): string { getUrl(keyword: string, start: number, pageSize: number): string {
return `https://m.douban.com/rexxar/api/v2/search?q=${keyword}&start=${pageNum}&count=${pageSize}`; return `https://www.douban.com/j/search?q=${keyword}&start=${start}`;
} }
support(type: SupportType): boolean { support(type: SupportType): boolean {
return type == SupportType.all; return type == SupportType.all;

@ -285,6 +285,7 @@ export default class DoubanPlugin extends Plugin {
this.settingsManager = new SettingsManager(this.app, this); this.settingsManager = new SettingsManager(this.app, this);
// this.fetchOnlineData(this.settingsManager); // this.fetchOnlineData(this.settingsManager);
this.userComponent = new UserComponent(this.settingsManager); this.userComponent = new UserComponent(this.settingsManager);
await this.userComponent.login();
this.netFileHandler = new NetFileHandler(this.fileHandler); this.netFileHandler = new NetFileHandler(this.fileHandler);
this.settingTab = new DoubanSettingTab(this.app, this); this.settingTab = new DoubanSettingTab(this.app, this);