1+ /*
2+ @header ({
3+ searchable: 0,
4+ filterable: 0,
5+ quickSearch: 0,
6+ title: 'webdav影视[盘]',
7+ '类型': '影视',
8+ lang: 'ds',
9+ style: {
10+ type: 'list',
11+ ratio: 1.433
12+ }
13+ })
14+ */
15+
16+ var rule = {
17+ 类型 : '影视' ,
18+ title : 'webdav[盘]' ,
19+ host : '' ,
20+ url : '' ,
21+ searchUrl : '' ,
22+ headers : { 'User-Agent' : 'UC_UA' } ,
23+ searchable : 0 ,
24+ quickSearch : 0 ,
25+ filterable : 0 ,
26+ double : true ,
27+ play_parse : true ,
28+ limit : 6 ,
29+ class_name : '' ,
30+ class_url : '' ,
31+ pans : [ ] ,
32+ style : { "type" : "list" , "ratio" : 1.433 } ,
33+ // 推荐样式
34+ hikerListCol : 'icon_round_2' ,
35+ // 分类列表样式
36+ hikerClassListCol : 'avatar' ,
37+ hostJs : async function ( ) {
38+ let { HOST } = this ;
39+ return rule . params ;
40+ } ,
41+ 预处理 : async function ( ) {
42+ log ( 'rule.host:' , rule . host ) ;
43+ let data = await request ( rule . host ) ;
44+ try {
45+ rule . pans = JSON . parse ( data ) ;
46+ } catch ( e ) {
47+ log ( '获取webdav配置错误:' , e . message ) ;
48+ }
49+ } ,
50+ class_parse : async function ( ) {
51+ let { input, pdfa, pdfh, pd} = this ;
52+ let classList = [ ] ;
53+ rule . pans . forEach ( pan => {
54+ classList . push ( {
55+ type_name : pan . name ,
56+ type_id : pan . id || pan . baseURL ,
57+ } )
58+ } )
59+
60+ let filters = [ {
61+ 'key' : 'order' ,
62+ 'name' : '排序' ,
63+ 'value' : [ { 'n' : '名称⬆️' , 'v' : 'vod_name_asc' } , { 'n' : '名称⬇️' , 'v' : 'vod_name_desc' } ,
64+ { 'n' : '中英⬆️' , 'v' : 'vod_cn_asc' } , { 'n' : '中英⬇️' , 'v' : 'vod_cn_desc' } ,
65+ { 'n' : '时间⬆️' , 'v' : 'vod_time_asc' } , { 'n' : '时间⬇️' , 'v' : 'vod_time_desc' } ,
66+ { 'n' : '大小⬆️' , 'v' : 'vod_size_asc' } , { 'n' : '大小⬇️' , 'v' : 'vod_size_desc' } , { 'n' : '无' , 'v' : 'none' } ]
67+ } ,
68+ { 'key' : 'show' , 'name' : '播放展示' , 'value' : [ { 'n' : '单集' , 'v' : 'single' } , { 'n' : '全集' , 'v' : 'all' } ] }
69+ ] ;
70+
71+ let filter_dict = { } ;
72+ classList . forEach ( it => {
73+ filter_dict [ it . type_id ] = filters ;
74+ } ) ;
75+
76+ return { class : classList , filters : filter_dict }
77+ } ,
78+ lazy : async function ( ) {
79+ let { input, webdavProxyUrl} = this ;
80+ console . log ( `✅webdavProxyUrl的结果:', ${ webdavProxyUrl } ` ) ;
81+ return {
82+ parse : 0 ,
83+ url : webdavProxyUrl + input
84+ }
85+ } ,
86+ action : async function ( action , value ) {
87+ if ( action === 'only_params' ) {
88+ return '这是个传参源哦'
89+ }
90+ return `未定义动作:${ action } `
91+ } ,
92+ 推荐 : async function ( ) {
93+ let { input, pdfa, pdfh, pd, publicUrl} = this ;
94+ let vod_pic = urljoin ( publicUrl , './images/icon_common/网盘.png' ) ;
95+ let d = [ ] ;
96+ if ( ! rule . pans || rule . pans . length < 1 ) {
97+ d . push ( {
98+ vod_id : 'only_params' ,
99+ vod_pic : vod_pic ,
100+ vod_name : '这是个传参源哦' ,
101+ vod_tag : 'action' ,
102+ } )
103+ }
104+ return d
105+ } ,
106+
107+ 一级 : async function ( tid , pg , filter , extend ) {
108+ let d = [ ] ;
109+ if ( Number ( pg ) > 1 ) {
110+ return d
111+ }
112+ const _id = tid . split ( '$' ) [ 0 ] ;
113+ const _tid = tid . split ( '$' ) [ 1 ] || '/' ;
114+ let pan = rule . pans . find ( it => it . id === _id || it . baseURL === _id ) ;
115+ if ( pan ) {
116+ const webdav = createWebDAVClient ( pan ) ;
117+ const isConnected = await webdav . testConnection ( ) ;
118+ if ( isConnected ) {
119+ const rootItems = await webdav . listDirectory ( _tid ) ;
120+ console . log ( 'Root directory contents:' ) ;
121+
122+ // 排除的文件扩展名列表
123+ const excludeExts = [
124+ // 文档文件
125+ 'nfo' , 'txt' , 'pdf' , 'doc' , 'docx' , 'xls' , 'xlsx' , 'ppt' , 'pptx' ,
126+ // 图片文件
127+ 'jpg' , 'jpeg' , 'png' , 'gif' , 'bmp' , 'webp' , 'ico' , 'svg' ,
128+ // 压缩文件
129+ 'zip' , 'rar' , '7z' , 'tar' , 'gz' , 'bz2' ,
130+ // 程序文件
131+ 'exe' , 'msi' , 'bat' , 'cmd' , 'sh' , 'dmg' , 'pkg' ,
132+ // 配置文件
133+ 'ini' , 'cfg' , 'conf' , 'config' , 'xml' , 'json' , 'yml' , 'yaml' ,
134+ // 其他文件
135+ 'url' , 'lnk' , 'torrent' , 'md' , 'log' , 'db' , 'sqlite'
136+ ] ;
137+
138+ const excludePattern = new RegExp ( `\\.(${ excludeExts . join ( '|' ) } )$` , 'i' ) ;
139+
140+ // 音视频文件扩展名
141+ const mediaExts = [
142+ 'mp4' , 'mkv' , 'avi' , 'ts' , 'mov' , 'wmv' , 'flv' , 'webm' , 'm4v' , '3gp' ,
143+ 'mp3' , 'wav' , 'flac' , 'aac' , 'wma' , 'm4a' , 'ogg' , 'ape' , 'dts'
144+ ] ;
145+ const mediaPattern = new RegExp ( `\\.(${ mediaExts . join ( '|' ) } )$` , 'i' ) ;
146+
147+ rootItems . forEach ( item => {
148+ log ( item ) ;
149+
150+ // 当 showAll 为 false 时,排除不需要的文件类型
151+ if ( pan . showAll === false && ! item . isDirectory ) {
152+ // 排除非音视频文件
153+ if ( excludePattern . test ( item . name ) ) {
154+ return ; // 跳过这些文件
155+ }
156+ }
157+
158+ const type = item . isDirectory ? 'folder' : 'file' ;
159+ const size = item . isDirectory ? '' : `${ ( item . size / ( 1024 * 1024 ) ) . toFixed ( 2 ) } MB` ;
160+ const content = item . isDirectory ? '' : `${ item . contentType } ` ;
161+
162+ // 根据文件类型设置图标
163+ let vod_pic = 'https://mpimg.cn/view.php/9f684b4c4d80cb4b31d3dfade4b34612.png' ; // 默认文件夹图标
164+
165+ if ( ! item . isDirectory ) {
166+ if ( mediaPattern . test ( item . name ) ) {
167+ // 音视频和图片文件使用媒体图标
168+ vod_pic = 'https://mpimg.cn/view.php/41a0fdeb398939242397a3a467567337.png' ;
169+ } else {
170+ // 其他文件使用默认文件图标
171+ vod_pic = 'https://mpimg.cn/view.php/9f684b4c4d80cb4b31d3dfade4b34612.png' ;
172+ }
173+ }
174+
175+ d . push ( {
176+ vod_name : item . name ,
177+ vod_remarks : size ,
178+ vod_tag : type ,
179+ vod_id : _id + '$' + item . path ,
180+ vod_pic : vod_pic ,
181+ vod_content : content ,
182+ } )
183+ } ) ;
184+
185+ let fl = filter ? extend : { } ;
186+ if ( fl . order ) {
187+ let key = fl . order . split ( '_' ) . slice ( 0 , - 1 ) . join ( '_' ) ;
188+ let order = fl . order . split ( '_' ) . slice ( - 1 ) [ 0 ] ;
189+ console . log ( `排序key:${ key } ,排序order:${ order } ` ) ;
190+
191+ if ( key . includes ( 'name' ) ) {
192+ d = sortListByName ( d , key , order ) ;
193+ } else if ( key . includes ( 'time' ) ) {
194+ d = sortListByTime ( d , key , order ) ;
195+ } else if ( key . includes ( 'size' ) ) {
196+ d = sortListBySize ( d , key , order ) ;
197+ }
198+ }
199+ }
200+ }
201+ return d
202+ } ,
203+
204+ 二级 : async function ( ids ) {
205+ let VOD = { } ;
206+ let tid = ids [ 0 ] ;
207+ const _id = tid . split ( '$' ) [ 0 ] ;
208+ const _tid = tid . split ( '$' ) [ 1 ] || '/' ;
209+ let pan = rule . pans . find ( it => it . id === _id || it . baseURL === _id ) ;
210+ if ( pan ) {
211+ const webdav = createWebDAVClient ( pan ) ;
212+ const isConnected = await webdav . testConnection ( ) ;
213+ if ( isConnected ) {
214+ const itemInfo = await webdav . getInfo ( _tid ) ;
215+ VOD . vod_name = itemInfo . name ;
216+ VOD . vod_content = itemInfo . path + '\n' + '上次修改时间:' + itemInfo . lastModified ;
217+ VOD . vod_remarks = itemInfo . size ;
218+ VOD . vod_director = itemInfo . etag ;
219+ VOD . vod_actor = itemInfo . contentType ;
220+ VOD . vod_pic = '/default-poster.svg' ;
221+ VOD . vod_play_from = '在线观看' ;
222+ const proxy_params_url = `file?config=${ encodeURIComponent ( JSON . stringify ( pan ) ) } &path=${ encodeURIComponent ( _tid ) } ` ;
223+ VOD . vod_play_url = itemInfo . name + '$' + proxy_params_url ;
224+ }
225+ }
226+ return VOD
227+ } ,
228+
229+ 搜索 : async function ( ) {
230+ let { input, pdfa, pdfh, pd} = this ;
231+ let d = [ ] ;
232+ return setResult ( d )
233+ }
234+ }
235+
236+ // 排序函数(移到 rule 对象外部)
237+ const sortListByName = ( vodList , key , order ) => {
238+ if ( ! key ) return vodList ;
239+ order = order || 'asc' ;
240+ return vodList . sort ( ( a , b ) => {
241+ const nameA = a [ key ] . toLowerCase ( ) ;
242+ const nameB = b [ key ] . toLowerCase ( ) ;
243+ if ( order === 'asc' ) {
244+ return nameA . localeCompare ( nameB ) ;
245+ } else {
246+ return nameB . localeCompare ( nameA ) ;
247+ }
248+ } ) ;
249+ } ;
250+
251+ const sortListByTime = ( vodList , key , order ) => {
252+ if ( ! key ) return vodList ;
253+ let ASCarr = vodList . sort ( ( a , b ) => {
254+ const timeA = new Date ( a . vod_content . split ( '上次修改时间:' ) [ 1 ] || 0 ) ;
255+ const timeB = new Date ( b . vod_content . split ( '上次修改时间:' ) [ 1 ] || 0 ) ;
256+ return timeA - timeB ;
257+ } ) ;
258+ if ( order === 'desc' ) {
259+ ASCarr . reverse ( ) ;
260+ }
261+ return ASCarr ;
262+ } ;
263+
264+ const sortListBySize = ( vodList , key , order ) => {
265+ if ( ! key ) return vodList ;
266+ let ASCarr = vodList . sort ( ( a , b ) => {
267+ const sizeA = parseInt ( a . vod_remarks ) || 0 ;
268+ const sizeB = parseInt ( b . vod_remarks ) || 0 ;
269+ return sizeA - sizeB ;
270+ } ) ;
271+ if ( order === 'desc' ) {
272+ ASCarr . reverse ( ) ;
273+ }
274+ return ASCarr ;
275+ } ;
0 commit comments