含羞草

含羞草-解析脚本,永久导航http://www.Fi11.app 中转地址:http://www.pmeaqve.cn 遇到播放地址为旧播放地址或者无反应,请自行多刷新几次当前页面,重新播放即可

// ==UserScript==
// @name         含羞草
// @namespace    http://tampermonkey.net/
// @version      2.2.1
// @description  含羞草-解析脚本,永久导航http://www.Fi11.app 中转地址:http://www.pmeaqve.cn    遇到播放地址为旧播放地址或者无反应,请自行多刷新几次当前页面,重新播放即可
// @author       院长
// @match        *://*/play/video/*
// @match        *://*/live/*
// @match        *://h5.*.com/home
// @match        *://h5.*.cn/home
// @match        *://www.*.com/home
// @match        *://www.*.cn/home
// @match        *://h5.*.com/play/video/*
// @match        *://h5.*.cn/play/video/*
// @match        *://www.*.com/play/video/*
// @match        *://www.*.cn/play/video/*
// @include      /^.*?://.*?\.fi.*?\.com.*?$/
// @include      /^.*?://.*?\.hx.*?\.com.*?$/
// @include      /^.*?://.*?/play/video.*?$/
// @include      /^.*?://(www|h5)\..*?\.com/play/video/.*?$/
// @include      /^.*?://(www|h5)\..*?\.cn/play/video/.*?$/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=3kjs.com
// @grant        none
// @require      https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/dplayer/1.26.0/DPlayer.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/hls.js/1.1.5/hls.min.js
// @run-at       document-end
// ==/UserScript==

//中转地址:http://www.zhongyouchuanmei.xyz
//含羞草永久导航:http://www.Fi11.tv http://fi11.com http://fi11.cn http://www.Fi11.live http://www.fi11av.com
//打开永久导航中的最新网址即可,若是脚本框架需要匹配域名,自行将导航中的最新网址填上即可
//遇到播放地址为旧播放地址或者无反应,请自行刷新当前页面,重新播放即可


/**********************************/

/*
含羞草-解析脚本
参考来源https://yaohuo.me/bbs-1210512.html

实现游客无限试用,无限获取真实播放地址

已兼容手机和电脑

*/
/**********************************/




// 权限认证标识
const TOKEN = 'hxc_1.0.0_token';
// 服务地址
//let baseUrl = location.origin;
let baseUrl = "https://ap988.hydzswyxgs.com";
// 视频试看地址
//const PRE_URL = baseUrl + '/api/videos/getPreUrl';
const PRE_URL = baseUrl + '/videos/getPreUrl';
// 手机免费视频地址
const PRE_URL_V2 = baseUrl + '/videos/v2/getUrl';
// 用户注册地址
//const REG_URL = baseUrl + '/api/login/userReg';
const REG_URL = baseUrl + '/login/userReg';
//获取cid地址
//const DETAIL_URL = baseUrl + '/api/gather/getDetail';
const DETAIL_URL = baseUrl + '/gather/getDetail';
var videoUrl = "";




// 参数加密
function Encrypt(word) {
    let keyStr = 'B77A9FF7F323B5404902102257503C2F';
    const key = CryptoJS.enc.Utf8.parse(keyStr);
    const iv = CryptoJS.enc.Utf8.parse(keyStr);
    const srcs = CryptoJS.enc.Utf8.parse(word);
    const encrypted = CryptoJS.AES.encrypt(srcs, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}

// 请求封装
const fetchData = async (url, body) => {
    const Z = new Date;
    //console.log("服务器系统时间戳",parseInt(Z.getTime() / 1e3) + Z.getTimezoneOffset() * 60)
    return fetch(url, {
        method: 'post',
        body: JSON.stringify({
            endata: Encrypt(JSON.stringify(body)),
            ents:Encrypt(parseInt(Z.getTime() / 1e3) + Z.getTimezoneOffset() * 60),
        }),
        headers: {
            // 携带认证头
            auth: localStorage.getItem(TOKEN)?.replace(/"/g, ''),
            'Content-Type': 'application/json'
        }
    });
};






// 去除限制
const setValue = async () => {
    let isDetail = location.href.includes('play/video');
    if (isDetail) {
        //判断是h5还是电脑,或者是合集视频
        let videoId = location.href.match(/.+\/h5\..+\/play\/video\/(\d+)\/.+/)||location.href.match(/.+\/www\..+\/play\/video\/(\d+)\/.+/);
        if(!videoId){
            videoId = location.href.match(/.+\/play\/video\/(\d+)/)[1];
            //电脑
            //console.log("电脑")
            var preInfo = localStorage.getItem("preInfo");
            if(preInfo){
                preInfo = JSON.parse(preInfo)
                preInfo.count = 0;
                preInfo = JSON.stringify(preInfo)
                localStorage.setItem("preInfo", preInfo);
            }

            //await setElement("pc",videoId);
            //console.log("最后的视频url:" + videoUrl)

            videoId = getVideoId()
            //用于判定当前页面的videoId是否变化
            if (window.videoId == videoId) {
                return
            }
            await pc()
        }else{
            //手机
            //console.log(`-----------判断是手机:${videoId}`);
            let isCid = location.href.match(/.+\/h5\..+\/play\/video\/(\d+)\/1?videoId=.+/)||location.href.match(/.+\/www\..+\/play\/video\/(\d+)\/1?videoId=.+/);
            videoId = videoId[1];
            //合集视频
            if(isCid){
                //console.log(`-----------判断是isCid:${isCid}`);
                let url_list = isCid[0].split('1?videoId=');
                //带了videoId=后缀
                if(url_list.length>1){
                    videoId = url_list[1];
                    //console.log(`-----------videoId:${videoId}`);
                }else{
                    //console.log(`-----------isCid:${videoId}`);
                    videoId = await isListId(isCid[1]);
                }
            }
            //console.log(videoId)
            var tryPlayNum = localStorage.getItem("tryPlayNum");
            if(tryPlayNum){
                tryPlayNum = JSON.parse(tryPlayNum)
                tryPlayNum.num = 0;
                tryPlayNum = JSON.stringify(tryPlayNum)
                localStorage.setItem("tryPlayNum", tryPlayNum);
            }
            //await setElement("mobile",videoId);
            //新增判断合集
            if (!(window.location.href.endsWith("0") || window.location.href.endsWith("1")|| location.href.match(/.+1?videoId=/))) {
                return
            }
            //console.log("执行到这来了========================")
            videoId = await getVideoId();
            if (window.videoId == videoId) {
                return
            }
            //console.log("执行手机操作========================")
            await mobile()
        }

        //console.log("最后的视频ID:" + videoId);
        var videoId_File = localStorage.getItem("videoId");
        //console.log("===========================")
        if(videoId_File && videoId_File === videoId){
            //console.log("----------------------------")
            return
        }
        localStorage.setItem("videoId", videoId);
    }


}


function importJS(src) {
    let script = document.createElement('script');
    script.src = src;
    document.head.appendChild(script);
}

//导包
function importLib() {
    importJS("https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/crypto-js.min.js")
    importJS("https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js")
    importJS("https://cdn.bootcdn.net/ajax/libs/dplayer/1.26.0/DPlayer.min.js")
    importJS("https://cdn.bootcdn.net/ajax/libs/hls.js/1.1.5/hls.min.js")
}

//判断是否为合集,返回第一集
async function isListId(cid){
     let json = await fetchData(DETAIL_URL, {
        gatherId: Number(cid)
    }).then(response => {
        return response.json();
    });
    return json.data.info.videos[0].id;
}


//获取视频id
async function getVideoId() {
    //console.log("匹配视频id")
    let url = window.location.href;
    let url_list = url.split('0?cid=');
    let videoId = 0;
    if(url_list.length<2){
        //手机模式,普通视频
        if (url.endsWith("0")) {
            let urlSplited = url.split("play/video")
            urlSplited = urlSplited[1].split("/")
            videoId = urlSplited[1]
            //console.log("匹配普通视频id:"+videoId)
            return parseInt(videoId);
        }
        //匹配手机模式合集
        if (url.endsWith("/1")) {
            let urlSplited = url.split("play/video")
            urlSplited = urlSplited[1].split("/")
            //console.log("匹配手机模式合集cid:"+urlSplited[1])
            videoId = await isListId(urlSplited[1])
            //console.log("videoId:"+videoId)
            return parseInt(videoId);
        }
        if(url.match(/.+1?videoId=/)){
            videoId = url.split('1?videoId=')[1];
            return parseInt(videoId);
        }
        //通用视频
        let urlSplited = url.split("/");
        videoId = urlSplited[urlSplited.length - 1];
    }else{
        //电脑模式合集
        videoId = await isListId(url_list[1])
        //console.log("电脑模式合集cid:"+videoId)
    }

    return parseInt(videoId);
}


//获取视频链接(区分手机和电脑)
async function getVideoUrl(type,videoId){
    //很重要,区分是否当前页的id
    window.videoId = videoId
    //删除参数
    var waibubofan = "#waibubofan";
    var shipindizhi = "#shipindizhi";
    var delete_waibubofan = document.querySelectorAll(waibubofan);
    var delete_shipindizhi = document.querySelectorAll(shipindizhi);
    //先删除按键
    if(delete_waibubofan){
        for(let i=0;i<delete_waibubofan.length;i++){
            //console.log(`删除外部播放按键:${i}`)
            delete_waibubofan[i].remove()
        }
    }
    if(delete_shipindizhi){
        for(let i=0;i<delete_shipindizhi.length;i++){
            //console.log(`删除视频地址按键:${i}`)
            delete_shipindizhi[i].remove()
        }
    }

    //设置按钮
    let selectorParam = ".el-divider.el-divider--horizontal";
    if(type == "mobile"){
        selectorParam = ".tendency-row";

    }
    let json =await fetchData(PRE_URL, {
        videoId: Number(videoId)
    }).then(response => {
        return response.json();
    });
    const isSuccess = !!json.data.url;
    let el = document.querySelector(selectorParam);
    let a = document.createElement('a');
    a.style =
        'display:block;font-size:18px;padding:12px;color:#1890ff;';
    a.text = isSuccess ? '视频地址' : '获取失败';
    a.target = "_blank";
    a.id = "shipindizhi";
    if (isSuccess) {
        let parseUrl = json.data.url.replace(/start=\d+&end=\d+/, '');
        a.href = parseUrl;
        // 获取ts切片
        let m3u8Str = await fetch(parseUrl).then(async res => {
            let m3u8Str = await res.text();
            return m3u8Str
        });
        // 提取第一条记录
        let tsUrl = m3u8Str.split('\n').find(item => {
            return /^[^#]/.test(item);
        });
        // 拼接
        const linkUrl =
              'https://m3u8play.com/?play=' +
              new URL(parseUrl).origin +
              tsUrl;
        videoUrl = new URL(parseUrl).origin + tsUrl;
        let external = document.createElement('a');
        external.style =
            'display:block;font-size:18px;padding:12px;color:#1890ff;';
        external.text = '外部播放';
        external.href = linkUrl;
        external.target = "_blank";
        external.id = "waibubofan";
        if(el){
            el.parentNode.insertBefore(external, el);
        }
        
    }else{
        //获取失败直接返回
        return;
    }
    if(el){
        el.parentNode.insertBefore(a, el);
    }

    
    return videoUrl;
}


//电脑播放
function play(playerUrl, pic, container, playType) {
    container.style.zIndex = 99999
    var videoObject = {
        container: '#v_prism', //容器的ID或className
        // live: true,//指定为直播
        //seek: 'cookie',//指定跳转到cookie记录的时间,使用该属性必需配置属性cookie
        cookie: 'abcdefg',//cookie名称,请在同一域中保持唯一
        plug: 'hls.js',//使用hls.js插件播放m3u8
        video: playerUrl//视频地址
    }
    window.ck = new ckplayer(videoObject);
    //window.ck.volume(0.5);//修改音量为0.5
    window.ck.volume(1);
    window.ck.play()
}

//手机播放
function mobilePlay(playerUrl, pic, container, playType) {
    container.style.zIndex = 99999
    window.dp = new DPlayer({
        container: container,                                              // 可选,player元素
        autoplay: false,                                                   // 可选,自动播放视频,不支持移动浏览器
        theme: '#FADFA3',                                                  // 可选,主题颜色,默认: #b7daff
        loop: true,                                                        // 可选,循环播放音乐,默认:true
        lang: 'zh',                                                        // 可选,语言,`zh'用于中文,`en'用于英语,默认:Navigator language
        screenshot: true,                                                  // 可选,启用截图功能,默认值:false,注意:如果设置为true,视频和视频截图必须启用跨域
        hotkey: true,                                                      // 可选,绑定热键,包括左右键和空格,默认值:true
        preload: 'auto',                                                   // 可选,预加载的方式可以是'none''metadata''auto',默认值:'auto'
        video: {                                                           // 必需,视频信息
            url: playerUrl,                                                // 必填,视频网址
            pic: pic,                                                      // 可选,视频截图
            thumbnails: pic
        }
    });
}


async function pc() {
     if (window.location.href.endsWith("home")) {
        return
    }
    let videoId = await getVideoId();
    //let videoUrl = await getVideoUrl(videoId)
    let videoUrl = await getVideoUrl("pc",videoId)
    if (videoUrl == null) {
        return
    }
    let pic = document.querySelector(".el-image.overflow-hidden > img")
    if (pic) {
        pic = pic.getAttribute("src")
    }
    let container = document.querySelector("#v_prism")
    let playType = 'live'
    let elem = document.querySelector(".vip-mask")
    if (elem) {
            elem.remove()
    }
    
    elem = document.querySelector(".el-image.overflow-hidden")
    if (elem) {
        elem.remove()
    }
    elem = document.querySelector(".top-0.left-0.w-full.h-full.overflow-hidden")
    if (elem) {
        elem.remove()
    }
    elem = document.querySelector(".vip-mask > div")
    if (elem) {
        elem.remove()
    }

    elem = document.querySelector(".absolute.bg-overlay")
    if (elem) {
        elem.remove()
    }
    //console.log(`-----------执行播放电脑视频事件-------------`);
    //console.log(`-----------视频地址:${videoUrl}`);
    play(videoUrl, pic, container, playType)
    //await setElement("pc",videoId);
}

async function mobile() {
    if (!(window.location.href.endsWith("0") || window.location.href.endsWith("1")|| location.href.match(/.+1?videoId=/))) {
        return
    }
    let videoId = await getVideoId()
    //let videoUrl = await getVideoUrl(videoId)
    let videoUrl = await getVideoUrl("mobile",videoId)
    console.log(`-----------视频地址:${videoUrl}`);
    if (videoUrl == null) {
        return
    }

    let pic = document.querySelector(".pub-video-poster")
    if (pic) {
        pic = pic.getAttribute("src")
    }
    //container = document.querySelector(".van-sticky")
    let container = document.querySelector("#video1")
    let playType = 'live'
    //document.querySelector(".try-detail-video").remove()
    mobilePlay(videoUrl, pic, container, playType)
    //await setElement("mobile",videoId);
}


async function main() {
    //console.log(`-----------启动-------------`);
    /**********************************/
    // hook: 拦截路由地址变化
    const _historyWrap = function (type) {
        const orig = history[type];
        const e = new Event(type);
        return function () {
            const rv = orig.apply(this, arguments);
            e.arguments = arguments;
            window.dispatchEvent(e);
            return rv;
        };
    };
    // 监听路由操作
    ['pushState', 'replaceState'].forEach(method => {
        history[method] = _historyWrap(method);
        window.addEventListener(method, () => {
            //console.log('当前URL为:', document.location.href);
            setValue();
        });
    });

    window.addEventListener('popstate', function(event) {
        //console.log('当前URL为:', document.location.href);
        //setValue();
    });
    /**********************************/
    importLib()
}


main()

window.onload = function() {
     let elem = document.querySelector(".vip-mask")
    if (elem) {
            elem.remove()
    }
 };