UXX
https://www.uxxtv.com/
SH869 (2786)2天前
协助者:阿鬼
酷安by:阿鬼不吃鱼
qq频道(阅读|一程书友会)by:꧁阿鬼꧂—不是大佬不会js
关键字:阿鬼
{ "bookSourceComment": "\/\/❗免责声明: \n本工具\/代码\/内容仅供学习交流使用,严禁用于任何非法用途。使用者应严格遵守所在国家或地区的法律法规,任何因滥用或违规使用导致的后果均与开发者\/提供者无关,责任自负❗", "bookSourceGroup": "🔞", "bookSourceName": "UXX", "bookSourceType": 0, "bookSourceUrl": "https:\/\/www.uxxtv.com\/", "customOrder": 16, "enabled": false, "enabledCookieJar": true, "enabledExplore": false, "exploreUrl": "全部视频::\/type\/1\/{{page}}.html\nvip视频::\/type\/5\/{{page}}.html\n全部小说::\/type\/2\/{{page}}.html\n全部有声::\/type\/3\/{{page}}.html\n全部漫画::\/type\/4\/{{page}}.html", "header": "@js:\nJSON.stringify({\n 'User-Agent': java.getWebViewUA(),\n 'sec-ch-ua-platform': \"\\\"Android\\\"\",\n 'origin': baseUrl,\n 'x-requested-with': \"cn.mujiankeji.mbrowser\",\n 'Referer': baseUrl,\n 'Accept-language': \"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\"\n})", "lastUpdateTime": "1756361946125", "loginUi": "[\n {\n \t\"name\": \"账号\", \n \t\"type\": \"text\"\n \t},\n {\n \t\"name\": \"密码\", \n \"type\": \"text\"\n },\n {\n \t\"name\": \"签到\", \n \"type\": \"button\",\n \"action\": \"signIn()\"\n \t},\n \t{\n \t\"name\": \"用户信息\", \n \"type\": \"button\",\n \"action\": \"getUserInfo()\"\n \t}\n \t\n]", "loginUrl": "function login() {\n var user = source.getLoginInfoMap();\n var loginParams = \"name=\" + encodeURIComponent(user.get(\"账号\")) + \"&pass=\" + encodeURIComponent(user.get(\"密码\"));\n var headers = {\"Content-Type\": \"application\/x-www-form-urlencoded\", \"token\": \"\"};\n \n var req = java.post(baseUrl + \"user\/login\/save\", loginParams, headers);\n var body = JSON.parse(req.body());\n \n if (body.result === \"success\") {\n var cs = Array.from(req.cookies(), function(pair) { return pair[0] + \"=\" + pair[1]; }).join(\";\");\n source.setVariable(cs);\n return source.putLoginHeader(JSON.stringify({Cookie: cs}));\n } else {\n java.log(\"登录失败,响应内容: \" + response.body());\n throw Error(\"登录失败\");\n }\n}\n\nfunction signIn() {\n var log = (msg) => {\n \tif(msg==null) return;\n java.longToast(msg);\n return java.log(msg);\n };\n var qd = java.ajax(baseUrl + '\/?d=user&c=ajax&m=qd');\n var data = JSON.parse(qd), \n zt = data.zt, str = data.str;\n \/\/log(qd)\n if(zt==\"ok\"){\n return log(\"签到成功!\");\n }else if(zt==\"yes\"){\n return log(\"今日已签到\");\n }else if(zt==\"no\"){\n log(\"签到失败!\\n未登录或\" + str);\n }\n}\n\nfunction getUserInfo() {\n var html = java.ajax(baseUrl + \"\/?d=user\");\n \n var nickMatch = html.match(\/<div class=\"account_box\">\\s*<div>([^<]+)<\\\/div>\/);\n var levelMatch = html.match(\/<p>([^<]+会员)<\\\/p>\/);\n var coinMatch = html.match(\/<p>金币:(\\d+)个<\\\/p>\/);\n\n var nick = nickMatch ? nickMatch[1].trim() : \"未知\";\n var level = levelMatch ? levelMatch[1].trim() : \"未知\";\n var coins = coinMatch ? coinMatch[1].trim() : \"0\";\n\n java.longToast(`昵称:${nick};会员等级:${level};金币总数:${coins}`);\n}", "respondTime": 180000, "ruleBookInfo": { "author": ".item.-2@text", "coverUrl": ".cover.0@img@src", "intro": ".brief@text", "kind": ".item.-3@text&&.update_state@text&&.score_box@text&&.props_box@text", "lastChapter": ".item.-4 @text##最新章节:", "name": "h1@text" }, "ruleContent": { "content": "@js:\nif (\/m3u8\/.test(result)) { \n \/\/ 自动购买程序\n user = java.ajax(`${source.key}?d=user&c=ajax&m=ulog`);\n let id = String(baseUrl).match(\/play\\\/(\\d+)\\\/\/)?.[1] || null;\n url = `${source.key}?c=play&m=buy&id=${id}`;\n buy = java.ajax(url);\n last = java.ajax(`${source.key}?c=play&m=bfq&id=${id}&zu=0&ji=0`);\n \n \/\/ 处理简介文本(换行优化)\n let intro = (`{{book.intro}}`).replace(\/\\s+\/g, '\\n');\n\n \/\/ 获取视频直链\n videoUrl = String(java.getString('#mui-player@src', result)) || String(java.getString('iframe@src', java.ajax(book.origin+java.getString(\".player script@src\", result)))).replace(\/\\\\\\\"\/g, \"\");\n \n \/\/ 构建播放器HTML\n function buildPlayerHtml(videoSource, fallbackIframe = '') {\n return `\n <html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n <title>{{book.name}}<\/title>\n <style>\n body {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #333;\n }\n .header {\n padding: 15px;\n background: linear-gradient(135deg, #6e48aa, #9d50bb);\n color: white;\n text-align: center;\n font-size: 1.2em;\n box-shadow: 0 2px 5px rgba(0,0,0,0.1);\n }\n .video-container {\n width: 100%;\n background: #000;\n position: relative;\n min-height: 300px;\n }\n video {\n width: 100%;\n height: 50%;\n display: block;\n }\n .info-panel {\n padding: 15px;\n background: white;\n margin: 10px;\n border-radius: 10px;\n box-shadow: 0 2px 10px rgba(0,0,0,0.05);\n }\n .info-item {\n margin: 10px 0;\n font-size: 0.95em;\n }\n .info-label {\n font-weight: bold;\n color: #6e48aa;\n }\n .seek-feedback {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: rgba(0,0,0,0.7);\n color: white;\n padding: 10px 20px;\n border-radius: 20px;\n font-size: 16px;\n display: none;\n z-index: 100;\n }\n .fallback-notice {\n padding: 10px;\n background: #ffeb3b;\n color: #333;\n text-align: center;\n font-size: 14px;\n }\n <\/style>\n <\/head>\n <body>\n <div class=\"header\">{{book.name}}<\/div>\n <div class=\"seek-feedback\" id=\"seekFeedback\"><\/div>\n <div class=\"video-container\">\n ${videoSource}\n ${fallbackIframe ? `<div class=\"fallback-notice\">视频加载失败,已切换备用播放器<\/div>` : ''}\n ${fallbackIframe}\n <\/div>\n <div class=\"info-panel\">\n <div class=\"info-item\">\n <span class=\"info-label\">👤 作者:<\/span>{{book.author}}\n <\/div>\n <div class=\"info-item\">\n <span class=\"info-label\">🔖 分类:<\/span>{{book.kind}}\n <\/div>\n <div class=\"info-item\">\n <span class=\"info-label\">📝 简介:<\/span>${intro}\n <\/div>\n <\/div>\n\n <script>\n \/\/ 检测视频是否可播放\n function checkVideoPlayable() {\n const video = document.getElementById('video');\n if (!video) return true;\n \n return new Promise((resolve) => {\n video.addEventListener('error', () => {\n resolve(false);\n });\n \n \/\/ 设置超时检测\n setTimeout(() => {\n if (video.readyState === 0) {\n resolve(false);\n } else {\n resolve(true);\n }\n }, 3000);\n });\n }\n \n \/\/ 初始化播放器\n async function initPlayer() {\n const video = document.getElementById('video');\n const fallbackIframe = document.getElementById('fallbackIframe');\n \n if (video) {\n const canPlay = await checkVideoPlayable();\n if (!canPlay && fallbackIframe) {\n video.style.display = 'none';\n fallbackIframe.style.display = 'block';\n }\n }\n \n \/\/ 添加控制逻辑\n setupVideoControls();\n }\n \n \/\/ 视频控制逻辑\n function setupVideoControls() {\n const video = document.getElementById('video');\n if (!video) return;\n \n const seekFeedback = document.getElementById('seekFeedback');\n let touchStartX = 0;\n let touchStartTime = 0;\n let isSeeking = false;\n let seekTimeout;\n\n \/\/ 长按滑动快进(左滑后退,右滑前进)\n video.addEventListener('touchstart', (e) => {\n if (e.touches.length === 1) {\n touchStartX = e.touches[0].clientX;\n touchStartTime = video.currentTime;\n isSeeking = true;\n }\n });\n\n video.addEventListener('touchmove', (e) => {\n if (!isSeeking || !video.duration || e.touches.length !== 1) return;\n \n const touchX = e.touches[0].clientX;\n const deltaX = touchX - touchStartX;\n const seekDistance = deltaX \/ window.innerWidth;\n const seekAmount = seekDistance * 30;\n \n let newTime = touchStartTime + seekAmount;\n newTime = Math.max(0, Math.min(newTime, video.duration));\n video.currentTime = newTime;\n \n seekFeedback.textContent = (seekAmount > 0 ? '⏩ +' : '⏪ ') + \n Math.abs(seekAmount).toFixed(1) + 's';\n seekFeedback.style.display = 'block';\n \n clearTimeout(seekTimeout);\n seekTimeout = setTimeout(() => {\n seekFeedback.style.display = 'none';\n }, 1000);\n \n e.preventDefault();\n });\n\n video.addEventListener('touchend', () => {\n isSeeking = false;\n clearTimeout(seekTimeout);\n setTimeout(() => {\n seekFeedback.style.display = 'none';\n }, 1000);\n });\n\n \/\/ 双击暂停\/播放\n let lastTap = 0;\n video.addEventListener('touchend', (e) => {\n const currentTime = new Date().getTime();\n const tapLength = currentTime - lastTap;\n \n if (tapLength < 300 && tapLength > 0) {\n video.paused ? video.play() : video.pause();\n e.preventDefault();\n }\n lastTap = currentTime;\n });\n }\n \n \/\/ 初始化\n window.addEventListener('DOMContentLoaded', initPlayer);\n <\/script>\n <\/body>\n <\/html>\n `;\n }\n\n \/\/ 构建主播放器和备用播放器\n const mainPlayer = `\n <video id=\"video\" controls poster=\"{{book.coverUrl}}\">\n <source src=\"${videoUrl}\" type=\"video\/mp4\">\n 您的浏览器不支持视频播放\n <\/video>`;\n \n \/\/ 获取备用iframe地址\n const iframeSrc = String(java.getString('iframe@src', java.ajax(book.origin+java.getString(\".player script@src\", result)))).replace(\/\\\\\\\"\/g, \"\");\n const fallbackPlayer = iframeSrc ? `\n <iframe id=\"fallbackIframe\" src=\"${iframeSrc}\" style=\"width:100%; height:100%; min-height:400px; border:none; display:none;\"><\/iframe>\n ` : '';\n \n \/\/ 构建完整HTML\n b64 = java['base64Encode'](buildPlayerHtml(mainPlayer, fallbackPlayer));\n \n \/\/ 在浏览器中打开\n dataUrl = 'data:text\/html;base64,' + b64;\n java['startBrowser'](dataUrl, '{{book.name}}');\n java['toast']('视频加载中...');\n\n \/\/ 返回结果\n '【刷新正文】播放✅\\n🎬 视频已加载\\n🔗 直链: ' + videoUrl + (iframeSrc ? '\\n🔧 备用播放器已准备' : '');\n\n} else if(result.includes('mp3')){\n \/\/ 获取MP3直链\n let mp3Url = java.getString('audio@src');\n \n \/\/ 构建播放页面\n b64 = java['base64Encode'](`\n <html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n <title>{{book.name}}<\/title>\n <style>\n body {\n margin: 0;\n padding: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #333;\n }\n .header {\n padding: 15px;\n background: linear-gradient(135deg, #6e48aa, #9d50bb);\n color: white;\n text-align: center;\n font-size: 1.2em;\n box-shadow: 0 2px 5px rgba(0,0,0,0.1);\n }\n .audio-container {\n width: 100%;\n padding: 20px;\n background: white;\n margin-top: 10px;\n }\n audio {\n width: 100%;\n }\n .info-panel {\n padding: 15px;\n background: white;\n margin: 10px;\n border-radius: 10px;\n box-shadow: 0 2px 10px rgba(0,0,0,0.05);\n }\n .info-item {\n margin: 10px 0;\n font-size: 0.95em;\n }\n .info-label {\n font-weight: bold;\n color: #6e48aa;\n }\n .cover-img {\n width: 100%;\n max-height: 300px;\n object-fit: contain;\n margin-bottom: 15px;\n }\n <\/style>\n <\/head>\n <body>\n <div class=\"header\">{{book.name}}<\/div>\n <div class=\"audio-container\">\n <img src=\"{{book.coverUrl}}\" class=\"cover-img\" onerror=\"this.style.display='none'\">\n <audio controls autoplay>\n <source src=\"${mp3Url}\" type=\"audio\/mpeg\">\n 您的浏览器不支持音频元素\n <\/audio>\n <\/div>\n <div class=\"info-panel\">\n <div class=\"info-item\">\n <span class=\"info-label\">👤 作者:<\/span>{{book.author}}\n <\/div>\n <div class=\"info-item\">\n <span class=\"info-label\">🔖 分类:<\/span>{{book.kind}}\n <\/div>\n <div class=\"info-item\">\n <span class=\"info-label\">📝 简介:<\/span>{{book.intro}}\n <\/div>\n <\/div>\n <\/body>\n <\/html>\n `);\n\n \/\/ 在浏览器中打开\n dataUrl = 'data:text\/html;base64,' + b64;\n java['startBrowser'](dataUrl, '{{book.name}}');\n java['toast']('音频加载中...');\n \n \/\/ 返回结果\n '【刷新正文】播放\\n✅MP3直链:\\n' + mp3Url;\n } else {\n var $ = (e) => java.getElement(e);\n $.get = (link) => java.get(book.origin + link, {Referer:baseUrl}).body();\n let data = eval(src.match(\/\\$.get\\(\"[^\"]+\"\/).toString()+\")\");\n java.htmlFormat(data);\n} ", "imageStyle": "FULL", "replaceRegex": "##(A.*V|有.*声|最.*新|收.*藏|更.*多|永.*久|要.*撸).*com" }, "ruleExplore": { "author": ".author.0@text", "bookList": ".video_li||.audio_li", "bookUrl": "a@href", "coverUrl": ".cover@img@src", "kind": ".view@text&&.state@text", "name": "a@title" }, "ruleSearch": { "author": ".author.0@text", "bookList": ".video_li||.audio_li", "bookUrl": "a@href##.*\/play\/(\\d+)\/\\d+\/\\d+\\.html##\/show\/$1.html###", "coverUrl": ".cover@img@src", "kind": ".view@text&&.state@text", "name": "a@title" }, "ruleToc": { "chapterList": ".menu>a", "chapterName": "text", "chapterUrl": "href" }, "searchUrl": "\/?c=search&wd={{encodeURI(key)}}&sort=addtime&order=desc&page={{page}}", "weight": 0 }