[{"articleStyle":1,"cacheFirst":false,"coverDecodeJs":"java.createSymmetricCrypto(\"AES\/CBC\/NoPadding\",\"f5d965df75336270\",\"97b60394abc2fbe1\").decrypt(result)","customOrder":-10106724,"enableJs":true,"enabled":true,"enabledCookieJar":false,"header":"hls = new Hls({\n    xhrSetup:function(xhr){\n        xhr.setRequestHeader(\"Referer\",\"https:\/\/域名\");\n        xhr.setRequestHeader(\"Origin\",\"https:\/\/域名\");\n    }\n});","injectJs":"(function() {\n    \/\/ ===== 横屏锁（仅横屏内容生效） =====\n    \/\/ 全屏时若视频为横屏，旋转页面并锁定方向为 landscape\n    var st = document.createElement('style');\n    st.textContent = 'body.fs-ls{transform:rotate(90deg) translateY(-100%);transform-origin:top left;width:100vh!important;height:100vw!important;overflow:hidden!important;position:fixed!important;top:0!important;left:0!important}';\n    document.head.appendChild(st);\n\n    function isLS() {\n        var v = document.querySelector('video');\n        return (!v || !v.videoWidth) ? true : v.videoWidth >= v.videoHeight;\n    }\n    function fsHandler() {\n        var full = document.fullscreenElement || document.webkitFullscreenElement;\n        if (full && isLS()) {\n            document.body.classList.add('fs-ls');\n            if (screen.orientation && screen.orientation.lock)\n                screen.orientation.lock('landscape').catch(function(){});\n        } else {\n            document.body.classList.remove('fs-ls');\n            if (screen.orientation && screen.orientation.unlock)\n                screen.orientation.unlock();\n        }\n    }\n    document.addEventListener('fullscreenchange', fsHandler);\n    document.addEventListener('webkitfullscreenchange', fsHandler);\n    if (document.fullscreenElement || document.webkitFullscreenElement) fsHandler();\n\n    \/\/ ============ 手势 ============\n    function bind(v) {\n        if (v.__gestureBound) return;\n        v.__gestureBound = true;\n\n        \/\/ ===== 可调参数 =====\n        var LONG_PRESS_MS = 500;    \/\/ 长按判定时长（毫秒）\n        var FAST_RATE     = 3.0;    \/\/ 长按时的播放倍速，这里调倍速\n        var SWIPE_SENS    = 2.0;    \/\/ 滑动灵敏度：划满一屏 = 播放完整时长，0.5 就是半屏\n        var SEEK_THROTTLE = 24;     \/\/ seek 节流间隔（毫秒）\n\n        var sx = 0, st0 = 0, lp = null, ff = false, wasPaused = false, origRate = 1;\n        var pendT = 0, seekTimer = null, seekPending = false, tipEl = null;\n        var speedTipEl = null;\n\n        \/\/ 把秒数格式化为 mm:ss\n        function fmt(t){var m=Math.floor(t\/60),s=Math.floor(t%60);return(m<10?'0':'')+m+':'+(s<10?'0':'')+s;}\n        \/\/ 显示进度浮层（当前时间 \/ 总时长）\n        function showTip(t){\n            if(!tipEl){tipEl=document.createElement('div');tipEl.style.cssText='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:rgba(0,0,0,.75);color:#fff;padding:10px 20px;border-radius:8px;font-size:16px;font-weight:bold;z-index:99999;pointer-events:none;';document.body.appendChild(tipEl);}\n            tipEl.textContent = fmt(t)+' \/ '+fmt(v.duration||0);\n            tipEl.style.display = 'block';\n        }\n        function hideTip(){ if(tipEl) tipEl.style.display='none'; }\n\n        \/\/ 显示倍速浮层（如 \"3x 倍速中\"）\n        function showSpeedTip(){\n            if(!speedTipEl){\n                speedTipEl=document.createElement('div');\n                speedTipEl.style.cssText='position:fixed;top:20px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,.8);color:#fff;padding:8px 16px;border-radius:20px;font-size:14px;z-index:99999;pointer-events:none;';\n                document.body.appendChild(speedTipEl);\n            }\n            speedTipEl.textContent = v.playbackRate + 'x 倍速中';\n            speedTipEl.style.display = 'block';\n        }\n        function hideSpeedTip(){ if(speedTipEl) speedTipEl.style.display='none'; }\n\n        function stopLong(){ if(lp){clearTimeout(lp);lp=null;} }\n        \/\/ 退出长按快进：恢复原始倍速，原本暂停的重新暂停\n        function resetFF(){ if(ff){v.playbackRate=origRate;ff=false;hideSpeedTip();if(wasPaused)v.pause();} }\n        \/\/ 立即应用挂起的 seek\n        function flushSeek(){ if(seekPending){seekPending=false;if(isFinite(pendT))v.currentTime=pendT;} clearTimeout(seekTimer); }\n\n        \/\/ 触摸开始：启动长按定时器，超时进入快进模式\n        v.addEventListener('touchstart', function(e){\n            if(e.touches.length!==1) { stopLong(); return; }\n            sx = e.touches[0].clientX;\n            st0 = v.currentTime || 0;\n            wasPaused = v.paused;\n            origRate = v.playbackRate || 1;\n            stopLong();\n            lp = setTimeout(function(){\n                lp = null;\n                ff = true;\n                v.playbackRate = FAST_RATE;\n                if(wasPaused) { var p = v.play(); if(p && p.catch) p.catch(function(){}); }\n                showSpeedTip();\n                hideTip();\n            }, LONG_PRESS_MS);\n        }, {passive:true});\n\n        \/\/ 触摸移动：超过 15px 视为滑动，按滑动比例快进\/快退\n        v.addEventListener('touchmove', function(e){\n            if(e.touches.length!==1) return;\n            stopLong();\n            var dx = e.touches[0].clientX - sx;\n            if(Math.abs(dx) > 15){\n                if(ff){v.playbackRate=origRate;ff=false;hideSpeedTip();}\n                e.preventDefault();\n                var dur = v.duration;\n                if(!isFinite(dur) || dur <= 0) return;   \/\/ 直播保护\n                var nt = st0 + (dx \/ (window.innerWidth * SWIPE_SENS)) * dur;\n                if(nt<0) nt=0; if(nt>dur) nt=dur;\n                pendT = nt;\n                showTip(nt);\n                if(!seekPending){\n                    seekPending = true;\n                    seekTimer = setTimeout(function(){ seekPending=false; if(isFinite(pendT)) v.currentTime=pendT; }, SEEK_THROTTLE);\n                }\n            }\n        }, {passive:false});\n\n        \/\/ 触摸结束：长按中则恢复倍速，否则应用最后一次 seek\n        function endTouch(){\n            stopLong();\n            if(ff){ resetFF(); return; }\n            flushSeek();\n            hideTip();\n        }\n        v.addEventListener('touchend', endTouch);\n        v.addEventListener('touchcancel', endTouch);\n    }\n\n    function tryBind(){\n        var v = document.querySelector('video');\n        if(v){ bind(v); }\n        setTimeout(tryBind, 800);\n    }\n    tryBind();\n    console.log('[注入] 已启用');\n})();","lastUpdateTime":1793261099652,"loadWithBaseUrl":true,"preload":false,"ruleArticles":"article","ruleContent":"@js:\nvar data = [], title = \"\";\nvar resultStr = String(result);\nvar sourcekey = String(source.getVariable() || \"\").replace(\/\\\/$\/, \"\");\n\n\/\/ 使用稳定的全网公共 CDN\nvar js = \"https:\/\/s4.zstatic.net\/ajax\/libs\/hls.js\/1.6.13\/hls.min.js\";\n\nvar getM3u8 = (html = resultStr) => {\n    var decodedHtml = html.replace(\/&quot;\/g, '\"').replace(\/\\\\\\\/\/g, '\/');\n    var url = \/(https?:[^'\"\\s]*?\\.m3u8[^'\"\\s]*)\/g;\n    var urlSet = new Set();\n    for (var match of (decodedHtml.matchAll(url) || [])) {\n        var ul = match[1].replace(\/\\\\\/g, \"\");\n        ul = ul.replace(\/[^a-zA-Z0-9:\\\/\\-\\.\\?\\=\\&_]\/g, '');\n        if (ul.length > 10) urlSet.add(ul);\n    }\n    return Array.from(urlSet);\n};\n\nif (\/点我\/.test(result) && \/查看详情\/.test(result)) {\n    \/\/ 【如果是合集页的逻辑，保持原样】\n    var list = java.getElements('@@#post>article>.post-content>p>a');\n    var links = Array.from(list).slice(0, -1);\n    var items = [];\n    links.forEach((link, i) => {\n        var href = String(link.attr('href'));\n        var itemTitle = String(link.text()).replace(\/.*《(.*?)》.*\/, \"$1\");\n        var fullUrl = href.indexOf('http') === 0 ? href : (sourcekey + href);\n        \n        if (i === 0) {\n            var doc = String(java.ajax(fullUrl));\n            var urls = getM3u8(doc);\n            urls.forEach((u, j) => {\n                items.push({ title: itemTitle + \" (P\" + (j+1) + \")\", href: '', urls: [u], loaded: true });\n            });\n        } else {\n            items.push({ title: itemTitle, href: fullUrl, urls: [], loaded: false });\n        }\n    });\n    data = items;\n} else {\n    \/\/ 【★ 单页多视频逻辑：提取 h2 标题 + 对应视频链接】\n    title = java.getString('h1.post-title@text') || java.getString('h1@text') || \"视频播放\";\n    \n    \/\/ 按 <h2> 或 <div class=\"dplayer\"> 切分页面，把标题和链接一一对应\n    var blocks = resultStr.split(\/(?=<h2>|<div\\s+class=\"dplayer\")\/i);\n    var currentTitle = title;\n    var items = [];\n    var count = 1;\n\n    for (var i = 0; i < blocks.length; i++) {\n        var block = blocks[i];\n        \n        \/\/ 如果这个区块是 h2，说明遇到了新标题\n        var h2m = block.match(\/<h2[^>]*>([\\s\\S]*?)<\\\/h2>\/i);\n        if (h2m) {\n            currentTitle = h2m[1].replace(\/<[^>]+>\/g, '').trim();\n            continue;\n        }\n        \n        \/\/ 如果这个区块是 dplayer，说明遇到了视频，去里面抠直链\n        if (block.indexOf('dplayer') !== -1 || block.indexOf('.m3u8') !== -1) {\n            var urls = getM3u8(block);\n            if (urls.length > 0) {\n                var displayTitle = currentTitle;\n                \/\/ 如果标题没变（比如一直没有h2），就自动加个序号\n                if (displayTitle === title && items.length > 0) {\n                    displayTitle = title + \" (P\" + count + \")\";\n                }\n                items.push({ title: displayTitle, href: '', urls: [urls[0]], loaded: true });\n                count++;\n                currentTitle = title; \/\/ 重置，准备匹配下一个 h2\n            }\n        }\n    }\n\n    \/\/ 兜底逻辑：如果上面按块切分失败了，直接提取所有链接\n    if (items.length === 0) {\n        var fallbackUrls = getM3u8(resultStr);\n        items = fallbackUrls.map((u, i) => {\n            return { title: title + \" (P\" + (i+1) + \")\", href: '', urls: [u], loaded: true };\n        });\n    }\n    \n    data = items;\n}\n\nvar dataJson = JSON.stringify(data).replace(\/<\\\/\/g, '<\\\\\/');\n\n`<html>\n    <head>\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n        <script src=\"${js}\"><\\\/script>\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                text-align: center;\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                overflow-wrap: break-word;\n                word-wrap: break-word;\n            }\n            .nav-container {\n                display: flex;\n                justify-content: space-between;\n                align-items: center;\n                padding: 15px 20px;\n                background: #f5f5f5;\n                border-top: 1px solid #ddd;\n                min-width: 320px;\n                box-sizing: border-box;\n            }\n            .nav-button {\n                padding: 10px 20px;\n                background: #007bff;\n                color: white;\n                border: none;\n                border-radius: 5px;\n                cursor: pointer;\n                font-size: 14px;\n                white-space: nowrap;\n                min-width: 80px;\n                text-align: center;\n            }\n            .nav-button:disabled {\n                background: #6c757d !important;\n                cursor: not-allowed;\n            }\n            .page-select {\n                padding: 10px 15px;\n                border: 1px solid #ddd;\n                border-radius: 5px;\n                font-size: 14px;\n                background: white;\n                min-width: 120px;\n            }\n            .video-info {\n                text-align: center;\n                padding: 10px;\n                background: #f8f9fa;\n                border-bottom: 1px solid #ddd;\n                font-size: 18px;\n                color: #666;\n            }\n        <\/style>\n    <\/head>\n    <body>\n        <div class=\"container\">\n            <h3>当前播放: 第<span id=\"currentVideo\">1<\/span>集 \/ 共${data.length}集<\/h3>\n            <div class=\"video-container\">\n                <video controls autoplay name=\"media\" id=\"videoPlayer\">\n                    <source src=\"${data[0] && data[0].urls && data[0].urls[0] ? data[0].urls[0] : ''}\" type=\"application\/x-mpegURL\">\n                <\/video>\n            <\/div>\n            <div class=\"nav-container\">\n                <button class=\"nav-button\" id=\"prevBtn\" onclick=\"changeVideo(-1)\">上一集<\/button>\n                <select class=\"page-select\" id=\"pageSelect\"><\/select>\n                <button class=\"nav-button\" id=\"nextBtn\" onclick=\"changeVideo(1)\">下一集<\/button>\n            <\/div>\n            <div class=\"info-container\">\n                <div class=\"video-info\" id=\"videoTitle\"><\/div>\n            <\/div>\n        <\/div>\n\n        <script>\n            var videoData = ${dataJson};\n            var currentVideoIndex = 0;\n            var currentUrlIdx = 0;\n            var hls = null;\n\n            var video = document.getElementById('videoPlayer');\n            var prevBtn = document.getElementById('prevBtn');\n            var nextBtn = document.getElementById('nextBtn');\n            var pageSelect = document.getElementById('pageSelect');\n            var currentVideoSpan = document.getElementById('currentVideo');\n            var videoTitle = document.getElementById('videoTitle');\n\n            function tryNextSource() {\n                var item = videoData[currentVideoIndex];\n                var list = (item && item.urls) || [];\n                currentUrlIdx++;\n                if (currentUrlIdx >= list.length) {\n                    videoTitle.textContent = ((item && item.title) || '') + ' [所有地址失败]';\n                    return;\n                }\n                if (hls) hls.loadSource(list[currentUrlIdx]);\n                else { video.src = list[currentUrlIdx]; video.load(); }\n                setTimeout(function () { video.play().catch(function () {}); }, 120);\n            }\n\n            function playFirst() {\n                var item = videoData[currentVideoIndex];\n                if (!item || !item.urls || item.urls.length === 0) {\n                    videoTitle.textContent = ((item && item.title) || '') + ' [无地址]';\n                    return;\n                }\n                currentUrlIdx = 0;\n                videoTitle.textContent = item.title || '';\n                if (hls) hls.loadSource(item.urls[0]);\n                else { video.src = item.urls[0]; video.load(); }\n                setTimeout(function () { video.play().catch(function () {}); }, 120);\n            }\n\n            try {\n                if (typeof Hls !== 'undefined' && Hls.isSupported()) {\n                    video.innerHTML = ''; \n                    hls = new Hls();\n                    hls.attachMedia(video);\n                    hls.on(Hls.Events.MANIFEST_PARSED, function () {\n                        video.play().catch(function () {});\n                    });\n                    hls.on(Hls.Events.ERROR, function (e, d) {\n                        if (d && d.fatal) tryNextSource();\n                    });\n                }\n            } catch (e) {}\n\n            function generateSelectOptions() {\n                var html = '';\n                for (var i = 0; i < videoData.length; i++) {\n                    html += '<option value=\"' + i + '\">' + (i+1) + '. ' + (videoData[i].title || '') + '<\/option>';\n                }\n                pageSelect.innerHTML = html;\n            }\n\n            function updateButtons() {\n                var isFirst = currentVideoIndex === 0;\n                var isLast = currentVideoIndex === videoData.length - 1;\n                if (prevBtn) {\n                    prevBtn.disabled = isFirst;\n                    prevBtn.style.background = isFirst ? '#555' : '#007bff';\n                    prevBtn.style.cursor = isFirst ? 'not-allowed' : 'pointer';\n                }\n                if (nextBtn) {\n                    nextBtn.disabled = isLast;\n                    nextBtn.style.background = isLast ? '#555' : '#007bff';\n                    nextBtn.style.cursor = isLast ? 'not-allowed' : 'pointer';\n                }\n                if (pageSelect) pageSelect.value = String(currentVideoIndex);\n                if (currentVideoSpan) currentVideoSpan.textContent = String(currentVideoIndex + 1);\n                var cur = videoData[currentVideoIndex];\n                if (videoTitle) videoTitle.textContent = (cur && cur.title) || '';\n            }\n\n            function loadItem(index, cb) {\n                var item = videoData[index];\n                if (!item) { cb(); return; }\n                if (item.loaded || !item.href) { cb(); return; }\n                if (item._loading) return;\n                item._loading = true;\n\n                var finish = function (html) {\n                    item._loading = false;\n                    item.loaded = true;\n                    var urls = extractM3u8(html || '');\n                    if (urls.length === 0) {\n                        item.href = '';\n                        item.urls = [];\n                        cb();\n                        return;\n                    }\n                    if (urls.length === 1) {\n                        item.urls = urls;\n                        item.href = '';\n                        cb();\n                        return;\n                    }\n                    var baseTitle = item.title;\n                    var newItems = urls.map(function (u, j) {\n                        return {\n                            title: baseTitle + \" (线路\" + (j+1) + \")\",\n                            href: '',\n                            urls: [u],\n                            loaded: true\n                        };\n                    });\n                    Array.prototype.splice.apply(videoData, [index, 1].concat(newItems));\n                    generateSelectOptions();\n                    cb();\n                };\n\n                var done = false;\n                try {\n                    if (typeof java !== 'undefined' && typeof java.ajax === 'function') {\n                        var html = String(java.ajax(item.href) || '');\n                        finish(html);\n                        done = true;\n                    }\n                } catch (e) {}\n                if (!done) {\n                    fetch(item.href)\n                        .then(function (r) { return r.text(); })\n                        .then(function (h) { finish(h); })\n                        .catch(function () { finish(''); });\n                }\n            }\n\n            function switchToVideo(index) {\n                if (index < 0 || index >= videoData.length) return;\n                loadItem(index, function () {\n                    currentVideoIndex = index;\n                    updateButtons();\n                    playFirst();\n                });\n            }\n\n            function changeVideo(direction) { switchToVideo(currentVideoIndex + direction); }\n            function selectVideo(index) { switchToVideo(parseInt(index, 10)); }\n\n            try {\n                generateSelectOptions();\n                updateButtons();\n                pageSelect.addEventListener('change', function () { selectVideo(this.value); });\n                if (videoData.length > 0) playFirst();\n            } catch(e) {}\n\n           \n        <\\\/script>\n    <\/body>\n<\/html>`","ruleImage":"@js:\nvar text = java.getString('script@html');\nvar match = text.match(\/loadBannerDirect\\('([^']+)'\/);\nvar img = match ? match[1] : '';\nimg;","ruleLink":"a.0@href","ruleNextPage":"text.下一页@href","rulePubDate":"{{@@.wraps@text}}{{@@.post-card-info span@text##\\n}}","ruleTitle":"class.post-card-title@text","searchUrl":"\/search\/{{key}}\/","showWebLog":false,"singleUrl":false,"sortUrl":"今日事件::\/category\/mrxl\/\n吃瓜热搜::\/category\/mldjh\/\nai短剧::\/category\/aifl\/\n每日大赛::\/category\/jchj\/\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\/whzq\/\n欧美系列::\/category\/omxl\/\n日韩系列::\/category\/rhxl\/\n户外野外::\/category\/hwyw\/\n调教受虐::\/category\/tjsn\/\n搜索::\/search\/{{source.getVariable()}}\/{{page}}\/","sourceComment":"https:\/\/mlgc01.co\/","sourceGroup":"临时2","sourceIcon":"https:\/\/annual.bjdbvvkh.cc\/favicon.ico","sourceName":"91大事件🥝","sourceUrl":"https:\/\/apply.cdcsygol.cc\/","type":0}]