import { distance } from "./mod.js"; import { sortListByCN } from "./sortName.js"; import cheerio from "assets://js/lib/cheerio.min.js" String.prototype.rstrip = function(chars) { let regex = new RegExp(chars + "$"); return this.replace(regex, "") }; var showMode = "single"; var searchDriver = ""; var search_type = ""; var detail_order = "name"; var __poster_mode = true; var __filter_data = null; let __imageServer = "https://" let __imageSource = '@Referer=https://api.douban.com/@User-Agent=Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/113.0.0.0%20Safari/537.36'; const __folder_img = "https://pic.616pic.com/ys_bnew_img/00/46/91/Kduke9oSev.jpg"; const __play_list_img = "https://pic.616pic.com/ys_bnew_img/00/24/42/xp3ozLGSm4.jpg"; const __num = "200"; const request_timeout = 10000; const VERSION = "alist v2/v3 202402020830"; function print(any) { any = any || ""; if (typeof any == "object" && Object.keys(any).length > 0) { try { any = JSON.stringify(any); console.log(any) } catch (e) { console.log(typeof any + ":" + any.length) } } else if (typeof any == "object" && Object.keys(any).length < 1) { console.log("null object") } else { console.log(any) } } const http = function(url, options = {},noAuth = false,timeout = request_timeout) { if (options.method === "POST" && options.data) { options.body = JSON.stringify(options.data); options.headers = Object.assign({ "content-type": "application/json" }, options.headers); if (!noAuth){ options.headers = Object.assign({ 'Authorization': 'alist-09ceb38a-f143-47f7-b255-c3eec819cd7b8RfQ6P4fxESnlox2sKdJQqlPfDrWzbgSOIqyFAmIlHmUFrcQ97CSr5yoGA5wkw70' }, options.headers); } } options.timeout = timeout; try { const res = req(url, options); res.json = () => res && res.content ? JSON.parse(res.content) : null; res.text = () => res && res.content ? res.content : ""; return res } catch (e) { return { json() { return null }, text() { return "" } } } }; ["get", "post"].forEach(method => { http[method] = function(url, options = {},noAuth = false,timeout = request_timeout) { return http(url, Object.assign(options, { method: method.toUpperCase() }),noAuth,timeout) } }); const __drives = {}; function isMedia(file) { return /\.(dff|dsf|mp3|aac|wav|wma|cda|flac|m4a|mid|mka|mp2|mpa|mpc|ape|ofr|ogg|ra|wv|tta|ac3|dts|tak|webm|wmv|mpeg|mov|ram|swf|mp4|avi|rm|rmvb|flv|mpg|mkv|m3u8|ts|3gp|asf)$/.test(file.toLowerCase()) } function get_drives_path(tid) { const index = tid.indexOf("$"); const name = tid.substring(0, index); const path = tid.substring(index + 1); return { drives: get_drives(name), path: path } } function get_drives(name) { const { settings, api, server } = __drives[name]; if (settings.v3 == null) { settings.title = "小雅的分类 Alist"; settings.v3 = true; settings.version = "小雅魔改版"; settings.enableSearch = false api.path = settings.v3 ? "/api/fs/list" : "/api/public/path"; api.file = settings.v3 ? "/api/fs/get" : "/api/public/path"; api.search = settings.v3 ? "/api/public/search" : "/api/public/search" } return __drives[name] } function init(ext) { console.log("当前版本号:" + VERSION); let data; if (typeof ext == "object") { data = ext; print("alist ext:object") } else if (typeof ext == "string") { if (ext.startsWith("http")) { let alist_data = ext.split(";"); let alist_data_url = alist_data[0]; search_type = alist_data.length > 2 ? alist_data[2] : search_type; print(alist_data_url); data = http.get(alist_data_url).json() } else { print("alist ext:json string"); data = JSON.parse(ext) } } let drives = []; if (Array.isArray(data) && data.length > 0 && data[0].hasOwnProperty("server") && data[0].hasOwnProperty("name")) { drives = data } else if (!Array.isArray(data) && data.hasOwnProperty("drives") && Array.isArray(data.drives)) { drives = data.drives.filter(it => it.type && it.type === "alist" || !it.type) } print(drives); __poster_mode = true; searchDriver = (drives.find(x => x.search) || {}).name || ""; if (!searchDriver && drives.length > 0) { searchDriver = drives[0].name __poster_mode = false; } print(searchDriver); drives.forEach(item => { let _path_param = []; if (item.params) { _path_param = Object.keys(item.params); _path_param.sort((a, b) => a.length - b.length) } let servers = item.server.split(";"); servers.forEach((server, index, array) => { array[index] = server.replace(/\/$/, ''); }); let server = servers[0]; __drives[item.name] = { name: item.name, server: server, servers: servers, startPage: item.startPage || "/", showAll: item.showAll === true, search: !!item.search, noAuth: !!item.noAuth, noPoster: !!item.noPoster, pathByApi: !!item.pathByApi, isPreview: !!item.isPreview, params: item.params || {}, _path_param: _path_param, settings: {}, api: {}, isFullList: false, getParams(path) { const key = this._path_param.find(x => path.startsWith(x)); return Object.assign({}, this.params[key], { path: path }) }, getPath(path) { try { const res = http.post(this.server + this.api.path, { data: this.getParams(path) }, this.noAuth,5000); return this.settings.v3 ? res.json().data.content : res.json().data.files; } catch (error) { } for (const server of this.servers) { try { if (server !== this.server) { const res = http.post(server + this.api.path, { data: this.getParams(path) }, this.noAuth,5000); this.server = server; return this.settings.v3 ? res.json().data.content : res.json().data.files; } } catch (error) { } } return null; }, getFile(path) { let raw_url = this.server + "/d" + path; raw_url = encodeURI(raw_url); let previewSuccess = false; try { if (isMedia(path) && this.isPreview) { const res = http.post(this.server + "/api/fs/other", { data: Object.assign({},this.getParams(path),{method: "video_preview"}) }).json(); let urls = res.data.video_preview_play_info.live_transcoding_task_list; raw_url = urls[urls.length-1].url; previewSuccess = true; } } catch(e) { previewSuccess = false; raw_url = this.server + "/d" + path; raw_url = encodeURI(raw_url); } if (!previewSuccess && this.pathByApi) { const res = http.post(this.server + "/api/fs/get", { data: this.getParams(path) }, this.noAuth).json(); raw_url = res.data.raw_url; } return { raw_url: raw_url } }, isFolder(data) { return data.type === 1 }, isVideo(data) { return this.settings.v3 ? data.type === 2 || data.type === 0 || data.type === 3 : data.type === 3 || data.type === 0 || data.type === 4 }, is_subt(data) { if (data.type === 1) { return false } const ext = /\.(srt|ass|scc|stl|ttml)$/; return ext.test(data.name) }, getPic(data) { let pic = this.settings.v3 ? data.thumb : data.thumbnail; return pic || (this.isFolder(data) ? __folder_img : "") }, getTime(data, isStandard) { isStandard = isStandard || false; try { let tTime = data.updated_at || data.time_str || data.modified || ""; let date = ""; if (tTime) { tTime = tTime.split("T"); date = tTime[0]; if (isStandard) { date = date.replace(/-/g, "/") } tTime = tTime[1].split(/Z|\./); date += " " + tTime[0] } return date } catch (e) { return "" } } } }); //__imageServer = __drives[searchDriver].server + "/image/"; try { __filter_data = http.get(__drives[searchDriver].server + "/tvbox/json/alist.filters.json").json().startPages; }catch(e) { __filter_data = null; } print("init执行完毕") } function genFilters(tid){ let { drives, path } = get_drives_path(tid); if (!__poster_mode || drives.noPoster) { return []; } let values = [{ n: "全部分类", v: "all" }]; try { var data = __filter_data; data = data.find(it => it.startPage === path).names; data.forEach(item => { let subpath = item; values.push({ n: subpath, v: subpath }); }); } catch (e){ const list = drives.getPath(path); list.forEach(item => { if (drives.isFolder(item)) { let subpath = item.name; values.push({ n: subpath, v: subpath }); } }); } let filters = [{ key: "subpath", name: "分类:", value: values },{ key: "douban", name: "豆瓣评分:", value: [{ n: "全部评分", v: "0" },{ n: "9分以上", v: "9" },{ n: "8分以上", v: "8" },{ n: "7分以上", v: "7" },{ n: "6分以上", v: "6" },{ n: "5分以上", v: "5" }] },{ key: "doubansort", name: "豆瓣排序:", value: [{ n: "原始顺序", v: "0" },{ n: "豆瓣评分⬇️", v: "1" },{ n: "豆瓣评分⬆️", v: "2" }] },{ key: "random", name: "随机显示:", value: [{ n: "固定显示", v: "0" },{ n: "随机显示️", v: "9999999999" },{ n: "随机200个️", v: "200" },{ n: "随机500个️", v: "500" }] }]; return filters; } function home(filter) { let classes = Object.keys(__drives).map(key => ({ type_id: `${key}$${__drives[key].startPage}`, type_name: key, type_flag: __drives[key].startPage === "/" || !__poster_mode || __drives[key].noPoster? "1" : "2" })); let filter_dict = {}; classes.forEach(it => { filter_dict[it.type_id] = genFilters(it.type_id); }); print("----home----"); print(classes); return JSON.stringify({ class: classes, filters: filter_dict }) } function homeVod(params) { if (!searchDriver) { return JSON.stringify({ list: [] }) } else { let driver = __drives[searchDriver]; driver.vods = getAllVods("filter=last&num=" + __num,driver.name).list; return JSON.stringify({ list: driver.vods }); } } function parseSou(htmlContent){ const regex = /]*)>/g; let matches = []; let match; while ((match = regex.exec(htmlContent)) !== null) { if (match[1] === "/" || match[1] === "https://t.me/xiaoyaliu"){ continue; } matches.push(match[1]); } return matches; } function getAllVods (para,drivename,pg = "0",filter = false,extend={}) { let driver = __drives[drivename]; let orgdrive = __drives[drivename]; let surl = driver.server + "/sou?" + para + "&type=video&num=" + __num; let fl = filter ? extend : {}; let isflmode = !!fl.subpath || !!fl.doubansort || !!fl.douban || !!fl.random; let fullList = false; pg = parseInt(pg); if (!pg || pg > 1 || isflmode){ surl = driver.server + "/sou?" + para + "&type=video"; fullList = true; } if (pg === 1 && !isflmode && orgdrive.name === "每日更新") { surl = driver.server + "/sou?filter=last&num=" + __num + "&type=video"; } if (orgdrive.startPage !== "/"){ if (orgdrive.isFullList || (!fullList && orgdrive.vods != null)){ return { list: orgdrive.vods }; } } else { orgdrive.isFullList = true; } let html = http.get(surl).text(); let lists = parseSou(html); let vods = []; let vods_pikpak = []; let vods_ali = []; let excludeReg = /\.(pdf|epub|mobi|txt|doc|lrc)$/; let pikpakRegex = /pikpak/; let cnt = 0; lists.forEach(it => { let isPikpak = false; let vhref = it; if (vhref) { vhref = unescape(vhref) } if (excludeReg.test(vhref.toLowerCase())) { return } if (pikpakRegex.test(vhref.toLowerCase())) { isPikpak = true; } const parts = vhref.split('#') if (parts.length >= 2) { vhref = parts[0] } cnt++; let vid = __drives[drivename].name + "$" + vhref + "#search#"; if (showMode === "all") { vid += "#all#" } let have_pic = 0; let vod_dbid = ""; let poster = ''; let douban_rate = ''; let display_path = ''; if (parts.length === 5) { let uri_parts = parts[4].split('://') poster = __imageServer + uri_parts[1] + __imageSource; have_pic = 1; } else{ // return } if (parts.length >= 4) { douban_rate = parts[3] ; } if (parts.length >= 3) { vod_dbid = parts[2] ; } if (parts.length < 2) { let path_list = parts[0].split('/'); //display_path = path_list[path_list.length - 2] + '/' + path_list[path_list.length - 1]; display_path = path_list[path_list.length - 1]; } vods = vods_ali; if (isPikpak){ vods = vods_pikpak; } vods.push({ vod_id: vid, vod_dbid: vod_dbid, vod_name: parts.length <2 ? display_path :parts[1], vod_tag: "file", vod_pic: have_pic ? poster : "http://img.xiaoya.pro/xiaoya.jpg", vod_remarks: douban_rate == '' ? "" : "豆瓣:" + douban_rate, vod_fullpath: parts[0], vod_poster: have_pic }); }); vods = vods_ali.concat(vods_pikpak); if (!orgdrive.isFullList){ orgdrive.isFullList = fullList; } let vods_poster = vods.filter(it => it.vod_poster); let vods_none_poster = vods.filter(it => !it.vod_poster); vods = vods_poster.concat(vods_none_poster); orgdrive.vods = vods; return { list: vods } } function removeDuplicates(arr) { const seen = new Set(); return arr.filter((item) => { const itemString = JSON.stringify(item); if (!seen.has(itemString)) { seen.add(itemString); return true; } return false; }); } function root_category(tid, pg, filter, extend) { let vods = []; let orid = tid.replace(/#all#|#search#/g, ""); let { drives, path } = get_drives_path(orid); drives.vods = getAllVods("box=" + path,drives.name,pg,filter,extend).list let fullpath = path; let fl = filter ? extend : {}; if(fl.subpath && fl.subpath !== "all"){ fullpath = path + "/" + fl.subpath; } drives.vods.forEach(it => { const pattern = new RegExp("^" + fullpath); if (!pattern.test(it.vod_fullpath)) { return } vods.push(it); }); let douban = 0; if(fl.douban){ douban = parseFloat(fl.douban); } let highRatedVods = vods.filter(vod => { var ratingString = vod.vod_remarks.replace("豆瓣:", "").trim(); if (ratingString === ""){ ratingString="0"; } return ratingString !== '' && parseFloat(ratingString) >= douban; }); vods = highRatedVods; if(fl.doubansort && fl.doubansort === "1"){ vods.sort((a, b) => { const ratingA = parseFloat(a.vod_remarks.replace("豆瓣:", "").trim()) || 0; const ratingB = parseFloat(b.vod_remarks.replace("豆瓣:", "").trim()) || 0; return ratingB - ratingA; }); } if(fl.doubansort && fl.doubansort === "2"){ vods.sort((a, b) => { const ratingA = parseFloat(a.vod_remarks.replace("豆瓣:", "").trim()) || 0; const ratingB = parseFloat(b.vod_remarks.replace("豆瓣:", "").trim()) || 0; return ratingA - ratingB; }); } let random = 0; if(fl.random) { random = parseInt(fl.random); } if(random !== 0) { let keepsequence = (fl.doubansort && fl.doubansort !== "0"); vods = getRandomElements(vods,random,keepsequence); } return JSON.stringify({ page: 1, pagecount: drives.isFullList ? 1 : 2, //pagecount: 2, //limit: vods.length, //total: vods.length, list: vods }) } function getRandomElements(arr, count, keepsequence) { if (arr.length <= count) { if (keepsequence) { return arr.slice(); } else { const shuffledArray = arr.slice(); for (let i = shuffledArray.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]]; } return shuffledArray; } } const randomIndexes = []; const selectedIndexes = new Set(); while (randomIndexes.length < count) { const index = Math.floor(Math.random() * arr.length); if (!selectedIndexes.has(index)) { selectedIndexes.add(index); randomIndexes.push(index); } } if (keepsequence) { randomIndexes.sort((a, b) => a - b); } const result = randomIndexes.map(index => arr[index]); return result; } function category(tid, pg, filter, extend) { let orid = tid.replace(/#all#|#search#/g, ""); let { drives, path } = get_drives_path(orid); if ( __poster_mode && !drives.noPoster && path !=="/" && path === drives.startPage){ return root_category(tid, pg, filter, extend); } const id = orid.endsWith("/") ? orid : orid + "/"; let list = null; if (!filter && extend.list) { list = extend.list; }else { list = drives.getPath(path); } let subList = []; let vodFiles = []; let allList = []; let fl = filter ? extend : {}; if (fl.show) { showMode = fl.show } list.forEach(item => { if (drives.is_subt(item)) { subList.push(item.name) } if ( !drives.isFolder(item) && !/\.(dff|dsf|mp3|aac|wav|wma|cda|flac|m4a|mid|mka|mp2|mpa|mpc|ape|ofr|ogg|ra|wv|tta|ac3|dts|tak|webm|wmv|mpeg|mov|ram|swf|mp4|avi|rm|rmvb|flv|mpg|mkv|m3u8|ts|3gp|asf)$/.test(item.name)){ return } if (!drives.showAll && !drives.isFolder(item) && !drives.isVideo(item)) { return } let vod_time = drives.getTime(item); let vod_size = get_size(item.size); let remark = vod_time.split(" ")[0].substr(3) + "\t" + vod_size; let vod_id = id + item.name + (drives.isFolder(item) ? "/" : ""); if (showMode === "all") { vod_id += "#all#" } print(vod_id); const vod = { vod_id: vod_id, vod_name: item.name.replaceAll("$", "").replaceAll("#", ""), vod_pic: drives.getPic(item), vod_time: vod_time, vod_size: item.size, vod_tag: drives.isFolder(item) ? "folder" : "file", // vod_tag: "file", vod_remarks: drives.isFolder(item) ? remark + " 文件夹" : remark }; if (drives.isVideo(item)) { vodFiles.push(vod) } allList.push(vod) }); if (vodFiles.length === 1 && subList.length > 0) { let sub; if (subList.length === 1) { sub = subList[0] } else { let subs = JSON.parse(JSON.stringify(subList)); subs.sort((a, b) => { let a_similar = (a.includes("chs") ? 100 : 0) + levenshteinDistance(a, vodFiles[0].vod_name); let b_similar = (b.includes("chs") ? 100 : 0) + levenshteinDistance(b, vodFiles[0].vod_name); if (a_similar > b_similar) { return 1 } else { return -1 } }); sub = subs.slice(-1)[0] } vodFiles[0].vod_id += "@@@" + sub; vodFiles[0].vod_remarks += "🏷️" } else { vodFiles.forEach(item => { var lh = 0; let sub; subList.forEach(s => { const l = levenshteinDistance(s, item.vod_name); if (l > 60 && l > lh) { sub = s lh = l; } }); if (sub) { item.vod_id += "@@@" + sub; item.vod_remarks += "🏷️" } }) } if (fl.order) { let key = fl.order.split("_").slice(0, -1).join("_"); let order = fl.order.split("_").slice(-1)[0]; print(`排序key:${key},排序order:${order}`); if (key.includes("name")) { detail_order = "name"; allList = sortListByName(allList, key, order) } else if (key.includes("cn")) { detail_order = "cn"; allList = sortListByCN(allList, "vod_name", order) } else if (key.includes("time")) { detail_order = "time"; allList = sortListByTime(allList, key, order) } else if (key.includes("size")) { detail_order = "size"; allList = sortListBySize(allList, key, order) } else if (fl.order.includes("none")) { detail_order = "none"; print("不排序") } } else { if (detail_order !== "none") { allList = sortListByName(allList, "vod_name", "asc") } } if (pg && vodFiles.length > 1) { const vod = { vod_id: id + "~playlist", vod_name: "播放列表", vod_pic: __play_list_img, vod_tag: "file", vod_remarks: "共" + vodFiles.length + "集" }; allList.unshift(vod) } print("----category----" + `tid:${tid},detail_order:${detail_order},showMode:${showMode}`); return JSON.stringify({ page: 1, pagecount: 1, limit: allList.length, total: allList.length, list: allList }) } function getAll(otid, tid, drives, path,ls = null,nopic = false) { try { const content = category(tid, null, false, {list: ls}); const isFile = isMedia(otid.replace(/#all#|#search#/g, "").split("@@@")[0]); const { list } = JSON.parse(content); let vod_play_url = []; list.forEach(x => { if (x.vod_tag === "file") { let vid = x.vod_id.replace(/#all#|#search#/g, ""); vod_play_url.push(`${x.vod_name}$${drives.name}~~~${vid.substring(vid.indexOf("$")+1)}`) } }); const pl = path.split("/").filter(it => it); let vod_name = pl[pl.length - 1] || drives.name; if (vod_name === drives.name) { print(pl) } if (otid.includes("#search#")) { // vod_name += "[搜]" } let orvod = nopic ? null : findVodById(drives,tid); let vod_pic = orvod !== null ? orvod.vod_pic : "https://avatars.githubusercontent.com/u/97389433?s=120&v=4"; let vod = { vod_id: otid, vod_name: vod_name, type_name: "文件夹", vod_pic: vod_pic, vod_content: tid, vod_tag: isFile ? "file" : "folder", vod_play_from: drives.name, vod_play_url: vod_play_url.join("#"), vod_remarks: drives.settings.title }; print("----detail1----"); print(vod); return JSON.stringify({ list: [vod] }) } catch (e) { print(e.message); return JSON.stringify({ list: [{}] }) } } function playlist(otid, tid, drives, path) { tid = tid.replace('/~playlist', '') otid = otid.replace('/~playlist', '') path = path.replace('/~playlist', '') return getAll(otid, tid, drives, path) } function findVodById(drives, targetVodId) { targetVodId = targetVodId.replace(/#all#|#search#/g, ""); let foundVod = null; // 使用 Array.find 查找元素 if (drives !== null && drives.vods != null) { foundVod = drives.vods.find(vod => vod.vod_id.replace(/#all#|#search#/g, "") === targetVodId); } if (!foundVod) { try { const result = get_drives_path(targetVodId); let driver = drives; let path = result.path; let wd = "/"; const parts = path.split('/'); if (parts.length >1) { wd += parts[1]; } if (wd !== "/" && !drives.noPoster) { foundVod = getAllVods("box=" + wd,driver.name).list.find(vod =>{ let r = get_drives_path(vod.vod_id.replace(/#all#|#search#/g, "")); return path === r.path; }); } }catch(e) { foundVod = null; } } return foundVod || null; } function isPathFolder(path) { return !(/\.(dff|dsf|mp3|aac|wav|wma|cda|flac|m4a|mid|mka|mp2|mpa|mpc|ape|ofr|ogg|ra|wv|tta|ac3|dts|tak|webm|wmv|mpeg|mov|ram|swf|mp4|avi|rm|rmvb|flv|mpg|mkv|m3u8|ts|3gp|asf|nfo)$/.test(path.toLowerCase())); } function genFolderPlayList(drives,path,url,from) { let vod_play_url = url; let vod_play_from =from; let subFolderList = []; try { let list = drives.getPath(path); list.forEach(item => { if (!drives.isFolder(item)) { return } subFolderList.push(item.name) }); var searchurl = drives.name + "$" + path; var tempvod = getAll(searchurl + "#search#", searchurl, drives, "/" + path,list,true); if (JSON.parse(tempvod).list[0].vod_play_url != "") { vod_play_url = vod_play_url+"$$$"+JSON.parse(tempvod).list[0].vod_play_url; vod_play_from = vod_play_from+"$$$"+path.substring(path.lastIndexOf("/") + 1); } } catch(e) { vod_play_url = url; vod_play_from =from; } subFolderList.forEach(item => { const result = genFolderPlayList(drives,path + "/" + item,vod_play_url,vod_play_from); vod_play_url = result.vod_play_url; vod_play_from = result.vod_play_from; }); return { vod_play_url: vod_play_url, vod_play_from: vod_play_from }; } function getDoubanInfo(id) { try{ if (id === "") { return {}; } const url = "https://movie.douban.com/subject/" + id +"/"; let html = http.get(url).text(); const $ = cheerio.load(html); let plot = $('#link-report-intra span[property="v:summary"]').text().trim(); const yearElement = $('.year'); let year = yearElement.text().replace(/\(|\)/g, ''); let region = ""; var text = html; var regex = /制片国家\/地区:<\/span>[\s\n]*([^<]+)/; var match = text.match(regex); if (match && match[1]) { region = match[1].trim(); } const actorElements = $('meta[property^="video:actor"]'); let actors = actorElements.map((index, element) => { return $(element).attr('content'); }).get(); actors = actors.join('/'); const directorElement = $('meta[property="video:director"]'); const director = directorElement.attr('content'); const genreElement = $('span.pl:contains("类型:")'); const type = genreElement.nextAll('span[property="v:genre"]').map((index, element) => { return $(element).text(); }).get().join('/'); return { plot, year, region, actors, director, type }; }catch(e){ return {}; } } function getFolderVodDetail(tid){ let orid = tid.replace(/#all#|#search#/g, ""); let { drives, path } = get_drives_path(orid); if (!isPathFolder(path.toLowerCase())){ return ""; } if (path.endsWith("/~playlist")){ return ""; } let orvod = findVodById(drives,tid) ; let vod_pic = orvod !== null ? orvod.vod_pic : "https://avatars.githubusercontent.com/u/97389433?s=120&v=4"; let { vod_play_url, vod_play_from } = genFolderPlayList(drives,path,"",""); vod_play_from = vod_play_from.replace(/^[$]{3}/, ''); vod_play_url = vod_play_url.replace(/^[$]{3}/, ''); let doubanInfo = {}; let vod_name = path.substring(path.lastIndexOf("/") + 1); if (orvod) { vod_name = orvod.vod_name; doubanInfo = getDoubanInfo(orvod.vod_dbid); } let vod_content = doubanInfo.plot ? doubanInfo.plot + " \n\n文件路径:" + path : path; let vod = { vod_id: orid, vod_name: vod_name, type_name: doubanInfo.type, vod_pic: vod_pic, vod_content: vod_content, vod_actor: doubanInfo.actors, vod_area: doubanInfo.region, vod_director: doubanInfo.director, vod_year: doubanInfo.year, vod_play_from: vod_play_from, vod_play_url: vod_play_url, vod_remarks: drives.settings.title }; return JSON.stringify({ list: [vod] }) } function detail(tid) { let folderVod = getFolderVodDetail(tid.split("@@@")[0]); if (folderVod !== ""){ return folderVod; } let isSearch = tid.includes("#search#"); let isAll = tid.includes("#all#"); let otid = tid; tid = tid.replace(/#all#|#search#/g, ""); let isFile = isMedia(tid.split("@@@")[0]); print(`isFile:${tid}?${isFile}`); let { drives, path } = get_drives_path(tid); print(`drives:${drives},path:${path}`); if (path.endsWith("/")) { return getAll(otid, tid, drives, path) } else if (path.endsWith("/~playlist")) { return playlist(otid, tid, drives, path) } else { if (isSearch && !isFile) { return getAll(otid, tid, drives, path) } else if (isAll) { let new_tid; if (isFile) { new_tid = tid.split("/").slice(0, -1).join("/") + "/" } else { new_tid = tid } print(`全集模式 tid:${tid}=>tid:${new_tid}`); let { drives, path } = get_drives_path(new_tid); return getAll(otid, new_tid, drives, path) } else if (isFile) { let paths = path.split("@@@"); let orvod = findVodById(drives,tid); let vod_pic = orvod !== null ? orvod.vod_pic : "https://avatars.githubusercontent.com/u/97389433?s=120&v=4"; let doubanInfo = {}; let vod_name = paths[0].substring(paths[0].lastIndexOf("/") + 1); if (orvod) { vod_name = orvod.vod_name; doubanInfo = getDoubanInfo(orvod.vod_dbid); } let vod_content = doubanInfo.plot ? doubanInfo.plot + " \n\n文件路径:" + paths[0]: paths[0]; let vod = { vod_id: otid, vod_name: vod_name, type_name: doubanInfo.type, vod_pic: vod_pic, vod_content: vod_content, vod_actor: doubanInfo.actors, vod_area: doubanInfo.region, vod_director: doubanInfo.director, vod_year: doubanInfo.year, vod_play_from: drives.name, vod_play_url: vod_name + "$" + drives.name + "~~~" + path, vod_remarks: drives.settings.title }; print("----detail2----"); print(vod); return JSON.stringify({ list: [vod] }) } else { return JSON.stringify({ list: [] }) } } } function play(flag, id, flags) { if (__drives[flag]==null){ //flag = __drives[searchDriver].name; } let urls = id.split("@@@"); flag = urls[0].split("~~~")[0]; urls[0] = urls[0].split("~~~")[1]; const drives = get_drives(flag); let vod = { parse: 0, playUrl: "", url: drives.getFile(urls[0]).raw_url }; if (urls.length >= 2) { const path = urls[0].substring(0, urls[0].lastIndexOf("/") + 1); vod.subt = drives.getFile(path + urls[1]).raw_url } print("----play----"); print(vod); return JSON.stringify(vod) } function search(wd, quick) { print(__drives); print("可搜索的alist驱动:" + searchDriver); if (!searchDriver || !wd) { return JSON.stringify({ list: [] }) } else { let driver = __drives[searchDriver]; wd = wd.split(" ").filter(it => it.trim()).join("+"); print(driver); driver.vods = getAllVods("box=" + wd,driver.name).list; return JSON.stringify({ page: 1, pagecount: 1, list: driver.vods }); } } function get_size(sz) { if (sz <= 0) { return "" } let filesize = ""; if (sz > 1024 * 1024 * 1024 * 1024) { sz /= 1024 * 1024 * 1024 * 1024; filesize = "TB" } else if (sz > 1024 * 1024 * 1024) { sz /= 1024 * 1024 * 1024; filesize = "GB" } else if (sz > 1024 * 1024) { sz /= 1024 * 1024; filesize = "MB" } else if (sz > 1024) { sz /= 1024; filesize = "KB" } else { filesize = "B" } let sizeStr = sz.toFixed(2) + filesize, index = sizeStr.indexOf("."), dou = sizeStr.substr(index + 1, 2); if (dou === "00") { return sizeStr.substring(0, index) + sizeStr.substr(index + 3, 2) } else { return sizeStr } } function levenshteinDistance(str1, str2) { return 100 - 100 * distance(str1, str2) / Math.max(str1.length, str2.length) } function naturalSort(options) { if (!options) { options = {} } return function(a, b) { if (options.key) { a = a[options.key]; b = b[options.key] } var EQUAL = 0; var GREATER = options.order === "desc" ? -1 : 1; var SMALLER = -GREATER; var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi; var sre = /(^[ ]*|[ ]*$)/g; var dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/; var hre = /^0x[0-9a-f]+$/i; var ore = /^0/; var normalize = function normalize(value) { var string = "" + value; return options.caseSensitive ? string : string.toLowerCase() }; var x = normalize(a).replace(sre, "") || ""; var y = normalize(b).replace(sre, "") || ""; var xN = x.replace(re, "\0$1\0").replace(/\0$/, "").replace(/^\0/, "").split("\0"); var yN = y.replace(re, "\0$1\0").replace(/\0$/, "").replace(/^\0/, "").split("\0"); if (!x && !y) return EQUAL; if (!x && y) return GREATER; if (x && !y) return SMALLER; var xD = parseInt(x.match(hre)) || xN.length != 1 && x.match(dre) && Date.parse(x); var yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null; var oFxNcL, oFyNcL; if (yD) { if (xD < yD) return SMALLER; else if (xD > yD) return GREATER } for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { oFxNcL = !(xN[cLoc] || "").match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; oFyNcL = !(yN[cLoc] || "").match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; if (isNaN(oFxNcL) !== isNaN(oFyNcL)) return isNaN(oFxNcL) ? GREATER : SMALLER; else if (typeof oFxNcL !== typeof oFyNcL) { oFxNcL += ""; oFyNcL += "" } if (oFxNcL < oFyNcL) return SMALLER; if (oFxNcL > oFyNcL) return GREATER } return EQUAL } } const sortListByName = (vodList, key, order) => { if (!key) { return vodList } order = order || "asc"; return vodList.sort(naturalSort({ key: key, order: order, caseSensitive: true })) }; const getTimeInt = timeStr => { return new Date(timeStr).getTime() }; const sortListByTime = (vodList, key, order) => { if (!key) { return vodList } let ASCarr = vodList.sort((a, b) => { a = a[key]; b = b[key]; return getTimeInt(a) - getTimeInt(b) }); if (order === "desc") { ASCarr.reverse() } return ASCarr }; const sortListBySize = (vodList, key, order) => { if (!key) { return vodList } let ASCarr = vodList.sort((a, b) => { a = a[key]; b = b[key]; return (Number(a) || 0) - (Number(b) || 0) }); if (order === "desc") { ASCarr.reverse() } return ASCarr }; export default { init: init, home: home, homeVod: homeVod, category: category, detail: detail, play: play, search: search };