海角社区

目前可以用,可以查看金币钻石视频,需要手动注册登录

Från och med 2024-01-20. Se den senaste versionen.

// ==UserScript==
// @name         海角社区
// @namespace    http://tampermonkey.net/
// @version      6.4
// @description  目前可以用,可以查看金币钻石视频,需要手动注册登录
// @author       xigua0012
// @license      MIT
// @match       https://tools.thatwind.com/tool*
// @match        https://*/post/details*
// @icon         https://hjbc30.top/images/common/project/favicon.ico
// @run-at      document-start
// @grant       unsafeWindow
// @grant        GM_download
// @grant        GM_openInTab
// @grant        GM_xmlhttpRequest
// @grant        GM_xmlhttpRequest
// @connect      *
// @require      https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js
// ==/UserScript==


function pwd() {
    let word = ''
    let a = '48/46/116/115'
    let b = a.split('/')
    for (let c in b) {
        let d = parseInt(b[c])
        let e = String.fromCharCode(d)
        word = word + e
    }
    return word
}

function clearContainer(container) {
    if (container.hasChildNodes()) {
        container.innerHTML = "";
        container.style.border = "";
    }
}
function getContainer() {
    const existContainer = document.querySelector(".big-img-container-c");
    if (!existContainer) {
        const container = document.createElement("div");
        container.className = "big-img-container-c";
        container.style.position = "fixed";
        container.style.top = 0;
        container.style.left = 0;
        container.style.zIndex = 999999;
        container.onclick = function () {
            clearContainer(container);
        };
        document.querySelector("html").appendChild(container);
        return container;
    }
    return existContainer;
}




(function () {
    'use strict';


    /*
    
        if (location.host === "tools.thatwind.com" || location.host === "localhost:3000") {
            alert("sdfdsf")
        }
    */


    let newurl = ""

    let isphone = IsPhone()
    if (isphone) {
        $("body").append(" <div id='myDiv'; style='right: 3px;width: 40px;height: 40px;font-size: 12px;border-radius:50%; bottom: 120px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>打赏脚本</div>");
        $("body").append(" <div id='dmyDiv'; style='right: 3px;width: 40px;height: 40px;font-size: 12px;border-radius:50%; bottom: 160px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>下载</div>");
    }
    else {
        $("body").append(" <div id='myDiv'; style='right: 3px;width: 50px;height: 50px;font-size: 16px;border-radius:50%; bottom: 120px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>打赏脚本</div>");
        $("body").append(" <div id='dmyDiv'; style='right: 3px;width: 50px;height: 50px;font-size: 16px;border-radius:50%; bottom: 170px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>下载</div>");
    }

    var dmyDiv = document.getElementById("dmyDiv"); // 获取到id为"myDiv"的div元素
    dmyDiv.addEventListener('click', function (e) {
        //alert("你点击了DIV!"); // 当点击该div时会触发此函数并显示提示信息
        var currentUrl = window.location.href;
        // 输出当前网址

        let url = "https://tools.thatwind.com/tool/m3u8downloader#m3u8="
        let url2 = "&referer=" + currentUrl + "&filename=%E6%B5%B7%E8%A7%92%E7%A4%BE%E5%8C%BA"
        let url3 = url + newurl + url2
        GM_openInTab(url3, { active: true });
        console.log(url3);
        //window.location.href = url;
        //window.open(url, "_blank");


    });




    var myDiv = document.getElementById("myDiv"); // 获取到id为"myDiv"的div元素
    myDiv.addEventListener('click', function (e) {
        //alert("你点击了DIV!"); // 当点击该div时会触发此函数并显示提示信息
        const container = getContainer();
        const halfWidth = window.innerWidth / 2;
        const halfHeight = window.innerHeight / 2;
        clearContainer(container);


        if (isphone) {
            const containerX = halfWidth - 160;
            const containerY = halfHeight - 140;
            container.style.left = `${containerX}px`;
            container.style.top = `${containerY}px`;
            container.style.border = "1px solid #000";
            const bigImg = e.target.cloneNode();
            container.appendChild(bigImg);
            // 创建img标签并设置src属性为要显示的图片链接
            var img = document.createElement('img');
            img.setAttribute("src", "https://greasyfork.org/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MTI4MDAzLCJwdXIiOiJibG9iX2lkIn19--362fa984de7dac0a445a418359f3b592c792ade4/360%E6%88%AA%E5%9B%BE20240109152050379.jpg?locale=zh-CN");
        }
        else {
            const containerX = halfWidth - 200;
            const containerY = halfHeight - 140;
            container.style.left = `${containerX}px`;
            container.style.top = `${containerY}px`;
            container.style.border = "1px solid #000";
            const bigImg = e.target.cloneNode();
            container.appendChild(bigImg);
            // 创建img标签并设置src属性为要显示的图片链接
            var img = document.createElement('img');
            img.setAttribute("src", "https://greasyfork.org/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MTI3OTQ5LCJwdXIiOiJibG9iX2lkIn19--9723e102c10049b845a51a29b15a9fea2b66f03c/360%E6%88%AA%E5%9B%BE20240108163227692.jpg?locale=zh-CN");

        }


        var bodyElement = document.getElementsByClassName('big-img-container-c')[0];
        bodyElement.appendChild(img);


    });
    function decode(s) {
        return atob(atob(atob(s)));
    }

    function encode(s) {
        return btoa(btoa(btoa(s)));
    }

    function jencode(s) {
        return encode(JSON.stringify(s, `utf-8`));
    }

    function get_real_m3u8_path(url) {
        var request = new XMLHttpRequest();
        request.open('GET', url, false);
        request.send(null);
        if (request.status !== 200) {
            console.log(`解析失败!`);
            return url;
        }
        let ts_path = request.responseText.split('\n')[6];
        let id = ts_path.match(/([\w_]+_?)[\d]+.ts/)[1];
        let rurl = url.replace(/([\w_]+).m3u8/, `${id}.m3u8`);
        return rurl;
    }
    function runAsync(url, send_type, data_ry) {
        console.log("请求开始");
        var p = new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: send_type,
                url: url,
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
                },
                data: data_ry,
                onload: function (response) {
                    console.log("请求成功");
                    //console.log(response.responseText);
                    resolve(response.responseText);
                },
                onerror: function (response) {
                    console.log("请求失败");
                    alert("解析失败,检查脚本是否有更新")
                    reject("请求失败");
                    
                }
            });
        })
        //console.log("p="+p);
        return p;
    }
    function get_user_dict(host, id) {
        var url = `https://${host}.com/api/topic/node/topics?page=1&userId=${id}&type=0`;
        var request = new XMLHttpRequest();
        request.open('GET', url, false);
        request.send(null);
        if (request.status !== 200) {
            console.log(`用户信息解析失败!`);
            return {};
        }
        let p = JSON.parse(request.responseText, `utf-8`).data;
        p = JSON.parse(decode(p), `utf-8`);
        let total = p.page.total;
        let uid = `[banned]`;
        if (`results` in p) {
            uid = p.results[0].user.nickname + ` ` + uid;
        }
        return {
            'isFavorite': false,
            'likeCount': 12,
            'user': {
                'id': parseInt(id),
                'nickname': uid,
                'avatar': '29',
                'description': `hj community`,
                'topicCount': total,
                'videoCount': 0,
                'commentCount': 303,
                'fansCount': 57,
                'favoriteCount': 39,
                'status': 0,
                'sex': 1,
                'vip': 0,
                'vipExpiresTime': '0001-01-01 00:00:00',
                'certified': false,
                'certVideo': false,
                'certProfessor': false,
                'famous': false,
                'forbidden': false,
                'tags': null,
                'role': 0,
                'popularity': 10,
                'diamondConsume': 0,
                'title': { 'id': 0, 'name': '', 'consume': 0, 'consumeEnd': 0, 'icon': '' },
                'friendStatus': false,
                'voiceStatus': false,
                'videoStatus': false,
                'voiceMoneyType': 0,
                'voiceAmount': 0,
                'videoMoneyType': 0,
                'videoAmount': 0,
                'depositMoney': 0
            }
        }
    }

    function destory() {
        document.getElementsByClassName('preview-title')[0].remove()
    }



    function remove_vip(body) {
        body.node.vipLimit = 0;
        let attachments = body.attachments;
        let image_urls = [];
        let video_urls = ``;
        let has_video = -1;
        for (var i = 0; i < attachments.length; i++) {
            var atta = attachments[i];
            if (atta.category === 'images') {
                image_urls.push(`<img src="${atta.remoteUrl}" data-id="${atta.id}"/>`)
            }
            if (atta.category === 'video') {
                has_video = i;
            }
        }
        let images = image_urls.join();
        if (has_video >= 0) {
            let [nbody, v] = replace_m3u8(body, has_video);
            body = nbody;
            video_urls = `<video src="${v.remoteUrl}" data-id="${v.id}"/></video>`
        }
        let content = body.content.replace(/\[[图片视频]+\]?/, ``);
        content = body.content.replace(/此处内容售价.*?您还没有购买,请购买后查看!/, ``);
        content = '<html><head></head><body>' + content + '<br/>' + images + '<br/>' + video_urls + '<br/></body></html>';
        body.content = content;
        return body;
    }
    async function play(url) {
        console.log("url=" + url)
        let isphone = IsPhone()
        let playpos = ''
        if (isphone) {
            //document.querySelector('.sell-btn').remove()
            playpos = '.sell-btn'
            let videoInfo = document.querySelector(playpos)
            videoInfo.innerHTML = '<video id="video" controls autoplay width="100%"></video>'
            var video = document.getElementById('video');
            var hls = new Hls();
            // bind them together
            console.log("11");
            hls.attachMedia(video);
            hls.on(Hls.Events.MEDIA_ATTACHED, function () {
                console.log("video and hls.js are now bound together !");

                hls.loadSource(url);
                hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
                    console.log("manifest loaded, found " + data.levels.length + " quality level");
                });
            });
        }
        else {
            playpos = '.sell-btn'
            window.dp = new DPlayer({
                element: document.querySelector(playpos),
                autoplay: false,
                theme: '#FADFA3',
                loop: true,
                lang: 'zh',
                screenshot: true,
                hotkey: true,
                preload: 'auto',
                video: {
                    url: url,
                    type: 'hls'
                }
            })
        }
    }


    function hasClass(element, className) {
        return element.classList.contains(className);
    }
    async function replace_m3u8(body, has_video) {
        let attachments = body.attachments;
        let vidx = has_video;
        if (vidx < 0) {
            return [body, undefined];
        }
        if (body.sale === null || body.sale.money_type == 0) {
            return [body, attachments[vidx]];
        }
        let url = attachments[vidx].remoteUrl;
        console.log("url", url)


        let res = await fetch("https://hjbdc8.top" + url, {
            method: 'get',
        })
        let m3u8Text = await res.text()


        /*
        hasClass(document.getElementById(app),"loginChange d-flex")
        let _class = document.getElementsByTagName('div')[0].getAttribute('loginChange d-flex'); 
if (_class == null) {
  console.log('不存在class'); 
} else {
  console.log('输出class', _class); 
}

*/

        // HTML结构如下:<div class="myDiv">这是一段文字</div>

        /*
                console.log("div.innerText" + div.innerText); // 输出:"这是一段文字"
                if (div.innerText === "发帖") {
        
                } else {
                    alert("请先登录")
                    return
                }
                */
        var textsent = m3u8Text
        let isphone = IsPhone()
        if (isphone) {
            var div = document.getElementsByClassName("nologin")[0]; // 获取第一个符合条件的元素
            console.log('div=', div);
            if (typeof div === 'undefined') {
                // do something

            } else {
                alert("请先登录-m")
                return
            }

            var i = 1;
            var intervalId = setInterval(function () {
                // 获取需要判断的元素
                let infolist = document.getElementsByClassName('html-box ishide')[0]
                infolist.className = 'html-box';
                let infophone = document.getElementsByClassName('preview-btn')[0]

                if (infophone) {
                    
                    textsent = infophone.innerText + "***" + textsent
                    console.log(textsent);
                    if (textsent.indexOf("IV=") === -1 || textsent.indexOf("分") === -1) {
                        alert("解析失败,请刷新重试")
                        return
                    }
                    fasong(textsent)
                    // 如果元素存在则执行相应的命令
                    console.log("元素已经存在!");
                    clearInterval(intervalId); // 清除定时器
                    // 这里写入你想要执行的命令或者其他操作
                } else {
                    console.log("元素还不存在...");
                }
                i++
                if (i>20) {
                    alert("解析失败,请刷新重试")
                }
            }, 1000);
        }
        else {

            var div = document.getElementsByClassName("navigation_button")[0]; // 获取第一个符合条件的元素

            if (div != null) {
                // 元素存在
            } else {
                alert("请先登录-p")
                return
            }

            var intervalId = setInterval(function () {
                // 获取需要判断的元素
                let info = document.getElementsByClassName('preview-title')[0]
                let videoInfo = info.getElementsByClassName('video-div')[0]
                
    
                if (videoInfo) {
                    textsent = info.innerText + "***" + textsent
                    console.log(textsent);
                    if (textsent.indexOf("IV=") === -1 || textsent.indexOf("分") === -1) {
                        alert("解析失败,请刷新重试")
                        return
                    }
                    fasong(textsent)
                    // 如果元素存在则执行相应的命令
                    console.log("元素已经存在!");
                    clearInterval(intervalId); // 清除定时器
                    // 这里写入你想要执行的命令或者其他操作
                } else {
                    console.log("元素还不存在...");
                }
                i++
                if (i>20) {
                    alert("解析失败,请刷新重试")
                }
            }, 1000);


           
            
        }


    }

    function fasong(textsent) {
        runAsync("http://1.92.71.103/getnmm8", "POST", textsent).then((result) => { return result; }).then(function (result) {
            //console.log(result);
            alert("视频解析成功!\n 用的好的话,希望大家多打赏,达不到预期我只好收费卖去了,没精力用爱发电。今天看了最近的打赏,有点心累,每天那么大量的使用,连500次1元都没有,里面付费视频可是至少好几块一个!!!最后还是感谢打赏的各位老板!!!\n本次更新优化视频时长,后续打算开放外链,可以使用idm下载,这个下载视频很快,也很方便!!\n如果脚本无效,请更新脚本!\n本脚本发布在油猴,别的途径均为倒卖!!!");
            var blob = new Blob([result], { type: 'text/plain' });
            newurl = URL.createObjectURL(blob)
            console.log("newurl", newurl)
            //play(newurl)

            setTimeout(async () => {
                await play(newurl)
            }, 1000)

        });

    }

    function replace_exist_img(body) {
        let content = body.content;
        let attachments = body.attachments;
        let all_img = {};
        let has_video = -1;
        for (var i = 0; i < attachments.length; i++) {
            var atta = attachments[i];
            if (atta.category === 'images') {
                all_img[atta.id] = atta.remoteUrl;
            }
            if (atta.category === 'video') {
                has_video = i;
                return [body, undefined, has_video];
            }
        }
        let re_img = /<img src=\"https:\/\/[\w\.\/]+?\/images\/.*?\" data-id=\"(\d+)\".*?\/>/g;
        for (let e of content.matchAll(re_img)) {
            let id = parseInt(e[1]);
            if (id in all_img) {
                // let nsrc = all_img[id];
                // let src = new RegExp(`(<img src=\")https:\/\/[\\w\.\/]+?\/images\/.*?\(" data-id=\"${id}\".*?\/>)`, 'g');
                // content = content.replace(src, `$1${nsrc}$2`);
                delete all_img[id];
            }
        }
        body.content = content;
        return [body, all_img, has_video];
    }

    function modify_data(data) {

        let body = JSON.parse(decode(data));
        console.log(body)
        if (body.node.vipLimit != 0) {
            body = remove_vip(body);
            return jencode(body);
        }
        let [nbody, rest_img, has_video] = replace_exist_img(body);
        body = nbody;
        // 已购买的帖子
        if (body.content.includes(`[/sell]`)) {
            return jencode(body);
        }
        if ('sale' in body && body.sale !== null) {
            body.sale.is_buy = true;
            body.sale.buy_index = parseInt(Math.random() * (5000 - 1000 + 1) + 1000, 10);
        }
        if (has_video >= 0) {
            let [nbody, v] = replace_m3u8(body, has_video);
            return jencode(nbody);
        }
        let img_elements = []
        for (const [id, src] of Object.entries(rest_img)) {
            img_elements.push(`<img src="${src}" data-id="${id}"/>`);
        }
        let selled_img = `[sell]` + img_elements.join() + `[/sell]`;
        let ncontent = body.content.replace(/<span class=\"sell-btn\".*<\/span>/, selled_img);
        body.content = ncontent;
        return jencode(body);
    }

    function modify_user(data, host, id) {
        if (data.errorCode === 0) {
            return data;
        }
        data.isEncrypted = true;
        data.errorCode = 0;
        data.success = true;
        data.message = "";
        let udict = get_user_dict(host, id);
        data.data = jencode(udict)
        return data
    }


    function IsPhone() {
        var info = navigator.userAgent;

        if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
            // 手机端代码
            console.log("isPhone=" + true)
            return true;
        } else {
            // 电脑端代码
            console.log("isPhone=" + false)
            return false;
        }

        //var isPhone = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/mobile/i.test(info);

    }
    const originOpen = XMLHttpRequest.prototype.open;
    const re_topic = /\/api\/topic\/\d+/;
    const re_user = /\/api\/user\/info\/\d+/;

    XMLHttpRequest.prototype.open = function (_, url) {
        // 拦截topic
        if (re_topic.test(url)) {
            const xhr = this;
            const getter = Object.getOwnPropertyDescriptor(
                XMLHttpRequest.prototype,
                "response"
            ).get;
            Object.defineProperty(xhr, "responseText", {
                get: () => {
                    let result = getter.call(xhr);
                    try {
                        let res = JSON.parse(result, `utf-8`);
                        // 这里修改data
                        res.data = modify_data(res.data)
                        return JSON.stringify(res, `utf-8`);
                    } catch (e) {
                        console.log('发生异常! 解析失败!');
                        console.log(e);
                        return result;
                    }
                },
            });
        } else if (re_user.test(url)) {
            const xhr = this;
            const getter = Object.getOwnPropertyDescriptor(
                XMLHttpRequest.prototype,
                "response"
            ).get;
            Object.defineProperty(xhr, "responseText", {
                get: () => {
                    let result = getter.call(xhr);
                    try {
                        let res = JSON.parse(result, `utf-8`);
                        let furl = xhr.responseURL;
                        let r = furl.match(/\W*(\w+)\.com\/api\/user\/info\/(\d+)/);
                        // 这里修改data
                        let data = modify_user(res, r[1], r[2]);
                        return JSON.stringify(data, `utf-8`);
                    } catch (e) {
                        console.log('发生异常! 解析失败!');
                        console.log(e);
                        return result;
                    }
                },
            });
        }
        originOpen.apply(this, arguments);
    };

    let clicked_flag = false;

    document.addEventListener("DOMNodeInserted", function (event) {
        if (!clicked_flag) {
            for (const element of document.getElementsByClassName('el-message-box')) {
                if (element.innerText.indexOf('令牌已过期') > -1) {
                    clicked_flag = true;
                    let e = element.querySelector("div.el-message-box__header > button");
                    setTimeout((e) => { e.click(); }, 100, e);
                    break;
                }
            }
        }
        if (event.relatedNode.getAttribute('id') === 'tidio-chat') {
            var eles = document.getElementsByTagName('*');
            for (var i = 0; i < eles.length; i++) {
                eles[i].style.userSelect = 'text';
            }
        }
    }, false);

})();




(function () {
    'use strict';

    const mgmapi = {

        addStyle(s) {
            let style = document.createElement("style");
            style.innerHTML = s;
            document.documentElement.appendChild(style);
        },
        xmlHttpRequest(details) {
            return ((typeof GM_xmlhttpRequest === "function") ? GM_xmlhttpRequest : GM.xmlHttpRequest)(details);
        },



    };


    if (location.host === "tools.thatwind.com" || location.host === "localhost:3000") {
        mgmapi.addStyle("#userscript-tip{display:none !important;}");
        console.log("host-----------------" + location.host);
        //alert("sdfsdf")
        // 对请求做代理
        const _fetch = unsafeWindow.fetch;
        unsafeWindow.fetch = async function (...args) {
            try {
                let response = await _fetch(...args);
                if (response.status !== 200) throw new Error(response.status);
                return response;
            } catch (e) {
                // 失败请求使用代理
                if (args.length == 1) {
                    console.log(`请求代理:${args[0]}`);
                    return await new Promise((resolve, reject) => {
                        let referer = new URLSearchParams(location.hash.slice(1)).get("referer");
                        let headers = {};
                        if (referer) {
                            referer = new URL(referer);
                            headers = {
                                "origin": referer.origin,
                                "referer": referer.href
                            };
                        }
                        mgmapi.xmlHttpRequest({
                            method: "GET",
                            url: args[0],
                            responseType: 'arraybuffer',
                            headers,
                            onload(r) {
                                resolve({
                                    status: r.status,
                                    headers: new Headers(r.responseHeaders.split("\n").filter(n => n).map(s => s.split(/:\s*/)).reduce((all, [a, b]) => { all[a] = b; return all; }, {})),
                                    async text() {
                                        return r.responseText;
                                    },
                                    async arrayBuffer() {
                                        return r.response;
                                    }
                                });
                            },
                            onerror() {
                                reject(new Error());
                            }
                        });
                    });
                } else {
                    throw e;
                }
            }
        }

        return;
    }

}
)();