|
| 1 | +/** |
| 2 | + * 已知问题: |
| 3 | + * [推荐]页面:'雷电模拟器'播放部份影片会出错,'播放器'改成'ijk' & '解码方式'改成'软解',即可正常播放 |
| 4 | + * 影视TV 超連結跳轉支持 |
| 5 | + * 影视TV 弹幕支持 |
| 6 | + * https://t.me/fongmi_offical/ |
| 7 | + * https://github.com/FongMi/Release/tree/main/apk |
| 8 | + * 皮皮虾DMBox 弹幕支持 |
| 9 | + * 设置 > 窗口预览 > 开启 |
| 10 | + * https://t.me/pipixiawerun |
| 11 | + * vod_area:'bilidanmu' |
| 12 | + * Cookie设置 |
| 13 | + * Cookie获取方法 https://ghproxy.net/https://raw.githubusercontent.com/UndCover/PyramidStore/main/list.md |
| 14 | + * Cookie设置方法1: DR-PY 后台管理界面 |
| 15 | + * CMS后台管理 > 设置中心 > 环境变量 > {"bili_cookie":"XXXXXXX","vmid":"XXXXXX"} > 保存 |
| 16 | + * Cookie设置方法2: 手动替换Cookie |
| 17 | + * 底下代码 headers的 |
| 18 | + * "Cookie":"$bili_cookie" |
| 19 | + * 手动替换为 |
| 20 | + * "Cookie":"将获取的Cookie黏贴在这" |
| 21 | + * 客户端长期Cookie设置教程: |
| 22 | + * 抓包哔哩手机端搜索access_key,取任意链接里的access_key和appkey在drpy环境变量中增加同名的环境变量即可 |
| 23 | + * 此时哔哩.js这个解析可用于此源的解析线路用 |
| 24 | + * 传参 ?render=1&type=url¶ms=../json/哔哩收藏.json@哔哩收藏[官] |
| 25 | + * 获取收藏 /x/v3/fav/resource/list?media_id=1145063440&pn=1&ps=20&keyword= |
| 26 | + * 用户可以通过PC端获取公开收藏夹配置,实现个人收藏夹视频播放 |
| 27 | + */ |
| 28 | +var rule = { |
| 29 | + title: '哔哩收藏[官]', |
| 30 | + host: 'https://api.bilibili.com', |
| 31 | + homeUrl: '/x/web-interface/ranking/v2?rid=0&type=origin', |
| 32 | + url: '/x/v3/fav/resource/list?media_id=fyclass&pn=fypage&ps=20&keyword=', |
| 33 | + // filter_url: 'keyword=fyclass{{fl.tid}}&page=fypage&duration={{fl.duration}}&order={{fl.order}}', |
| 34 | + class_parse: async function () { |
| 35 | + // // let html = request('{{host}}/files/json/哔哩教育.json'); |
| 36 | + // let up_mid = "503852483"; |
| 37 | + // // 获取收藏 |
| 38 | + // let collectionUrl = "https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid=503852483"; |
| 39 | + // let collectionData = JSON.parse(await request(collectionUrl)).data; |
| 40 | + // // 获取订阅 |
| 41 | + // let subscribeUrl = "https://api.bilibili.com/x/v3/fav/folder/collected/list?pn=1&ps=20&up_mid=503852483&platform=web"; |
| 42 | + // let subscribeData = JSON.parse(await request(subscribeUrl)).data; |
| 43 | + // console.log(11111111,collectionData,subscribeData) |
| 44 | + let html = await request(rule.params); |
| 45 | + let json = dealJson(html); |
| 46 | + let classes = json.classes; |
| 47 | + return { |
| 48 | + class: classes, |
| 49 | + } |
| 50 | + }, |
| 51 | + filterable: 1, |
| 52 | + detailUrl: '/x/web-interface/view/detail?aid=fyid', |
| 53 | + searchUrl: '/x/web-interface/search/type?search_type=video&keyword=**&page=fypage', |
| 54 | + searchable: 2, |
| 55 | + quickSearch: 0, |
| 56 | + // params: '?render=1&type=url¶ms=../json/哔哩教育.json@哔哩教育[官]', |
| 57 | + // params: '?render=1&type=url¶ms=../json/哔哩大全.json@哔哩大全[官]', |
| 58 | + headers: { |
| 59 | + "User-Agent": "PC_UA", |
| 60 | + "Referer": "https://www.bilibili.com", |
| 61 | + "Cookie": "buvid3=666" |
| 62 | + }, |
| 63 | + timeout: 5000, |
| 64 | + limit: 8, |
| 65 | + play_parse: true, |
| 66 | + double: false, |
| 67 | + lazy: async function () { |
| 68 | + let {input} = this; |
| 69 | + let ids = input.split('_'); |
| 70 | + let dan = 'https://api.bilibili.com/x/v1/dm/list.so?oid=' + ids[1]; |
| 71 | + let result = {}; |
| 72 | + let iurl = 'https://api.bilibili.com:443/x/player/playurl?avid=' + ids[0] + '&cid=' + ids[1] + '&qn=116'; |
| 73 | + let html = await request(iurl); |
| 74 | + let jRoot = JSON.parse(html); |
| 75 | + let jo = jRoot.data; |
| 76 | + let ja = jo.durl; |
| 77 | + let maxSize = -1; |
| 78 | + let position = -1; |
| 79 | + ja.forEach(function (tmpJo, i) { |
| 80 | + if (maxSize < Number(tmpJo.size)) { |
| 81 | + maxSize = Number(tmpJo.size); |
| 82 | + position = i |
| 83 | + } |
| 84 | + }); |
| 85 | + let purl = ''; |
| 86 | + if (ja.length > 0) { |
| 87 | + if (position === -1) { |
| 88 | + position = 0 |
| 89 | + } |
| 90 | + purl = ja[position].url |
| 91 | + } |
| 92 | + result.parse = 0; |
| 93 | + result.playUrl = ''; |
| 94 | + result.url = unescape(purl); |
| 95 | + result.header = { |
| 96 | + 'Referer': 'https://live.bilibili.com', |
| 97 | + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' |
| 98 | + }; |
| 99 | + if (/\\.flv/.test(purl)) { |
| 100 | + result.contentType = 'video/x-flv'; |
| 101 | + } else { |
| 102 | + result.contentType = ''; |
| 103 | + } |
| 104 | + result.danmaku = dan; |
| 105 | + return result |
| 106 | + }, |
| 107 | + 一级: async function () { |
| 108 | + let {input, MY_CATE, MY_PAGE} = this; |
| 109 | + if (MY_CATE.endsWith('_clicklink')) { |
| 110 | + MY_CATE = MY_CATE.split('_')[0]; |
| 111 | + input = rule.host + '/x/web-interface/search/type?search_type=video&keyword=' + MY_CATE + '&page=' + MY_PAGE; |
| 112 | + } |
| 113 | + let data = []; |
| 114 | + let vodList = []; |
| 115 | + |
| 116 | + data = JSON.parse(await request(input)).data; |
| 117 | + vodList = data.medias; |
| 118 | + |
| 119 | + let videos = []; |
| 120 | + vodList.forEach(function (vod) { |
| 121 | + let aid = vod.aid ? vod.aid : vod.id; |
| 122 | + let title = misc.stripHtmlTag(vod.title); |
| 123 | + let img = vod.cover; |
| 124 | + if (img.startsWith('//')) { |
| 125 | + img = 'https:' + img; |
| 126 | + } |
| 127 | + let play = ''; |
| 128 | + let danmaku = ''; |
| 129 | + |
| 130 | + play = ConvertNum(vod.play); |
| 131 | + danmaku = vod.video_review; |
| 132 | + |
| 133 | + let remark = turnDHM(vod.duration) + ' ▶' + play + ' 💬' + danmaku; |
| 134 | + videos.push({ |
| 135 | + vod_id: aid, |
| 136 | + vod_name: title, |
| 137 | + vod_pic: img, |
| 138 | + vod_remarks: remark |
| 139 | + }) |
| 140 | + }); |
| 141 | + return videos |
| 142 | + }, |
| 143 | + 二级: async function () { |
| 144 | + let {input} = this; |
| 145 | + let html = await request(input); |
| 146 | + let jo = JSON.parse(html).data.View; |
| 147 | + // 历史记录 |
| 148 | + let cookies = rule.headers.Cookie.split(';'); |
| 149 | + let bili_jct = ''; |
| 150 | + cookies.forEach(cookie => { |
| 151 | + if (cookie.includes('bili_jct')) { |
| 152 | + bili_jct = cookie.split('=')[1]; |
| 153 | + } |
| 154 | + }); |
| 155 | + if (bili_jct !== '') { |
| 156 | + let historyReport = 'https://api.bilibili.com/x/v2/history/report'; |
| 157 | + let dataPost = { |
| 158 | + aid: jo.aid, |
| 159 | + cid: jo.cid, |
| 160 | + csrf: bili_jct, |
| 161 | + }; |
| 162 | + await post(historyReport, dataPost, 'form'); |
| 163 | + } |
| 164 | + |
| 165 | + let stat = jo.stat; |
| 166 | + let up_info = JSON.parse(html).data.Card; |
| 167 | + let relation = up_info.following ? '已关注' : '未关注'; |
| 168 | + let aid = jo.aid; |
| 169 | + let title = misc.stripHtmlTag(jo.title); |
| 170 | + let pic = jo.pic; |
| 171 | + let desc = jo.desc; |
| 172 | + |
| 173 | + let date = new Date(jo.pubdate * 1000); |
| 174 | + let yy = date.getFullYear().toString(); |
| 175 | + let mm = date.getMonth() + 1; |
| 176 | + mm = mm < 10 ? ('0' + mm) : mm; |
| 177 | + let dd = date.getDate(); |
| 178 | + dd = dd < 10 ? ('0' + dd) : dd; |
| 179 | + |
| 180 | + let up_name = jo.owner.name; |
| 181 | + let typeName = jo.tname; |
| 182 | + // let remark = jo.duration; |
| 183 | + let vod = { |
| 184 | + vod_id: aid, |
| 185 | + vod_name: title, |
| 186 | + vod_pic: pic, |
| 187 | + type_name: typeName, |
| 188 | + vod_year: yy + mm + dd, |
| 189 | + vod_area: 'bilidanmu', |
| 190 | + // vod_remarks: remark, |
| 191 | + vod_tags: 'mv', |
| 192 | + // vod_director: '🆙 ' + up_name + ' 👥 ' + up_info.follower + ' ' + relation, |
| 193 | + vod_director: '🆙 ' + '[a=cr:' + JSON.stringify({ |
| 194 | + 'id': up_name + '_clicklink', |
| 195 | + 'name': up_name |
| 196 | + }) + '/]' + up_name + '[/a]' + ' 👥 ' + up_info.follower + ' ' + relation, |
| 197 | + vod_actor: '▶' + stat.view + ' ' + '💬' + stat.danmaku + ' ' + '👍' + stat.like + ' ' + '💰' + stat.coin + ' ' + '⭐' + stat.favorite, |
| 198 | + vod_content: desc |
| 199 | + }; |
| 200 | + let ja = jo.pages; |
| 201 | + let treeMap = {}; |
| 202 | + let playurls = []; |
| 203 | + ja.forEach(function (tmpJo) { |
| 204 | + let cid = tmpJo.cid; |
| 205 | + let part = tmpJo.part.replaceAll('#', '﹟').replaceAll('$', '﹩'); |
| 206 | + playurls.push( |
| 207 | + part + '$' + aid + '_' + cid |
| 208 | + ) |
| 209 | + }); |
| 210 | + treeMap['B站'] = playurls.join('#'); |
| 211 | + let relatedData = JSON.parse(html).data.Related; |
| 212 | + playurls = []; |
| 213 | + relatedData.forEach(function (rd) { |
| 214 | + let ccid = rd.cid; |
| 215 | + let title = rd.title.replaceAll('#', '﹟').replaceAll('$', '﹩'); |
| 216 | + let aaid = rd.aid; |
| 217 | + playurls.push( |
| 218 | + title + '$' + aaid + '_' + ccid |
| 219 | + ) |
| 220 | + }); |
| 221 | + treeMap['相关推荐'] = playurls.join('#'); |
| 222 | + vod.vod_play_from = Object.keys(treeMap).join("$$$"); |
| 223 | + vod.vod_play_url = Object.values(treeMap).join("$$$"); |
| 224 | + return vod; |
| 225 | + }, |
| 226 | + 搜索: async function () { |
| 227 | + let {input} = this; |
| 228 | + let html = await request(input); |
| 229 | + let videos = []; |
| 230 | + let vodList = JSON.parse(html).data.result; |
| 231 | + vodList.forEach(function (vod) { |
| 232 | + let aid = vod.aid; |
| 233 | + let title = misc.stripHtmlTag(vod.title); |
| 234 | + let img = vod.pic; |
| 235 | + if (img.startsWith('//')) { |
| 236 | + img = 'https:' + img; |
| 237 | + } |
| 238 | + let remark = turnDHM(vod.duration); |
| 239 | + videos.push({ |
| 240 | + vod_id: aid, |
| 241 | + vod_name: title, |
| 242 | + vod_pic: img, |
| 243 | + vod_remarks: remark |
| 244 | + }) |
| 245 | + }); |
| 246 | + return videos; |
| 247 | + }, |
| 248 | +} |
| 249 | + |
| 250 | + |
| 251 | +function turnDHM(duration) { |
| 252 | + let min = ''; |
| 253 | + let sec = ''; |
| 254 | + try { |
| 255 | + min = duration.split(':')[0]; |
| 256 | + sec = duration.split(':')[1]; |
| 257 | + } catch (e) { |
| 258 | + min = Math.floor(duration / 60); |
| 259 | + sec = duration % 60; |
| 260 | + } |
| 261 | + if (isNaN(parseInt(duration))) { |
| 262 | + return '无效输入'; |
| 263 | + } |
| 264 | + if (min == 0) { |
| 265 | + return sec + '秒' |
| 266 | + } else if (0 < min && min < 60) { |
| 267 | + return min + '分' |
| 268 | + } else if (60 <= min && min < 1440) { |
| 269 | + if (min % 60 == 0) { |
| 270 | + let h = min / 60; |
| 271 | + return h + '小时' |
| 272 | + } else { |
| 273 | + let h = min / 60; |
| 274 | + h = (h + '').split('.')[0]; |
| 275 | + let m = min % 60; |
| 276 | + return h + '小时' + m + '分'; |
| 277 | + } |
| 278 | + } else if (min >= 1440) { |
| 279 | + let d = min / 60 / 24; |
| 280 | + d = (d + '').split('.')[0]; |
| 281 | + let h = min / 60 % 24; |
| 282 | + h = (h + '').split('.')[0]; |
| 283 | + let m = min % 60; |
| 284 | + let dhm = ''; |
| 285 | + if (d > 0) { |
| 286 | + dhm = d + '天' |
| 287 | + } |
| 288 | + if (h >= 1) { |
| 289 | + dhm = dhm + h + '小时' |
| 290 | + } |
| 291 | + if (m > 0) { |
| 292 | + dhm = dhm + m + '分' |
| 293 | + } |
| 294 | + return dhm |
| 295 | + } |
| 296 | + return null |
| 297 | +} |
| 298 | + |
| 299 | +function ConvertNum(num) { |
| 300 | + let _ws = Math.pow(10, 1); |
| 301 | + let _b = 1e4; |
| 302 | + if (num < _b) { |
| 303 | + return num.toString(); |
| 304 | + } |
| 305 | + let _r = ''; |
| 306 | + let _strArg = ['', '万', '亿', '万亿']; |
| 307 | + let _i = Math.floor(Math.log(num) / Math.log(_b)); |
| 308 | + if (_i > 3) { |
| 309 | + _i = 3; |
| 310 | + } |
| 311 | + _r = Math.floor(num / Math.pow(_b, _i) * _ws) / _ws + _strArg[_i]; |
| 312 | + return _r; |
| 313 | +} |
0 commit comments