1+ //@name :[盘] LibVio
2+ //@version :4
3+ //@webSite :https://libvio.mov/
4+ //@order :A04
5+ //@codeID :
6+ //@env :
7+ //@isAV :0
8+ //@deprecated :0
9+
10+ const appConfig = {
11+ _webSite : 'https://libvio.mov' ,
12+ /**
13+ * 网站主页,uz 调用每个函数前都会进行赋值操作
14+ * 如果不想被改变 请自定义一个变量
15+ */
16+ get webSite ( ) {
17+ return this . _webSite
18+ } ,
19+ set webSite ( value ) {
20+ this . _webSite = value
21+ } ,
22+
23+ _uzTag : '' ,
24+ /**
25+ * 扩展标识,初次加载时,uz 会自动赋值,请勿修改
26+ * 用于读取环境变量
27+ */
28+ get uzTag ( ) {
29+ return this . _uzTag
30+ } ,
31+ set uzTag ( value ) {
32+ this . _uzTag = value
33+ } ,
34+ }
35+
36+ /** 统一 UA */
37+ function getUA ( ) {
38+ return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
39+ }
40+
41+ /** 统一请求头 */
42+ function getHeaders ( ) {
43+ return {
44+ Referer : appConfig . webSite ,
45+ 'User-Agent' : getUA ( ) ,
46+ }
47+ }
48+
49+ /**
50+ * 异步获取分类列表的方法。
51+ * @param {UZArgs } args
52+ * @returns {@Promise<JSON.stringify(new RepVideoClassList())> }
53+ */
54+ async function getClassList ( args ) {
55+ var backData = new RepVideoClassList ( )
56+ try {
57+ backData . data = [
58+ { type_id : '1' , type_name : '电影' , hasSubclass : false } ,
59+ { type_id : '2' , type_name : '剧集' , hasSubclass : false } ,
60+ { type_id : '3' , type_name : '综艺' , hasSubclass : false } ,
61+ { type_id : '4' , type_name : '动漫' , hasSubclass : false } ,
62+ ]
63+ } catch ( error ) {
64+ backData . error = error . toString ( )
65+ }
66+ return JSON . stringify ( backData )
67+ }
68+
69+ /**
70+ * 获取二级分类列表筛选列表的方法。
71+ * @param {UZArgs } args
72+ * @returns {@Promise<JSON.stringify(new RepVideoSubclassList())> }
73+ */
74+ async function getSubclassList ( args ) {
75+ var backData = new RepVideoSubclassList ( )
76+ try {
77+ } catch ( error ) {
78+ backData . error = error . toString ( )
79+ }
80+ return JSON . stringify ( backData )
81+ }
82+
83+ /**
84+ * 获取分类视频列表
85+ * @param {UZArgs } args
86+ * @returns {@Promise<JSON.stringify(new RepVideoList())> }
87+ */
88+ async function getVideoList ( args ) {
89+ var backData = new RepVideoList ( )
90+ try {
91+ const url = `${ appConfig . webSite } /type/${ args . url } -${ args . page || 1 } .html`
92+
93+ const response = await req ( url )
94+ const $ = cheerio . load ( response . data )
95+
96+ $ ( '.stui-vodlist li' ) . each ( ( _ , element ) => {
97+ const video = new VideoDetail ( )
98+
99+ const $link = $ ( element ) . find ( 'a' ) . first ( )
100+ // 提取视频ID
101+ video . vod_id = ( $link . attr ( 'href' ) ) . match ( / \/ d e t a i l \/ ( \d + ) \. h t m l / i) ?. [ 1 ]
102+ // 视频名称
103+ video . vod_name = $link . attr ( 'title' )
104+ // 封面图片
105+ video . vod_pic = $link . attr ( 'data-original' )
106+ // 状态信息
107+ video . vod_remarks = $link . find ( '.pic-text' ) . first ( ) . text ( )
108+ // 评分信息
109+ const scores = $link . find ( '.pic-tag' ) . first ( ) . text ( )
110+ if ( scores !== '0.0' ) {
111+ video . topRightRemarks = '豆瓣 ' + scores
112+ video . vod_douban_score = '豆瓣 ' + scores
113+ }
114+
115+ backData . data . push ( video )
116+ } )
117+ } catch ( error ) {
118+ backData . error = error . toString ( )
119+ }
120+ return JSON . stringify ( backData )
121+ }
122+
123+ /**
124+ * 获取二级分类视频列表 或 筛选视频列表
125+ * @param {UZSubclassVideoListArgs } args
126+ * @returns {@Promise<JSON.stringify(new RepVideoList())> }
127+ */
128+ async function getSubclassVideoList ( args ) {
129+ var backData = new RepVideoList ( )
130+ try {
131+ } catch ( error ) {
132+ backData . error = error . toString ( )
133+ }
134+ return JSON . stringify ( backData )
135+ }
136+
137+ /**
138+ * 获取视频详情
139+ * @param {UZArgs } args
140+ * @returns {@Promise<JSON.stringify(new RepVideoDetail())> }
141+ */
142+ async function getVideoDetail ( args ) {
143+ var backData = new RepVideoDetail ( )
144+ try {
145+ const url = `${ appConfig . webSite } /detail/${ args . url } .html`
146+
147+ const response = await req ( url )
148+ const $ = cheerio . load ( response . data )
149+
150+ const video = new VideoDetail ( )
151+ // 提取视频ID
152+ video . vod_id = args . url
153+ // 视频名称
154+ vodName = $ ( 'h1.title' ) . text ( )
155+ if ( vodName ) {
156+ video . vod_name = vodName
157+ } else {
158+ throw new Error ( '请刷新重试' )
159+ }
160+
161+ // 封面图片
162+ video . vod_pic = $ ( 'img.lazyload' ) . attr ( 'data-original' ) || $ ( 'img.lazyload' ) . attr ( 'src' )
163+ // 视频简介
164+ video . vod_content = $ ( '.detail-content' ) . text ( )
165+
166+
167+ const playFromList = [ ]
168+ const playUrlList = [ ]
169+ const panUrls = [ ]
170+
171+ $ ( '.playlist-panel' ) . each ( ( _ , panel ) => {
172+ const $panel = $ ( panel )
173+ // 获取普通播放线路名字
174+ const rawName = $panel . find ( '.panel-head h3' ) . first ( ) . text ( )
175+
176+ // 获取普通播放线路:ul li a
177+ const episodes = [ ]
178+ $panel . find ( 'ul li a' ) . each ( ( __ , a ) => {
179+ const epName = $ ( a ) . text ( )
180+ const href = $ ( a ) . attr ( 'href' )
181+ if ( epName && href ) episodes . push ( `${ epName } $${ href } ` )
182+ } )
183+
184+ if ( episodes . length > 0 ) {
185+ playFromList . push ( rawName )
186+ playUrlList . push ( episodes . join ( '#' ) )
187+ }
188+
189+ // 获取网盘线路:a.netdisk-item
190+ $panel . find ( 'a.netdisk-item' ) . each ( ( __ , a ) => {
191+ const href = $ ( a ) . attr ( 'href' )
192+ if ( href ) panUrls . push ( href )
193+ } )
194+ } )
195+
196+ video . panUrls = Array . from ( new Set ( panUrls ) )
197+ video . vod_play_from = playFromList . join ( '$$$' )
198+ video . vod_play_url = playUrlList . join ( '$$$' )
199+ backData . data = video
200+ } catch ( error ) {
201+ backData . error = error . toString ( )
202+ }
203+ return JSON . stringify ( backData )
204+ }
205+
206+ /**
207+ * 获取视频的播放地址
208+ * @param {UZArgs } args
209+ * @returns {@Promise<JSON.stringify(new RepVideoPlayUrl())> }
210+ */
211+ async function getVideoPlayUrl ( args ) {
212+ var backData = new RepVideoPlayUrl ( )
213+ try {
214+ // let webSite = appConfig.webSite
215+ // const inputUrl = (args.url).trim()
216+ const fullUrl = appConfig . webSite . replace ( / \/ $ / , '' ) + args . url
217+ const fromName = ( ( args . from || args . flag ) + '' ) . toUpperCase ( )
218+ const headers = getHeaders ( )
219+
220+ // 仅对BD5线路进行特殊处理
221+ if ( fromName . includes ( 'BD5' ) ) {
222+ const response = await req ( fullUrl , { headers } )
223+ const $ = cheerio . load ( response . data )
224+
225+ // 提取并解析player_aaaa
226+ const scriptContent = $ ( '.stui-player__video script' ) . first ( ) . html ( )
227+ const match = scriptContent . match ( / p l a y e r _ a a a a \s * = \s * ( \{ [ ^ } ] + \} ) / i)
228+
229+ let player = JSON . parse ( match [ 1 ] . trim ( ) )
230+
231+ const proxyUrl = `${ appConfig . webSite } /vid/plyr/vr2.php?url=${ encodeURIComponent ( player . url ) } &next=${ encodeURIComponent ( player . link_next ) } &id=${ encodeURIComponent ( player . id ) } &nid=${ encodeURIComponent ( player . nid ) } `
232+ const proxyResp = await req ( proxyUrl , { headers } )
233+
234+ let finalUrl = player . url
235+ for ( const name of [ 'urls' , 'url' , 'vid' ] ) {
236+ const m = ( proxyResp . data ) . match ( new RegExp ( `(?:var|let|const)\\s+${ name } \\s*=\\s*["']([^"']+)["']` , 'i' ) )
237+ if ( m ?. [ 1 ] ) {
238+ finalUrl = m [ 1 ] . replace ( / \\ \/ / g, '/' ) . replace ( / \\ \\ / g, '\\' )
239+ break
240+ }
241+ }
242+
243+ backData . url = finalUrl
244+ backData . headers = headers
245+ } else {
246+ // 其他线路使用嗅探
247+ backData . sniffer = {
248+ url : fullUrl ,
249+ ua : getUA ( ) ,
250+ timeOut : 15 ,
251+ retry : 2
252+ }
253+ backData . headers = getHeaders ( )
254+ }
255+ } catch ( error ) {
256+ backData . error = error . toString ( )
257+ }
258+ return JSON . stringify ( backData )
259+ }
260+
261+ /**
262+ * 搜索视频
263+ * @param {UZArgs } args
264+ * @returns {@Promise<JSON.stringify(new RepVideoList())> }
265+ */
266+ async function searchVideo ( args ) {
267+ var backData = new RepVideoList ( )
268+ try {
269+ const url = `${ appConfig . webSite } /search/${ encodeURIComponent ( args . searchWord ) } ----------${ args . page || 1 } ---.html`
270+
271+ const response = await req ( url )
272+ const $ = cheerio . load ( response . data )
273+
274+ $ ( '.stui-vodlist li' ) . each ( ( _ , element ) => {
275+ const video = new VideoDetail ( )
276+
277+ const $link = $ ( element ) . find ( 'a' ) . first ( )
278+ // 提取视频ID
279+ video . vod_id = ( $link . attr ( 'href' ) ) . match ( / \/ d e t a i l \/ ( \d + ) \. h t m l / i) ?. [ 1 ]
280+ // 视频名称
281+ video . vod_name = $link . attr ( 'title' )
282+ // 封面图片
283+ video . vod_pic = $link . attr ( 'data-original' )
284+ // 状态信息
285+ video . vod_remarks = $link . find ( '.pic-text' ) . first ( ) . text ( )
286+ // 评分信息
287+ const scores = $link . find ( '.pic-tag' ) . first ( ) . text ( )
288+ if ( scores !== '0.0' ) {
289+ video . topRightRemarks = '豆瓣 ' + scores
290+ video . vod_douban_score = '豆瓣 ' + scores
291+ }
292+
293+ backData . data . push ( video )
294+ } )
295+ } catch ( error ) {
296+ backData . error = error . toString ( )
297+ }
298+ return JSON . stringify ( backData )
299+ }
0 commit comments