├── .github └── workflows │ └── metadata-generator.yml ├── .gitignore ├── .vscode └── launch.json ├── README.md ├── action └── parse-metadata.cjs ├── av_auto.json ├── av_raw_auto.json ├── cms └── cms.json ├── core ├── README.md ├── core │ ├── CryptoJS.min.js │ ├── JSEncrypt.min.js │ ├── JSONbig.js │ ├── buffer.js │ ├── cheerio.js │ ├── node-html-parser.js │ ├── uz3lib.js │ ├── uzHome.js │ ├── uzUtils.js │ └── uzVideo.js ├── template │ ├── danMu.js │ ├── panTools.js │ ├── uzHome.js │ └── vod101.js └── verifyServer.js ├── danMu ├── README.md ├── danMu.json └── js │ ├── danMu.js │ └── danMu2.txt ├── env.json ├── live └── live.json ├── local.json ├── package-lock.json ├── package.json ├── panTools ├── README.md ├── js │ ├── panTools.js │ └── panTools2.js └── panTools.json ├── readme └── README.main.md ├── recommend ├── README.md ├── douban.json └── js │ └── douban.txt ├── uzAio.json ├── uzAio.zip ├── uzAio_raw.json └── vod ├── README.md ├── js ├── 4kav.js ├── 91jav.js ├── aggl.js ├── aomipan.js ├── baijia.js ├── biliys.js ├── bttwo.js ├── changZhang20240614.js ├── clicli.js ├── cms.js ├── cms2.js ├── cms3.js ├── cmsUser.js ├── dandanju.js ├── dawanou.js ├── duanjutt.js ├── duoduo.js ├── eacg.js ├── eacg2.js ├── erxiao.js ├── funletu.txt ├── gzapp.txt ├── gzys.js ├── hjkk.js ├── hkdoll.js ├── huban.js ├── jable.js ├── jcy.js ├── jocy.js ├── jpyy.js ├── labipan.js ├── laobai.js ├── leijing.txt ├── liuqu.js ├── madou.js ├── mifun.js ├── missav.js ├── mogg.js ├── mubai.js ├── nanfdj.js ├── netflav.js ├── olevod.js ├── ouge.js ├── pansearch.txt ├── qingying.js ├── qiyou.js ├── resyunpan.js ├── revohd.js ├── saohuo.js ├── shandian.js ├── subaibai.js ├── tgs.js ├── tiantian.js ├── tianyiso.txt ├── wobg.js ├── xiafan.js ├── xiaomi.js ├── xpgtv.js ├── zhizhen.js └── zxzj.js └── vod.json /.github/workflows/metadata-generator.yml: -------------------------------------------------------------------------------- 1 | name: Metadata JSON Generator 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | generate-metadata: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | contents: write # 确保 GITHUB_TOKEN 具有写入权限 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 # 获取完整的 Git 历史,避免 push 失败 17 | 18 | - name: Set up Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: '20' 22 | 23 | - name: Install dependencies 24 | run: npm install 25 | 26 | - name: Generate Metadata 27 | run: | 28 | node action/parse-metadata.cjs 29 | 30 | - name: Commit changes 31 | run: | 32 | git config --global user.name 'GitHub Action' 33 | git config --global user.email 'action@github.com' 34 | git add *.json 35 | git add *.zip 36 | git add *.md 37 | git commit -m '该文件自动生成,无需手动修改。' || echo 'No changes to commit' 38 | git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | node_modules 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "node", 10 | "request": "launch", 11 | "name": "Launch Program", 12 | "skipFiles": [ 13 | "/**" 14 | ], 15 | "program": "${workspaceFolder}/core/template/vod101.js" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # uz 影视 扩展仓库 2 | 3 | 1. 欢迎向本仓库提交适用于 uz 影视 的扩展 4 | 2. 可以提交使用 uz 影视 加密的扩展,但不支持提交需要验证 `sid` 的扩展 5 | 6 | | 模块 | 功能描述 | 类型 | 7 | | :---------------------------------------------------------------------------------------------------------: | :-------------: | :------: | 8 | | **[core](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#uzutilsjs-提供网络存储toast-等功能)** | uz 影视基础能力 | - | 9 | | **[vod](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#视频源-type101-扩展)** | 视频源扩展 | type 101 | 10 | | **[recommend](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#uzhome首页推荐-type200-扩展)** | 推荐首页扩展 | type 200 | 11 | | **[panTools](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#pantools网盘工具-type300扩展)** | 网盘工具扩展 | type 300 | 12 | | **[danMu](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#danmu弹幕-type400-扩展)** | 弹幕扩展 | type 400 | 13 | 14 | # 订阅 15 | 16 | ``` 17 | https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/refs/heads/main/uzAio.zip 18 | ``` 19 | 20 | # 添加方式 21 | 22 | uz 影视 -> 设置 -> 数据管理 -> 订阅 -> + -> 输入链接 -> 确定 23 | 24 | # 请为扩展添加以下注释,用于自动更新 json 25 | 26 | ``` 27 | // 如果扩展加密了要用成对的 //空格ignore 包裹 28 | 29 | // ignore 30 | 31 | //@name:扩展名称 32 | // 网站主页,只有视频源扩展需要 33 | //@webSite:网站主页 34 | // 版本号纯数字 35 | //@version:1 36 | // 备注,没有的话就不填 37 | //@remark:这是备注 38 | // 加密 id,没有的话就不填 39 | //@codeID: 40 | // 使用的环境变量,没有的话就不填 41 | //@env: 42 | // 是否是AV 1是 0否 43 | //@isAV:0 44 | //是否弃用 1是 0否 45 | //@deprecated:0 46 | 47 | // ignore 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /av_auto.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "「禁」 麻豆", 4 | "version": 2, 5 | "webSite": "https://madou.club", 6 | "instance": "madou20240626", 7 | "order": "E", 8 | "api": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/madou.js", 9 | "type": 100 10 | }, 11 | { 12 | "name": "「禁」 玩偶姐姐", 13 | "version": 2, 14 | "webSite": "https://hongkongdollvideo.com", 15 | "instance": "hkdoll20240705", 16 | "order": "E", 17 | "api": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/hkdoll.js", 18 | "type": 100 19 | }, 20 | { 21 | "name": "「禁」 91jav", 22 | "version": 3, 23 | "webSite": "https://041.bndmpsjx.com", 24 | "order": "E", 25 | "api": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/91jav.js", 26 | "type": 101 27 | }, 28 | { 29 | "name": "「禁」 jable", 30 | "version": 3, 31 | "webSite": "https://jable.tv", 32 | "instance": "jable20240831", 33 | "order": "E", 34 | "api": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/jable.js", 35 | "type": 100 36 | }, 37 | { 38 | "name": "「禁」 missav", 39 | "version": 2, 40 | "webSite": "https://missav.ai", 41 | "instance": "missav20240627", 42 | "order": "E", 43 | "api": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/missav.js", 44 | "type": 100 45 | }, 46 | { 47 | "name": "「禁」 netflav", 48 | "version": 2, 49 | "webSite": "https://www.netflav.com", 50 | "instance": "netflav20240905", 51 | "order": "E", 52 | "api": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/netflav.js", 53 | "type": 100 54 | } 55 | ] -------------------------------------------------------------------------------- /av_raw_auto.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "「禁」 麻豆", 4 | "version": 2, 5 | "webSite": "https://madou.club", 6 | "instance": "madou20240626", 7 | "order": "E", 8 | "api": "https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/madou.js", 9 | "type": 100 10 | }, 11 | { 12 | "name": "「禁」 玩偶姐姐", 13 | "version": 2, 14 | "webSite": "https://hongkongdollvideo.com", 15 | "instance": "hkdoll20240705", 16 | "order": "E", 17 | "api": "https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/hkdoll.js", 18 | "type": 100 19 | }, 20 | { 21 | "name": "「禁」 91jav", 22 | "version": 3, 23 | "webSite": "https://041.bndmpsjx.com", 24 | "order": "E", 25 | "api": "https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/91jav.js", 26 | "type": 101 27 | }, 28 | { 29 | "name": "「禁」 jable", 30 | "version": 3, 31 | "webSite": "https://jable.tv", 32 | "instance": "jable20240831", 33 | "order": "E", 34 | "api": "https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/jable.js", 35 | "type": 100 36 | }, 37 | { 38 | "name": "「禁」 missav", 39 | "version": 2, 40 | "webSite": "https://missav.ai", 41 | "instance": "missav20240627", 42 | "order": "E", 43 | "api": "https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/missav.js", 44 | "type": 100 45 | }, 46 | { 47 | "name": "「禁」 netflav", 48 | "version": 2, 49 | "webSite": "https://www.netflav.com", 50 | "instance": "netflav20240905", 51 | "order": "E", 52 | "api": "https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/main/vod/js/netflav.js", 53 | "type": 100 54 | } 55 | ] -------------------------------------------------------------------------------- /cms/cms.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "api": "https://cj.rycjapi.com/api.php/provide/vod", 3 | "name": "「采」如意", 4 | "type": 0 5 | }, 6 | { 7 | "api": "https://json.heimuer.xyz/api.php/provide/vod/", 8 | "name": "「采」黑木耳", 9 | "type": 0 10 | }, 11 | { 12 | "api": "https://cjhwba.com/api.php/provide/vod/", 13 | "name": "「采」华为吧", 14 | "type": 0 15 | }] -------------------------------------------------------------------------------- /core/core/uz3lib.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | import { createCheerio } from './cheerio.js' 3 | import { createCryptoJS } from './CryptoJS.min.js' 4 | import { loadJSEncrypt } from './JSEncrypt.min.js' 5 | import { JSONbig } from './JSONbig.js' 6 | import { createBuffer } from './buffer.js' 7 | import { node_html_parser } from './node-html-parser.js' 8 | // ignore 9 | 10 | // 推荐优先使用 cheerio, parse 后期可能会移除 11 | const parse = node_html_parser.parse 12 | 13 | const cheerio = createCheerio() 14 | const Crypto = createCryptoJS() 15 | const Encrypt = loadJSEncrypt() 16 | const BufferLib = createBuffer() 17 | const Buffer = BufferLib.Buffer 18 | // const SlowBuffer = BufferLib.SlowBuffer 19 | // const Blob = BufferLib.Blob 20 | // const File = BufferLib.File 21 | // const atob = BufferLib.atob 22 | // const btoa = BufferLib.btoa 23 | // const INSPECT_MAX_BYTES = BufferLib.INSPECT_MAX_BYTES 24 | // const kMaxLength = BufferLib.kMaxLength 25 | // const kStringMaxLength = BufferLib.kStringMaxLength 26 | // const constants = BufferLib.constants 27 | 28 | // ignore 29 | export { cheerio, Crypto, Encrypt, JSONbig, Buffer } 30 | // ignore 31 | -------------------------------------------------------------------------------- /core/core/uzHome.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 首页推荐扩展 3 | */ 4 | 5 | //MARK: - 列表展示 UI类型 如需添加更多 UI 类型请联系 https://t.me/uzVideoAppbot 6 | const UIType = { 7 | /** 8 | * 轮播海报 9 | */ 10 | banner: "banner", 11 | 12 | /** 13 | * 横滑小海报 14 | */ 15 | smallCard: "smallCard", 16 | 17 | /** 18 | * 横滑大海报 19 | */ 20 | largeCard: "largeCard", 21 | }; 22 | 23 | //MARK: - 单个广告位展示数据 24 | /** 25 | * UI 展示数据 26 | */ 27 | class RepAd { 28 | constructor() { 29 | /** 30 | * UI 类型 31 | * @type {UIType} 32 | */ 33 | this.uiType = UIType.smallCard; 34 | 35 | /** 36 | * 海报宽高比 37 | */ 38 | this.ratio = 10.0 / 16.0; 39 | 40 | /** 41 | * 标题 为空不展示标题 42 | * @type {string} 43 | */ 44 | this.title = ""; 45 | 46 | /** 47 | * 展示数据 48 | * @type {VideoDetail} 必要字段 vod_name、vod_pic, 49 | * 次要 vod_remarks(海报上的小标签), 50 | * 后续用于提高匹配度的字段 vod_year vod_director type_name 51 | */ 52 | this.data = []; 53 | } 54 | } 55 | 56 | //MARK: - tab 列表数据 57 | /** 58 | * tab列表数据,data 与 filter 二选一 59 | * 当有 filter 时展示为筛选列表样式 60 | * 当有 data 时展示为普通列表样式 61 | */ 62 | class RepTabList { 63 | constructor() { 64 | /** 65 | * tab 列表数据 66 | * @type {Array } 67 | */ 68 | this.data = []; 69 | 70 | /** 71 | * 筛选列表 72 | * @type {FilterTitle[]} 73 | */ 74 | this.filter = []; 75 | 76 | this.error = ""; 77 | } 78 | } 79 | 80 | class HomeTabModel { 81 | constructor() { 82 | /** 83 | * 当前分类的链接 84 | **/ 85 | this.id = ""; 86 | 87 | /** 88 | * 分类名称 89 | */ 90 | this.name = ""; 91 | 92 | /** 93 | * 是否是筛选列表 94 | */ 95 | this.isFilter = false; 96 | 97 | /** 98 | * 扩展运行标识 ** uzApp 运行时自动赋值,请勿修改 ** 99 | */ 100 | this.uzTag = ""; 101 | } 102 | } 103 | 104 | //MARK: - 首页数据 105 | /** 106 | * 首页数据 107 | */ 108 | class RepHome { 109 | constructor() { 110 | /** 111 | * 各 tab 页面名称,用于 getTab() 入参 112 | * @type {Array } 113 | */ 114 | this.data = []; 115 | this.error = ""; 116 | } 117 | } 118 | 119 | //MARK:- 首页扩展类 120 | /** 121 | * 首页扩展,固定实例名称为 uzHomeJs,(例如 const uzHomeJs = new UZHomeJS();) 122 | */ 123 | class UZHome { 124 | /** 125 | * 获取首页 126 | * @returns {Promise} 127 | */ 128 | async getHome() { 129 | let repData = new RepHome(); 130 | return JSON.stringify(repData); 131 | } 132 | 133 | /** 134 | * 获取 tab 135 | * @param {UZArgs} args 主要参数 args.url args.page 136 | * @returns {Promise} 137 | */ 138 | async getTab(args) { 139 | let repData = new RepTabList(); 140 | return JSON.stringify(repData); 141 | } 142 | 143 | /** 144 | * 获取筛选列表数据 145 | * 当 getTab() 返回 RepTabList.filter 时调用 146 | * @param {UZSubclassVideoListArgs} args 主要参数 args.mainClassId(即 VideoClass.id) 、 args.filter( 按 getTab() 返回的 filter 顺序传入) 147 | * @returns {Promise}返回筛选列表 148 | */ 149 | async getFilterList(args) { 150 | let repData = new RepVideoList(); 151 | return JSON.stringify(repData); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /core/template/danMu.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:扩展名称 3 | // 版本号纯数字 4 | //@version:1 5 | // 备注,没有的话就不填 6 | //@remark:这是备注 7 | // 加密 id,没有的话就不填 8 | //@codeID: 9 | // 使用的环境变量,没有的话就不填 10 | //@env: 11 | // 是否是AV 1是 0否 12 | //@isAV:0 13 | //是否弃用 1是 0否 14 | //@deprecated:0 15 | // ignore 16 | 17 | 18 | // ignore 19 | // 不支持导入,这里只是本地开发用于代码提示 20 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 21 | import { 22 | FilterLabel, 23 | FilterTitle, 24 | VideoClass, 25 | VideoSubclass, 26 | VideoDetail, 27 | RepVideoClassList, 28 | RepVideoSubclassList, 29 | RepVideoList, 30 | RepVideoDetail, 31 | RepVideoPlayUrl, 32 | UZArgs, 33 | UZSubclassVideoListArgs, 34 | } from '../core/uzVideo.js' 35 | 36 | import { 37 | UZUtils, 38 | ProData, 39 | ReqResponseType, 40 | ReqAddressType, 41 | req, 42 | getEnv, 43 | setEnv, 44 | goToVerify, 45 | openWebToBindEnv, 46 | toast, 47 | kIsDesktop, 48 | kIsAndroid, 49 | kIsIOS, 50 | kIsWindows, 51 | kIsMacOS, 52 | kIsTV, 53 | kLocale, 54 | kAppVersion, 55 | formatBackData, 56 | } from '../core/uzUtils.js' 57 | 58 | import { cheerio, Crypto, Encrypt, JSONbig } from '../core/uz3lib.js' 59 | // ignore 60 | 61 | 62 | const appConfig = { 63 | _uzTag: '', 64 | /** 65 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 66 | * 用于读取环境变量 67 | */ 68 | get uzTag() { 69 | return this._uzTag 70 | }, 71 | set uzTag(value) { 72 | this._uzTag = value 73 | }, 74 | } 75 | 76 | class DanMu { 77 | constructor() { 78 | /** 79 | * 弹幕内容 80 | * @type {string} 81 | */ 82 | this.content = '' 83 | 84 | /** 85 | * 弹幕出现时间 单位秒 86 | * @type {number} 87 | */ 88 | this.time = 0 89 | } 90 | } 91 | 92 | class BackData { 93 | constructor() { 94 | /** 95 | * 弹幕数据 96 | * @type {DanMu[]} 97 | */ 98 | this.data = [] 99 | /** 100 | * 错误信息 101 | * @type {string} 102 | */ 103 | this.error = '' 104 | } 105 | } 106 | 107 | class SearchParameters { 108 | constructor() { 109 | /** 110 | * 动画或影片名称 111 | */ 112 | this.name = '' 113 | /** 114 | * 动画或影片集数 115 | */ 116 | this.episode = '' 117 | /** 118 | * 是否是电影 119 | */ 120 | this.isMovie = false 121 | } 122 | } 123 | 124 | /** 125 | * 搜索弹幕 126 | * @param {SearchParameters} item - 包含搜索参数的对象 127 | * @returns {Promise} backData - 返回一个 Promise 对象 128 | */ 129 | async function searchDanMu(item) { 130 | let backData = new BackData() 131 | try { 132 | let all = [] 133 | //MARK: - 实现你的弹幕搜索逻辑 134 | 135 | backData.data = all 136 | } catch (error) { 137 | backData.error = error.toString() 138 | } 139 | if (backData.data.length == 0) { 140 | backData.error = '未找到弹幕' 141 | } 142 | return formatBackData(backData) 143 | } 144 | -------------------------------------------------------------------------------- /core/template/uzHome.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | 3 | //@name:扩展名称 4 | // 版本号纯数字 5 | //@version:1 6 | // 备注,没有的话就不填 7 | //@remark:这是备注 8 | // 加密 id,没有的话就不填 9 | //@codeID: 10 | // 使用的环境变量,没有的话就不填 11 | //@env: 12 | // 是否是AV 1是 0否 13 | //@isAV:0 14 | //是否弃用 1是 0否 15 | //@deprecated:0 16 | 17 | // ignore 18 | 19 | 20 | 21 | 22 | // ignore 23 | // 不支持导入,这里只是本地开发用于代码提示 24 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 25 | import { 26 | FilterLabel, 27 | FilterTitle, 28 | VideoClass, 29 | VideoSubclass, 30 | VideoDetail, 31 | RepVideoClassList, 32 | RepVideoSubclassList, 33 | RepVideoList, 34 | RepVideoDetail, 35 | RepVideoPlayUrl, 36 | UZArgs, 37 | UZSubclassVideoListArgs, 38 | } from '../core/uzVideo.js' 39 | 40 | import { 41 | UZUtils, 42 | ProData, 43 | ReqResponseType, 44 | ReqAddressType, 45 | req, 46 | getEnv, 47 | setEnv, 48 | goToVerify, 49 | openWebToBindEnv, 50 | toast, 51 | kIsDesktop, 52 | kIsAndroid, 53 | kIsIOS, 54 | kIsWindows, 55 | kIsMacOS, 56 | kIsTV, 57 | kLocale, 58 | kAppVersion, 59 | formatBackData, 60 | } from '../core/uzUtils.js' 61 | 62 | import { cheerio, Crypto, Encrypt, JSONbig } from '../core/uz3lib.js' 63 | // ignore 64 | 65 | 66 | /** 67 | * @file 首页推荐扩展 68 | */ 69 | 70 | //MARK: - 列表展示 UI类型 如需添加更多 UI 类型请联系 https://t.me/uzVideoAppbot 71 | const UIType = { 72 | /** 73 | * 轮播海报 74 | */ 75 | banner: 'banner', 76 | 77 | /** 78 | * 横滑小海报 79 | */ 80 | smallCard: 'smallCard', 81 | 82 | /** 83 | * 横滑大海报 84 | */ 85 | largeCard: 'largeCard', 86 | } 87 | 88 | //MARK: - 单个广告位展示数据 89 | /** 90 | * UI 展示数据 91 | */ 92 | class RepAd { 93 | constructor() { 94 | /** 95 | * UI 类型 96 | * @type {UIType} 97 | */ 98 | this.uiType = UIType.smallCard 99 | 100 | /** 101 | * 海报宽高比 102 | */ 103 | this.ratio = 10.0 / 16.0 104 | 105 | /** 106 | * 标题 为空不展示标题 107 | * @type {string} 108 | */ 109 | this.title = '' 110 | 111 | /** 112 | * 展示数据 113 | * @type {VideoDetail} 必要字段 vod_name、vod_pic, 114 | * 次要 vod_remarks(海报上的小标签), 115 | * 后续用于提高匹配度的字段 vod_year vod_director type_name 116 | */ 117 | this.data = [] 118 | } 119 | } 120 | 121 | //MARK: - tab 列表数据 122 | /** 123 | * tab列表数据,data 与 filter 二选一 124 | * 当有 filter 时展示为筛选列表样式 125 | * 当有 data 时展示为普通列表样式 126 | */ 127 | class RepTabList { 128 | constructor() { 129 | /** 130 | * tab 列表数据 131 | * @type {Array } 132 | */ 133 | this.data = [] 134 | 135 | /** 136 | * 筛选列表 137 | * @type {FilterTitle[]} 138 | */ 139 | this.filter = [] 140 | 141 | this.error = '' 142 | } 143 | } 144 | 145 | class HomeTabModel { 146 | constructor() { 147 | /** 148 | * 当前分类的链接 149 | **/ 150 | this.id = '' 151 | 152 | /** 153 | * 分类名称 154 | */ 155 | this.name = '' 156 | 157 | /** 158 | * 是否是筛选列表 159 | */ 160 | this.isFilter = false 161 | 162 | /** 163 | * 扩展运行标识 ** uzApp 运行时自动赋值,请勿修改 ** 164 | */ 165 | this.uzTag = '' 166 | } 167 | } 168 | 169 | //MARK: - 首页数据 170 | /** 171 | * 首页数据 172 | */ 173 | class RepHome { 174 | constructor() { 175 | /** 176 | * 各 tab 页面名称,用于 getTab() 入参 177 | * @type {Array } 178 | */ 179 | this.data = [] 180 | this.error = '' 181 | } 182 | } 183 | 184 | //MARK:- 首页扩展类具体实现 185 | /** 186 | * 首页扩展,固定实例名称为 uzHomeJs,(例如 const uzHomeJs = new UZHomeJS();) 187 | */ 188 | class UZHome { 189 | /** 190 | * 获取首页 191 | * @returns {Promise} 192 | */ 193 | async getHome() { 194 | let repData = new RepHome() 195 | return JSON.stringify(repData) 196 | } 197 | 198 | /** 199 | * 获取 tab 200 | * @param {UZArgs} args 主要参数 args.url args.page 201 | * @returns {Promise} 202 | */ 203 | async getTab(args) { 204 | let repData = new RepTabList() 205 | return JSON.stringify(repData) 206 | } 207 | 208 | /** 209 | * 获取筛选列表数据 210 | * 当 getTab() 返回 RepTabList.filter 时调用 211 | * @param {UZSubclassVideoListArgs} args 主要参数 args.mainClassId(即 VideoClass.id) 、 args.filter( 按 getTab() 返回的 filter 顺序传入) 212 | * @returns {Promise}返回筛选列表 213 | */ 214 | async getFilterList(args) { 215 | let repData = new RepVideoList() 216 | return JSON.stringify(repData) 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /core/template/vod101.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | 3 | //@name:扩展名称 4 | // 网站主页,只有视频源扩展需要 5 | //@webSite:网站主页 6 | // 版本号纯数字 7 | //@version:1 8 | // 备注,没有的话就不填 9 | //@remark:这是备注 10 | // 加密 id,没有的话就不填 11 | //@codeID: 12 | // 使用的环境变量,没有的话就不填 13 | //@env: 14 | // 是否是AV 1是 0否 15 | //@isAV:0 16 | //是否弃用 1是 0否 17 | //@deprecated:0 18 | 19 | // ignore 20 | 21 | 22 | 23 | // ignore 24 | // 不支持导入,这里只是本地开发用于代码提示 25 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 26 | import { 27 | FilterLabel, 28 | FilterTitle, 29 | VideoClass, 30 | VideoSubclass, 31 | VideoDetail, 32 | RepVideoClassList, 33 | RepVideoSubclassList, 34 | RepVideoList, 35 | RepVideoDetail, 36 | RepVideoPlayUrl, 37 | UZArgs, 38 | UZSubclassVideoListArgs, 39 | } from '../core/uzVideo.js' 40 | 41 | import { 42 | UZUtils, 43 | ProData, 44 | ReqResponseType, 45 | ReqAddressType, 46 | req, 47 | getEnv, 48 | setEnv, 49 | goToVerify, 50 | openWebToBindEnv, 51 | toast, 52 | kIsDesktop, 53 | kIsAndroid, 54 | kIsIOS, 55 | kIsWindows, 56 | kIsMacOS, 57 | kIsTV, 58 | kLocale, 59 | kAppVersion, 60 | formatBackData, 61 | } from '../core/uzUtils.js' 62 | 63 | import { cheerio, Crypto, Encrypt, JSONbig } from '../core/uz3lib.js' 64 | // ignore 65 | 66 | 67 | //MARK: 注意 68 | // 直接复制该文件进行扩展开发 69 | // 请保持以下 变量 及 函数 名称不变 70 | // 请勿删减,可以新增 71 | 72 | const appConfig = { 73 | _webSite: '', 74 | /** 75 | * 网站主页,uz 调用每个函数前都会进行赋值操作 76 | * 如果不想被改变 请自定义一个变量 77 | */ 78 | get webSite() { 79 | return this._webSite 80 | }, 81 | set webSite(value) { 82 | this._webSite = value 83 | }, 84 | 85 | _uzTag: '', 86 | /** 87 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 88 | * 用于读取环境变量 89 | */ 90 | get uzTag() { 91 | return this._uzTag 92 | }, 93 | set uzTag(value) { 94 | this._uzTag = value 95 | }, 96 | } 97 | 98 | /** 99 | * 异步获取分类列表的方法。 100 | * @param {UZArgs} args 101 | * @returns {@Promise} 102 | */ 103 | async function getClassList(args) { 104 | var backData = new RepVideoClassList() 105 | try { 106 | } catch (error) { 107 | backData.error = error.toString() 108 | } 109 | return JSON.stringify(backData) 110 | } 111 | 112 | /** 113 | * 获取二级分类列表筛选列表的方法。 114 | * @param {UZArgs} args 115 | * @returns {@Promise} 116 | */ 117 | async function getSubclassList(args) { 118 | var backData = new RepVideoSubclassList() 119 | try { 120 | } catch (error) { 121 | backData.error = error.toString() 122 | } 123 | return JSON.stringify(backData) 124 | } 125 | 126 | /** 127 | * 获取分类视频列表 128 | * @param {UZArgs} args 129 | * @returns {@Promise} 130 | */ 131 | async function getVideoList(args) { 132 | var backData = new RepVideoList() 133 | try { 134 | } catch (error) { 135 | backData.error = error.toString() 136 | } 137 | return JSON.stringify(backData) 138 | } 139 | 140 | /** 141 | * 获取二级分类视频列表 或 筛选视频列表 142 | * @param {UZSubclassVideoListArgs} args 143 | * @returns {@Promise} 144 | */ 145 | async function getSubclassVideoList(args) { 146 | var backData = new RepVideoList() 147 | try { 148 | } catch (error) { 149 | backData.error = error.toString() 150 | } 151 | return JSON.stringify(backData) 152 | } 153 | 154 | /** 155 | * 获取视频详情 156 | * @param {UZArgs} args 157 | * @returns {@Promise} 158 | */ 159 | async function getVideoDetail(args) { 160 | var backData = new RepVideoDetail() 161 | try { 162 | } catch (error) { 163 | backData.error = error.toString() 164 | } 165 | return JSON.stringify(backData) 166 | } 167 | 168 | /** 169 | * 获取视频的播放地址 170 | * @param {UZArgs} args 171 | * @returns {@Promise} 172 | */ 173 | async function getVideoPlayUrl(args) { 174 | var backData = new RepVideoPlayUrl() 175 | try { 176 | } catch (error) { 177 | backData.error = error.toString() 178 | } 179 | return JSON.stringify(backData) 180 | } 181 | 182 | /** 183 | * 搜索视频 184 | * @param {UZArgs} args 185 | * @returns {@Promise} 186 | */ 187 | async function searchVideo(args) { 188 | var backData = new RepVideoList() 189 | try { 190 | } catch (error) { 191 | backData.error = error.toString() 192 | } 193 | return JSON.stringify(backData) 194 | } 195 | -------------------------------------------------------------------------------- /core/verifyServer.js: -------------------------------------------------------------------------------- 1 | // TODO: 替换为自己的盐 2 | // 服务器接收来自 app 的请求的盐 3 | const saltApp2End = "123321"; 4 | // 服务器发送数据到 app 的盐 5 | const saltEnd2App = "123321"; 6 | 7 | addEventListener("fetch", (event) => { 8 | event.respondWith(handleRequest(event.request)); 9 | }); 10 | 11 | async function handleRequest(request) { 12 | let params; 13 | 14 | try { 15 | params = await request.json(); 16 | } catch (error) { 17 | return new Response(); 18 | } 19 | 20 | if (!params || Object.keys(params).length === 0) { 21 | return new Response(); 22 | } 23 | 24 | if (!(await _verifySignFromApp(params))) { 25 | return new Response(); 26 | } 27 | 28 | if (!_verifyTimestamp(params.date)) { 29 | return new Response(); 30 | } 31 | 32 | let responseData = {}; 33 | let sid = params.sid; 34 | //TODO: 判断 sid 是否是允许的用户 35 | // 如果使用 cloudflare worker,可以使用 KV 存储 key: sid value:与用户定义的其它标识 例如邮箱 36 | if (sid) { 37 | responseData.pass = true; 38 | } else { 39 | responseData.pass = false; 40 | } 41 | 42 | const signedResponse = await _signResponse2App( 43 | responseData, 44 | params.sessionId 45 | ); 46 | 47 | return new Response(JSON.stringify(signedResponse), { 48 | headers: { "Content-Type": "application/json" }, 49 | }); 50 | } 51 | 52 | async function _verifySignFromApp(params) { 53 | const { sign, ...otherParams } = params; 54 | if ( 55 | !sign || 56 | !otherParams.random || 57 | !otherParams.date || 58 | !otherParams.sessionId || 59 | !otherParams.sid 60 | ) 61 | return false; 62 | 63 | const sortedParams = Object.entries(otherParams) 64 | .sort((a, b) => b[0].localeCompare(a[0])) 65 | .map(([key, value]) => `${key}=${value}`) 66 | .join("&"); 67 | 68 | const salt = 69 | saltApp2End + otherParams.random.slice(-4) + otherParams.date.slice(-4); 70 | const signStr = salt + sortedParams; 71 | const calculatedSign = await _keyToSha256(signStr); 72 | 73 | return calculatedSign === sign; 74 | } 75 | 76 | async function _signResponse2App(data, sessionId) { 77 | const signMap = { ...data }; 78 | // 64位随机数 79 | const random = crypto.randomUUID().slice(-64); 80 | const date = Date.now().toString(); 81 | 82 | signMap.random = random; 83 | signMap.date = date; 84 | signMap.sessionId = sessionId; 85 | 86 | const sortedParams = Object.entries(signMap) 87 | .sort((a, b) => b[0].localeCompare(a[0])) 88 | .map(([key, value]) => `${key}=${value}`) 89 | .join("&"); 90 | 91 | const salt = saltEnd2App + random.slice(-4) + date.slice(-4); 92 | const signStr = salt + sortedParams; 93 | signMap.sign = await _keyToSha256(signStr); 94 | 95 | return signMap; 96 | } 97 | 98 | async function _keyToSha256(input) { 99 | const encoder = new TextEncoder(); 100 | const data = encoder.encode(input); 101 | const hashBuffer = await crypto.subtle.digest("SHA-256", data); 102 | return Array.from(new Uint8Array(hashBuffer)) 103 | .map((b) => b.toString(16).padStart(2, "0")) 104 | .join(""); 105 | } 106 | 107 | // 验证时间戳 108 | function _verifyTimestamp(timestamp) { 109 | // 时间为了保证任意时区都一致 所以使用格林威治时间 110 | const currentTimeString = new Date().toISOString(); 111 | const currentTime = new Date(currentTimeString).getTime(); 112 | const requestTime = parseInt(timestamp); 113 | const timeDifference = Math.abs(currentTime - requestTime); 114 | // 检查时间差是否小于2分钟(120000毫秒) 115 | return timeDifference < 120000; 116 | } 117 | -------------------------------------------------------------------------------- /danMu/README.md: -------------------------------------------------------------------------------- 1 | # 弹幕扩展 type:400 2 | 3 | 1. 请尽量整合在 `danMu.js` 内 4 | 2. 请为扩展编写单独的 `json` 文件 5 | 6 | 7 | # 请为扩展添加以下注释,用于自动更新 json 8 | 9 | ``` 10 | // 如果扩展加密了要用成对的 //空格ignore 包裹 11 | 12 | // ignore 13 | 14 | //@name:扩展名称 15 | // 版本号纯数字 16 | //@version:1 17 | // 备注,没有的话就不填 18 | //@remark:这是备注 19 | // 加密 id,没有的话就不填 20 | //@codeID: 21 | // 使用的环境变量,没有的话就不填 22 | //@env: 23 | 24 | // ignore 25 | 26 | ``` 27 | -------------------------------------------------------------------------------- /danMu/danMu.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dandanPlay 弹幕", 3 | "remark": "数据来自 弹弹Play", 4 | "url": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/refs/heads/main/danMu/js/danMu.js", 5 | "type": 400, 6 | "version": 1 7 | } 8 | -------------------------------------------------------------------------------- /danMu/js/danMu.js: -------------------------------------------------------------------------------- 1 | //@name:弹幕扩展 2 | //@version:1 3 | //@remark: 4 | //@order: A02 5 | // ignore 6 | import {} from '../../core/uz3lib.js' 7 | import {} from '../../core/uzUtils.js' 8 | // ignore 9 | 10 | const appConfig = { 11 | _uzTag: '', 12 | /** 13 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 14 | * 用于读取环境变量 15 | */ 16 | get uzTag() { 17 | return this._uzTag 18 | }, 19 | set uzTag(value) { 20 | this._uzTag = value 21 | }, 22 | } 23 | 24 | class DanMu { 25 | constructor() { 26 | /** 27 | * 弹幕内容 28 | * @type {string} 29 | */ 30 | this.content = '' 31 | 32 | /** 33 | * 弹幕出现时间 单位秒 34 | * @type {number} 35 | */ 36 | this.time = 0 37 | } 38 | } 39 | 40 | class BackData { 41 | constructor() { 42 | /** 43 | * 弹幕数据 44 | * @type {DanMu[]} 45 | */ 46 | this.data = [] 47 | /** 48 | * 错误信息 49 | * @type {string} 50 | */ 51 | this.error = '' 52 | } 53 | } 54 | 55 | /** 56 | * 搜索弹幕 57 | * @param {Object} item - 包含搜索参数的对象 58 | * @param {string} item.name - 动画或影片的名称 59 | * @param {number} item.episode - 动画或影片的集数 60 | * @param {boolean} item.isMovie - 是否是电影 61 | * @returns {Promise} backData - 返回一个 Promise 对象 62 | */ 63 | async function searchDanMu(item) { 64 | let backData = new BackData() 65 | try { 66 | let all = [] 67 | //MARK: - 实现你的弹幕搜索逻辑 68 | let ddpList = await searchByDandanPlay(item) 69 | 70 | all = all.concat(ddpList) 71 | backData.data = all 72 | } catch (error) { 73 | backData.error = error.toString() 74 | } 75 | if (backData.data.length == 0) { 76 | backData.error = '未找到弹幕' 77 | } 78 | return formatBackData(backData) 79 | } 80 | 81 | async function searchByDandanPlay(item) { 82 | let list = [] 83 | try { 84 | var searchResult = await req( 85 | 'https://api.dandanplay.net/api/v2/search/episodes', 86 | { 87 | queryParameters: { 88 | anime: item.name, 89 | episode: item.isMovie ? 'movie' : `${item.episode}`, 90 | }, 91 | } 92 | ) 93 | if (searchResult.data?.animes?.length > 0) { 94 | let episodeId = searchResult.data.animes[0].episodes[0].episodeId 95 | let isSimplified = kLocale.indexOf('CN') !== -1 96 | var danMuResult = await req( 97 | `https://api.dandanplay.net/api/v2/comment/${episodeId}?withRelated=true&chConvert=${ 98 | isSimplified ? '1' : '2' 99 | }` 100 | ) 101 | 102 | if (danMuResult.data?.comments?.length > 0) { 103 | for ( 104 | let index = 0; 105 | index < danMuResult.data.comments.length; 106 | index++ 107 | ) { 108 | const element = danMuResult.data.comments[index] 109 | let params = element.p.split(',') 110 | let danMu = new DanMu() 111 | danMu.content = element.m 112 | danMu.time = params[0] 113 | list.push(danMu) 114 | } 115 | } 116 | } 117 | } catch (error) {} 118 | return list 119 | } 120 | -------------------------------------------------------------------------------- /env.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "采集解析地址", 4 | "desc": "内置两个,失效不要反馈。格式:名称1@地址1;名称2@地址2", 5 | "value": "" 6 | }, 7 | { 8 | "name": "采集解析地址", 9 | "desc": "内置两个,失效不要反馈。格式:名称1@地址1;名称2@地址2", 10 | "value": "" 11 | }, 12 | { 13 | "name": "囧次元更新网址", 14 | "desc": "填写1,然后在首页源列表重新切换到囧次元,可更新手动更新网址", 15 | "value": "" 16 | }, 17 | { 18 | "name": "UCCookie", 19 | "desc": "用于播放UC网盘视频", 20 | "value": "" 21 | }, 22 | { 23 | "name": "UC_UT", 24 | "desc": "播放视频自动获取,不可用时点击删除重新获取 cookie ,再重启app", 25 | "value": "" 26 | }, 27 | { 28 | "name": "夸克Cookie", 29 | "desc": "用于播放Quark网盘视频", 30 | "value": "" 31 | }, 32 | { 33 | "name": "阿里Token", 34 | "desc": "用于播放阿里网盘视频", 35 | "value": "" 36 | }, 37 | { 38 | "name": "转存文件夹名称", 39 | "desc": "在各网盘转存文件时使用的文件夹名称", 40 | "value": "" 41 | }, 42 | { 43 | "name": "123网盘账号", 44 | "desc": "用于播放123网盘视频", 45 | "value": "" 46 | }, 47 | { 48 | "name": "123网盘密码", 49 | "desc": "用于播放123网盘视频", 50 | "value": "" 51 | }, 52 | { 53 | "name": "天翼网盘账号", 54 | "desc": "用于播放天翼网盘视频", 55 | "value": "" 56 | }, 57 | { 58 | "name": "天翼网盘密码", 59 | "desc": "用于播放天翼网盘视频", 60 | "value": "" 61 | }, 62 | { 63 | "name": "采集解析地址", 64 | "desc": "内置两个,失效不要反馈。格式:名称1@地址1;名称2@地址2", 65 | "value": "" 66 | }, 67 | { 68 | "name": "弹幕解析地址", 69 | "desc": "内置 4 条线路。格式 地址1;地址2", 70 | "value": "" 71 | } 72 | ] -------------------------------------------------------------------------------- /live/live.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "📺电视直播", 4 | "api": "https://tv.iill.top/m3u/Gather", 5 | "type": 10, 6 | "remark": "来自 YanG-1989 大佬 https://github.com/YanG-1989" 7 | }, 8 | { 9 | "name": "🎥网络直播", 10 | "api": "https://tv.iill.top/m3u/Live", 11 | "type": 10, 12 | "remark": "来自 YanG-1989 大佬 https://github.com/YanG-1989" 13 | }, 14 | { 15 | "name": "🚴‍♂️体育直播", 16 | "api": "https://tv.iill.top/m3u/Sport", 17 | "type": 10, 18 | "remark": "来自 YanG-1989 大佬 https://github.com/YanG-1989" 19 | } 20 | ] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uzvideo-extensions", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "description": "uzVideo extensions", 6 | "private": true, 7 | "dependencies": { 8 | "archiver": "^7.0.1", 9 | "https-proxy-agent": "^7.0.6", 10 | "node-fetch": "^3.3.2" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /panTools/README.md: -------------------------------------------------------------------------------- 1 | # 网盘工具扩展 type:300 2 | 3 | 1. 请尽量整合在 `panTools` 内 4 | 5 | # 请为扩展添加以下注释,用于自动更新 json 6 | 7 | ``` 8 | // 如果扩展加密了要用成对的 //空格ignore 包裹 9 | 10 | // ignore 11 | 12 | //@name:扩展名称 13 | // 版本号纯数字 14 | //@version:1 15 | // 备注,没有的话就不填 16 | //@remark:这是备注 17 | // 加密 id,没有的话就不填 18 | //@codeID: 19 | // 使用的环境变量,没有的话就不填 20 | //@env: 21 | 22 | // ignore 23 | 24 | ``` 25 | -------------------------------------------------------------------------------- /panTools/panTools.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "UC、夸克、阿里 网盘解析工具", 3 | "url": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/refs/heads/main/panTools/js/panTools.js", 4 | "env": "UCCookie##用于播放UC网盘视频&&夸克Cookie##用于播放Quark网盘视频&&阿里Token##用于播放阿里网盘视频&&转存文件夹名称##在各网盘转存文件时使用的文件夹名称", 5 | "remark": "", 6 | "version": 14, 7 | "type": 300 8 | } 9 | -------------------------------------------------------------------------------- /readme/README.main.md: -------------------------------------------------------------------------------- 1 | # uz 影视 扩展仓库 2 | 3 | 1. 欢迎向本仓库提交适用于 uz 影视 的扩展 4 | 2. 可以提交使用 uz 影视 加密的扩展,但不支持提交需要验证 `sid` 的扩展 5 | 6 | | 模块 | 功能描述 | 类型 | 7 | | :---------------------------------------------------------------------------------------------------------: | :-------------: | :------: | 8 | | **[core](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#uzutilsjs-提供网络存储toast-等功能)** | uz 影视基础能力 | - | 9 | | **[vod](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#视频源-type101-扩展)** | 视频源扩展 | type 101 | 10 | | **[recommend](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#uzhome首页推荐-type200-扩展)** | 推荐首页扩展 | type 200 | 11 | | **[panTools](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#pantools网盘工具-type300扩展)** | 网盘工具扩展 | type 300 | 12 | | **[danMu](https://github.com/YYDS678/uzVideo-extensions/tree/main/core#danmu弹幕-type400-扩展)** | 弹幕扩展 | type 400 | 13 | 14 | # 订阅 15 | 16 | ``` 17 | https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/refs/heads/main/uzAio.zip 18 | ``` 19 | 20 | # 添加方式 21 | 22 | uz 影视 -> 设置 -> 数据管理 -> 订阅 -> + -> 输入链接 -> 确定 23 | 24 | # 请为扩展添加以下注释,用于自动更新 json 25 | 26 | ``` 27 | // 如果扩展加密了要用成对的 //空格ignore 包裹 28 | 29 | // ignore 30 | 31 | //@name:扩展名称 32 | // 网站主页,只有视频源扩展需要 33 | //@webSite:网站主页 34 | // 版本号纯数字 35 | //@version:1 36 | // 备注,没有的话就不填 37 | //@remark:这是备注 38 | // 加密 id,没有的话就不填 39 | //@codeID: 40 | // 使用的环境变量,没有的话就不填 41 | //@env: 42 | // 是否是AV 1是 0否 43 | //@isAV:0 44 | //是否弃用 1是 0否 45 | //@deprecated:0 46 | 47 | // ignore 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /recommend/README.md: -------------------------------------------------------------------------------- 1 | # 推荐页扩展 type:200 2 | 3 | # 请为扩展添加以下注释,用于自动更新 json 4 | ``` 5 | // 如果扩展加密了要用成对的 //空格ignore 包裹 6 | 7 | // ignore 8 | 9 | //@name:扩展名称 10 | // 版本号纯数字 11 | //@version:1 12 | // 备注,没有的话就不填 13 | //@remark:这是备注 14 | // 加密 id,没有的话就不填 15 | //@codeID: 16 | // 使用的环境变量,没有的话就不填 17 | //@env: 18 | 19 | // ignore 20 | 21 | ``` -------------------------------------------------------------------------------- /recommend/douban.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "豆瓣推荐 影视推荐", 3 | "codeID": "N7WRmLmOdB8FSh4M", 4 | "url": "https://github.moeyy.xyz/https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/refs/heads/main/recommend/js/douban.txt", 5 | "remark": "", 6 | "version": "3", 7 | "type": 200 8 | } 9 | -------------------------------------------------------------------------------- /uzAio.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YYDS678/uzVideo-extensions/d83de301288178c9a08bc75a738ae9ba8b43bef2/uzAio.zip -------------------------------------------------------------------------------- /vod/README.md: -------------------------------------------------------------------------------- 1 | # 视频源扩展 type:101 2 | 3 | [比较详细的 视频源扩展](https://github.com/YYDS678/uzVideo-extensions/tree/main/vod/js/eacg.js) 4 | 5 | # 请为扩展添加以下注释,用于自动更新 json 6 | 7 | ``` 8 | // 如果扩展加密了要用成对的 //空格ignore 包裹 9 | 10 | // ignore 11 | 12 | //@name:扩展名称 13 | // 网站主页,只有视频源扩展需要 14 | //@webSite:网站主页 15 | // 版本号纯数字 16 | //@version:1 17 | // 备注,没有的话就不填 18 | //@remark:这是备注 19 | // 加密 id,没有的话就不填 20 | //@codeID: 21 | // 使用的环境变量,没有的话就不填 22 | //@env: 23 | // 是否是AV 1是 0否 24 | //@isAV:0 25 | //是否弃用 1是 0否 26 | //@deprecated:0 27 | 28 | // ignore 29 | 30 | ``` 31 | -------------------------------------------------------------------------------- /vod/js/aggl.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「嗅」 girigirilove 3 | //@version:1 4 | //@webSite:https://anime.girigirilove.com 5 | //@remark: 6 | //@order: D 7 | // ignore 8 | 9 | // 适用于 把鼠标放在视频封面上 可以右键 复制正确链接的网站 10 | // 不能保证一定能用,不能用的欢迎反馈 11 | 12 | /// 是否模拟 PC 是 1, 手机是 0 13 | const isUsePC = 1 14 | /// 当视频不能播放的时候,可以把这个设置为 1, 否则不要改动 15 | const isAddReferer = 0 16 | 17 | // 网站主页 18 | const webSite = 'https://anime.girigirilove.com' 19 | // 网站搜索 20 | // https://anime.girigirilove.com/search/海----------2---/ 21 | const searchUrl = '@{webSite}/search/@{searchWord}----------@{page}---' 22 | // 当前网站任意视频详情页 23 | // https://anime.girigirilove.com/GV26152/ 24 | const videoDetailPage = '@{webSite}/GV26152/' 25 | // 当前网站任意视频播放页 26 | // https://anime.girigirilove.com/playGV26152-1-1/ 27 | const videoPlayPage = '@{webSite}/playGV26152-1-1/' 28 | 29 | // 保持不变 30 | const filterListUrl = '' 31 | 32 | const firstClass = [ 33 | { 34 | name: '日漫', 35 | id: '日漫', 36 | subClass: [ 37 | { 38 | name: '全部', 39 | // https://anime.girigirilove.com/show/2--------2--- 40 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 41 | id: '@{webSite}/show/2--------@{page}---', 42 | }, 43 | { 44 | name: '喜剧', 45 | // https://anime.girigirilove.com/show/2---喜剧-----2--- 46 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 47 | id: '@{webSite}/show/2---喜剧-----@{page}---', 48 | }, 49 | { 50 | name: '爱情', 51 | id: '@{webSite}/show/2---爱情-----@{page}---', 52 | }, 53 | { 54 | name: '恐怖', 55 | id: '@{webSite}/show/2---恐怖-----@{page}---', 56 | }, 57 | { 58 | name: '动作', 59 | id: '@{webSite}/show/2---动作-----@{page}---', 60 | }, 61 | { 62 | name: '科幻', 63 | id: '@{webSite}/show/2---科幻-----@{page}---', 64 | }, 65 | { 66 | name: '剧情', 67 | id: '@{webSite}/show/2---剧情-----@{page}---', 68 | }, 69 | { 70 | name: '战争', 71 | id: '@{webSite}/show/2---战争-----@{page}---', 72 | }, 73 | { 74 | name: '奇幻', 75 | id: '@{webSite}/show/2---奇幻-----@{page}---', 76 | }, 77 | { 78 | name: '冒险', 79 | id: '@{webSite}/show/2---冒险-----@{page}---', 80 | }, 81 | { 82 | name: '悬疑', 83 | id: '@{webSite}/show/2---悬疑-----@{page}---', 84 | }, 85 | { 86 | name: '热血', 87 | id: '@{webSite}/show/2---热血-----@{page}---', 88 | }, 89 | ], 90 | }, 91 | { 92 | name: '剧场版', 93 | id: '剧场版', 94 | subClass: [ 95 | { 96 | // https://anime.girigirilove.com/show/21--------2---/ 97 | name: '全部', 98 | id: '@{webSite}/show/21--------@{page}---', 99 | }, 100 | { 101 | // https://anime.girigirilove.com/show/21---喜剧-----2---/ 102 | name: '喜剧', 103 | id: '@{webSite}/show/21---喜剧-----@{page}---', 104 | }, 105 | { 106 | name: '爱情', 107 | id: '@{webSite}/show/21---爱情-----@{page}---', 108 | }, 109 | { 110 | name: '恐怖', 111 | id: '@{webSite}/show/21---恐怖-----@{page}---', 112 | }, 113 | { 114 | name: '动作', 115 | id: '@{webSite}/show/21---动作-----@{page}---', 116 | }, 117 | { 118 | name: '科幻', 119 | id: '@{webSite}/show/21---科幻-----@{page}---', 120 | }, 121 | { 122 | name: '剧情', 123 | id: '@{webSite}/show/21---剧情-----@{page}---', 124 | }, 125 | { 126 | name: '战争', 127 | id: '@{webSite}/show/21---战争-----@{page}---', 128 | }, 129 | { 130 | name: '奇幻', 131 | id: '@{webSite}/show/21---奇幻-----@{page}---', 132 | }, 133 | { 134 | name: '冒险', 135 | id: '@{webSite}/show/21---冒险-----@{page}---', 136 | }, 137 | { 138 | name: '悬疑', 139 | id: '@{webSite}/show/21---悬疑-----@{page}---', 140 | }, 141 | { 142 | name: '热血', 143 | id: '@{webSite}/show/21---热血-----@{page}---', 144 | }, 145 | ], 146 | }, 147 | ] 148 | 149 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 150 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 151 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 152 | 153 | //#BaseCode1# 154 | -------------------------------------------------------------------------------- /vod/js/aomipan.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 奥秘 3 | //@version:3 4 | //@webSite:https://vip.omii.top 5 | //@remark: 6 | //@order: B 7 | // ignore 8 | const appConfig = { 9 | _webSite: 'https://vip.omii.top', 10 | /** 11 | * 网站主页,uz 调用每个函数前都会进行赋值操作 12 | * 如果不想被改变 请自定义一个变量 13 | */ 14 | get webSite() { 15 | return this._webSite 16 | }, 17 | set webSite(value) { 18 | this._webSite = value 19 | }, 20 | 21 | _uzTag: '', 22 | /** 23 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 24 | * 用于读取环境变量 25 | */ 26 | get uzTag() { 27 | return this._uzTag 28 | }, 29 | set uzTag(value) { 30 | this._uzTag = value 31 | }, 32 | } 33 | 34 | /** 35 | * 异步获取分类列表的方法。 36 | * @param {UZArgs} args 37 | * @returns {Promise} 38 | */ 39 | async function getClassList(args) { 40 | var backData = new RepVideoClassList() 41 | backData.data = [ 42 | { 43 | type_id: '30', 44 | type_name: '奥秘电影', 45 | hasSubclass: false, 46 | }, 47 | { 48 | type_id: '31', 49 | type_name: '奥秘剧集', 50 | hasSubclass: false, 51 | }, 52 | { 53 | type_id: '32', 54 | type_name: '奥秘动漫', 55 | hasSubclass: false, 56 | }, 57 | { 58 | type_id: '33', 59 | type_name: '奥秘综艺', 60 | hasSubclass: false, 61 | }, 62 | { 63 | type_id: '34', 64 | type_name: '奥秘短剧', 65 | hasSubclass: false, 66 | }, 67 | { 68 | type_id: '35', 69 | type_name: '奥秘音乐', 70 | hasSubclass: false, 71 | }, 72 | ] 73 | return JSON.stringify(backData) 74 | } 75 | async function getSubclassList(args) { 76 | let backData = new RepVideoSubclassList() 77 | return JSON.stringify(backData) 78 | } 79 | async function getSubclassVideoList(args) { 80 | var backData = new RepVideoList() 81 | return JSON.stringify(backData) 82 | } 83 | /** 84 | * 获取分类视频列表 85 | * @param {UZArgs} args 86 | * @returns {Promise} 87 | */ 88 | async function getVideoList(args) { 89 | var backData = new RepVideoList() 90 | let url = 91 | UZUtils.removeTrailingSlash(appConfig.webSite) + 92 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 93 | try { 94 | const pro = await req(url) 95 | backData.error = pro.error 96 | let videos = [] 97 | if (pro.data) { 98 | const $ = cheerio.load(pro.data) 99 | let vodItems = $('#main .module-item') 100 | vodItems.each((_, e) => { 101 | let videoDet = new VideoDetail() 102 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 103 | videoDet.vod_name = $(e) 104 | .find('.module-item-pic img') 105 | .attr('alt') 106 | videoDet.vod_pic = $(e) 107 | .find('.module-item-pic img') 108 | .attr('data-src') 109 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 110 | videoDet.vod_year = $(e) 111 | .find('.module-item-caption span') 112 | .first() 113 | .text() 114 | videos.push(videoDet) 115 | }) 116 | } 117 | backData.data = videos 118 | } catch (error) {} 119 | return JSON.stringify(backData) 120 | } 121 | 122 | /** 123 | * 获取视频详情 124 | * @param {UZArgs} args 125 | * @returns {Promise} 126 | */ 127 | async function getVideoDetail(args) { 128 | var backData = new RepVideoDetail() 129 | try { 130 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 131 | let pro = await req(webUrl) 132 | 133 | backData.error = pro.error 134 | let proData = pro.data 135 | if (proData) { 136 | const $ = cheerio.load(proData) 137 | let vodDetail = new VideoDetail() 138 | vodDetail.vod_id = args.url 139 | vodDetail.vod_name = $('.page-title')[0].children[0].data 140 | vodDetail.vod_pic = $($('.mobile-play')).find( 141 | '.lazyload' 142 | )[0].attribs['data-src'] 143 | 144 | let video_items = $('.video-info-itemtitle') 145 | 146 | for (const item of video_items) { 147 | let key = $(item).text() 148 | 149 | let vItems = $(item).next().find('a') 150 | let value = vItems 151 | .map((i, el) => { 152 | let text = $(el).text().trim() // 获取并去除空白字符 153 | return text ? text : null // 只有非空的文本才返回 154 | }) 155 | .get() // 将 jQuery 对象转换为普通数组 156 | .filter(Boolean) // 过滤掉 null 和空字符串 157 | .join(', ') // 用逗号和空格分割 158 | 159 | if (key.includes('剧情')) { 160 | vodDetail.vod_content = $(item) 161 | .next() 162 | .find('p') 163 | .text() 164 | .trim() 165 | } else if (key.includes('导演')) { 166 | vodDetail.vod_director = value.trim() 167 | } else if (key.includes('主演')) { 168 | vodDetail.vod_actor = value.trim() 169 | } 170 | } 171 | 172 | const panUrls = [] 173 | let items = $('.module-row-info') 174 | for (const item of items) { 175 | let shareUrl = $(item).find('p')[0].children[0].data 176 | panUrls.push(shareUrl) 177 | } 178 | vodDetail.panUrls = panUrls 179 | console.log(panUrls) 180 | 181 | backData.data = vodDetail 182 | } 183 | } catch (error) { 184 | backData.error = '获取视频详情失败' + error 185 | } 186 | 187 | return JSON.stringify(backData) 188 | } 189 | 190 | /** 191 | * 获取视频的播放地址 192 | * @param {UZArgs} args 193 | * @returns {Promise} 194 | */ 195 | async function getVideoPlayUrl(args) { 196 | var backData = new RepVideoPlayUrl() 197 | return JSON.stringify(backData) 198 | } 199 | 200 | /** 201 | * 搜索视频 202 | * @param {UZArgs} args 203 | * @returns {Promise} 204 | */ 205 | async function searchVideo(args) { 206 | var backData = new RepVideoList() 207 | try { 208 | let searchUrl = `${UZUtils.removeTrailingSlash( 209 | appConfig.webSite 210 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 211 | let repData = await req(searchUrl) 212 | 213 | const $ = cheerio.load(repData.data) 214 | let items = $('.module-search-item') 215 | 216 | for (const item of items) { 217 | let video = new VideoDetail() 218 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 219 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 220 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 221 | 'data-src' 222 | ] 223 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 224 | backData.data.push(video) 225 | } 226 | } catch (error) { 227 | backData.error = error 228 | } 229 | return JSON.stringify(backData) 230 | } 231 | 232 | function combineUrl(url) { 233 | if (url === undefined) { 234 | return '' 235 | } 236 | if (url.indexOf(appConfig.webSite) !== -1) { 237 | return url 238 | } 239 | if (url.startsWith('/')) { 240 | return appConfig.webSite + url 241 | } 242 | return appConfig.webSite + '/' + url 243 | } 244 | -------------------------------------------------------------------------------- /vod/js/baijia.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 百家 3 | //@version:1 4 | //@webSite:http://cj.jiexi.news 5 | //@remark: 6 | //@order: B 7 | // ignore 8 | const appConfig = { 9 | _webSite: 'http://cj.jiexi.news', 10 | /** 11 | * 网站主页,uz 调用每个函数前都会进行赋值操作 12 | * 如果不想被改变 请自定义一个变量 13 | */ 14 | get webSite() { 15 | return this._webSite 16 | }, 17 | set webSite(value) { 18 | this._webSite = value 19 | }, 20 | 21 | _uzTag: '', 22 | /** 23 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 24 | * 用于读取环境变量 25 | */ 26 | get uzTag() { 27 | return this._uzTag 28 | }, 29 | set uzTag(value) { 30 | this._uzTag = value 31 | }, 32 | } 33 | 34 | /** 35 | * 异步获取分类列表的方法。 36 | * @param {UZArgs} args 37 | * @returns {Promise} 38 | */ 39 | async function getClassList(args) { 40 | var backData = new RepVideoClassList() 41 | backData.data = [ 42 | { 43 | type_id: '1', 44 | type_name: '电影', 45 | hasSubclass: false, 46 | }, 47 | { 48 | type_id: '2', 49 | type_name: '剧集', 50 | hasSubclass: false, 51 | }, 52 | { 53 | type_id: '4', 54 | type_name: '动漫', 55 | hasSubclass: false, 56 | }, 57 | { 58 | type_id: '3', 59 | type_name: '综艺', 60 | hasSubclass: false, 61 | }, 62 | { 63 | type_id: '39', 64 | type_name: '臻彩', 65 | hasSubclass: false, 66 | }, 67 | { 68 | type_id: '38', 69 | type_name: '天翼|123', 70 | hasSubclass: false, 71 | }, 72 | ] 73 | return JSON.stringify(backData) 74 | } 75 | async function getSubclassList(args) { 76 | let backData = new RepVideoSubclassList() 77 | return JSON.stringify(backData) 78 | } 79 | async function getSubclassVideoList(args) { 80 | var backData = new RepVideoList() 81 | return JSON.stringify(backData) 82 | } 83 | /** 84 | * 获取分类视频列表 85 | * @param {UZArgs} args 86 | * @returns {Promise} 87 | */ 88 | async function getVideoList(args) { 89 | var backData = new RepVideoList() 90 | let url = 91 | UZUtils.removeTrailingSlash(appConfig.webSite) + 92 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 93 | try { 94 | const pro = await req(url) 95 | backData.error = pro.error 96 | let videos = [] 97 | if (pro.data) { 98 | const $ = cheerio.load(pro.data) 99 | let vodItems = $('#main .module-item') 100 | vodItems.each((_, e) => { 101 | let videoDet = new VideoDetail() 102 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 103 | videoDet.vod_name = $(e) 104 | .find('.module-item-pic img') 105 | .attr('alt') 106 | videoDet.vod_pic = $(e) 107 | .find('.module-item-pic img') 108 | .attr('data-src') 109 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 110 | videoDet.vod_year = $(e) 111 | .find('.module-item-caption span') 112 | .first() 113 | .text() 114 | videos.push(videoDet) 115 | }) 116 | } 117 | backData.data = videos 118 | } catch (error) {} 119 | return JSON.stringify(backData) 120 | } 121 | 122 | /** 123 | * 获取视频详情 124 | * @param {UZArgs} args 125 | * @returns {Promise} 126 | */ 127 | async function getVideoDetail(args) { 128 | var backData = new RepVideoDetail() 129 | try { 130 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 131 | let pro = await req(webUrl) 132 | 133 | backData.error = pro.error 134 | let proData = pro.data 135 | if (proData) { 136 | const $ = cheerio.load(proData) 137 | let vodDetail = new VideoDetail() 138 | vodDetail.vod_id = args.url 139 | vodDetail.vod_name = $('.page-title')[0].children[0].data 140 | vodDetail.vod_pic = $($('.mobile-play')).find( 141 | '.lazyload' 142 | )[0].attribs['data-src'] 143 | 144 | let video_items = $('.video-info-itemtitle') 145 | 146 | for (const item of video_items) { 147 | let key = $(item).text() 148 | 149 | let vItems = $(item).next().find('a') 150 | let value = vItems 151 | .map((i, el) => { 152 | let text = $(el).text().trim() // 获取并去除空白字符 153 | return text ? text : null // 只有非空的文本才返回 154 | }) 155 | .get() // 将 jQuery 对象转换为普通数组 156 | .filter(Boolean) // 过滤掉 null 和空字符串 157 | .join(', ') // 用逗号和空格分割 158 | 159 | if (key.includes('剧情')) { 160 | vodDetail.vod_content = $(item) 161 | .next() 162 | .find('p') 163 | .text() 164 | .trim() 165 | } else if (key.includes('导演')) { 166 | vodDetail.vod_director = value.trim() 167 | } else if (key.includes('主演')) { 168 | vodDetail.vod_actor = value.trim() 169 | } 170 | } 171 | 172 | const panUrls = [] 173 | let items = $('.module-row-info') 174 | for (const item of items) { 175 | let shareUrl = $(item).find('p')[0].children[0].data 176 | panUrls.push(shareUrl) 177 | } 178 | vodDetail.panUrls = panUrls 179 | console.log(panUrls) 180 | 181 | backData.data = vodDetail 182 | } 183 | } catch (error) { 184 | backData.error = '获取视频详情失败' + error 185 | } 186 | 187 | return JSON.stringify(backData) 188 | } 189 | 190 | /** 191 | * 获取视频的播放地址 192 | * @param {UZArgs} args 193 | * @returns {Promise} 194 | */ 195 | async function getVideoPlayUrl(args) { 196 | var backData = new RepVideoPlayUrl() 197 | return JSON.stringify(backData) 198 | } 199 | 200 | /** 201 | * 搜索视频 202 | * @param {UZArgs} args 203 | * @returns {Promise} 204 | */ 205 | async function searchVideo(args) { 206 | var backData = new RepVideoList() 207 | try { 208 | let searchUrl = `${UZUtils.removeTrailingSlash( 209 | appConfig.webSite 210 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 211 | let repData = await req(searchUrl) 212 | 213 | const $ = cheerio.load(repData.data) 214 | let items = $('.module-search-item') 215 | 216 | for (const item of items) { 217 | let video = new VideoDetail() 218 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 219 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 220 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 221 | 'data-src' 222 | ] 223 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 224 | backData.data.push(video) 225 | } 226 | } catch (error) { 227 | backData.error = error 228 | } 229 | return JSON.stringify(backData) 230 | } 231 | 232 | function combineUrl(url) { 233 | if (url === undefined) { 234 | return '' 235 | } 236 | if (url.indexOf(appConfig.webSite) !== -1) { 237 | return url 238 | } 239 | if (url.startsWith('/')) { 240 | return appConfig.webSite + url 241 | } 242 | return appConfig.webSite + '/' + url 243 | } 244 | -------------------------------------------------------------------------------- /vod/js/clicli.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「嗅」 clicli 3 | //@version:1 4 | //@webSite:https://www.clicli.pro 5 | //@remark: 6 | //@order: D 7 | // ignore 8 | 9 | // 适用于 把鼠标放在视频封面上 可以右键 复制正确链接的网站 10 | // 不能保证一定能用,不能用的欢迎反馈 11 | 12 | /// 是否模拟 PC 是 1, 手机是 0 13 | const isUsePC = 1 14 | /// 默认应该是 0,当视频不能播放的时候,可以把这个设置为 1, 否则不要改动 15 | const isAddReferer = 1 16 | 17 | // 网站主页 18 | const webSite = 'https://www.clicli.pro' 19 | // 网站搜索 20 | // https://www.clicli.pro/search/page/2/wd/海.html 21 | // 把网站主页变成 @{webSite} 把搜索词变成 @{searchWord} 把页码变成 @{page} 22 | const searchUrl = '@{webSite}/search/page/@{page}/wd/@{searchWord}.html' 23 | // 当前网站任意视频详情页 24 | // https://www.clicli.pro/bangumi/3384.html 25 | const videoDetailPage = '@{webSite}/bangumi/3384.html' 26 | // 当前网站任意视频播放页 27 | // https://www.clicli.pro/video/3384/1-1.html 28 | const videoPlayPage = '@{webSite}/video/3384/1-1.html' 29 | 30 | // 保持不变 31 | const filterListUrl = '' 32 | 33 | const firstClass = [ 34 | { 35 | name: '番剧', 36 | // https://www.clicli.pro/show/id/1/page/2.html 37 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 38 | id: '@{webSite}/show/id/1/page/@{page}.html', 39 | }, 40 | { 41 | name: '剧场版', 42 | // https://www.clicli.pro/show/id/2/page/2.html 43 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 44 | id: '@{webSite}/show/id/2/page/@{page}.html', 45 | }, 46 | ] 47 | 48 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 49 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 50 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 51 | 52 | //#BaseCode1# 53 | -------------------------------------------------------------------------------- /vod/js/cms.js: -------------------------------------------------------------------------------- 1 | //@name:「解」 虾米 2 | //@version:3 3 | //@webSite:https://zy.hls.one/api.php/provide/vod 4 | //@remark:通用官采解析1,需配合网盘解析工具使用。每次消耗所有解析次数! 5 | // @order: A 6 | 7 | // ignore 8 | // 不支持导入,这里只是本地开发用于代码提示 9 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 10 | import { 11 | FilterLabel, 12 | FilterTitle, 13 | VideoClass, 14 | VideoSubclass, 15 | VideoDetail, 16 | RepVideoClassList, 17 | RepVideoSubclassList, 18 | RepVideoList, 19 | RepVideoDetail, 20 | RepVideoPlayUrl, 21 | UZArgs, 22 | UZSubclassVideoListArgs, 23 | } from '../../core/core/uzVideo.js' 24 | 25 | import { 26 | UZUtils, 27 | ProData, 28 | ReqResponseType, 29 | ReqAddressType, 30 | req, 31 | getEnv, 32 | setEnv, 33 | goToVerify, 34 | openWebToBindEnv, 35 | toast, 36 | kIsDesktop, 37 | kIsAndroid, 38 | kIsIOS, 39 | kIsWindows, 40 | kIsMacOS, 41 | kIsTV, 42 | kLocale, 43 | kAppVersion, 44 | formatBackData, 45 | } from '../../core/core/uzUtils.js' 46 | 47 | import { cheerio, Crypto, Encrypt, JSONbig } from '../../core/core/uz3lib.js' 48 | // ignore 49 | 50 | const appConfig = { 51 | _webSite: 'https://zy.hls.one/api.php/provide/vod', 52 | /** 53 | * 网站主页,uz 调用每个函数前都会进行赋值操作 54 | * 如果不想被改变 请自定义一个变量 55 | */ 56 | get webSite() { 57 | return this._webSite 58 | }, 59 | set webSite(value) { 60 | this._webSite = value 61 | }, 62 | 63 | _uzTag: '', 64 | /** 65 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 66 | * 用于读取环境变量 67 | */ 68 | get uzTag() { 69 | return this._uzTag 70 | }, 71 | set uzTag(value) { 72 | this._uzTag = value 73 | }, 74 | 75 | ignoreClassName: ['vip', 'qq', '免费', '群', '公告'], 76 | } 77 | 78 | /** 79 | * 异步获取分类列表的方法。 80 | * @param {UZArgs} args 81 | * @returns {@Promise} 82 | */ 83 | async function getClassList(args) { 84 | var backData = new RepVideoClassList() 85 | try { 86 | let response = await req(appConfig.webSite) 87 | let data = JSON.parse(response.data) 88 | backData.data = data.class.filter((item) => { 89 | const typeName = item.type_name.toLowerCase() 90 | return !appConfig.ignoreClassName.some((keyword) => 91 | typeName.includes(keyword.toLowerCase()) 92 | ) 93 | }) 94 | } catch (error) { 95 | backData.error = error.toString() 96 | } 97 | return JSON.stringify(backData) 98 | } 99 | 100 | /** 101 | * 获取二级分类列表筛选列表的方法。 102 | * @param {UZArgs} args 103 | * @returns {@Promise} 104 | */ 105 | async function getSubclassList(args) { 106 | var backData = new RepVideoSubclassList() 107 | try { 108 | } catch (error) { 109 | backData.error = error.toString() 110 | } 111 | return JSON.stringify(backData) 112 | } 113 | 114 | /** 115 | * 获取分类视频列表 116 | * @param {UZArgs} args 117 | * @returns {@Promise} 118 | */ 119 | async function getVideoList(args) { 120 | var backData = new RepVideoList() 121 | try { 122 | let response = await req( 123 | `${appConfig.webSite}?ac=detail&t=${args.url}&pg=${args.page}` 124 | ) 125 | let data = JSON.parse(response.data) 126 | backData.data = data.list 127 | } catch (error) { 128 | backData.error = error.toString() 129 | } 130 | return JSON.stringify(backData) 131 | } 132 | 133 | /** 134 | * 获取二级分类视频列表 或 筛选视频列表 135 | * @param {UZSubclassVideoListArgs} args 136 | * @returns {@Promise} 137 | */ 138 | async function getSubclassVideoList(args) { 139 | var backData = new RepVideoList() 140 | try { 141 | } catch (error) { 142 | backData.error = error.toString() 143 | } 144 | return JSON.stringify(backData) 145 | } 146 | 147 | /** 148 | * 获取视频详情 149 | * @param {UZArgs} args 150 | * @returns {@Promise} 151 | */ 152 | async function getVideoDetail(args) { 153 | var backData = new RepVideoDetail() 154 | try { 155 | let response = await req( 156 | `${appConfig.webSite}?ac=detail&ids=${args.url}` 157 | ) 158 | let data = JSON.parse(response.data) 159 | let video = data.list[0] 160 | video.panUrls = video.vod_play_url.split('$$$') 161 | video.vod_play_url = '' 162 | backData.data = video 163 | } catch (error) { 164 | backData.error = error.toString() 165 | } 166 | return JSON.stringify(backData) 167 | } 168 | 169 | /** 170 | * 获取视频的播放地址 171 | * @param {UZArgs} args 172 | * @returns {@Promise} 173 | */ 174 | async function getVideoPlayUrl(args) { 175 | var backData = new RepVideoPlayUrl() 176 | try { 177 | } catch (error) { 178 | backData.error = error.toString() 179 | } 180 | return JSON.stringify(backData) 181 | } 182 | 183 | /** 184 | * 搜索视频 185 | * @param {UZArgs} args 186 | * @returns {@Promise} 187 | */ 188 | async function searchVideo(args) { 189 | var backData = new RepVideoList() 190 | try { 191 | const response = await req( 192 | `${appConfig.webSite}?ac=detail&wd=${args.searchWord}&pg=${args.page}` 193 | ) 194 | const data = JSON.parse(response.data) 195 | backData.data = data.list 196 | } catch (error) { 197 | backData.error = error.toString() 198 | } 199 | return JSON.stringify(backData) 200 | } 201 | -------------------------------------------------------------------------------- /vod/js/cms2.js: -------------------------------------------------------------------------------- 1 | //@name:「解」 虾米 2 | //@version:1 3 | //@webSite:https://zy.hls.one/api.php/provide/vod 4 | //@remark:通用官采解析2,需配合网盘解析工具使用。在环境变量配置 采集解析地址。 5 | //@env:采集解析地址##内置两个,失效不要反馈。格式:名称1@地址1;名称2@地址2 6 | // @order: A 7 | 8 | // ignore 9 | // 不支持导入,这里只是本地开发用于代码提示 10 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 11 | import { 12 | FilterLabel, 13 | FilterTitle, 14 | VideoClass, 15 | VideoSubclass, 16 | VideoDetail, 17 | RepVideoClassList, 18 | RepVideoSubclassList, 19 | RepVideoList, 20 | RepVideoDetail, 21 | RepVideoPlayUrl, 22 | UZArgs, 23 | UZSubclassVideoListArgs, 24 | } from '../../core/core/uzVideo.js' 25 | 26 | import { 27 | UZUtils, 28 | ProData, 29 | ReqResponseType, 30 | ReqAddressType, 31 | req, 32 | getEnv, 33 | setEnv, 34 | goToVerify, 35 | openWebToBindEnv, 36 | toast, 37 | kIsDesktop, 38 | kIsAndroid, 39 | kIsIOS, 40 | kIsWindows, 41 | kIsMacOS, 42 | kIsTV, 43 | kLocale, 44 | kAppVersion, 45 | formatBackData, 46 | } from '../../core/core/uzUtils.js' 47 | 48 | import { cheerio, Crypto, Encrypt, JSONbig } from '../../core/core/uz3lib.js' 49 | // ignore 50 | 51 | const appConfig = { 52 | _webSite: 'https://zy.hls.one/api.php/provide/vod', 53 | /** 54 | * 网站主页,uz 调用每个函数前都会进行赋值操作 55 | * 如果不想被改变 请自定义一个变量 56 | */ 57 | get webSite() { 58 | return this._webSite 59 | }, 60 | set webSite(value) { 61 | this._webSite = value 62 | }, 63 | 64 | _uzTag: '', 65 | /** 66 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 67 | * 用于读取环境变量 68 | */ 69 | get uzTag() { 70 | return this._uzTag 71 | }, 72 | set uzTag(value) { 73 | this._uzTag = value 74 | }, 75 | 76 | ignoreClassName: ['vip', 'qq', '免费', '群', '公告'], 77 | 78 | 79 | jiexiMap:{} 80 | } 81 | 82 | /** 83 | * 异步获取分类列表的方法。 84 | * @param {UZArgs} args 85 | * @returns {@Promise} 86 | */ 87 | async function getClassList(args) { 88 | var backData = new RepVideoClassList() 89 | try { 90 | let response = await req(appConfig.webSite) 91 | let data = JSON.parse(response.data) 92 | backData.data = data.class.filter((item) => { 93 | const typeName = item.type_name.toLowerCase() 94 | return !appConfig.ignoreClassName.some((keyword) => 95 | typeName.includes(keyword.toLowerCase()) 96 | ) 97 | }) 98 | } catch (error) { 99 | backData.error = error.toString() 100 | } 101 | return JSON.stringify(backData) 102 | } 103 | 104 | /** 105 | * 获取二级分类列表筛选列表的方法。 106 | * @param {UZArgs} args 107 | * @returns {@Promise} 108 | */ 109 | async function getSubclassList(args) { 110 | var backData = new RepVideoSubclassList() 111 | try { 112 | } catch (error) { 113 | backData.error = error.toString() 114 | } 115 | return JSON.stringify(backData) 116 | } 117 | 118 | /** 119 | * 获取分类视频列表 120 | * @param {UZArgs} args 121 | * @returns {@Promise} 122 | */ 123 | async function getVideoList(args) { 124 | var backData = new RepVideoList() 125 | try { 126 | let response = await req( 127 | `${appConfig.webSite}?ac=detail&t=${args.url}&pg=${args.page}` 128 | ) 129 | let data = JSON.parse(response.data) 130 | backData.data = data.list 131 | } catch (error) { 132 | backData.error = error.toString() 133 | } 134 | return JSON.stringify(backData) 135 | } 136 | 137 | /** 138 | * 获取二级分类视频列表 或 筛选视频列表 139 | * @param {UZSubclassVideoListArgs} args 140 | * @returns {@Promise} 141 | */ 142 | async function getSubclassVideoList(args) { 143 | var backData = new RepVideoList() 144 | try { 145 | } catch (error) { 146 | backData.error = error.toString() 147 | } 148 | return JSON.stringify(backData) 149 | } 150 | 151 | 152 | 153 | 154 | /** 155 | * 获取视频详情 156 | * @param {UZArgs} args 157 | * @returns {@Promise} 158 | */ 159 | async function getVideoDetail(args) { 160 | var backData = new RepVideoDetail() 161 | try { 162 | let response = await req( 163 | `${appConfig.webSite}?ac=detail&ids=${args.url}` 164 | ) 165 | let data = JSON.parse(response.data) 166 | let video = data.list[0] 167 | let allUrls = await getEnv(appConfig.uzTag, '采集解析地址') 168 | if (allUrls.length < 1) { 169 | allUrls = 170 | '钓鱼@http://8.129.30.117:8117/diaoyu.php?url=;乌贼@http://jx.dedyn.io/?url=' 171 | await setEnv(appConfig.uzTag, '采集解析地址', allUrls) 172 | } 173 | const jxLinks = allUrls.split(';') 174 | 175 | const singleFrom = video.vod_play_url.replace(/\${3}/g, '#') 176 | let allFrom = "" 177 | let fromNames = "" 178 | for (let i = 0; i < jxLinks.length; i++) { 179 | allFrom += singleFrom + "$$$" 180 | const fromName = jxLinks[i].split('@')[0] 181 | const fromUrl = jxLinks[i].split('@')[1] 182 | fromNames += fromName + "$$$" 183 | appConfig.jiexiMap[fromName] = fromUrl 184 | } 185 | if (allFrom.endsWith('$$$')) { 186 | allFrom = allFrom.slice(0, -3) 187 | } 188 | if (fromNames.endsWith('$$$')) { 189 | fromNames = fromNames.slice(0, -3) 190 | } 191 | 192 | video.vod_play_url = allFrom 193 | video.vod_play_from = fromNames 194 | backData.data = video 195 | } catch (error) { 196 | backData.error = error.toString() 197 | } 198 | return JSON.stringify(backData) 199 | } 200 | 201 | /** 202 | * 获取视频的播放地址 203 | * @param {UZArgs} args 204 | * @returns {@Promise} 205 | */ 206 | async function getVideoPlayUrl(args) { 207 | var backData = new RepVideoPlayUrl() 208 | try { 209 | const api = appConfig.jiexiMap[args.flag] 210 | const response = await req(api + args.url) 211 | 212 | if (response.code === 200) { 213 | let item 214 | try { 215 | item = JSON.parse(response.data) 216 | } catch (error) { 217 | item = response.data 218 | } 219 | if (item) { 220 | for (let key in item) { 221 | if (item.hasOwnProperty(key)) { 222 | let value = item[key] 223 | if (value && typeof value === 'string') { 224 | if ( 225 | value.includes('http') && 226 | (value.includes('m3u8') || 227 | value.includes('mp4')) 228 | ) { 229 | backData.data = value 230 | break 231 | } 232 | } 233 | } 234 | } 235 | } 236 | } 237 | 238 | 239 | } catch (error) { 240 | backData.error = error.toString() 241 | } 242 | return JSON.stringify(backData) 243 | } 244 | 245 | /** 246 | * 搜索视频 247 | * @param {UZArgs} args 248 | * @returns {@Promise} 249 | */ 250 | async function searchVideo(args) { 251 | var backData = new RepVideoList() 252 | try { 253 | const response = await req( 254 | `${appConfig.webSite}?ac=detail&wd=${args.searchWord}&pg=${args.page}` 255 | ) 256 | const data = JSON.parse(response.data) 257 | backData.data = data.list 258 | } catch (error) { 259 | backData.error = error.toString() 260 | } 261 | return JSON.stringify(backData) 262 | } -------------------------------------------------------------------------------- /vod/js/cms3.js: -------------------------------------------------------------------------------- 1 | //@name:「解」 小猫咪 2 | //@version:1 3 | //@webSite:https://zy.xiaomaomi.cc/api.php/provide/vod 4 | //@remark:通用官采解析2,需配合网盘解析工具使用。在环境变量配置 采集解析地址。 5 | //@env:采集解析地址##内置两个,失效不要反馈。格式:名称1@地址1;名称2@地址2 6 | // @order: A 7 | 8 | // ignore 9 | // 不支持导入,这里只是本地开发用于代码提示 10 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 11 | import { 12 | FilterLabel, 13 | FilterTitle, 14 | VideoClass, 15 | VideoSubclass, 16 | VideoDetail, 17 | RepVideoClassList, 18 | RepVideoSubclassList, 19 | RepVideoList, 20 | RepVideoDetail, 21 | RepVideoPlayUrl, 22 | UZArgs, 23 | UZSubclassVideoListArgs, 24 | } from '../../core/core/uzVideo.js' 25 | 26 | import { 27 | UZUtils, 28 | ProData, 29 | ReqResponseType, 30 | ReqAddressType, 31 | req, 32 | getEnv, 33 | setEnv, 34 | goToVerify, 35 | openWebToBindEnv, 36 | toast, 37 | kIsDesktop, 38 | kIsAndroid, 39 | kIsIOS, 40 | kIsWindows, 41 | kIsMacOS, 42 | kIsTV, 43 | kLocale, 44 | kAppVersion, 45 | formatBackData, 46 | } from '../../core/core/uzUtils.js' 47 | 48 | import { cheerio, Crypto, Encrypt, JSONbig } from '../../core/core/uz3lib.js' 49 | // ignore 50 | 51 | const appConfig = { 52 | _webSite: 'https://zy.xiaomaomi.cc/api.php/provide/vod', 53 | /** 54 | * 网站主页,uz 调用每个函数前都会进行赋值操作 55 | * 如果不想被改变 请自定义一个变量 56 | */ 57 | get webSite() { 58 | return this._webSite 59 | }, 60 | set webSite(value) { 61 | this._webSite = value 62 | }, 63 | 64 | _uzTag: '', 65 | /** 66 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 67 | * 用于读取环境变量 68 | */ 69 | get uzTag() { 70 | return this._uzTag 71 | }, 72 | set uzTag(value) { 73 | this._uzTag = value 74 | }, 75 | 76 | ignoreClassName: ['短剧', '资讯', '明星资讯', '影视资讯', '演员', '内地', '港台', '欧美', '日韩'], 77 | 78 | 79 | jiexiMap:{} 80 | } 81 | 82 | /** 83 | * 异步获取分类列表的方法。 84 | * @param {UZArgs} args 85 | * @returns {@Promise} 86 | */ 87 | async function getClassList(args) { 88 | var backData = new RepVideoClassList() 89 | try { 90 | let response = await req(appConfig.webSite) 91 | let data = JSON.parse(response.data) 92 | backData.data = data.class.filter((item) => { 93 | const typeName = item.type_name.toLowerCase() 94 | return !appConfig.ignoreClassName.some((keyword) => 95 | typeName.includes(keyword.toLowerCase()) 96 | ) 97 | }) 98 | } catch (error) { 99 | backData.error = error.toString() 100 | } 101 | return JSON.stringify(backData) 102 | } 103 | 104 | /** 105 | * 获取二级分类列表筛选列表的方法。 106 | * @param {UZArgs} args 107 | * @returns {@Promise} 108 | */ 109 | async function getSubclassList(args) { 110 | var backData = new RepVideoSubclassList() 111 | try { 112 | } catch (error) { 113 | backData.error = error.toString() 114 | } 115 | return JSON.stringify(backData) 116 | } 117 | 118 | /** 119 | * 获取分类视频列表 120 | * @param {UZArgs} args 121 | * @returns {@Promise} 122 | */ 123 | async function getVideoList(args) { 124 | var backData = new RepVideoList() 125 | try { 126 | let response = await req( 127 | `${appConfig.webSite}?ac=detail&t=${args.url}&pg=${args.page}` 128 | ) 129 | let data = JSON.parse(response.data) 130 | backData.data = data.list 131 | } catch (error) { 132 | backData.error = error.toString() 133 | } 134 | return JSON.stringify(backData) 135 | } 136 | 137 | /** 138 | * 获取二级分类视频列表 或 筛选视频列表 139 | * @param {UZSubclassVideoListArgs} args 140 | * @returns {@Promise} 141 | */ 142 | async function getSubclassVideoList(args) { 143 | var backData = new RepVideoList() 144 | try { 145 | } catch (error) { 146 | backData.error = error.toString() 147 | } 148 | return JSON.stringify(backData) 149 | } 150 | 151 | 152 | 153 | 154 | /** 155 | * 获取视频详情 156 | * @param {UZArgs} args 157 | * @returns {@Promise} 158 | */ 159 | async function getVideoDetail(args) { 160 | var backData = new RepVideoDetail() 161 | try { 162 | let response = await req( 163 | `${appConfig.webSite}?ac=detail&ids=${args.url}` 164 | ) 165 | let data = JSON.parse(response.data) 166 | let video = data.list[0] 167 | let allUrls = await getEnv(appConfig.uzTag, '采集解析地址') 168 | if (allUrls.length < 1) { 169 | allUrls = 170 | '钓鱼@http://8.129.30.117:8117/diaoyu.php?url=;乌贼@http://jx.dedyn.io/?url=' 171 | await setEnv(appConfig.uzTag, '采集解析地址', allUrls) 172 | } 173 | const jxLinks = allUrls.split(';') 174 | 175 | const singleFrom = video.vod_play_url.replace(/\${3}/g, '#') 176 | let allFrom = "" 177 | let fromNames = "" 178 | for (let i = 0; i < jxLinks.length; i++) { 179 | allFrom += singleFrom + "$$$" 180 | const fromName = jxLinks[i].split('@')[0] 181 | const fromUrl = jxLinks[i].split('@')[1] 182 | fromNames += fromName + "$$$" 183 | appConfig.jiexiMap[fromName] = fromUrl 184 | } 185 | if (allFrom.endsWith('$$$')) { 186 | allFrom = allFrom.slice(0, -3) 187 | } 188 | if (fromNames.endsWith('$$$')) { 189 | fromNames = fromNames.slice(0, -3) 190 | } 191 | 192 | video.vod_play_url = allFrom 193 | video.vod_play_from = fromNames 194 | backData.data = video 195 | } catch (error) { 196 | backData.error = error.toString() 197 | } 198 | return JSON.stringify(backData) 199 | } 200 | 201 | /** 202 | * 获取视频的播放地址 203 | * @param {UZArgs} args 204 | * @returns {@Promise} 205 | */ 206 | async function getVideoPlayUrl(args) { 207 | var backData = new RepVideoPlayUrl() 208 | try { 209 | const api = appConfig.jiexiMap[args.flag] 210 | const response = await req(api + args.url) 211 | 212 | if (response.code === 200) { 213 | let item 214 | try { 215 | item = JSON.parse(response.data) 216 | } catch (error) { 217 | item = response.data 218 | } 219 | if (item) { 220 | for (let key in item) { 221 | if (item.hasOwnProperty(key)) { 222 | let value = item[key] 223 | if (value && typeof value === 'string') { 224 | if ( 225 | value.includes('http') && 226 | (value.includes('m3u8') || 227 | value.includes('mp4')) 228 | ) { 229 | backData.data = value 230 | break 231 | } 232 | } 233 | } 234 | } 235 | } 236 | } 237 | 238 | 239 | } catch (error) { 240 | backData.error = error.toString() 241 | } 242 | return JSON.stringify(backData) 243 | } 244 | 245 | /** 246 | * 搜索视频 247 | * @param {UZArgs} args 248 | * @returns {@Promise} 249 | */ 250 | async function searchVideo(args) { 251 | var backData = new RepVideoList() 252 | try { 253 | const response = await req( 254 | `${appConfig.webSite}?ac=detail&wd=${args.searchWord}&pg=${args.page}` 255 | ) 256 | const data = JSON.parse(response.data) 257 | backData.data = data.list 258 | } catch (error) { 259 | backData.error = error.toString() 260 | } 261 | return JSON.stringify(backData) 262 | } -------------------------------------------------------------------------------- /vod/js/cmsUser.js: -------------------------------------------------------------------------------- 1 | //@name:自行搭建的 cms 2 | //@version:1 3 | //@webSite:https://cj.rycjapi.com/api.php/provide/vod 4 | //@remark:地址输入自己搭建的 cms 采集地址,默认使用如意采集占位 5 | 6 | // ignore 7 | // 不支持导入,这里只是本地开发用于代码提示 8 | // 如需添加通用依赖,请联系 https://t.me/uzVideoAppbot 9 | import { 10 | FilterLabel, 11 | FilterTitle, 12 | VideoClass, 13 | VideoSubclass, 14 | VideoDetail, 15 | RepVideoClassList, 16 | RepVideoSubclassList, 17 | RepVideoList, 18 | RepVideoDetail, 19 | RepVideoPlayUrl, 20 | UZArgs, 21 | UZSubclassVideoListArgs, 22 | } from '../../core/core/uzVideo.js' 23 | 24 | import { 25 | UZUtils, 26 | ProData, 27 | ReqResponseType, 28 | ReqAddressType, 29 | req, 30 | getEnv, 31 | setEnv, 32 | goToVerify, 33 | openWebToBindEnv, 34 | toast, 35 | kIsDesktop, 36 | kIsAndroid, 37 | kIsIOS, 38 | kIsWindows, 39 | kIsMacOS, 40 | kIsTV, 41 | kLocale, 42 | kAppVersion, 43 | formatBackData, 44 | } from '../../core/core/uzUtils.js' 45 | 46 | import { cheerio, Crypto, Encrypt, JSONbig } from '../../core/core/uz3lib.js' 47 | // ignore 48 | 49 | const appConfig = { 50 | _webSite: 'https://cj.rycjapi.com/api.php/provide/vod', 51 | /** 52 | * 网站主页,uz 调用每个函数前都会进行赋值操作 53 | * 如果不想被改变 请自定义一个变量 54 | */ 55 | get webSite() { 56 | return this._webSite 57 | }, 58 | set webSite(value) { 59 | this._webSite = value 60 | }, 61 | 62 | _uzTag: '', 63 | /** 64 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 65 | * 用于读取环境变量 66 | */ 67 | get uzTag() { 68 | return this._uzTag 69 | }, 70 | set uzTag(value) { 71 | this._uzTag = value 72 | }, 73 | // 忽略的分类名称列表 74 | ignoreClassName: ['短剧', '资讯', '明星资讯', '影视资讯', '演员', '内地', '港台', '欧美', '日韩'], 75 | 76 | reqOptions: { 77 | // 接受数据超时时间 78 | receiveTimeout: 40, 79 | }, 80 | } 81 | 82 | /** 83 | * 异步获取分类列表的方法。 84 | * @param {UZArgs} args 85 | * @returns {@Promise} 86 | */ 87 | async function getClassList(args) { 88 | var backData = new RepVideoClassList() 89 | try { 90 | let response = await req(appConfig.webSite, appConfig.reqOptions) 91 | let data = JSON.parse(response.data) 92 | backData.data = data.class.filter((item) => { 93 | const typeName = item.type_name.toLowerCase() 94 | return !appConfig.ignoreClassName.some((keyword) => typeName.includes(keyword.toLowerCase())) 95 | }) 96 | } catch (error) { 97 | backData.error = error.toString() 98 | } 99 | return JSON.stringify(backData) 100 | } 101 | 102 | /** 103 | * 获取二级分类列表筛选列表的方法。 104 | * @param {UZArgs} args 105 | * @returns {@Promise} 106 | */ 107 | async function getSubclassList(args) { 108 | var backData = new RepVideoSubclassList() 109 | try { 110 | } catch (error) { 111 | backData.error = error.toString() 112 | } 113 | return JSON.stringify(backData) 114 | } 115 | 116 | /** 117 | * 获取分类视频列表 118 | * @param {UZArgs} args 119 | * @returns {@Promise} 120 | */ 121 | async function getVideoList(args) { 122 | var backData = new RepVideoList() 123 | try { 124 | let response = await req(`${appConfig.webSite}?ac=detail&t=${args.url}&pg=${args.page}`, appConfig.reqOptions) 125 | let data = JSON.parse(response.data) 126 | backData.data = data.list 127 | } catch (error) { 128 | backData.error = error.toString() 129 | } 130 | return JSON.stringify(backData) 131 | } 132 | 133 | /** 134 | * 获取二级分类视频列表 或 筛选视频列表 135 | * @param {UZSubclassVideoListArgs} args 136 | * @returns {@Promise} 137 | */ 138 | async function getSubclassVideoList(args) { 139 | var backData = new RepVideoList() 140 | try { 141 | } catch (error) { 142 | backData.error = error.toString() 143 | } 144 | return JSON.stringify(backData) 145 | } 146 | 147 | /** 148 | * 获取视频详情 149 | * @param {UZArgs} args 150 | * @returns {@Promise} 151 | */ 152 | async function getVideoDetail(args) { 153 | var backData = new RepVideoDetail() 154 | try { 155 | let response = await req(`${appConfig.webSite}?ac=detail&ids=${args.url}`, appConfig.reqOptions) 156 | let data = JSON.parse(response.data) 157 | let video = data.list[0] 158 | backData.data = video 159 | } catch (error) { 160 | backData.error = error.toString() 161 | } 162 | return JSON.stringify(backData) 163 | } 164 | 165 | /** 166 | * 获取视频的播放地址 167 | * @param {UZArgs} args 168 | * @returns {@Promise} 169 | */ 170 | async function getVideoPlayUrl(args) { 171 | var backData = new RepVideoPlayUrl() 172 | try { 173 | backData.data = args.url 174 | } catch (error) { 175 | backData.error = error.toString() 176 | } 177 | return JSON.stringify(backData) 178 | } 179 | 180 | /** 181 | * 搜索视频 182 | * @param {UZArgs} args 183 | * @returns {@Promise} 184 | */ 185 | async function searchVideo(args) { 186 | var backData = new RepVideoList() 187 | try { 188 | const response = await req(`${appConfig.webSite}?ac=detail&wd=${args.searchWord}&pg=${args.page}`, appConfig.reqOptions) 189 | const data = JSON.parse(response.data) 190 | backData.data = data.list 191 | } catch (error) { 192 | backData.error = error.toString() 193 | } 194 | return JSON.stringify(backData) 195 | } 196 | -------------------------------------------------------------------------------- /vod/js/dawanou.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 大玩ou 3 | //@version:1 4 | //@webSite:http://149.88.87.18:6688 5 | //@remark: 6 | //@order: B 7 | // ignore 8 | const appConfig = { 9 | _webSite: 'http://149.88.87.18:6688', 10 | /** 11 | * 网站主页,uz 调用每个函数前都会进行赋值操作 12 | * 如果不想被改变 请自定义一个变量 13 | */ 14 | get webSite() { 15 | return this._webSite 16 | }, 17 | set webSite(value) { 18 | this._webSite = value 19 | }, 20 | 21 | _uzTag: '', 22 | /** 23 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 24 | * 用于读取环境变量 25 | */ 26 | get uzTag() { 27 | return this._uzTag 28 | }, 29 | set uzTag(value) { 30 | this._uzTag = value 31 | }, 32 | } 33 | 34 | /** 35 | * 异步获取分类列表的方法。 36 | * @param {UZArgs} args 37 | * @returns {Promise} 38 | */ 39 | async function getClassList(args) { 40 | var backData = new RepVideoClassList() 41 | backData.data = [ 42 | { 43 | type_id: '1', 44 | type_name: '电影', 45 | hasSubclass: false, 46 | }, 47 | { 48 | type_id: '2', 49 | type_name: '剧集', 50 | hasSubclass: false, 51 | }, 52 | { 53 | type_id: '3', 54 | type_name: '动漫', 55 | hasSubclass: false, 56 | }, 57 | { 58 | type_id: '4', 59 | type_name: '综艺', 60 | hasSubclass: false, 61 | }, 62 | { 63 | type_id: '5', 64 | type_name: '音乐', 65 | hasSubclass: false, 66 | }, 67 | { 68 | type_id: '20', 69 | type_name: '短剧', 70 | hasSubclass: false, 71 | }, 72 | { 73 | type_id: '21', 74 | type_name: '记录', 75 | hasSubclass: false, 76 | }, 77 | { 78 | type_id: '22', 79 | type_name: '4k高码', 80 | hasSubclass: false, 81 | }, 82 | ] 83 | return JSON.stringify(backData) 84 | } 85 | async function getSubclassList(args) { 86 | let backData = new RepVideoSubclassList() 87 | return JSON.stringify(backData) 88 | } 89 | async function getSubclassVideoList(args) { 90 | var backData = new RepVideoList() 91 | return JSON.stringify(backData) 92 | } 93 | /** 94 | * 获取分类视频列表 95 | * @param {UZArgs} args 96 | * @returns {Promise} 97 | */ 98 | async function getVideoList(args) { 99 | var backData = new RepVideoList() 100 | let url = 101 | UZUtils.removeTrailingSlash(appConfig.webSite) + 102 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 103 | try { 104 | const pro = await req(url) 105 | backData.error = pro.error 106 | let videos = [] 107 | if (pro.data) { 108 | const $ = cheerio.load(pro.data) 109 | let vodItems = $('#main .module-item') 110 | vodItems.each((_, e) => { 111 | let videoDet = new VideoDetail() 112 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 113 | videoDet.vod_name = $(e) 114 | .find('.module-item-pic img') 115 | .attr('alt') 116 | videoDet.vod_pic = $(e) 117 | .find('.module-item-pic img') 118 | .attr('data-src') 119 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 120 | videoDet.vod_year = $(e) 121 | .find('.module-item-caption span') 122 | .first() 123 | .text() 124 | videos.push(videoDet) 125 | }) 126 | } 127 | backData.data = videos 128 | } catch (error) {} 129 | return JSON.stringify(backData) 130 | } 131 | 132 | /** 133 | * 获取视频详情 134 | * @param {UZArgs} args 135 | * @returns {Promise} 136 | */ 137 | async function getVideoDetail(args) { 138 | var backData = new RepVideoDetail() 139 | try { 140 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 141 | let pro = await req(webUrl) 142 | 143 | backData.error = pro.error 144 | let proData = pro.data 145 | if (proData) { 146 | const $ = cheerio.load(proData) 147 | let vodDetail = new VideoDetail() 148 | vodDetail.vod_id = args.url 149 | vodDetail.vod_name = $('.page-title')[0].children[0].data 150 | vodDetail.vod_pic = $($('.mobile-play')).find( 151 | '.lazyload' 152 | )[0].attribs['data-src'] 153 | 154 | let video_items = $('.video-info-itemtitle') 155 | 156 | for (const item of video_items) { 157 | let key = $(item).text() 158 | 159 | let vItems = $(item).next().find('a') 160 | let value = vItems 161 | .map((i, el) => { 162 | let text = $(el).text().trim() // 获取并去除空白字符 163 | return text ? text : null // 只有非空的文本才返回 164 | }) 165 | .get() // 将 jQuery 对象转换为普通数组 166 | .filter(Boolean) // 过滤掉 null 和空字符串 167 | .join(', ') // 用逗号和空格分割 168 | 169 | if (key.includes('剧情')) { 170 | vodDetail.vod_content = $(item) 171 | .next() 172 | .find('p') 173 | .text() 174 | .trim() 175 | } else if (key.includes('导演')) { 176 | vodDetail.vod_director = value.trim() 177 | } else if (key.includes('主演')) { 178 | vodDetail.vod_actor = value.trim() 179 | } 180 | } 181 | 182 | const panUrls = [] 183 | let items = $('.module-row-info') 184 | for (const item of items) { 185 | let shareUrl = $(item).find('p')[0].children[0].data 186 | panUrls.push(shareUrl) 187 | } 188 | vodDetail.panUrls = panUrls 189 | console.log(panUrls) 190 | 191 | backData.data = vodDetail 192 | } 193 | } catch (error) { 194 | backData.error = '获取视频详情失败' + error 195 | } 196 | 197 | return JSON.stringify(backData) 198 | } 199 | 200 | /** 201 | * 获取视频的播放地址 202 | * @param {UZArgs} args 203 | * @returns {Promise} 204 | */ 205 | async function getVideoPlayUrl(args) { 206 | var backData = new RepVideoPlayUrl() 207 | return JSON.stringify(backData) 208 | } 209 | 210 | /** 211 | * 搜索视频 212 | * @param {UZArgs} args 213 | * @returns {Promise} 214 | */ 215 | async function searchVideo(args) { 216 | var backData = new RepVideoList() 217 | try { 218 | let searchUrl = `${UZUtils.removeTrailingSlash( 219 | appConfig.webSite 220 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 221 | let repData = await req(searchUrl) 222 | 223 | const $ = cheerio.load(repData.data) 224 | let items = $('.module-search-item') 225 | 226 | for (const item of items) { 227 | let video = new VideoDetail() 228 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 229 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 230 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 231 | 'data-src' 232 | ] 233 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 234 | backData.data.push(video) 235 | } 236 | } catch (error) { 237 | backData.error = error 238 | } 239 | return JSON.stringify(backData) 240 | } 241 | 242 | function combineUrl(url) { 243 | if (url === undefined) { 244 | return '' 245 | } 246 | if (url.indexOf(appConfig.webSite) !== -1) { 247 | return url 248 | } 249 | if (url.startsWith('/')) { 250 | return appConfig.webSite + url 251 | } 252 | return appConfig.webSite + '/' + url 253 | } 254 | -------------------------------------------------------------------------------- /vod/js/duoduo.js: -------------------------------------------------------------------------------- 1 | //@version:3 2 | //@name:「盘」 多多 3 | //@webSite:https://tv.yydsys.top 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://tv.yydsys.top', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '多多电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '多多剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '5', 52 | type_name: '多多短剧', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '多多动漫', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '3', 62 | type_name: '多多综艺', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '20', 67 | type_name: '多多纪录', 68 | hasSubclass: false, 69 | }, 70 | ] 71 | return JSON.stringify(backData) 72 | } 73 | async function getSubclassList(args) { 74 | let backData = new RepVideoSubclassList() 75 | return JSON.stringify(backData) 76 | } 77 | async function getSubclassVideoList(args) { 78 | var backData = new RepVideoList() 79 | return JSON.stringify(backData) 80 | } 81 | /** 82 | * 获取分类视频列表 83 | * @param {UZArgs} args 84 | * @returns {Promise} 85 | */ 86 | async function getVideoList(args) { 87 | var backData = new RepVideoList() 88 | let url = 89 | UZUtils.removeTrailingSlash(appConfig.webSite) + 90 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 91 | try { 92 | const pro = await req(url) 93 | backData.error = pro.error 94 | let videos = [] 95 | if (pro.data) { 96 | const $ = cheerio.load(pro.data) 97 | let vodItems = $('#main .module-item') 98 | vodItems.each((_, e) => { 99 | let videoDet = new VideoDetail() 100 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 101 | videoDet.vod_name = $(e) 102 | .find('.module-item-pic img') 103 | .attr('alt') 104 | videoDet.vod_pic = $(e) 105 | .find('.module-item-pic img') 106 | .attr('data-src') 107 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 108 | videoDet.vod_year = $(e) 109 | .find('.module-item-caption span') 110 | .first() 111 | .text() 112 | videos.push(videoDet) 113 | }) 114 | } 115 | backData.data = videos 116 | } catch (error) {} 117 | return JSON.stringify(backData) 118 | } 119 | 120 | /** 121 | * 获取视频详情 122 | * @param {UZArgs} args 123 | * @returns {Promise} 124 | */ 125 | async function getVideoDetail(args) { 126 | var backData = new RepVideoDetail() 127 | try { 128 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 129 | let pro = await req(webUrl) 130 | 131 | backData.error = pro.error 132 | let proData = pro.data 133 | if (proData) { 134 | const $ = cheerio.load(proData) 135 | let vodDetail = new VideoDetail() 136 | vodDetail.vod_id = args.url 137 | vodDetail.vod_name = $('.page-title')[0].children[0].data 138 | vodDetail.vod_pic = $($('.mobile-play')).find( 139 | '.lazyload' 140 | )[0].attribs['data-src'] 141 | 142 | let video_items = $('.video-info-itemtitle') 143 | 144 | for (const item of video_items) { 145 | let key = $(item).text() 146 | 147 | let vItems = $(item).next().find('a') 148 | let value = vItems 149 | .map((i, el) => { 150 | let text = $(el).text().trim() // 获取并去除空白字符 151 | return text ? text : null // 只有非空的文本才返回 152 | }) 153 | .get() // 将 jQuery 对象转换为普通数组 154 | .filter(Boolean) // 过滤掉 null 和空字符串 155 | .join(', ') // 用逗号和空格分割 156 | 157 | if (key.includes('剧情')) { 158 | vodDetail.vod_content = $(item) 159 | .next() 160 | .find('p') 161 | .text() 162 | .trim() 163 | } else if (key.includes('导演')) { 164 | vodDetail.vod_director = value.trim() 165 | } else if (key.includes('主演')) { 166 | vodDetail.vod_actor = value.trim() 167 | } 168 | } 169 | 170 | const panUrls = [] 171 | let items = $('.module-row-info') 172 | for (const item of items) { 173 | let shareUrl = $(item).find('p')[0].children[0].data 174 | panUrls.push(shareUrl) 175 | } 176 | vodDetail.panUrls = panUrls 177 | console.log(panUrls) 178 | 179 | backData.data = vodDetail 180 | } 181 | } catch (error) { 182 | backData.error = '获取视频详情失败' + error 183 | } 184 | 185 | return JSON.stringify(backData) 186 | } 187 | 188 | /** 189 | * 获取视频的播放地址 190 | * @param {UZArgs} args 191 | * @returns {Promise} 192 | */ 193 | async function getVideoPlayUrl(args) { 194 | var backData = new RepVideoPlayUrl() 195 | return JSON.stringify(backData) 196 | } 197 | 198 | /** 199 | * 搜索视频 200 | * @param {UZArgs} args 201 | * @returns {Promise} 202 | */ 203 | async function searchVideo(args) { 204 | var backData = new RepVideoList() 205 | try { 206 | let searchUrl = `${UZUtils.removeTrailingSlash( 207 | appConfig.webSite 208 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 209 | let repData = await req(searchUrl) 210 | 211 | const $ = cheerio.load(repData.data) 212 | let items = $('.module-search-item') 213 | 214 | for (const item of items) { 215 | let video = new VideoDetail() 216 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 217 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 218 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 219 | 'data-src' 220 | ] 221 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 222 | backData.data.push(video) 223 | } 224 | } catch (error) { 225 | backData.error = error 226 | } 227 | return JSON.stringify(backData) 228 | } 229 | 230 | function combineUrl(url) { 231 | if (url === undefined) { 232 | return '' 233 | } 234 | if (url.indexOf(appConfig.webSite) !== -1) { 235 | return url 236 | } 237 | if (url.startsWith('/')) { 238 | return appConfig.webSite + url 239 | } 240 | return appConfig.webSite + '/' + url 241 | } 242 | -------------------------------------------------------------------------------- /vod/js/eacg2.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「嗅」 E-ACG2 3 | //@version:1 4 | //@webSite:https://eacg1.com 5 | //@remark: 6 | //@order: D 7 | // ignore 8 | 9 | // 适用于 把鼠标放在视频封面上 可以右键 复制正确链接的网站 10 | // 不能保证一定能用,不能用的欢迎反馈 11 | 12 | /// 是否模拟 PC 是 1, 手机是 0 13 | const isUsePC = 1 14 | /// 默认应该是 0,当视频不能播放的时候,可以把这个设置为 1, 否则不要改动 15 | const isAddReferer = 0 16 | 17 | // 网站主页 18 | const webSite = 'https://eacg1.com' 19 | // 网站搜索 20 | // https://eacg1.com/vodsearch/海----------2---.html 21 | // 把网站主页变成 @{webSite} 把搜索词变成 @{searchWord} 把页码变成 @{page} 22 | const searchUrl = '@{webSite}/vodsearch/@{searchWord}----------@{page}---.html' 23 | // 当前网站任意视频详情页 24 | // https://eacg1.com/voddetails-55797.html 25 | const videoDetailPage = '@{webSite}/voddetails-55797.html' 26 | // 当前网站任意视频播放页 27 | // https://eacg1.com/Comicplay/55797-1-1.html 28 | const videoPlayPage = '@{webSite}/Comicplay/55797-1-1.html' 29 | 30 | // https://eacg1.com/vodshow/21---搞笑-----2---2021.html 31 | // 筛选列表 @{mainId} 对应上面的 21 即大分类 32 | // 筛选列表 @{filterId0} 对应上面的 搞笑 即筛选条件类型 33 | // 筛选列表 @{filterId1} 对应上面的 2021 即筛选条件年份 34 | // 筛选列表 @{page} 对应上面的 2 即页码 35 | const filterListUrl = '@{webSite}/vodshow/@{mainId}---@{filterId0}-----@{page}---@{filterId1}.html' 36 | 37 | const firstClass = [ 38 | { 39 | // 分类列表 筛选列表 40 | // 一级分类的名称 如果不想写筛选 那么往下看剧场版分类 或者搜索 3.5 41 | // 这个就是我们在网站上看到的一级分类的名称 42 | // 也是在 app 里展示的名称 43 | name: '日漫', 44 | // 这个就是我们在网站上看到的一级分类的 id 对应上面的 @{mainId} 即21 45 | id: '21', 46 | // 这个是这个大分类的所有筛选类别 类型、地区、年份 这种 都是写在这个 [] 里的 47 | filter: [ 48 | // MARK: 3.1 这个是单个筛选类别 49 | { 50 | // 这个是筛选标题 51 | name: '类型', 52 | // 这里面就是 类型 的筛选列表,可以在网站上依次选中看看变化 53 | // 同一个类型的 key 是一致的! 54 | // 这个 key 就是上面链接里要被替换的内容,这里对应 @{filterId0} 55 | list: [ 56 | { 57 | // 这个就是筛选标签的名称 58 | name: '全部', 59 | // 这个就是筛选标签的 id 对应上面的 @{filterId0} 60 | // 可以看到我们选了全部之后链接没有增加东西 61 | // 所以这里的 id 是 空 62 | id: '', 63 | key: '@{filterId0}', 64 | }, 65 | { 66 | // 这个就是筛选标签的名称 67 | name: '科幻', 68 | // 这个就是筛选标签的 id 对应上面的 @{filterId0} 即科幻 69 | // 我们选中科幻后 链接只增加了 科幻 两个字,所有 id 是 科幻 70 | id: '科幻', 71 | key: '@{filterId0}', 72 | }, 73 | { 74 | name: '热血', 75 | id: '热血', 76 | key: '@{filterId0}', 77 | }, 78 | { 79 | name: '推理', 80 | id: '推理', 81 | key: '@{filterId0}', 82 | }, 83 | ], 84 | }, 85 | // MARK: 3.2 一个大分类 多个筛选条件 86 | // 现在是第二个筛选条件 年份 对应 @{filterId1} 87 | { 88 | name: '年份', 89 | list: [ 90 | { 91 | name: '全部', 92 | id: '', 93 | key: '@{filterId1}', 94 | }, 95 | { 96 | name: '2025', 97 | id: '2025', 98 | key: '@{filterId1}', 99 | }, 100 | { 101 | name: '2024', 102 | id: '2024', 103 | key: '@{filterId1}', 104 | }, 105 | { 106 | name: '2023', 107 | id: '2023', 108 | key: '@{filterId1}', 109 | }, 110 | { 111 | name: '2022', 112 | id: '2022', 113 | key: '@{filterId1}', 114 | }, 115 | ], 116 | }, 117 | ], 118 | }, 119 | { 120 | // 3.3 一级分类的名称 121 | // 第二个大分类 122 | name: '国语动漫', 123 | // 这个就是我们在网站上看到的一级分类的 id 对应上面的 @{mainId} 即20 124 | id: '20', 125 | filter: [ 126 | // 4.这个是筛选类别,我们只写了一个类型。如果有多个筛选类别那么就照着这个大括号的格式写多个 127 | { 128 | // 这个是筛选标题 129 | name: '类型', 130 | // 这里面就是 类型 的筛选列表,可以在网站上依次选中看看变化 131 | list: [ 132 | { 133 | // 这个就是筛选标签的名称 134 | name: '全部', 135 | // 这个就是筛选标签的 id 对应上面的 @{filterId0} 136 | // 可以看到我们选了全部之后链接没有增加东西 137 | // 所以这里的 id 是 空 138 | id: '', 139 | key: '@{filterId0}', 140 | }, 141 | { 142 | // 这个就是筛选标签的名称 143 | name: '科幻', 144 | // 这个就是筛选标签的 id 对应上面的 @{filterId0} 即科幻 145 | id: '科幻', 146 | key: '@{filterId0}', 147 | }, 148 | { 149 | name: '热血', 150 | id: '热血', 151 | key: '@{filterId0}', 152 | }, 153 | { 154 | name: '推理', 155 | id: '推理', 156 | key: '@{filterId0}', 157 | }, 158 | ], 159 | }, 160 | ], 161 | }, 162 | { 163 | name: '剧场版', 164 | // 不想写分类筛选了。。。 165 | // https://eacg1.com/vodclassification/24-2.html 166 | id: '@{webSite}/vodclassification/24-@{page}.html', 167 | }, 168 | ] 169 | 170 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 171 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 172 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 173 | 174 | //#BaseCode1# 175 | -------------------------------------------------------------------------------- /vod/js/erxiao.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 二小 3 | //@version:1 4 | //@webSite:https://2xiaopan.fun 5 | //@remark: 6 | //@order: B 7 | // ignore 8 | const appConfig = { 9 | _webSite: 'https://2xiaopan.fun', 10 | /** 11 | * 网站主页,uz 调用每个函数前都会进行赋值操作 12 | * 如果不想被改变 请自定义一个变量 13 | */ 14 | get webSite() { 15 | return this._webSite 16 | }, 17 | set webSite(value) { 18 | this._webSite = value 19 | }, 20 | 21 | _uzTag: '', 22 | /** 23 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 24 | * 用于读取环境变量 25 | */ 26 | get uzTag() { 27 | return this._uzTag 28 | }, 29 | set uzTag(value) { 30 | this._uzTag = value 31 | }, 32 | } 33 | 34 | /** 35 | * 异步获取分类列表的方法。 36 | * @param {UZArgs} args 37 | * @returns {Promise} 38 | */ 39 | async function getClassList(args) { 40 | var backData = new RepVideoClassList() 41 | backData.data = [ 42 | { 43 | type_id: '1', 44 | type_name: '二小电影', 45 | hasSubclass: false, 46 | }, 47 | { 48 | type_id: '2', 49 | type_name: '二小剧集', 50 | hasSubclass: false, 51 | }, 52 | { 53 | type_id: '3', 54 | type_name: '二小动漫', 55 | hasSubclass: false, 56 | }, 57 | { 58 | type_id: '17', 59 | type_name: '二小综艺', 60 | hasSubclass: false, 61 | }, 62 | ] 63 | return JSON.stringify(backData) 64 | } 65 | async function getSubclassList(args) { 66 | let backData = new RepVideoSubclassList() 67 | return JSON.stringify(backData) 68 | } 69 | async function getSubclassVideoList(args) { 70 | var backData = new RepVideoList() 71 | return JSON.stringify(backData) 72 | } 73 | /** 74 | * 获取分类视频列表 75 | * @param {UZArgs} args 76 | * @returns {Promise} 77 | */ 78 | async function getVideoList(args) { 79 | var backData = new RepVideoList() 80 | let url = 81 | UZUtils.removeTrailingSlash(appConfig.webSite) + 82 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 83 | try { 84 | const pro = await req(url) 85 | backData.error = pro.error 86 | let videos = [] 87 | if (pro.data) { 88 | const $ = cheerio.load(pro.data) 89 | let vodItems = $('#main .module-item') 90 | vodItems.each((_, e) => { 91 | let videoDet = new VideoDetail() 92 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 93 | videoDet.vod_name = $(e) 94 | .find('.module-item-pic img') 95 | .attr('alt') 96 | videoDet.vod_pic = $(e) 97 | .find('.module-item-pic img') 98 | .attr('data-src') 99 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 100 | videoDet.vod_year = $(e) 101 | .find('.module-item-caption span') 102 | .first() 103 | .text() 104 | videos.push(videoDet) 105 | }) 106 | } 107 | backData.data = videos 108 | } catch (error) {} 109 | return JSON.stringify(backData) 110 | } 111 | 112 | /** 113 | * 获取视频详情 114 | * @param {UZArgs} args 115 | * @returns {Promise} 116 | */ 117 | async function getVideoDetail(args) { 118 | var backData = new RepVideoDetail() 119 | try { 120 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 121 | let pro = await req(webUrl) 122 | 123 | backData.error = pro.error 124 | let proData = pro.data 125 | if (proData) { 126 | const $ = cheerio.load(proData) 127 | let vodDetail = new VideoDetail() 128 | vodDetail.vod_id = args.url 129 | vodDetail.vod_name = $('.page-title')[0].children[0].data 130 | vodDetail.vod_pic = $($('.mobile-play')).find( 131 | '.lazyload' 132 | )[0].attribs['data-src'] 133 | 134 | let video_items = $('.video-info-itemtitle') 135 | 136 | for (const item of video_items) { 137 | let key = $(item).text() 138 | 139 | let vItems = $(item).next().find('a') 140 | let value = vItems 141 | .map((i, el) => { 142 | let text = $(el).text().trim() // 获取并去除空白字符 143 | return text ? text : null // 只有非空的文本才返回 144 | }) 145 | .get() // 将 jQuery 对象转换为普通数组 146 | .filter(Boolean) // 过滤掉 null 和空字符串 147 | .join(', ') // 用逗号和空格分割 148 | 149 | if (key.includes('剧情')) { 150 | vodDetail.vod_content = $(item) 151 | .next() 152 | .find('p') 153 | .text() 154 | .trim() 155 | } else if (key.includes('导演')) { 156 | vodDetail.vod_director = value.trim() 157 | } else if (key.includes('主演')) { 158 | vodDetail.vod_actor = value.trim() 159 | } 160 | } 161 | 162 | const panUrls = [] 163 | let items = $('.module-row-info') 164 | for (const item of items) { 165 | let shareUrl = $(item).find('p')[0].children[0].data 166 | panUrls.push(shareUrl) 167 | } 168 | vodDetail.panUrls = panUrls 169 | console.log(panUrls) 170 | 171 | backData.data = vodDetail 172 | } 173 | } catch (error) { 174 | backData.error = '获取视频详情失败' + error 175 | } 176 | 177 | return JSON.stringify(backData) 178 | } 179 | 180 | /** 181 | * 获取视频的播放地址 182 | * @param {UZArgs} args 183 | * @returns {Promise} 184 | */ 185 | async function getVideoPlayUrl(args) { 186 | var backData = new RepVideoPlayUrl() 187 | return JSON.stringify(backData) 188 | } 189 | 190 | /** 191 | * 搜索视频 192 | * @param {UZArgs} args 193 | * @returns {Promise} 194 | */ 195 | async function searchVideo(args) { 196 | var backData = new RepVideoList() 197 | try { 198 | let searchUrl = `${UZUtils.removeTrailingSlash( 199 | appConfig.webSite 200 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 201 | let repData = await req(searchUrl) 202 | 203 | const $ = cheerio.load(repData.data) 204 | let items = $('.module-search-item') 205 | 206 | for (const item of items) { 207 | let video = new VideoDetail() 208 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 209 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 210 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 211 | 'data-src' 212 | ] 213 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 214 | backData.data.push(video) 215 | } 216 | } catch (error) { 217 | backData.error = error 218 | } 219 | return JSON.stringify(backData) 220 | } 221 | 222 | function combineUrl(url) { 223 | if (url === undefined) { 224 | return '' 225 | } 226 | if (url.indexOf(appConfig.webSite) !== -1) { 227 | return url 228 | } 229 | if (url.startsWith('/')) { 230 | return appConfig.webSite + url 231 | } 232 | return appConfig.webSite + '/' + url 233 | } 234 | -------------------------------------------------------------------------------- /vod/js/funletu.txt: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 趣盘搜 3 | //@version:3 4 | //@webSite:https://pan.funletu.com 5 | //@remark:来自proversion2024,仅搜索 6 | //@codeID:LO5aQSJYBZLrRD1g 7 | //@type:100 8 | //@instance:funletu20241124 9 | //@order: B 10 | // ignore 11 | 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 -------------------------------------------------------------------------------- /vod/js/huban.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 虎斑 3 | //@version:1 4 | //@webSite:http://103.45.162.207:20720 5 | //@remark: 6 | //@order: B 7 | // ignore 8 | const appConfig = { 9 | _webSite: 'http://103.45.162.207:20720', 10 | /** 11 | * 网站主页,uz 调用每个函数前都会进行赋值操作 12 | * 如果不想被改变 请自定义一个变量 13 | */ 14 | get webSite() { 15 | return this._webSite 16 | }, 17 | set webSite(value) { 18 | this._webSite = value 19 | }, 20 | 21 | _uzTag: '', 22 | /** 23 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 24 | * 用于读取环境变量 25 | */ 26 | get uzTag() { 27 | return this._uzTag 28 | }, 29 | set uzTag(value) { 30 | this._uzTag = value 31 | }, 32 | } 33 | 34 | /** 35 | * 异步获取分类列表的方法。 36 | * @param {UZArgs} args 37 | * @returns {Promise} 38 | */ 39 | async function getClassList(args) { 40 | var backData = new RepVideoClassList() 41 | backData.data = [ 42 | { 43 | type_id: '1', 44 | type_name: '小虎斑影', 45 | hasSubclass: false, 46 | }, 47 | { 48 | type_id: '2', 49 | type_name: '小虎斑剧', 50 | hasSubclass: false, 51 | }, 52 | { 53 | type_id: '4', 54 | type_name: '小虎斑漫', 55 | hasSubclass: false, 56 | }, 57 | { 58 | type_id: '3', 59 | type_name: '小虎斑综', 60 | hasSubclass: false, 61 | }, 62 | { 63 | type_id: '5', 64 | type_name: '小虎斑精', 65 | hasSubclass: false, 66 | }, 67 | { 68 | type_id: '6', 69 | type_name: '小虎斑短', 70 | hasSubclass: false, 71 | }, 72 | ] 73 | return JSON.stringify(backData) 74 | } 75 | async function getSubclassList(args) { 76 | let backData = new RepVideoSubclassList() 77 | return JSON.stringify(backData) 78 | } 79 | async function getSubclassVideoList(args) { 80 | var backData = new RepVideoList() 81 | return JSON.stringify(backData) 82 | } 83 | /** 84 | * 获取分类视频列表 85 | * @param {UZArgs} args 86 | * @returns {Promise} 87 | */ 88 | async function getVideoList(args) { 89 | var backData = new RepVideoList() 90 | let url = 91 | UZUtils.removeTrailingSlash(appConfig.webSite) + 92 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 93 | try { 94 | const pro = await req(url) 95 | backData.error = pro.error 96 | let videos = [] 97 | if (pro.data) { 98 | const $ = cheerio.load(pro.data) 99 | let vodItems = $('#main .module-item') 100 | vodItems.each((_, e) => { 101 | let videoDet = new VideoDetail() 102 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 103 | videoDet.vod_name = $(e) 104 | .find('.module-item-pic img') 105 | .attr('alt') 106 | videoDet.vod_pic = $(e) 107 | .find('.module-item-pic img') 108 | .attr('data-src') 109 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 110 | videoDet.vod_year = $(e) 111 | .find('.module-item-caption span') 112 | .first() 113 | .text() 114 | videos.push(videoDet) 115 | }) 116 | } 117 | backData.data = videos 118 | } catch (error) {} 119 | return JSON.stringify(backData) 120 | } 121 | 122 | /** 123 | * 获取视频详情 124 | * @param {UZArgs} args 125 | * @returns {Promise} 126 | */ 127 | async function getVideoDetail(args) { 128 | var backData = new RepVideoDetail() 129 | try { 130 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 131 | let pro = await req(webUrl) 132 | 133 | backData.error = pro.error 134 | let proData = pro.data 135 | if (proData) { 136 | const $ = cheerio.load(proData) 137 | let vodDetail = new VideoDetail() 138 | vodDetail.vod_id = args.url 139 | vodDetail.vod_name = $('.page-title')[0].children[0].data 140 | vodDetail.vod_pic = $($('.mobile-play')).find( 141 | '.lazyload' 142 | )[0].attribs['data-src'] 143 | 144 | let video_items = $('.video-info-itemtitle') 145 | 146 | for (const item of video_items) { 147 | let key = $(item).text() 148 | 149 | let vItems = $(item).next().find('a') 150 | let value = vItems 151 | .map((i, el) => { 152 | let text = $(el).text().trim() // 获取并去除空白字符 153 | return text ? text : null // 只有非空的文本才返回 154 | }) 155 | .get() // 将 jQuery 对象转换为普通数组 156 | .filter(Boolean) // 过滤掉 null 和空字符串 157 | .join(', ') // 用逗号和空格分割 158 | 159 | if (key.includes('剧情')) { 160 | vodDetail.vod_content = $(item) 161 | .next() 162 | .find('p') 163 | .text() 164 | .trim() 165 | } else if (key.includes('导演')) { 166 | vodDetail.vod_director = value.trim() 167 | } else if (key.includes('主演')) { 168 | vodDetail.vod_actor = value.trim() 169 | } 170 | } 171 | 172 | const panUrls = [] 173 | let items = $('.module-row-info') 174 | for (const item of items) { 175 | let shareUrl = $(item).find('p')[0].children[0].data 176 | panUrls.push(shareUrl) 177 | } 178 | vodDetail.panUrls = panUrls 179 | console.log(panUrls) 180 | 181 | backData.data = vodDetail 182 | } 183 | } catch (error) { 184 | backData.error = '获取视频详情失败' + error 185 | } 186 | 187 | return JSON.stringify(backData) 188 | } 189 | 190 | /** 191 | * 获取视频的播放地址 192 | * @param {UZArgs} args 193 | * @returns {Promise} 194 | */ 195 | async function getVideoPlayUrl(args) { 196 | var backData = new RepVideoPlayUrl() 197 | return JSON.stringify(backData) 198 | } 199 | 200 | /** 201 | * 搜索视频 202 | * @param {UZArgs} args 203 | * @returns {Promise} 204 | */ 205 | async function searchVideo(args) { 206 | var backData = new RepVideoList() 207 | try { 208 | let searchUrl = `${UZUtils.removeTrailingSlash( 209 | appConfig.webSite 210 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 211 | let repData = await req(searchUrl) 212 | 213 | const $ = cheerio.load(repData.data) 214 | let items = $('.module-search-item') 215 | 216 | for (const item of items) { 217 | let video = new VideoDetail() 218 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 219 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 220 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 221 | 'data-src' 222 | ] 223 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 224 | backData.data.push(video) 225 | } 226 | } catch (error) { 227 | backData.error = error 228 | } 229 | return JSON.stringify(backData) 230 | } 231 | 232 | function combineUrl(url) { 233 | if (url === undefined) { 234 | return '' 235 | } 236 | if (url.indexOf(appConfig.webSite) !== -1) { 237 | return url 238 | } 239 | if (url.startsWith('/')) { 240 | return appConfig.webSite + url 241 | } 242 | return appConfig.webSite + '/' + url 243 | } 244 | -------------------------------------------------------------------------------- /vod/js/labipan.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 蜡笔 2 | //@version:3 3 | //@webSite:http://feimaoai.site 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'http://feimaoai.site', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '蜡笔电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '蜡笔剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '蜡笔动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '蜡笔综艺', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '24', 62 | type_name: '臻彩4K', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '29', 67 | type_name: '蜡笔臻彩', 68 | hasSubclass: false, 69 | }, 70 | { 71 | type_id: '5', 72 | type_name: '蜡笔短剧', 73 | hasSubclass: false, 74 | }, 75 | ] 76 | return JSON.stringify(backData) 77 | } 78 | async function getSubclassList(args) { 79 | let backData = new RepVideoSubclassList() 80 | return JSON.stringify(backData) 81 | } 82 | async function getSubclassVideoList(args) { 83 | var backData = new RepVideoList() 84 | return JSON.stringify(backData) 85 | } 86 | /** 87 | * 获取分类视频列表 88 | * @param {UZArgs} args 89 | * @returns {Promise} 90 | */ 91 | async function getVideoList(args) { 92 | var backData = new RepVideoList() 93 | let url = 94 | UZUtils.removeTrailingSlash(appConfig.webSite) + 95 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 96 | try { 97 | const pro = await req(url) 98 | backData.error = pro.error 99 | let videos = [] 100 | if (pro.data) { 101 | const $ = cheerio.load(pro.data) 102 | let vodItems = $('#main .module-item') 103 | vodItems.each((_, e) => { 104 | let videoDet = new VideoDetail() 105 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 106 | videoDet.vod_name = $(e) 107 | .find('.module-item-pic img') 108 | .attr('alt') 109 | videoDet.vod_pic = $(e) 110 | .find('.module-item-pic img') 111 | .attr('data-src') 112 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 113 | videoDet.vod_year = $(e) 114 | .find('.module-item-caption span') 115 | .first() 116 | .text() 117 | videos.push(videoDet) 118 | }) 119 | } 120 | backData.data = videos 121 | } catch (error) {} 122 | return JSON.stringify(backData) 123 | } 124 | 125 | /** 126 | * 获取视频详情 127 | * @param {UZArgs} args 128 | * @returns {Promise} 129 | */ 130 | async function getVideoDetail(args) { 131 | var backData = new RepVideoDetail() 132 | try { 133 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 134 | let pro = await req(webUrl) 135 | 136 | backData.error = pro.error 137 | let proData = pro.data 138 | if (proData) { 139 | const $ = cheerio.load(proData) 140 | let vodDetail = new VideoDetail() 141 | vodDetail.vod_id = args.url 142 | vodDetail.vod_name = $('.page-title')[0].children[0].data 143 | vodDetail.vod_pic = $($('.mobile-play')).find( 144 | '.lazyload' 145 | )[0].attribs['data-src'] 146 | 147 | let video_items = $('.video-info-itemtitle') 148 | 149 | for (const item of video_items) { 150 | let key = $(item).text() 151 | 152 | let vItems = $(item).next().find('a') 153 | let value = vItems 154 | .map((i, el) => { 155 | let text = $(el).text().trim() // 获取并去除空白字符 156 | return text ? text : null // 只有非空的文本才返回 157 | }) 158 | .get() // 将 jQuery 对象转换为普通数组 159 | .filter(Boolean) // 过滤掉 null 和空字符串 160 | .join(', ') // 用逗号和空格分割 161 | 162 | if (key.includes('剧情')) { 163 | vodDetail.vod_content = $(item) 164 | .next() 165 | .find('p') 166 | .text() 167 | .trim() 168 | } else if (key.includes('导演')) { 169 | vodDetail.vod_director = value.trim() 170 | } else if (key.includes('主演')) { 171 | vodDetail.vod_actor = value.trim() 172 | } 173 | } 174 | 175 | const panUrls = [] 176 | let items = $('.module-row-info') 177 | for (const item of items) { 178 | let shareUrl = $(item).find('p')[0].children[0].data 179 | panUrls.push(shareUrl) 180 | } 181 | vodDetail.panUrls = panUrls 182 | console.log(panUrls) 183 | 184 | backData.data = vodDetail 185 | } 186 | } catch (error) { 187 | backData.error = '获取视频详情失败' + error 188 | } 189 | 190 | return JSON.stringify(backData) 191 | } 192 | 193 | /** 194 | * 获取视频的播放地址 195 | * @param {UZArgs} args 196 | * @returns {Promise} 197 | */ 198 | async function getVideoPlayUrl(args) { 199 | var backData = new RepVideoPlayUrl() 200 | return JSON.stringify(backData) 201 | } 202 | 203 | /** 204 | * 搜索视频 205 | * @param {UZArgs} args 206 | * @returns {Promise} 207 | */ 208 | async function searchVideo(args) { 209 | var backData = new RepVideoList() 210 | try { 211 | let searchUrl = `${UZUtils.removeTrailingSlash( 212 | appConfig.webSite 213 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 214 | let repData = await req(searchUrl) 215 | 216 | const $ = cheerio.load(repData.data) 217 | let items = $('.module-search-item') 218 | 219 | for (const item of items) { 220 | let video = new VideoDetail() 221 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 222 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 223 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 224 | 'data-src' 225 | ] 226 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 227 | backData.data.push(video) 228 | } 229 | } catch (error) { 230 | backData.error = error 231 | } 232 | return JSON.stringify(backData) 233 | } 234 | 235 | function combineUrl(url) { 236 | if (url === undefined) { 237 | return '' 238 | } 239 | if (url.indexOf(appConfig.webSite) !== -1) { 240 | return url 241 | } 242 | if (url.startsWith('/')) { 243 | return appConfig.webSite + url 244 | } 245 | return appConfig.webSite + '/' + url 246 | } 247 | -------------------------------------------------------------------------------- /vod/js/liuqu.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 六趣 2 | //@version:1 3 | //@webSite:https://wp.0v.fit 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://wp.0v.fit', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '六趣电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '六趣剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '4', 52 | type_name: '六趣动漫', 53 | hasSubclass: false, 54 | }, 55 | ] 56 | return JSON.stringify(backData) 57 | } 58 | 59 | async function getSubclassList(args) { 60 | let backData = new RepVideoSubclassList() 61 | return JSON.stringify(backData) 62 | } 63 | async function getSubclassVideoList(args) { 64 | var backData = new RepVideoList() 65 | return JSON.stringify(backData) 66 | } 67 | 68 | /** 69 | * 获取分类视频列表 70 | * @param {UZArgs} args 71 | * @returns {Promise} 72 | */ 73 | async function getVideoList(args) { 74 | var backData = new RepVideoList() 75 | let url = 76 | UZUtils.removeTrailingSlash(appConfig.webSite) + 77 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 78 | try { 79 | const pro = await req(url) 80 | backData.error = pro.error 81 | let videos = [] 82 | if (pro.data) { 83 | const $ = cheerio.load(pro.data) 84 | let vodItems = $('#main .module-item') 85 | vodItems.each((_, e) => { 86 | let videoDet = new VideoDetail() 87 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 88 | videoDet.vod_name = $(e) 89 | .find('.module-item-pic img') 90 | .attr('alt') 91 | videoDet.vod_pic = $(e) 92 | .find('.module-item-pic img') 93 | .attr('data-src') 94 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 95 | videoDet.vod_year = $(e) 96 | .find('.module-item-caption span') 97 | .first() 98 | .text() 99 | videos.push(videoDet) 100 | }) 101 | } 102 | backData.data = videos 103 | } catch (error) {} 104 | return JSON.stringify(backData) 105 | } 106 | 107 | /** 108 | * 获取视频详情 109 | * @param {UZArgs} args 110 | * @returns {Promise} 111 | */ 112 | async function getVideoDetail(args) { 113 | var backData = new RepVideoDetail() 114 | try { 115 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 116 | let pro = await req(webUrl) 117 | 118 | backData.error = pro.error 119 | let proData = pro.data 120 | if (proData) { 121 | const $ = cheerio.load(proData) 122 | let vodDetail = new VideoDetail() 123 | vodDetail.vod_id = args.url 124 | vodDetail.vod_name = $('.page-title')[0].children[0].data 125 | vodDetail.vod_pic = $($('.mobile-play')).find( 126 | '.lazyload' 127 | )[0].attribs['data-src'] 128 | 129 | let video_items = $('.video-info-itemtitle') 130 | 131 | for (const item of video_items) { 132 | let key = $(item).text() 133 | 134 | let vItems = $(item).next().find('a') 135 | let value = vItems 136 | .map((i, el) => { 137 | let text = $(el).text().trim() // 获取并去除空白字符 138 | return text ? text : null // 只有非空的文本才返回 139 | }) 140 | .get() // 将 jQuery 对象转换为普通数组 141 | .filter(Boolean) // 过滤掉 null 和空字符串 142 | .join(', ') // 用逗号和空格分割 143 | 144 | if (key.includes('剧情')) { 145 | vodDetail.vod_content = $(item) 146 | .next() 147 | .find('p') 148 | .text() 149 | .trim() 150 | } else if (key.includes('导演')) { 151 | vodDetail.vod_director = value.trim() 152 | } else if (key.includes('主演')) { 153 | vodDetail.vod_actor = value.trim() 154 | } 155 | } 156 | 157 | const panUrls = [] 158 | let items = $('.module-row-info') 159 | for (const item of items) { 160 | let shareUrl = $(item).find('p')[0].children[0].data 161 | panUrls.push(shareUrl) 162 | } 163 | vodDetail.panUrls = panUrls 164 | console.log(panUrls) 165 | 166 | backData.data = vodDetail 167 | } 168 | } catch (error) { 169 | backData.error = '获取视频详情失败' + error 170 | } 171 | 172 | return JSON.stringify(backData) 173 | } 174 | 175 | /** 176 | * 获取视频的播放地址 177 | * @param {UZArgs} args 178 | * @returns {Promise} 179 | */ 180 | async function getVideoPlayUrl(args) { 181 | var backData = new RepVideoPlayUrl() 182 | return JSON.stringify(backData) 183 | } 184 | 185 | /** 186 | * 搜索视频 187 | * @param {UZArgs} args 188 | * @returns {Promise} 189 | */ 190 | async function searchVideo(args) { 191 | var backData = new RepVideoList() 192 | try { 193 | let searchUrl = `${UZUtils.removeTrailingSlash( 194 | appConfig.webSite 195 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 196 | let repData = await req(searchUrl) 197 | appConfig.checkVerify(searchUrl, repData.data) 198 | const $ = cheerio.load(repData.data) 199 | let items = $('.module-search-item') 200 | 201 | for (const item of items) { 202 | let video = new VideoDetail() 203 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 204 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 205 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 206 | 'data-src' 207 | ] 208 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 209 | backData.data.push(video) 210 | } 211 | } catch (error) { 212 | backData.error = error 213 | } 214 | return JSON.stringify(backData) 215 | } 216 | 217 | function combineUrl(url) { 218 | if (url === undefined) { 219 | return '' 220 | } 221 | if (url.indexOf(appConfig.webSite) !== -1) { 222 | return url 223 | } 224 | if (url.startsWith('/')) { 225 | return appConfig.webSite + url 226 | } 227 | return appConfig.webSite + '/' + url 228 | } 229 | -------------------------------------------------------------------------------- /vod/js/mogg.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 木偶 2 | //@version:2 3 | //@webSite:https://666.666291.xyz 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://666.666291.xyz', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '木偶电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '木偶剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '木偶动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '木偶纪录', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '27', 62 | type_name: '天翼专区', 63 | hasSubclass: false, 64 | }, 65 | ] 66 | return JSON.stringify(backData) 67 | } 68 | 69 | async function getSubclassList(args) { 70 | let backData = new RepVideoSubclassList() 71 | return JSON.stringify(backData) 72 | } 73 | async function getSubclassVideoList(args) { 74 | var backData = new RepVideoList() 75 | return JSON.stringify(backData) 76 | } 77 | 78 | /** 79 | * 获取分类视频列表 80 | * @param {UZArgs} args 81 | * @returns {Promise} 82 | */ 83 | async function getVideoList(args) { 84 | var backData = new RepVideoList() 85 | let url = 86 | UZUtils.removeTrailingSlash(appConfig.webSite) + 87 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 88 | try { 89 | const pro = await req(url) 90 | backData.error = pro.error 91 | let videos = [] 92 | if (pro.data) { 93 | const $ = cheerio.load(pro.data) 94 | let vodItems = $('#main .module-item') 95 | vodItems.each((_, e) => { 96 | let videoDet = new VideoDetail() 97 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 98 | videoDet.vod_name = $(e) 99 | .find('.module-item-pic img') 100 | .attr('alt') 101 | videoDet.vod_pic = $(e) 102 | .find('.module-item-pic img') 103 | .attr('data-src') 104 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 105 | videoDet.vod_year = $(e) 106 | .find('.module-item-caption span') 107 | .first() 108 | .text() 109 | videos.push(videoDet) 110 | }) 111 | } 112 | backData.data = videos 113 | } catch (error) {} 114 | return JSON.stringify(backData) 115 | } 116 | 117 | /** 118 | * 获取视频详情 119 | * @param {UZArgs} args 120 | * @returns {Promise} 121 | */ 122 | async function getVideoDetail(args) { 123 | var backData = new RepVideoDetail() 124 | try { 125 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 126 | let pro = await req(webUrl) 127 | 128 | backData.error = pro.error 129 | let proData = pro.data 130 | if (proData) { 131 | const $ = cheerio.load(proData) 132 | let vodDetail = new VideoDetail() 133 | vodDetail.vod_id = args.url 134 | vodDetail.vod_name = $('.page-title')[0].children[0].data 135 | vodDetail.vod_pic = $($('.mobile-play')).find( 136 | '.lazyload' 137 | )[0].attribs['data-src'] 138 | 139 | let video_items = $('.video-info-itemtitle') 140 | 141 | for (const item of video_items) { 142 | let key = $(item).text() 143 | 144 | let vItems = $(item).next().find('a') 145 | let value = vItems 146 | .map((i, el) => { 147 | let text = $(el).text().trim() // 获取并去除空白字符 148 | return text ? text : null // 只有非空的文本才返回 149 | }) 150 | .get() // 将 jQuery 对象转换为普通数组 151 | .filter(Boolean) // 过滤掉 null 和空字符串 152 | .join(', ') // 用逗号和空格分割 153 | 154 | if (key.includes('剧情')) { 155 | vodDetail.vod_content = $(item) 156 | .next() 157 | .find('p') 158 | .text() 159 | .trim() 160 | } else if (key.includes('导演')) { 161 | vodDetail.vod_director = value.trim() 162 | } else if (key.includes('主演')) { 163 | vodDetail.vod_actor = value.trim() 164 | } 165 | } 166 | 167 | const panUrls = [] 168 | let items = $('.module-row-info') 169 | for (const item of items) { 170 | let shareUrl = $(item).find('p')[0].children[0].data 171 | panUrls.push(shareUrl) 172 | } 173 | vodDetail.panUrls = panUrls 174 | console.log(panUrls) 175 | 176 | backData.data = vodDetail 177 | } 178 | } catch (error) { 179 | backData.error = '获取视频详情失败' + error 180 | } 181 | 182 | return JSON.stringify(backData) 183 | } 184 | 185 | /** 186 | * 获取视频的播放地址 187 | * @param {UZArgs} args 188 | * @returns {Promise} 189 | */ 190 | async function getVideoPlayUrl(args) { 191 | var backData = new RepVideoPlayUrl() 192 | return JSON.stringify(backData) 193 | } 194 | 195 | /** 196 | * 搜索视频 197 | * @param {UZArgs} args 198 | * @returns {Promise} 199 | */ 200 | async function searchVideo(args) { 201 | var backData = new RepVideoList() 202 | try { 203 | let searchUrl = `${UZUtils.removeTrailingSlash( 204 | appConfig.webSite 205 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 206 | let repData = await req(searchUrl) 207 | const $ = cheerio.load(repData.data) 208 | let items = $('.module-search-item') 209 | 210 | for (const item of items) { 211 | let video = new VideoDetail() 212 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 213 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 214 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 215 | 'data-src' 216 | ] 217 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 218 | backData.data.push(video) 219 | } 220 | } catch (error) { 221 | backData.error = error 222 | } 223 | return JSON.stringify(backData) 224 | } 225 | 226 | function combineUrl(url) { 227 | if (url === undefined) { 228 | return '' 229 | } 230 | if (url.indexOf(appConfig.webSite) !== -1) { 231 | return url 232 | } 233 | if (url.startsWith('/')) { 234 | return appConfig.webSite + url 235 | } 236 | return appConfig.webSite + '/' + url 237 | } 238 | -------------------------------------------------------------------------------- /vod/js/mubai.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「嗅」 木白 3 | //@version:1 4 | //@webSite:https://m.mubai.link/index 5 | //@remark: 6 | //@deprecated:1 7 | // ignore 8 | 9 | // 适用于 把鼠标放在视频封面上 可以右键 复制正确链接的网站 10 | // 不能保证一定能用,不能用的欢迎反馈 11 | 12 | /// 是否模拟 PC 是 1, 手机是 0 13 | const isUsePC = 1 14 | /// 默认应该是 0,当视频不能播放的时候,可以把这个设置为 1, 否则不要改动 15 | const isAddReferer = 0 16 | 17 | // 网站主页 18 | const webSite = 'https://m.mubai.link/index' 19 | // 网站搜索 20 | // https://m.mubai.link/search?search=海 21 | // 把网站主页变成 @{webSite} 把搜索词变成 @{searchWord} 把页码变成 @{page} 22 | const searchUrl = '@{webSite}/search?search=@{searchWord}¤t=@{page}' 23 | // 当前网站任意视频详情页 24 | // https://m.mubai.link/filmDetail?link=86711 25 | const videoDetailPage = '@{webSite}/filmDetail?link=86711' 26 | // 当前网站任意视频播放页 27 | // https://m.mubai.link/play?id=86711&episode=0&source=2E5B5769897C9353 28 | const videoPlayPage = '@{webSite}/play?id=86711&episode=0&source=2E5B5769897C9353' 29 | 30 | // 保持不变 31 | const filterListUrl = '' 32 | 33 | const firstClass = [ 34 | { 35 | name: '动漫', 36 | // https://m.mubai.link/filmClassifySearch?Pid=4&Sort=update_stamp¤t=2 37 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 38 | id: '@{webSite}/filmClassifySearch?Pid=4&Sort=update_stamp¤t=@{page}', 39 | }, 40 | { 41 | name: '剧场版', 42 | // https://m.mubai.link/filmClassifySearch?Pid=2&Sort=update_stamp¤t=2 43 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 44 | id: '@{webSite}/filmClassifySearch?Pid=2&Sort=update_stamp¤t=@{page}', 45 | }, 46 | ] 47 | 48 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 49 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 50 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 51 | 52 | //#BaseCode1# 53 | -------------------------------------------------------------------------------- /vod/js/ouge.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 欧歌 2 | //@version:3 3 | //@webSite:https://woog.nxog.eu.org 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://woog.nxog.eu.org', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '欧歌电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '欧哥剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '欧歌动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '欧歌综艺', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '5', 62 | type_name: '欧歌短剧', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '21', 67 | type_name: '欧歌综合', 68 | hasSubclass: false, 69 | }, 70 | ] 71 | return JSON.stringify(backData) 72 | } 73 | 74 | async function getSubclassList(args) { 75 | let backData = new RepVideoSubclassList() 76 | return JSON.stringify(backData) 77 | } 78 | async function getSubclassVideoList(args) { 79 | var backData = new RepVideoList() 80 | return JSON.stringify(backData) 81 | } 82 | 83 | /** 84 | * 获取分类视频列表 85 | * @param {UZArgs} args 86 | * @returns {Promise} 87 | */ 88 | async function getVideoList(args) { 89 | var backData = new RepVideoList() 90 | let url = 91 | UZUtils.removeTrailingSlash(appConfig.webSite) + 92 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 93 | try { 94 | const pro = await req(url) 95 | backData.error = pro.error 96 | let videos = [] 97 | if (pro.data) { 98 | const $ = cheerio.load(pro.data) 99 | let vodItems = $('#main .module-item') 100 | vodItems.each((_, e) => { 101 | let videoDet = new VideoDetail() 102 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 103 | videoDet.vod_name = $(e) 104 | .find('.module-item-pic img') 105 | .attr('alt') 106 | videoDet.vod_pic = $(e) 107 | .find('.module-item-pic img') 108 | .attr('data-src') 109 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 110 | videoDet.vod_year = $(e) 111 | .find('.module-item-caption span') 112 | .first() 113 | .text() 114 | videos.push(videoDet) 115 | }) 116 | } 117 | backData.data = videos 118 | } catch (error) {} 119 | return JSON.stringify(backData) 120 | } 121 | 122 | /** 123 | * 获取视频详情 124 | * @param {UZArgs} args 125 | * @returns {Promise} 126 | */ 127 | async function getVideoDetail(args) { 128 | var backData = new RepVideoDetail() 129 | try { 130 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 131 | let pro = await req(webUrl) 132 | 133 | backData.error = pro.error 134 | let proData = pro.data 135 | if (proData) { 136 | const $ = cheerio.load(proData) 137 | let vodDetail = new VideoDetail() 138 | vodDetail.vod_id = args.url 139 | vodDetail.vod_name = $('.page-title')[0].children[0].data 140 | vodDetail.vod_pic = $($('.mobile-play')).find( 141 | '.lazyload' 142 | )[0].attribs['data-src'] 143 | 144 | let video_items = $('.video-info-itemtitle') 145 | 146 | for (const item of video_items) { 147 | let key = $(item).text() 148 | 149 | let vItems = $(item).next().find('a') 150 | let value = vItems 151 | .map((i, el) => { 152 | let text = $(el).text().trim() // 获取并去除空白字符 153 | return text ? text : null // 只有非空的文本才返回 154 | }) 155 | .get() // 将 jQuery 对象转换为普通数组 156 | .filter(Boolean) // 过滤掉 null 和空字符串 157 | .join(', ') // 用逗号和空格分割 158 | 159 | if (key.includes('剧情')) { 160 | vodDetail.vod_content = $(item) 161 | .next() 162 | .find('p') 163 | .text() 164 | .trim() 165 | } else if (key.includes('导演')) { 166 | vodDetail.vod_director = value.trim() 167 | } else if (key.includes('主演')) { 168 | vodDetail.vod_actor = value.trim() 169 | } 170 | } 171 | 172 | const panUrls = [] 173 | let items = $('.module-row-info') 174 | for (const item of items) { 175 | let shareUrl = $(item).find('p')[0].children[0].data 176 | panUrls.push(shareUrl) 177 | } 178 | vodDetail.panUrls = panUrls 179 | console.log(panUrls) 180 | 181 | backData.data = vodDetail 182 | } 183 | } catch (error) { 184 | backData.error = '获取视频详情失败' + error 185 | } 186 | 187 | return JSON.stringify(backData) 188 | } 189 | 190 | /** 191 | * 获取视频的播放地址 192 | * @param {UZArgs} args 193 | * @returns {Promise} 194 | */ 195 | async function getVideoPlayUrl(args) { 196 | var backData = new RepVideoPlayUrl() 197 | return JSON.stringify(backData) 198 | } 199 | 200 | /** 201 | * 搜索视频 202 | * @param {UZArgs} args 203 | * @returns {Promise} 204 | */ 205 | async function searchVideo(args) { 206 | var backData = new RepVideoList() 207 | try { 208 | let searchUrl = `${UZUtils.removeTrailingSlash( 209 | appConfig.webSite 210 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 211 | let repData = await req(searchUrl) 212 | const $ = cheerio.load(repData.data) 213 | let items = $('.module-search-item') 214 | 215 | for (const item of items) { 216 | let video = new VideoDetail() 217 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 218 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 219 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 220 | 'data-src' 221 | ] 222 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 223 | backData.data.push(video) 224 | } 225 | } catch (error) { 226 | backData.error = error 227 | } 228 | return JSON.stringify(backData) 229 | } 230 | 231 | function combineUrl(url) { 232 | if (url === undefined) { 233 | return '' 234 | } 235 | if (url.indexOf(appConfig.webSite) !== -1) { 236 | return url 237 | } 238 | if (url.startsWith('/')) { 239 | return appConfig.webSite + url 240 | } 241 | return appConfig.webSite + '/' + url 242 | } 243 | -------------------------------------------------------------------------------- /vod/js/qingying.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 清影 2 | //@version:1 3 | //@webSite:https://revohd.com 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://revohd.com', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '5', 52 | type_name: '动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '3', 57 | type_name: '娱乐', 58 | hasSubclass: false, 59 | } 60 | ] 61 | return JSON.stringify(backData) 62 | } 63 | 64 | async function getSubclassList(args) { 65 | let backData = new RepVideoSubclassList() 66 | return JSON.stringify(backData) 67 | } 68 | async function getSubclassVideoList(args) { 69 | var backData = new RepVideoList() 70 | return JSON.stringify(backData) 71 | } 72 | 73 | /** 74 | * 获取分类视频列表 75 | * @param {UZArgs} args 76 | * @returns {Promise} 77 | */ 78 | async function getVideoList(args) { 79 | var backData = new RepVideoList() 80 | let url = 81 | UZUtils.removeTrailingSlash(appConfig.webSite) + 82 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 83 | try { 84 | const pro = await req(url) 85 | backData.error = pro.error 86 | let videos = [] 87 | if (pro.data) { 88 | const $ = cheerio.load(pro.data) 89 | let vodItems = $('#main .module-item') 90 | vodItems.each((_, e) => { 91 | let videoDet = new VideoDetail() 92 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 93 | videoDet.vod_name = $(e) 94 | .find('.module-item-pic img') 95 | .attr('alt') 96 | videoDet.vod_pic = combineUrl($(e) 97 | .find('.module-item-pic img') 98 | .attr('data-src')) 99 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 100 | videoDet.vod_year = $(e) 101 | .find('.module-item-caption span') 102 | .first() 103 | .text() 104 | videos.push(videoDet) 105 | }) 106 | } 107 | backData.data = videos 108 | } catch (error) {} 109 | return JSON.stringify(backData) 110 | } 111 | 112 | /** 113 | * 获取视频详情 114 | * @param {UZArgs} args 115 | * @returns {Promise} 116 | */ 117 | async function getVideoDetail(args) { 118 | var backData = new RepVideoDetail() 119 | try { 120 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 121 | let pro = await req(webUrl) 122 | backData.error = pro.error 123 | let proData = pro.data 124 | if (proData) { 125 | const $ = cheerio.load(proData) 126 | let vodDetail = new VideoDetail() 127 | vodDetail.vod_id = args.url 128 | // 标题 129 | vodDetail.vod_name = $('.video-info-header h1.page-title a').text().trim() || $('.video-info-header h1.page-title').text().trim() 130 | // 封面 131 | vodDetail.vod_pic = combineUrl($('.module-item-pic img').attr('data-src')) 132 | // 导演 133 | vodDetail.vod_director = '' 134 | // 主演 135 | vodDetail.vod_actor = '' 136 | // 简介 137 | vodDetail.vod_content = $('.video-info-content.vod_content').text().trim() || $('.video-info-itemtitle:contains("剧情")').nextAll('.video-info-item').first().text().trim() 138 | // 年份 139 | vodDetail.vod_year = $('.video-info-aux .tag-link').filter((_,el)=>/\d{4}/.test($(el).text())).text().trim() 140 | // 地区 141 | vodDetail.vod_area = $('.video-info-aux .tag-link').filter((_,el)=>/大陆|香港|台湾|美国|英国|日本|韩国|法国/.test($(el).text())).text().trim() 142 | // 类型 143 | vodDetail.vod_type = $('.video-info-aux .tag-link').not(function(){return $(this).text().match(/\d{4}|大陆|香港|台湾|美国|英国|日本|韩国|法国/) }).text().trim() 144 | // 评分 145 | vodDetail.vod_douban_score = $('.video-info-itemtitle:contains("评分")').next('.video-info-item').text().replace('分','').trim() || $('.module-item-caption span').first().text().replace('豆瓣','').trim() 146 | // panUrls 147 | vodDetail.panUrls = [] 148 | $('.module-row-info .module-row-title p').each((_, el) => { 149 | let url = $(el).text().trim() 150 | if (url.startsWith('http')) vodDetail.panUrls.push(url) 151 | }) 152 | backData.data = vodDetail 153 | } 154 | } catch (error) { 155 | backData.error = '获取视频详情失败' + error 156 | } 157 | return JSON.stringify(backData) 158 | } 159 | 160 | /** 161 | * 获取视频的播放地址 162 | * @param {UZArgs} args 163 | * @returns {Promise} 164 | */ 165 | async function getVideoPlayUrl(args) { 166 | var backData = new RepVideoPlayUrl() 167 | return JSON.stringify(backData) 168 | } 169 | 170 | /** 171 | * 搜索视频 172 | * @param {UZArgs} args 173 | * @returns {Promise} 174 | */ 175 | async function searchVideo(args) { 176 | var backData = new RepVideoList() 177 | try { 178 | let searchWord = encodeURIComponent(args.searchWord) 179 | let searchUrl 180 | if (args.page == 1) { 181 | searchUrl = `${UZUtils.removeTrailingSlash(appConfig.webSite)}/vodsearch/-------------.html?wd=${searchWord}` 182 | } else { 183 | searchUrl = `${UZUtils.removeTrailingSlash(appConfig.webSite)}/vodsearch/${searchWord}----------${args.page}---.html` 184 | } 185 | let repData = await req(searchUrl) 186 | const $ = cheerio.load(repData.data) 187 | let items = $('.module-search-item') 188 | if (items.length === 0) { 189 | items = $('.module-item') 190 | } 191 | items.each((_, e) => { 192 | let video = new VideoDetail() 193 | video.vod_id = $(e).find('.module-item-pic a').attr('href') 194 | video.vod_name = $(e).find('.module-item-pic img').attr('alt') 195 | video.vod_pic = combineUrl($(e).find('.module-item-pic img').attr('data-src')) 196 | video.vod_remarks = $(e).find('.module-item-text').text() 197 | backData.data.push(video) 198 | }) 199 | } catch (error) { 200 | backData.error = error 201 | } 202 | return JSON.stringify(backData) 203 | } 204 | 205 | function combineUrl(url) { 206 | if (url === undefined) { 207 | return '' 208 | } 209 | if (url.indexOf(appConfig.webSite) !== -1) { 210 | return url 211 | } 212 | if (url.startsWith('/')) { 213 | return appConfig.webSite + url 214 | } 215 | return appConfig.webSite + '/' + url 216 | } -------------------------------------------------------------------------------- /vod/js/resyunpan.js: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 云盘资源网 3 | //@version:1 4 | //@webSite:https://res.yunpan.win 5 | //@remark: 6 | //@type:100 7 | //@instance:resYunPan20241120 8 | //@order: B 9 | import {} from '../../core/uzVideo.js' 10 | import {} from '../../core/uzHome.js' 11 | import {} from '../../core/uz3lib.js' 12 | import {} from '../../core/uzUtils.js' 13 | // ignore 14 | 15 | // 类名要特殊 16 | class ResYunPan extends WebApiBase { 17 | constructor() { 18 | super() 19 | this.webSite = 'https://res.yunpan.win' 20 | } 21 | /** 22 | * 异步获取分类列表的方法。 23 | * @param {UZArgs} args 24 | * @returns {Promise} 25 | */ 26 | async getClassList(args) { 27 | var backData = new RepVideoClassList() 28 | backData.data = [ 29 | { 30 | type_id: '1', 31 | type_name: '全部', 32 | hasSubclass: false, 33 | }, 34 | ] 35 | return JSON.stringify(backData) 36 | } 37 | 38 | /** 39 | * 获取分类视频列表 40 | * @param {UZArgs} args 41 | * @returns {Promise} 42 | */ 43 | async getVideoList(args) { 44 | var backData = new RepVideoList() 45 | var endWebSite = UZUtils.removeTrailingSlash(this.webSite) 46 | let url = 47 | endWebSite + 48 | `/?PageIndex=${args.page}&PageSize=12&Keyword=&Type=&Tag=&YunPanSourceType=` 49 | try { 50 | const pro = await req(url) 51 | backData.error = pro.error 52 | let videos = [] 53 | if (pro.data) { 54 | const $ = cheerio.load(pro.data) 55 | let vodItems = $('div.col') 56 | vodItems.each((_, e) => { 57 | let videoDet = new VideoDetail() 58 | videoDet.vod_pic = 59 | endWebSite + $(e).find('img').first().attr('src') 60 | videoDet.vod_id = $(e) 61 | .find('div.float-end a.card-link') 62 | .last() 63 | .attr('href') 64 | videoDet.vod_name = $(e) 65 | .find('h5.card-title') 66 | .contents() // 获取所有子节点 67 | .not('span') // 排除 span 元素 68 | .text() // 提取文本内容 69 | .trim() 70 | videos.push(videoDet) 71 | }) 72 | } 73 | backData.data = videos 74 | } catch (error) {} 75 | return JSON.stringify(backData) 76 | } 77 | 78 | /** 79 | * 获取视频详情 80 | * @param {UZArgs} args 81 | * @returns {Promise} 82 | */ 83 | async getVideoDetail(args) { 84 | var backData = new RepVideoDetail() 85 | try { 86 | var endWebSite = UZUtils.removeTrailingSlash(this.webSite) 87 | let webUrl = endWebSite + args.url 88 | let pro = await req(webUrl) 89 | backData.error = pro.error 90 | let proData = pro.data 91 | if (proData) { 92 | const $ = cheerio.load(proData) 93 | let vodDetail = new VideoDetail() 94 | vodDetail.vod_content = $('p.card-text').first().text().trim() 95 | const panUrls = [] 96 | const onclickAttr = $('a.card-link.float-end').attr('onclick') // 获取 onclick 属性内容 97 | // 使用正则解析出 window.open 的链接 98 | const match = onclickAttr.match(/window\.open\('([^']+)'\)/) // 正则匹配单引号内的链接 99 | const link = match ? match[1] : null // 提取链接 100 | panUrls.push(link) 101 | vodDetail.panUrls = panUrls 102 | backData.data = vodDetail 103 | } 104 | } catch (error) { 105 | backData.error = '获取视频详情失败' + error 106 | } 107 | 108 | return JSON.stringify(backData) 109 | } 110 | 111 | /** 112 | * 获取视频的播放地址 113 | * @param {UZArgs} args 114 | * @returns {Promise} 115 | */ 116 | async getVideoPlayUrl(args) { 117 | var backData = new RepVideoPlayUrl() 118 | return JSON.stringify(backData) 119 | } 120 | 121 | /** 122 | * 搜索视频 123 | * @param {UZArgs} args 124 | * @returns {Promise} 125 | */ 126 | async searchVideo(args) { 127 | var backData = new RepVideoList() 128 | var endWebSite = UZUtils.removeTrailingSlash(this.webSite) 129 | let url = 130 | endWebSite + 131 | `/?PageIndex=${args.page}&PageSize=12&Keyword=${args.searchWord}&Type=&Tag=&YunPanSourceType=` 132 | try { 133 | const pro = await req(url) 134 | backData.error = pro.error 135 | let videos = [] 136 | if (pro.data) { 137 | const $ = cheerio.load(pro.data) 138 | let vodItems = $('div.col') 139 | vodItems.each((_, e) => { 140 | let videoDet = new VideoDetail() 141 | videoDet.vod_pic = 142 | endWebSite + $(e).find('img').first().attr('src') 143 | videoDet.vod_id = $(e) 144 | .find('div.float-end a.card-link') 145 | .last() 146 | .attr('href') 147 | videoDet.vod_name = $(e) 148 | .find('h5.card-title') 149 | .contents() // 获取所有子节点 150 | .not('span') // 排除 span 元素 151 | .text() // 提取文本内容 152 | .trim() 153 | videos.push(videoDet) 154 | }) 155 | } 156 | backData.data = videos 157 | } catch (error) {} 158 | return JSON.stringify(backData) 159 | } 160 | } 161 | 162 | // json 中 instance 的值,这个名称一定要特殊 163 | var resYunPan20241120 = new ResYunPan() 164 | -------------------------------------------------------------------------------- /vod/js/revohd.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 清影 2 | //@version:1 3 | //@webSite:https://www.revohd.com 4 | //@remark:v1.6.57及以上版本可用,加载不出来就是空资源 5 | //@deprecated:1 6 | //@order: B 7 | 8 | 9 | 10 | // 适用于 把鼠标放在视频封面上 可以右键 复制正确链接的网站 11 | // 不能保证一定能用,不能用的欢迎反馈 12 | 13 | /// 是否模拟 PC 是 1, 手机是 0 14 | const isUsePC = 1 15 | /// 默认应该是 0,当视频不能播放的时候,可以把这个设置为 1, 否则不要改动 16 | const isAddReferer = 0 17 | 18 | /// 当前网站是不是网盘资源分享站 0 不是,1 是 19 | const isPan = 1 20 | 21 | /// 匹配的网盘类型,一般不需要改动 22 | const panUrls = [ 23 | '189.cn', //天翼 24 | '123684.com', // 123 25 | '123865.com', 26 | '123912.com', 27 | '123pan.com', 28 | '123pan.cn', 29 | '123592.com', 30 | 'pan.quark.cn', // 夸克 31 | 'drive.uc.cn', // uc 32 | 'alipan.com', // 阿里 33 | ] 34 | 35 | // 网站主页 36 | const webSite = 'https://www.revohd.com' 37 | 38 | // 网站搜索 39 | // https://www.revohd.com/vodsearch/海----------2---.html 40 | // 把网站主页变成 @{webSite} 把搜索词变成 @{searchWord} 把页码变成 @{page} 41 | const searchUrl = '@{webSite}/vodsearch/@{searchWord}----------@{page}---.html' 42 | 43 | // 当前网站任意视频详情页 44 | // https://www.revohd.com/voddetail/12895.html 45 | const videoDetailPage = '@{webSite}/voddetail/12895.html' 46 | 47 | // 当 isPan = 1 时,表明是资源分享站 这个不用改动。 48 | // 当前网站任意视频播放页 49 | const videoPlayPage = '' 50 | 51 | // 保持不变 52 | const filterListUrl = '' 53 | 54 | const firstClass = [ 55 | { 56 | name: '电影', 57 | // https://www.revohd.com/vod/show/id/1/page/2.html 58 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 59 | id: '@{webSite}/vod/show/id/1/page/@{page}.html', 60 | }, 61 | { 62 | name: '剧集', 63 | // https://www.revohd.com/vod/show/id/2/page/2.html 64 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 65 | id: '@{webSite}/vod/show/id/2/page/@{page}.html', 66 | }, 67 | { 68 | name: '动漫', 69 | // https://www.revohd.com/vod/show/id/5/page/2.html 70 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 71 | id: '@{webSite}/vod/show/id/5/page/@{page}.html', 72 | }, 73 | { 74 | name: '娱乐', 75 | // https://www.revohd.com/vod/show/id/3/page/2.html 76 | // 把网站主页变成 @{webSite} 把页码变成 @{page} 77 | id: '@{webSite}/vod/show/id/3/page/@{page}.html', 78 | }, 79 | ] 80 | 81 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 82 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 83 | // 下面这个不要有任何改动,且保持在最后一行,加载内置代码需要 84 | 85 | //#BaseCode1# -------------------------------------------------------------------------------- /vod/js/shandian.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 闪电 2 | //@version:1 3 | //@webSite:http://1.95.79.193/ 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'http://1.95.79.193/', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '闪电电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '闪电剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '闪电综艺', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '闪电动漫', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '30', 62 | type_name: '闪电短剧', 63 | hasSubclass: false, 64 | }, 65 | ] 66 | return JSON.stringify(backData) 67 | } 68 | async function getSubclassList(args) { 69 | let backData = new RepVideoSubclassList() 70 | return JSON.stringify(backData) 71 | } 72 | async function getSubclassVideoList(args) { 73 | var backData = new RepVideoList() 74 | return JSON.stringify(backData) 75 | } 76 | /** 77 | * 获取分类视频列表 78 | * @param {UZArgs} args 79 | * @returns {Promise} 80 | */ 81 | async function getVideoList(args) { 82 | var backData = new RepVideoList() 83 | let url = 84 | UZUtils.removeTrailingSlash(appConfig.webSite) + 85 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 86 | try { 87 | const pro = await req(url) 88 | backData.error = pro.error 89 | let videos = [] 90 | if (pro.data) { 91 | const $ = cheerio.load(pro.data) 92 | let vodItems = $('#main .module-item') 93 | vodItems.each((_, e) => { 94 | let videoDet = new VideoDetail() 95 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 96 | videoDet.vod_name = $(e) 97 | .find('.module-item-pic img') 98 | .attr('alt') 99 | videoDet.vod_pic = $(e) 100 | .find('.module-item-pic img') 101 | .attr('data-src') 102 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 103 | videoDet.vod_year = $(e) 104 | .find('.module-item-caption span') 105 | .first() 106 | .text() 107 | videos.push(videoDet) 108 | }) 109 | } 110 | backData.data = videos 111 | } catch (error) {} 112 | return JSON.stringify(backData) 113 | } 114 | 115 | /** 116 | * 获取视频详情 117 | * @param {UZArgs} args 118 | * @returns {Promise} 119 | */ 120 | async function getVideoDetail(args) { 121 | var backData = new RepVideoDetail() 122 | try { 123 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 124 | let pro = await req(webUrl) 125 | 126 | backData.error = pro.error 127 | let proData = pro.data 128 | if (proData) { 129 | const $ = cheerio.load(proData) 130 | let vodDetail = new VideoDetail() 131 | vodDetail.vod_id = args.url 132 | vodDetail.vod_name = $('.page-title')[0].children[0].data 133 | vodDetail.vod_pic = $($('.mobile-play')).find( 134 | '.lazyload' 135 | )[0].attribs['data-src'] 136 | 137 | let video_items = $('.video-info-itemtitle') 138 | 139 | for (const item of video_items) { 140 | let key = $(item).text() 141 | 142 | let vItems = $(item).next().find('a') 143 | let value = vItems 144 | .map((i, el) => { 145 | let text = $(el).text().trim() // 获取并去除空白字符 146 | return text ? text : null // 只有非空的文本才返回 147 | }) 148 | .get() // 将 jQuery 对象转换为普通数组 149 | .filter(Boolean) // 过滤掉 null 和空字符串 150 | .join(', ') // 用逗号和空格分割 151 | 152 | if (key.includes('剧情')) { 153 | vodDetail.vod_content = $(item) 154 | .next() 155 | .find('p') 156 | .text() 157 | .trim() 158 | } else if (key.includes('导演')) { 159 | vodDetail.vod_director = value.trim() 160 | } else if (key.includes('主演')) { 161 | vodDetail.vod_actor = value.trim() 162 | } 163 | } 164 | 165 | const panUrls = [] 166 | let items = $('.module-row-info') 167 | for (const item of items) { 168 | let shareUrl = $(item).find('p')[0].children[0].data 169 | panUrls.push(shareUrl) 170 | } 171 | vodDetail.panUrls = panUrls 172 | console.log(panUrls) 173 | 174 | backData.data = vodDetail 175 | } 176 | } catch (error) { 177 | backData.error = '获取视频详情失败' + error 178 | } 179 | 180 | return JSON.stringify(backData) 181 | } 182 | 183 | /** 184 | * 获取视频的播放地址 185 | * @param {UZArgs} args 186 | * @returns {Promise} 187 | */ 188 | async function getVideoPlayUrl(args) { 189 | var backData = new RepVideoPlayUrl() 190 | return JSON.stringify(backData) 191 | } 192 | 193 | /** 194 | * 搜索视频 195 | * @param {UZArgs} args 196 | * @returns {Promise} 197 | */ 198 | async function searchVideo(args) { 199 | var backData = new RepVideoList() 200 | try { 201 | let searchUrl = `${UZUtils.removeTrailingSlash( 202 | appConfig.webSite 203 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 204 | let repData = await req(searchUrl) 205 | 206 | const $ = cheerio.load(repData.data) 207 | let items = $('.module-search-item') 208 | 209 | for (const item of items) { 210 | let video = new VideoDetail() 211 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 212 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 213 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 214 | 'data-src' 215 | ] 216 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 217 | backData.data.push(video) 218 | } 219 | } catch (error) { 220 | backData.error = error 221 | } 222 | return JSON.stringify(backData) 223 | } 224 | 225 | function combineUrl(url) { 226 | if (url === undefined) { 227 | return '' 228 | } 229 | if (url.indexOf(appConfig.webSite) !== -1) { 230 | return url 231 | } 232 | if (url.startsWith('/')) { 233 | return appConfig.webSite + url 234 | } 235 | return appConfig.webSite + '/' + url 236 | } 237 | -------------------------------------------------------------------------------- /vod/js/tianyiso.txt: -------------------------------------------------------------------------------- 1 | // ignore 2 | //@name:「盘」 天逸搜 3 | //@version:3 4 | //@webSite:https://www.tianyiso.com 5 | //@remark:来自proversion2024,仅搜索 6 | //@codeID:DU9z425w42hk9B8l 7 | //@type:100 8 | //@instance:tianyiso20241129 9 | //@order: B 10 | // ignore 11 | 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 -------------------------------------------------------------------------------- /vod/js/wobg.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 玩偶 2 | //@version:3 3 | //@webSite:http://wogg.xxooo.cf 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'http://wogg.xxooo.cf', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '玩偶电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '玩偶剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '玩偶动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '玩偶综艺', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '44', 62 | type_name: '臻彩视界', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '6', 67 | type_name: '玩偶短剧', 68 | hasSubclass: false, 69 | }, 70 | { 71 | type_id: '5', 72 | type_name: '玩偶音乐', 73 | hasSubclass: false, 74 | }, 75 | { 76 | type_id: '46', 77 | type_name: '玩偶纪录', 78 | hasSubclass: false, 79 | }, 80 | ] 81 | return JSON.stringify(backData) 82 | } 83 | async function getSubclassList(args) { 84 | let backData = new RepVideoSubclassList() 85 | return JSON.stringify(backData) 86 | } 87 | async function getSubclassVideoList(args) { 88 | var backData = new RepVideoList() 89 | return JSON.stringify(backData) 90 | } 91 | /** 92 | * 获取分类视频列表 93 | * @param {UZArgs} args 94 | * @returns {Promise} 95 | */ 96 | async function getVideoList(args) { 97 | var backData = new RepVideoList() 98 | let url = 99 | UZUtils.removeTrailingSlash(appConfig.webSite) + 100 | `/vodshow/${args.url}--------${args.page}---.html` 101 | try { 102 | const pro = await req(url) 103 | backData.error = pro.error 104 | 105 | let videos = [] 106 | if (pro.data) { 107 | const $ = cheerio.load(pro.data) 108 | let vodItems = $('#main .module-item') 109 | vodItems.each((_, e) => { 110 | let videoDet = new VideoDetail() 111 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 112 | videoDet.vod_name = $(e) 113 | .find('.module-item-pic img') 114 | .attr('alt') 115 | videoDet.vod_pic = $(e) 116 | .find('.module-item-pic img') 117 | .attr('data-src') 118 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 119 | videos.push(videoDet) 120 | }) 121 | } 122 | backData.data = videos 123 | } catch (error) {} 124 | return JSON.stringify(backData) 125 | } 126 | 127 | /** 128 | * 获取视频详情 129 | * @param {UZArgs} args 130 | * @returns {Promise} 131 | */ 132 | async function getVideoDetail(args) { 133 | var backData = new RepVideoDetail() 134 | try { 135 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 136 | let pro = await req(webUrl) 137 | 138 | backData.error = pro.error 139 | let proData = pro.data 140 | if (proData) { 141 | const $ = cheerio.load(proData) 142 | let vodDetail = new VideoDetail() 143 | vodDetail.vod_id = args.url 144 | vodDetail.vod_name = $('.page-title')[0].children[0].data 145 | vodDetail.vod_pic = $($('.mobile-play')).find( 146 | '.lazyload' 147 | )[0].attribs['data-src'] 148 | 149 | let video_items = $('.video-info-itemtitle') 150 | 151 | for (const item of video_items) { 152 | let key = $(item).text() 153 | 154 | let vItems = $(item).next().find('a') 155 | let value = vItems 156 | .map((i, el) => { 157 | let text = $(el).text().trim() // 获取并去除空白字符 158 | return text ? text : null // 只有非空的文本才返回 159 | }) 160 | .get() // 将 jQuery 对象转换为普通数组 161 | .filter(Boolean) // 过滤掉 null 和空字符串 162 | .join(', ') // 用逗号和空格分割 163 | 164 | if (key.includes('年代')) { 165 | vodDetail.vod_year = value.trim() 166 | } else if (key.includes('导演')) { 167 | vodDetail.vod_director = value.trim() 168 | } else if (key.includes('主演')) { 169 | vodDetail.vod_actor = value.trim() 170 | } 171 | } 172 | 173 | const panUrls = [] 174 | let items = $('.module-row-info') 175 | for (const item of items) { 176 | let shareUrl = $(item).find('p')[0].children[0].data 177 | panUrls.push(shareUrl) 178 | } 179 | vodDetail.panUrls = panUrls 180 | console.log(panUrls) 181 | 182 | backData.data = vodDetail 183 | } 184 | } catch (error) { 185 | backData.error = '获取视频详情失败' + error 186 | } 187 | 188 | return JSON.stringify(backData) 189 | } 190 | 191 | /** 192 | * 获取视频的播放地址 193 | * @param {UZArgs} args 194 | * @returns {Promise} 195 | */ 196 | async function getVideoPlayUrl(args) { 197 | var backData = new RepVideoPlayUrl() 198 | return JSON.stringify(backData) 199 | } 200 | 201 | /** 202 | * 搜索视频 203 | * @param {UZArgs} args 204 | * @returns {Promise} 205 | */ 206 | async function searchVideo(args) { 207 | var backData = new RepVideoList() 208 | try { 209 | let searchUrl = combineUrl( 210 | 'vodsearch/' + 211 | args.searchWord + 212 | '----------' + 213 | args.page + 214 | '---.html' 215 | ) 216 | let repData = await req(searchUrl) 217 | 218 | const $ = cheerio.load(repData.data) 219 | let items = $('.module-search-item') 220 | 221 | for (const item of items) { 222 | let video = new VideoDetail() 223 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 224 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 225 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 226 | 'data-src' 227 | ] 228 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 229 | backData.data.push(video) 230 | } 231 | } catch (error) { 232 | backData.error = error 233 | } 234 | return JSON.stringify(backData) 235 | } 236 | 237 | function combineUrl(url) { 238 | if (url === undefined) { 239 | return '' 240 | } 241 | if (url.indexOf(appConfig.webSite) !== -1) { 242 | return url 243 | } 244 | if (url.startsWith('/')) { 245 | return appConfig.webSite + url 246 | } 247 | return appConfig.webSite + '/' + url 248 | } 249 | -------------------------------------------------------------------------------- /vod/js/xiafan.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 下饭 2 | //@version:1 3 | //@webSite:http://www.xn--ghqy10g1w0a.xyz/ 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'http://www.xn--ghqy10g1w0a.xyz/', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '下饭电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '下饭剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '下饭动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '下饭综艺', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '30', 62 | type_name: '下饭臻彩', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '28', 67 | type_name: '下饭记录', 68 | hasSubclass: false, 69 | }, 70 | ] 71 | return JSON.stringify(backData) 72 | } 73 | async function getSubclassList(args) { 74 | let backData = new RepVideoSubclassList() 75 | return JSON.stringify(backData) 76 | } 77 | async function getSubclassVideoList(args) { 78 | var backData = new RepVideoList() 79 | return JSON.stringify(backData) 80 | } 81 | /** 82 | * 获取分类视频列表 83 | * @param {UZArgs} args 84 | * @returns {Promise} 85 | */ 86 | async function getVideoList(args) { 87 | var backData = new RepVideoList() 88 | let url = 89 | UZUtils.removeTrailingSlash(appConfig.webSite) + 90 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 91 | try { 92 | const pro = await req(url) 93 | backData.error = pro.error 94 | let videos = [] 95 | if (pro.data) { 96 | const $ = cheerio.load(pro.data) 97 | let vodItems = $('#main .module-item') 98 | vodItems.each((_, e) => { 99 | let videoDet = new VideoDetail() 100 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 101 | videoDet.vod_name = $(e) 102 | .find('.module-item-pic img') 103 | .attr('alt') 104 | videoDet.vod_pic = $(e) 105 | .find('.module-item-pic img') 106 | .attr('data-src') 107 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 108 | videoDet.vod_year = $(e) 109 | .find('.module-item-caption span') 110 | .first() 111 | .text() 112 | videos.push(videoDet) 113 | }) 114 | } 115 | backData.data = videos 116 | } catch (error) {} 117 | return JSON.stringify(backData) 118 | } 119 | 120 | /** 121 | * 获取视频详情 122 | * @param {UZArgs} args 123 | * @returns {Promise} 124 | */ 125 | async function getVideoDetail(args) { 126 | var backData = new RepVideoDetail() 127 | try { 128 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 129 | let pro = await req(webUrl) 130 | 131 | backData.error = pro.error 132 | let proData = pro.data 133 | if (proData) { 134 | const $ = cheerio.load(proData) 135 | let vodDetail = new VideoDetail() 136 | vodDetail.vod_id = args.url 137 | vodDetail.vod_name = $('.page-title')[0].children[0].data 138 | vodDetail.vod_pic = $($('.mobile-play')).find( 139 | '.lazyload' 140 | )[0].attribs['data-src'] 141 | 142 | let video_items = $('.video-info-itemtitle') 143 | 144 | for (const item of video_items) { 145 | let key = $(item).text() 146 | 147 | let vItems = $(item).next().find('a') 148 | let value = vItems 149 | .map((i, el) => { 150 | let text = $(el).text().trim() // 获取并去除空白字符 151 | return text ? text : null // 只有非空的文本才返回 152 | }) 153 | .get() // 将 jQuery 对象转换为普通数组 154 | .filter(Boolean) // 过滤掉 null 和空字符串 155 | .join(', ') // 用逗号和空格分割 156 | 157 | if (key.includes('剧情')) { 158 | vodDetail.vod_content = $(item) 159 | .next() 160 | .find('p') 161 | .text() 162 | .trim() 163 | } else if (key.includes('导演')) { 164 | vodDetail.vod_director = value.trim() 165 | } else if (key.includes('主演')) { 166 | vodDetail.vod_actor = value.trim() 167 | } 168 | } 169 | 170 | const panUrls = [] 171 | let items = $('.module-row-info') 172 | for (const item of items) { 173 | let shareUrl = $(item).find('p')[0].children[0].data 174 | panUrls.push(shareUrl) 175 | } 176 | vodDetail.panUrls = panUrls 177 | console.log(panUrls) 178 | 179 | backData.data = vodDetail 180 | } 181 | } catch (error) { 182 | backData.error = '获取视频详情失败' + error 183 | } 184 | 185 | return JSON.stringify(backData) 186 | } 187 | 188 | /** 189 | * 获取视频的播放地址 190 | * @param {UZArgs} args 191 | * @returns {Promise} 192 | */ 193 | async function getVideoPlayUrl(args) { 194 | var backData = new RepVideoPlayUrl() 195 | return JSON.stringify(backData) 196 | } 197 | 198 | /** 199 | * 搜索视频 200 | * @param {UZArgs} args 201 | * @returns {Promise} 202 | */ 203 | async function searchVideo(args) { 204 | var backData = new RepVideoList() 205 | try { 206 | let searchUrl = `${UZUtils.removeTrailingSlash( 207 | appConfig.webSite 208 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 209 | let repData = await req(searchUrl) 210 | 211 | const $ = cheerio.load(repData.data) 212 | let items = $('.module-search-item') 213 | 214 | for (const item of items) { 215 | let video = new VideoDetail() 216 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 217 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 218 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 219 | 'data-src' 220 | ] 221 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 222 | backData.data.push(video) 223 | } 224 | } catch (error) { 225 | backData.error = error 226 | } 227 | return JSON.stringify(backData) 228 | } 229 | 230 | function combineUrl(url) { 231 | if (url === undefined) { 232 | return '' 233 | } 234 | if (url.indexOf(appConfig.webSite) !== -1) { 235 | return url 236 | } 237 | if (url.startsWith('/')) { 238 | return appConfig.webSite + url 239 | } 240 | return appConfig.webSite + '/' + url 241 | } 242 | -------------------------------------------------------------------------------- /vod/js/xiaomi.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 小米 2 | //@version:3 3 | //@webSite:https://xiaomiai.site 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://xiaomiai.site', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '小米电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '小米剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '小米动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '小米综艺', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '5', 62 | type_name: '小米短剧', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '24', 67 | type_name: '小米老剧', 68 | hasSubclass: false, 69 | }, 70 | { 71 | type_id: '26', 72 | type_name: '小米臻彩', 73 | hasSubclass: false, 74 | }, 75 | ] 76 | return JSON.stringify(backData) 77 | } 78 | async function getSubclassList(args) { 79 | let backData = new RepVideoSubclassList() 80 | return JSON.stringify(backData) 81 | } 82 | async function getSubclassVideoList(args) { 83 | var backData = new RepVideoList() 84 | return JSON.stringify(backData) 85 | } 86 | /** 87 | * 获取分类视频列表 88 | * @param {UZArgs} args 89 | * @returns {Promise} 90 | */ 91 | async function getVideoList(args) { 92 | var backData = new RepVideoList() 93 | let url = 94 | UZUtils.removeTrailingSlash(appConfig.webSite) + 95 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 96 | try { 97 | const pro = await req(url) 98 | backData.error = pro.error 99 | let videos = [] 100 | if (pro.data) { 101 | const $ = cheerio.load(pro.data) 102 | let vodItems = $('#main .module-item') 103 | vodItems.each((_, e) => { 104 | let videoDet = new VideoDetail() 105 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 106 | videoDet.vod_name = $(e) 107 | .find('.module-item-pic img') 108 | .attr('alt') 109 | videoDet.vod_pic = $(e) 110 | .find('.module-item-pic img') 111 | .attr('data-src') 112 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 113 | videoDet.vod_year = $(e) 114 | .find('.module-item-caption span') 115 | .first() 116 | .text() 117 | videos.push(videoDet) 118 | }) 119 | } 120 | backData.data = videos 121 | } catch (error) {} 122 | return JSON.stringify(backData) 123 | } 124 | 125 | /** 126 | * 获取视频详情 127 | * @param {UZArgs} args 128 | * @returns {Promise} 129 | */ 130 | async function getVideoDetail(args) { 131 | var backData = new RepVideoDetail() 132 | try { 133 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 134 | let pro = await req(webUrl) 135 | 136 | backData.error = pro.error 137 | let proData = pro.data 138 | if (proData) { 139 | const $ = cheerio.load(proData) 140 | let vodDetail = new VideoDetail() 141 | vodDetail.vod_id = args.url 142 | vodDetail.vod_name = $('.page-title')[0].children[0].data 143 | vodDetail.vod_pic = $($('.mobile-play')).find( 144 | '.lazyload' 145 | )[0].attribs['data-src'] 146 | 147 | let video_items = $('.video-info-itemtitle') 148 | 149 | for (const item of video_items) { 150 | let key = $(item).text() 151 | 152 | let vItems = $(item).next().find('a') 153 | let value = vItems 154 | .map((i, el) => { 155 | let text = $(el).text().trim() // 获取并去除空白字符 156 | return text ? text : null // 只有非空的文本才返回 157 | }) 158 | .get() // 将 jQuery 对象转换为普通数组 159 | .filter(Boolean) // 过滤掉 null 和空字符串 160 | .join(', ') // 用逗号和空格分割 161 | 162 | if (key.includes('剧情')) { 163 | vodDetail.vod_content = $(item) 164 | .next() 165 | .find('p') 166 | .text() 167 | .trim() 168 | } else if (key.includes('导演')) { 169 | vodDetail.vod_director = value.trim() 170 | } else if (key.includes('主演')) { 171 | vodDetail.vod_actor = value.trim() 172 | } 173 | } 174 | 175 | const panUrls = [] 176 | let items = $('.module-row-info') 177 | for (const item of items) { 178 | let shareUrl = $(item).find('p')[0].children[0].data 179 | panUrls.push(shareUrl) 180 | } 181 | vodDetail.panUrls = panUrls 182 | console.log(panUrls) 183 | 184 | backData.data = vodDetail 185 | } 186 | } catch (error) { 187 | backData.error = '获取视频详情失败' + error 188 | } 189 | 190 | return JSON.stringify(backData) 191 | } 192 | 193 | /** 194 | * 获取视频的播放地址 195 | * @param {UZArgs} args 196 | * @returns {Promise} 197 | */ 198 | async function getVideoPlayUrl(args) { 199 | var backData = new RepVideoPlayUrl() 200 | return JSON.stringify(backData) 201 | } 202 | 203 | /** 204 | * 搜索视频 205 | * @param {UZArgs} args 206 | * @returns {Promise} 207 | */ 208 | async function searchVideo(args) { 209 | var backData = new RepVideoList() 210 | try { 211 | let searchUrl = `${UZUtils.removeTrailingSlash( 212 | appConfig.webSite 213 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 214 | let repData = await req(searchUrl) 215 | const $ = cheerio.load(repData.data) 216 | let items = $('.module-search-item') 217 | 218 | for (const item of items) { 219 | let video = new VideoDetail() 220 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 221 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 222 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 223 | 'data-src' 224 | ] 225 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 226 | backData.data.push(video) 227 | } 228 | } catch (error) { 229 | backData.error = error 230 | } 231 | return JSON.stringify(backData) 232 | } 233 | 234 | function combineUrl(url) { 235 | if (url === undefined) { 236 | return '' 237 | } 238 | if (url.indexOf(appConfig.webSite) !== -1) { 239 | return url 240 | } 241 | if (url.startsWith('/')) { 242 | return appConfig.webSite + url 243 | } 244 | return appConfig.webSite + '/' + url 245 | } 246 | -------------------------------------------------------------------------------- /vod/js/zhizhen.js: -------------------------------------------------------------------------------- 1 | //@name:「盘」 至臻 2 | //@version:3 3 | //@webSite:https://mihdr.top 4 | //@remark: 5 | //@order: B 6 | const appConfig = { 7 | _webSite: 'https://mihdr.top', 8 | /** 9 | * 网站主页,uz 调用每个函数前都会进行赋值操作 10 | * 如果不想被改变 请自定义一个变量 11 | */ 12 | get webSite() { 13 | return this._webSite 14 | }, 15 | set webSite(value) { 16 | this._webSite = value 17 | }, 18 | 19 | _uzTag: '', 20 | /** 21 | * 扩展标识,初次加载时,uz 会自动赋值,请勿修改 22 | * 用于读取环境变量 23 | */ 24 | get uzTag() { 25 | return this._uzTag 26 | }, 27 | set uzTag(value) { 28 | this._uzTag = value 29 | }, 30 | } 31 | 32 | /** 33 | * 异步获取分类列表的方法。 34 | * @param {UZArgs} args 35 | * @returns {Promise} 36 | */ 37 | async function getClassList(args) { 38 | var backData = new RepVideoClassList() 39 | backData.data = [ 40 | { 41 | type_id: '1', 42 | type_name: '至臻电影', 43 | hasSubclass: false, 44 | }, 45 | { 46 | type_id: '2', 47 | type_name: '至臻剧集', 48 | hasSubclass: false, 49 | }, 50 | { 51 | type_id: '3', 52 | type_name: '至臻动漫', 53 | hasSubclass: false, 54 | }, 55 | { 56 | type_id: '4', 57 | type_name: '至臻综艺', 58 | hasSubclass: false, 59 | }, 60 | { 61 | type_id: '5', 62 | type_name: '至臻短剧', 63 | hasSubclass: false, 64 | }, 65 | { 66 | type_id: '24', 67 | type_name: '至臻老剧', 68 | hasSubclass: false, 69 | }, 70 | { 71 | type_id: '26', 72 | type_name: '至臻严选', 73 | hasSubclass: false, 74 | }, 75 | ] 76 | return JSON.stringify(backData) 77 | } 78 | 79 | async function getSubclassList(args) { 80 | let backData = new RepVideoSubclassList() 81 | return JSON.stringify(backData) 82 | } 83 | async function getSubclassVideoList(args) { 84 | var backData = new RepVideoList() 85 | return JSON.stringify(backData) 86 | } 87 | /** 88 | * 获取分类视频列表 89 | * @param {UZArgs} args 90 | * @returns {Promise} 91 | */ 92 | async function getVideoList(args) { 93 | var backData = new RepVideoList() 94 | let url = 95 | UZUtils.removeTrailingSlash(appConfig.webSite) + 96 | `/index.php/vod/show/id/${args.url}/page/${args.page}.html` 97 | try { 98 | const pro = await req(url) 99 | backData.error = pro.error 100 | let videos = [] 101 | if (pro.data) { 102 | const $ = cheerio.load(pro.data) 103 | let vodItems = $('#main .module-item') 104 | vodItems.each((_, e) => { 105 | let videoDet = new VideoDetail() 106 | videoDet.vod_id = $(e).find('.module-item-pic a').attr('href') 107 | videoDet.vod_name = $(e) 108 | .find('.module-item-pic img') 109 | .attr('alt') 110 | videoDet.vod_pic = $(e) 111 | .find('.module-item-pic img') 112 | .attr('data-src') 113 | videoDet.vod_remarks = $(e).find('.module-item-text').text() 114 | videoDet.vod_year = $(e) 115 | .find('.module-item-caption span') 116 | .first() 117 | .text() 118 | videos.push(videoDet) 119 | }) 120 | } 121 | backData.data = videos 122 | } catch (error) {} 123 | return JSON.stringify(backData) 124 | } 125 | 126 | /** 127 | * 获取视频详情 128 | * @param {UZArgs} args 129 | * @returns {Promise} 130 | */ 131 | async function getVideoDetail(args) { 132 | var backData = new RepVideoDetail() 133 | try { 134 | let webUrl = UZUtils.removeTrailingSlash(appConfig.webSite) + args.url 135 | let pro = await req(webUrl) 136 | 137 | backData.error = pro.error 138 | let proData = pro.data 139 | if (proData) { 140 | const $ = cheerio.load(proData) 141 | let vodDetail = new VideoDetail() 142 | vodDetail.vod_id = args.url 143 | vodDetail.vod_name = $('.page-title')[0].children[0].data 144 | vodDetail.vod_pic = $($('.mobile-play')).find( 145 | '.lazyload' 146 | )[0].attribs['data-src'] 147 | 148 | let video_items = $('.video-info-itemtitle') 149 | 150 | for (const item of video_items) { 151 | let key = $(item).text() 152 | 153 | let vItems = $(item).next().find('a') 154 | let value = vItems 155 | .map((i, el) => { 156 | let text = $(el).text().trim() // 获取并去除空白字符 157 | return text ? text : null // 只有非空的文本才返回 158 | }) 159 | .get() // 将 jQuery 对象转换为普通数组 160 | .filter(Boolean) // 过滤掉 null 和空字符串 161 | .join(', ') // 用逗号和空格分割 162 | 163 | if (key.includes('剧情')) { 164 | vodDetail.vod_content = $(item) 165 | .next() 166 | .find('p') 167 | .text() 168 | .trim() 169 | } else if (key.includes('导演')) { 170 | vodDetail.vod_director = value.trim() 171 | } else if (key.includes('主演')) { 172 | vodDetail.vod_actor = value.trim() 173 | } 174 | } 175 | 176 | const panUrls = [] 177 | let items = $('.module-row-info') 178 | for (const item of items) { 179 | let shareUrl = $(item).find('p')[0].children[0].data 180 | panUrls.push(shareUrl) 181 | } 182 | vodDetail.panUrls = panUrls 183 | console.log(panUrls) 184 | 185 | backData.data = vodDetail 186 | } 187 | } catch (error) { 188 | backData.error = '获取视频详情失败' + error 189 | } 190 | 191 | return JSON.stringify(backData) 192 | } 193 | 194 | /** 195 | * 获取视频的播放地址 196 | * @param {UZArgs} args 197 | * @returns {Promise} 198 | */ 199 | async function getVideoPlayUrl(args) { 200 | var backData = new RepVideoPlayUrl() 201 | return JSON.stringify(backData) 202 | } 203 | 204 | /** 205 | * 搜索视频 206 | * @param {UZArgs} args 207 | * @returns {Promise} 208 | */ 209 | async function searchVideo(args) { 210 | var backData = new RepVideoList() 211 | try { 212 | let searchUrl = `${UZUtils.removeTrailingSlash( 213 | appConfig.webSite 214 | )}/index.php/vod/search/page/${args.page}/wd/${args.searchWord}.html` 215 | let repData = await req(searchUrl) 216 | const $ = cheerio.load(repData.data) 217 | let items = $('.module-search-item') 218 | 219 | for (const item of items) { 220 | let video = new VideoDetail() 221 | video.vod_id = $(item).find('.video-serial')[0].attribs.href 222 | video.vod_name = $(item).find('.video-serial')[0].attribs.title 223 | video.vod_pic = $(item).find('.module-item-pic > img')[0].attribs[ 224 | 'data-src' 225 | ] 226 | video.vod_remarks = $($(item).find('.video-serial')[0]).text() 227 | backData.data.push(video) 228 | } 229 | } catch (error) { 230 | backData.error = error 231 | } 232 | return JSON.stringify(backData) 233 | } 234 | 235 | function combineUrl(url) { 236 | if (url === undefined) { 237 | return '' 238 | } 239 | if (url.indexOf(appConfig.webSite) !== -1) { 240 | return url 241 | } 242 | if (url.startsWith('/')) { 243 | return appConfig.webSite + url 244 | } 245 | return appConfig.webSite + '/' + url 246 | } 247 | --------------------------------------------------------------------------------