11import BaseSource from './base.js' ;
22import { log } from "../utils/log-util.js" ;
3- import { getDoubanDetail , searchDoubanTitles } from "../utils/douban-util.js" ;
3+ import { getDoubanDetail , searchDoubanTitles , searchDoubanTitlesByPublic } from "../utils/douban-util.js" ;
44
55// =====================
66// 获取豆瓣源播放链接
@@ -17,9 +17,24 @@ export default class DoubanSource extends BaseSource {
1717
1818 async search ( keyword ) {
1919 try {
20- const response = await searchDoubanTitles ( keyword ) ;
21-
22- const data = response . data ;
20+ let response = await searchDoubanTitles ( keyword ) ;
21+ let data = response ?. data ;
22+
23+ // 兜底策略:如果 searchDoubanTitles 失败或返回空结果,使用 searchDoubanTitlesByPublic
24+ if ( ! data || ( ! data ?. subjects ?. items ?. length && ! data ?. smart_box ?. length ) ) {
25+ log ( "info" , "searchDoubanTitles failed or empty, trying searchDoubanTitlesByPublic" ) ;
26+ const fallbackResponse = await searchDoubanTitlesByPublic ( keyword ) ;
27+ const fallbackData = fallbackResponse ?. data ;
28+
29+ if ( fallbackData ?. subjects ?. length > 0 ) {
30+ // 将 searchDoubanTitlesByPublic 返回的数据转换为原格式
31+ data = {
32+ subjects : {
33+ items : fallbackData . subjects . map ( item => this . convertToOriginalFormat ( item ) ) ,
34+ }
35+ } ;
36+ }
37+ }
2338
2439 let tmpAnimes = [ ] ;
2540 if ( data ?. subjects ?. items ?. length > 0 ) {
@@ -43,6 +58,58 @@ export default class DoubanSource extends BaseSource {
4358 }
4459 }
4560
61+ // 将 searchDoubanTitlesByPublic 返回的数据格式转换为原格式
62+ convertToOriginalFormat ( item ) {
63+ // subtype: "movie" -> "电影", "tv" -> "电视剧"
64+ const typeMap = {
65+ 'movie' : '电影' ,
66+ 'tv' : '电视剧'
67+ } ;
68+ const typeName = typeMap [ item . subtype ] || item . subtype ;
69+
70+ // 构建 cover_url:从原始图片URL中提取图片ID,然后构造固定格式的URL
71+ const originalImageUrl = item . images ?. large || item . images ?. medium || item . images ?. small || '' ;
72+ let coverUrl = '' ;
73+ if ( originalImageUrl ) {
74+ // 从类似 https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2887095203.jpg 的URL中提取 p2887095203
75+ const match = originalImageUrl . match ( / \/ ( p \d + ) \. j p g / ) ;
76+ if ( match && match [ 1 ] ) {
77+ const imageId = match [ 1 ] ; // 例如 p2887095203
78+ coverUrl = `https://qnmob3.doubanio.com/view/photo/large/public/${ imageId } .jpg?imageView2/0/q/80/w/9999/h/120/format/jpg` ;
79+ }
80+ }
81+
82+ // 构建 card_subtitle,包含地区、类型、导演、演员等信息
83+ const directors = item . directors ?. map ( d => d . name ) . join ( ' ' ) || '' ;
84+ const casts = item . casts ?. slice ( 0 , 3 ) . map ( c => c . name ) . join ( ' ' ) || '' ;
85+ const cardSubtitle = `${ item . year } / ${ item . genres ?. join ( ' / ' ) || '' } / ${ directors } ${ casts ? ' / ' + casts : '' } ` ;
86+
87+ return {
88+ layout : 'subject' ,
89+ type_name : typeName ,
90+ target_id : String ( item . id ) ,
91+ target : {
92+ rating : {
93+ count : item . collect_count || 0 ,
94+ max : item . rating ?. max || 10 ,
95+ star_count : item . rating ?. stars ? parseInt ( item . rating . stars ) / 10 : 0 ,
96+ value : item . rating ?. average || 0
97+ } ,
98+ controversy_reason : '' ,
99+ title : item . title ,
100+ abstract : '' ,
101+ has_linewatch : false ,
102+ uri : `douban://douban.com/${ item . subtype === 'movie' ? 'movie' : 'tv' } /${ item . id } ` ,
103+ cover_url : coverUrl ,
104+ year : String ( item . year || '' ) ,
105+ card_subtitle : cardSubtitle ,
106+ id : String ( item . id ) ,
107+ null_rating_reason : ''
108+ } ,
109+ target_type : item . subtype === 'movie' ? 'movie' : 'tv'
110+ } ;
111+ }
112+
46113 async getEpisodes ( id ) { }
47114
48115 async handleAnimes ( sourceAnimes , queryTitle , curAnimes , detailStore = null ) {
0 commit comments