[
  {
    "articleStyle": 0,
    "customOrder": -10101009,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "",
    "sourceIcon": "https://www.yckceo.com/favicon.ico",
    "sourceName": "源仓库",
    "sourceUrl": "https://yckceo.vip/"
  },
  {
    "articleStyle": 0,
    "contentBlacklist": "",
    "contentWhitelist": "",
    "customOrder": -10101008,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n\"User-Agent\": \"Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; MI 8 Lite Build/OPM1.171019.019) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.2.0.1100 Mobile Safari/537.36\"\n}",
    "injectJs": "",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "class.module-item",
    "ruleContent": "<div class=\"play_video\">\n{{@@title@text}}{{@@class.player-wrapper@all}}",
    "ruleImage": "img@data-cover",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page",
    "rulePubDate": "class.module-item-caption@text",
    "ruleTitle": "img@alt",
    "singleUrl": false,
    "sortUrl": "变量搜索::/search?wd={{java.encodeURI(source.getVariable())}}\n\n最新::https://cn1.91short.com/\n推荐::/short/recommend_home_list/\n美女正妹::/short/label_related_list/Ug_pu_kskqY%3D\n91大神::/short/label_related_list/otDa4t6lDDQ%3D\n门事件::/short/label_related_list/3QW8lOdBcls%3D\n大神::/search?wd=大神\n\n学生::/search?wd=学生\n91::/search?wd=91\n偷情::/search?wd=偷情\n推特::/search?wd=推特\n少女::/search?wd=少女\n贫乳::/search?wd=贫乳\n口交::/search?wd=口交\n妹妹::/search?wd=妹妹\n美女::/search?wd=美女\n\n美臀巨臀::/short/label_related_list/azG9-jZfzG0%3D?title=%E7%BE%8E%E8%87%80%E5%B7%A8%E8%87%80\n后入::/search?wd=后入\n国产高清::/short/home_category_list/hd\n排行::/short/ranking_list\n国产AV::/short/label_related_list/1Bd0Zzp8D_E%3D\n大象传媒::/short/label_related_list/F16wCJ3LmWY%3D\n情趣综艺::/short/label_related_list/-0S1LwkskU4%3D\n推荐2::/film/home_recommend_list\n专题::/film/home_subject_list\n女优::/film/home_actor_list\n无码::/film/home_category_list/coded\n中字::/film/home_category_list/chinese_subtitle\n动漫::/film/home_list/jOSxa-4E27U%3D\n经典三级::/film/home_list/uZg0vDL8P8A%3D\n欧美性爱::/film/home_list/LblejiEnM6s%3D\nAV解说::/film/home_list/vJq_GzRiesQ%3D",
    "sourceComment": "翻页和封面不会\n\n永久域名 https://cn1.91short.com",
    "sourceGroup": "视频",
    "sourceIcon": "https://cn1.91short.com/public/statics/logo.png",
    "sourceName": "91视频",
    "sourceUrl": "https://cn1.91short.com/",
    "style": "iframe{\n\theight:auto\n}\ntitle{\n\tdisplay:block\n}"
  },
  {
    "articleStyle": 0,
    "contentBlacklist": "",
    "contentWhitelist": "",
    "customOrder": -10101007,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n\"User-Agent\": \"Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; MI 8 Lite Build/OPM1.171019.019) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 UCBrowser/13.2.0.1100 Mobile Safari/537.36\"\n}",
    "injectJs": "",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "class.module-item",
    "ruleContent": "<div class=\"play_video\">\n{{@@title@text}}{{@@class.player-wrapper@all}}",
    "ruleImage": "img@data-cover",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page",
    "rulePubDate": "class.module-item-caption@text",
    "ruleTitle": "img@alt",
    "singleUrl": false,
    "sortUrl": "搜索::/search?wd={{java.encodeURI(source.getVariable())}}\n\n最新::https://cn1.91short.com/\n推荐::/short/recommend_home_list/\n美女正妹::/short/label_related_list/Ug_pu_kskqY%3D\n91大神::/short/label_related_list/otDa4t6lDDQ%3D\n门事件::/short/label_related_list/3QW8lOdBcls%3D\n大神::/search?wd=大神\n\n学生::/search?wd=学生\n91::/search?wd=91\n偷情::/search?wd=偷情\n推特::/search?wd=推特\n少女::/search?wd=少女\n贫乳::/search?wd=贫乳\n口交::/search?wd=口交\n妹妹::/search?wd=妹妹\n美女::/search?wd=美女\n\n美臀巨臀::/short/label_related_list/azG9-jZfzG0%3D?title=%E7%BE%8E%E8%87%80%E5%B7%A8%E8%87%80\n后入::/search?wd=后入\n国产高清::/short/home_category_list/hd\n排行::/short/ranking_list\n国产AV::/short/label_related_list/1Bd0Zzp8D_E%3D\n大象传媒::/short/label_related_list/F16wCJ3LmWY%3D\n情趣综艺::/short/label_related_list/-0S1LwkskU4%3D\n推荐2::/film/home_recommend_list\n专题::/film/home_subject_list\n女优::/film/home_actor_list\n无码::/film/home_category_list/coded\n中字::/film/home_category_list/chinese_subtitle\n动漫::/film/home_list/jOSxa-4E27U%3D\n经典三级::/film/home_list/uZg0vDL8P8A%3D\n欧美性爱::/film/home_list/LblejiEnM6s%3D\nAV解说::/film/home_list/vJq_GzRiesQ%3D",
    "sourceComment": "翻页和封面不会\n\n永久域名 https://cn1.91short.com",
    "sourceGroup": "视频",
    "sourceIcon": "https://cn1.91short.com/public/statics/logo.png",
    "sourceName": "911",
    "sourceUrl": "https://cn1.91short.com",
    "style": "iframe{\n\theight:auto\n}\ntitle{\n\tdisplay:block\n}"
  },
  {
    "articleStyle": 0,
    "customOrder": -10101006,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 1775590466136,
    "loadWithBaseUrl": true,
    "ruleArticles": "article",
    "ruleContent": "class.dplayer@all<js>\nresult=result.match(/http.*0/)[0]##\\</js>{{@@title@text##成人黑料.*}}\n<video src=\"{{result}}\" width=\"100%\" height=\"auto\" controls></video>",
    "ruleImage": "@js:\"https://mgtv-bbqn.oss-cn-beijing.aliyuncs.com/1/2310310103284A29582395A850D3A0F5C26862354MzFE/SrRlbr0.gif\"",
    "ruleLink": "a@href",
    "ruleNextPage": "page",
    "rulePubDate": "span.1@text",
    "ruleTitle": "class.post-card-title@text",
    "singleUrl": false,
    "sortUrl": "搜索::/search/{{source.getVariable()}}/{{page}}/\n今日吃瓜::/category/wpcz/{{page}}/\n热门大瓜::/category/rdsj/{{page}}/\n学生校园::/category/xsxy/{{page}}/\n网红黑料::/category/whhl/{{page}}/\n看片娱乐::/category/ysyl/{{page}}/\n乱伦道德::/category/lldd/{{page}}/\n人人吃瓜::/category/rrcg/{{page}}/\n海外吃瓜::/category/hwcg/{{page}}/\n骚男骚女::/category/snsn/{{page}}/",
    "sourceComment": "https://51cgg32.com",
    "sourceGroup": "视频",
    "sourceIcon": "http://p6.itc.cn/images01/20201202/8d012ed623d647a78635557e7d235ab6.jpeg",
    "sourceName": "51吃瓜🥝",
    "sourceUrl": "https://arrange.vvwwyahpo.com"
  },
  {
    "articleStyle": 3,
    "customOrder": 0,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 1775587987390,
    "loadWithBaseUrl": true,
    "ruleArticles": "article",
    "ruleContent": "class.dplayer@all<js>\nresult=result.match(/http.*0/)[0]##\\</js>{{@@title@text##正在播放:|永久.*}}\n<video src=\"{{result}}\" width=\"100%\" height=\"auto\" controls></video>",
    "ruleImage": "@js:\"https://mgtv-bbqn.oss-cn-beijing.aliyuncs.com/1/2310310103284A29582395A850D3A0F5C26862354MzFE/SrRlbr0.gif\"",
    "ruleLink": "a.0@href",
    "ruleNextPage": "text.下一页@href",
    "rulePubDate": "span.1@text",
    "ruleTitle": "class.post-card-title@text",
    "singleUrl": false,
    "sortUrl": "搜索::/search/{{source.getVariable()}}/{{page}}/\n主播::/search/牛仔裤/{{page}}/\n今日事件::/category/mrxl/\n吃瓜热搜::/category/mldjh/\n学生校园::/category/xyml/\n看片娱乐::/category/ldcz/\n海角乱伦::/category/llsj/\n猎奇事件::/category/qwys/\n动漫大全::\t/category/dmdq/\n精选探花::/category/jxth/\n反差美女::/category/rmbg/\n网红黑料::/category/whmx/\n欧美系列::/category/omxl/\n日韩系列::/category/rhxl/\n户外野外::/category/hwyw/\n调教受虐::/category/tjsn/",
    "sourceComment": "https://mlgc01.co/",
    "sourceGroup": "视频",
    "sourceIcon": "http://p6.itc.cn/images01/20201202/8d012ed623d647a78635557e7d235ab6.jpeg",
    "sourceName": "91大事件🥝",
    "sourceUrl": "https://jd3dz1.sidtajvsr.cc"
  },
  {
    "articleStyle": 0,
    "customOrder": 4724,
    "enableJs": true,
    "enabled": false,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceComment": "",
    "sourceGroup": "视频",
    "sourceIcon": "",
    "sourceName": "51吃瓜",
    "sourceUrl": "https://51cgg32.com"
  },
  {
    "articleStyle": 0,
    "customOrder": 4725,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\"User-Agent\": \"Mozilla/5.0 (Linux; Android 12; 22041211AC Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36\"}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": ".list@li",
    "ruleContent": "<js>\nvar v = result.match(/source\\s*=\\s*[\"']([^\"']*?\\.(m3u8|mp4)\\b[^\"']*)[\"']/i);\nvar p = v ? v[1].replace(/\\\\/g,'') : '';\nvar t = '@get:{t}';\nvar d = java.getString('[property=\"video:tag\"]@content');\nvar sign1 = java.base64Decode('44CQ5aSc5piO56m644CR55qE5pKt5pS+5Zmo');\nvar sign2 = java.base64Decode('5LuF5L6b5Liq5Lq65a2m5Lmg5L2/55So77yM5Lil56aB5YiG5Lqr44CB5YCS5Y2W5Y+K5Lu75L2V6L+d5rOV6KGM5Li677yB');\nvar sign3 = java.base64Decode('5L2/55So6ICF6Ieq6KGM5om/5ouF6aOO6Zmp5LiO6LSj5Lu7');\n`<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>${t}</title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:-apple-system,sans-serif;background:#f0f9ff;padding:10px}\n.v-box{max-width:800px;margin:0 auto;background:white;border-radius:12px;box-shadow:0 5px 15px rgba(0,0,0,0.1);overflow:hidden}\n.header{padding:12px;border-bottom:1px solid #eee;display:flex;flex-wrap:wrap;justify-content:space-between}\n.sign{background:#e9f7ff;padding:6px;border-radius:6px;margin-bottom:8px;font-size:14px;color:#1a73e8;width:100%}\n.title{font-size:18px;font-weight:600;margin-bottom:8px;width:100%}\n.tags{color:#5f6368;font-size:14px;flex:1;min-width:60%;word-break:break-all}\n.time{color:#5f6368;font-size:14px;text-align:right;flex-basis:35%}\n.v-wrap{position:relative;padding-top:56.25%;background:#000}\n.video{position:absolute;top:0;left:0;width:100%;height:100%}\n.footer{padding:8px;text-align:center;color:#5f6368;font-size:13px}\n.info-box{padding:15px;font-size:14px;line-height:1.6}\n.info-box p{margin:8px 0}\n.hint{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,0.7);color:#fff;padding:12px 20px;border-radius:20px;font-size:1.1rem;z-index:10;display:none}\n.controls{position:absolute;top:0;left:0;width:100%;height:4px;background:rgba(255,255,255,0.3);z-index:5;transition:opacity 0.3s}\n.progress{height:100%;background:#4a9eff;width:0}\n</style>\n</head>\n<body>\n<div class=\"v-box\">\n<div class=\"header\">\n<div class=\"sign\" style=\"text-align:center;padding:5px 0\">\n<div>${sign1}</div>\n<div style=\"text-align:left; padding-top:4px\">\n${sign2}<br>${sign3}</div>\n</div>\n<div class=\"title\">${t}</div>\n<div class=\"tags\">${d}</div>\n<div class=\"time\" id=\"timeDisplay\">00:00/00:00</div></div>\n<div class=\"v-wrap\">\n<div class=\"controls\"><div class=\"progress\" id=\"progressBar\"></div></div>\n<div class=\"hint\" id=\"hint\">快进中 &gt;&gt;</div>\n<video class=\"video\" id=\"v\" controls playsinline>\n<source src=\"${p}\" type=\"video/mp4\">您的浏览器不支持HTML5视频\n</video>\n</div>\n<div class=\"footer\">滑动调整进度 | 长按2倍速</div>\n</div>\n<script>\nvar v = document.getElementById('v');\nvar tDisplay = document.getElementById('timeDisplay');\nvar pBar = document.getElementById('progressBar');\nvar hint = document.getElementById('hint');\nvar startX = 0, startTime = 0;\nvar longPressTimer;\nvar sensitivity = 0.1;\nvar longPressTime = 500;\nvar hintDuration = 2000;\nfunction updateTime() {\nif (!v.duration) return;\nvar m1 = Math.floor(v.currentTime / 60);\nvar s1 = Math.floor(v.currentTime % 60);\nvar m2 = Math.floor(v.duration / 60);\nvar s2 = Math.floor(v.duration % 60);\ntDisplay.textContent = m1 + ':' + (s1 < 10 ? '0' : '') + s1 + '/' + m2 + ':' + (s2 < 10 ? '0' : '') + s2;\npBar.style.width = (v.currentTime / v.duration) * 100 + '%';}\nv.addEventListener('timeupdate', updateTime);\nv.addEventListener('loadedmetadata', updateTime);\nv.addEventListener('touchstart', function(e) {\nstartX = e.touches[0].clientX;\nstartTime = Date.now();\nif (longPressTimer) clearTimeout(longPressTimer);\nhint.style.display = 'none';\nlongPressTimer = setTimeout(function() {\nv.playbackRate = 2.0;\nhint.style.display = 'block';\nsetTimeout(function() { hint.style.display = 'none'; }, hintDuration);}, longPressTime);});\nv.addEventListener('touchmove', function(e) {\ne.preventDefault();\nclearTimeout(longPressTimer);\nvar diffX = e.touches[0].clientX - startX;\nvar change = diffX * sensitivity * v.duration / 100;\nv.currentTime = Math.max(0, Math.min(v.currentTime + change, v.duration));\nstartX = e.touches[0].clientX;updateTime();});\nv.addEventListener('touchend', function() {\nv.playbackRate = 1.0;\nclearTimeout(longPressTimer);});\n</script>\n</body>\n</html>`\n</js>",
    "ruleImage": "img@data-original",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page",
    "rulePubDate": "{{@@.vodlist_img@html##(\\d+)-(\\d+)-(\\d+)##$0###}} | {{@@.vodlist_img@span.0@text}}",
    "ruleTitle": ".title@text@put:{\"t\":\"@@.title@text\"}",
    "singleUrl": false,
    "sortUrl": "搜索 🔍::/s/page/{{page}}/wd/{{source.getVariable()}}/\n最新::/label/hot/by/time/page/{{page}}/\n日榜::/label/hot/by/hits_day/page/{{page}}/\n周榜::/label/hot/by/hits_week/page/{{page}}/\n月榜::/label/hot/by/hits_month/page/{{page}}/\n国产 🎞::/t/1-{{page}}/\n自拍::/t/5-{{page}}/\n主播大秀::/t/6-{{page}}/\n主播诱惑::/t/36-{{page}}/\n探花::/t/7-{{page}}/\n偷拍::/t/8-{{page}}/\n乱伦::/t/8-{{page}}/\n吃瓜::/t/10-{{page}}/\n抖阴::/t/11-{{page}}/\nAV::/t/12-{{page}}/\n福利姬::/t/20-{{page}}/\n侵犯::/t/37-{{page}}/\n日韩 🎞::/t/2-{{page}}/\n日韩自拍::/t/13-{{page}}/\n日本无码::/t/14-{{page}}/\n字幕::/t/15-{{page}}/\n解说::/t/17-{{page}}/\n换脸::/t/18-{{page}}/\n欧美 🎞::/t/3-{{page}}/\n自拍::/t/21-{{page}}/\n字幕::/t/22-{{page}}/\n伦理 🎞::/t/4-{{page}}/\n三级::/t/29-{{page}}/\n日韩::/t/30-{{page}}/\n动漫 🎞::/t/16-{{page}}/\n剧集::/t/26-{{page}}/\n3D::/t/27-{{page}}/\n次元::/t/28-{{page}}/\n另类 🎞::/t/39-{{page}}/\n同性恋::/t/38-{{page}}/\n变性::/t/40-{{page}}/\n重口味::/t/23-{{page}}/",
    "sourceComment": "<声明>\n//2025.8.10 作者：夜明空\n//源社区：https://taoba.cf\n//仅供个人学习使用，严禁分享、倒卖及任何违法行为！使用者自行承担风险与责任\n</声明>\n\n//网址更新频繁，有需要请到发布页自行更新\n//发布页：\nhttps://18j.18hu.link/mdce\n18j.vip\n18zy.vip\n51zy.vip",
    "sourceGroup": "视频",
    "sourceIcon": "https://18zc.life/18link/18j/images/favicon.ico",
    "sourceName": "18J",
    "sourceUrl": "https://18zc.life/cn/label/sort"
  },
  {
    "articleStyle": 0,
    "coverDecodeJs": "java.createSymmetricCrypto(\"AES/CBC/NoPadding\",\"f5d965df75336270\",\"97b60394abc2fbe1\").decrypt(result)",
    "customOrder": 4727,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\"User-Agent\":\"Mozilla/5.0 (Linux; U; Android 13; zh-Hans-CN; PFJM10 Build/TP1A.220905.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/135.0.4896.58 Quark/6.13.6.581 Mobile Safari/537.36\",\n\"Accept-Language\":\"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\"}",
    "lastUpdateTime": 1774283231132,
    "loadWithBaseUrl": true,
    "ruleArticles": "#body>.container>.row>div[role=\"main\"]>article:not(:has(meta[content=\"广告\"]))>a",
    "ruleContent": "",
    "ruleImage": "@js:\nvar text = java.getString('script@html');\nvar match = text.match(/loadBannerDirect\\('([^']+)'/);\nvar img = match ? match[1] : '';\nimg;",
    "ruleLink": "href",
    "ruleNextPage": "text.下一页@href",
    "rulePubDate": "{{@@.wraps@text}}{{@@.post-card-info span@text##\\n}}",
    "ruleTitle": "h2@text",
    "singleUrl": false,
    "sortUrl": "搜索::/search/{{source.getVariable()}}/{{page}}/\n\t\n\t首页::/page/{{page}}/\n每日大赛::/category/mrds/{{page}}/\n主题大赛::/category/ztds/{{page}}/\n热搜吃瓜::/category/rstt/{{page}}/\n校园学生::/category/xazd/{{page}}/\n必撸大赛::/category/blyp/{{page}}/\n反差泄密::/category/fctg/{{page}}/\n网红黑料::/category/mhds/{{page}}/\n猎奇重口::/category/lqdp/{{page}}/\nAV看片::/category/jdsj/{{page}}/\n明星大赛::/category/mxwh/{{page}}/\n动漫之家::/category/smdh/{{page}}/\n影视国漫::/category/dypd/{{page}}/\ncos写真::/category/mtds/{{page}}/\n声控ASMR::/category/ysds/{{page}}/\n寸止挑战::/category/czds/{{page}}/\n混剪PMV::/category/hjds/{{page}}/\n原创投稿::/category/tgds/{{page}}/\n欧美精品::/category/omjp/{{page}}/\n全网参赛::/category/qwcs/{{page}}/",
    "sourceComment": "发布页: https://www.njttvylz.cc\n最新网址: https://mrds72.com\n永久地址: https://mrds.com\n备用网址: https://mrdsx5.com\n备用线路1: big.ktgchwz.xyz\n备用线路2: adjust.ktgchwz.xyz\n备用线路3: borrow.ktgchwz.xyz\n备用线路4: black.ktgchwz.xyz\n获取地址: mrds.club@gmail.com",
    "sourceGroup": "视频",
    "sourceIcon": "https://bike-egg-cup.img12345.com/ico/heiseicon.png",
    "sourceName": "大赛",
    "sourceUrl": "https://anger.caylrfbb.cc/",
    "style": ""
  },
  {
    "articleStyle": 0,
    "customOrder": 4728,
    "enableJs": true,
    "enabled": false,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "每日大赛",
    "sourceUrl": "https://www.njttvylz.cc"
  },
  {
    "articleStyle": 3,
    "customOrder": 4729,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n\t\"User-Agent\": \"Mozilla/5.0 (Linux; Android 9) Mobile Safari/537.36\",\"referer\": \"{{baseUrl}}\"\n\t}",
    "jsLib": "let search = \"https://dns.jingluo.love/2025/68a878e00d302.jpg\";",
    "lastUpdateTime": 1770433530465,
    "loadWithBaseUrl": true,
    "ruleArticles": ".pornkvideos",
    "ruleContent": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<title>内容提取</title>\n<!-- v2025.05.10 -->\n\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<script src=\"https://code.jquery.com/jquery-3.6.0.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css\" />\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js\"></script>\n<style>\n    body { font-family: Arial, sans-serif; font-size: 16px; }\n    #title, #page, #loading-status { margin: 0 auto; font-size: 20px; text-align: center; }\n    #description, #urls, #video-url, #video-sources, #messages { width: 100%; max-width: 800px; margin: 1.5px auto; font-size: 14px; text-align: left; word-wrap: break-word; white-space: pre-wrap; }\n    #text, #text :not(img), #text img + * { text-indent: 2em; width: 100%; font-size: 16px; line-height: 1.5em; margin-top: 0; margin-bottom: 0; word-wrap: break-word; white-space: pre-wrap; }\n    img, #text img { width: 100%; height: auto; display: block; margin-bottom: 1.5px; }\n    .flex-container { display: flex; justify-content: center; align-items: center; gap: 10px; margin: 1.5px 0; font-size: 14px; }\n    button, select { flex: 1 1 31%; padding: 3px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; cursor: pointer; background-color: #f9f9f9; transition: background-color 0.3s ease; margin: 1.5px; min-width: 0; font-size: 14px; }\n    #url-select, #video-source-select { flex: 1 1 100%; margin-left: 0; margin-right: 0; text-align: center; }\n    #video-element { width: 100%; height: auto; }\n    textarea { width: 100%; height: auto; min-height: 100px; box-sizing: border-box; resize: vertical; }\n    .error, .warn { color: red; }\n</style>\n</head>\n<body>\n    <h3 id=\"title\">{{@@title@text||h1.0@text||h2.0@text||.title.0@text}}</h3>\n    <p id=\"description\">{{@@.info.0@html||.jianjie@html}}</p>\n    <p id=\"page\" style=\"display:none;\">共<span id=\"total-pages\">1</span>页</p>\n    <p id=\"loading-status\" style=\"display:none;\"></p>\n\n    <div class=\"flex-container\" id=\"loading-buttons\" style=\"display:none;\">\n        <button id=\"prev-page-btn\">上一页</button>\n        <button id=\"next-page-btn\">下一页</button>\n        <button id=\"auto-load-btn\">自&nbsp;&nbsp;动</button>\n    </div>\n    \n    <div class=\"flex-container\">\n        <select id=\"url-select\" style=\"display:none;\"></select>\n    </div>\n    \n    <div class=\"flex-container\">\n        <button id=\"toggle-urls-btn\">显/隐网址</button>\n        <button id=\"toggle-messages-btn\">显/隐信息</button>\n        <button id=\"toggle-debug-btn\">显/隐调试</button>\n    </div>\n    <div id=\"urls\"></div>\n    <div id=\"messages\"></div>\n    <div id=\"debug-info\"></div>\n    <div id=\"video-url\"></div>\n    <div id=\"video-container\" style=\"display: none;\">\n        <video id=\"video-element\" controls preload=\"auto\" width=\"640\" height=\"264\">\n            <source id=\"video-source\" src=\"\" type=\"\">您的浏览器不支持 video 标签。\n        </video>\n    </div>\n    <div class=\"flex-container\" id=\"video-source-container\" style=\"display: none;\">\n        <select id=\"video-source-select\" onchange=\"updateVideoSource()\"></select>\n    </div>\n    <div id=\"images\"></div>\n    <div id=\"text\"></div>\n\n    <script>\n        // 配置对象，包含各种选择器、延迟时间等配置项\n        const config = {    \n            videoSelector: 'body', // 视频选择器\n            imgSelector: '.gridlane-box-inside img,.photos figure img,.content p img', // 图片选择器\n            textSelector: '#content', // 文本选择器\n            debugSelector: '#content, .page, .pager, .content, script', // 调试信息选择器\n            swapImageAttributes: false, // 是否交换图片属性\n            delayTime: 1500, // 延迟提取时间\n            retryDelayTime: 1500, // 重试加载延迟时间\n            maxLoadAttempts: 3, // 最大加载次数\n            autoLoading: false, // true自动模式，false单页模式\n            debugOnce: 0, // 只在特定索引输出一次调试信息\n            totalPagesText: '{{@@.page.0@a.-2@textNodes}}', // 总页码\n            urlSuffixToRemove: /\\.html$/, // 移除url后缀\n            pageUrlText: '{urlPrefix}_{i}.html', // 拼接URL模板        \n            ListMode: true, // true网址列表模式，false网址拼接模式    \n            initialUrls: `{{@@#sort-item-5.0@a@href}}`, // 网址\n            initialUrlsName: `{{@@#sort-item-5.0@a@span@text}}`, // 网址名称\n            sourceurl: '', // 来源URL前缀\n        };\n\n        let videoSources = []; // 存储视频源数组\n        let loadAttempts = {}; // 记录每个URL的加载尝试次数\n        let urls = []; // 存储所有页面的URL\n        let imageBox;\n        let textBox;\n        let currentPageIndex = 0; // 当前页面索引\n        let canLoadNextPage = true; // 控制是否可以加载下一页\n        let autoLoadInProgress = false; // 自动加载状态\n\n        // 构建URL列表\n        function buildUrls(totalPages, baseUrl) {\n            let initialUrlsArray = config.initialUrls.trim().split('\\n').filter(url => url.trim() !== '');\n            let initialUrlsNameArray = config.initialUrlsName.trim().split('\\n').filter(name => name.trim() !== '');\n\n            if (config.ListMode && initialUrlsArray.length > 0) {\n                if (initialUrlsArray.length !== initialUrlsNameArray.length) {\n                    $('#messages').append(`<span class=\"warn\">警告：initialUrls 和 initialUrlsName 的长度不匹配。</span><br>`);\n                }\n\n                urls = initialUrlsArray.map(url => {\n                    if (config.sourceurl && url.startsWith('/') && !/^https?:\\/\\//i.test(url)) {\n                        return config.sourceurl.replace(/\\/$/, '') + url;\n                    } else {\n                        return url;\n                    }\n                });\n\n                urls.forEach((url, index) => {\n                    const name = initialUrlsNameArray[index] || `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            } else {\n                if (totalPages === 1) {\n                    urls.push(baseUrl);\n                } else {\n                    urls.push(baseUrl);\n                    for (let i = 2; i <= totalPages; i++) {\n                        urls.push(config.pageUrlText.replace('{urlPrefix}', baseUrl.replace(config.urlSuffixToRemove, '').replace(/\\/$/, '')).replace('{i}', i));\n                    }\n                }\n\n                urls.forEach((url, index) => {\n                    const name = `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            }\n\n            $('#total-pages').text(urls.length);\n            toggleNavigationButtons();\n            toggleTotalPagesDisplay();\n        }\n\n        // 规范化URL\n        function normalizeUrl(url) {\n            if (typeof url !== 'string' || !url.trim()) {\n                return '';\n            }\n            const match = url.match(/['\"](.*?)['\"]/);\n            if (match && match[1]) {\n                url = match[1];\n            }\n\n            function processUrl(str) {\n                str = str.trim();\n                str = str.replace(/\\\\u[\\dA-F]{4}/gi, match => String.fromCharCode(parseInt(match.replace(/\\\\u/g, ''), 16)));\n                str = decodeURIComponent(str);\n                str = str.replace(/^http:\\/([^/])/, 'http://$1');\n                str = str.replace(/^https:\\/([^/])/, 'https://$1');\n                return str;\n            }\n            return processUrl(url);\n        }\n\n        // 清空容器内容\n        function clearContainers() {\n            $('#messages').empty();\n            $('#images').empty();\n            $('#text').empty();\n        }\n\n        // 更新图像源\n        function updateImageSrc(elements, shouldSwap) {\n            elements.each(function () {\n                const $this = $(this);\n                const attrsToUpdate = {};\n                if (shouldSwap) {\n                    ['data-original', 'data-src', 'data-url'].forEach(attr => {\n                        if ($this.attr(attr)) {\n                            attrsToUpdate['src'] = $this.attr(attr);\n                        }\n                    });\n                }\n                $this.attr(attrsToUpdate);\n            });\n            return elements;\n        }\n\n        // 切换导航按钮显示状态\n        function toggleNavigationButtons() {\n            if ($('#url-select option').length > 1 && !config.autoLoading) {\n                $('#loading-buttons').show();\n                $('#url-select').show();\n            } else {\n                $('#loading-buttons').hide();\n                $('#url-select').hide();\n            }\n        }\n\n        // 显示加载状态\n        function showLoadingStatus(pageNumber) {\n            const selectedOption = $('#url-select option:selected').text();\n            $('#loading-status').text(`正在加载：${selectedOption}`).show();\n        }\n\n        // 隐藏加载状态\n        function hideLoadingStatus() {\n            $('#loading-status').hide();\n        }\n\n        // 加载指定索引的内容\n        function loadContent(index) {\n            if (index < 0 || index >= urls.length || !canLoadNextPage) return;\n            canLoadNextPage = false;\n            currentPageIndex = index;\n            $('#url-select').val(index);\n            $('#messages').append(`<div>当前地址: <span class=\"warn\">${urls[index]}</span></div>`);\n            if (autoLoadInProgress) {\n                showLoadingStatus(index + 1);\n            }\n            $.ajax({\n                url: urls[index],\n                type: 'GET',\n                success: function (data) {\n                    try {\n                    const $data = $(data);\n                    let updatedHtmlContent = data.replace(/(['\"])(\\/\\/)(?!\\/)/g, '$1https://')\n                        .replace(/src=\"upload/gi, 'src=\"/upload')\n                        .replace(/style=[\"'][^'\"]+[\"']/gi, '')\n                        .replace(/\\\\\\//g, '/');\n                    const parser = new DOMParser();\n                    const doc = parser.parseFromString(updatedHtmlContent, \"text/html\");\n\n                    if (config.debugOnce === index) {\n                        const debugElements = $(doc).find(config.debugSelector);\n                        if (debugElements.length > 0) {\n                            const debugContents = $('<pre>').html(debugElements.clone().wrapAll('<div/>').parent().html()).html();\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">${debugContents}</textarea></span>`);\n                        } else {\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">调试信息未提取到内容，请检查选择器！</textarea></span>`);\n                        }\n                    }\n                    // 方法1：提取视频\n                    const videoSources1 = [];\n                    const videoContents = $(doc).find(config.videoSelector);\n                    const videoTags = $(videoContents).find('video, source');\n                    videoTags.each(function() {\n                        const videosrc = $(this).attr('src') || \n                                     $(this).attr('data-src') || \n                                     $(this).attr('data-original') || '';\n                        \n                        if (videosrc) {\n                            videoSources1.push(videosrc);\n                        }\n                    });\n                    //反馈\n                    if (videoSources1.length > 0) {\n                        $('#messages').append(`<span>方法1，找到 ${videoSources1.length} 个视频。</span><br>`);\n                    }\n\n                    // 方法2：正则提取视频\n                    const regex = /['\"]https?[^'<>\"]+(m3u8|mp4|webm|ogg|flv|mp3|m4a|wav|ape|flac)([^'<>\"]+)?['\"]/gi;\n                    const matches = data.match(regex);\n                    const videoSources2 = [];\n\n                    if (matches) {\n                        const uniqueMatches = [...new Set(matches)];\n                    \n                        uniqueMatches.forEach(match => {\n                            const normalizedSrc = normalizeUrl(match.replace(/['\"]/g, ''));\n                            videoSources2.push(normalizedSrc);\n                        });\n                    }\n                    //反馈\n                    if (videoSources2.length > 0) {\n                        $('#messages').append(`<span>方法2，找到 ${videoSources2.length} 个视频。</span><br>`);\n                    }\n\n                    // 合并两种方法的结果\n                    videoSources = [...videoSources1, ...videoSources2];\n\n                    // 去重并标准化 URL\n                    const imageExtensions = /\\.(jpg|jpeg|png|gif|bmp|svg)$/i;\n\n                    videoSources = videoSources\n                                  .map(src => normalizeUrl(src.replace(/\\\\+/g, '')))\n                                  .filter(src => src) // 过滤空值\n                                  .filter(src => !imageExtensions.test(src)); // 移除图片地址\n                        \n                    videoSources = [...new Set(videoSources)];// 去重\n\n                    // 显示最终结果\n                    $('#messages').append(`<span>总共找到 ${videoSources.length} 个视频。</span><br>`);\n\n                    if (videoSources.length > 0) {\n                        $('#messages').append(`<span>成功提取到视频，找到 ${videoSources.length} 个视频。</span><br>`);\n                        videoSources.forEach((src, idx) => {\n                            $('#messages').append(`<div>视频地址:<span class=\"warn\"> ${src}</span><br></div>`);\n                            $('#video-source-select').append(`<option value=\"${idx}\">视频源 ${idx + 1}</option>`);\n                        });\n                    \n                        if (videoSources.length == 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').hide();\n                            updateVideoSource();\n                        } else if (videoSources.length > 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').show();\n                            updateVideoSource();\n                        } else {\n                            $('#video-container').hide();\n                            $('#video-url').hide();\n                            $('#video-source-container').hide();\n                        }\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未找到视频源。</span><br>`);\n                        $('#video-container').hide();\n                        $('#video-url').hide();\n                        $('#video-source-container').hide();\n                    }\n\n                    //提取图片\n                    const $imgContents = $(doc).find(config.imgSelector);\n                    const shouldSwap = config.swapImageAttributes;\n                    const newContents = updateImageSrc($imgContents.clone(), shouldSwap);\n                    $('#images').append(newContents).show();\n                    if (newContents.length > 0) {\n                        $('#messages').append(`<span>成功提取图片，共 ${newContents.length} 张。</span><br>`);\n                        newContents.each(function () {\n                            const imgSrc = $(this).attr('src') || $(this).attr('data-original') || $(this).attr('data-src') || $(this).attr('data-url');\n                            $('#messages').append(`<div>地址:<span class=\"warn\"> ${imgSrc}</span><br></div>`);\n                        });\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图片。</span><br>`);\n                    }\n\n                    //提取图片和文本\n                    const textContents = $(doc).find(config.textSelector).map(function () {\n                        const $currentContents = $(this);\n                        $currentContents.find('img + br, script, video, source, iframe').remove();\n                        $currentContents.html($currentContents.html().replace(/>\\s+/gi, '>').replace(/<\\/?br\\s*([^>]*)\\s*\\/?>/gi, '\\n').replace(/\\n+/g, '\\n'));\n                        return $currentContents.html();\n                    }).get().join('');\n                    if (textContents.trim()) {\n                        $('#text').append(`<span>${textContents}</span><br>`).show();\n                        $('#messages').append(`<span>成功提取图文。</span><br>`);\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图文。</span><br>`);\n                    }\n\n                    if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                        setTimeout(() => { \n                            canLoadNextPage = true;\n                            loadContent(currentPageIndex + 1); \n                        }, config.delayTime);\n                    } else {\n                        canLoadNextPage = true;\n                        if (autoLoadInProgress) {\n                            hideLoadingStatus();\n                        }\n                    }\n                } catch (parseError) {\n                    $('#messages').append(`<span class=\"error\">解析页面内容时发生错误: ${parseError.message}</span><br>`);\n                    handleLoadFailure(urls, index);\n                } finally {\n                    if (imageBox) imageBox.viewer.update();\n                    if (textBox) textBox.viewer.update();\n                }\n            },\n            error: function (jqXHR, textStatus, errorThrown) {\n                let errorMessage = `内容加载失败: ${urls[index]}`;\n                switch (textStatus) {\n                    case 'timeout':\n                        errorMessage += ', 请求超时';\n                        break;\n                    case 'abort':\n                        errorMessage += ', 请求被取消';\n                        break;\n                    case 'parsererror':\n                        errorMessage += ', 解析响应出错';\n                        break;\n                    default:\n                        errorMessage += `, 状态码: ${jqXHR.status}, 错误信息: ${errorThrown}`;\n                        break;\n                }\n                $('#messages').append(`<span class=\"error\">${errorMessage}</span><br>`);\n                handleLoadFailure(urls, index);\n                }\n            });\n        }\n\n        // 处理加载失败的情况\n        function handleLoadFailure(urls, index) {\n            if (!loadAttempts[urls[index]]) {\n                loadAttempts[urls[index]] = 1;\n            } else {\n                loadAttempts[urls[index]]++;\n            }\n            if (loadAttempts[urls[index]] <= config.maxLoadAttempts) {\n                const retryMessage = `第${index + 1}页加载失败，正在进行第${loadAttempts[urls[index]]}次加载！`;\n                $('#messages').append(`<span class=\"error\">${retryMessage}</span><br>`);\n                setTimeout(() => { \n                    canLoadNextPage = true;\n                    loadContent(index); \n                }, config.retryDelayTime);\n            } else {\n                const finalErrorMessage = `第${index + 1}页加载失败，已达到最大尝试次数(${config.maxLoadAttempts})！`;\n                $('#messages').append(`<span class=\"error\">${finalErrorMessage}</span><br>`);\n                if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                    setTimeout(() => { \n                        canLoadNextPage = true;\n                        loadContent(currentPageIndex + 1); \n                    }, config.delayTime);\n                } else {\n                    canLoadNextPage = true;\n                    if (autoLoadInProgress) {\n                        hideLoadingStatus();\n                    }\n                }\n            }\n        }\n\n        // 更新视频源\n        function updateVideoSource() {\n            const selectedIndex = parseInt(document.getElementById('video-source-select').value);\n            if (isNaN(selectedIndex) || !videoSources[selectedIndex]) {\n                $('#messages').append(`<span class=\"warn\">未找到有效的视频源。</span><br>`);\n                console.warn(\"Invalid or undefined video source:\", selectedIndex, videoSources);\n                return;\n            }\n\n            const selectedSource = videoSources[selectedIndex];\n            document.getElementById('video-url').textContent = `视频地址:\\n ${selectedSource}`;\n\n            const videoSourceElement = document.getElementById('video-source');\n            videoSourceElement.src = selectedSource;\n\n            const videoElement = document.getElementById('video-element');\n            videoElement.load();\n\n            $('#messages').append(`<span>更新视频源为: ${selectedSource}</span><br>`);\n            console.log(\"Updated video source to:\", selectedSource);\n        }\n\n        // 切换总页数显示状态\n        function toggleTotalPagesDisplay() {\n            if (urls.length > 1) {\n                $('#page').show();\n            } else {\n                $('#page').hide();\n            }\n        }\n\n        // 页面加载完成后执行的主要逻辑\n        $(document).ready(function () {\n            imageBox = document.getElementById('images');\n            textBox = document.getElementById('text');\n            if (imageBox && textBox) {\n                new Viewer(imageBox, { title: true, interval: 2000 });\n                new Viewer(textBox, { title: true, interval: 2000 });\n            }\n\n            const totalPagesText = config.totalPagesText;\n            const totalPages = parseInt(totalPagesText, 10) || 1;\n            const baseUrl = '{{baseUrl}}';\n\n            clearContainers();\n            $('#urls, #debug-info textarea, #video-url, #video-source-select').empty();\n            $('#urls, #messages, #debug-info, #video-url, #video-container, #video-source-container, #images, #text').hide();\n\n            buildUrls(totalPages, baseUrl);\n\n            const urlSelect = document.getElementById('url-select');\n            if (urlSelect.options.length > 0) {\n                urlSelect.value = '0'; \n\n                if (config.autoLoading) {\n                    autoLoadInProgress = true;\n                    for (let i = 0; i < urls.length; i++) {\n                        loadContent(i);\n                    }\n                } else {\n                    loadContent(0);\n                }\n            } else {\n                loadContent(0);\n            }\n\n            $('#url-select').change(function () {\n                clearContainers();\n                const selectedIndex = parseInt($(this).val());\n                loadContent(selectedIndex);\n            });\n            $('#prev-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex > 0) {\n                    loadContent(currentPageIndex - 1);\n                }\n            });\n            $('#next-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex < urls.length - 1) {\n                    loadContent(currentPageIndex + 1);\n                }\n            });\n            $('#auto-load-btn').click(function () {\n                autoLoadInProgress = true;\n                showLoadingStatus(1); \n                for (let i = currentPageIndex + 1; i < urls.length; i++) {\n                    loadContent(i);\n                }\n            });\n            $('#toggle-messages-btn').click(function () { $('#messages').toggle(); });\n            $('#toggle-urls-btn').click(function () { $('#urls').toggle(); });\n            $('#toggle-debug-btn').click(function () { $('#debug-info').toggle(); });\n        });\n    </script>\n</body>\n</html>",
    "ruleImage": "img@data-src",
    "ruleLink": "/vodplay/{{@a.0@href##voddetail/(.*).html##$1##}}-1-1.html",
    "ruleNextPage": "text.下页@href",
    "rulePubDate": ".vlength@text",
    "ruleTitle": "a@text",
    "singleUrl": false,
    "sortUrl": "搜索::https://baf7baf7.shewo11.cc/vodsearch/-------------.html?wd={{java.encodeURI(source.getVariable())}}\n\n\n国产色情::/vodtype/12.html\n日本无码::/vodtype/20.html\n自拍偷拍::/vodtype/21.html\n人妻熟女::/vodtype/22.html\n黑人洋屌::/vodtype/23.html\n欧美精品::/vodtype/24.html\n岛国女优::/vodtype/25.html\n萝莉少女::/vodtype/26.html\n国产精品::/vodtype/55.html\n国产直播::/vodtype/56.html\n动漫禁漫::/vodtype/57.html\n黑料吃瓜::/vodtype/58.html\n欧美大屌::/vodtype/60.html\n探花约炮::/vodtype/61.html\n华语精品::/vodtype/63.html\n乱伦精品::/vodtype/64.html\n学生合集::/vodtype/65.html\n卡通动漫::/vodtype/69.html\n乱伦中出::/vodtype/70.html\n传媒原创::/vodtype/71.html\n口爆颜射::/vodtype/72.html\n岛国群交::/vodtype/73.html\n日本有码::/vodtype/74.html\n中文字幕::/vodtype/75.html\n吃瓜爆料::/vodtype/76.html\n角色扮演::/vodtype/77.html\n淫娃自慰::/vodtype/78.html\n日本有码::/vodtype/80.html\n主播网红::/vodtype/81.html\n韩国直播::/vodtype/84.html\n公开漏出::/vodtype/85.html\n日本无码::/vodtype/86.html\n重口调教::/vodtype/88.html\n户外打野::/vodtype/89.html",
    "sourceComment": "shewo1.cc",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "射我里面了",
    "sourceUrl": "https://baf7baf7.shewo11.cc/"
  },
  {
    "articleStyle": 3,
    "customOrder": 4731,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 1773222833605,
    "loadWithBaseUrl": true,
    "ruleArticles": "[class=\"box\"]@a",
    "ruleContent": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<title>内容提取</title>\n<!-- v2025.05.10 -->\n\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<script src=\"https://code.jquery.com/jquery-3.6.0.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css\" />\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js\"></script>\n<style>\n    body { font-family: Arial, sans-serif; font-size: 16px; }\n    #title, #page, #loading-status { margin: 0 auto; font-size: 20px; text-align: center; }\n    #description, #urls, #video-url, #video-sources, #messages { width: 100%; max-width: 800px; margin: 1.5px auto; font-size: 14px; text-align: left; word-wrap: break-word; white-space: pre-wrap; }\n    #text, #text :not(img), #text img + * { text-indent: 2em; width: 100%; font-size: 16px; line-height: 1.5em; margin-top: 0; margin-bottom: 0; word-wrap: break-word; white-space: pre-wrap; }\n    img, #text img { width: 100%; height: auto; display: block; margin-bottom: 1.5px; }\n    .flex-container { display: flex; justify-content: center; align-items: center; gap: 10px; margin: 1.5px 0; font-size: 14px; }\n    button, select { flex: 1 1 31%; padding: 3px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; cursor: pointer; background-color: #f9f9f9; transition: background-color 0.3s ease; margin: 1.5px; min-width: 0; font-size: 14px; }\n    #url-select, #video-source-select { flex: 1 1 100%; margin-left: 0; margin-right: 0; text-align: center; }\n    #video-element { width: 100%; height: auto; }\n    textarea { width: 100%; height: auto; min-height: 100px; box-sizing: border-box; resize: vertical; }\n    .error, .warn { color: red; }\n</style>\n</head>\n<body>\n    <h3 id=\"title\">{{@@title@text||h1.0@text||h2.0@text||.title.0@text}}</h3>\n    <p id=\"description\">{{@@.info.0@html||.jianjie@html}}</p>\n    <p id=\"page\" style=\"display:none;\">共<span id=\"total-pages\">1</span>页</p>\n    <p id=\"loading-status\" style=\"display:none;\"></p>\n\n    <div class=\"flex-container\" id=\"loading-buttons\" style=\"display:none;\">\n        <button id=\"prev-page-btn\">上一页</button>\n        <button id=\"next-page-btn\">下一页</button>\n        <button id=\"auto-load-btn\">自&nbsp;&nbsp;动</button>\n    </div>\n    \n    <div class=\"flex-container\">\n        <select id=\"url-select\" style=\"display:none;\"></select>\n    </div>\n    \n    <div class=\"flex-container\">\n        <button id=\"toggle-urls-btn\">显/隐网址</button>\n        <button id=\"toggle-messages-btn\">显/隐信息</button>\n        <button id=\"toggle-debug-btn\">显/隐调试</button>\n    </div>\n    <div id=\"urls\"></div>\n    <div id=\"messages\"></div>\n    <div id=\"debug-info\"></div>\n    <div id=\"video-url\"></div>\n    <div id=\"video-container\" style=\"display: none;\">\n        <video id=\"video-element\" controls preload=\"auto\" width=\"640\" height=\"264\">\n            <source id=\"video-source\" src=\"\" type=\"\">您的浏览器不支持 video 标签。\n        </video>\n    </div>\n    <div class=\"flex-container\" id=\"video-source-container\" style=\"display: none;\">\n        <select id=\"video-source-select\" onchange=\"updateVideoSource()\"></select>\n    </div>\n    <div id=\"images\"></div>\n    <div id=\"text\"></div>\n\n    <script>\n        // 配置对象，包含各种选择器、延迟时间等配置项\n        const config = {    \n            videoSelector: 'body', // 视频选择器\n            imgSelector: '.gridlane-box-inside img,.photos figure img,.content p img', // 图片选择器\n            textSelector: '#content', // 文本选择器\n            debugSelector: '#content, .page, .pager, .content, script', // 调试信息选择器\n            swapImageAttributes: false, // 是否交换图片属性\n            delayTime: 1500, // 延迟提取时间\n            retryDelayTime: 1500, // 重试加载延迟时间\n            maxLoadAttempts: 3, // 最大加载次数\n            autoLoading: false, // true自动模式，false单页模式\n            debugOnce: 0, // 只在特定索引输出一次调试信息\n            totalPagesText: '{{@@.page.0@a.-2@textNodes}}', // 总页码\n            urlSuffixToRemove: /\\.html$/, // 移除url后缀\n            pageUrlText: '{urlPrefix}_{i}.html', // 拼接URL模板        \n            ListMode: true, // true网址列表模式，false网址拼接模式    \n            initialUrls: `{{@@#sort-item-5.0@a@href}}`, // 网址\n            initialUrlsName: `{{@@#sort-item-5.0@a@span@text}}`, // 网址名称\n            sourceurl: '', // 来源URL前缀\n        };\n\n        let videoSources = []; // 存储视频源数组\n        let loadAttempts = {}; // 记录每个URL的加载尝试次数\n        let urls = []; // 存储所有页面的URL\n        let imageBox;\n        let textBox;\n        let currentPageIndex = 0; // 当前页面索引\n        let canLoadNextPage = true; // 控制是否可以加载下一页\n        let autoLoadInProgress = false; // 自动加载状态\n\n        // 构建URL列表\n        function buildUrls(totalPages, baseUrl) {\n            let initialUrlsArray = config.initialUrls.trim().split('\\n').filter(url => url.trim() !== '');\n            let initialUrlsNameArray = config.initialUrlsName.trim().split('\\n').filter(name => name.trim() !== '');\n\n            if (config.ListMode && initialUrlsArray.length > 0) {\n                if (initialUrlsArray.length !== initialUrlsNameArray.length) {\n                    $('#messages').append(`<span class=\"warn\">警告：initialUrls 和 initialUrlsName 的长度不匹配。</span><br>`);\n                }\n\n                urls = initialUrlsArray.map(url => {\n                    if (config.sourceurl && url.startsWith('/') && !/^https?:\\/\\//i.test(url)) {\n                        return config.sourceurl.replace(/\\/$/, '') + url;\n                    } else {\n                        return url;\n                    }\n                });\n\n                urls.forEach((url, index) => {\n                    const name = initialUrlsNameArray[index] || `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            } else {\n                if (totalPages === 1) {\n                    urls.push(baseUrl);\n                } else {\n                    urls.push(baseUrl);\n                    for (let i = 2; i <= totalPages; i++) {\n                        urls.push(config.pageUrlText.replace('{urlPrefix}', baseUrl.replace(config.urlSuffixToRemove, '').replace(/\\/$/, '')).replace('{i}', i));\n                    }\n                }\n\n                urls.forEach((url, index) => {\n                    const name = `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            }\n\n            $('#total-pages').text(urls.length);\n            toggleNavigationButtons();\n            toggleTotalPagesDisplay();\n        }\n\n        // 规范化URL\n        function normalizeUrl(url) {\n            if (typeof url !== 'string' || !url.trim()) {\n                return '';\n            }\n            const match = url.match(/['\"](.*?)['\"]/);\n            if (match && match[1]) {\n                url = match[1];\n            }\n\n            function processUrl(str) {\n                str = str.trim();\n                str = str.replace(/\\\\u[\\dA-F]{4}/gi, match => String.fromCharCode(parseInt(match.replace(/\\\\u/g, ''), 16)));\n                str = decodeURIComponent(str);\n                str = str.replace(/^http:\\/([^/])/, 'http://$1');\n                str = str.replace(/^https:\\/([^/])/, 'https://$1');\n                return str;\n            }\n            return processUrl(url);\n        }\n\n        // 清空容器内容\n        function clearContainers() {\n            $('#messages').empty();\n            $('#images').empty();\n            $('#text').empty();\n        }\n\n        // 更新图像源\n        function updateImageSrc(elements, shouldSwap) {\n            elements.each(function () {\n                const $this = $(this);\n                const attrsToUpdate = {};\n                if (shouldSwap) {\n                    ['data-original', 'data-src', 'data-url'].forEach(attr => {\n                        if ($this.attr(attr)) {\n                            attrsToUpdate['src'] = $this.attr(attr);\n                        }\n                    });\n                }\n                $this.attr(attrsToUpdate);\n            });\n            return elements;\n        }\n\n        // 切换导航按钮显示状态\n        function toggleNavigationButtons() {\n            if ($('#url-select option').length > 1 && !config.autoLoading) {\n                $('#loading-buttons').show();\n                $('#url-select').show();\n            } else {\n                $('#loading-buttons').hide();\n                $('#url-select').hide();\n            }\n        }\n\n        // 显示加载状态\n        function showLoadingStatus(pageNumber) {\n            const selectedOption = $('#url-select option:selected').text();\n            $('#loading-status').text(`正在加载：${selectedOption}`).show();\n        }\n\n        // 隐藏加载状态\n        function hideLoadingStatus() {\n            $('#loading-status').hide();\n        }\n\n        // 加载指定索引的内容\n        function loadContent(index) {\n            if (index < 0 || index >= urls.length || !canLoadNextPage) return;\n            canLoadNextPage = false;\n            currentPageIndex = index;\n            $('#url-select').val(index);\n            $('#messages').append(`<div>当前地址: <span class=\"warn\">${urls[index]}</span></div>`);\n            if (autoLoadInProgress) {\n                showLoadingStatus(index + 1);\n            }\n            $.ajax({\n                url: urls[index],\n                type: 'GET',\n                success: function (data) {\n                    try {\n                    const $data = $(data);\n                    let updatedHtmlContent = data.replace(/(['\"])(\\/\\/)(?!\\/)/g, '$1https://')\n                        .replace(/src=\"upload/gi, 'src=\"/upload')\n                        .replace(/style=[\"'][^'\"]+[\"']/gi, '')\n                        .replace(/\\\\\\//g, '/');\n                    const parser = new DOMParser();\n                    const doc = parser.parseFromString(updatedHtmlContent, \"text/html\");\n\n                    if (config.debugOnce === index) {\n                        const debugElements = $(doc).find(config.debugSelector);\n                        if (debugElements.length > 0) {\n                            const debugContents = $('<pre>').html(debugElements.clone().wrapAll('<div/>').parent().html()).html();\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">${debugContents}</textarea></span>`);\n                        } else {\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">调试信息未提取到内容，请检查选择器！</textarea></span>`);\n                        }\n                    }\n                    // 方法1：提取视频\n                    const videoSources1 = [];\n                    const videoContents = $(doc).find(config.videoSelector);\n                    const videoTags = $(videoContents).find('video, source');\n                    videoTags.each(function() {\n                        const videosrc = $(this).attr('src') || \n                                     $(this).attr('data-src') || \n                                     $(this).attr('data-original') || '';\n                        \n                        if (videosrc) {\n                            videoSources1.push(videosrc);\n                        }\n                    });\n                    //反馈\n                    if (videoSources1.length > 0) {\n                        $('#messages').append(`<span>方法1，找到 ${videoSources1.length} 个视频。</span><br>`);\n                    }\n\n                    // 方法2：正则提取视频\n                    const regex = /['\"]https?[^'<>\"]+(m3u8|mp4|webm|ogg|flv|mp3|m4a|wav|ape|flac)([^'<>\"]+)?['\"]/gi;\n                    const matches = data.match(regex);\n                    const videoSources2 = [];\n\n                    if (matches) {\n                        const uniqueMatches = [...new Set(matches)];\n                    \n                        uniqueMatches.forEach(match => {\n                            const normalizedSrc = normalizeUrl(match.replace(/['\"]/g, ''));\n                            videoSources2.push(normalizedSrc);\n                        });\n                    }\n                    //反馈\n                    if (videoSources2.length > 0) {\n                        $('#messages').append(`<span>方法2，找到 ${videoSources2.length} 个视频。</span><br>`);\n                    }\n\n                    // 合并两种方法的结果\n                    videoSources = [...videoSources1, ...videoSources2];\n\n                    // 去重并标准化 URL\n                    const imageExtensions = /\\.(jpg|jpeg|png|gif|bmp|svg)$/i;\n\n                    videoSources = videoSources\n                                  .map(src => normalizeUrl(src.replace(/\\\\+/g, '')))\n                                  .filter(src => src) // 过滤空值\n                                  .filter(src => !imageExtensions.test(src)); // 移除图片地址\n                        \n                    videoSources = [...new Set(videoSources)];// 去重\n\n                    // 显示最终结果\n                    $('#messages').append(`<span>总共找到 ${videoSources.length} 个视频。</span><br>`);\n\n                    if (videoSources.length > 0) {\n                        $('#messages').append(`<span>成功提取到视频，找到 ${videoSources.length} 个视频。</span><br>`);\n                        videoSources.forEach((src, idx) => {\n                            $('#messages').append(`<div>视频地址:<span class=\"warn\"> ${src}</span><br></div>`);\n                            $('#video-source-select').append(`<option value=\"${idx}\">视频源 ${idx + 1}</option>`);\n                        });\n                    \n                        if (videoSources.length == 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').hide();\n                            updateVideoSource();\n                        } else if (videoSources.length > 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').show();\n                            updateVideoSource();\n                        } else {\n                            $('#video-container').hide();\n                            $('#video-url').hide();\n                            $('#video-source-container').hide();\n                        }\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未找到视频源。</span><br>`);\n                        $('#video-container').hide();\n                        $('#video-url').hide();\n                        $('#video-source-container').hide();\n                    }\n\n                    //提取图片\n                    const $imgContents = $(doc).find(config.imgSelector);\n                    const shouldSwap = config.swapImageAttributes;\n                    const newContents = updateImageSrc($imgContents.clone(), shouldSwap);\n                    $('#images').append(newContents).show();\n                    if (newContents.length > 0) {\n                        $('#messages').append(`<span>成功提取图片，共 ${newContents.length} 张。</span><br>`);\n                        newContents.each(function () {\n                            const imgSrc = $(this).attr('src') || $(this).attr('data-original') || $(this).attr('data-src') || $(this).attr('data-url');\n                            $('#messages').append(`<div>地址:<span class=\"warn\"> ${imgSrc}</span><br></div>`);\n                        });\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图片。</span><br>`);\n                    }\n\n                    //提取图片和文本\n                    const textContents = $(doc).find(config.textSelector).map(function () {\n                        const $currentContents = $(this);\n                        $currentContents.find('img + br, script, video, source, iframe').remove();\n                        $currentContents.html($currentContents.html().replace(/>\\s+/gi, '>').replace(/<\\/?br\\s*([^>]*)\\s*\\/?>/gi, '\\n').replace(/\\n+/g, '\\n'));\n                        return $currentContents.html();\n                    }).get().join('');\n                    if (textContents.trim()) {\n                        $('#text').append(`<span>${textContents}</span><br>`).show();\n                        $('#messages').append(`<span>成功提取图文。</span><br>`);\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图文。</span><br>`);\n                    }\n\n                    if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                        setTimeout(() => { \n                            canLoadNextPage = true;\n                            loadContent(currentPageIndex + 1); \n                        }, config.delayTime);\n                    } else {\n                        canLoadNextPage = true;\n                        if (autoLoadInProgress) {\n                            hideLoadingStatus();\n                        }\n                    }\n                } catch (parseError) {\n                    $('#messages').append(`<span class=\"error\">解析页面内容时发生错误: ${parseError.message}</span><br>`);\n                    handleLoadFailure(urls, index);\n                } finally {\n                    if (imageBox) imageBox.viewer.update();\n                    if (textBox) textBox.viewer.update();\n                }\n            },\n            error: function (jqXHR, textStatus, errorThrown) {\n                let errorMessage = `内容加载失败: ${urls[index]}`;\n                switch (textStatus) {\n                    case 'timeout':\n                        errorMessage += ', 请求超时';\n                        break;\n                    case 'abort':\n                        errorMessage += ', 请求被取消';\n                        break;\n                    case 'parsererror':\n                        errorMessage += ', 解析响应出错';\n                        break;\n                    default:\n                        errorMessage += `, 状态码: ${jqXHR.status}, 错误信息: ${errorThrown}`;\n                        break;\n                }\n                $('#messages').append(`<span class=\"error\">${errorMessage}</span><br>`);\n                handleLoadFailure(urls, index);\n                }\n            });\n        }\n\n        // 处理加载失败的情况\n        function handleLoadFailure(urls, index) {\n            if (!loadAttempts[urls[index]]) {\n                loadAttempts[urls[index]] = 1;\n            } else {\n                loadAttempts[urls[index]]++;\n            }\n            if (loadAttempts[urls[index]] <= config.maxLoadAttempts) {\n                const retryMessage = `第${index + 1}页加载失败，正在进行第${loadAttempts[urls[index]]}次加载！`;\n                $('#messages').append(`<span class=\"error\">${retryMessage}</span><br>`);\n                setTimeout(() => { \n                    canLoadNextPage = true;\n                    loadContent(index); \n                }, config.retryDelayTime);\n            } else {\n                const finalErrorMessage = `第${index + 1}页加载失败，已达到最大尝试次数(${config.maxLoadAttempts})！`;\n                $('#messages').append(`<span class=\"error\">${finalErrorMessage}</span><br>`);\n                if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                    setTimeout(() => { \n                        canLoadNextPage = true;\n                        loadContent(currentPageIndex + 1); \n                    }, config.delayTime);\n                } else {\n                    canLoadNextPage = true;\n                    if (autoLoadInProgress) {\n                        hideLoadingStatus();\n                    }\n                }\n            }\n        }\n\n        // 更新视频源\n        function updateVideoSource() {\n            const selectedIndex = parseInt(document.getElementById('video-source-select').value);\n            if (isNaN(selectedIndex) || !videoSources[selectedIndex]) {\n                $('#messages').append(`<span class=\"warn\">未找到有效的视频源。</span><br>`);\n                console.warn(\"Invalid or undefined video source:\", selectedIndex, videoSources);\n                return;\n            }\n\n            const selectedSource = videoSources[selectedIndex];\n            document.getElementById('video-url').textContent = `视频地址:\\n ${selectedSource}`;\n\n            const videoSourceElement = document.getElementById('video-source');\n            videoSourceElement.src = selectedSource;\n\n            const videoElement = document.getElementById('video-element');\n            videoElement.load();\n\n            $('#messages').append(`<span>更新视频源为: ${selectedSource}</span><br>`);\n            console.log(\"Updated video source to:\", selectedSource);\n        }\n\n        // 切换总页数显示状态\n        function toggleTotalPagesDisplay() {\n            if (urls.length > 1) {\n                $('#page').show();\n            } else {\n                $('#page').hide();\n            }\n        }\n\n        // 页面加载完成后执行的主要逻辑\n        $(document).ready(function () {\n            imageBox = document.getElementById('images');\n            textBox = document.getElementById('text');\n            if (imageBox && textBox) {\n                new Viewer(imageBox, { title: true, interval: 2000 });\n                new Viewer(textBox, { title: true, interval: 2000 });\n            }\n\n            const totalPagesText = config.totalPagesText;\n            const totalPages = parseInt(totalPagesText, 10) || 1;\n            const baseUrl = '{{baseUrl}}';\n\n            clearContainers();\n            $('#urls, #debug-info textarea, #video-url, #video-source-select').empty();\n            $('#urls, #messages, #debug-info, #video-url, #video-container, #video-source-container, #images, #text').hide();\n\n            buildUrls(totalPages, baseUrl);\n\n            const urlSelect = document.getElementById('url-select');\n            if (urlSelect.options.length > 0) {\n                urlSelect.value = '0'; \n\n                if (config.autoLoading) {\n                    autoLoadInProgress = true;\n                    for (let i = 0; i < urls.length; i++) {\n                        loadContent(i);\n                    }\n                } else {\n                    loadContent(0);\n                }\n            } else {\n                loadContent(0);\n            }\n\n            $('#url-select').change(function () {\n                clearContainers();\n                const selectedIndex = parseInt($(this).val());\n                loadContent(selectedIndex);\n            });\n            $('#prev-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex > 0) {\n                    loadContent(currentPageIndex - 1);\n                }\n            });\n            $('#next-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex < urls.length - 1) {\n                    loadContent(currentPageIndex + 1);\n                }\n            });\n            $('#auto-load-btn').click(function () {\n                autoLoadInProgress = true;\n                showLoadingStatus(1); \n                for (let i = currentPageIndex + 1; i < urls.length; i++) {\n                    loadContent(i);\n                }\n            });\n            $('#toggle-messages-btn').click(function () { $('#messages').toggle(); });\n            $('#toggle-urls-btn').click(function () { $('#urls').toggle(); });\n            $('#toggle-debug-btn').click(function () { $('#debug-info').toggle(); });\n        });\n    </script>\n</body>\n</html>",
    "ruleImage": "img@data-src",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page",
    "rulePubDate": "em@text",
    "ruleTitle": "strong@text",
    "singleUrl": false,
    "sortUrl": "搜索🔍::/new/index.php?mod=search&kw={{source.getVariable()}}&page={{page}}\n最新::/new/index.php?page={{page}}\n国产自拍::/new/index.php?mod=forumdisplay&fid=10065&page={{page}}\n欧美极品::/new/index.php?mod=forumdisplay&fid=10066&page={{page}}\n日韩无码::/new/index.php?mod=forumdisplay&fid=10067&page={{page}}\n日韩有码::/new/index.php?mod=forumdisplay&fid=10068&page={{page}}\n中文字幕::/new/index.php?mod=forumdisplay&fid=10069&page={{page}}\n动漫精品::/new/index.php?mod=forumdisplay&fid=10070&page={{page}}\n极品萝莉::/new/index.php?mod=forumdisplay&fid=10071&page={{page}}\n强奸乱伦::/new/index.php?mod=forumdisplay&fid=10072&page={{page}}\n童颜巨乳::/new/index.php?mod=forumdisplay&fid=10073&page={{page}}\n三级自慰::/new/index.php?mod=forumdisplay&fid=10075&page={{page}}",
    "sourceComment": "xxrbs.com",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "日鲍社",
    "sourceUrl": "https://879.xxrbs.biz/"
  },
  {
    "articleStyle": 3,
    "customOrder": 4732,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 1774110092242,
    "loadWithBaseUrl": true,
    "ruleArticles": ".item-box",
    "ruleContent": "<js>\n// 提取m3u8链接\nvar m3u8Match = result.match(/\"([^\"]*?index\\.m3u8[^\"]*)\"/i) \n             || result.match(/'([^']*?index\\.m3u8[^']*)'/i);\n\nvar p = '';\nif (m3u8Match) {\n    var u = m3u8Match[1]\n        .replace(/\\\\\\//g, '/')      // \\/ → /\n        .replace(/\\\\\\\\/g, '\\\\')      // \\\\ → \\\n        .trim();\n    \n    // 补全协议\n    if (u.startsWith('//')) {\n        u = 'https:' + u;\n    } else if (!u.startsWith('http')) {\n        // 需要基础URL，这里假设当前页面URL在result中或需要传入\n        u = 'https://' + u;  // 简化处理，或根据实际需求调整\n    }\n    p = u;\n}\n\n// 标题：从 span.tx-flex-sh > a 的 title 属性获取\nvar t = java.getString('.tags-box.0@a.0 @text') || '未知标题';\n\n// 标签：从 meta[name=\"description\"] 的 content 获取  \nvar b = java.getString('.mb5.1 @text') || '';\nvar updateIndex = b.indexOf('更新时间');\nif (updateIndex !== -1) {\nvar d = b.substring(updateIndex);  // 保留\"更新时间\"及之后的内容\n}\n\n`<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>${t}</title>\n<style>\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:-apple-system,sans-serif;background:#f0f9ff;padding:10px}\n.v-box{max-width:800px;margin:0 auto;background:white;border-radius:12px;box-shadow:0 5px 15px rgba(0,0,0,0.1);overflow:hidden}\n.header{padding:12px;border-bottom:1px solid #eee;display:flex;flex-wrap:wrap;justify-content:space-between}\n.title{font-size:18px;font-weight:600;margin-bottom:8px;width:100%}\n.tags{color:#5f6368;font-size:14px;flex:1;min-width:60%;word-break:break-all}\n.time{color:#5f6368;font-size:14px;text-align:right;flex-basis:35%}\n.v-wrap{position:relative;padding-top:56.25%;background:#000}\n.video{position:absolute;top:0;left:0;width:100%;height:100%}\n.footer{padding:8px;text-align:center;color:#5f6368;font-size:13px}\n.info-box{padding:15px;font-size:14px;line-height:1.6}\n.info-box p{margin:8px 0}\n.hint{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,0.7);color:#fff;padding:12px 20px;border-radius:20px;font-size:1.1rem;z-index:10;display:none}\n.controls{position:absolute;top:0;left:0;width:100%;height:4px;background:rgba(255,255,255,0.3);z-index:5;transition:opacity 0.3s}\n.progress{height:100%;background:#4a9eff;width:0}\n</style>\n</head>\n<body>\n<div class=\"v-box\">\n<div class=\"header\">\n<div class=\"title\">${t}</div>\n<div class=\"tags\">${d}</div>\n<div class=\"time\" id=\"timeDisplay\">00:00/00:00</div></div>\n<div class=\"v-wrap\">\n<div class=\"controls\"><div class=\"progress\" id=\"progressBar\"></div></div>\n<div class=\"hint\" id=\"hint\">快进中 &gt;&gt;</div>\n<video class=\"video\" id=\"v\" controls playsinline>\n<source src=\"${p}\" type=\"application/x-mpegURL\">您的浏览器不支持HTML5视频\n</video>\n</div>\n<div class=\"footer\">滑动调整进度 | 长按2倍速</div>\n</div>\n<script>\nvar v = document.getElementById('v');\nvar tDisplay = document.getElementById('timeDisplay');\nvar pBar = document.getElementById('progressBar');\nvar hint = document.getElementById('hint');\nvar startX = 0, startTime = 0;\nvar longPressTimer;\nvar sensitivity = 0.1;\nvar longPressTime = 500;\nvar hintDuration = 2000;\nfunction updateTime() {\nif (!v.duration) return;\nvar m1 = Math.floor(v.currentTime / 60);\nvar s1 = Math.floor(v.currentTime % 60);\nvar m2 = Math.floor(v.duration / 60);\nvar s2 = Math.floor(v.duration % 60);\ntDisplay.textContent = m1 + ':' + (s1 < 10 ? '0' : '') + s1 + '/' + m2 + ':' + (s2 < 10 ? '0' : '') + s2;\npBar.style.width = (v.currentTime / v.duration) * 100 + '%';}\nv.addEventListener('timeupdate', updateTime);\nv.addEventListener('loadedmetadata', updateTime);\nv.addEventListener('touchstart', function(e) {\nstartX = e.touches[0].clientX;\nstartTime = Date.now();\nif (longPressTimer) clearTimeout(longPressTimer);\nhint.style.display = 'none';\nlongPressTimer = setTimeout(function() {\nv.playbackRate = 2.0;\nhint.style.display = 'block';\nsetTimeout(function() { hint.style.display = 'none'; }, hintDuration);}, longPressTime);});\nv.addEventListener('touchmove', function(e) {\ne.preventDefault();\nclearTimeout(longPressTimer);\nvar diffX = e.touches[0].clientX - startX;\nvar change = diffX * sensitivity * v.duration / 100;\nv.currentTime = Math.max(0, Math.min(v.currentTime + change, v.duration));\nstartX = e.touches[0].clientX;updateTime();});\nv.addEventListener('touchend', function() {\nv.playbackRate = 1.0;\nclearTimeout(longPressTimer);});\n</script>\n</body>\n</html>`\n</js>\n",
    "ruleImage": "img@src",
    "ruleLink": "a@href<js> resutl='https://l5--25w3xh.wumatantoupai1.com'+result</js><js>\nresult=result.replace('oddetail', '');\n</js>\n",
    "ruleNextPage": ".laypage_next@href",
    "ruleTitle": "a@title",
    "shouldOverrideUrlLoading": "ture",
    "singleUrl": false,
    "sortUrl": "搜索::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key={{source.getVariable()}}\n国产传媒::https://l5--25w3xh.wumatantoupai1.com/t/2/\n网红头条::https://l5--25w3xh.wumatantoupai1.com/t/241/\n国产视频::https://l5--25w3xh.wumatantoupai1.com/t/163/\n探花系列::https://l5--25w3xh.wumatantoupai1.com/t/239/\n网暴黑料::https://l5--25w3xh.wumatantoupai1.com/t/232/\n自拍::https://l5--25w3xh.wumatantoupai1.com/s/wd/%E5%9B%BD%E4%BA%A7%E8%87%AA%E6%8B%8D\nIPX::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=IPX\nJUL::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=JUL\nABW::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=ABW\nJUQ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=JUQ\nSONE::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=SONE\nMIRD::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=MIRD\nIPZZ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=IPZZ\nOFJE::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=OFJE\nMIDV::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=MIDV\nCAWD::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=CAWD\nSONE::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=SONE\nMIAB::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=MIAB\nMIMK::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=MIMK\nSSIS::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=SSIS\nPRED::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=PRED\nDASS::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=DASS\nSTARS::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=STARS\nFSDSS::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=FSDSS\nSTART::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=START\nmiru::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=miru\n爆菊::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=爆菊\n求饶::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=求饶\n短裙::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=短裙\n浴场::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=浴场\n迷晕::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=迷晕\n嫖妓::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=嫖妓\n正妹::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=正妹\n紧身::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=紧身\n老婆::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=老婆\n中出::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=中出\n女模::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=女模\n按摩::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=按摩\n阴道::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=阴道\n开档::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=开档\n拍摄::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=拍摄\n海滩::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=海滩\n奴隶::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=奴隶\n惩罚::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=惩罚\n精液::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=精液\n嫂子::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=嫂子\n上位::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=上位\n秘书::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=秘书\n上班::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=上班\n强迫::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=强迫\n甜蜜::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=甜蜜\n温柔::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=温柔\n暴力::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=暴力\n撕烂::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=撕烂\n女星::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=女星\n卖淫::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=卖淫\n夜班::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=夜班\n尾随::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=尾随\n色狼::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=色狼\n痴汉::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=痴汉\n偶遇::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=偶遇\n巨乳::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=巨乳\n调教::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=调教\n萝莉::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=萝莉\n自慰::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=自慰\n妈妈::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=妈妈\n母子::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=母子\n石川澪::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=石川澪\n皆月光::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=皆月光\n大槻響::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=大槻響\n櫻空桃::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=櫻空桃\n波多野結衣::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=波多野結衣\n桃乃木香奈::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=桃乃木香奈\n七瀨愛麗絲::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=七瀨愛麗絲\n吉根柚莉愛::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=吉根柚莉愛\n柏木こなつ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=柏木こなつ\n天馬ゆい::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=天馬ゆい\n夢乃あいか::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=夢乃あいか\n未步なな::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=未步なな\n倉本すみれ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=倉本すみれ\n望月つぼみ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=望月つぼみ\n新井リマ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=新井リマ\n浅野こころ::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=浅野こころ\n東雲みれい::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=東雲みれい\n松本一香::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=松本一香\n木下日葵::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=木下日葵\n瀬户环奈::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=瀬户环奈\n河北彩花::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=河北彩花\n沙月惠奈::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=沙月惠奈\n美園和花::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=美園和花\n沙月芽衣::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=沙月芽衣\n藤森里穗::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=藤森里穗\n石原希望::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=石原希望\n月乃露娜::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=月乃露娜\n小宵虎南::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=小宵虎南\n七澤米亞::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=七澤米亞\n小野六花::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=小野六花\n彌生美月::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=彌生美月\n山岸逢花::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=山岸逢花\n三上悠亞::https://l5--25w3xh.wumatantoupai1.com/addons/s/wd/link.php?key=三上悠亞",
    "sourceComment": "",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "桃子",
    "sourceUrl": "https://l5--25w3xh.wumatantoupai1.com/show/2/ "
  },
  {
    "articleStyle": 0,
    "customOrder": 4733,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": ".appel-max@ul@li!0:1:2:3:4:5",
    "ruleContent": "<js>\np=result.match(/url\\\"\\:\\\"(.*?)\\\"\\,\\\"url/)[1].replace(/\\\\/g,'')\nvar p\n`<html>\n    <head>\n        <meta name=\"viewport\" content=\"width=device-width\">\n        <style>\n            body {\n                margin: 0;\n                font-family: Arial, sans-serif;\n                background: linear-gradient(135deg, #ece9e6, #ffffff);\n                display: flex;\n                flex-direction: column;\n                align-items: center;\n                justify-content: flex-start;\n                padding: 20px;\n            }\n           .container {\n                width: 100%;\n                max-width: 800px;\n                background: #fff;\n                border-radius: 10px;\n                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n                overflow: hidden;\n                margin-bottom: 20px;\n            }\n            h3 {\n                margin: 0;\n                padding: 10px 20px;\n                font-size: 0.9em;\n                background: #333;\n                color: #fff;\n                border-radius: 10px 10px 0 0;\n            }\n           .video-container {\n                width: 100%;\n                background: #000;\n                position: relative;\n            }\n            video {\n                width: 100%;\n                height: auto;\n                display: block;\n            }\n           .info-container {\n                padding: 20px;\n            }\n           .info-container p {\n                margin: 10px 0;\n                color: #555;\n            }\n           .info-container p span {\n                font-weight: bold;\n                color: #000;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n            <div class=\"video-container\">\n                <video controls autoplay name=\"media\">\n                    <source src=\"${p}\" type=\"video/mp4\">\n                </video>\n            </div>\n            <div class=\"info-container\">\n                \n            </div>\n        </div>\n    </body>\n</html>`;\n\n</js>",
    "ruleImage": "img@data-original##.*gif",
    "ruleLink": "a.-1@href##/voddetail/(\\d+).html##https://cdnaaapi.yiniuyingshi6.com:2053/vodplay/$1-1-1.html",
    "ruleNextPage": "text.下一页@href",
    "rulePubDate": "{{@span.video-grade@text}}  {{@p@text}}",
    "ruleTitle": "h5@a@text",
    "singleUrl": false,
    "sortUrl": "制服丝袜::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/20.html\n群交淫乱::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/21.html\n无码专区::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/22.html\n偷拍自拍::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/23.html\n卡通动画::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/24.html\n中文字幕:https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/25.html\n欧美性爱::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/26.html\n巨乳美乳::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/27.html\n国产裸聊::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/28.html\n国产自拍::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/29.html\n国产盗摄::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/30.html\n伦理三级::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/31.html\n女同性恋::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/32.html\n少女萝莉::https://cdnaaapi.yiniuyingshi6.com:2053/vodtype/33.html",
    "sourceComment": "需要频道换源\n地址发布页\nhttp://www.henniu69.xyz/",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "一牛",
    "sourceUrl": "https://cdnaaapi.yiniuyingshi6.com:2053"
  },
  {
    "articleStyle": 0,
    "customOrder": 4734,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "class.inner_layer@ul@li@a",
    "ruleContent": "text.普通下载@href\n<js>\nresult+=\".m3u8\";\r\nresult = \"<video src=\\\"\" + result + \"\\\" width=\\\"100%\\\" height=\\\"240px\\\" controls=\\\"controls\\\" ></video>\";\r\nresult = \"<html><head><meta charset=\\\"utf-8\\\"><meta name=\\\"viewport\\\" content=\\\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\\\" /><style>html,body{margin:0;padding:0;width:100%;}</style></head><body>\" + result + \"</body></html>\"\n</js>",
    "ruleImage": "img@data-original||img@src",
    "ruleLink": "href##$##,\\{\\\"webView\\\": true\\}",
    "ruleNextPage": "page",
    "rulePubDate": "class.timeobxobx@text",
    "ruleTitle": "p.-1@text",
    "singleUrl": false,
    "sortUrl": "亚洲精品::/Html/110/{{page - 1 == 0 ? \"\":\"index-\"+page+\".html\"}},{\"webView\": true}\nS级女优::/Html/100/{{page - 1 == 0 ? \"\":\"index-\"+page+\".html\"}},{\"webView\": true}\n成人动漫::/Html/101/{{page - 1 == 0 ? \"\":\"index-\"+page+\".html\"}},{\"webView\": true}\n欧美巨龙::/Html/62/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n熟女人妻::/Html/111/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n美颜巨乳::/Html/112/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n颜射吃精::/Html/113/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n丝袜制服::/Html/114/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n自拍隐摄::/Html/89/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n换妻游戏::/Html/90/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n网红主播::/Html/91/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}\n经典三级::/Html/109/{{page - 1 == 0 ? \"\": \"index-\"+page+\".html\"}},{\"webView\": true}",
    "sourceComment": "发布页https://guochandizhi6.com/\n永久地址https://992kp.com/",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "小黄",
    "sourceUrl": "https://992.992kp340.work:8443/index.html"
  },
  {
    "articleStyle": 0,
    "customOrder": 4735,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.rescont.data",
    "ruleContent": "<video src=\"{{$.rescont.videopath}}\" controls width=\"auto\" height=\"auto\"></video>",
    "ruleImage": "$.coverpath",
    "ruleLink": "http://lu3fcm.aksdsrle.com/api/videoplay/{{$.id}}?&uuid=1",
    "ruleNextPage": "page",
    "rulePubDate": "{{$.authername}}",
    "ruleTitle": "$.title",
    "singleUrl": false,
    "sortUrl": "测试::http://lu3fcm.aksdsrle.com/api/videosort/9?orderby=&page=1&uuid=1&device=0\n网红主播::http://lu3fcm.aksdsrle.com/api/videosort/42?orderby=&page={{page}}&uuid=1&device=0\n国产AV::http://lu3fcm.aksdsrle.com/api/videosort/44?orderby=&page={{page}}&uuid=1&device=0\n狼友求片::http://lu3fcm.aksdsrle.com/api/videosort/43?orderby=&page={{page}}&uuid=1&device=0\n18::http://lu3fcm.aksdsrle.com/api/videosort/41?orderby=&page={{page}}&uuid=1&device=0\n16::http://lu3fcm.aksdsrle.com/api/videosort/38?orderby=&page={{page}}&uuid=1&device=0\n15::http://lu3fcm.aksdsrle.com/api/videosort/37?orderby=&page={{page}}&uuid=1&device=0\n\n9::http://lu3fcm.aksdsrle.com/api/videosort/50?orderby=&page={{page}}&uuid=1&device=0\nAV解说::http://lu3fcm.aksdsrle.com/api/videosort/49?orderby=&page={{page}}&uuid=1&device=0\n破解版::http://lu3fcm.aksdsrle.com/api/videosort/48?orderby=&page={{page}}&uuid=1&device=0\n6::http://lu3fcm.aksdsrle.com/api/videosort/27?orderby=&page={{page}}&uuid=1&device=0\n三级电影::http://lu3fcm.aksdsrle.com/api/videosort/25?orderby=&page={{page}}&uuid=1&device=0\n欧美激情::http://lu3fcm.aksdsrle.com/api/videosort/16?orderby=&page={{page}}&uuid=1&device=0\n动漫::http://lu3fcm.aksdsrle.com/api/videosort/14?orderby=&page={{page}}&uuid=1&device=0\n国产精品::http://lu3fcm.aksdsrle.com/api/videosort/10?orderby=&page={{page}}&uuid=1&device=0\n1::http://lu3fcm.aksdsrle.com/api/videosort/9?orderby=&page={{page}}&uuid=1&device=0",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "噜噜噜",
    "sourceUrl": "http://lu3fcm.aksdsrle.com/api/videosort/9?orderby=&page=1&uuid=1&device=0"
  },
  {
    "articleStyle": 3,
    "customOrder": 4736,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 1770433323182,
    "loadWithBaseUrl": true,
    "ruleArticles": "ul@li",
    "ruleContent": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<title>内容提取</title>\n<!-- v2025.05.10 -->\n\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<script src=\"https://code.jquery.com/jquery-3.6.0.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css\" />\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js\"></script>\n<style>\n    body { font-family: Arial, sans-serif; font-size: 16px; }\n    #title, #page, #loading-status { margin: 0 auto; font-size: 20px; text-align: center; }\n    #description, #urls, #video-url, #video-sources, #messages { width: 100%; max-width: 800px; margin: 1.5px auto; font-size: 14px; text-align: left; word-wrap: break-word; white-space: pre-wrap; }\n    #text, #text :not(img), #text img + * { text-indent: 2em; width: 100%; font-size: 16px; line-height: 1.5em; margin-top: 0; margin-bottom: 0; word-wrap: break-word; white-space: pre-wrap; }\n    img, #text img { width: 100%; height: auto; display: block; margin-bottom: 1.5px; }\n    .flex-container { display: flex; justify-content: center; align-items: center; gap: 10px; margin: 1.5px 0; font-size: 14px; }\n    button, select { flex: 1 1 31%; padding: 3px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; cursor: pointer; background-color: #f9f9f9; transition: background-color 0.3s ease; margin: 1.5px; min-width: 0; font-size: 14px; }\n    #url-select, #video-source-select { flex: 1 1 100%; margin-left: 0; margin-right: 0; text-align: center; }\n    #video-element { width: 100%; height: auto; }\n    textarea { width: 100%; height: auto; min-height: 100px; box-sizing: border-box; resize: vertical; }\n    .error, .warn { color: red; }\n</style>\n</head>\n<body>\n    <h3 id=\"title\">{{@@title@text||h1.0@text||h2.0@text||.title.0@text}}</h3>\n    <p id=\"description\">{{@@.info.0@html||.jianjie@html}}</p>\n    <p id=\"page\" style=\"display:none;\">共<span id=\"total-pages\">1</span>页</p>\n    <p id=\"loading-status\" style=\"display:none;\"></p>\n\n    <div class=\"flex-container\" id=\"loading-buttons\" style=\"display:none;\">\n        <button id=\"prev-page-btn\">上一页</button>\n        <button id=\"next-page-btn\">下一页</button>\n        <button id=\"auto-load-btn\">自&nbsp;&nbsp;动</button>\n    </div>\n    \n    <div class=\"flex-container\">\n        <select id=\"url-select\" style=\"display:none;\"></select>\n    </div>\n    \n    <div class=\"flex-container\">\n        <button id=\"toggle-urls-btn\">显/隐网址</button>\n        <button id=\"toggle-messages-btn\">显/隐信息</button>\n        <button id=\"toggle-debug-btn\">显/隐调试</button>\n    </div>\n    <div id=\"urls\"></div>\n    <div id=\"messages\"></div>\n    <div id=\"debug-info\"></div>\n    <div id=\"video-url\"></div>\n    <div id=\"video-container\" style=\"display: none;\">\n        <video id=\"video-element\" controls preload=\"auto\" width=\"640\" height=\"264\">\n            <source id=\"video-source\" src=\"\" type=\"\">您的浏览器不支持 video 标签。\n        </video>\n    </div>\n    <div class=\"flex-container\" id=\"video-source-container\" style=\"display: none;\">\n        <select id=\"video-source-select\" onchange=\"updateVideoSource()\"></select>\n    </div>\n    <div id=\"images\"></div>\n    <div id=\"text\"></div>\n\n    <script>\n        // 配置对象，包含各种选择器、延迟时间等配置项\n        const config = {    \n            videoSelector: 'body', // 视频选择器\n            imgSelector: '.gridlane-box-inside img,.photos figure img,.content p img', // 图片选择器\n            textSelector: '#content', // 文本选择器\n            debugSelector: '#content, .page, .pager, .content, script', // 调试信息选择器\n            swapImageAttributes: false, // 是否交换图片属性\n            delayTime: 1500, // 延迟提取时间\n            retryDelayTime: 1500, // 重试加载延迟时间\n            maxLoadAttempts: 3, // 最大加载次数\n            autoLoading: false, // true自动模式，false单页模式\n            debugOnce: 0, // 只在特定索引输出一次调试信息\n            totalPagesText: '{{@@.page.0@a.-2@textNodes}}', // 总页码\n            urlSuffixToRemove: /\\.html$/, // 移除url后缀\n            pageUrlText: '{urlPrefix}_{i}.html', // 拼接URL模板        \n            ListMode: true, // true网址列表模式，false网址拼接模式    \n            initialUrls: `{{@@#sort-item-5.0@a@href}}`, // 网址\n            initialUrlsName: `{{@@#sort-item-5.0@a@span@text}}`, // 网址名称\n            sourceurl: '', // 来源URL前缀\n        };\n\n        let videoSources = []; // 存储视频源数组\n        let loadAttempts = {}; // 记录每个URL的加载尝试次数\n        let urls = []; // 存储所有页面的URL\n        let imageBox;\n        let textBox;\n        let currentPageIndex = 0; // 当前页面索引\n        let canLoadNextPage = true; // 控制是否可以加载下一页\n        let autoLoadInProgress = false; // 自动加载状态\n\n        // 构建URL列表\n        function buildUrls(totalPages, baseUrl) {\n            let initialUrlsArray = config.initialUrls.trim().split('\\n').filter(url => url.trim() !== '');\n            let initialUrlsNameArray = config.initialUrlsName.trim().split('\\n').filter(name => name.trim() !== '');\n\n            if (config.ListMode && initialUrlsArray.length > 0) {\n                if (initialUrlsArray.length !== initialUrlsNameArray.length) {\n                    $('#messages').append(`<span class=\"warn\">警告：initialUrls 和 initialUrlsName 的长度不匹配。</span><br>`);\n                }\n\n                urls = initialUrlsArray.map(url => {\n                    if (config.sourceurl && url.startsWith('/') && !/^https?:\\/\\//i.test(url)) {\n                        return config.sourceurl.replace(/\\/$/, '') + url;\n                    } else {\n                        return url;\n                    }\n                });\n\n                urls.forEach((url, index) => {\n                    const name = initialUrlsNameArray[index] || `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            } else {\n                if (totalPages === 1) {\n                    urls.push(baseUrl);\n                } else {\n                    urls.push(baseUrl);\n                    for (let i = 2; i <= totalPages; i++) {\n                        urls.push(config.pageUrlText.replace('{urlPrefix}', baseUrl.replace(config.urlSuffixToRemove, '').replace(/\\/$/, '')).replace('{i}', i));\n                    }\n                }\n\n                urls.forEach((url, index) => {\n                    const name = `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            }\n\n            $('#total-pages').text(urls.length);\n            toggleNavigationButtons();\n            toggleTotalPagesDisplay();\n        }\n\n        // 规范化URL\n        function normalizeUrl(url) {\n            if (typeof url !== 'string' || !url.trim()) {\n                return '';\n            }\n            const match = url.match(/['\"](.*?)['\"]/);\n            if (match && match[1]) {\n                url = match[1];\n            }\n\n            function processUrl(str) {\n                str = str.trim();\n                str = str.replace(/\\\\u[\\dA-F]{4}/gi, match => String.fromCharCode(parseInt(match.replace(/\\\\u/g, ''), 16)));\n                str = decodeURIComponent(str);\n                str = str.replace(/^http:\\/([^/])/, 'http://$1');\n                str = str.replace(/^https:\\/([^/])/, 'https://$1');\n                return str;\n            }\n            return processUrl(url);\n        }\n\n        // 清空容器内容\n        function clearContainers() {\n            $('#messages').empty();\n            $('#images').empty();\n            $('#text').empty();\n        }\n\n        // 更新图像源\n        function updateImageSrc(elements, shouldSwap) {\n            elements.each(function () {\n                const $this = $(this);\n                const attrsToUpdate = {};\n                if (shouldSwap) {\n                    ['data-original', 'data-src', 'data-url'].forEach(attr => {\n                        if ($this.attr(attr)) {\n                            attrsToUpdate['src'] = $this.attr(attr);\n                        }\n                    });\n                }\n                $this.attr(attrsToUpdate);\n            });\n            return elements;\n        }\n\n        // 切换导航按钮显示状态\n        function toggleNavigationButtons() {\n            if ($('#url-select option').length > 1 && !config.autoLoading) {\n                $('#loading-buttons').show();\n                $('#url-select').show();\n            } else {\n                $('#loading-buttons').hide();\n                $('#url-select').hide();\n            }\n        }\n\n        // 显示加载状态\n        function showLoadingStatus(pageNumber) {\n            const selectedOption = $('#url-select option:selected').text();\n            $('#loading-status').text(`正在加载：${selectedOption}`).show();\n        }\n\n        // 隐藏加载状态\n        function hideLoadingStatus() {\n            $('#loading-status').hide();\n        }\n\n        // 加载指定索引的内容\n        function loadContent(index) {\n            if (index < 0 || index >= urls.length || !canLoadNextPage) return;\n            canLoadNextPage = false;\n            currentPageIndex = index;\n            $('#url-select').val(index);\n            $('#messages').append(`<div>当前地址: <span class=\"warn\">${urls[index]}</span></div>`);\n            if (autoLoadInProgress) {\n                showLoadingStatus(index + 1);\n            }\n            $.ajax({\n                url: urls[index],\n                type: 'GET',\n                success: function (data) {\n                    try {\n                    const $data = $(data);\n                    let updatedHtmlContent = data.replace(/(['\"])(\\/\\/)(?!\\/)/g, '$1https://')\n                        .replace(/src=\"upload/gi, 'src=\"/upload')\n                        .replace(/style=[\"'][^'\"]+[\"']/gi, '')\n                        .replace(/\\\\\\//g, '/');\n                    const parser = new DOMParser();\n                    const doc = parser.parseFromString(updatedHtmlContent, \"text/html\");\n\n                    if (config.debugOnce === index) {\n                        const debugElements = $(doc).find(config.debugSelector);\n                        if (debugElements.length > 0) {\n                            const debugContents = $('<pre>').html(debugElements.clone().wrapAll('<div/>').parent().html()).html();\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">${debugContents}</textarea></span>`);\n                        } else {\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">调试信息未提取到内容，请检查选择器！</textarea></span>`);\n                        }\n                    }\n                    // 方法1：提取视频\n                    const videoSources1 = [];\n                    const videoContents = $(doc).find(config.videoSelector);\n                    const videoTags = $(videoContents).find('video, source');\n                    videoTags.each(function() {\n                        const videosrc = $(this).attr('src') || \n                                     $(this).attr('data-src') || \n                                     $(this).attr('data-original') || '';\n                        \n                        if (videosrc) {\n                            videoSources1.push(videosrc);\n                        }\n                    });\n                    //反馈\n                    if (videoSources1.length > 0) {\n                        $('#messages').append(`<span>方法1，找到 ${videoSources1.length} 个视频。</span><br>`);\n                    }\n\n                    // 方法2：正则提取视频\n                    const regex = /['\"]https?[^'<>\"]+(m3u8|mp4|webm|ogg|flv|mp3|m4a|wav|ape|flac)([^'<>\"]+)?['\"]/gi;\n                    const matches = data.match(regex);\n                    const videoSources2 = [];\n\n                    if (matches) {\n                        const uniqueMatches = [...new Set(matches)];\n                    \n                        uniqueMatches.forEach(match => {\n                            const normalizedSrc = normalizeUrl(match.replace(/['\"]/g, ''));\n                            videoSources2.push(normalizedSrc);\n                        });\n                    }\n                    //反馈\n                    if (videoSources2.length > 0) {\n                        $('#messages').append(`<span>方法2，找到 ${videoSources2.length} 个视频。</span><br>`);\n                    }\n\n                    // 合并两种方法的结果\n                    videoSources = [...videoSources1, ...videoSources2];\n\n                    // 去重并标准化 URL\n                    const imageExtensions = /\\.(jpg|jpeg|png|gif|bmp|svg)$/i;\n\n                    videoSources = videoSources\n                                  .map(src => normalizeUrl(src.replace(/\\\\+/g, '')))\n                                  .filter(src => src) // 过滤空值\n                                  .filter(src => !imageExtensions.test(src)); // 移除图片地址\n                        \n                    videoSources = [...new Set(videoSources)];// 去重\n\n                    // 显示最终结果\n                    $('#messages').append(`<span>总共找到 ${videoSources.length} 个视频。</span><br>`);\n\n                    if (videoSources.length > 0) {\n                        $('#messages').append(`<span>成功提取到视频，找到 ${videoSources.length} 个视频。</span><br>`);\n                        videoSources.forEach((src, idx) => {\n                            $('#messages').append(`<div>视频地址:<span class=\"warn\"> ${src}</span><br></div>`);\n                            $('#video-source-select').append(`<option value=\"${idx}\">视频源 ${idx + 1}</option>`);\n                        });\n                    \n                        if (videoSources.length == 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').hide();\n                            updateVideoSource();\n                        } else if (videoSources.length > 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').show();\n                            updateVideoSource();\n                        } else {\n                            $('#video-container').hide();\n                            $('#video-url').hide();\n                            $('#video-source-container').hide();\n                        }\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未找到视频源。</span><br>`);\n                        $('#video-container').hide();\n                        $('#video-url').hide();\n                        $('#video-source-container').hide();\n                    }\n\n                    //提取图片\n                    const $imgContents = $(doc).find(config.imgSelector);\n                    const shouldSwap = config.swapImageAttributes;\n                    const newContents = updateImageSrc($imgContents.clone(), shouldSwap);\n                    $('#images').append(newContents).show();\n                    if (newContents.length > 0) {\n                        $('#messages').append(`<span>成功提取图片，共 ${newContents.length} 张。</span><br>`);\n                        newContents.each(function () {\n                            const imgSrc = $(this).attr('src') || $(this).attr('data-original') || $(this).attr('data-src') || $(this).attr('data-url');\n                            $('#messages').append(`<div>地址:<span class=\"warn\"> ${imgSrc}</span><br></div>`);\n                        });\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图片。</span><br>`);\n                    }\n\n                    //提取图片和文本\n                    const textContents = $(doc).find(config.textSelector).map(function () {\n                        const $currentContents = $(this);\n                        $currentContents.find('img + br, script, video, source, iframe').remove();\n                        $currentContents.html($currentContents.html().replace(/>\\s+/gi, '>').replace(/<\\/?br\\s*([^>]*)\\s*\\/?>/gi, '\\n').replace(/\\n+/g, '\\n'));\n                        return $currentContents.html();\n                    }).get().join('');\n                    if (textContents.trim()) {\n                        $('#text').append(`<span>${textContents}</span><br>`).show();\n                        $('#messages').append(`<span>成功提取图文。</span><br>`);\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图文。</span><br>`);\n                    }\n\n                    if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                        setTimeout(() => { \n                            canLoadNextPage = true;\n                            loadContent(currentPageIndex + 1); \n                        }, config.delayTime);\n                    } else {\n                        canLoadNextPage = true;\n                        if (autoLoadInProgress) {\n                            hideLoadingStatus();\n                        }\n                    }\n                } catch (parseError) {\n                    $('#messages').append(`<span class=\"error\">解析页面内容时发生错误: ${parseError.message}</span><br>`);\n                    handleLoadFailure(urls, index);\n                } finally {\n                    if (imageBox) imageBox.viewer.update();\n                    if (textBox) textBox.viewer.update();\n                }\n            },\n            error: function (jqXHR, textStatus, errorThrown) {\n                let errorMessage = `内容加载失败: ${urls[index]}`;\n                switch (textStatus) {\n                    case 'timeout':\n                        errorMessage += ', 请求超时';\n                        break;\n                    case 'abort':\n                        errorMessage += ', 请求被取消';\n                        break;\n                    case 'parsererror':\n                        errorMessage += ', 解析响应出错';\n                        break;\n                    default:\n                        errorMessage += `, 状态码: ${jqXHR.status}, 错误信息: ${errorThrown}`;\n                        break;\n                }\n                $('#messages').append(`<span class=\"error\">${errorMessage}</span><br>`);\n                handleLoadFailure(urls, index);\n                }\n            });\n        }\n\n        // 处理加载失败的情况\n        function handleLoadFailure(urls, index) {\n            if (!loadAttempts[urls[index]]) {\n                loadAttempts[urls[index]] = 1;\n            } else {\n                loadAttempts[urls[index]]++;\n            }\n            if (loadAttempts[urls[index]] <= config.maxLoadAttempts) {\n                const retryMessage = `第${index + 1}页加载失败，正在进行第${loadAttempts[urls[index]]}次加载！`;\n                $('#messages').append(`<span class=\"error\">${retryMessage}</span><br>`);\n                setTimeout(() => { \n                    canLoadNextPage = true;\n                    loadContent(index); \n                }, config.retryDelayTime);\n            } else {\n                const finalErrorMessage = `第${index + 1}页加载失败，已达到最大尝试次数(${config.maxLoadAttempts})！`;\n                $('#messages').append(`<span class=\"error\">${finalErrorMessage}</span><br>`);\n                if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                    setTimeout(() => { \n                        canLoadNextPage = true;\n                        loadContent(currentPageIndex + 1); \n                    }, config.delayTime);\n                } else {\n                    canLoadNextPage = true;\n                    if (autoLoadInProgress) {\n                        hideLoadingStatus();\n                    }\n                }\n            }\n        }\n\n        // 更新视频源\n        function updateVideoSource() {\n            const selectedIndex = parseInt(document.getElementById('video-source-select').value);\n            if (isNaN(selectedIndex) || !videoSources[selectedIndex]) {\n                $('#messages').append(`<span class=\"warn\">未找到有效的视频源。</span><br>`);\n                console.warn(\"Invalid or undefined video source:\", selectedIndex, videoSources);\n                return;\n            }\n\n            const selectedSource = videoSources[selectedIndex];\n            document.getElementById('video-url').textContent = `视频地址:\\n ${selectedSource}`;\n\n            const videoSourceElement = document.getElementById('video-source');\n            videoSourceElement.src = selectedSource;\n\n            const videoElement = document.getElementById('video-element');\n            videoElement.load();\n\n            $('#messages').append(`<span>更新视频源为: ${selectedSource}</span><br>`);\n            console.log(\"Updated video source to:\", selectedSource);\n        }\n\n        // 切换总页数显示状态\n        function toggleTotalPagesDisplay() {\n            if (urls.length > 1) {\n                $('#page').show();\n            } else {\n                $('#page').hide();\n            }\n        }\n\n        // 页面加载完成后执行的主要逻辑\n        $(document).ready(function () {\n            imageBox = document.getElementById('images');\n            textBox = document.getElementById('text');\n            if (imageBox && textBox) {\n                new Viewer(imageBox, { title: true, interval: 2000 });\n                new Viewer(textBox, { title: true, interval: 2000 });\n            }\n\n            const totalPagesText = config.totalPagesText;\n            const totalPages = parseInt(totalPagesText, 10) || 1;\n            const baseUrl = '{{baseUrl}}';\n\n            clearContainers();\n            $('#urls, #debug-info textarea, #video-url, #video-source-select').empty();\n            $('#urls, #messages, #debug-info, #video-url, #video-container, #video-source-container, #images, #text').hide();\n\n            buildUrls(totalPages, baseUrl);\n\n            const urlSelect = document.getElementById('url-select');\n            if (urlSelect.options.length > 0) {\n                urlSelect.value = '0'; \n\n                if (config.autoLoading) {\n                    autoLoadInProgress = true;\n                    for (let i = 0; i < urls.length; i++) {\n                        loadContent(i);\n                    }\n                } else {\n                    loadContent(0);\n                }\n            } else {\n                loadContent(0);\n            }\n\n            $('#url-select').change(function () {\n                clearContainers();\n                const selectedIndex = parseInt($(this).val());\n                loadContent(selectedIndex);\n            });\n            $('#prev-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex > 0) {\n                    loadContent(currentPageIndex - 1);\n                }\n            });\n            $('#next-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex < urls.length - 1) {\n                    loadContent(currentPageIndex + 1);\n                }\n            });\n            $('#auto-load-btn').click(function () {\n                autoLoadInProgress = true;\n                showLoadingStatus(1); \n                for (let i = currentPageIndex + 1; i < urls.length; i++) {\n                    loadContent(i);\n                }\n            });\n            $('#toggle-messages-btn').click(function () { $('#messages').toggle(); });\n            $('#toggle-urls-btn').click(function () { $('#urls').toggle(); });\n            $('#toggle-debug-btn').click(function () { $('#debug-info').toggle(); });\n        });\n    </script>\n</body>\n</html>",
    "ruleImage": "a@data-original",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page||text.下一页@href",
    "rulePubDate": "[class=\"pic-text text-right\"]@text",
    "ruleTitle": "h4@text",
    "singleUrl": false,
    "sortUrl": "搜索🔍::/jiejie/index.php/vod/search.html?wd={{source.getVariable()}}\n黄瓜资源::/jiejie/index.php/vod/type/id/87.html\n155资源::/jiejie/index.php/vod/type/id/248.html\n森林资源::/jiejie/index.php/vod/type/id/117.html\n奥斯卡资源::/jiejie/index.php/vod/type/id/86.html\n百万资源::/jiejie/index.php/vod/type/id/237.html\n制服诱惑::/jiejie/index.php/vod/show/id/251.html\n中文字幕::/jiejie/index.php/vod/show/id/254.html\n美乳巨乳::/jiejie/index.php/vod/show/id/262.html\n熟女人妻::/jiejie/index.php/vod/show/id/259.html\n萝莉少女::/jiejie/index.php/vod/show/id/260.html\n强奸乱伦::/jiejie/index.php/vod/show/id/263.html\n无码专区::/jiejie/index.php/vod/show/id/249.html",
    "sourceComment": "jiejiesp.xyz",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "姐姐视频",
    "sourceUrl": "https://wap.jiejiesp19.xyz"
  },
  {
    "articleStyle": 0,
    "customOrder": 4737,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.list",
    "ruleDescription": "<br><h3>{{$.vod_name}}</h3>\n<h6>[{{$.vod_score}}分] [{{$.vod_class ##\\,##] [}}]<b>发布于 {{$.vod_time}}</b></h6>\n\n<video src=\"{{$.vod_play_url ##^.*?\\$}}\" poster=\"{{$.vod_pic}}\" controls></video>",
    "ruleImage": "$.vod_pic",
    "ruleLink": "/api.php/provide/vod/?ac=detail&ids={{$.vod_id}}",
    "ruleNextPage": "page",
    "rulePubDate": "⏱️ {{$.vod_duration}}　{{$.vod_score}}分　{{$.vod_time}}",
    "ruleTitle": "$.vod_name",
    "singleUrl": false,
    "sortUrl": "精品推荐::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=20\n🔎 视频搜索::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&wd={{source.getVariable()}}\n国产视频::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=22\n主播直播::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=23\n日本无码::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=24\n日本有码::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=25\n中文字幕::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=26\n巨乳美乳::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=27\n制服丝袜::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=34\n角色扮演::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=35\n熟女人妻::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=28\n强奸乱伦::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=29\n欧美精品::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=30\n少女萝莉::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=31\n三级伦理::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=32\n成人动漫::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=33\n自拍偷拍::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=34\n制服丝袜::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=35\n口交颜射::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=36\n日本精品::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=37\nCosplay::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=38\n素人自拍::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=39\n台湾辣妹::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=40\n韩国御姐::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=41\n唯美港姐::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=42\n东南亚AV::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=43\n欺辱凌辱::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=44\n剧情介绍::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=45\n多人多P::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=46\n91探花::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=47\n网红流出::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=48\n野外露出::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=49\n古装扮演::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=50\n女优系列::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=51\n可爱学生::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=52\n风情旗袍::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=53\n兽耳系列::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=54\n瑜伽裤::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=55\n闷骚护士::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=56\n过膝袜::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=57\n网爆门::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=58\n传媒出品::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=59\n女同性恋::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=60\n男同性恋::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=61\n练腿狂魔::https://slapibf.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=63",
    "sourceComment": "★源URL的填写链接为【list】格式\n\t网站网址\n\t网站网址/api.php/provide/vod/?ac=【list】\n\n例：\nhttps://apittzy.com\nhttps://apittzy.com/api.php/provide/vod/?ac=list\n\nps：\n\t使用【list】格式查看分类和分类id以组成分类URL\n\n\n\n★分类URL的填写链接为【detail】格式\n\t视频搜索::网站网址/api.php/provide/vod/?ac=【detail】&pg={{page}}&wd=关键词\n\t分类名称::网站网址/api.php/provide/vod/?ac=【detail】&pg={{page}}&t=分类id\n\n例：\n\t视频搜索::https://apittzy.com/api.php/provide/vod/?ac=detail&pg={{page}}&wd=按摩\n\t精品推荐::https://apittzy.com/api.php/provide/vod/?ac=detail&pg={{page}}&t=1\n\nps：\n\t分类URL写成【list】格式也行，但是没有详细信息。需要通过正文链接跳转正文页再填写正文规则。而且没有封面！\n\n\n\n★正文规则\n\t因为分类URL使用了【detail】格式，需要的信息都显示了。(视频链接)\n\t所以我们在描述规则填写正文规则就行了，这样子就省的再跳转一次正文链接了。\n\t但是链接规则还是要写的，不然不会加载列表。\n\n\n\n☆【vod】和【art】\n视频分类链接为【vod】格式\n\t网站网址/api.php/provide/vod/?ac=list\n图文分类链接为【art】格式\n\t网站网址/api.php/provide/art/?ac=list\n通过【list】格式查看分类和分类id以组成分类URL\n\nps：\n\t图片和小说链接都是【art】格式，这样子不好分割，建议把小说分类相关链接移除\n\t因为【art】格式的【detail】链接并不会显示全部套图，所以需要填写正确的链接规则跳转正文页再填写正文规则而不是直接在描述规则处填写规则\n\n\n\n☆详情页链接规则\n\t详情页链接仅支持【detail】格式\n网站网址/api.php/provide/(vod/art)/?ac=detail&ids=(视频id/图文id)\n\n\t如果分类URL只填写了网址，那么链接规则补充剩下的链接就行了\n例：\n\t/api.php/provide/vod/?ac=detail&ids=视频id\n❗仅限【vod】/【art】单格式使用\n\n\t如果订阅同时写了【vod】和【art】两种格式，链接就需要使用js判定\n@js:\nif(baseUrl.match(/art/)){\n\t网站网址/api.php/provide/art/?ac=detail&ids={{$.art_id}}\n}else{\n\t网站网址/api.php/provide/vod/?ac=detail&ids={{$.vod_id}}\n}\nps：\n\t使用两种格式时，此js在正文规则也会需要用到。\n\n\n\n\n\n‼️以下网址加上【list】链接可更改为json格式，查看分类及分类id\n\n\t因为json链接格式固定？\n\t所以修改一下网站之间的分类URL差别即可使用此订阅格式套用，，，大概\n\nps：\n\t注意【list】和【detail】格式以及【vod】和【art】链接的差别\n\n\n共30个网址：\n\n\t★鲨鱼::https://shayuapi.com\n\t\tps：老朋友了\n\n\n\t老鸭资源失效::http://laoyazy50.cc\n\t\tps：网站有时效性？\n\n\n\t老鸭资源2失效::https://api.apilyzy.com\n\n\n\n\t水蜜桃失效::http://51smt4.xyz\n\n\n\t99资源失效::http://99zy.pw\n\n\n\t99资源吧失效::http://99zyba.com\n\n\n\t丝袜资源失效::http://siwazyw.net\n\n\n\t浪潮资源失效::http://langchaozy6.com\n\n\n\tCK资源失效::http://www.feifei67.com\n\n\n\t大雕资源失效::http://www.dd-01.com\n\n\n\t银龙资源失效::https://yinlong.tv\n\n\n\t苍天资源失效::http://cj.cangtiancj.com\n\n\n\t骚色资源失效::http://api.saosezy.icu\n\n\n\t芒果资源失效::https://mgzyz1.com\n\n\n\t酷豆资源失效::https://kudouzy.com\n\n\n\t酷伦理资源失效::https://api.kudian70.com\n\n\n\t速播资源失效::https://api.suboapi.com\n\n\n\t国产精品::https://zy.difi.life\n\n\n\t痴汉队长失效::https://javcaptain.com\n\n\n\t秀色资源失效::https://api.xiuseapi.com\n\n\n\t苹果资源失效::https://www.pg111222.com\n\n\n\t茄子资源失效::http://www.qiezizy8.com\n\n\n\t辣椒资源失效::https://www.lajiaozy18.com\n\n\n\t花椒资源失效::https://apihjzy.com/api.php/provide/vod/?ac=list\n\t\tps：网站无法打开，json链接可以\n\n\n\t桃色资源失效::https://api.taoseapi.com/api.php/provide/vod/?ac=list\n\t\tps：网站无法打开，json链接可以\n\n\n\t乐播资源::https://lbapi9.com/api.php/provide/vod/?ac=list\n\t\tps：网站无法打开，json链接可以\n\n\n\t佳丽资源失效::https://jializyzapi.com/api.php/provide/vod/?ac=list\n\t\tps：网站无法打开，json链接可以\n\n\n\t番号资源::http://fhapi9.com/api.php/provide/vod/?ac=list\n\t\tps：网站无法打开，json链接可以\n\n\n\tx8优酷失效::https://gov.gooder.bar\n\t\tps：没有vod格式？\n\n\n\t土狗采集失效::http://vip-04.tgzy.cc\n\t\tpa：vod格式好像是音乐？\n\n\n\n☆使用【vod】和【art】两种链接的正文规则参考\n<br><h3>{{$.list..vod_name||$.list..art_name}}</h3>\n<h6>[{{$.list..type_name}}]<b>发布于 {{$.list..vod_time||$.list..art_time}}</b></h6>\n\n<video src=\"{{$.list..vod_play_url ##^.*?\\$}}\" poster=\"{{$.list..vod_pic}}\" controls>视频加载失败</video>\n\n<div id=\"TúPiàn\">\n{{$.list..art_content ##</?(br|p)>}}\n</div>\n<link rel=\"stylesheet\" href=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.2/viewer.min.css\">\n<script src=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.2/viewer.min.js\"></script>\n<script>\n  new Viewer(\n    document.getElementById(\"TúPiàn\")    ,{\n//设置图片地址来源\n    url: 'src',\n//是否显示图片标题(true/false)\n    title: false,\n//设置播放间隔(单位毫秒，1秒=1000毫秒)\n    interval: 3000\n    }\n  );\n</script>\n\n@js:\nif(baseUrl.match(/art/)){\n\tresult.replace(/<vid[\\s\\S]+deo>/,'')\n}else{\n\tresult.replace(/<div[\\s\\S]+ipt>/,'')\n}",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "不错",
    "sourceUrl": "https://slapibf.com/api.php/provide/vod/?ac=list",
    "style": "h3{text-align:center}\nh6{margin-bottom:0}\nb{float:right}\n\nvideo{width:100%;max-height:285px;border-radius:5px}"
  },
  {
    "articleStyle": 0,
    "customOrder": 4738,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "ul@li",
    "ruleContent": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<title>内容提取</title>\n<!-- v2025.05.10 -->\n\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<script src=\"https://code.jquery.com/jquery-3.6.0.min.js\"></script>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.css\" />\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.11.3/viewer.min.js\"></script>\n<style>\n    body { font-family: Arial, sans-serif; font-size: 16px; }\n    #title, #page, #loading-status { margin: 0 auto; font-size: 20px; text-align: center; }\n    #description, #urls, #video-url, #video-sources, #messages { width: 100%; max-width: 800px; margin: 1.5px auto; font-size: 14px; text-align: left; word-wrap: break-word; white-space: pre-wrap; }\n    #text, #text :not(img), #text img + * { text-indent: 2em; width: 100%; font-size: 16px; line-height: 1.5em; margin-top: 0; margin-bottom: 0; word-wrap: break-word; white-space: pre-wrap; }\n    img, #text img { width: 100%; height: auto; display: block; margin-bottom: 1.5px; }\n    .flex-container { display: flex; justify-content: center; align-items: center; gap: 10px; margin: 1.5px 0; font-size: 14px; }\n    button, select { flex: 1 1 31%; padding: 3px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; cursor: pointer; background-color: #f9f9f9; transition: background-color 0.3s ease; margin: 1.5px; min-width: 0; font-size: 14px; }\n    #url-select, #video-source-select { flex: 1 1 100%; margin-left: 0; margin-right: 0; text-align: center; }\n    #video-element { width: 100%; height: auto; }\n    textarea { width: 100%; height: auto; min-height: 100px; box-sizing: border-box; resize: vertical; }\n    .error, .warn { color: red; }\n</style>\n</head>\n<body>\n    <h3 id=\"title\">{{@@title@text||h1.0@text||h2.0@text||.title.0@text}}</h3>\n    <p id=\"description\">{{@@.info.0@html||.jianjie@html}}</p>\n    <p id=\"page\" style=\"display:none;\">共<span id=\"total-pages\">1</span>页</p>\n    <p id=\"loading-status\" style=\"display:none;\"></p>\n\n    <div class=\"flex-container\" id=\"loading-buttons\" style=\"display:none;\">\n        <button id=\"prev-page-btn\">上一页</button>\n        <button id=\"next-page-btn\">下一页</button>\n        <button id=\"auto-load-btn\">自&nbsp;&nbsp;动</button>\n    </div>\n    \n    <div class=\"flex-container\">\n        <select id=\"url-select\" style=\"display:none;\"></select>\n    </div>\n    \n    <div class=\"flex-container\">\n        <button id=\"toggle-urls-btn\">显/隐网址</button>\n        <button id=\"toggle-messages-btn\">显/隐信息</button>\n        <button id=\"toggle-debug-btn\">显/隐调试</button>\n    </div>\n    <div id=\"urls\"></div>\n    <div id=\"messages\"></div>\n    <div id=\"debug-info\"></div>\n    <div id=\"video-url\"></div>\n    <div id=\"video-container\" style=\"display: none;\">\n        <video id=\"video-element\" controls preload=\"auto\" width=\"640\" height=\"264\">\n            <source id=\"video-source\" src=\"\" type=\"\">您的浏览器不支持 video 标签。\n        </video>\n    </div>\n    <div class=\"flex-container\" id=\"video-source-container\" style=\"display: none;\">\n        <select id=\"video-source-select\" onchange=\"updateVideoSource()\"></select>\n    </div>\n    <div id=\"images\"></div>\n    <div id=\"text\"></div>\n\n    <script>\n        // 配置对象，包含各种选择器、延迟时间等配置项\n        const config = {    \n            videoSelector: 'body', // 视频选择器\n            imgSelector: '.gridlane-box-inside img,.photos figure img,.content p img', // 图片选择器\n            textSelector: '#content', // 文本选择器\n            debugSelector: '#content, .page, .pager, .content, script', // 调试信息选择器\n            swapImageAttributes: false, // 是否交换图片属性\n            delayTime: 1500, // 延迟提取时间\n            retryDelayTime: 1500, // 重试加载延迟时间\n            maxLoadAttempts: 3, // 最大加载次数\n            autoLoading: false, // true自动模式，false单页模式\n            debugOnce: 0, // 只在特定索引输出一次调试信息\n            totalPagesText: '{{@@.page.0@a.-2@textNodes}}', // 总页码\n            urlSuffixToRemove: /\\.html$/, // 移除url后缀\n            pageUrlText: '{urlPrefix}_{i}.html', // 拼接URL模板        \n            ListMode: true, // true网址列表模式，false网址拼接模式    \n            initialUrls: `{{@@#sort-item-5.0@a@href}}`, // 网址\n            initialUrlsName: `{{@@#sort-item-5.0@a@span@text}}`, // 网址名称\n            sourceurl: '', // 来源URL前缀\n        };\n\n        let videoSources = []; // 存储视频源数组\n        let loadAttempts = {}; // 记录每个URL的加载尝试次数\n        let urls = []; // 存储所有页面的URL\n        let imageBox;\n        let textBox;\n        let currentPageIndex = 0; // 当前页面索引\n        let canLoadNextPage = true; // 控制是否可以加载下一页\n        let autoLoadInProgress = false; // 自动加载状态\n\n        // 构建URL列表\n        function buildUrls(totalPages, baseUrl) {\n            let initialUrlsArray = config.initialUrls.trim().split('\\n').filter(url => url.trim() !== '');\n            let initialUrlsNameArray = config.initialUrlsName.trim().split('\\n').filter(name => name.trim() !== '');\n\n            if (config.ListMode && initialUrlsArray.length > 0) {\n                if (initialUrlsArray.length !== initialUrlsNameArray.length) {\n                    $('#messages').append(`<span class=\"warn\">警告：initialUrls 和 initialUrlsName 的长度不匹配。</span><br>`);\n                }\n\n                urls = initialUrlsArray.map(url => {\n                    if (config.sourceurl && url.startsWith('/') && !/^https?:\\/\\//i.test(url)) {\n                        return config.sourceurl.replace(/\\/$/, '') + url;\n                    } else {\n                        return url;\n                    }\n                });\n\n                urls.forEach((url, index) => {\n                    const name = initialUrlsNameArray[index] || `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            } else {\n                if (totalPages === 1) {\n                    urls.push(baseUrl);\n                } else {\n                    urls.push(baseUrl);\n                    for (let i = 2; i <= totalPages; i++) {\n                        urls.push(config.pageUrlText.replace('{urlPrefix}', baseUrl.replace(config.urlSuffixToRemove, '').replace(/\\/$/, '')).replace('{i}', i));\n                    }\n                }\n\n                urls.forEach((url, index) => {\n                    const name = `第 ${index + 1} 页`;\n                    $('#url-select').append(`<option value=\"${index}\">${name}</option>`);\n                    $('#urls').append(`<div>${name}: ${url}</div>`);\n                });\n            }\n\n            $('#total-pages').text(urls.length);\n            toggleNavigationButtons();\n            toggleTotalPagesDisplay();\n        }\n\n        // 规范化URL\n        function normalizeUrl(url) {\n            if (typeof url !== 'string' || !url.trim()) {\n                return '';\n            }\n            const match = url.match(/['\"](.*?)['\"]/);\n            if (match && match[1]) {\n                url = match[1];\n            }\n\n            function processUrl(str) {\n                str = str.trim();\n                str = str.replace(/\\\\u[\\dA-F]{4}/gi, match => String.fromCharCode(parseInt(match.replace(/\\\\u/g, ''), 16)));\n                str = decodeURIComponent(str);\n                str = str.replace(/^http:\\/([^/])/, 'http://$1');\n                str = str.replace(/^https:\\/([^/])/, 'https://$1');\n                return str;\n            }\n            return processUrl(url);\n        }\n\n        // 清空容器内容\n        function clearContainers() {\n            $('#messages').empty();\n            $('#images').empty();\n            $('#text').empty();\n        }\n\n        // 更新图像源\n        function updateImageSrc(elements, shouldSwap) {\n            elements.each(function () {\n                const $this = $(this);\n                const attrsToUpdate = {};\n                if (shouldSwap) {\n                    ['data-original', 'data-src', 'data-url'].forEach(attr => {\n                        if ($this.attr(attr)) {\n                            attrsToUpdate['src'] = $this.attr(attr);\n                        }\n                    });\n                }\n                $this.attr(attrsToUpdate);\n            });\n            return elements;\n        }\n\n        // 切换导航按钮显示状态\n        function toggleNavigationButtons() {\n            if ($('#url-select option').length > 1 && !config.autoLoading) {\n                $('#loading-buttons').show();\n                $('#url-select').show();\n            } else {\n                $('#loading-buttons').hide();\n                $('#url-select').hide();\n            }\n        }\n\n        // 显示加载状态\n        function showLoadingStatus(pageNumber) {\n            const selectedOption = $('#url-select option:selected').text();\n            $('#loading-status').text(`正在加载：${selectedOption}`).show();\n        }\n\n        // 隐藏加载状态\n        function hideLoadingStatus() {\n            $('#loading-status').hide();\n        }\n\n        // 加载指定索引的内容\n        function loadContent(index) {\n            if (index < 0 || index >= urls.length || !canLoadNextPage) return;\n            canLoadNextPage = false;\n            currentPageIndex = index;\n            $('#url-select').val(index);\n            $('#messages').append(`<div>当前地址: <span class=\"warn\">${urls[index]}</span></div>`);\n            if (autoLoadInProgress) {\n                showLoadingStatus(index + 1);\n            }\n            $.ajax({\n                url: urls[index],\n                type: 'GET',\n                success: function (data) {\n                    try {\n                    const $data = $(data);\n                    let updatedHtmlContent = data.replace(/(['\"])(\\/\\/)(?!\\/)/g, '$1https://')\n                        .replace(/src=\"upload/gi, 'src=\"/upload')\n                        .replace(/style=[\"'][^'\"]+[\"']/gi, '')\n                        .replace(/\\\\\\//g, '/');\n                    const parser = new DOMParser();\n                    const doc = parser.parseFromString(updatedHtmlContent, \"text/html\");\n\n                    if (config.debugOnce === index) {\n                        const debugElements = $(doc).find(config.debugSelector);\n                        if (debugElements.length > 0) {\n                            const debugContents = $('<pre>').html(debugElements.clone().wrapAll('<div/>').parent().html()).html();\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">${debugContents}</textarea></span>`);\n                        } else {\n                            $('#debug-info').html(`<span class=\"warn\">调试信息: <textarea rows=\"10\" cols=\"80\">调试信息未提取到内容，请检查选择器！</textarea></span>`);\n                        }\n                    }\n                    // 方法1：提取视频\n                    const videoSources1 = [];\n                    const videoContents = $(doc).find(config.videoSelector);\n                    const videoTags = $(videoContents).find('video, source');\n                    videoTags.each(function() {\n                        const videosrc = $(this).attr('src') || \n                                     $(this).attr('data-src') || \n                                     $(this).attr('data-original') || '';\n                        \n                        if (videosrc) {\n                            videoSources1.push(videosrc);\n                        }\n                    });\n                    //反馈\n                    if (videoSources1.length > 0) {\n                        $('#messages').append(`<span>方法1，找到 ${videoSources1.length} 个视频。</span><br>`);\n                    }\n\n                    // 方法2：正则提取视频\n                    const regex = /['\"]https?[^'<>\"]+(m3u8|mp4|webm|ogg|flv|mp3|m4a|wav|ape|flac)([^'<>\"]+)?['\"]/gi;\n                    const matches = data.match(regex);\n                    const videoSources2 = [];\n\n                    if (matches) {\n                        const uniqueMatches = [...new Set(matches)];\n                    \n                        uniqueMatches.forEach(match => {\n                            const normalizedSrc = normalizeUrl(match.replace(/['\"]/g, ''));\n                            videoSources2.push(normalizedSrc);\n                        });\n                    }\n                    //反馈\n                    if (videoSources2.length > 0) {\n                        $('#messages').append(`<span>方法2，找到 ${videoSources2.length} 个视频。</span><br>`);\n                    }\n\n                    // 合并两种方法的结果\n                    videoSources = [...videoSources1, ...videoSources2];\n\n                    // 去重并标准化 URL\n                    const imageExtensions = /\\.(jpg|jpeg|png|gif|bmp|svg)$/i;\n\n                    videoSources = videoSources\n                                  .map(src => normalizeUrl(src.replace(/\\\\+/g, '')))\n                                  .filter(src => src) // 过滤空值\n                                  .filter(src => !imageExtensions.test(src)); // 移除图片地址\n                        \n                    videoSources = [...new Set(videoSources)];// 去重\n\n                    // 显示最终结果\n                    $('#messages').append(`<span>总共找到 ${videoSources.length} 个视频。</span><br>`);\n\n                    if (videoSources.length > 0) {\n                        $('#messages').append(`<span>成功提取到视频，找到 ${videoSources.length} 个视频。</span><br>`);\n                        videoSources.forEach((src, idx) => {\n                            $('#messages').append(`<div>视频地址:<span class=\"warn\"> ${src}</span><br></div>`);\n                            $('#video-source-select').append(`<option value=\"${idx}\">视频源 ${idx + 1}</option>`);\n                        });\n                    \n                        if (videoSources.length == 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').hide();\n                            updateVideoSource();\n                        } else if (videoSources.length > 1) {\n                            $('#video-container').show();\n                            $('#video-url').show();\n                            $('#video-source-container').show();\n                            updateVideoSource();\n                        } else {\n                            $('#video-container').hide();\n                            $('#video-url').hide();\n                            $('#video-source-container').hide();\n                        }\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未找到视频源。</span><br>`);\n                        $('#video-container').hide();\n                        $('#video-url').hide();\n                        $('#video-source-container').hide();\n                    }\n\n                    //提取图片\n                    const $imgContents = $(doc).find(config.imgSelector);\n                    const shouldSwap = config.swapImageAttributes;\n                    const newContents = updateImageSrc($imgContents.clone(), shouldSwap);\n                    $('#images').append(newContents).show();\n                    if (newContents.length > 0) {\n                        $('#messages').append(`<span>成功提取图片，共 ${newContents.length} 张。</span><br>`);\n                        newContents.each(function () {\n                            const imgSrc = $(this).attr('src') || $(this).attr('data-original') || $(this).attr('data-src') || $(this).attr('data-url');\n                            $('#messages').append(`<div>地址:<span class=\"warn\"> ${imgSrc}</span><br></div>`);\n                        });\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图片。</span><br>`);\n                    }\n\n                    //提取图片和文本\n                    const textContents = $(doc).find(config.textSelector).map(function () {\n                        const $currentContents = $(this);\n                        $currentContents.find('img + br, script, video, source, iframe').remove();\n                        $currentContents.html($currentContents.html().replace(/>\\s+/gi, '>').replace(/<\\/?br\\s*([^>]*)\\s*\\/?>/gi, '\\n').replace(/\\n+/g, '\\n'));\n                        return $currentContents.html();\n                    }).get().join('');\n                    if (textContents.trim()) {\n                        $('#text').append(`<span>${textContents}</span><br>`).show();\n                        $('#messages').append(`<span>成功提取图文。</span><br>`);\n                    } else {\n                        $('#messages').append(`<span class=\"warn\">未提取到图文。</span><br>`);\n                    }\n\n                    if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                        setTimeout(() => { \n                            canLoadNextPage = true;\n                            loadContent(currentPageIndex + 1); \n                        }, config.delayTime);\n                    } else {\n                        canLoadNextPage = true;\n                        if (autoLoadInProgress) {\n                            hideLoadingStatus();\n                        }\n                    }\n                } catch (parseError) {\n                    $('#messages').append(`<span class=\"error\">解析页面内容时发生错误: ${parseError.message}</span><br>`);\n                    handleLoadFailure(urls, index);\n                } finally {\n                    if (imageBox) imageBox.viewer.update();\n                    if (textBox) textBox.viewer.update();\n                }\n            },\n            error: function (jqXHR, textStatus, errorThrown) {\n                let errorMessage = `内容加载失败: ${urls[index]}`;\n                switch (textStatus) {\n                    case 'timeout':\n                        errorMessage += ', 请求超时';\n                        break;\n                    case 'abort':\n                        errorMessage += ', 请求被取消';\n                        break;\n                    case 'parsererror':\n                        errorMessage += ', 解析响应出错';\n                        break;\n                    default:\n                        errorMessage += `, 状态码: ${jqXHR.status}, 错误信息: ${errorThrown}`;\n                        break;\n                }\n                $('#messages').append(`<span class=\"error\">${errorMessage}</span><br>`);\n                handleLoadFailure(urls, index);\n                }\n            });\n        }\n\n        // 处理加载失败的情况\n        function handleLoadFailure(urls, index) {\n            if (!loadAttempts[urls[index]]) {\n                loadAttempts[urls[index]] = 1;\n            } else {\n                loadAttempts[urls[index]]++;\n            }\n            if (loadAttempts[urls[index]] <= config.maxLoadAttempts) {\n                const retryMessage = `第${index + 1}页加载失败，正在进行第${loadAttempts[urls[index]]}次加载！`;\n                $('#messages').append(`<span class=\"error\">${retryMessage}</span><br>`);\n                setTimeout(() => { \n                    canLoadNextPage = true;\n                    loadContent(index); \n                }, config.retryDelayTime);\n            } else {\n                const finalErrorMessage = `第${index + 1}页加载失败，已达到最大尝试次数(${config.maxLoadAttempts})！`;\n                $('#messages').append(`<span class=\"error\">${finalErrorMessage}</span><br>`);\n                if (autoLoadInProgress && currentPageIndex < urls.length - 1) {\n                    setTimeout(() => { \n                        canLoadNextPage = true;\n                        loadContent(currentPageIndex + 1); \n                    }, config.delayTime);\n                } else {\n                    canLoadNextPage = true;\n                    if (autoLoadInProgress) {\n                        hideLoadingStatus();\n                    }\n                }\n            }\n        }\n\n        // 更新视频源\n        function updateVideoSource() {\n            const selectedIndex = parseInt(document.getElementById('video-source-select').value);\n            if (isNaN(selectedIndex) || !videoSources[selectedIndex]) {\n                $('#messages').append(`<span class=\"warn\">未找到有效的视频源。</span><br>`);\n                console.warn(\"Invalid or undefined video source:\", selectedIndex, videoSources);\n                return;\n            }\n\n            const selectedSource = videoSources[selectedIndex];\n            document.getElementById('video-url').textContent = `视频地址:\\n ${selectedSource}`;\n\n            const videoSourceElement = document.getElementById('video-source');\n            videoSourceElement.src = selectedSource;\n\n            const videoElement = document.getElementById('video-element');\n            videoElement.load();\n\n            $('#messages').append(`<span>更新视频源为: ${selectedSource}</span><br>`);\n            console.log(\"Updated video source to:\", selectedSource);\n        }\n\n        // 切换总页数显示状态\n        function toggleTotalPagesDisplay() {\n            if (urls.length > 1) {\n                $('#page').show();\n            } else {\n                $('#page').hide();\n            }\n        }\n\n        // 页面加载完成后执行的主要逻辑\n        $(document).ready(function () {\n            imageBox = document.getElementById('images');\n            textBox = document.getElementById('text');\n            if (imageBox && textBox) {\n                new Viewer(imageBox, { title: true, interval: 2000 });\n                new Viewer(textBox, { title: true, interval: 2000 });\n            }\n\n            const totalPagesText = config.totalPagesText;\n            const totalPages = parseInt(totalPagesText, 10) || 1;\n            const baseUrl = '{{baseUrl}}';\n\n            clearContainers();\n            $('#urls, #debug-info textarea, #video-url, #video-source-select').empty();\n            $('#urls, #messages, #debug-info, #video-url, #video-container, #video-source-container, #images, #text').hide();\n\n            buildUrls(totalPages, baseUrl);\n\n            const urlSelect = document.getElementById('url-select');\n            if (urlSelect.options.length > 0) {\n                urlSelect.value = '0'; \n\n                if (config.autoLoading) {\n                    autoLoadInProgress = true;\n                    for (let i = 0; i < urls.length; i++) {\n                        loadContent(i);\n                    }\n                } else {\n                    loadContent(0);\n                }\n            } else {\n                loadContent(0);\n            }\n\n            $('#url-select').change(function () {\n                clearContainers();\n                const selectedIndex = parseInt($(this).val());\n                loadContent(selectedIndex);\n            });\n            $('#prev-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex > 0) {\n                    loadContent(currentPageIndex - 1);\n                }\n            });\n            $('#next-page-btn').click(function () {\n                clearContainers();\n                if (currentPageIndex < urls.length - 1) {\n                    loadContent(currentPageIndex + 1);\n                }\n            });\n            $('#auto-load-btn').click(function () {\n                autoLoadInProgress = true;\n                showLoadingStatus(1); \n                for (let i = currentPageIndex + 1; i < urls.length; i++) {\n                    loadContent(i);\n                }\n            });\n            $('#toggle-messages-btn').click(function () { $('#messages').toggle(); });\n            $('#toggle-urls-btn').click(function () { $('#urls').toggle(); });\n            $('#toggle-debug-btn').click(function () { $('#debug-info').toggle(); });\n        });\n    </script>\n</body>\n</html>",
    "ruleImage": "a@data-original",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page||text.下一页@href",
    "rulePubDate": "[class=\"pic-text text-right\"]@text",
    "ruleTitle": "h4@text",
    "singleUrl": false,
    "sortUrl": "搜索🔍::/jiejie/index.php/vod/search.html?wd={{source.getVariable()}}\n黄瓜资源::/jiejie/index.php/vod/type/id/87.html\n155资源::/jiejie/index.php/vod/type/id/248.html\n森林资源::/jiejie/index.php/vod/type/id/117.html\n奥斯卡资源::/jiejie/index.php/vod/type/id/86.html\n百万资源::/jiejie/index.php/vod/type/id/237.html\n制服诱惑::/jiejie/index.php/vod/show/id/251.html\n中文字幕::/jiejie/index.php/vod/show/id/254.html\n美乳巨乳::/jiejie/index.php/vod/show/id/262.html\n熟女人妻::/jiejie/index.php/vod/show/id/259.html\n萝莉少女::/jiejie/index.php/vod/show/id/260.html\n强奸乱伦::/jiejie/index.php/vod/show/id/263.html\n无码专区::/jiejie/index.php/vod/show/id/249.html",
    "sourceComment": "jiejiesp.xyz",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "姐姐",
    "sourceUrl": "https://wap.jiejiesp27.xyz/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4739,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "<js>\nheaders={\n    \"User-Agent\": \"Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36 EdgA/127.0.0.0\",\n\"Cache-Control\": \"no-cache\",\n    \"Referer\": String(source.getKey()).replace(/(.*\\/\\/[a-z0-9.-]+).*/, '$1')\n}\nJSON.stringify(headers);\n</js>",
    "injectJs": "function setupCustomPlayer(video) {\n  // 手势滑动快进\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  \n  // 长按加速相关变量\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n\n  // 触摸事件处理\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    \n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n\n  // 添加触摸事件监听\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  \n  // 初始播放速度\n  video.playbackRate = NORMAL_SPEED;\n\n  // 创建按钮的通用函数\n  function createButton(text, onClick, position, width = '20px', top = '50%', fontSize = '16px') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = top;\n    button.style.transform = top === '50%' ? 'translateY(-50%)' : 'none';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.style.fontSize = fontSize; // 添加字体大小设置\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n\n  // 旋转按钮（右侧上方） \n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    \n    // 保留当前的缩放比例和反转状态\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    // 获取当前反转状态\n    const isFlipped = video.getAttribute('data-flipped') === 'true';\n    const flipValue = isFlipped ? -1 : 1;\n    \n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale}) scaleX(${flipValue})`;\n  }, { horizontal: 'right' }, '20px', 'calc(50% - 20px)');\n\n  // 播放/暂停按钮（右侧下方）\n  let isPlaying = !video.paused;\n  const playPauseBtn = createButton(\n    isPlaying ? '❚❚' : '▶',\n    () => {\n      if (video.paused) {\n        video.play();\n        playPauseBtn.textContent = '❚❚';\n      } else {\n        video.pause();\n        playPauseBtn.textContent = '▶';\n      }\n    },\n    { horizontal: 'right' },\n    '22px',\n    'calc(50% + 20px)',\n    '10px' // 单独设置字体大小\n  );\n\n  // 监听视频的播放状态变化\n  video.addEventListener('play', () => {\n    playPauseBtn.textContent = '❚❚';\n    isPlaying = true;\n  });\n\n  video.addEventListener('pause', () => {\n    playPauseBtn.textContent = '▶';\n    isPlaying = false;\n  });\n\n  // 缩放按钮（左侧上方）\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    \n    // 获取当前缩放比例和反转状态\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    // 获取当前反转状态\n    const isFlipped = video.getAttribute('data-flipped') === 'true';\n    const flipValue = isFlipped ? -1 : 1;\n    \n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale}) scaleX(${flipValue})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1) scaleX(${flipValue})`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' }, '20px', 'calc(50% - 20px)');\n\n  // 反转按钮（左侧下方）\n  const flipBtn = createButton('⇄', () => {\n    const isFlipped = video.getAttribute('data-flipped') === 'true';\n    const newFlipState = !isFlipped;\n    video.setAttribute('data-flipped', newFlipState);\n    \n    // 保留当前的旋转和缩放比例\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    const flipValue = newFlipState ? -1 : 1;\n    video.style.transform = `rotate(${currentRotation}deg) scale(${currentScale}) scaleX(${flipValue})`;\n  }, { horizontal: 'left' }, '20px', 'calc(50% + 20px)', '10px'); // 单独设置字体大小\n\n  // 快速跳转按钮（底部中央）\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  \n  // 按钮配置\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    // 快速跳转按钮使用默认字体大小\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n video.parentNode.appendChild(buttonContainer);\n\n// 跳过片头功能\n  video.addEventListener('timeupdate', () => {\n    if (video.currentTime < 10) {\n      video.currentTime = 10;\n    }\n  });\n}\n\n// 修改初始化逻辑，增加重试机制\nfunction initPlayerWithRetry() {\n  const maxRetries = 10;\n  const retryInterval = 500;\n  let retries = 0;\n  const tryInit = () => {\n    const video = document.getElementById('video');\n    if (video) {\n      setupCustomPlayer(video);\n    } else if (retries < maxRetries) {\n      retries++;\n      setTimeout(tryInit, retryInterval);\n    }\n  };\n  tryInit();\n}\n// 使用重试机制初始化播放器\ninitPlayerWithRetry();",
    "lastUpdateTime": 1770070818566,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.data.list",
    "ruleContent": "{{$.data.movie_m3u8_url..url}}\n@js:\nresult=decodeURIComponent(result);\nresult=result.replace(/\\\\/g,'');\nresult=`\n<html>  \n<head>  \n<meta charset=\"utf-8\">  \n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\">\n<meta name=\"referrer\" content=\"never\"/>\n<style>html,body{text-align:center;margin:0;padding:0;width:100%;overflow: hidden;}</style>\n</head>  \n<body>  \n<div class=\"container\"><div  class=\"title\">{{$.data.movie_name}}</div>\n<video id=\"video\" width=\"100%\" height=\"91%\" poster=\"{{$.data.movie_cover}}\"  controls autoplay muted loop>  \n    <source src=\"${result}\" type=\"application/x-mpegURL\">    \n</video></div>\n</body>  \n</html>\n`;",
    "ruleImage": "$.movie_cover",
    "ruleLink": "/api/Webapi_v1/Resource/movieInfo?movie_id={{$.movie_id}}",
    "ruleNextPage": "page",
    "rulePubDate": "{{$.movie_cover##/(20.*)/.*/##$1##}} ⏱️{{$.movie_long}}",
    "ruleTitle": "@js:\nif (\"{{$.need_vip}}\"==\"0\"){result=\"{{$.movie_name##.*屎.*|.*Ts.*|.*TS.*|.*ts.*|.*伪娘.*|.*无法抑制的热情.*}}\"}else{result=\"\"}",
    "singleUrl": false,
    "sortUrl": "\n主播随机::/api/Webapi_v1/Resource/movieList?page={{ Math.ceil(Math.random()*380) }}&num=20&sort=1&label_ids[0]=5\n\n最新::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1\n\n🔎搜索::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&search={{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('奸');source.getVariable()}}\n\n自拍::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=2\n主播::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=5\n中字::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=20\nAV::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=25\n国产::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=26\n网红::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=21\n麻豆::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=22\n偷拍::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=23\n探花::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=24\n欧美::/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=6\n动漫:/api/Webapi_v1/Resource/movieList?page={{page}}&num=20&sort=1&label_ids[0]=9\n",
    "sourceComment": "http://www.wus82.com/\n备用地址 \nhttps://www.x3o5z.com/\nhttps://www.e2d0m.com/\nhttps://www.m4e0p.com/\nhttps://www.b1b4j.com/\nhttps://www.s1b9k.com/\nhttps://www.w4x5j.com/\nhttps://www.8u0lz.com/\n",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "✿吾色      S",
    "sourceUrl": "https://www.l1m9r.top/",
    "style": ".container {\n    position: relative; \n    height: 100%; \n    overflow: hidden; \n}\n.title {\n    position: absolute; \n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; \n    background: #000; \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; \n    top: -120px; /* 视频上移 */\n    left: 0; \n    width: 100%; \n    height: calc(96% + 120px);  /* 调整高度以适应内容 */\n    object-fit: contain; \n    z-index: 0; \n    controls=\"controls\" autoplay muted; \n} \nvideo::-webkit-media-controls-overlay-play-button {\n    display: none !important;\n}\n"
  },
  {
    "articleStyle": 0,
    "customOrder": 4740,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "{\n    \"User-Agent\": \"Mozilla/5.0 (Linux; Android 13; SM-G998B Build/TP1A.220624.014) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36 SearchCraft/3.9.2\",\n    \"referer\": \"{{baseUrl}}\"\n}",
    "injectJs": "function setupCustomPlayer(video) {\n  // 手势滑动快进\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  \n  // 长按加速相关变量\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n\n  // 触摸事件处理\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    \n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n\n  // 添加触摸事件监听\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  \n  // 初始播放速度\n  video.playbackRate = NORMAL_SPEED;\n\n  // 创建按钮的通用函数\n  function createButton(text, onClick, position, width = '20px') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = '50%';\n    button.style.transform = 'translateY(-50%)';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n\n  // 旋转按钮（右侧）\n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    \n    // 保留当前的缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale})`;\n  }, { horizontal: 'right' });\n\n  // 缩放按钮（左侧）\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    \n    // 获取当前缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1)`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' });\n\n  // 快速跳转按钮（底部中央）\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  \n  // 按钮配置\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n\n  video.parentNode.appendChild(buttonContainer);\n\n// 跳过片头功能\n  video.addEventListener('timeupdate', () => {\n    if (video.currentTime < 5) {\n      video.currentTime = 5;\n    }\n  });\n}\n\n// 修改初始化逻辑，增加重试机制\nfunction initPlayerWithRetry() {\n  const maxRetries = 10;\n  const retryInterval = 500;\n  let retries = 0;\n  const tryInit = () => {\n    const video = document.getElementById('video');\n    if (video) {\n      setupCustomPlayer(video);\n    } else if (retries < maxRetries) {\n      retries++;\n      setTimeout(tryInit, retryInterval);\n    }\n  };\n  tryInit();\n}\n// 使用重试机制初始化播放器\ninitPlayerWithRetry();",
    "lastUpdateTime": 1769953281311,
    "loadWithBaseUrl": true,
    "ruleArticles": ".col-md-6",
    "ruleContent": "@js:\nresult=java.ajax(source.sourceUrl+\"{{@@text.第1集@href##https://.*?/}}\");\nA=result.match(\"https.*\\.(mp4|m3u8)\")[0]\nresult=`\n<html><head><meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\" />\n<meta name=\"referrer\" content=\"never\"/>\n  <style>html, body {text-align: center;margin: 0; padding: 0;width: 100%;overflow: hidden;} </style>\n  <script src=\"https://unpkg.com/hls.js@1.4.3/dist/hls.min.js\"></script>\n</head><body>\n  <div class=\"container\">\n    <div class=\"title\">{{@@h1@text}}</div>\n    <video id=\"video\" width=\"100%\" height=\"91%\" poster=\"${java.get('pic')}\" controls autoplay muted loop></video>\n  </div>\n<script>\nconst v=document.getElementById('video'),s=[\n  \"${A}\",\n  \"\"];\nlet c=0;\nfunction setupCustomControls(e){/* 自定义功能实现 */}\nfunction playNext(){\n  c>=s.length&&(c=0); // 循环重置计数器\n  const u=s[c++];\n  // 检测Hls对象是否存在\n  if (typeof Hls !== 'undefined' && Hls.isSupported()) {\n    const h = new Hls({\n      enableSoftwareAES: true,          // 强制软件解密\n      forceKeyFrameOnDiscontinuity: true // 关键帧恢复\n    });\n    h.loadSource(u);\n    h.attachMedia(v);\n    h.on(Hls.Events.MANIFEST_PARSED,()=>v.play().then(()=>setupCustomControls(v)).catch(console.log));\n    h.on(Hls.Events.ERROR,(_,d)=>d.fatal&&playNext())\n  } else { // Hls加载失败或浏览器原生支持HLS\n    if (v.canPlayType('application/vnd.apple.mpegurl')) {\n      v.src = u;\n      v.onloadedmetadata = () => v.play().then(() => setupCustomControls(v));\n      v.onerror = playNext;\n    } else {\n      // 如果都不支持，尝试直接播放（可能支持MP4等格式）\n      v.src = u;\n      v.onerror = playNext;\n      v.play().then(() => setupCustomControls(v)).catch(playNext);\n    }\n  }\n}playNext();\n</script>\n</body></html>\n`",
    "ruleImage": "https://images.floriscope.io.cloud-ed.fr/?url={{@@a@data-original}}&w=400&h=300&fit=fill\n<js>\njava.put('pic',result)\n</js>",
    "ruleLink": "a@href##https://.*?/",
    "ruleNextPage": "text.下一页@href",
    "rulePubDate": "a@data-original##allimg/(.*)/.*.jpg##$1##||.pic-text@ownText",
    "ruleTitle": "{{@@h4@a@text}}\n<js>\nconst blockKeywords = /屎|TS|伪娘|伪男|人妖|男同|狼狗|奶狗|鲜肉|帅哥|正装|猛1|ZKtop1|体育生|大屌|双性|男男|直男|gv|父子|飞机|撸|女性向|骚0|poop|娘娘腔|变性|TGirls|鸡巴|鸡吧|阴茎|男奴|奴男|同志|苏木|西装|骚受|QS|Peter|摔跤社|基情|天菜|大鸡|肌肉|薄肌|G片|术0|宏翔|男蜜|自制口|威廉|骚男|基友|美男子|鸡儿|口活王子|融化的冰|自己射|運動生|苏婧薇|社畜|纪练深|性别|淋尿|控射|熟女|CD|肥女|老阿姨|排泄|臭脚|大便|马眼|聖水|尸|廁|圣水|豊満|黑妹|黑人女孩|坦克|黑屁股|黑人妹子|黑逼|孕妇|消遣|伦勃朗|拉丁裔|asmr|GOOD|奶奶|老妈|妈妈|母亲|儿子|爸爸|女儿|母子|父女|兄妹|亲姐|亲妹|VR|都丸富美|山本かを|守谷多香子|波多|飯岡|希島|希岛|深田|君島|君岛|田中瞳|向美奈|美原咲|华行香|藤泽丽|Hitomi|美乃雀|若菜奈|水野朝|後藤|明日花|卯水|由爱|JULIA|风间|濑圆|平冈|藤樱|藤泽|蓮実|藤沢麗央|木村玲|SILK|afchina|fway|rebd|mbdd|REBD|FWAY|眼射|水果派|解说|π|偷拍|偸拍|抄底|攝像頭|摄像头|番系列|经典番|里番|老番|国漫|王者|斗罗|穿越|斗破|仙剑|小舞|MMD|實測|女王|AIKA|喝尿|田中|Ｍ男|40岁/i;\nif (blockKeywords.test(result)) {\n  // 如果包含关键词，将标题设为空字符串\n  result = \"\";\n}\njava.put('title',result)\n</js>",
    "singleUrl": false,
    "sortUrl": "随机::/category/{{ [1959, 1960][Math.floor(Math.random()*2)] }}/time-{{ Math.ceil(Math.random()*1000) }}.html\n\n随机:/category/1958/time-{{ Math.ceil(Math.random()*2600) }}.html\n最新::/category.html\n🔎搜索::/search.html?keyword={{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('奸');source.getVariable()}}\n国产::/category/1959.html\n动漫::/category/1962.html\n日韩::/category/1960.html\n欧美::/category/1961.html",
    "sourceComment": "play9115@gmail.com\nhttp://170.178.166.170/\n备用地址  需改内容规则内地址\nhttps://64.32.31.83/\nhttps://64.32.31.84/\nhttps://64.32.31.85/ 到\nhttps://64.32.31.108/\nhttps://64.32.31.117/\nhttps://64.32.31.118/\nhttps://64.32.31.119/\n",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "❀清清草原S",
    "sourceUrl": "https://64.32.31.100/",
    "style": ".container {\n    position: relative; /* 相对定位，用于包含视频 */\n    height: 100%; /* 容器高度与视频原始高度相同 */\n    overflow: hidden; /* 隐藏超出容器的部分 */\n}\n.title {\n    position: absolute; /* 绝对定位，相对于容器 */\n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; /* 确保标题在视频之上 */\n    background: #000; /* 纯黑色背景 */ \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; /* 绝对定位，相对于容器 */ \n    top: -20px; /* 视频上移 */\n    left: 0; \n    width: 100%; \n    height: calc(96% + 20px);  /* 调整高度以适应内容 */\n    object-fit: contain; /* 确保视频内容不被裁剪 */\n    z-index: 0; /* 确保视频在标题之下 */\n    controls=\"controls\" autoplay muted; \n} \n"
  },
  {
    "articleStyle": 0,
    "contentBlacklist": "https://pc.stgowan.com/,\nhttps://dmku.mhtjx.top/,\nhttps://dmku.m3u8.pw/,\nhttps://dm.bbj.icu/,\nhttps://www.superplayer.top/index.php/index/dm",
    "coverDecodeJs": "function toByteArray(input) {\n  var out = new Packages.java.io.ByteArrayOutputStream();\n  var buffer = java.strToBytes('\\0'.repeat(4096));\n  var bytesRead;\n  while ((bytesRead = input.read(buffer)) != -1) {\n    out.write(buffer, 0, bytesRead);\n  }\n  return out.toByteArray();\n}\n\n(function() {\n  // 1. 读取原始字节内容\n  var textBytes = toByteArray(result);\n  // 2. 如果是GIF文件，直接返回原始字节\n  if (src.endsWith('.gif')) {\n    return textBytes;\n  }\n  try {\n    // 3. 将字节转换为字符串（用于解析数据URI）\n    var dataUri = java.bytesToStr(textBytes, \"UTF-8\");\n    // 4. 判断是完整的数据URI还是纯Base64数据\n    var base64Prefix = \"base64,\";\n    var base64Index = dataUri.indexOf(base64Prefix);\n    if (base64Index === -1) {\n      // 如果没有找到base64前缀，检查是否需要截取第一个/及之后的内容\n      var firstSlashIndex = dataUri.indexOf('/');\n      if (firstSlashIndex !== -1) {\n        // 如果找到第一个/，截取/及之后的内容\n        dataUri = dataUri.substring(firstSlashIndex);\n      }\n      // 对整个内容进行Base64解码\n      return java.base64DecodeToByteArray(dataUri);\n    } else {\n      // 如果是标准data URI，提取base64编码部分解码\n      var base64Data = dataUri.substring(base64Index + base64Prefix.length);\n      return java.base64DecodeToByteArray(base64Data);\n    }\n  } catch (e) {\n    // 解码失败时返回原始字节\n    return textBytes;\n  }\n})();",
    "customOrder": 4741,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n\t\"User-Agent\":\"Mozilla/5.0 (Linux; U; Android 10; zh-cn; MI CC 11)  AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/18.1.8 swan-mibrowser\",\n\t\"referer\": \"{{baseUrl}}\"\n}",
    "injectJs": "function setupCustomPlayer(video) {\n  // 手势滑动快进\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  \n  // 长按加速相关变量\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n\n  // 触摸事件处理\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    \n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n\n  // 添加触摸事件监听\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  \n  // 初始播放速度\n  video.playbackRate = NORMAL_SPEED;\n\n  // 创建按钮的通用函数\n  function createButton(text, onClick, position, width = '20px') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = '50%';\n    button.style.transform = 'translateY(-50%)';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n\n  // 旋转按钮（右侧）\n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    \n    // 保留当前的缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale})`;\n  }, { horizontal: 'right' });\n\n  // 缩放按钮（左侧）\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    \n    // 获取当前缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1)`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' });\n\n  // 快速跳转按钮（底部中央）\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  \n  // 按钮配置\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n\n  video.parentNode.appendChild(buttonContainer);\n}\n\n// 修改初始化逻辑，增加重试机制\nfunction initPlayerWithRetry() {\n  const maxRetries = 10;\n  const retryInterval = 500;\n  let retries = 0;\n  const tryInit = () => {\n    const video = document.getElementById('video');\n    if (video) {\n      setupCustomPlayer(video);\n    } else if (retries < maxRetries) {\n      retries++;\n      setTimeout(tryInit, retryInterval);\n    }\n  };\n  tryInit();\n}\n// 使用重试机制初始化播放器\ninitPlayerWithRetry();",
    "lastUpdateTime": 1769952820089,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.rescont.data",
    "ruleContent": "<html><head><meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\" />\n<meta name=\"referrer\" content=\"never\"/>\n  <style>html, body {text-align: center;margin: 0; padding: 0;width: 100%;overflow: hidden;} </style>\n  <script src=\"https://unpkg.com/hls.js@1.4.3/dist/hls.min.js\"></script>\n</head><body>\n  <div class=\"container\">\n    <div class=\"title\">{{$.rescont.title}}</div>\n    <video id=\"video\" width=\"100%\" height=\"91%\" poster=\"\" controls autoplay muted loop></video>\n  </div>\n<script>\nconst v=document.getElementById('video'),s=[\n  \"{{$.rescont.videopath}}\",\n  \"\"];\nlet c=0;\nfunction setupCustomControls(e){/* 自定义功能实现 */}\nfunction playNext(){\n  c>=s.length&&(c=0); // 循环重置计数器\n  const u=s[c++];\n  // 检测Hls对象是否存在\n  if (typeof Hls !== 'undefined' && Hls.isSupported()) {\n    const h = new Hls({\n      enableSoftwareAES: true,          // 强制软件解密\n      forceKeyFrameOnDiscontinuity: true // 关键帧恢复\n    });\n    h.loadSource(u);\n    h.attachMedia(v);\n    h.on(Hls.Events.MANIFEST_PARSED,()=>v.play().then(()=>setupCustomControls(v)).catch(console.log));\n    h.on(Hls.Events.ERROR,(_,d)=>d.fatal&&playNext())\n  } else { // Hls加载失败或浏览器原生支持HLS\n    if (v.canPlayType('application/vnd.apple.mpegurl')) {\n      v.src = u;\n      v.onloadedmetadata = () => v.play().then(() => setupCustomControls(v));\n      v.onerror = playNext;\n    } else {\n      // 如果都不支持，尝试直接播放（可能支持MP4等格式）\n      v.src = u;\n      v.onerror = playNext;\n      v.play().then(() => setupCustomControls(v)).catch(playNext);\n    }\n  }\n}playNext();\n</script>\n</body></html>",
    "ruleImage": "{{$.coverbase64.url}}",
    "ruleLink": "/api/videoplay/{{$.id}}?uuid=1",
    "ruleNextPage": "$.rescont.next_page_url",
    "rulePubDate": "📆{{$.updated_at## .*}}  ⏱️{{$.playtimes}}",
    "ruleTitle": "$.title##.*屎.*|.*Ts.*|.*TS.*|.*ts.*|.*伪娘.*|.*人妖.*|.*男同.*|.*mbrba.*|.*水果派.*|.*解说.*|.*mmraa.*|.*ss-.*|.*fway.*|.*rebd.*|.*mbdd.*|.*双性.*|.*妈妈.*|.*儿子.*|.*爸爸.*|.*女儿.*|.*母子.*|.*父女.*|.*熟女.*|.*眼射.*|.*直男.*|.*CD.*|.*肥女.*|.*黄金.*|.*骚0.*|.*gv.*|.*父子.*|.*飞机.*|.*撸.*|.*厕.*|.*老阿姨.*|.*乱伦.*|.*[电影].*",
    "singleUrl": false,
    "sortUrl": "\n随机::/api/videosort/0?page={{ Math.ceil(Math.random()*1600) }}\n最新::/api/videosort/0?page={{page}}\n🔎搜索::/api/videosort/0?serach={{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('强奸');source.getVariable()}}&page={{page}}\n国产自拍::/api/videosort/28?page={{page}}\nH动漫::/api/videosort/32?page={{page}}\n3D动画::/api/videosort/65?page={{page}}\n国产AV::/api/videosort/68?page={{page}}\n高清无码::/api/videosort/30?page={{page}}\n凌辱侵犯::/api/videosort/60?page={{page}}\n性虐调教::/api/videosort/64?page={{page}}\n长腿丝袜::/api/videosort/43?page={{page}}\n制服诱惑::/api/videosort/33?page={{page}}\nAV素人::/api/videosort/39?page={{page}}\nAV剧情::/api/videosort/49?page={{page}}\n绿帽人妻::/api/videosort/58?page={{page}}\n痴女淫娃::/api/videosort/61?page={{page}}\n美乳巨乳::/api/videosort/38?page={{page}}\n草莓推荐::/api/videosort/52?page={{page}}\ntaipei1001::/api/videosort/69?page={{page}}\n259LUXU::/api/videosort/50?page={{page}}\n明星淫梦::/api/videosort/56?page={{page}}\n电车痴汉::/api/videosort/59?page={{page}}\n絕色佳人::/api/videosort/44?page={{page}}\n网红嫩模::/api/videosort/37?page={{page}}\n口交自慰::/api/videosort/63?page={{page}}\n精油汗汁::/api/videosort/62?page={{page}}\n角色扮演::/api/videosort/27?page={{page}}\n魔镜系列::/api/videosort/54?page={{page}}\n重咸口味::/api/videosort/48?page={{page}}\n三级电影:/api/videosort/46?page={{page}}\n家庭乱伦::/api/videosort/57?page={{page}}\nAV欧美::/api/videosort/36?page={{page}}\n恐怖情色::/api/videosort/51?page={{page}}\n酒店偷拍::/api/videosort/67?page={{page}}",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "🌈草莓    S",
    "sourceUrl": "https://api.cmapiaba.xyz/",
    "style": ".container {\n    position: relative; /* 相对定位，用于包含视频 */\n    height: 100%; /* 容器高度与视频原始高度相同 */\n    overflow: hidden; /* 隐藏超出容器的部分 */\n}\n.title {\n    position: absolute; /* 绝对定位，相对于容器 */\n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; /* 确保标题在视频之上 */\n    background: #000; /* 纯黑色背景 */ \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; /* 绝对定位，相对于容器 */ \n    top: -65px; /* 上移80px */\n    left: 0; \n    width: 100%; \n    height: calc(96% + 65px);  /* 调整高度以适应内容 */\n    object-fit: contain; /* 确保视频内容不被裁剪 */\n    z-index: 0; /* 确保视频在标题之下 */\n    controls=\"controls\" autoplay muted; \n} \n"
  },
  {
    "articleStyle": 0,
    "contentBlacklist": "https://pc.stgowan.com/,\nhttps://dmku.mhtjx.top/,\nhttps://dmku.m3u8.pw/,\nhttps://dm.bbj.icu/,\nhttps://www.superplayer.top/index.php/index/dm,\nhttps://jx.8852.top/dmku/,\nhttps://api.js1736.com:666/tj/tongji.js,\nhttps://node11.aizhantj.com:21233/tjjs/",
    "coverDecodeJs": "function toByteArray(input) {\n  var out = new Packages.java.io.ByteArrayOutputStream();\n  var buffer = java.strToBytes('\\0'.repeat(4096));\n  var bytesRead;\n  while ((bytesRead = input.read(buffer)) != -1) {\n    out.write(buffer, 0, bytesRead);\n  }\n  return out.toByteArray();\n}\n\n(function() {\n  // 1. 读取原始字节内容\n  var textBytes = toByteArray(result);\n  // 2. 如果是GIF文件，直接返回原始字节\n  if (src.endsWith('.gif')) {\n    return textBytes;\n  }\n  try {\n    // 3. 将字节转换为字符串（用于解析数据URI）\n    var dataUri = java.bytesToStr(textBytes, \"UTF-8\");\n    // 4. 判断是完整的数据URI还是纯Base64数据\n    var base64Prefix = \"base64,\";\n    var base64Index = dataUri.indexOf(base64Prefix);\n    if (base64Index === -1) {\n      // 如果没有找到base64前缀，检查是否需要截取第一个/及之后的内容\n      var firstSlashIndex = dataUri.indexOf('/');\n      if (firstSlashIndex !== -1) {\n        // 如果找到第一个/，截取/及之后的内容\n        dataUri = dataUri.substring(firstSlashIndex);\n      }\n      // 对整个内容进行Base64解码\n      return java.base64DecodeToByteArray(dataUri);\n    } else {\n      // 如果是标准data URI，提取base64编码部分解码\n      var base64Data = dataUri.substring(base64Index + base64Prefix.length);\n      return java.base64DecodeToByteArray(base64Data);\n    }\n  } catch (e) {\n    // 解码失败时返回原始字节\n    return textBytes;\n  }\n})();",
    "customOrder": 4742,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "{\n  \"User-Agent\": \"okhttp/4.2.2\",\n}",
    "injectJs": "function setupCustomPlayer(video) {\n  // 手势滑动快进\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  \n  // 长按加速相关变量\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n\n  // 触摸事件处理\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    \n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n\n  // 添加触摸事件监听\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  \n  // 初始播放速度\n  video.playbackRate = NORMAL_SPEED;\n\n  // 创建按钮的通用函数\n  function createButton(text, onClick, position, width = '20px') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = '50%';\n    button.style.transform = 'translateY(-50%)';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n\n  // 旋转按钮（右侧）\n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    \n    // 保留当前的缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale})`;\n  }, { horizontal: 'right' });\n\n  // 缩放按钮（左侧）\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    \n    // 获取当前缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1)`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' });\n\n  // 快速跳转按钮（底部中央）\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  \n  // 按钮配置\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n\n  video.parentNode.appendChild(buttonContainer);\n}\n\n// 修改初始化逻辑，增加重试机制\nfunction initPlayerWithRetry() {\n  const maxRetries = 10;\n  const retryInterval = 500;\n  let retries = 0;\n  const tryInit = () => {\n    const video = document.getElementById('video');\n    if (video) {\n      setupCustomPlayer(video);\n    } else if (retries < maxRetries) {\n      retries++;\n      setTimeout(tryInit, retryInterval);\n    }\n  };\n  tryInit();\n}\n// 使用重试机制初始化播放器\ninitPlayerWithRetry();",
    "lastUpdateTime": 1769953204779,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.rescont.data",
    "ruleContent": "<html><head><meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\" />\n<meta name=\"referrer\" content=\"never\"/>\n  <style>html, body {text-align: center;margin: 0; padding: 0;width: 100%;overflow: hidden;} </style>\n  <script src=\"https://unpkg.com/hls.js@1.4.3/dist/hls.min.js\"></script>\n</head><body>\n  <div class=\"container\">\n    <div class=\"title\">{{$.rescont.title}}</div>\n    <video id=\"video\" width=\"100%\" height=\"91%\" poster=\"\" controls autoplay muted loop></video>\n  </div>\n<script>\nconst v=document.getElementById('video'),s=[\n  \"{{$.rescont.videopath}}\",\n  \"\"];\nlet c=0;\nfunction setupCustomControls(e){/* 自定义功能实现 */}\nfunction playNext(){\n  c>=s.length&&(c=0); // 循环重置计数器\n  const u=s[c++];\n  // 检测Hls对象是否存在\n  if (typeof Hls !== 'undefined' && Hls.isSupported()) {\n    const h = new Hls({\n      enableSoftwareAES: true,          // 强制软件解密\n      forceKeyFrameOnDiscontinuity: true // 关键帧恢复\n    });\n    h.loadSource(u);\n    h.attachMedia(v);\n    h.on(Hls.Events.MANIFEST_PARSED,()=>v.play().then(()=>setupCustomControls(v)).catch(console.log));\n    h.on(Hls.Events.ERROR,(_,d)=>d.fatal&&playNext())\n  } else { // Hls加载失败或浏览器原生支持HLS\n    if (v.canPlayType('application/vnd.apple.mpegurl')) {\n      v.src = u;\n      v.onloadedmetadata = () => v.play().then(() => setupCustomControls(v));\n      v.onerror = playNext;\n    } else {\n      // 如果都不支持，尝试直接播放（可能支持MP4等格式）\n      v.src = u;\n      v.onerror = playNext;\n      v.play().then(() => setupCustomControls(v)).catch(playNext);\n    }\n  }\n}playNext();\n</script>\n</body></html>",
    "ruleImage": "{{$.coverbase64.url}}",
    "ruleLink": "/api/videoplay/{{$.id}}",
    "ruleNextPage": "page",
    "rulePubDate": "📆 {{$.updated_at## .*}}  ⏱️ {{$.playtimes}}",
    "ruleTitle": "$.title##.*屎.*|.*Ts.*|.*TS.*|.*ts.*|.*伪娘.*|.*人妖.*|.*男同.*|.*mbrba.*|.*水果派.*|.*解说.*|.*mmraa.*|.*ss-.*|.*fway.*|.*rebd.*|.*mbdd.*|.*双性.*|.*妈妈.*|.*儿子.*|.*爸爸.*|.*女儿.*|.*母子.*|.*父女.*|.*熟女.*|.*眼射.*|.*直男.*|.*CD.*|.*肥女.*|.*黄金.*|.*骚0.*|.*gv.*|.*父子.*|.*飞机.*|.*撸.*|.*厕.*|.*老阿姨.*|.*乱伦.*",
    "singleUrl": false,
    "sortUrl": "\n随机::/api/videosort/0?page={{ Math.ceil(Math.random()*1500) }}\n最新::/api/videosort/0?page={{page}}\n🔎搜索::/api/videosort/0?serach={{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('强奸');source.getVariable()}}&page={{page}}\n国产自拍::/api/videosort/10?page={{page}}\nH动漫::/api/videosort/14?page={{page}}\n国产剧情::/api/videosort/52?page={{page}}\n盗摄偷拍::/api/videosort/46?page={{page}}\n宅男福利::/api/videosort/31?page={{page}}\n小编推荐::/api/videosort/30?page={{page}}\n嫩模专区::/api/videosort/37?page={{page}}\n网红主播::/api/videosort/17?page={{page}}\n明星换脸::/api/videosort/33?page={{page}}\nASMR系列::/api/videosort/51?page={{page}}\n高清无码::/api/videosort/1?page={{page}}\nAV剧情::/api/videosort/29?page={{page}}\n翘臀美穴::/api/videosort/21?page={{page}}\n自慰口交::/api/videosort/50?page={{page}}\n淫乱职场::/api/videosort/45?page={{page}}\n制服诱惑::/api/videosort/5?page={{page}}\n美乳巨乳::/api/videosort/20?page={{page}}\n长腿丝袜::/api/videosort/11?page={{page}}\n角色扮演::/api/videosort/4?page={{page}}\n师生淫乱::/api/videosort/40?page={{page}}\n人妻熟女::/api/videosort/6?page={{page}}\n特工女警::/api/videosort/41?page={{page}}\n护士医生::/api/videosort/42?page={{page}}\n近亲相奸::/api/videosort/43?page={{page}}\nAV素人::/api/videosort/24?page={{page}}\n淫欲痴汉::/api/videosort/44?page={{page}}\n有码破坏::/api/videosort/48?page={{page}}\n当红女优::/api/videosort/9?page={{page}}\n制服诱惑::/api/videosort/5?page={{page}}\n青春萝莉::/api/videosort/22?page={{page}}\n重咸口味::/api/videosort/23?page={{page}}\n女同性爱::/api/videosort/38?page={{page}}\n三级电影::/api/videosort/25?page={{page}}",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "🌈向日葵   S",
    "sourceUrl": "https://api.xrkapiaba.xyz",
    "style": ".container {\n    position: relative; /* 相对定位，用于包含视频 */\n    height: 100%; /* 容器高度与视频原始高度相同 */\n    overflow: hidden; /* 隐藏超出容器的部分 */\n}\n.title {\n    position: absolute; /* 绝对定位，相对于容器 */\n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; /* 确保标题在视频之上 */\n    background: #000; /* 纯黑色背景 */ \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; /* 绝对定位，相对于容器 */ \n    top: -65px; /* 上移80px */\n    left: 0; \n    width: 100%; \n    height: calc(96% + 65px);  /* 调整高度以适应内容 */\n    object-fit: contain; /* 确保视频内容不被裁剪 */\n    z-index: 0; /* 确保视频在标题之下 */\n    controls=\"controls\" autoplay muted; \n} \n"
  },
  {
    "articleStyle": 0,
    "coverDecodeJs": "function decodeImage(data, keyBytes) {\n  var out = new Packages.java.io.ByteArrayOutputStream()\n  var byte\n  var count = 0\n  var keyLength = keyBytes.length\n  while ((byte = data.read()) != -1) {\n    if (count < 100) {\n      out.write(byte ^ keyBytes[count % keyLength])\n      count++\n    } else {\n      out.write(byte)\n    }\n  }\n  return out.toByteArray()\n}\nfunction toByteArray(input) {\n  var out = new Packages.java.io.ByteArrayOutputStream();\n  var buffer = java.strToBytes('\\0'.repeat(4096));\n  var bytesRead;\n  while ((bytesRead = input.read(buffer)) != -1) {\n    out.write(buffer, 0, bytesRead);\n  }\n  return out.toByteArray();\n}\nvar keyStr = \"2019ysapp7527\"\nvar keyBytes = java.strToBytes(keyStr, \"UTF-8\")\nvar excludeKeywords = ['yximgs', 'Uploads'];\nvar shouldExclude = excludeKeywords.some(function(keyword) {\n  return src.indexOf(keyword) !== -1;\n});\nif (shouldExclude) {\n  toByteArray(result)\n} else {\n  decodeImage(result, keyBytes)\n}",
    "customOrder": 4743,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "{\n    \"User-Agent\": \"Mozilla/5.0 (Linux; Android 13; SM-G998B Build/TP1A.220624.014) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36 SearchCraft/3.9.2 okhttp/4.2.2\",\n    \"referer\": \"{{baseUrl}}\"\n}",
    "injectJs": "function setupCustomPlayer(video) {\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  video.playbackRate = NORMAL_SPEED;\n  function createButton(text, onClick, position, width = '20px', top = '50%') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = top;\n    button.style.transform = top === '50%' ? 'translateY(-50%)' : 'none';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    const isFlipped = video.getAttribute('data-flipped') === 'true';\n    const flipValue = isFlipped ? -1 : 1;\n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale}) scaleX(${flipValue})`;\n  }, { horizontal: 'right' }, '20px', 'calc(50% - 20px)');\n  let isPlaying = !video.paused;\n  const playPauseBtn = createButton(\n    isPlaying ? '❚❚' : '▶',\n    () => {\n      if (video.paused) {\n        video.play();\n        playPauseBtn.textContent = '❚❚';\n      } else {\n        video.pause();\n        playPauseBtn.textContent = '▶';\n      }\n    },\n    { horizontal: 'right' },\n    '20px',\n    'calc(50% + 20px)'\n  );\n  video.addEventListener('play', () => {\n    playPauseBtn.textContent = '❚❚';\n    isPlaying = true;\n  });\n  video.addEventListener('pause', () => {\n    playPauseBtn.textContent = '▶';\n    isPlaying = false;\n  });\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    const isFlipped = video.getAttribute('data-flipped') === 'true';\n    const flipValue = isFlipped ? -1 : 1;\n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale}) scaleX(${flipValue})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1) scaleX(${flipValue})`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' }, '20px', 'calc(50% - 20px)');\n  createButton('⇄', () => {\n    const isFlipped = video.getAttribute('data-flipped') === 'true';\n    const newFlipState = !isFlipped;\n    video.setAttribute('data-flipped', newFlipState);\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    const flipValue = newFlipState ? -1 : 1;\n    video.style.transform = `rotate(${currentRotation}deg) scale(${currentScale}) scaleX(${flipValue})`;\n  }, { horizontal: 'left' }, '20px', 'calc(50% + 20px)');\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n\n  video.parentNode.appendChild(buttonContainer);\n}\nfunction initPlayerWithRetry() {\n  const maxRetries = 10;\n  const retryInterval = 500;\n  let retries = 0;\n  const tryInit = () => {\n    const video = document.getElementById('video');\n    if (video) {\n      setupCustomPlayer(video);\n    } else if (retries < maxRetries) {\n      retries++;\n      setTimeout(tryInit, retryInterval);\n    }\n  };\n  tryInit();\n}\ninitPlayerWithRetry();",
    "jsLib": "function decrypt(encryptedText) {\n  let result = '';\n  for (let i = 0; i < encryptedText.length; i++) {\n    result += String.fromCharCode(128 ^ encryptedText.charCodeAt(i));\n  }\n  return result;\n}",
    "lastUpdateTime": 1766110000613,
    "loadWithBaseUrl": true,
    "ruleArticles": ".vodbox",
    "ruleContent": "@js:\nplayer = baseUrl.match(/id=(.*.m3u8)/)[1];\nconst tokens = (result.match(/token=([^',]+)/g) || []).map(match => match.replace('token=', ''));\nlet token = tokens[3] || '';\nvar sources = [\n  `${player}?token=${token}`,\n];\nvar sourceButtons = \"\";\nif (sources.length > 1) {\n    for (var i = 0; i < sources.length; i++) {\n        sourceButtons += `<button class=\"source-btn\" data-index=\"${i}\">源${i+1}</button>`;\n    }\n}\nresult=`\n<html>  \n<head>  \n<meta charset=\"utf-8\">  \n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\">\n<meta name=\"referrer\" content=\"never\"/>\n<script src=\"https://s4.zstatic.net/ajax/libs/hls.js/1.6.13/hls.min.js\"></script>\n<style>\nhtml, body { text-align: center;margin: 0; padding: 0; width: 100%; overflow: hidden; }\n.source-container { position: absolute; top: 23px; right: 1px; z-index: 10; display: flex; gap: 1px; }\n.source-btn { color: #ff0; background: rgba(0,0,0,0.7); padding: 1px 5px; border-radius: 10px; font-size: 13px; border: none; cursor: pointer; }\n.source-btn.active { color: red !important; }\n</style>\n</head>  \n<body>  \n<div class=\"container\">\n    <div class=\"title\">{{java.get('title')}}</div>\n    ${sources.length > 1 ? `<div class=\"source-container\">${sourceButtons}</div>` : ''}\n    <video id=\"video\" width=\"100%\" height=\"91%\" poster=\"\" controls autoplay muted loop></video>\n<script>\n    const video = document.getElementById('video');\n    const sources = ${JSON.stringify(sources)};\n    let hls = null;\n    let currentSource = 0;\n    function playHLS(url) {\n        if (hls) hls.destroy();\n        if (Hls.isSupported()) {\n            hls = new Hls({\n                enableSoftwareAES: true,\n                maxBufferLength: 30,\n                maxMaxBufferLength: 60\n            });\n            hls.on(Hls.Events.ERROR, function(event, data) {\n                if (data.fatal) {\n                    switchToNextSource();\n                }\n            });\n            hls.loadSource(url);\n            hls.attachMedia(video);\n        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n            video.src = url;\n        }\n        video.onerror = function() {\n            switchToNextSource();\n        };\n    }\n    function switchToNextSource() {\n        if (sources.length <= 1) return;\n        currentSource = (currentSource + 1) % sources.length;\n        playHLS(sources[currentSource]);\n        updateButtons();\n    }\n    function switchSource(index) {\n        currentSource = index;\n        playHLS(sources[index]);\n        updateButtons();\n    }\n    function updateButtons() {\n        document.querySelectorAll('.source-btn').forEach((btn, i) => {\n            btn.classList.toggle('active', i === currentSource);\n        });\n    }\n    video.onended = function() {\n        if (sources.length === 1) {\n            video.currentTime = 0;\n            video.play();\n        } else {\n            switchToNextSource();\n        }\n    };\n    document.querySelectorAll('.source-btn').forEach(btn => {\n        btn.addEventListener('click', () => switchSource(parseInt(btn.dataset.index)));\n    });\n    if (sources.length > 0) switchSource(0);\n</script>\n</div>\n</body>  \n</html>\n`;",
    "ruleImage": "{{@@img@data-original}}",
    "ruleLink": "{{@@a.0@href}}",
    "ruleNextPage": "page",
    "rulePubDate": "{{@@img.0@data-original##cn\\/cf(.*?)\\/##$1##}}\n@js:\nresult = result !== \"\" ? result : \"点击播放\";",
    "ruleTitle": "{{@@.km-script@text}}\n<js>\nconst blockKeywords = /TS|Latina|自他屏蔽关键自行添加/i;\nresult = decrypt(result);\nif (blockKeywords.test(result)) {\n  // 如果包含关键词，将标题设为空字符串\n  result = \"\";\n}\njava.put('title',result)\n</js>",
    "singleUrl": false,
    "sortUrl": "\n随机::/index.php/vod/type/id/1/page/{{ Math.ceil(Math.random()*1570) }}.html\n最新::/index.php/vod/type/id/1/page/{{page}}.html\n\n🔎搜索::/index.php/vod/type/id/1/wd/{{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('奸');source.getVariable()}}/page/{{page}}.html\n\n国产::/index.php/vod/type/id/54/page/{{page}}.html\n其他分类自行添加\n动漫::/index.php/vod/type/id/9/page/{{page}}.html",
    "sourceComment": "备用网址\nhttps://618879.xyz/\nhttps://618051.xyz/\nhttps://618082.xyz/\nhttps://618063.xyz/\nhttps://618070.xyz/\n\nhttps://d2m1d86x8ze4id.cloudfront.net\n\n",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "🌈md视频    S",
    "sourceUrl": "https://618061.xyz/",
    "style": ".container {\n    position: relative; \n    height: 100%; \n    overflow: hidden;\n}\n.title {\ntext-align:center;\n    position: absolute; \n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; \n    background: #000; \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; \n    top: +20px; \n    left: 0; \n    width: 100%; \n    height: calc(93% + 0px);  \n    object-fit: contain; \n    z-index: 0; \n    controls=\"controls\" autoplay muted; \n} \nvideo::-webkit-media-controls-overlay-play-button {\n    display: none !important;\n}\nvideo::-webkit-media-controls-fullscreen-button {\n    display: none !important;\n}"
  },
  {
    "articleStyle": 0,
    "customOrder": 4744,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "{\n    \"User-Agent\": \"Mozilla/5.0 (Linux; Android 13; SM-G998B Build/TP1A.220624.014) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36 SearchCraft/3.9.2 \",\n    \"referer\": \"{{baseUrl}}\"\n}",
    "lastUpdateTime": 1765680387004,
    "loadWithBaseUrl": true,
    "ruleArticles": ".item",
    "ruleContent": "@js:\n// 定义所有视频源\nvar sources = [\n `{{@@source.0@src}}`, \n `{{@@source.1@src}}`,\n `{{@@source.2@src}}`,\n];\n\n// 生成源按钮 - 只生成非空源的按钮\nvar sourceButtons = \"\";\nvar validSources = []; // 存储有效源的索引\n\n// 收集所有非空的有效源\nfor (var i = 0; i < sources.length; i++) {\n    // 检查源是否为空（去除空格后判断）\n    if (sources[i] && sources[i].trim() !== '') {\n        validSources.push(i);\n    }\n}\n\n// 只有当有效源数量大于1时才显示按钮\nif (validSources.length > 1) {\n    for (var j = 0; j < validSources.length; j++) {\n        var index = validSources[j];\n        sourceButtons += `<button class=\"source-btn\" data-index=\"${index}\">源${index+1}</button>`;\n    }\n}\n\nresult=`\n<html>  \n<head>  \n<meta charset=\"utf-8\">  \n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\">\n<meta name=\"referrer\" content=\"never\"/>\n<script src=\"https://s4.zstatic.net/ajax/libs/hls.js/1.6.13/hls.min.js\"></script>\n<style>\nhtml, body { margin: 0; padding: 0; width: 100%; overflow: hidden; }\n.source-container { position: absolute; top: 23px; right: 1px; z-index: 10; display: flex; gap: 1px; }\n.source-btn { color: #ff0; background: rgba(0,0,0,0.7); padding: 1px 5px; border-radius: 10px; font-size: 13px; border: none; cursor: pointer; }\n.source-btn.active { color: red !important; }\n</style>\n</head>  \n<body>  \n<div class=\"container\">\n    <div class=\"title\"><span>{{@@title@text##- J163视频}}</span></div>\n    ${sourceButtons ? `<div class=\"source-container\">${sourceButtons}</div>` : ''}\n    <video id=\"video\" width=\"100%\" height=\"91%\" poster=\"{{@@script@all##preview_url: '(.*?)',##$1##}}\" controls autoplay muted loop></video>\n<script>\n    const video = document.getElementById('video');\n    const sources = ${JSON.stringify(sources)};\n    const validSources = ${JSON.stringify(validSources)}; // 有效源的索引数组\n    let hls = null;\n    let currentSource = 0;\n    \n    // 初始化HLS播放\n    function playHLS(url) {\n        if (hls) hls.destroy();\n        \n        if (Hls.isSupported()) {\n            hls = new Hls({\n                enableSoftwareAES: true,\n                maxBufferLength: 30,\n                maxMaxBufferLength: 60\n            });\n            \n            // 添加错误监听\n            hls.on(Hls.Events.ERROR, function(event, data) {\n                if (data.fatal) {\n                    switchToNextSource();\n                }\n            });\n            \n            hls.loadSource(url);\n            hls.attachMedia(video);\n        } else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n            video.src = url;\n        }\n        \n        // 视频元素错误监听\n        video.onerror = function() {\n            switchToNextSource();\n        };\n    }\n\n    // 获取下一个有效源索引\n    function getNextValidSourceIndex() {\n        if (validSources.length <= 1) return currentSource;\n        \n        const currentIndex = validSources.indexOf(currentSource);\n        if (currentIndex === -1) return validSources[0];\n        \n        const nextIndex = (currentIndex + 1) % validSources.length;\n        return validSources[nextIndex];\n    }\n    \n    // 切换到下一个有效源\n    function switchToNextSource() {\n        if (validSources.length <= 1) return;\n        \n        currentSource = getNextValidSourceIndex();\n        playHLS(sources[currentSource]);\n        updateButtons();\n    }\n    \n    // 切换视频源\n    function switchSource(index) {\n        // 确保索引有效且源不为空\n        if (validSources.includes(index) && sources[index] && sources[index].trim() !== '') {\n            currentSource = index;\n            playHLS(sources[index]);\n            updateButtons();\n        }\n    }\n    \n    // 更新按钮状态\n    function updateButtons() {\n        document.querySelectorAll('.source-btn').forEach(btn => {\n            const index = parseInt(btn.dataset.index);\n            btn.classList.toggle('active', index === currentSource);\n        });\n    }\n    \n    // 获取第一个有效源\n    function getFirstValidSource() {\n        for (let i = 0; i < sources.length; i++) {\n            if (sources[i] && sources[i].trim() !== '') {\n                return i;\n            }\n        }\n        return 0; // 如果没有有效源，返回0\n    }\n    \n    // 监听播放结束事件\n    video.onended = function() {\n        if (validSources.length === 1) {\n            // 单源循环播放\n            video.currentTime = 0;\n            video.play();\n        } else {\n            // 多源顺序播放\n            switchToNextSource();\n        }\n    };\n    \n    // 绑定按钮事件\n    document.querySelectorAll('.source-btn').forEach(btn => {\n        btn.addEventListener('click', () => switchSource(parseInt(btn.dataset.index)));\n    });\n    \n    // 播放第一个有效源\n    const firstValidSource = getFirstValidSource();\n    if (sources.length > 0 && sources[firstValidSource]) {\n        currentSource = firstValidSource;\n        switchSource(firstValidSource);\n    }\n</script>\n\n</div>\n</body>  \n</html>\n`;",
    "ruleImage": "img@data-original\n<js>\njava.put('pic',result)\n</js>",
    "ruleLink": "{{@@a.0@href##(.*)/videos/##$1##}}/embed/{{@@a.0@href##videos/(.*)/.*/##$1##}}",
    "ruleNextPage": "page",
    "rulePubDate": "{{@@.added@text}}  ⏱️{{@@.duration@text}}",
    "ruleTitle": "@js:\nif (\"{{@@.ico-private@text}}\" || \"{{@@.line-private@all}}\") {\n    result = \"\";\n} else {\n    result = \"{{@@strong@text}}\";\n}",
    "singleUrl": false,
    "sortUrl": "\n随机::/latest-updates/?mode=async&function=get_block&block_id=list_videos_latest_videos_list&duration_from=600&sort_by=post_date&from={{ Math.ceil(Math.random()*3000) }}\n\n最新::/latest-updates/{{page}}/\n\n国产::/tags/guo-chan/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from={{page}}\n传媒::/tags/chuan-mei/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from={{page}}\n强奸::/tags/qiang-jian/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from={{page}}\n丝袜::/tags/si-wa/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from={{page}}\n性感::/tags/xing-gan/?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=post_date&from={{page}}",
    "sourceComment": "\n备用地址\nhttps://boboporn.net/\nhttps://boboporn.com/\n\n",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "❀boboporn",
    "sourceUrl": "https://boboporn.com/",
    "style": ".container {\n    position: relative; /* 相对定位，用于包含视频 */\n    height: 100%; /* 容器高度与视频原始高度相同 */\n    overflow: hidden; /* 隐藏超出容器的部分 */\n}\n.title {\n\ttext-align: center;\n    position: absolute; /* 绝对定位，相对于容器 */\n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; /* 确保标题在视频之上 */\n    background: #000; /* 纯黑色背景 */ \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; /* 绝对定位，相对于容器 */ \n    top: +20px; /* 视频上移 */\n    left: 0; \n    width: 100%; \n    height: calc(93% + 0px);  /* 调整高度以适应内容 */\n    object-fit: contain; /* 确保视频内容不被裁剪 */\n    z-index: 0; /* 确保视频在标题之下 */\n    controls=\"controls\" autoplay muted; \n} \n"
  },
  {
    "articleStyle": 0,
    "customOrder": 4745,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\"User-Agent\": \"Mozilla/5.0 (Linux; Android 10;Xiaomi 10pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36\"}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "$..data[*]",
    "ruleContent": "$..videopath##.*\\$\n\n@js:\nurl=result;\n\nloadding=java.get(\"pic\")\n\nhtml=\n`<link rel=\"stylesheet\" type=\"text/css\" href=\"https://muiplayer.js.org/css/mui-player.min.css\" />\n\n<script type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/gh/ljun223/reader3@main/js/mui-player.min.js\"></script>\n\n<script type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/gh/ljun223/reader3@main/js/mui-player-mobile-plugin.min.js\"></script>\n\n<div class=\"dz\">`+url+`</div>\n\n<div id=\"mui-player\" style=\"width:100%;height:300px\"></div>\n\n<script>\n   var mp = new MuiPlayer(\t{\n \t\t  \"container\": \"#mui-player\",\n \t\t  \"src\": \"`+url+`\",\n \t\t  \"poster\":\"`+loadding+`\",\n \t\t  \"autoFit\":false,\n \t\t  \"lang\": \"zh-cn\",\n \t  \t\"height\":\"300px\",\n \t\t  plugins: [\n \t\t    new MuiPlayerMobilePlugin({\n \t\t\t    \"key\":\n \t\t\t \"01I01I01H01J01L01K01J01I01K01J01H01D01J01G01E\",\n \t\t    \t\"showMenuButton\": true,\n \t\t\t    \"pageGesture\":true,\n \t\t\t   })\n    ]\n   }); \n </script>`",
    "ruleImage": "coverpath@put:{\"pic\":\"$.coverpath\"}",
    "ruleLink": "https://77gmk8o.com/api/videoplay/{{$.id}}?uuid=1",
    "ruleNextPage": "page",
    "rulePubDate": "authername",
    "ruleTitle": "title",
    "singleUrl": false,
    "sortUrl": "@js:\n\ndata=java.ajax(\"https://77gmk8o.com/api/videosort\");\n\njson=JSON.parse(data);\n\nvar list=[];\nvar num=json.rescont.length;\nfor(var i=1;i<num;i++){\nlist+=json.rescont[i].name+\"::\"+\"https://77gmk8o.com/api/videosort/\"+json.rescont[i].id+\"?orderby=&page={{page}}\"+\"\\n\"\n\t};\n\"搜索用::https://77gmk8o.com/api/videosort/0?page={{page}}&serach={{source.getVariable()}}\"+\"\\n\"+list",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "葫芦视频",
    "sourceUrl": "https://77gmk8o.com"
  },
  {
    "articleStyle": 1,
    "customOrder": 4746,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\"User-Agent\": \"Mozilla/5.0 (Linux; U; Android 14; zh-cn; M2102K1AC Build/UKQ1.231207.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.118 Mobile Safari/537.36 MQQBrowser/10.1.0\"}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": ".thumbnail-group@li",
    "ruleContent": "<js>\np=result.match(/vod\\_data.*url\\\"\\:\\\"(.*?)\\\"\\,\\\"url/);\np=(p?p[1]:1).replace(/\\\\/g,'')||1; pi=java.getString('.breadcrumbs@span@text')||1;\n`<html>\n    <head>\n        <meta name=\"viewport\" content=\"width=device-width\">\n        <style>\n            body {\n                margin: 0;\n                font-family: Arial, sans-serif;\n                background: linear-gradient(135deg, #ece9e6, #ffffff);\n                display: flex;\n                flex-direction: column;\n                align-items: center;\n                justify-content: flex-start;\n                padding: 20px;\n            }\n            .container {\n                width: 100%;\n                max-width: 800px;\n                background: #fff;\n                border-radius: 10px;\n                box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);\n                overflow: hidden;\n                margin-bottom: 20px;\n            }\n            h3 {\n                margin: 0;\n                padding: 10px 20px;\n                font-size: 0.9em;\n                background: #333;\n                color: #fff;\n                border-radius: 10px 10px 0 0;\n            }\n            .video-container {\n                width: 100%;\n                background: #000;\n                position: relative;\n            }\n            video {\n                width: 100%;\n                height: auto;\n                display: block;\n            }\n            .info-container {\n                padding: 20px;\n            }\n            .info-container p {\n                margin: 10px 0;\n                color: #555;\n            }\n            .info-container p span {\n                font-weight: bold;\n                color: #000;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n        <h3>${pi}</h3>\n            <div class=\"video-container\">\n                <video controls autoplay name=\"media\" id=\"videoPlayer\">\n                    <source src=\"${p}\" type=\"video/mp4\">\n                </video>\n            </div>\n            <div class=\"info-container\">\n                \n            </div>\n        </div>\n\n        <script>\n            // 获取视频元素\n            const video = document.getElementById('videoPlayer');\n            let touchStartX = 0;\n            let touchStartY = 0;\n            let touchStartTime = 0;\n            let isLongPress = false;\n\n            // 滑动快进\n            video.addEventListener('touchstart', (e) => {\n                touchStartX = e.touches[0].clientX;\n                touchStartY = e.touches[0].clientY;\n                touchStartTime = Date.now();\n                isLongPress = false;\n            });\n\n            video.addEventListener('touchmove', (e) => {\n                const deltaX = e.touches[0].clientX - touchStartX;\n                const deltaY = e.touches[0].clientY - touchStartY;\n\n                // 如果是水平滑动，且未进入长按状态\n                if (Math.abs(deltaX) > Math.abs(deltaY) && !isLongPress) {\n                    const duration = video.duration;\n                    const seekTime = video.currentTime + (deltaX / 100); // 每滑动100px快进1秒\n                    video.currentTime = Math.min(Math.max(seekTime, 0), duration);\n                }\n            });\n\n            // 长按快进\n            video.addEventListener('touchend', (e) => {\n                const touchEndTime = Date.now();\n                const touchDuration = touchEndTime - touchStartTime;\n\n                // 如果长按时间超过500ms，进入长按快进状态\n                if (touchDuration > 500) {\n                    isLongPress = true;\n\n                    // 在长按状态下，根据滑动距离快进\n                    const deltaX = e.changedTouches[0].clientX - touchStartX;\n                    const duration = video.duration;\n                    const seekTime = video.currentTime + (deltaX / 100); // 每滑动100px快进1秒\n                    video.currentTime = Math.min(Math.max(seekTime, 0), duration);\n                } else {\n                    isLongPress = false;\n                }\n            });\n\n            // 防止默认行为（如页面滚动）\n            video.addEventListener('touchmove', (e) => {\n                e.preventDefault();\n            });\n        </script>\n    </body>\n</html>`;\n\n</js>",
    "ruleImage": "img@src",
    "ruleLink": "a@href",
    "ruleNextPage": "text.下一页@href",
    "rulePubDate": "p@text",
    "ruleTitle": "h5@text||img@alt",
    "singleUrl": false,
    "sortUrl": "搜索🔍::/index.php/vod/search/page/{{page}}/wd/{{source.getVariable()}}.html\n伦理三级::/index.php/vod/type/id/6/page/{{page}}.html\n国产精品::/index.php/vod/type/id/7/page/{{page}}.html\n偷拍自拍::/index.php/vod/type/id/8/page/{{page}}.html\n主播大秀::/index.php/vod/type/id/9/page/{{page}}.html\n卡通动漫::/index.php/vod/type/id/10/page/{{page}}.html\n制服丝袜::/index.php/vod/type/id/11/page/{{page}}.html\n少女萝莉::/index.php/vod/type/id/12/page/{{page}}.html\n巨乳美乳::/index.php/vod/type/id/20/page/{{page}}.html\n熟女人妻::/index.php/vod/type/id/21/page/{{page}}.html\n亚洲有码::/index.php/vod/type/id/22/page/{{page}}.html\n强奸乱伦::/index.php/vod/type/id/23/page/{{page}}.html\n亚洲无码::/index.php/vod/type/id/25/page/{{page}}.html\n中文字幕::/index.php/vod/type/id/26/page/{{page}}.html\n同性专区::/index.php/vod/type/id/27/page/{{page}}.html\nAl换脸::/index.php/vod/type/id/28/page/{{page}}.html\n欧美精品::/index.php/vod/type/id/32/page/{{page}}.html\n国产传媒::/index.php/vod/type/id/33/page/{{page}}.html\n口交颜射::/index.php/vod/type/id/34/page/{{page}}.html\n女优明星::/index.php/vod/type/id/35/page/{{page}}.html\n素人自拍::/index.php/vod/type/id/36/page/{{page}}.html\n多人群交::/index.php/vod/type/id/37/page/{{page}}.html\n网曝门::/index.php/vod/type/id/39/page/{{page}}.html\n探花系列::/index.php/vod/type/id/41/page/{{page}}.html\n麻豆传媒::/index.php/vod/type/id/43/page/{{page}}.html\n天美传媒::/index.php/vod/type/id/46/page/{{page}}.html\nSA国际传媒::/index.php/vod/type/id/47/page/{{page}}.html\n果冻传媒::/index.php/vod/type/id/50/page/{{page}}.html\n星空无限::/index.php/vod/type/id/51/page/{{page}}.html\n精东影业::/index.php/vod/type/id/52/page/{{page}}.html\n蜜桃传媒::/index.php/vod/type/id/54/page/{{page}}.html\nAV解说::/index.php/vod/type/id/56/page/{{page}}.html\nVR视角::/index.php/vod/type/id/57/page/{{page}}.html\nJVID::/index.php/vod/type/id/59/page/{{page}}.html\nSWAG::/index.php/vod/type/id/60/page/{{page}}.html \ncosplay::/index.php/vod/type/id/61/page/{{page}}.html\n抖音视频::/index.php/vod/type/id/62/page/{{page}}.html\n热门头条::/index.php/vod/type/id/63/page/{{page}}.html\n素人搭讪::/index.php/vod/type/id/80/page/{{page}}.html\n欺辱凌辱::/index.php/vod/type/id/81/page/{{page}}.html\n野外激情::/index.php/vod/type/id/82/page/{{page}}.html\n学生诱惑::/index.php/vod/type/id/83/page/{{page}}.html\nSM调教::/index.php/vod/type/id/84/page/{{page}}.html\n水果派::/index.php/vod/type/id/86/page/{{page}}.html\n91传媒::/index.php/vod/type/id/88/page/{{page}}.html\n糖心传媒::/index.php/vod/type/id/90/page/{{page}}.html\n一本道::/index.php/vod/type/id/93/page/{{page}}.html\n",
    "sourceComment": "发布页：https://wuxiants.github.io/",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "无限",
    "sourceUrl": "https://wxts.wuxiants834.com/"
  },
  {
    "articleStyle": 0,
    "contentBlacklist": "https://pc.stgowan.com/,\nhttps://dmku.mhtjx.top/,\nhttps://dmku.m3u8.pw/,\nhttps://dm.bbj.icu/,\nhttps://www.superplayer.top/index.php/index/dm",
    "coverDecodeJs": "function toByteArray(input) {\n  var out = new Packages.java.io.ByteArrayOutputStream();\n  var buffer = java.strToBytes('\\0'.repeat(4096));\n  var bytesRead;\n  while ((bytesRead = input.read(buffer)) != -1) {\n    out.write(buffer, 0, bytesRead);\n  }\n  return out.toByteArray();\n}\n\n(function() {\n  // 1. 读取原始字节内容\n  var textBytes = toByteArray(result);\n  // 2. 如果是GIF文件，直接返回原始字节\n  if (src.endsWith('.gif')) {\n    return textBytes;\n  }\n  try {\n    // 3. 将字节转换为字符串（用于解析数据URI）\n    var dataUri = java.bytesToStr(textBytes, \"UTF-8\");\n    // 4. 判断是完整的数据URI还是纯Base64数据\n    var base64Prefix = \"base64,\";\n    var base64Index = dataUri.indexOf(base64Prefix);\n    if (base64Index === -1) {\n      // 如果没有找到base64前缀，检查是否需要截取第一个/及之后的内容\n      var firstSlashIndex = dataUri.indexOf('/');\n      if (firstSlashIndex !== -1) {\n        // 如果找到第一个/，截取/及之后的内容\n        dataUri = dataUri.substring(firstSlashIndex);\n      }\n      // 对整个内容进行Base64解码\n      return java.base64DecodeToByteArray(dataUri);\n    } else {\n      // 如果是标准data URI，提取base64编码部分解码\n      var base64Data = dataUri.substring(base64Index + base64Prefix.length);\n      return java.base64DecodeToByteArray(base64Data);\n    }\n  } catch (e) {\n    // 解码失败时返回原始字节\n    return textBytes;\n  }\n})();",
    "customOrder": 4749,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n\t\"User-Agent\":\"Mozilla/5.0 (Linux; U; Android 10; zh-cn; MI CC 11)  AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/18.1.8 swan-mibrowser\",\n\t\"referer\": \"{{baseUrl}}\"\n}",
    "injectJs": "function setupCustomPlayer(video) {\n  // 手势滑动快进\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  \n  // 长按加速相关变量\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n\n  // 触摸事件处理\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    \n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n\n  // 添加触摸事件监听\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  \n  // 初始播放速度\n  video.playbackRate = NORMAL_SPEED;\n\n  // 创建按钮的通用函数\n  function createButton(text, onClick, position, width = '20px') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = '50%';\n    button.style.transform = 'translateY(-50%)';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n\n  // 旋转按钮（右侧）\n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    \n    // 保留当前的缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale})`;\n  }, { horizontal: 'right' });\n\n  // 缩放按钮（左侧）\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    \n    // 获取当前缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1)`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' });\n\n  // 快速跳转按钮（底部中央）\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  \n  // 按钮配置\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n\n  video.parentNode.appendChild(buttonContainer);\n}\n\n// 修改初始化逻辑，增加重试机制\nfunction initPlayerWithRetry() {\n  const maxRetries = 10;\n  const retryInterval = 500;\n  let retries = 0;\n  const tryInit = () => {\n    const video = document.getElementById('video');\n    if (video) {\n      setupCustomPlayer(video);\n    } else if (retries < maxRetries) {\n      retries++;\n      setTimeout(tryInit, retryInterval);\n    }\n  };\n  tryInit();\n}\n// 使用重试机制初始化播放器\ninitPlayerWithRetry();",
    "lastUpdateTime": 1775588357478,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.rescont.data[*]",
    "ruleContent": "<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\" />\n  <meta name=\"referrer\" content=\"never\"/>\n  <style>\n    * {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n    }\n    html, body {\n      width: 100%;\n      height: 100vh;\n      background: #000;\n      overflow: hidden;\n    }\n    .container {\n      display: flex;\n      flex-direction: column;\n      height: 100%;\n      background: #000;\n    }\n    .title {\n      color: white;\n      background: rgba(0,0,0,0.8);\n      padding: 10px;\n      font-size: 16px;\n      text-align: center;\n      font-weight: bold;\n      border-bottom: 1px solid #333;\n      flex-shrink: 0;\n    }\n    .url-bar {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      background: #1e1e1e;  /* 完全不透明背景 */\n      padding: 8px 12px;\n      gap: 10px;\n      border-bottom: 1px solid #444;\n      flex-shrink: 0;\n      position: relative;\n      z-index: 20;  /* 确保在视频之上 */\n    }\n    .url-text {\n      flex: 1;\n      color: #0f0;\n      font-family: monospace;\n      font-size: 12px;\n      word-break: break-all;\n      max-height: 60px;\n      overflow-y: auto;\n      background: #2d2d2d;\n      padding: 6px 8px;\n      border-radius: 4px;\n    }\n    .copy-btn {\n      background: #007bff;\n      border: none;\n      color: white;\n      padding: 6px 12px;\n      border-radius: 4px;\n      cursor: pointer;\n      font-size: 12px;\n      flex-shrink: 0;\n      position: relative;\n      z-index: 21;\n      pointer-events: auto; /* 确保可点击 */\n    }\n    .copy-btn:active {\n      background: #0056b3;\n    }\n    .video-wrapper {\n      flex: 1;\n      position: relative;\n      background: #000;\n      min-height: 0;\n    }\n    video {\n      width: 100%;\n      height: 100%;\n      object-fit: contain;\n    }\n  </style>\n  <script src=\"https://unpkg.com/hls.js@1.4.3/dist/hls.min.js\"></script>\n</head>\n<body>\n<div class=\"container\">\n  <div class=\"title\">{{$.rescont.title}}</div>\n  <div class=\"url-bar\">\n    <div class=\"url-text\" id=\"urlText\">加载中...</div>\n    <button class=\"copy-btn\" id=\"copyBtn\">复制</button>\n  </div>\n  <div class=\"video-wrapper\">\n    <video id=\"video\" controls autoplay muted loop></video>\n  </div>\n</div>\n\n<script>\nconst v = document.getElementById('video');\nconst urlTextDiv = document.getElementById('urlText');\nconst copyBtn = document.getElementById('copyBtn');\nlet currentUrl = '';\n\nconst s = [\n  \"{{$.rescont.videopath}}\",\n  \"\"\n];\nlet c = 0;\n\nfunction updateUrlDisplay(url) {\n  currentUrl = url || '';\n  urlTextDiv.innerText = currentUrl || '无地址';\n}\n\nfunction copyUrl() {\n  if (!currentUrl) {\n    alert('没有可复制的地址');\n    return;\n  }\n  navigator.clipboard.writeText(currentUrl).then(() => {\n    const originalText = copyBtn.innerText;\n    copyBtn.innerText = '已复制';\n    setTimeout(() => {\n      copyBtn.innerText = originalText;\n    }, 1500);\n  }).catch(err => {\n    alert('复制失败: ' + err);\n  });\n}\ncopyBtn.addEventListener('click', copyUrl);\n\nfunction setupCustomControls(e) {\n  // 自定义功能（原逻辑保留）\n}\n\nfunction playNext() {\n  if (c >= s.length) c = 0;\n  const u = s[c++];\n  updateUrlDisplay(u);\n\n  if (typeof Hls !== 'undefined' && Hls.isSupported()) {\n    const h = new Hls({\n      enableSoftwareAES: true,\n      forceKeyFrameOnDiscontinuity: true\n    });\n    h.loadSource(u);\n    h.attachMedia(v);\n    h.on(Hls.Events.MANIFEST_PARSED, () => {\n      v.play().then(() => setupCustomControls(v)).catch(console.log);\n    });\n    h.on(Hls.Events.ERROR, (_, d) => {\n      if (d.fatal) playNext();\n    });\n  } else {\n    if (v.canPlayType('application/vnd.apple.mpegurl')) {\n      v.src = u;\n      v.onloadedmetadata = () => v.play().then(() => setupCustomControls(v));\n      v.onerror = playNext;\n    } else {\n      v.src = u;\n      v.onerror = playNext;\n      v.play().then(() => setupCustomControls(v)).catch(playNext);\n    }\n  }\n}\n\nplayNext();\n</script>\n</body>\n</html>",
    "ruleImage": "{{$.coverbase64.url}}",
    "ruleLink": "/api/videoplay/{{$.id}}?uuid=1",
    "ruleNextPage": "$.rescont.next_page_url",
    "rulePubDate": "📆{{$.updated_at## .*}}  ⏱️{{$.playtimes}}",
    "ruleTitle": "$.title##.*屎.*|.*Ts.*|.*TS.*|.*ts.*|.*伪娘.*|.*人妖.*|.*男同.*|.*mbrba.*|.*水果派.*|.*解说.*|.*mmraa.*|.*ss-.*|.*fway.*|.*rebd.*|.*mbdd.*|.*双性.*|.*妈妈.*|.*儿子.*|.*爸爸.*|.*女儿.*|.*母子.*|.*父女.*|.*熟女.*|.*眼射.*|.*直男.*|.*CD.*|.*肥女.*|.*黄金.*|.*骚0.*|.*gv.*|.*父子.*|.*飞机.*|.*撸.*|.*厕.*|.*老阿姨.*|.*乱伦.*",
    "singleUrl": false,
    "sortUrl": "\n随机::/api/videosort/0?page={{ Math.ceil(Math.random()*1500) }}\n最新::/api/videosort/0?page={{page}}\n🔎搜索::/api/videosort/0?serach={{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('强奸');source.getVariable()}}&page={{page}}\n国产自拍::/api/videosort/10?page={{page}}\nH动漫::/api/videosort/14?page={{page}}\n扶她姐妹::/api/videosort/58?page={{page}}\n国产AV::/api/videosort/60?page={{page}}\n网红主播::/api/videosort/17?page={{page}}\n嫩模专区::/api/videosort/37?page={{page}}\n偷拍盗摄::/api/videosort/53?page={{page}}\n萌妹酱篇::/api/videosort/54?page={{page}}\n精彩短片::/api/videosort/55?page={{page}}\n外流视频::/api/videosort/32?page={{page}}\n明星淫梦::/api/videosort/40?page={{page}}\n鹿少女集::/api/videosort/56?page={{page}}\n高清无码::/api/videosort/1?page={{page}}\n制服诱惑::/api/videosort/5?page={{page}}\n长腿丝袜::/api/videosort/11?page={{page}}\nAV剧情::/api/videosort/29?page={{page}}\nAV素人::/api/videosort/24?page={{page}}\n淫荡痴女::/api/videosort/51?page={{page}}\n巨乳咪咪::/api/videosort/20?page={{page}}\n人妻熟女::/api/videosort/6?page={{page}}\n近亲乱伦::/api/videosort/49?page={{page}}\n淫乱师生::/api/videosort/46?page={{page}}\n角色扮演::/api/videosort/4?page={{page}}\n青春萝莉::/api/videosort/22?page={{page}}\n魔镜系列::/api/videosort/39?page={{page}}\n中文无码::/api/videosort/57?page={{page}}\n当红女优::/api/videosort/9?page={{page}}\n中文字幕::/api/videosort/19?page={{page}}\n259LUXU::/api/videosort/36?page={{page}}\n重咸口味::/api/videosort/23?page={{page}}\n丝瓜推荐::/api/videosort/30?page={{page}}\n三级电影::/api/videosort/25?page={{page}}\n电车之狼::/api/videosort/52?page={{page}}\n中外合拍::/api/videosort/59?page={{page}}\n苍老师::/api/videosort/44?page={{page}}\n女同性爱::/api/videosort/38?page={{page}}\n欧美AV::/api/videosort/16?page={{page}}\n恐怖情色::/api/videosort/35?page={{page}}",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "🌈丝瓜    S",
    "sourceUrl": "https://api.sgapiaba.xyz",
    "style": ".container {\n    position: relative; /* 相对定位，用于包含视频 */\n    height: 100%; /* 容器高度与视频原始高度相同 */\n    overflow: hidden; /* 隐藏超出容器的部分 */\n}\n.title {\n    position: absolute; /* 绝对定位，相对于容器 */\n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; /* 确保标题在视频之上 */\n    background: #000; /* 纯黑色背景 */ \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; /* 绝对定位，相对于容器 */ \n    top: -65px; /* 上移80px */\n    left: 0; \n    width: 100%; \n    height: calc(96% + 65px);  /* 调整高度以适应内容 */\n    object-fit: contain; /* 确保视频内容不被裁剪 */\n    z-index: 0; /* 确保视频在标题之下 */\n    controls=\"controls\" autoplay muted; \n} \n"
  },
  {
    "articleStyle": 0,
    "customOrder": 4750,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "{\n\t\"User-Agent\":\"Mozilla/5.0 (Linux; Android 11; Pixel 3 XL Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.4988.0 Mobile Safari/537.36 SearchCraft/3.9.2 (Baidu; P1 11)\",\n\t\"referer\": \"{{baseUrl}}\"\n}",
    "injectJs": "function setupCustomPlayer(video) {\n  // 手势滑动快进\n  let isDragging = false;\n  let startX = 0;\n  let startTime = 0;\n  \n  // 长按加速相关变量\n  let longPressTimer = null;\n  const LONG_PRESS_DELAY = 300;\n  const NORMAL_SPEED = 1.25;\n  const FAST_SPEED = 3;\n  let wasPaused = false;\n\n  // 触摸事件处理\n  function handleTouchStart(e) {\n    startX = e.touches[0].clientX;\n    startTime = video.currentTime;\n    wasPaused = video.paused;\n    \n    longPressTimer = setTimeout(() => {\n      video.playbackRate = FAST_SPEED;\n      if (wasPaused) video.play();\n    }, LONG_PRESS_DELAY);\n  }\n\n  function handleTouchMove(e) {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    const dx = e.touches[0].clientX - startX;\n    if (Math.abs(dx) > 10) {\n      if (!isDragging) {\n        video.pause();\n        isDragging = true;\n      }\n      const change = (dx / video.clientWidth) * video.duration;\n      video.currentTime = Math.max(0, Math.min(startTime + change, video.duration));\n    }\n  }\n\n  function handleTouchEnd() {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      longPressTimer = null;\n    }\n    \n    if (isDragging) {\n      video.playbackRate = NORMAL_SPEED;\n      video.play();\n      isDragging = false;\n    } else if (video.playbackRate === FAST_SPEED) {\n      video.playbackRate = NORMAL_SPEED;\n      if (wasPaused) video.pause();\n    }\n  }\n\n  // 添加触摸事件监听\n  video.addEventListener('touchstart', handleTouchStart);\n  video.addEventListener('touchmove', handleTouchMove);\n  video.addEventListener('touchend', handleTouchEnd);\n  \n  // 初始播放速度\n  video.playbackRate = NORMAL_SPEED;\n\n  // 创建按钮的通用函数\n  function createButton(text, onClick, position, width = '20px') {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.position = 'absolute';\n    button.style[position.horizontal] = '0';\n    button.style.top = '50%';\n    button.style.transform = 'translateY(-50%)';\n    button.style.zIndex = '999';\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = width;\n    button.style.height = '30px';\n    button.addEventListener('click', onClick);\n    video.parentNode.appendChild(button);\n    return button;\n  }\n\n  // 旋转按钮（右侧）\n  createButton('⟳', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    const newRotation = (currentRotation + 90) % 360;\n    video.setAttribute('data-rotation', newRotation);\n    \n    // 保留当前的缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    video.style.transform = `rotate(${newRotation}deg) scale(${currentScale})`;\n  }, { horizontal: 'right' });\n\n  // 缩放按钮（左侧）\n  let zoomCount = 0;\n  createButton('+', () => {\n    const currentRotation = parseInt(video.getAttribute('data-rotation') || '0');\n    \n    // 获取当前缩放比例\n    const currentTransform = video.style.transform || '';\n    let currentScale = 1;\n    const scaleMatch = currentTransform.match(/scale\\(([^)]+)\\)/);\n    if (scaleMatch) currentScale = parseFloat(scaleMatch[1]);\n    \n    if (zoomCount < 4) {\n      const newScale = currentScale * 1.25;\n      video.style.transform = `rotate(${currentRotation}deg) scale(${newScale})`;\n      zoomCount++;\n    } else {\n      video.style.transform = `rotate(${currentRotation}deg) scale(1)`;\n      zoomCount = 0;\n    }\n  }, { horizontal: 'left' });\n\n  // 快速跳转按钮（底部中央）\n  const buttonContainer = document.createElement('div');\n  buttonContainer.style.position = 'absolute';\n  buttonContainer.style.bottom = '0';\n  buttonContainer.style.left = '50%';\n  buttonContainer.style.transform = 'translateX(-50%)';\n  buttonContainer.style.display = 'flex';\n  buttonContainer.style.gap = '10px';\n  buttonContainer.style.zIndex = '999';\n  \n  // 按钮配置\n  const seekButtons = [\n    { text: '-5分', time: -300 },\n    { text: '-1分', time: -60 },\n    { text: '+1分', time: 60 },\n    { text: '+5分', time: 300 }\n  ];\n\n  seekButtons.forEach(({ text, time }) => {\n    const button = document.createElement('button');\n    button.textContent = text;\n    button.style.padding = '1px';\n    button.style.background = 'rgba(51, 51, 51, 0)';\n    button.style.color = '#fff';\n    button.style.border = 'none';\n    button.style.cursor = 'pointer';\n    button.style.width = '60px';\n    button.style.height = '30px';\n    button.addEventListener('click', () => {\n      video.currentTime = Math.max(0, Math.min(video.currentTime + time, video.duration));\n    });\n    buttonContainer.appendChild(button);\n  });\n\n  video.parentNode.appendChild(buttonContainer);\n}\n\n// 直接初始化避免额外事件\nconst video = document.getElementById('video');\nif (video) setupCustomPlayer(video);",
    "lastUpdateTime": 1775591752645,
    "loadWithBaseUrl": true,
    "ruleArticles": "<js>\nresult = java.ajax(source.sourceUrl + \"go.js\");\nvar urlMatch = result.match(/top\\.location\\s*=\\s*['\"](https?:\\/\\/[^\\/'\"]+)/);\nif (urlMatch) {\n    A = urlMatch[1];} else {\n    A = source.sourceUrl;}\njava.put('url', A);\npath = baseUrl.replace(/^https?:\\/\\/[^\\/]+/, '');\nB = A + path;\njava.put('next', B);\njava.ajax(B);\n</js>\n.stui-vodlist__box",
    "ruleContent": "{{@@script@all##\"url\":\"(.*)\",\"url##$1##}}\n@js:\nresult = result.replace(/\\\\+/g, '');\n\nresult = `\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\">\n<style>\nhtml, body { text-align:center; margin:0; padding:0; width:100%; overflow:hidden; }\n</style>\n<!-- 引入CryptoJS库 -->\n<script src=\"https://s4.zstatic.net/ajax/libs/crypto-js/4.1.1/crypto-js.min.js\"></script>\n</head>\n<body>\n<div class=\"container\">\n<div class=\"title\">{{@@h4.0@text##.*:}}</div>\n<video id=\"video\" width=\"100%\" height=\"90%\" poster=\"{{java.get('pic')}}\" controls autoplay muted loop></video>\n</div>\n\n<script>\n(function() {\n// 配置解密参数\nconst key = CryptoJS.enc.Latin1.parse('9q4h7kt7skwsc9af1qmwy14jkfq2biab');\nconst iv = CryptoJS.enc.Latin1.parse('6b3gslw69k6eazmw');\nconst encryptedUrl = \"${result}\"; // 注入加密URL\n\ntry {\n// 1. 预处理URL\nlet base64Str = encryptedUrl\n.replace(/-/g, '+') // URL安全Base64替换\n.replace(/_/g, '/');\n\n// 2. Base64补全\nconst pad = base64Str.length % 4;\nif (pad) base64Str += '===='.slice(0, 4 - pad);\n\n// 3. 解密流程\nconst encryptedData = CryptoJS.enc.Base64.parse(base64Str);\nconst decrypted = CryptoJS.AES.decrypt(\n{ ciphertext: encryptedData },\nkey,\n{ iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding }\n);\n\n// 4. 处理解密结果\nconst decryptedStr = decodeURIComponent(\nCryptoJS.enc.Latin1.stringify(decrypted)\n);\nconst parts = decryptedStr.split(',');\n\nif (parts.length !== 5) throw new Error('无效解密数据');\nconst realUrl = \\`https://cdn-m.asujp.com:59888/f/\\${parts[0]}/\\${parts[1]}/\\${parts[2]}/play.m3u8?_KS=\\${parts[3]}&_KE=\\${parts[4]}\\`;\n\n// 5. 动态设置视频源\ndocument.getElementById('video').src = realUrl;\n} catch (e) {\ndocument.body.innerHTML = '视频解析失败: ' + e.message;\n}\n})();\n</script>\n</body>\n</html>\n`;\nresult",
    "ruleImage": "{{@@a@data-original}}\n<js>\njava.put('pic',result)\n</js>",
    "ruleLink": "{{java.get('url')}}{{@@a.0@href}}",
    "ruleNextPage": "@js:\nvar A = java.get('next'); \nvar B = java.ajax(A);\nvar C = java.get('url'); \nvar D = B.match(/<a [^>]*href=\"([^\"]+)\"[^>]*>\\s*下一页\\s*<\\/a>/i);\nnextPageUrl = D ? (C + D[1]) : \"\";\n",
    "rulePubDate": "{{@@span@text}}\n@js:\nresult = result !== \"\" ? result : \"点击播放\";",
    "ruleTitle": "h4@text##.*屎.*|.*喝尿.*|.*Ts.*|.*ts.*|.*伪娘.*|.*伪男.*|.*人妖.*|.*男同.*|.*狼狗.*|.*奶狗.*|.*鲜肉.*|.*帅哥.*|.*正装.*|.*猛1.*|.*ZKtop1.*|.*体育生.*|.*双性.*|.*男男.*|.*直男.*|.*gv.*|.*父子.*|.*飞机.*|.*撸.*|.*女性向.*|.*骚0.*|.*poop.*|.*男奴.*|.*奴男.*|.*同志.*|.*苏木.*|.*西装.*|.*骚受.*|.*QS.*|.*Peter.*|.*摔跤社.*|.*基情.*|.*天菜.*|.*大鸡.*|.*肌肉.*|.*薄肌.*|.*G片.*|.*术0.*|.*宏翔.*|.*男蜜.*|.*自制口.*|.*威廉.*|.*骚男.*|.*基友.*|.*美男子.*|.*鸡儿.*",
    "singleUrl": false,
    "sortUrl": "\n随机::/index.php/vod/type/id/{{ Math.floor(Math.random()*3) +1}}/page/{{ Math.ceil(Math.random()*440) }}.html\n\n🔎搜索::/index.php/vod/search.html?wd={{v=source.getVariable();if(/^\\s*$/.test(v)||v==null)source.setVariable('奸');source.getVariable()}}\n\n国产::/index.php/vod/type/id/1.html\n无码::/index.php/vod/type/id/2.html\n有码::/index.php/vod/type/id/3.html\n黑料::/index.php/vod/type/id/7.html\n欧美::/index.php/vod/type/id/4.html\n三级::/index.php/vod/type/id/6.html\n动漫::/index.php/vod/type/id/5.html",
    "sourceComment": "备用地址\nhttp://3.j332.cc/\nhttp://k587.cc/\ng396.cc\n",
    "sourceGroup": "视频",
    "sourceIcon": "https://img0.baidu.com/it/u=2908908160,2785784129&fm=253&fmt=auto&app=138&f=PNG",
    "sourceName": "YourPorn",
    "sourceUrl": "https://x13wbc2zweq43.com:58011/",
    "style": ".container {\n    position: relative; /* 相对定位，用于包含视频 */\n    height: 100%; /* 容器高度与视频原始高度相同 */\n    overflow: hidden; /* 隐藏超出容器的部分 */\n}\n.title {\n    position: absolute; /* 绝对定位，相对于容器 */\n    top: 0; \n    width: 100%;\n    overflow: hidden; \n    text-overflow: ellipsis;\n    display: -webkit-box;\n    -webkit-box-orient: vertical; \n    -webkit-line-clamp: 2;\n    z-index: 1; /* 确保标题在视频之上 */\n    background: #000; /* 纯黑色背景 */ \n    padding: 0 0 3px 0;\n}\nvideo {\n    position: absolute; /* 绝对定位，相对于容器 */ \n    top: +20px; /* 视频上移 */\n    left: 0; \n    width: 100%; \n    height: calc(93% + 0px);  /* 调整高度以适应内容 */\n    object-fit: contain; /* 确保视频内容不被裁剪 */\n    z-index: 0; /* 确保视频在标题之下 */\n    controls=\"controls\" autoplay muted; \n} \n"
  },
  {
    "articleStyle": 2,
    "customOrder": 4751,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
    "injectJs": "(function() {\n    console.log('验证码脚本启动');\n    \n    // 延迟执行，确保页面加载完成\n    setTimeout(function() {\n        // 查找所有文本节点，寻找数学问题\n        const walker = document.createTreeWalker(\n            document.body,\n            NodeFilter.SHOW_TEXT,\n            null,\n            false\n        );\n        \n        let node;\n        while (node = walker.nextNode()) {\n            const text = node.textContent.trim();\n            // 简单的数字运算匹配\n            if (text.match(/\\d+\\s*[\\+\\-\\*/]\\s*\\d+/)) {\n                console.log('发现数学问题:', text);\n                \n                // 尝试填写\n                const inputs = document.getElementsByTagName('input');\n                for (let input of inputs) {\n                    if (input.type === 'text') {\n                        // 简单计算 1+1 作为测试\n                        input.value = '2';\n                        input.dispatchEvent(new Event('input'));\n                        console.log('已尝试填写验证码');\n                        break;\n                    }\n                }\n            }\n        }\n    }, 2000);\n})();",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "li:has(img)||ul@li||div@li",
    "ruleContent": "<!DOCTYPE html>\r\n<html>\r\n\r\n<head>\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\r\n    <link rel=\"stylesheet\" href=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.1/viewer.min.css\">\r\n    <script src=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.1/viewer.min.js\"></script>\r\n    <script src=\"http://libs.baidu.com/jquery/2.0.0/jquery.min.js\"></script>\n    {{@@tag.title@html}}\r\n</head>\r\n\r\n<body>\r\n    <h3>{{@@.h@tag.h1@text}}</h3>\r\n    <div id=\"box\">{{@@id.picg@tag.img@html}}</div>\r\n    <div id=\"loads\">加载中...</div>\r\n    <script>\r\n        var loads;\r\n        $(document).ready(function () {\r\n            var box = document.getElementById(\"box\");\r\n            loads = document.getElementById(\"loads\");\r\n            new Viewer(box, { title: false, interval: 3000 })\r\n            var i = 2;\r\n            // 尝试获取总页数，如果获取失败默认给个大一点的数字或者1\r\n            var pageStr = \"{{@@class.pagelist.0@tag.a.-2@textNodes##\\\\n}}\";\r\n            var page = parseInt(pageStr);\r\n            if(isNaN(page)) page = 100; // 容错处理\r\n            \r\n            var url = \"{{baseUrl.replace('.html','_')}}\";\r\n            \r\n            new IntersectionObserver(entries => {\r\n                if (entries[0].intersectionRatio) {\r\n                    if (entries[0].intersectionRatio <= 0) return;\r\n                    if (i <= page) {\r\n                        fetchHtml(i, page, url);\r\n                        i += 1;\r\n                    } else {\r\n                        $('#loads').html(\"已显示全部\");\r\n                    }\r\n                }\r\n            }).observe(loads)\r\n        });\r\n\r\n\r\n        function fetchHtml(i, page, url) {\n            nurl = url + i + '.html';\r\n            $.ajax({\r\n                url: nurl,\r\n                dataType: 'html',\r\n                success: function (html) {\r\n                    $('#box').append('<h5>' + (i) + '/' + (page) + '</h5>');\r\n                    // 修正：使用 #picg img 选择器，与主规则一致\r\n                    var newImg = $(html).find('#picg img');\r\n                    if(newImg.length === 0) {\r\n                        // 备用选择器，防止ID变化\r\n                        newImg = $(html).find('.content img, img');\r\n                    }\r\n                    $('#box').append(newImg);\r\n                    box.viewer.update();\r\n                },\r\n                error: function (xhr) { \r\n                    $('#loads').html(\"加载失败\");\r\n                }\r\n            });\r\n        }\r\n    </script>\r\n</body>\r\n\r\n</html>",
    "ruleImage": "img@lazy-src",
    "ruleLink": "a@href",
    "ruleNextPage": "page",
    "ruleTitle": "class.title@text",
    "singleUrl": false,
    "sortUrl": "\n今日更新::/\n\n套图::/shey/yingtiiurm/1_{{page}}.html\n\n日韩::/shey/yingtiiurm/2_{{page}}.html\n\n内衣::/shey/yingtiiurm/9_{{page}}.html\n\n萌妹::/shey/yingtiiurm/11_{{page}}.html\n\n精品::/shey/yingtiiurm/18_{{page}}.html\n\n高清::/shey/yingtiiurm/24_{{page}}.html\n\n无圣光::/shey/yingtiiurm/25_{{page}}.html",
    "sourceComment": "可以换着看，大部分不一样\n摄影图库：http://www.sytuk.com\n精品美女图:http://www.akywt.com\n私房妹子图:http://www.gqsft.com\n高清尤物图:http://www.flsft.com\n私拍尤物图:http://www.mtgqt.com\n性感尤物图:http://www.akxzt.com\n私拍美女图:http://www.sfsnt.com\n极品尤物图:http://www.mtsyt.com\n高清私房图:http://www.jpnst.com\n漂亮网红图:http://www.sfwht.com\n尤物嫩模图:http://www.ywnmt.com\n经典网红图:http://www.jcmeinv.com\n模特网红图:http://www.mtmnw.com\n特色写真图:http://www.jpsft.com.com\n高清网红图:http://www.jpmnt.com\n福利网红图:http://www.sfmtw.com\n高清妹子图:http://www.gqtuku.com\n少女私房图:http://www.sntaotu.com\n极品美女图:http://www.xzmeinv.com\n免费私房图:http://www.mtflt.com\n私房网红图:http://www.gqsft.com",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "摄影",
    "sourceUrl": "http://www.sytuk.com",
    "style": "/*标题相关*/\r\nh3{text-align:center}\r\nh6{margin-bottom:0}\r\nimg{width:100%}\nh5{margin-bottom:0;padding-left:5;text-align:center;color:#666;font-size:12px;}"
  },
  {
    "articleStyle": 0,
    "customOrder": 4752,
    "enableJs": true,
    "enabled": false,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "摄影图库",
    "sourceUrl": "http://www.sytuk.com/"
  },
  {
    "articleStyle": 2,
    "customOrder": 4753,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 1773223654663,
    "loadWithBaseUrl": true,
    "ruleArticles": "",
    "ruleContent": "",
    "ruleImage": "",
    "ruleLink": "",
    "ruleNextPage": "",
    "rulePubDate": "",
    "ruleTitle": "",
    "singleUrl": false,
    "sortUrl": "首页::page/{{page}}/\n萝莉COS::/index.php/mntu/1/{{page}}/\n网红COS::/index.php/mntu/2/{{page}}/\n轻兰映画::/index.php/mntu/3/{{page}}/\n韩国美女::/index.php/mntu/4/{{page}}/\n丝袜美女::/index.php/mntu/130/{{page}}/\n动漫美女::/index.php/mntu/137/{{page}}/\nJK制服::/index.php/mntu/175/{{page}}/",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "萌图社",
    "sourceUrl": "https://www.446m.com/"
  },
  {
    "articleStyle": 2,
    "customOrder": 4754,
    "enableJs": true,
    "enabled": false,
    "enabledCookieJar": true,
    "header": "",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "loginUrl": "",
    "ruleArticles": "id.masonry.0@class.item",
    "ruleContent": ".content@tag.img@data-original##\\n##\\$\n\n<js>\nli='\\n'\njava.log(result)\nlist=result.split('$')\nfor(i in list){\n\t     if(list[i].length<20) break;\n\t\tli += '<li><img src=\"/static/thumbnail.gif\" data-src=\"'+list[i]+'\"></li>\\n';\n\t}\nli\n</js>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n\n\n<ul id=\"box\">\n{{result}}\n</ul>\n<h3>{{@@.song-info@h3@text}}</h3>\r\n<h6>{{@@id.myList@h4@text}}</h6>\n\n<link rel=\"stylesheet\" href=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.1/viewer.min.css\">\r\n<script src=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.1/viewer.min.js\"></script>\n<script>\n\troot = document.getElementById('box')\n\tlazy = new IntersectionObserver(entires => {\n\t\tentires.forEach(item => {\n\t\t\tif(item.isIntersecting){\n\t\t\t\titem=item.target\n\t\t\t\titem.src=item.getAttribute('data-src')\n\t\t\t\tlazy.unobserve(item)\n\t\t\t}\n\t\t})\n\t}, {\n\t\troot: root,\n\t\tthreshold: [0],\n\t\trootMargin:\"0px 0px 500px 0px\"\n\t})\n\nimgs = document.getElementsByTagName('img')\nArray.from(imgs).forEach(item => {\n\t\tlazy.observe(item)\n\t})\n\n//查看大图插件\nnew Viewer(root,{title:false,interval:3000})\n</script>",
    "ruleImage": "tag.img.0@data-original",
    "ruleLink": "tag.a.0@href",
    "ruleNextPage": "page",
    "rulePubDate": "class.item-sort.0@text",
    "ruleTitle": "class.item-link-text.0@text",
    "singleUrl": false,
    "sortUrl": "搜索::https://www.63721685.xyz/search/{{source.getVariable()}}\nR18::https://www.63721685.xyz/sort/r18.html#cate_r18\nR15::https://www.63721685.xyz/sort/r15.html#cate_r15\n随机R15::/sort/r15.html/{{ Math.ceil(Math.random()*690) }}/\n随机R18::/sort/r18.html/{{ Math.ceil(Math.random()*309) }}/",
    "sourceComment": "https://www.sshs.pw/",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "绅士会所",
    "sourceUrl": "https://www.63721685.xyz/",
    "style": "* {\n\tmargin: 0;\n\tpadding: 0\n}\nul {\n\tfont-size: 0;\n\theight: 100%;\n\toverflow-y: scroll\n}\nli {\n\tlist-style: none;\n\ttext-align: center\n}\nimg {\n\twidth: 100%;\n\theight: auto\n}"
  },
  {
    "articleStyle": 0,
    "customOrder": 4756,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "绅士",
    "sourceUrl": "https://www.63721685.xyz"
  },
  {
    "articleStyle": 2,
    "customOrder": 4757,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n  \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\",\n  \"Referer\": \"https://meirentu.club/\"\n}",
    "lastUpdateTime": 1769069467887,
    "loadWithBaseUrl": true,
    "ruleArticles": "li.i_list",
    "ruleContent": "<!doctype html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<title>{{@@title@text}}</title>\n<style>\nbody {\n    margin: 0;\n    font: 14px/1.4 sans-serif;\n    background: #111;\n    color: #eee;\n}\n\n#msg {\n    position: sticky;\n    top: 0;\n    z-index: 9;\n    background: #222;\n    padding: 8px 12px;\n    text-align: center;\n    font-size: 13px;\n}\n\n#imgList {\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: center;\n    padding: 8px;  /* 容器左右边距 */\n    box-sizing: border-box;\n}\n\n#imgList img {\n    display: block;\n    width: 100%;              /* 占满宽度 */\n    max-width: 100%;          /* 防止溢出 */\n    height: auto;\n    min-height: 220px;\n    margin: 6px 0;            /* 只保留上下间距 */\n    border-radius: 4px;\n    background: #222;\n    box-sizing: border-box;\n}\n</style>\n</head>\n<body>\n\n<!-- 实时提示 -->\n<div id=\"msg\">瀑布流初始化完成，向下滚动加载更多~</div>\n\n<!-- 图片容器 -->\n<div id=\"imgList\">\n{{@@class.content_left@img@all}}\n</div>\n\n<script>\n/*** 配置区 ***/\nconst pageUrls = `{{@@class.page@a:not(.current)@href}}`\n  .split('\\n')\n  .map(s => s.trim())\n  .filter(Boolean)\n // .slice(0,2) //选取前三页，测试用\nlet nextIndex = 0;\n\n/*** 页面元素 ***/\nconst imgList = document.getElementById('imgList');\nconst msgBox = document.getElementById('msg');\n\n/*** 工具函数 ***/\nfunction showMsg(text) {\n  if (msgBox) msgBox.textContent = text;\n}\n\n// 使用 iframe 加载\nfunction loadPageInIframe(url) {\n  return new Promise((resolve, reject) => {\n    const iframe = document.createElement('iframe');\n    iframe.style.display = 'none';\n    \n    // 超时处理\n    const timeout = setTimeout(() => {\n      document.body.removeChild(iframe);\n      reject(new Error('请求超时'));\n    }, 10000);\n    \n    iframe.onload = () => {\n      try {\n        clearTimeout(timeout);\n        const doc = iframe.contentDocument;\n        \n        // 查找图片（多重选择器兼容）\n        let imgs = doc.querySelectorAll('.content_left img');\n        if (imgs.length === 0) imgs = doc.querySelectorAll('.content img');\n        if (imgs.length === 0) imgs = doc.querySelectorAll('article img');\n        \n        const urls = Array.from(imgs, img => img.src);\n        \n        document.body.removeChild(iframe);\n        resolve(urls);\n      } catch (e) {\n        document.body.removeChild(iframe);\n        reject(e);\n      }\n    };\n    \n    iframe.onerror = (e) => {\n      clearTimeout(timeout);\n      document.body.removeChild(iframe);\n      reject(new Error('网络错误'));\n    };\n    \n    iframe.src = url;\n    document.body.appendChild(iframe);\n  });\n}\n\n// 使用正则表达式提取（备选方案）\nfunction extractImagesByRegex(html) {\n  const urls = [];\n  // 提取 content_left 区域\n  const areaMatch = html.match(/class=\"content_left\"[\\s\\S]*?<\\/div>/i);\n  const searchHtml = areaMatch ? areaMatch[0] : html;\n  \n  // 提取所有 img src\n  const regex = /<img[^>]+src=[\"']?([^\"'\\s>]+)[\"']?[^>]*>/gi;\n  let match;\n  \n  while ((match = regex.exec(searchHtml)) !== null) {\n    let src = match[1];\n    if (src.startsWith('/')) src = 'https://meirentu.club' + src;\n    if (src.startsWith('http')) urls.push(src);\n  }\n  \n  return urls;\n}\n\n// 获取图片列表（主逻辑）\nasync function getImages(url) {\n  showMsg(`加载中: ${url}`);\n  \n  try {\n    // 方案1：优先使用 iframe（最兼容）\n    return await loadPageInIframe(url);\n  } catch (e1) {\n    showMsg(`iframe失败，尝试正则解析...`);\n    try {\n      // 方案2：降级为 fetch + 正则\n      const resp = await fetch(url);\n      if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n      const html = await resp.text();\n      return extractImagesByRegex(html);\n    } catch (e2) {\n      throw new Error(`双重失败: ${e2.message}`);\n    }\n  }\n}\n\n// 追加图片\nfunction appendImages(urls) {\n  if (!urls || !urls.length) return;\n  \n  urls.forEach(src => {\n    const img = document.createElement('img');\n    img.src = src;\n    img.style.cssText = 'display:block;width:300px;height:auto;min-height:220px;margin:6px;border-radius:4px;background:#222;';\n    imgList.appendChild(img);\n  });\n}\n\n// 滚动加载\nlet isLoading = false;\nlet retryCount = 0;\nconst maxRetry = 3;\n\nasync function loadMore() {\n  if (isLoading || nextIndex >= pageUrls.length) {\n    if (nextIndex >= pageUrls.length) showMsg('已加载全部');\n    return;\n  }\n  \n  isLoading = true;\n  const url = pageUrls[nextIndex];\n  \n  try {\n    const urls = await getImages(url);\n    \n    if (!urls.length) throw new Error('未找到图片');\n    \n    appendImages(urls);\n    nextIndex++;\n    retryCount = 0; // 重置重试计数\n    \n    showMsg(`已加载 ${nextIndex}/${pageUrls.length} 页`);\n    \n    // 重新监听\n    setTimeout(() => {\n      isLoading = false;\n      observeLast();\n    }, 500);\n    \n  } catch (error) {\n    retryCount++;\n    showMsg(`第${nextIndex + 1}页失败(${retryCount}/${maxRetry}): ${error.message}`);\n    \n    if (retryCount >= maxRetry) {\n      showMsg(`跳过第${nextIndex + 1}页`);\n      nextIndex++;\n      retryCount = 0;\n      // 继续下一页\n      setTimeout(loadMore, 1000);\n    } else {\n      // 重试当前页\n      setTimeout(() => {\n        isLoading = false;\n        loadMore();\n      }, 2000);\n    }\n  }\n}\n\n// IntersectionObserver 监听最后一张图\nlet observer = null;\nfunction observeLast() {\n  if (observer) observer.disconnect();\n  \n  const im",
    "ruleImage": "img@data-src||img@src",
    "ruleLink": "a.0@href",
    "ruleNextPage": ".current+a@href||a[aria-label=\"Next\"]@href",
    "rulePubDate": "{{@@span.0@text}}  {{@@span.1@text}}",
    "ruleTitle": ".meta-title@text",
    "singleUrl": false,
    "sortUrl": "搜索::https://meirentu.club/s/{{source.getVariable()}}-1.html\n首页::/\n热门精选::/hots.html\nXiuRen秀人网::/group/XiuRen-1.html\nMFStar模范学院::/group/MFStar-1.html\nMiStar魅妍社::/group/MiStar-1.html\nMyGirl美媛馆::/group/MyGirl-1.html\nImiss爱蜜社::/group/Imiss-1.html\nBoLoli兔几盟::/group/BoLoli-1.html\nYouWu尤物馆::/group/YouWu-1.html\nUxing优星馆::/group/Uxing-1.html\nMiiTao蜜桃社::/group/MiiTao-1.html\nFeiLin嗲囡囡::/group/FeiLin-1.html\nWingS影私荟::/group/WingS-1.html\nTaste顽味生活::/group/Taste-1.html\nLeYuan星乐园::/group/LeYuan-1.html\nHuaYan花の颜::/group/HuaYan-1.html\nDKGirl御女郎::/group/DKGirl-1.html\nMintYe薄荷叶::/group/MintYe-1.html\nYouMi尤蜜荟::/group/YouMi-1.html\nCandy糖果画报::/group/Candy-1.html\nMTMeng模特联盟::/group/MTMeng-1.html\nMicat猫萌榜::/group/Micat-1.html\nHuaYang花漾::/group/HuaYang-1.html\nXingYan星颜社::/group/XingYan-1.html\nXiaoYu画语界::/group/XiaoYu-1.html",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "美人",
    "sourceUrl": "https://meirentu.club "
  },
  {
    "articleStyle": 2,
    "customOrder": 4758,
    "enableJs": true,
    "enabled": false,
    "enabledCookieJar": true,
    "header": "{\n\t \"User-Agent\": \"Mozilla/5.0 (Linux; U; Android 9; zh-cn; MIX 2S Build/PKQ1.180729.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/16.7.35 swan-mibrowser\",\n\t \"Referer\": \"{{baseUrl}}\"\n}",
    "lastUpdateTime": 1780642105465,
    "loadWithBaseUrl": true,
    "ruleArticles": "li.i_list.list_n2",
    "ruleContent": "<!doctype html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<title>{{@@title@text}}</title>\n<style>\nbody {\n    margin: 0;\n    font: 14px/1.4 sans-serif;\n    background: #111;\n    color: #eee;\n}\n\n#msg {\n    position: sticky;\n    top: 0;\n    z-index: 9;\n    background: #222;\n    padding: 8px 12px;\n    text-align: center;\n    font-size: 13px;\n}\n\n#imgList {\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: center;\n    padding: 8px;  /* 容器左右边距 */\n    box-sizing: border-box;\n}\n\n#imgList img {\n    display: block;\n    width: 100%;              /* 占满宽度 */\n    max-width: 100%;          /* 防止溢出 */\n    height: auto;\n    min-height: 220px;\n    margin: 6px 0;            /* 只保留上下间距 */\n    border-radius: 4px;\n    background: #222;\n    box-sizing: border-box;\n}\n</style>\n</head>\n<body>\n\n<!-- 实时提示 -->\n<div id=\"msg\">瀑布流初始化完成，向下滚动加载更多~</div>\n\n<!-- 图片容器 -->\n<div id=\"imgList\">\n{{@@class.content_left@img@all}}\n</div>\n\n<script>\n/*** 配置区 ***/\nconst pageUrls = `{{@@class.page@a:not(.current)@href}}`\n  .split('\\n')\n  .map(s => s.trim())\n  .filter(Boolean)\n // .slice(0,2) //选取前三页，测试用\nlet nextIndex = 0;\n\n/*** 页面元素 ***/\nconst imgList = document.getElementById('imgList');\nconst msgBox = document.getElementById('msg');\n\n/*** 工具函数 ***/\nfunction showMsg(text) {\n  if (msgBox) msgBox.textContent = text;\n}\n\n// 使用 iframe 加载\nfunction loadPageInIframe(url) {\n  return new Promise((resolve, reject) => {\n    const iframe = document.createElement('iframe');\n    iframe.style.display = 'none';\n    \n    // 超时处理\n    const timeout = setTimeout(() => {\n      document.body.removeChild(iframe);\n      reject(new Error('请求超时'));\n    }, 10000);\n    \n    iframe.onload = () => {\n      try {\n        clearTimeout(timeout);\n        const doc = iframe.contentDocument;\n        \n        // 查找图片（多重选择器兼容）\n        let imgs = doc.querySelectorAll('.content_left img');\n        if (imgs.length === 0) imgs = doc.querySelectorAll('.content img');\n        if (imgs.length === 0) imgs = doc.querySelectorAll('article img');\n        \n        const urls = Array.from(imgs, img => img.src);\n        \n        document.body.removeChild(iframe);\n        resolve(urls);\n      } catch (e) {\n        document.body.removeChild(iframe);\n        reject(e);\n      }\n    };\n    \n    iframe.onerror = (e) => {\n      clearTimeout(timeout);\n      document.body.removeChild(iframe);\n      reject(new Error('网络错误'));\n    };\n    \n    iframe.src = url;\n    document.body.appendChild(iframe);\n  });\n}\n\n// 使用正则表达式提取（备选方案）\nfunction extractImagesByRegex(html) {\n  const urls = [];\n  // 提取 content_left 区域\n  const areaMatch = html.match(/class=\"content_left\"[\\s\\S]*?<\\/div>/i);\n  const searchHtml = areaMatch ? areaMatch[0] : html;\n  \n  // 提取所有 img src\n  const regex = /<img[^>]+src=[\"']?([^\"'\\s>]+)[\"']?[^>]*>/gi;\n  let match;\n  \n  while ((match = regex.exec(searchHtml)) !== null) {\n    let src = match[1];\n    if (src.startsWith('/')) src = 'https://meirentu.club' + src;\n    if (src.startsWith('http')) urls.push(src);\n  }\n  \n  return urls;\n}\n\n// 获取图片列表（主逻辑）\nasync function getImages(url) {\n  showMsg(`加载中: ${url}`);\n  \n  try {\n    // 方案1：优先使用 iframe（最兼容）\n    return await loadPageInIframe(url);\n  } catch (e1) {\n    showMsg(`iframe失败，尝试正则解析...`);\n    try {\n      // 方案2：降级为 fetch + 正则\n      const resp = await fetch(url);\n      if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n      const html = await resp.text();\n      return extractImagesByRegex(html);\n    } catch (e2) {\n      throw new Error(`双重失败: ${e2.message}`);\n    }\n  }\n}\n\n// 追加图片\nfunction appendImages(urls) {\n  if (!urls || !urls.length) return;\n  \n  urls.forEach(src => {\n    const img = document.createElement('img');\n    img.src = src;\n    img.style.cssText = 'display:block;width:300px;height:auto;min-height:220px;margin:6px;border-radius:4px;background:#222;';\n    imgList.appendChild(img);\n  });\n}\n\n// 滚动加载\nlet isLoading = false;\nlet retryCount = 0;\nconst maxRetry = 3;\n\nasync function loadMore() {\n  if (isLoading || nextIndex >= pageUrls.length) {\n    if (nextIndex >= pageUrls.length) showMsg('已加载全部');\n    return;\n  }\n  \n  isLoading = true;\n  const url = pageUrls[nextIndex];\n  \n  try {\n    const urls = await getImages(url);\n    \n    if (!urls.length) throw new Error('未找到图片');\n    \n    appendImages(urls);\n    nextIndex++;\n    retryCount = 0; // 重置重试计数\n    \n    showMsg(`已加载 ${nextIndex}/${pageUrls.length} 页`);\n    \n    // 重新监听\n    setTimeout(() => {\n      isLoading = false;\n      observeLast();\n    }, 500);\n    \n  } catch (error) {\n    retryCount++;\n    showMsg(`第${nextIndex + 1}页失败(${retryCount}/${maxRetry}): ${error.message}`);\n    \n    if (retryCount >= maxRetry) {\n      showMsg(`跳过第${nextIndex + 1}页`);\n      nextIndex++;\n      retryCount = 0;\n      // 继续下一页\n      setTimeout(loadMore, 1000);\n    } else {\n      // 重试当前页\n      setTimeout(() => {\n        isLoading = false;\n        loadMore();\n      }, 2000);\n    }\n  }\n}\n\n// IntersectionObserver 监听最后一张图\nlet observer = null;\nfunction observeLast() {\n  if (observer) observer.disconnect();\n  \n  const imgs = imgList.querySelectorAll('img');\n  if (!imgs.length) return;\n  \n  const lastImg = imgs[imgs.length - 1];\n  \n  observer = new IntersectionObserver((entries) => {\n    if (entries[0].isIntersecting && !isLoading) {\n      observer.disconnect();\n      loadMore();\n    }\n  }, {\n    rootMargin: '800px',\n    threshold: 0.01\n  });\n  \n  observer.observe(lastImg);\n}\n\n// 初始化\nshowMsg(`初始化完成，共${pageUrls.length}页待加载`);\nsetTimeout(observeLast, 1000); // 延迟确保图片渲染完成\n\n</script>\n</body>\n</html>",
    "ruleImage": "img@data-src##$##,{\"headers\":{\n\t \"User-Agent\": \"Mozilla/5.0 (Linux; U; Android 9; zh-cn; MIX 2S Build/PKQ1.180729.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/16.7.35 swan-mibrowser\",\n\t \"Referer\": \"{{baseUrl}}\"\n}}",
    "ruleLink": "a.0@href",
    "ruleNextPage": "text.下页@href",
    "rulePubDate": "##(\\d{4}-\\d{2}-\\d{2})##$1###",
    "ruleTitle": ".meta-title@text",
    "singleUrl": false,
    "sortUrl": "XiuRen秀人网::/group/XiuRen-1.html\nMFStar模范学院::/group/MFStar-1.html\nMiStar魅妍社::/group/MiStar-1.html\nMyGirl美媛馆::/group/MyGirl-1.html\nImiss爱蜜社::/group/Imiss-1.html\nBoLoli兔几盟::/group/BoLoli-1.html\nYouWu尤物馆::/group/YouWu-1.html\nUxing优星馆::/group/Uxing-1.html\nMiiTao蜜桃社::/group/MiiTao-1.html\nFeiLin嗲囡囡::/group/FeiLin-1.html\nWingS影私荟::/group/WingS-1.html\nTaste顽味生活::/group/Taste-1.html\nLeYuan星乐园::/group/LeYuan-1.html\nHuaYan花の颜::/group/HuaYan-1.html\nDKGirl御女郎::/group/DKGirl-1.html\nMintYe薄荷叶::/group/MintYe-1.html\nYouMi尤蜜荟::/group/YouMi-1.html\nCandy糖果画报::/group/Candy-1.html\nMTMeng模特联盟::/group/MTMeng-1.html\nMicat猫萌榜::/group/Micat-1.html\nHuaYang花漾::/group/HuaYang-1.html\nXingYan星颜社::/group/XingYan-1.html\nXiaoYu画语界::/group/XiaoYu-1.html",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "美美人",
    "sourceUrl": "https://meirentu.club",
    "style": "#imgList img {\n    width: 100% !important;\n    max-width: 100% !important;\n    height: auto !important;\n}"
  },
  {
    "articleStyle": 0,
    "customOrder": 4759,
    "enableJs": true,
    "enabled": false,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "推图",
    "sourceUrl": "https://m.tuiimg.com/tag/"
  },
  {
    "articleStyle": 2,
    "concurrentRate": "",
    "customOrder": 4760,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "loginUrl": "",
    "ruleArticles": "id.main@tag.li||$",
    "ruleContent": "id.allbtn@text##展开全图\\(1/|\\)\n<js>\nn=Number(result)+1\nu='{{@@id.nowimg@src##1\\.jpg$}}'\n\nlist='\\n'\nfor(i=1;i<n;i++){\n\t\tlist += '<li><img src=\"https://www.tuiimg.com/images/logo.png\" data-src=\"'+u+i+'.jpg\"></li>\\n'\n\t}\nlist\n</js>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">\n\n\n<ul id=\"box\">\n{{result}}\n</ul>\n\n\n<link rel=\"stylesheet\" href=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.1/viewer.min.css\">\r\n<script src=\"https://cdn.bootcdn.net/ajax/libs/viewerjs/1.10.1/viewer.min.js\"></script>\n<script>\n\troot = document.getElementById('box')\n\tlazy = new IntersectionObserver(entires => {\n\t\tentires.forEach(item => {\n\t\t\tif(item.isIntersecting){\n\t\t\t\titem=item.target\n\t\t\t\titem.src=item.getAttribute('data-src')\n\t\t\t\tlazy.unobserve(item)\n\t\t\t}\n\t\t})\n\t}, {\n\t\troot: root,\n\t\tthreshold: [0],\n\t\trootMargin:\"0px\"\n\t})\n\nimgs = document.getElementsByTagName('img')\nArray.from(imgs).forEach(item => {\n\t\tlazy.observe(item)\n\t})\n\n//查看大图插件\nnew Viewer(root,{title:false,interval:3000})\n</script>",
    "ruleImage": "tag.img@realsrc\n@js:\nresult?result:'https://i.tuiimg.net/{{$.catalog}}/{{$.id}}/mc.jpg'",
    "ruleLink": "tag.a@href\n@js:\nresult?result:'https://m.tuiimg.com/meinv/{{$.id}}/'",
    "ruleNextPage": "page",
    "rulePubDate": "{{$.time}}{{@@tag.span.0@text## 发布}} 发布　　喜欢({{$.love}}{{@@tag.span.1@text##(\\d+)##$1###}})",
    "ruleTitle": "tag.h2@text||$.title",
    "singleUrl": false,
    "sortUrl": "首页最新::https://m.tuiimg.com/data.php?page={{page}}\n变量搜索::https://m.tuiimg.com/search/list_{{page}}.html,{'method':'POST','body': 'skey={{v=source.getVariable();(v!='',v!=null)?v:(source.setVariable('三度'),source.getVariable())}}'}\n综合全部::https://m.tuiimg.com/meinv/list_{{page}}.html\n性感美女::https://m.tuiimg.com/xingganmeinv/list_{{page}}.html\n清纯美女::https://m.tuiimg.com/qingchunmeinv/list_{{page}}.html\n妹子图集::https://m.tuiimg.com/meizitu/list_{{page}}.html\n美女写真::https://m.tuiimg.com/meinvxiezhen/list_{{page}}.html\n\n\n//标签\n美胸::https://m.tuiimg.com/tag/meixiong/list_{{page}}.html\n美臀::https://m.tuiimg.com/tag/meitun/list_{{page}}.html\n美腿::https://m.tuiimg.com/tag/meitui/list_{{page}}.html\n妩媚::https://m.tuiimg.com/tag/wumei/list_{{page}}.html\n爆乳::https://m.tuiimg.com/tag/baoru/list_{{page}}.html\n诱惑::https://m.tuiimg.com/tag/youhuo/list_{{page}}.html\n丰满::https://m.tuiimg.com/tag/fengman/list_{{page}}.html\n可爱::https://m.tuiimg.com/tag/keai/list_{{page}}.html\n嫩模::https://m.tuiimg.com/tag/nenmo/list_{{page}}.html\n甜美::https://m.tuiimg.com/tag/tianmei/list_{{page}}.html\n萌妹::https://m.tuiimg.com/tag/mengmei/list_{{page}}.html\n\n\n//平台\nROSI::https://m.tuiimg.com/rosi/list_{{page}}.html\n秀人网::https://m.tuiimg.com/xiuren/list_{{page}}.html\n尤蜜荟::https://m.tuiimg.com/tag/youmihui/list_{{page}}.html\n尤果网::https://m.tuiimg.com/tag/ugirls/list_{{page}}.html\n美媛馆::https://m.tuiimg.com/tag/myg/list_{{page}}.html\n魅妍社::https://m.tuiimg.com/tag/mistar/list_{{page}}.html\n爱蜜社::https://m.tuiimg.com/tag/imiss/list_{{page}}.html\n蜜桃社::https://m.tuiimg.com/tag/miitao/list_{{page}}.html\n模范学院::https://m.tuiimg.com/tag/mfstar/list_{{page}}.html\n尤物馆::https://m.tuiimg.com/tag/youwu/list_{{page}}.html\n星颜社::https://m.tuiimg.com/tag/xingyan/list_{{page}}.html\n嗲囡囡::https://m.tuiimg.com/tag/feilin/list_{{page}}.html\n花の颜::https://m.tuiimg.com/tag/huayan/list_{{page}}.html\n御女郎::https://m.tuiimg.com/tag/dkgirl/list_{{page}}.html\n花漾::https://m.tuiimg.com/tag/huayang/list_{{page}}.html\n网红馆::https://m.tuiimg.com/tag/candy/list_{{page}}.html\n第四印象::https://m.tuiimg.com/tag/disi/list_{{page}}.html\n头条女神::https://m.tuiimg.com/tag/toutiaogirls/list_{{page}}.html\n\n\n//更多分类请自己添加\n//https://m.tuiimg.com/tag/",
    "sourceComment": "v0.2\n更改正文模板\n优化key的获取",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "推图网",
    "sourceUrl": "@js:\npage=org.jsoup.Jsoup.parse(\n\tjava.ajax('https://m.tuiimg.com/meinv')\n).select('.end').attr('href').match(/\\d+/)[0]\n'https://m.tuiimg.com/meinv/list_' + Math.ceil(Math.random()*page) + '.html'",
    "style": "* {\n\tmargin: 0;\n\tpadding: 0\n}\nul {\n\tfont-size: 0;\n\theight: 100%;\n\toverflow-y: scroll\n}\nli {\n\tlist-style: none;\n\ttext-align: center\n}\nimg {\n\twidth: 100%;\n\theight: auto\n}"
  },
  {
    "articleStyle": 0,
    "customOrder": 4761,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "injectJs": "//选择需要删除的标签，以,分隔\nitems = document.querySelectorAll(`\n\t.notice-top,\n\t.navbar-nav>li:nth-child(n+3),\n\t.navbar-right,\n\t.anti-select,\n\t#show-qrcode,\n\t#ex-comment,\n\t.hidden-more\n`)\n\n//把选择的html值改成空\nArray.from(items,(item)=>{\n\titem.innerHTML = ``\n\titem.style.display = `none`\n})\n\n\n\n//上面是通用js，下面的不是\n//删除网站的随机广告\nitems = document.querySelectorAll('.item')\nif(items){\nArray.from(items,(item)=>{\nif(item.querySelector('.item-num').innerText == 'AD'){\n\t\titem.innerHTML = ``\n\t\titem.style.display = `none`\n\t}\n})\n}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "",
    "ruleContent": "",
    "ruleDescription": "",
    "ruleLink": "",
    "ruleTitle": "",
    "singleUrl": true,
    "sourceComment": "广告屏蔽测试，阅读版本需要22.11.08以上",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "福利兔",
    "sourceUrl": "https://www.fulitu.cc"
  },
  {
    "articleStyle": 0,
    "customOrder": 4762,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "class.pb@tag.div",
    "ruleDescription": "",
    "ruleImage": "class.focus@tag.span@tag.img@src",
    "ruleNextPage": "class.pagination pagination-multi@class.next-page@tag.a@href",
    "rulePubDate": "class.text-muted time.0@text##发布于:",
    "ruleTitle": "class.excerpt excerpt-one.0@tag.header@tag.a@text",
    "singleUrl": true,
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "美女写真",
    "sourceUrl": "https://www.san449.com/meinv"
  },
  {
    "articleStyle": 2,
    "customOrder": 4763,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n  \"User-Agent\": \"Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36\",\n  \"Referer\": \"https://qikzj.com/\"\n}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": ".bricks-layout-item.repeater-item",
    "ruleContent": "@js:\nvar doc = org.jsoup.Jsoup.parse(result);\nvar myImgs = [];\n\n// 1. 严格锁定正文 ID，彻底避开 Related Posts 等外部组件\nvar contentHtml = \"\";\nvar mainBox = doc.getElementById(\"brxe-qoenez\");\nif (mainBox) {\n    contentHtml = mainBox.html();\n} else {\n    contentHtml = doc.select(\".brxe-post-content\").html();\n}\n\nif (contentHtml) {\n    // 2. 在限定范围内扫描高清图片链接\n    var regex = /https?:\\/\\/qikzj\\.com\\/wp-content\\/uploads\\/[^\"'\\s<>]*?\\.(?:jpg|jpeg|png|webp|gif)/gi;\n    var matches;\n    while ((matches = regex.exec(contentHtml)) !== null) {\n        var s = matches[0];\n        // 过滤 Logo 和头像\n        if (s.indexOf(\"logo\") === -1 && s.indexOf(\"avatar\") === -1) {\n            // 还原高清原图路径，去掉尺寸和缩放后缀\n            var cleanUrl = s.replace(/-\\d+x\\d+\\./i, \".\").replace(/-scaled\\./i, \".\");\n            if (myImgs.indexOf(cleanUrl) === -1) {\n                myImgs.push(cleanUrl);\n            }\n        }\n    }\n}\n\nvar displayTitle = (typeof title !== 'undefined' && title) ? title : \"QikZ Visuals\";\n\nvar h = \"<!DOCTYPE html><html><head><style>body{margin:0;background:#050505;color:#eee;font-family:sans-serif;padding-bottom:100px} .top{background:#111;color:#888;text-align:center;padding:15px;font-size:10px;text-transform:uppercase;letter-spacing:3px;border-bottom:1px solid #222} .header{padding:40px 25px;text-align:center} .img-list{padding:0 10px} .img-box{position:relative;margin-bottom:18px;background:#000;border-radius:2px;overflow:hidden;box-shadow:0 10px 30px rgba(0,0,0,0.5)} .img-box img{width:100%;display:block;height:auto} .img-num{position:absolute;bottom:10px;right:15px;background:rgba(0,0,0,0.6);color:#fff;padding:2px 8px;border-radius:2px;font-size:10px;font-family:monospace;font-weight:bold}</style></head><body>\";\nh += \"<div class='top'>HD VISUAL SHOWCASE</div>\";\nh += \"<div class='header'><h1 style='font-size:20px;margin:0;font-weight:300;color:#fff;line-height:1.4'>\" + displayTitle + \"</h1></div>\";\nh += \"<div class='img-list'>\";\nfor(var k=0; k<myImgs.length; k++){\n    h += \"<div class='img-box'><img src='\" + myImgs[k] + \"'><span class='img-num'>\" + (k+1) + \" / \" + myImgs.length + \"</span></div>\";\n}\nh += \"</div><p style='text-align:center;color:#333;font-size:10px;margin-top:60px;letter-spacing:2px'>QIKZ PHOTOGRAPHY GALLERY</p></body></html>\";\nresult = h;",
    "ruleImage": "@js:\nvar img = result.select(\"img\").first();\nif (img) {\n    var s = img.attr(\"data-src\") || img.attr(\"data-srcset\") || img.attr(\"src\");\n    if (s && s.indexOf(\" \") > 0) s = s.split(\" \")[0];\n    result = s;\n} else {\n    result = \"https://qikzj.com/favicon.ico\";\n}\nresult;",
    "ruleLink": "h3.dynamic a@href",
    "ruleNextPage": ".page-numbers.next@href",
    "ruleTitle": "h3.dynamic a@text",
    "singleUrl": false,
    "sortUrl": "",
    "sourceGroup": "图",
    "sourceIcon": "http://www.sytuk.com/favicon.ico",
    "sourceName": "美图",
    "sourceUrl": "https://qikzj.com"
  },
  {
    "articleStyle": 0,
    "customOrder": 4764,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页1",
    "sourceUrl": "https://www.33ccpp.com/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4765,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceComment": "",
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页2",
    "sourceUrl": "https://xrhf.taimei-t140.vip/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4766,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页3",
    "sourceUrl": "https://www.xn--vctr31ecwaz4k.com/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4767,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceComment": "视频",
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页4",
    "sourceUrl": "https://www.xhsiy38.cc:2024/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4768,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceComment": "视频",
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页5",
    "sourceUrl": "https://2.hlg6440d.cc/"
  },
  {
    "articleStyle": 1,
    "customOrder": 4769,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\"User-Agent\":\"Mozilla/5.0 (Linux; Android 11; PCAM10 Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4103.106 Mobile Safari/537.36\"} ",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "",
    "ruleContent": "",
    "ruleImage": "",
    "ruleLink": "",
    "ruleNextPage": "",
    "rulePubDate": "",
    "ruleTitle": "",
    "singleUrl": true,
    "sortUrl": "",
    "sourceComment": "",
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页6",
    "sourceUrl": "https://bqm.avds8.com/g/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4770,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页7",
    "sourceUrl": "https://www.q6md.com/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4771,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页8",
    "sourceUrl": "https://baf7baf7.shewo11.cc"
  },
  {
    "articleStyle": 0,
    "customOrder": 4772,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 1775405861793,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/087.webp",
    "sourceName": "网页9",
    "sourceUrl": "https://nsvod.me"
  },
  {
    "articleStyle": 0,
    "customOrder": 4773,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceComment": "",
    "sourceGroup": "网页",
    "sourceIcon": "https://m.acgnfl.com/24/07/content_33/525867/073.webp",
    "sourceName": "网页10",
    "sourceUrl": "https://www.mt314iu.vip:9527/"
  },
  {
    "articleStyle": 0,
    "customOrder": 4774,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "",
    "ruleContent": "",
    "ruleImage": "",
    "ruleLink": "",
    "ruleNextPage": "",
    "ruleTitle": "",
    "singleUrl": true,
    "sourceGroup": "直播",
    "sourceIcon": "https://img2.baidu.com/it/u=3810767422,2486090729&fm=253&fmt=auto&app=138&f=PNG?w=192&h=192",
    "sourceName": "直播1",
    "sourceUrl": "https://zh.virtualtaboo.live/",
    "style": "video{\nwidth:100%;\nheight:auto;}"
  },
  {
    "articleStyle": 0,
    "concurrentRate": "",
    "customOrder": 4775,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.zhubo",
    "ruleContent": "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n<script src=\"http://bilibili.github.io/flv.js/dist/flv.js\"></script>\n</head>\n<body>\n\t\t\t<video id=\"player1\"  autoplay=\"autoplay\" preload=\"auto\" muted controls=\"controls\">\n\t\t</video>\n\t\t<p>\n    <button onclick=\"enableMute()\" type=\"button\">关闭声音</button>\n\n    <button onclick=\"disableMute()\" type=\"button\">打开声音</button>\n\n</p> \n<div>\n直播链接:{{baseUrl.replace(/zhibo/,\"flv\").replace(/http:\\/\\/api.hclyz.com:81/,\"不可播放rtmp:/\")}}\n</div>\n</body>\n</html>\n<script>\n    if (flvjs.isSupported()) {\n        var videoElement = document.getElementById('player1');\n\t\tvar flvPlayer = flvjs.createPlayer({\n            type: 'flv', \n            url: '{{baseUrl.replace(/zhibo/,\"flv\").replace(/http:\\/\\/api.hclyz.com:81/,\"rtmp://\")}}',\n     });\n\t\tflvPlayer.attachMediaElement(videoElement);\n\t\tflvPlayer.load();\n\t\t//flvPlayer.play();\n    }\n</script>\n <script>\n\nvar myVid = document.getElementById(\"player1\");\n\nfunction enableMute() { \n\n    myVid.muted = true;\n\n} \n\nfunction disableMute() { \n\n    myVid.muted = false;\n\n} \n</script> ",
    "ruleDescription": "",
    "ruleImage": "$.img",
    "ruleLink": "$.address@js:result\n.replace(/\\.flv/,\".zhibo\")\n.replace(/rtmp:\\//,\"\")",
    "rulePubDate": "",
    "ruleTitle": "$.title",
    "singleUrl": false,
    "sortUrl": "偶遇::http://api.hclyz.com:81/mf/jsonouyu.txt\n依依::http://api.hclyz.com:81/mf/jsonyiyi.txt\n夜色::http://api.hclyz.com:81/mf/jsonyese.txt\n亚米::http://api.hclyz.com:81/mf/jsonyami.txt\n色趣::http://api.hclyz.com:81/mf/jsonsequ.txt\n咪狐::http://api.hclyz.com:81/mf/jsonmihu.txt\n夜律::http://api.hclyz.com:81/mf/jsonyelu.txt\n暗语::http://api.hclyz.com:81/mf/jsonanyu.txt\n咪咪::http://api.hclyz.com:81/mf/jsonmimi.txt\n糯米::http://api.hclyz.com:81/mf/jsonnuomi.txt\n苦瓜::http://api.hclyz.com:81/mf/jsonkugua.txt\n蝴蝶::http://api.hclyz.com:81/mf/jsonhudie.txt\n云鹿::http://api.hclyz.com:81/mf/jsonyunlu.txt\n付宝::http://api.hclyz.com:81/mf/jsonfubao.txt\n菠萝::http://api.hclyz.com:81/mf/jsonboluo.txt\n夜艳::http://api.hclyz.com:81/mf/jsonyeyan.txt\n二嫂::http://api.hclyz.com:81/mf/jsonersao.txt\n土豪::http://api.hclyz.com:81/mf/jsontuhao.txt\n盘他::http://api.hclyz.com:81/mf/jsonpanta.txt\n美夕::http://api.hclyz.com:81/mf/jsonmeixi.txt\n坦克::http://api.hclyz.com:81/mf/jsontanke.txt\n蜜桃::http://api.hclyz.com:81/mf/jsonmitao.txt\n她秀::http://api.hclyz.com:81/mf/jsontaxiu.txt\n金鱼::http://api.hclyz.com:81/mf/jsonjinyu.txt\n浴火::http://api.hclyz.com:81/mf/jsonyuhuo.txt\n套路::http://api.hclyz.com:81/mf/jsontaolu.txt\n日出::http://api.hclyz.com:81/mf/jsonrichu.txt\n桃花::http://api.hclyz.com:81/mf/jsontaohua.txt\nLOVE::http://api.hclyz.com:81/mf/jsonLOVE.txt\n久久::http://api.hclyz.com:81/mf/jsonjiujiu.txt\n杏趣::http://api.hclyz.com:81/mf/jsonxingqu.txt\n媚颜::http://api.hclyz.com:81/mf/jsonmeiyan.txt\n灰灰::http://api.hclyz.com:81/mf/jsonhuihui.txt\n爱零::http://api.hclyz.com:81/mf/jsonailing.txt\n爱恋::http://api.hclyz.com:81/mf/jsonailian.txt\n杏播::http://api.hclyz.com:81/mf/jsonxingbo.txt\n金呗::http://api.hclyz.com:81/mf/jsonjinbei.txt\nmoon::http://api.hclyz.com:81/mf/jsonmoon.txt\n夜纯::http://api.hclyz.com:81/mf/jsonyechun.txt\n彩云::http://api.hclyz.com:81/mf/jsoncaiyun.txt\n妞妞::http://api.hclyz.com:81/mf/jsonniuniu.txt\n艳后::http://api.hclyz.com:81/mf/jsonyanhou.txt\n蓝猫::http://api.hclyz.com:81/mf/jsonlanmao.txt\n情趣::http://api.hclyz.com:81/mf/jsonqingqu.txt\n翠鸟::http://api.hclyz.com:81/mf/jsoncuiniao.txt\n糖果::http://api.hclyz.com:81/mf/jsontangguo.txt\n么么哒::http://api.hclyz.com:81/mf/jsonmemeda.txt\n豹娱l::http://api.hclyz.com:81/mf/jsonbaoyul.txt\n卡哇伊::http://api.hclyz.com:81/mf/jsonkawayi.txt\n小妖::http://api.hclyz.com:81/mf/jsonxiaoyao.txt\n幽梦::http://api.hclyz.com:81/mf/jsonyoumeng.txt\n风流::http://api.hclyz.com:81/mf/jsonfengliu.txt\n樱桃::http://api.hclyz.com:81/mf/jsonyingtao.txt\n享色::http://api.hclyz.com:81/mf/jsonxiangse.txt\n娇媚::http://api.hclyz.com:81/mf/jsonjiaomei.txt\n爱爱你::http://api.hclyz.com:81/mf/jsonaiaini.txt\n花房::http://api.hclyz.com:81/mf/jsonhuafang.txt\n卡路里::http://api.hclyz.com:81/mf/jsonkaluli.txt\n名流::http://api.hclyz.com:81/mf/jsonmingliu.txt\n倾心::http://api.hclyz.com:81/mf/jsonqingxin.txt\n樱花::http://api.hclyz.com:81/mf/jsonyinghua.txt\n飘雪::http://api.hclyz.com:81/mf/jsonpiaoxue.txt\n入巷::http://api.hclyz.com:81/mf/jsonruxiang.txt\n蝶恋::http://api.hclyz.com:81/mf/jsondielian.txt\n彩虹::http://api.hclyz.com:81/mf/jsoncaihong.txt\n奥斯卡::http://api.hclyz.com:81/mf/jsonaosika.txt\n皇后::http://api.hclyz.com:81/mf/jsonhuanghou.txt\n牵手::http://api.hclyz.com:81/mf/jsonqianshou.txt\n台妹l::http://api.hclyz.com:81/mf/jsontaimeil.txt\n夜妖姬::http://api.hclyz.com:81/mf/jsonyeyaoji.txt\n一直播::http://api.hclyz.com:81/mf/jsonyizhibo.txt\n玲珑::http://api.hclyz.com:81/mf/jsonlinglong.txt\n橙秀::http://api.hclyz.com:81/mf/jsonchengxiu.txt\n黄瓜::http://api.hclyz.com:81/mf/jsonhuanggua.txt\n颜如玉::http://api.hclyz.com:81/mf/jsonyanruyu.txt\n蛟龙::http://api.hclyz.com:81/mf/jsonjiaolong.txt\n好基友::http://api.hclyz.com:81/mf/jsonhaojiyou.txt\n夜女郎::http://api.hclyz.com:81/mf/jsonyenulang.txt\n娇喘::http://api.hclyz.com:81/mf/jsonjiaochuan.txt\n小妲己::http://api.hclyz.com:81/mf/jsonxiaodaji.txt\n花蝴蝶::http://api.hclyz.com:81/mf/jsonhuahudie.txt\n尤物岛::http://api.hclyz.com:81/mf/jsonyouwudao.txt\n77直播::http://api.hclyz.com:81/mf/json77zhibo.txt\n十八禁::http://api.hclyz.com:81/mf/jsonshibajin.txt\n蝴蝶飞::http://api.hclyz.com:81/mf/jsonhudiefei.txt\n喜欢你::http://api.hclyz.com:81/mf/jsonxihuanni.txt\n兔女郎::http://api.hclyz.com:81/mf/jsontunulang.txt\n双碟::http://api.hclyz.com:81/mf/jsonshuangdie.txt\n约直播::http://api.hclyz.com:81/mf/jsonyuezhibo.txt\n九尾狐::http://api.hclyz.com:81/mf/jsonjiuweihu.txt\n红妆::http://api.hclyz.com:81/mf/jsonhongzhuang.txt\n花仙子::http://api.hclyz.com:81/mf/jsonhuaxianzi.txt\n持久男::http://api.hclyz.com:81/mf/jsonchijiunan.txt\n丽柜厅::http://api.hclyz.com:81/mf/jsonliguiting.txt\n桃花运::http://api.hclyz.com:81/mf/jsontaohuayun.txt\n903娱乐::http://api.hclyz.com:81/mf/json903yule.txt\n视觉秀::http://api.hclyz.com:81/mf/jsonshijuexiu.txt\n芒果派::http://api.hclyz.com:81/mf/jsonmangguopai.txt\n七仙女s::http://api.hclyz.com:81/mf/jsonqixiannus.txt\n夜来香::http://api.hclyz.com:81/mf/jsonyelaixiang.txt\n星宝贝::http://api.hclyz.com:81/mf/jsonxingbaobei.txt\n小蜜蜂::http://api.hclyz.com:81/mf/jsonxiaomifeng.txt\n小棉袄::http://api.hclyz.com:81/mf/jsonxiaomianao.txt\n小辣椒::http://api.hclyz.com:81/mf/jsonxiaolajiao.txt\n小仙女::http://api.hclyz.com:81/mf/jsonxiaoxiannu.txt\n兰桂坊::http://api.hclyz.com:81/mf/jsonlanguifang.txt\n花果山::http://api.hclyz.com:81/mf/jsonhuaguoshan.txt\n招财猫::http://api.hclyz.com:81/mf/jsonzhaocaimao.txt\n心之恋::http://api.hclyz.com:81/mf/jsonxinzhilian.txt\n睡美人::http://api.hclyz.com:81/mf/jsonshuimeiren.txt\n小花螺::http://api.hclyz.com:81/mf/jsonxiaohualuo.txt\n小天使::http://api.hclyz.com:81/mf/jsonxiaotianshi.txt\n小红帽::http://api.hclyz.com:81/mf/jsonxiaohongmao.txt\n樱花雨i::http://api.hclyz.com:81/mf/jsonyinghuayui.txt\n小萌猪::http://api.hclyz.com:81/mf/jsonxiaomengzhu.txt\n小坏蛋::http://api.hclyz.com:81/mf/jsonxiaohuaidan.txt\n小性感::http://api.hclyz.com:81/mf/jsonxiaoxinggan.txt\n红浪漫::http://api.hclyz.com:81/mf/jsonhonglangman.txt\n蚊香社::http://api.hclyz.com:81/mf/jsonwenxiangshe.txt\n蓝月亮::http://api.hclyz.com:81/mf/jsonlanyueliang.txt\n小精灵::http://api.hclyz.com:81/mf/jsonxiaojingling.txt\n红高粱::http://api.hclyz.com:81/mf/jsonhonggaoliang.txt\n小天仙::http://api.hclyz.com:81/mf/jsonxiaotianxian.txt",
    "sourceComment": "某个软件的聚合直播\nrtmp的手机网页应该是无法播放\nmp4的都是广告没管",
    "sourceGroup": "直播",
    "sourceIcon": "https://img2.baidu.com/it/u=3810767422,2486090729&fm=253&fmt=auto&app=138&f=PNG?w=192&h=192",
    "sourceName": "直播2",
    "sourceUrl": "http://api.hclyz.com:81",
    "style": "video{\nwidth:100%;\nheight:auto;}"
  },
  {
    "articleStyle": 3,
    "customOrder": 4776,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "header": "{\n\"User-Agent\": \"Mozilla/5.0 (Android)\"\n}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": "$.blocks..models[*]&&$.models[*]",
    "ruleContent": "<js>\nconst parts = baseUrl.split(',').map(function(item) { return item.trim(); });\nconst domain = parts[0].split('/').slice(0, 3).join('/');\nconst username = parts[0].split('/').pop() || parts[0];\n\nconst camAjax = java.ajax(domain + '/api/front/v2/models/username/' + username + '/cam?uniq=0');\nconst configAjax = java.ajax(domain + '/api/front/v3/config/initial');\nconst membersAjax = java.ajax(domain + '/api/front/v2/models/username/' + username + '/members?uniq=0');\n\nlet responseData = { status: \"offline\", avatarUrl: \"\", startTime: \"\", coverImg: \"\", userDescription: \"\", goalDescription: \"\", fanClubDescription: \"\", topic: \"\", username: username, stream: \"\", topBestPlace: \"\", hlsLines: [], cdn: \"\", pixelatedResolutions: [], membersCount: 0, tipMenuPriceList: [], isLive: false, tipMenuCreatedAt: \"\", websocketUrl: \"\", websocketToken: \"\", modelId: \"\" };\n\nif (camAjax) {\n    const camData = JSON.parse(camAjax);\n    const user = camData.user && camData.user.user ? camData.user.user : {};\n    const cam = camData.cam ? camData.cam : {};\n    \n    responseData.status = user.status || \"offline\";\n    responseData.avatarUrl = user.avatarUrl || \"\";\n    responseData.startTime = user.statusChangedAt || \"\";\n    responseData.userDescription = user.description || \"\";\n    responseData.goalDescription = cam.goal && cam.goal.description ? cam.goal.description : \"\";\n    responseData.fanClubDescription = cam.userFanClub && cam.userFanClub.description ? cam.userFanClub.description : \"\";\n    responseData.topic = cam.topic || \"\";\n    responseData.stream = cam.streamName || \"\";\n    responseData.topBestPlace = user.topBestPlace || \"\";\n    responseData.modelId = user.id || \"\";\n    \n    if (user.snapshotTimestamp && responseData.modelId) {\n        responseData.coverImg = \"https://img.doppiocdn.live/thumbs/\" + user.snapshotTimestamp + \"/\" + responseData.modelId;\n    }\n    \n    if (cam.broadcastSettings && cam.broadcastSettings.presets) {\n        const presets = cam.broadcastSettings.presets;\n        var allResolutions = [];\n        \n        if (presets.default && presets.default.constructor === Array) {\n            allResolutions = allResolutions.concat(presets.default);\n        }\n        \n        if (presets.pixelated && presets.pixelated.constructor === Array) {\n            allResolutions = allResolutions.concat(presets.pixelated);\n        }\n        \n        if (presets.testing && presets.testing.constructor === Array) {\n            allResolutions = allResolutions.concat(presets.testing);\n        }\n        \n        if (presets.h265 && presets.h265.constructor === Array) {\n            allResolutions = allResolutions.concat(presets.h265);\n        }\n        \n        if (presets.vr && presets.vr.constructor === Array) {\n            allResolutions = allResolutions.concat(presets.vr);\n        }\n        \n        var uniqueResolutions = [];\n        for (var i = 0; i < allResolutions.length; i++) {\n            if (uniqueResolutions.indexOf(allResolutions[i]) === -1) {\n                uniqueResolutions.push(allResolutions[i]);\n            }\n        }\n        \n        uniqueResolutions.sort(function(a, b) {\n            var numA = parseInt(a);\n            var numB = parseInt(b);\n            if (isNaN(numA)) numA = 0;\n            if (isNaN(numB)) numB = 0;\n            if (a === \"auto\") return 1;\n            if (b === \"auto\") return -1;\n            if (a === \"160p_blurred\") return 1;\n            if (b === \"160p_blurred\") return -1;\n            return numB - numA;\n        });\n        \n        responseData.pixelatedResolutions = uniqueResolutions;\n    }\n    \n    responseData.isLive = user.isOnline === true;\n    responseData.tipMenuCreatedAt = cam.tipMenu && cam.tipMenu.createdAt ? cam.tipMenu.createdAt : \"\";\n    \n    if (cam.tipMenu && cam.tipMenu.settings) {\n        responseData.tipMenuPriceList = cam.tipMenu.settings.map(function(item) {\n            return {\n                activity: item.activity || \"\",\n                price: item.price || 0\n            };\n        });\n    }\n}\n\nif (configAjax) {\n    const configData = JSON.parse(configAjax);\n    const hosts = configData.initial && configData.initial.common && configData.initial.common.hlsStreamHosts ? configData.initial.common.hlsStreamHosts : {};\n    var hlsLines = [];\n    if (hosts.A) hlsLines.push(hosts.A);\n    if (hosts.B) hlsLines.push(hosts.B);\n    if (hosts.C) hlsLines.push(hosts.C);\n    if (hosts.D) hlsLines.push(hosts.D);\n    if (hosts.E) hlsLines.push(hosts.E);\n    if (hosts.F) hlsLines.push(hosts.F);\n    responseData.hlsLines = hlsLines;\n    responseData.cdn = responseData.hlsLines[0] || \"\";\n    \n    const client = configData.initial && configData.initial.client ? configData.initial.client : {};\n    responseData.websocketUrl = client.websocket && client.websocket.url ? client.websocket.url : \"\";\n    responseData.websocketToken = client.websocket && client.websocket.token ? client.websocket.token : \"\";\n}\n\nif (membersAjax) {\n    try {\n        const membersData = JSON.parse(membersAjax);\n        responseData.membersCount = \n            (membersData && membersData.guests ? membersData.guests : 0) + \n            (membersData && membersData.spies ? membersData.spies : 0) + \n            (membersData && membersData.invisibles ? membersData.invisibles : 0) + \n            (membersData && membersData.greens ? membersData.greens : 0) + \n            (membersData && membersData.golds ? membersData.golds : 0) + \n            (membersData && membersData.regulars ? membersData.regulars : 0);\n    } catch (error) {\n        responseData.membersCount = 0;\n    }\n}\n\nJSON.stringify(responseData);\n</js>\n<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title></title>\n</head>\n    <style>\n        * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Microsoft Yahei', sans-serif; }\n        body { color: #333; padding: 0.1rem; min-height: 100vh; background: #f5f5f5; }\n        .app-container { display: grid; grid-template-columns: 1fr; gap: 1rem; max-width: 1200px; margin: 0 auto; }\n        .live-section { border-radius: 12px; overflow: hidden; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); border: 1px solid #eaeaea; background: #fff; }\n        .topic-section { padding: 14px 20px; border-bottom: 1px solid #eaeaea; background: #fff; display: none; }\n        .topic-label { font-size: 12px; color: #666; margin-bottom: 6px; display: flex; align-items: center; gap: 8px; font-weight: 500; }\n        .topic-content { font-size: 15px; color: #333; font-weight: 500; line-height: 1.4; }\n        .chat-section { border-radius: 12px; padding: 1rem; display: flex; flex-direction: column; height: 500px; border: 1px solid #eaeaea; background: #fff; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); }\n        .chat-messages { flex: 1; overflow-y: auto; padding-right: 0.5rem; width: 100%; }\n        .chat-messages::-webkit-scrollbar { width: 6px; }\n        .chat-messages::-webkit-scrollbar-track { background: #f0f0f0; border-radius: 3px; }\n        .chat-messages::-webkit-scrollbar-thumb { background: #c0c0c0; border-radius: 3px; }\n        .message-wrapper { display: block; margin-bottom: 0.3rem; width: 100%; }\n        .message-item { padding: 0.3rem 0.6rem; border-radius: 16px; font-size: 0.85rem; line-height: 1.3; border: 1px solid rgba(224, 224, 224, 0.6); display: block; background: #f8f8f8; color: #333; width: 100%; word-break: break-word; box-sizing: border-box; }\n        .lovense-item { border-color: #e0e0e0; background: #f8f8f8; }\n        .tip-item { border-color: #e0e0e0; background: #f8f8f8; }\n        .system-message { border-color: #e0e0e0; color: #666; font-size: 0.85rem; margin: 0 auto 0.3rem auto; background: #f8f8f8; }\n        .user-name { font-weight: 600; color: #222; margin-left: 0.4rem; }\n        .level-tag { font-size: 0.75rem; color: #666; background: #f0f0f0; padding: 0.1rem 0.4rem; border-radius: 8px; }\n        .tip-amount { color: #e74c3c; font-weight: 600; }\n        .live-header { padding: 16px 20px; border-bottom: 1px solid #eaeaea; display: flex; align-items: center; gap: 15px; background: #fff; }\n        .avatar-container { width: 56px; height: 56px; flex-shrink: 0; }\n        .avatar { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; border: 3px solid #007aff; }\n        .host-info { flex: 1; min-width: 0; }\n        .host-info h2 { font-size: 18px; margin-bottom: 6px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #333; }\n        .status-container { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }\n        .live-badge { display: inline-flex; align-items: center; background: #ff3b30; color: white; padding: 4px 10px; border-radius: 4px; font-size: 12px; font-weight: 600; letter-spacing: 0.3px; }\n        .live-badge::before { content: ''; display: inline-block; width: 6px; height: 6px; background-color: white; border-radius: 50%; margin-right: 6px; animation: blink 1.5s infinite; }\n        @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }\n        .viewer-count { font-size: 13px; color: #666; display: flex; align-items: center; gap: 5px; }\n        .player-container { position: relative; background: #000000; overflow: hidden; }\n        .player-container:fullscreen { display: flex; align-items: center; justify-content: center; }\n        .player-container:-webkit-full-screen { display: flex; align-items: center; justify-content: center; }\n        #dplayer { width: 100% !important; height: 100% !important; display: flex; align-items: center; }\n        #dplayer video { object-fit: contain !important; }\n        .dplayer-controller { display: none !important; }\n        .dplayer-notice { display: none !important; }\n        .custom-controls { position: absolute; bottom: 0; left: 0; right: 0; padding: 12px 15px 6px; display: flex; align-items: center; justify-content: space-between; opacity: 0; transition: opacity 0.2s; z-index: 1000; pointer-events: none; }\n        .player-container.controls-visible .custom-controls { opacity: 1; pointer-events: auto; }\n        .player-container.controls-hidden .custom-controls { opacity: 0; pointer-events: none; }\n        .left-controls, .right-controls { display: flex; align-items: center; gap: 8px; pointer-events: auto; }\n        .rotate-btn { background: rgba(255, 255, 255, 0.15); border: 1px solid rgba(255, 255, 255, 0.25); color: rgba(255, 255, 255, 0.9); padding: 6px 10px; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500; white-space: nowrap; display: flex; align-items: center; justify-content: center; transition: all 0.15s; min-width: 52px; pointer-events: auto; }\n        .rotate-btn:hover { background: rgba(255, 255, 255, 0.25); color: white; }\n        .control-btn { background: rgba(255, 255, 255, 0.15); border: 1px solid rgba(255, 255, 255, 0.25); color: #ffffff; width: 36px; height: 36px; border-radius: 6px; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 16px; transition: all 0.15s; pointer-events: auto; }\n        .control-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n        .selector-btn { background: rgba(255, 255, 255, 0.15); border: 1px solid rgba(255, 255, 255, 0.25); color: #ffffff; padding: 6px 10px; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500; white-space: nowrap; display: flex; align-items: center; gap: 5px; transition: all 0.15s; min-width: 65px; justify-content: center; pointer-events: auto; }\n        .selector-menu { position: absolute; bottom: 42px; background: #ffffff; border-radius: 8px; min-width: 90px; display: none; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16); border: 1px solid #d1d1d6; overflow: hidden; z-index: 1001; pointer-events: auto; }\n        .menu-item { padding: 8px 12px; color: #333; cursor: pointer; font-size: 13px; transition: all 0.15s; border-bottom: 1px solid #eaeaea; display: flex; align-items: center; justify-content: space-between; pointer-events: auto; }\n        .menu-item:last-child { border-bottom: none; }\n        .menu-item:hover:not(:disabled) { background: #007aff; color: white; }\n        .menu-item.active { background: rgba(10, 132, 255, 0.1); color: #007aff; }\n        .menu-item.active:after { content: \"✓\"; font-size: 12px; color: #007aff; }\n        .loading-indicator { position: absolute; top: 15px; left: 15px; background: rgba(0, 0, 0, 0.8); color: white; padding: 6px 12px; border-radius: 4px; font-size: 12px; z-index: 1002; display: none; border: 1px solid rgba(255, 255, 255, 0.1); }\n        .floating-button { position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; border-radius: 50%; background: #007aff; color: white; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 122, 255, 0.3); z-index: 10000; border: none; font-size: 24px; }\n        .floating-panel { position: fixed; bottom: 90px; right: 20px; width: 400px; background: #ffffff; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); padding: 20px; z-index: 9999; border: 1px solid #eaeaea; display: none; max-height: 80vh; overflow-y: auto; }\n        .floating-panel::-webkit-scrollbar { width: 6px; }\n        .floating-panel::-webkit-scrollbar-track { background: #f0f0f0; border-radius: 3px; }\n        .floating-panel::-webkit-scrollbar-thumb { background: #c0c0c0; border-radius: 3px; }\n        .floating-panel-title { font-size: 18px; font-weight: 600; margin-bottom: 15px; color: #333; padding-bottom: 10px; border-bottom: 1px solid #eaeaea; }\n        .floating-info-section { margin-bottom: 20px; }\n        .floating-info-section-title { font-size: 15px; color: #007aff; margin-bottom: 12px; font-weight: 600; display: flex; align-items: center; gap: 8px; }\n        .floating-info-item { margin-bottom: 12px; display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #f5f5f5; }\n        .floating-info-item:last-child { border-bottom: none; margin-bottom: 0; }\n        .floating-info-label { font-size: 13px; color: #666; min-width: 120px; }\n        .floating-info-value { font-size: 14px; color: #333; font-weight: 500; text-align: right; flex: 1; }\n        .floating-content { background: #f8f9fa; border: 1px solid #eaeaea; border-radius: 8px; padding: 12px; font-size: 14px; color: #333; line-height: 1.5; margin-bottom: 15px; }\n        .floating-price-list { display: flex; flex-direction: column; gap: 8px; }\n        .floating-price-item { background: #ffffff; border: 1px solid #eaeaea; border-radius: 8px; padding: 10px 12px; display: flex; align-items: center; justify-content: space-between; transition: all 0.2s; }\n        .floating-price-item:hover { border-color: #007aff; }\n        .floating-price-activity { font-size: 14px; color: #333; flex: 1; }\n        .floating-price-value { font-size: 14px; color: #ff3b30; font-weight: 600; }\n        @media (max-width: 768px) {\n            .floating-panel { width: 350px; right: 10px; bottom: 80px; }\n            .floating-button { width: 50px; height: 50px; font-size: 20px; right: 15px; bottom: 15px; }\n            .live-header { padding: 14px 16px; }\n            .avatar-container { width: 48px; height: 48px; }\n            .host-info h2 { font-size: 16px; }\n        }\n        @media (max-width: 480px) {\n            .floating-panel { width: 300px; }\n            .chat-section { height: 400px; }\n            .app-container { padding: 0.5rem; gap: 1rem; }\n        }\n    </style>\n<body>\n    <div id=\"config\" style=\"display:none;\">\n        <div id=\"liveData\" style=\"display:none;\">{{result}}</div>\n    </div>\n    \n    <div class=\"app-container\">\n        <div class=\"live-section\">\n            <div class=\"topic-section\" id=\"topicContainer\">\n                <div class=\"topic-label\">\n                    <i class=\"fas fa-bullhorn\"></i> 直播标题\n                </div>\n                <div class=\"topic-content\" id=\"topic\"></div>\n            </div>\n            \n            <div class=\"live-header\">\n                <div class=\"avatar-container\">\n                    <img class=\"avatar\" id=\"avatarImg\" src=\"\" alt=\"\">\n                </div>\n                <div class=\"host-info\">\n                    <h2 id=\"hostName\">正在加载...</h2>\n                    <div class=\"status-container\">\n                        <span class=\"live-badge\">直播中</span>\n                        <div class=\"viewer-count\">\n                            <i class=\"fas fa-users\"></i>\n                            <span id=\"membersCount\">--</span> 人\n                        </div>\n                    </div>\n                </div>\n            </div>\n            \n            <div class=\"player-container\" id=\"playerContainer\">\n                <div id=\"dplayer\"></div>\n                <div class=\"loading-indicator\" id=\"loadingIndicator\">正在切换...</div>\n                <div class=\"custom-controls\">\n                    <div class=\"left-controls\">\n                        <button class=\"control-btn\" id=\"refreshBtn\" title=\"刷新播放\">\n                            <i class=\"fas fa-redo-alt\"></i>\n                        </button>\n                        <button class=\"control-btn\" id=\"volumeBtn\" title=\"静音/取消静音\">\n                            <i class=\"fas fa-volume-up\"></i>\n                        </button>\n                        <div class=\"rotate-btn\" id=\"rotateBtn\">竖屏</div>\n                    </div>\n                    <div class=\"right-controls\">\n                        <div class=\"line-selector\">\n                            <div class=\"selector-btn\" id=\"lineBtn\" title=\"选择线路\">线路1 <i class=\"fas fa-chevron-down\"></i></div>\n                            <div class=\"selector-menu\" id=\"lineMenu\"></div>\n                        </div>\n                        <div class=\"quality-selector\">\n                            <div class=\"selector-btn\" id=\"qualityBtn\" title=\"选择清晰度\">默认 <i class=\"fas fa-chevron-down\"></i></div>\n                            <div class=\"selector-menu\" id=\"qualityMenu\"></div>\n                        </div>\n                        <button class=\"control-btn\" id=\"fullscreenBtn\" title=\"全屏\">\n                            <i class=\"fas fa-expand\"></i>\n                        </button>\n                    </div>\n                </div>\n            </div>\n        </div>\n        \n        <div class=\"chat-section\">\n             <div class=\"chat-messages\" id=\"chatContainer\"></div>\n        </div>\n    </div>\n    \n    <button class=\"floating-button\" id=\"floatingBtn\">\n        <i class=\"fas fa-info\"></i>\n    </button>\n    \n    <div class=\"floating-panel\" id=\"floatingPanel\">\n        <div class=\"floating-panel-title\">直播信息</div>\n        \n        <div class=\"floating-info-section\">\n            <div class=\"floating-info-section-title\">\n                <i class=\"fas fa-user\"></i> 主播信息\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\">主播名称:</span>\n                <span class=\"floating-info-value\" id=\"floatingHostName\">--</span>\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\">历史最高排行:</span>\n                <span class=\"floating-info-value\" id=\"floatingTopBestPlace\">--</span>\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\">总人数:</span>\n                <span class=\"floating-info-value\" id=\"floatingMembersCount\">--</span>\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\">首次开播日期:</span>\n                <span class=\"floating-info-value\" id=\"floatingTipMenuCreatedAt\">--</span>\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\" id=\"floatingDurationLabel\">时长标签:</span>\n                <span class=\"floating-info-value\" id=\"floatingDuration\">--</span>\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\" id=\"floatingTimeLabel\">时间标签:</span>\n                <span class=\"floating-info-value\" id=\"floatingStatusTime\">--</span>\n            </div>\n        </div>\n        \n        <div class=\"floating-info-section\" id=\"floatingUserDescriptionSection\">\n            <div class=\"floating-info-section-title\">\n                <i class=\"fas fa-user-circle\"></i> 主播介绍\n            </div>\n            <div class=\"floating-content\" id=\"floatingUserDescription\"></div>\n        </div>\n        \n        <div class=\"floating-info-section\" id=\"floatingGoalSection\">\n            <div class=\"floating-info-section-title\">\n                <i class=\"fas fa-bullseye\"></i> 直播目标\n            </div>\n            <div class=\"floating-content\" id=\"floatingGoalDescription\"></div>\n        </div>\n        \n        <div class=\"floating-info-section\" id=\"floatingFanClubSection\">\n            <div class=\"floating-info-section-title\">\n                <i class=\"fas fa-users\"></i> 粉丝团留言\n            </div>\n            <div class=\"floating-content\" id=\"floatingFanClubDescription\"></div>\n        </div>\n        \n        <div class=\"floating-info-section\">\n            <div class=\"floating-info-section-title\">\n                <i class=\"fas fa-gift\"></i> 打赏菜单\n            </div>\n            <div class=\"floating-price-list\" id=\"floatingPriceList\"></div>\n        </div>\n        \n        <div class=\"floating-info-section\">\n            <div class=\"floating-info-section-title\">\n                <i class=\"fas fa-tv\"></i> 播放设置\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\">当前线路:</span>\n                <span class=\"floating-info-value\" id=\"floatingLine\">线路1</span>\n            </div>\n            <div class=\"floating-info-item\">\n                <span class=\"floating-info-label\">清晰度:</span>\n                <span class=\"floating-info-value\" id=\"floatingQuality\">默认</span>\n            </div>\n        </div>\n    </div>\n\n    <script src=\"https://cdn.jsdelivr.net/npm/dplayer@1.27.1/dist/DPlayer.min.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/npm/hls.js@1.4.10/dist/hls.min.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/js/all.min.js\"></script>\n    <script>\n        const liveDataElement = document.getElementById('liveData');\n        let liveData = {};\n        \n        if (liveDataElement.textContent) {\n            try {\n                liveData = JSON.parse(liveDataElement.textContent);\n            } catch (e) {}\n        }\n        \n        const chatContainer = document.getElementById('chatContainer');\n        let chatWs = null;\n\n        function addSystemMessage(text) {\n            const systemDiv = document.createElement('div');\n            systemDiv.className = 'message-item system-message';\n            systemDiv.textContent = text;\n            chatContainer.prepend(systemDiv);\n            chatContainer.scrollTop = 0;\n        }\n        \n        function initChat() {\n            if (!liveData.modelId || !liveData.websocketUrl || !liveData.websocketToken) return;\n\n            addSystemMessage('开始连接弹幕服务器');\n            \n            const timeoutMs = 10000;\n            let connectTimeoutTimer = setTimeout(() => {\n                if (chatWs && chatWs.readyState !== WebSocket.OPEN) {\n                    chatWs.close();\n                    addSystemMessage('连接超时：未能成功连接弹幕服务器');\n                }\n            }, timeoutMs);\n            \n            if (chatWs && chatWs.readyState === WebSocket.OPEN) {\n                chatWs.close();\n            }\n            \n            chatWs = new WebSocket(`${liveData.websocketUrl}`);\n            const sendQueue = [\n                '{\"connect\":{\"token\":\"' + liveData.websocketToken + '\"},\"id\":1}',\n                `{\"subscribe\":{\"channel\":\"newChatMessage@${liveData.modelId}\"},\"id\":2}`\n            ];\n            \n            function getUserLevelTag(userData) {\n                return userData?.userRanking?.level ? `<span class=\"level-tag\">Lv.${userData.userRanking.level}</span>` : '';\n            }\n            \n            function createMessageElement(data) {\n                const messageDiv = document.createElement('div');\n                messageDiv.className = 'message-item';\n                \n                const { type, userData, details } = data.message;\n                const levelTag = getUserLevelTag(userData);\n                \n                let content = '';\n                switch(type) {\n                    case 'text':\n                        messageDiv.className += ' text-item';\n                        content = `${levelTag}<span class=\"user-name\">${userData.username}</span>: ${details.body}`;\n                        break;\n                    case 'tip':\n                        messageDiv.className += ' tip-item';\n                        content = `${levelTag}<span class=\"user-name\">${userData.username}</span>: 已支付<span class=\"tip-amount\">${details.amount}</span>代币`;\n                        break;\n                    case 'lovense':\n                        messageDiv.className += ' lovense-item';\n                        const { power, time, amount } = details.lovenseDetails.detail;\n                        const powerText = power === 'low' ? '低' : power === 'medium' ? '中' : '高';\n                        const clientLevelTag = getUserLevelTag(details.lovenseDetails.clientUserInfo);\n                        content = `${clientLevelTag}<span class=\"user-name\">${details.lovenseDetails.clientUserInfo.username}</span>: ${powerText}强度 · ${time}秒`;\n                        break;\n                    default:\n                        return null;\n                }\n                \n                messageDiv.innerHTML = content;\n                return messageDiv;\n            }\n            \n            function addMessageToPanel(messageData) {\n                const messageElement = createMessageElement(messageData);\n                if (messageElement) {\n                    const messageWrapper = document.createElement('div');\n                    messageWrapper.className = 'message-wrapper';\n                    messageWrapper.appendChild(messageElement);\n                    chatContainer.prepend(messageWrapper);\n                    chatContainer.scrollTop = 0;\n                }\n            }\n            \n            chatWs.onopen = () => {\n                clearTimeout(connectTimeoutTimer);\n                sendQueue.forEach(cmd => chatWs.send(cmd));\n                addSystemMessage('弹幕服务器连接正常');\n            };\n            \n            chatWs.onmessage = (e) => {\n                if (e.data.trim() === '{}') {\n                    chatWs.send('{}');\n                    return;\n                }\n                try {\n                    const data = JSON.parse(e.data);\n                    if (data.ping) {\n                        chatWs.send(JSON.stringify({ pong: data.ping }));\n                    }\n                    if (data.push?.channel === `newChatMessage@${liveData.modelId}`) {\n                        addMessageToPanel(data.push.pub.data);\n                    }\n                } catch (error) {}\n            };\n            \n            chatWs.onerror = (err) => {\n                const errorDiv = document.createElement('div');\n                errorDiv.className = 'message-item system-message';\n                errorDiv.textContent = '连接错误';\n                chatContainer.prepend(errorDiv);\n                chatContainer.scrollTop = 0;\n            };\n            \n            chatWs.onclose = (e) => {\n                const closeDiv = document.createElement('div');\n                closeDiv.className = 'message-item system-message';\n                closeDiv.textContent = `连接关闭 | 错误码: ${e.code}`;\n                chatContainer.prepend(closeDiv);\n                chatContainer.scrollTop = 0;\n            };\n        }\n        \n        const elements = {\n            avatarImg: document.getElementById('avatarImg'),\n            hostName: document.getElementById('hostName'),\n            refreshBtn: document.getElementById('refreshBtn'),\n            volumeBtn: document.getElementById('volumeBtn'),\n            lineBtn: document.getElementById('lineBtn'),\n            lineMenu: document.getElementById('lineMenu'),\n            qualityBtn: document.getElementById('qualityBtn'),\n            qualityMenu: document.getElementById('qualityMenu'),\n            fullscreenBtn: document.getElementById('fullscreenBtn'),\n            loadingIndicator: document.getElementById('loadingIndicator'),\n            playerContainer: document.getElementById('playerContainer'),\n            membersCount: document.getElementById('membersCount'),\n            floatingBtn: document.getElementById('floatingBtn'),\n            floatingPanel: document.getElementById('floatingPanel'),\n            floatingHostName: document.getElementById('floatingHostName'),\n            floatingTopBestPlace: document.getElementById('floatingTopBestPlace'),\n            floatingMembersCount: document.getElementById('floatingMembersCount'),\n            floatingTipMenuCreatedAt: document.getElementById('floatingTipMenuCreatedAt'),\n            floatingTopic: document.getElementById('floatingTopic'),\n            floatingTopicSection: document.getElementById('floatingTopicSection'),\n            floatingGoalDescription: document.getElementById('floatingGoalDescription'),\n            floatingGoalSection: document.getElementById('floatingGoalSection'),\n            floatingUserDescription: document.getElementById('floatingUserDescription'),\n            floatingUserDescriptionSection: document.getElementById('floatingUserDescriptionSection'),\n            floatingFanClubDescription: document.getElementById('floatingFanClubDescription'),\n            floatingFanClubSection: document.getElementById('floatingFanClubSection'),\n            floatingPriceList: document.getElementById('floatingPriceList'),\n            floatingDurationLabel: document.getElementById('floatingDurationLabel'),\n            floatingDuration: document.getElementById('floatingDuration'),\n            floatingTimeLabel: document.getElementById('floatingTimeLabel'),\n            floatingStatusTime: document.getElementById('floatingStatusTime'),\n            floatingLine: document.getElementById('floatingLine'),\n            floatingQuality: document.getElementById('floatingQuality'),\n            topicContainer: document.getElementById('topicContainer'),\n            topic: document.getElementById('topic'),\n            rotateBtn: document.getElementById('rotateBtn')\n        };\n        \n        let dp = null;\n        let isMuted = false;\n        let isFullscreen = false;\n        let hlsInstance = null;\n        let durationInterval = null;\n        let config = {};\n        let hideControlsTimer = null;\n        \n        const getStreamUrl = (lineIndex = config.currentLine || 0, quality = config.currentQuality || 'auto') => {\n            const line = config.hlsLines?.[lineIndex];\n            if (!line || !config.stream) return '';\n            \n            const pureStatus = (config.status || '').toLowerCase();\n            let suffix = '_auto';\n            \n            if (pureStatus !== 'public') {\n                suffix = '_160p_blurred';\n            } else if (quality === 'auto') {\n                suffix = '_auto';\n            } else {\n                suffix = '_' + quality;\n            }\n            \n            return `https://edge-hls.${line}/hls/${config.stream}/master/${config.stream}${suffix}.m3u8?pkey=bXorqTB5ZhP5FcpX`;\n        };\n        \n        function showControls() {\n            elements.playerContainer.classList.remove('controls-hidden');\n            elements.playerContainer.classList.add('controls-visible');\n            if (hideControlsTimer) {\n                clearTimeout(hideControlsTimer);\n            }\n            hideControlsTimer = setTimeout(() => {\n                elements.playerContainer.classList.remove('controls-visible');\n                elements.playerContainer.classList.add('controls-hidden');\n            }, 3000);\n        }\n        \n        function switchStream(url) {\n            if (!dp || !dp.video || !url) return;\n            \n            config.isSwitching = true;\n            elements.loadingIndicator.style.display = 'block';\n            showControls();\n            \n            const video = dp.video;\n            video.pause();\n            video.src = '';\n            video.load();\n            \n            if (hlsInstance) {\n                try {\n                    hlsInstance.stopLoad();\n                    setTimeout(() => {\n                        hlsInstance.destroy();\n                        hlsInstance = null;\n                        startNewStream(url, video);\n                    }, 50);\n                } catch (e) {\n                    hlsInstance.destroy();\n                    hlsInstance = null;\n                    startNewStream(url, video);\n                }\n            } else {\n                startNewStream(url, video);\n            }\n        }\n        \n        function startNewStream(url, video) {\n            video.src = url;\n            \n            if (Hls.isSupported()) {\n                hlsInstance = new Hls({\n                    enableWorker: true,\n                    lowLatencyMode: true,\n                    backBufferLength: 60,\n                    maxBufferSize: 30 * 1000 * 1000,\n                    maxBufferLength: 30\n                });\n                \n                hlsInstance.loadSource(url);\n                hlsInstance.attachMedia(video);\n                \n                hlsInstance.on(Hls.Events.MANIFEST_PARSED, () => {\n                    completeSwitch();\n                    video.play().catch(e => {});\n                });\n                \n                hlsInstance.on(Hls.Events.ERROR, (event, data) => {\n                    if (data.fatal) {\n                        switch(data.type) {\n                            case Hls.ErrorTypes.NETWORK_ERROR:\n                                hlsInstance.startLoad();\n                                break;\n                            case Hls.ErrorTypes.MEDIA_ERROR:\n                                hlsInstance.recoverMediaError();\n                                break;\n                            default:\n                                completeSwitch();\n                                break;\n                        }\n                    }\n                });\n                \n                setTimeout(() => {\n                    if (config.isSwitching) {\n                        completeSwitch();\n                    }\n                }, 5000);\n                \n            } else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n                video.addEventListener('loadedmetadata', () => {\n                    completeSwitch();\n                    video.play().catch(e => {});\n                });\n                \n                video.addEventListener('error', () => {\n                    completeSwitch();\n                });\n                \n                setTimeout(() => {\n                    if (config.isSwitching) {\n                        completeSwitch();\n                    }\n                }, 5000);\n            } else {\n                completeSwitch();\n            }\n        }\n        \n        function completeSwitch() {\n            config.isSwitching = false;\n            elements.loadingIndicator.style.display = 'none';\n        }\n        \n        function initPlayer() {\n            config = { ...liveData, currentLine: 0, currentQuality: 'auto', isSwitching: false };\n            \n            const url = getStreamUrl();\n            if (!url) return;\n            \n            if (dp) {\n                dp.destroy();\n                dp = null;\n            }\n            \n            dp = new DPlayer({\n                container: document.getElementById('dplayer'),\n                live: true,\n                autoplay: true,\n                theme: '#00a1d6',\n                loop: false,\n                lang: 'zh-cn',\n                screenshot: false,\n                hotkey: false,\n                preload: 'auto',\n                volume: 0.7,\n                mutex: true,\n                controls: false,\n                video: {\n                    url: url,\n                    pic: config.coverImg,\n                    type: 'customHls',\n                    customType: {\n                        customHls: function(video, player) {}\n                    }\n                },\n                contextmenu: [],\n                danmaku: false\n            });\n            \n            const videoElement = dp.video;\n            if (videoElement) {\n                videoElement.style.pointerEvents = 'none';\n                videoElement.addEventListener('click', function(e) {\n                    e.preventDefault();\n                    e.stopPropagation();\n                    return false;\n                });\n            }\n            \n            const dplayerContainer = dp.container;\n            dplayerContainer.style.pointerEvents = 'none';\n            dplayerContainer.addEventListener('click', function(e) {\n                e.preventDefault();\n                e.stopPropagation();\n                return false;\n            });\n            \n            isMuted = dp.video.muted;\n            elements.volumeBtn.innerHTML = isMuted \n                ? '<i class=\"fas fa-volume-mute\"></i>'\n                : '<i class=\"fas fa-volume-up\"></i>';\n            \n            switchStream(url);\n        }\n\n        function refreshPlayer() {\n            if (config.isSwitching || !config.stream) return;\n            const url = getStreamUrl(config.currentLine, config.currentQuality);\n            switchStream(url);\n        }\n        \n        function switchLine(lineIndex) {\n            if (config.isSwitching || !config.hlsLines || lineIndex >= config.hlsLines.length) return;\n            config.currentLine = lineIndex;\n            elements.lineBtn.innerHTML = `线路${lineIndex + 1} <i class=\"fas fa-chevron-down\"></i>`;\n            elements.floatingLine.textContent = `线路${lineIndex + 1}`;\n            updateLineMenuHighlights();\n            elements.lineMenu.style.display = 'none';\n            \n            const url = getStreamUrl(lineIndex, config.currentQuality);\n            switchStream(url);\n        }\n        \n        function switchQuality(quality) {\n            if (config.isSwitching) return;\n            config.currentQuality = quality;\n            const displayText = quality === 'auto' ? '默认' : quality;\n            elements.qualityBtn.innerHTML = `${displayText} <i class=\"fas fa-chevron-down\"></i>`;\n            elements.floatingQuality.textContent = displayText;\n            updateQualityMenuHighlights();\n            elements.qualityMenu.style.display = 'none';\n            \n            const url = getStreamUrl(config.currentLine, quality);\n            switchStream(url);\n        }\n        \n        function formatDuration(seconds) {\n            if (!seconds) return '0秒';\n            \n            const days = Math.floor(seconds / (24 * 60 * 60));\n            const hours = Math.floor((seconds % (24 * 60 * 60)) / (60 * 60));\n            const minutes = Math.floor((seconds % (60 * 60)) / 60);\n            const secs = Math.floor(seconds % 60);\n            \n            let result = '';\n            if (days > 0) result += `${days}天`;\n            if (hours > 0) result += `${hours}小时`;\n            if (minutes > 0) result += `${minutes}分钟`;\n            if (secs > 0 || result === '') result += `${secs}秒`;\n            \n            return result;\n        }\n        \n        function updateTimeInfo() {\n            if (!config.status || !config.startTime) return;\n            \n            const pureStatus = config.status.replace(/^状态：/, '').toLowerCase();\n            const isPublic = pureStatus === 'public';\n            const startTime = config.startTime ? new Date(config.startTime).getTime() : null;\n            const now = Date.now();\n            \n            if (config.isLive && startTime) {\n                if (isPublic) {\n                    elements.floatingDurationLabel.textContent = '直播时长:';\n                    elements.floatingTimeLabel.textContent = '直播时间:';\n                    \n                    const duration = Math.floor((now - startTime) / 1000);\n                    const durationText = formatDuration(duration);\n                    elements.floatingDuration.textContent = durationText;\n                    \n                    const startDate = new Date(startTime);\n                    elements.floatingStatusTime.textContent = startDate.toLocaleString();\n                } else {\n                    elements.floatingDurationLabel.textContent = '持续时长:';\n                    elements.floatingTimeLabel.textContent = '私密直播:';\n                    \n                    const duration = Math.floor((now - startTime) / 1000);\n                    const durationText = formatDuration(duration);\n                    elements.floatingDuration.textContent = durationText;\n                    \n                    const startDate = new Date(startTime);\n                    elements.floatingStatusTime.textContent = startDate.toLocaleString();\n                }\n            } else if (startTime) {\n                elements.floatingDurationLabel.textContent = '持续时长:';\n                elements.floatingTimeLabel.textContent = '下播时间:';\n                \n                const duration = Math.floor((now - startTime) / 1000);\n                let durationText = formatDuration(duration);\n                elements.floatingDuration.textContent = durationText;\n                \n                const endDate = new Date(startTime);\n                elements.floatingStatusTime.textContent = endDate.toLocaleString();\n            } else {\n                elements.floatingDuration.textContent = '--';\n                elements.floatingStatusTime.textContent = '--';\n            }\n        }\n        \n        function startDurationUpdate() {\n            if (durationInterval) {\n                clearInterval(durationInterval);\n            }\n            \n            updateTimeInfo();\n            durationInterval = setInterval(updateTimeInfo, 1000);\n        }\n        \n        function updateFloatingPanel() {\n            const pureUsername = (config.username || '').split('/').pop() || config.username || '';\n            elements.floatingHostName.textContent = pureUsername || '未知主播';\n            elements.membersCount.textContent = config.membersCount > 0 ? config.membersCount.toLocaleString() : '--';\n            elements.floatingMembersCount.textContent = config.membersCount > 0 ? config.membersCount.toLocaleString() : '--';\n            \n            if (config.topBestPlace > 0) {\n                const rankText = `TOP ${config.topBestPlace}`;\n                elements.floatingTopBestPlace.textContent = rankText;\n            } else {\n                elements.floatingTopBestPlace.textContent = '未上榜';\n            }\n            \n            if (config.tipMenuCreatedAt) {\n                const createdAt = new Date(config.tipMenuCreatedAt);\n                elements.floatingTipMenuCreatedAt.textContent = createdAt.toLocaleString();\n            } else {\n                elements.floatingTipMenuCreatedAt.textContent = '--';\n            }\n            \n            if (config.userDescription && config.userDescription.trim() !== '') {\n                elements.floatingUserDescription.textContent = config.userDescription;\n                elements.floatingUserDescriptionSection.style.display = 'block';\n            } else {\n                elements.floatingUserDescriptionSection.style.display = 'none';\n            }\n            \n            if (config.goalDescription && config.goalDescription.trim() !== '') {\n                elements.floatingGoalDescription.textContent = config.goalDescription;\n                elements.floatingGoalSection.style.display = 'block';\n            } else {\n                elements.floatingGoalSection.style.display = 'none';\n            }\n            \n            if (config.fanClubDescription && config.fanClubDescription.trim() !== '') {\n                elements.floatingFanClubDescription.textContent = config.fanClubDescription;\n                elements.floatingFanClubSection.style.display = 'block';\n            } else {\n                elements.floatingFanClubSection.style.display = 'none';\n            }\n            \n            if (config.tipMenuPriceList && config.tipMenuPriceList.length > 0) {\n                elements.floatingPriceList.innerHTML = '';\n                config.tipMenuPriceList.forEach((tip) => {\n                    const priceItem = document.createElement('div');\n                    priceItem.className = 'floating-price-item';\n                    \n                    const activityDiv = document.createElement('div');\n                    activityDiv.className = 'floating-price-activity';\n                    activityDiv.textContent = tip.activity || '未命名';\n                    \n                    const priceDiv = document.createElement('div');\n                    priceDiv.className = 'floating-price-value';\n                    priceDiv.textContent = `${tip.price || 0} 代币`;\n                    \n                    priceItem.appendChild(activityDiv);\n                    priceItem.appendChild(priceDiv);\n                    elements.floatingPriceList.appendChild(priceItem);\n                });\n            } else {\n                elements.floatingPriceList.innerHTML = '<div class=\"floating-price-item\"><div class=\"floating-price-activity\">暂无打赏菜单</div></div>';\n            }\n            \n            startDurationUpdate();\n        }\n        \n        function initUI() {\n            const pureUsername = (config.username || '').split('/').pop() || config.username || '';\n            elements.hostName.textContent = pureUsername || '未知主播';\n            \n            if (config.topic && config.topic.trim() !== '') {\n                elements.topic.textContent = config.topic;\n                elements.topicContainer.style.display = 'block';\n                document.title = config.topic;\n            } else {\n                elements.topicContainer.style.display = 'none';\n                document.title = pureUsername || '直播间';\n            }\n            \n            if (config.avatarUrl) {\n                const prefix = 'https://static-cdn.strpst.com';\n                if (config.avatarUrl.startsWith(prefix + prefix)) {\n                    config.avatarUrl = config.avatarUrl.replace(prefix + prefix, prefix);\n                }\n                elements.avatarImg.src = config.avatarUrl;\n            } else {\n                elements.avatarImg.src = '主播';\n            }\n            \n            updateFloatingPanel();\n        }\n        \n        function initLineMenu() {\n            elements.lineMenu.innerHTML = '';\n            \n            if (!config.hlsLines || config.hlsLines.length === 0) {\n                const item = document.createElement('div');\n                item.className = 'menu-item';\n                item.textContent = '无线路';\n                item.style.opacity = '0.6';\n                elements.lineMenu.appendChild(item);\n                return;\n            }\n            \n            config.hlsLines.forEach((line, index) => {\n                const item = document.createElement('div');\n                item.className = `menu-item ${index === config.currentLine ? 'active' : ''}`;\n                item.textContent = `线路${index + 1}`;\n                item.dataset.index = index;\n                item.onclick = (e) => {\n                    e.stopPropagation();\n                    switchLine(index);\n                };\n                elements.lineMenu.appendChild(item);\n            });\n        }\n        \n        function initQualityMenu() {\n            elements.qualityMenu.innerHTML = '';\n            const pureStatus = (config.status || '').replace(/^状态：/, '').toLowerCase();\n            \n            let availableQualities = [];\n            availableQualities.push({ value: 'auto', display: '默认' });\n            \n            if (pureStatus !== 'public') {\n                availableQualities = [{ value: '160p_blurred', display: '模糊' }];\n                config.currentQuality = '160p_blurred';\n            } else if (config.pixelatedResolutions && config.pixelatedResolutions.length > 0) {\n                config.pixelatedResolutions.forEach(resolution => {\n                    if (resolution !== '160p_blurred') {\n                        availableQualities.push({ \n                            value: resolution, \n                            display: resolution \n                        });\n                    }\n                });\n            }\n            \n            availableQualities.forEach((quality) => {\n                const isActive = quality.value === config.currentQuality;\n                const item = document.createElement('div');\n                item.className = `menu-item ${isActive ? 'active' : ''}`;\n                item.textContent = quality.display;\n                item.dataset.quality = quality.value;\n                item.onclick = (e) => {\n                    e.stopPropagation();\n                    switchQuality(quality.value);\n                };\n                elements.qualityMenu.appendChild(item);\n            });\n            \n            const currentQuality = availableQualities.find(q => q.value === config.currentQuality);\n            const displayText = currentQuality ? currentQuality.display : '默认';\n            elements.qualityBtn.innerHTML = `${displayText} <i class=\"fas fa-chevron-down\"></i>`;\n            elements.floatingQuality.textContent = displayText;\n        }\n        \n        function updateLineMenuHighlights() {\n            const items = elements.lineMenu.querySelectorAll('.menu-item');\n            items.forEach((item, index) => {\n                if (index === config.currentLine) {\n                    item.classList.add('active');\n                } else {\n                    item.classList.remove('active');\n                }\n            });\n        }\n        \n        function updateQualityMenuHighlights() {\n            const items = elements.qualityMenu.querySelectorAll('.menu-item');\n            items.forEach((item) => {\n                const quality = item.dataset.quality;\n                if (quality === config.currentQuality) {\n                    item.classList.add('active');\n                } else {\n                    item.classList.remove('active');\n                }\n            });\n        }\n        \n        async function handleRotateClick() {\n            try {\n                if (!document.fullscreenElement) {\n                    await elements.playerContainer.requestFullscreen();\n                }\n                \n                if (screen.orientation) {\n                    const type = screen.orientation.type;\n                    if (type.startsWith('portrait')) {\n                        await screen.orientation.lock('landscape');\n                        elements.rotateBtn.textContent = '横屏';\n                    } else {\n                        await screen.orientation.lock('portrait');\n                        elements.rotateBtn.textContent = '横屏';\n                    }\n                }\n                showControls();\n            } catch (err) {}\n        }\n        \n        function bindEvents() {\n            elements.refreshBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                refreshPlayer();\n                showControls();\n            });\n            \n            elements.volumeBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                if (dp && dp.video && !config.isSwitching) {\n                    isMuted = !isMuted;\n                    dp.video.muted = isMuted;\n                    elements.volumeBtn.innerHTML = isMuted \n                        ? '<i class=\"fas fa-volume-mute\"></i>'\n                        : '<i class=\"fas fa-volume-up\"></i>';\n                }\n                showControls();\n            });\n            \n            elements.fullscreenBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                if (!isFullscreen) {\n                    const container = document.querySelector('.player-container');\n                    if (container.requestFullscreen) {\n                        container.requestFullscreen();\n                    } else if (container.webkitRequestFullscreen) {\n                        container.webkitRequestFullscreen();\n                    }\n                    elements.fullscreenBtn.innerHTML = '<i class=\"fas fa-compress\"></i>';\n                } else {\n                    if (document.exitFullscreen) {\n                        document.exitFullscreen();\n                    } else if (document.webkitExitFullscreen) {\n                        document.webkitExitFullscreen();\n                    }\n                    elements.fullscreenBtn.innerHTML = '<i class=\"fas fa-expand\"></i>';\n                }\n                isFullscreen = !isFullscreen;\n                showControls();\n            });\n            \n            elements.lineBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                elements.lineMenu.style.display = \n                    elements.lineMenu.style.display === 'block' ? 'none' : 'block';\n                elements.qualityMenu.style.display = 'none';\n                updateLineMenuHighlights();\n                showControls();\n            });\n            \n            elements.qualityBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                elements.qualityMenu.style.display = \n                    elements.qualityMenu.style.display === 'block' ? 'none' : 'block';\n                elements.lineMenu.style.display = 'none';\n                updateQualityMenuHighlights();\n                showControls();\n            });\n            \n            elements.rotateBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                handleRotateClick();\n            });\n            \n            elements.playerContainer.addEventListener('touchstart', (e) => {\n                if (e.target.closest('.custom-controls, .selector-menu, .control-btn, .selector-btn, .menu-item, .rotate-btn')) {\n                    showControls();\n                    return;\n                }\n                \n                if (elements.playerContainer.classList.contains('controls-hidden')) {\n                    showControls();\n                } else {\n                    elements.playerContainer.classList.remove('controls-visible');\n                    elements.playerContainer.classList.add('controls-hidden');\n                    if (hideControlsTimer) {\n                        clearTimeout(hideControlsTimer);\n                        hideControlsTimer = null;\n                    }\n                }\n            });\n            \n            document.addEventListener('click', (e) => {\n                if (!e.target.closest('.selector-btn')) {\n                    elements.lineMenu.style.display = 'none';\n                    elements.qualityMenu.style.display = 'none';\n                }\n            });\n            \n            document.addEventListener('fullscreenchange', handleFullscreenChange);\n            document.addEventListener('webkitfullscreenchange', handleFullscreenChange);\n            \n            elements.floatingBtn.addEventListener('click', (e) => {\n                e.stopPropagation();\n                elements.floatingPanel.style.display = \n                    elements.floatingPanel.style.display === 'block' ? 'none' : 'block';\n            });\n            \n            document.addEventListener('click', (e) => {\n                if (!e.target.closest('.floating-button') && !e.target.closest('.floating-panel')) {\n                    elements.floatingPanel.style.display = 'none';\n                }\n            });\n        }\n        \n        function handleFullscreenChange() {\n            const isFullscreenNow = !!(document.fullscreenElement || \n                document.webkitFullscreenElement);\n            if (!isFullscreenNow) {\n                elements.fullscreenBtn.innerHTML = '<i class=\"fas fa-expand\"></i>';\n                isFullscreen = false;\n            }\n        }\n        \n        function initializeApp() {\n            if (!liveData || Object.keys(liveData).length === 0) return;\n            \n            addSystemMessage('正在读取直播间信息');\n            \n            config = { ...liveData, currentLine: 0, currentQuality: 'auto', isSwitching: false };\n            \n            initUI();\n            initLineMenu();\n            initQualityMenu();\n            initPlayer();\n            bindEvents();\n            initChat();\n            \n            elements.playerContainer.classList.add('controls-visible');\n            showControls();\n        }\n        \n        document.addEventListener('DOMContentLoaded', initializeApp);\n    </script>\n</body>\n</html>",
    "ruleImage": "https://img.doppiocdn.live/thumbs/{$.popularSnapshotTimestamp}/{$..id}_webp",
    "ruleLink": "/{$.username}",
    "rulePubDate": "{$.isLive}观众：{$.viewersCount}人 状态：{$.status}@js:result.replace(/(状态：)public/g, \"$1公开\").replace(/(状态：)(?!公开).+/g, \"$1付费\").replace(/false.*/g, '状态：未直播').replace(/true/g, '')",
    "ruleTitle": "$.username",
    "singleUrl": false,
    "sortUrl": "全部直播::/api/front/v2/models?limit=60&primaryTag=girls\n直播推荐::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"recommended\"]]\n竖屏直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"mobile\"]]\n中文直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"tagLanguageChinese\"]]\n日本直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"tagLanguageJapanese\"]]\n韩国直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"tagLanguageKorean\"]]\n户外直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"doPublicPlace\"]]\n青少年直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"ageTeen\"]]\n俄罗斯直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"tagLanguageRussianSpeaking\"]]\nASMR直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"asmr\"]]\nCOS直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"doCosplay\"]]\n情侣直播::/api/front/models?limit=60&primaryTag=couples\n变性直播::/api/front/models?limit=60&primaryTag=trans\n新人直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"autoTagNew\"]]\n互动玩具::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"autoTagInteractiveToy\"]]\n炮机直播::/api/front/models?limit=60&primaryTag=girls&filterGroupTags=[[\"fuckMachine\"]]",
    "sourceComment": "备用：\nhttps://zh.virtualtaboo.live\nhttps://zh.spiritzone.top\nhttps://zh.stripchat.webcam\nhttps://zh.mywebcamroom.com\nhttps://zh.topcams.tv\nhttps://zh.stripchatgirls.com\nhttps://zh.stripchat.com\nhttps://zh.xhamsterlive.com\nhttps://zh.hotzcam.com\nhttps://zh.tklivechat.com\nhttps://zh.spankbanglive.com\nhttps://zh.live.91pinse.com\npkey=Iecohquahc5RieQu\npkey=bXorqTB5ZhP5FcpX",
    "sourceGroup": "直播",
    "sourceIcon": "https://img2.baidu.com/it/u=3810767422,2486090729&fm=253&fmt=auto&app=138&f=PNG?w=192&h=192",
    "sourceName": "直播3",
    "sourceUrl": "https://zh.topcams.tv"
  },
  {
    "articleStyle": 0,
    "customOrder": 4777,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": false,
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "singleUrl": true,
    "sourceGroup": "漫画",
    "sourceIcon": "https://i.postimg.cc/xTLWq1dp/IMG-20220930-223954.jpg",
    "sourceName": "漫画",
    "sourceUrl": "http://www.mxshm.top"
  },
  {
    "articleStyle": 0,
    "customOrder": 4778,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\n    'User-Agent': 'Mozilla/5.0 (Linux; Android 11; Pixel 3 XL Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.4988.0 Mobile Safari/537.36 SearchCraft/3.9.2 (Baidu; P1 11) '\n}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": ".catagory-list ul li",
    "ruleContent": ".post-content@all",
    "ruleImage": "@js:\"https://i.postimg.cc/rwJKQgWq/1680488577806.png\"",
    "ruleLink": "a@href",
    "ruleNextPage": "text.下一页@href",
    "rulePubDate": "span@text",
    "ruleTitle": "a@text",
    "singleUrl": false,
    "sortUrl": "人妻熟女::https://dwkm.xyz/category/milf.html\n师生校园::https://dwkm.xyz/category/school.html\n都市生活::https://dwkm.xyz/category/city.html\n强暴虐待::https://dwkm.xyz/category/bdsm.html\n家庭乱伦::https://dwkm.xyz/category/family.html\n明星名媛::https://dwkm.xyz/category/celebrity.html\n成人武侠::https://dwkm.xyz/category/classic.html\n",
    "sourceGroup": "小说",
    "sourceIcon": "https://i.postimg.cc/8CnkM6sZ/Screenshot-20230503-195814.jpg",
    "sourceName": "小说1",
    "sourceUrl": "https://dwkm.xyz/category/school-p{{page}}.html"
  },
  {
    "articleStyle": 0,
    "customOrder": 4779,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "{\"User-Agent\": \"Mozilla/5.0 (Linux; Android 12; 22041211AC Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.104 Mobile Safari/537.36\"}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "ruleArticles": ".list-group@a",
    "ruleContent": "<title>🏄Mengteen</title>\n{{@@.panel-body@p@html}}",
    "ruleImage": "@js:\"https://iknow-pic.cdn.bcebos.com/8326cffc1e178a82ae0a94affb03738da977e88f?x-bce-process=image/resize,m_lfit,w_600,h_800,limit_1/quality,q_85/format,f_auto\"",
    "ruleLink": "a@href",
    "ruleNextPage": "page",
    "rulePubDate": "@js:\"📖书中自有颜如玉;开启一天的阅读吧!\"",
    "ruleTitle": "a@text",
    "singleUrl": false,
    "sortUrl": "都市::/arttype/20-{{page}}.html\n搜索::/artsearch/{{source.getVariable()}}------{{page}}-.html\n校园::/arttype/21-{{page}}.html\n真实::/arttype/22-{{page}}.html\n武侠::/arttype/23-{{page}}.html\n乱伦::/arttype/24-{{page}}.html\n职场::/arttype/25-{{page}}.html\n经验::/arttype/26-{{page}}.html\n暴力::/arttype/27-{{page}}.html\n幻想::/arttype/28-{{page}}.html\n明星::/arttype/29-{{page}}.html\n人妻::/arttype/30-{{page}}.html",
    "sourceComment": "源社区：@Mengteen 2025.06.29原创\n二传二创或者是其它问题请联系我。\n我邮箱:[xxxmgqxxx@vip.qq.com]",
    "sourceGroup": "小说",
    "sourceIcon": "https://i.postimg.cc/8CnkM6sZ/Screenshot-20230503-195814.jpg",
    "sourceName": "小说2",
    "sourceUrl": "https://yinghuar.yingxx102.cc/label/index.html##@Mengteen",
    "variableComment": "🏄Mengteen提示：在此输入关键词搜索！"
  }
]