Porn_Plus

Make a better Porn Website browsing experience!</br> 让你有一个更好的簧片站浏览体验!

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Porn_Plus
// @namespace    J8Trade
// @version      0.3.1_beta
// @description  Make a better Porn Website browsing experience!</br> 让你有一个更好的簧片站浏览体验!
// @author       Lord2333
// @include      /^https?:\/\/(\w*\.)?javdb(\d)*\.com.*$/
// @match        http*://jable.tv/*
// @match        http*://twitter.com/*
// @match        http*://x.com/*
// @match        http*://www.summer-plus.net/*
// @match        https://jinjier.art/*
// @icon         https://c0.jdbstatic.com/images/logo_120x120.png
// @connect      jable.tv
// @connect      missav.com
// @connect      avgle.com
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';
    const Config={
        MyPage: ["https://www.summer-plus.net/read.php?tid=2080398", "https://t.me/MrHenti"],
        javDBOfficial: "https://javdb.com",//==============================================================》JAVDB主站
        onlineWatch: ["https://jable.tv", "https://missav.com", "https://avgle.com"],//====================》在线观看网站
        removeAppAD: true, //==============================================================================》*关闭广告和APP推广
        vpnNotice: true, //================================================================================》*镜像网站提示
        loadThreshold: 0.75,//=============================================================================》*瀑布流预加载滚动阈值(滚动到页面的哪里才开始加载下一页),填写1.1即可关闭全部瀑布流功能
        loadForTextinfo: false,//==========================================================================》瀑布流加载是否在文字页面启用(关闭则只在首页和搜索结果页面启用瀑布流)
        settingMenu: true,//===============================================================================》设置按钮
        autoDarkMode: false,//=============================================================================》自动切换暗色模式
        safeMode: 0,//=====================================================================================》*安全标题模式,0-关闭;1-宽松模式;2-伪装模式;3-自毁模式
        titleInfo: ["百度一下,你就知道", "https://www.baidu.com/favicon.ico", "passwd"],//================》伪装页面的参数,第一个是favicon地址,第二个是标题,第三个是伪装页面的密码
        codeJump:true,//===================================================================================》自动搜索全局文本,替换疑似番号的文本为Javdb的链接
    }

    var Var = {
        nextPageUrl: "",
        isLoading: false,
        lastDigit: 0
    }

    //=====================================================================================================》正则匹配公式
    var Regex = {
        Num: /\d+$/, //=============================================================================》匹配链接最后的数字
        JAVDBhome: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/$/,//======================================》匹配JAVDB首页
        JAVDBpages: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/[a-zA-Z]+/,//=============================》匹配JAVDB列表页面
        JAVDBpage: /https:\/\/javdb\.com\/.*\?[^=]+=[^&]+&page=\d+/,//==============================》匹配page参数
        JAVDBvideo: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/v\/[a-zA-Z0-9]+$/,//======================》匹配JAVDB视频详情页
        JAVDBuser: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/users+$/,//================================》匹配JAVDB个人页面
        JAVDBrankings: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/rankings+/, //=========================》匹配JAVDB推荐
        JABLEvideo: /https?:\/\/(\w*\.)?jable.tv\/videos+/,//=======================================》匹配JABLE视频页面
        CodeForm: /\b([a-zA-Z]{4,}-?\d{3,})\b/g,//==================================================》匹配番号
    };

    //=========================================================================================================》toolkit
    // 安全模式,不怕社死啦
    function safeMode(){
        // 宽松模式,修改title和favicon
        var existingFavicons = document.querySelectorAll('link[rel="icon"]');
        existingFavicons.forEach(function(fav){fav.remove();});
        existingFavicons = document.querySelector('link[rel="apple-touch-icon"]');
        existingFavicons.remove();

        var newFavicon = document.createElement('link');
        newFavicon.rel = 'icon';
        newFavicon.type = 'image/png';
        newFavicon.href = Config.titleInfo[1];
        document.title = Config.titleInfo[0];
        document.head.appendChild(newFavicon);
        if(Config.safeMode == 2){ // 严格模式,添加蒙版伪装为百度
            fakePage(Config.titleInfo[2]);
        }else if(Config.safeMode == 3){ // 自毁模式,在切回原页面时直接关闭
            document.addEventListener('visibilitychange', function() {
                if (document.visibilityState != 'visible'){
                    try {
                        window.opener = window;
                        var win = window.open("", "_self");
                        win.close();
                    } catch (e) {
                    }
                }
            });
        }
    }

    // 伪装页面
    function fakePage(passwd){
        var overlay = document.createElement('div');
        overlay.id = 'page-overlay';
        overlay.innerHTML = `
        <div class="baidu-bg">
            <div class="baidu-container">
                <img src="https://www.baidu.com/img/flexible/logo/pc/result.png" alt="Baidu Logo" class="baidu-logo">
                <div class="baidu-box">
                    <input type="text" class="baidu-input" placeholder="百度一下,你就知道">
                    <button class="baidu-btn">百度一下</button>
                </div>
            </div>
        </div>
    `;
        document.body.appendChild(overlay);

        // 添加样式
        GM_addStyle(`
        #page-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: white;
            display: none;
            z-index: 9999;
            text-align: center;
            font-family: 'Arial', sans-serif;
        }

        .baidu-bg {
            background-size: cover;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-left: auto;
            margin-right: auto;
            margin-top: auto;
        }

        .baidu-container {
            background-color: rgba(255, 255, 255, 0.8);
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            text-align: center;
            max-width: 400px;
            width: 100%;
        }

        .baidu-logo {
            width: 100px;
            margin-bottom: 20px;
        }

        .baidu-box {
            display: flex;
            flex-direction: center;
            align-items: center;
        }

        .baidu-input {
            width: 100%;
            padding: 10px;
            font-size: 16px;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin-bottom: 10px;
        }

        .baidu-btn {
            width: 40%;
            padding: 10px;
            font-size: 16px;
            background-color: #3385ff;
            color: white;
            border: none;
            border-radius: 5px;
            margin-bottom: 10px;
            cursor: pointer;
        }
    `);

        // 监听可见性变化事件
        document.addEventListener('visibilitychange', function() {
            if (document.visibilityState === 'visible') {
                overlay.style.display = 'flex';
            } else {
                overlay.style.display = 'none';
            }
        });

        // 监听搜索按钮点击事件
        var searchBtn = document.querySelector('.baidu-btn');
        searchBtn.addEventListener('click', function() {
            var searchInput = document.querySelector('.baidu-input');
            if (searchInput.value === passwd) {
                overlay.style.display = 'none';
                searchInput.value = ''; // 清空搜索框防止露馅
            }else{
                window.open('https://www.baidu.com/s?wd=' + searchInput.value, '_blank');
            }
        });
    }

    // 获取Cookie参数
    function getCookieValue(cookieName) {
        var name = cookieName + '=';
        var decodedCookie = decodeURIComponent(document.cookie);
        var cookieArray = decodedCookie.split(';');
        for (var i = 0; i < cookieArray.length; i++) {
            var cookie = cookieArray[i];
            while (cookie.charAt(0) === ' ') {
                cookie = cookie.substring(1);
            }
            if (cookie.indexOf(name) === 0) {
                return cookie.substring(name.length, cookie.length);
            }
        }
        return '';
    }

    // 修改回到顶部按钮并添加菜单按钮
    function addButton(){
        var navbars = document.querySelectorAll('.navbar-link');
        navbars[5].remove();
        navbars[6].remove();
        var settingButton = document.createElement('div');
        settingButton.className = 'setting-button';
        settingButton.textContent = '⚙设置';
        document.body.appendChild(settingButton);

        var menuContainer = document.createElement('div');
        menuContainer.className = 'menu-container';
        menuContainer.innerHTML = `
            <button id="darkModeButton">🌙黑暗模式</button><br>
            <button id="languageButton">🔤English</button><br>
            <button id="nanjia">南加:shixiong</button>
            <button id="tg">TG:隔壁的混子</button>
        `;

        // 将弹窗添加到页面
        document.body.appendChild(menuContainer);

        // 添加菜单按钮
        GM_addStyle(`
            .setting-button {
                position: fixed;
                top: 60px;
                right: 5px;
                overflow: show;
                outline: none;
                border: none;
                cursor: hand;
                font-size: .8rem;
                z-index: 1000;
                display: table
            }
            .menu-container {
                position: fixed;
                top: 60px;
                right: 5px;
                width: 150px;
                padding: 10px;
                background-color: RGBA(255,255,255, 0.3);
                border: 1px solid #ccc;
                border-radius: 5px;
                display: none;
                z-index: 1001;
            }
        `);

        // 按钮点击事件处理
        settingButton.addEventListener('click', function() {
            settingButton.style.display = (settingButton.style.display === 'table') ? 'none' : 'table';
            menuContainer.style.display = (menuContainer.style.display === 'none') ? 'block' : 'none';
        });
        var darkModeButton = document.getElementById('darkModeButton');
        var languageButton = document.getElementById('languageButton');
        var nanjiaButton = document.getElementById('nanjia');
        var tgButton = document.getElementById('tg');

        var theme, langUrl;
        if(getCookieValue("locale") == "zh"){langUrl = window.location.origin+"/?locale=en";languageButton.innerText="English";}else{langUrl = window.location.origin+"/?locale=zh";languageButton.innerText="中文";}
        darkModeButton.addEventListener('click', function() {
            theme = document.documentElement.getAttribute('data-theme');
            if(theme == "auto" || theme == "light"){theme = "dark";darkModeButton.innerText="☀️亮色模式";}else{theme = "light";darkModeButton.innerText="🌙黑暗模式";}
            document.documentElement.setAttribute('data-theme', theme)
        });
        languageButton.addEventListener('click', function() {
            GM_xmlhttpRequest({
                method: 'GET',
                url: langUrl,
                headers: {
                    '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"
                },
                onload: function(response) {
                    window.location.reload();
                },
            });
        });
        nanjiaButton.addEventListener('click', function(){window.open(Config.MyPage[0], "_blank");});
        tgButton.addEventListener('click', function(){window.open(Config.MyPage[1], "_blank");});
        document.addEventListener('click', function(event) {
            if (!settingButton.contains(event.target) && event.target !== settingButton) {
                menuContainer.style.display = 'none';
                settingButton.style.display = 'table';
            }
        });
    }

    // 关闭顶部和底部安装APP提示,和页面内广告
    function removeAppAD(){
        var app = document.querySelector(".app-desktop-banner");
        var sub_header = document.querySelector(".sub-header");
        var page_AD = document.querySelector(".top-meta");
        if(app){try{
            app.remove();sub_header.remove();page_AD.remove();
        }catch{}}
    }

    // 检查网站连通性
    function checkWebsites(websites, outtime) {
        var promises = websites.map(function(website) {
            return new Promise(function(resolve) {
                GM_xmlhttpRequest({
                    method: "GET",
                    url: website,
                    outtime: outtime,
                    onload: function(response) {
                        resolve({ website: website, status: response.status });
                    },
                    onerror: function(error) {
                        resolve({ website: website, error: error.message });
                    }
                });
            });
        });
        return Promise.all(promises);
    }

    // 镜像站检测
    function vpnNotice(){
        const url = window.location.href;
        if(!Regex.JAVDBhome.test(url)){return;}
        if (!url.startsWith(Config.javDBOfficial) ) {
            var confirmation = confirm("您正在使用镜像站,javPlus脚本可能无法正常工作!\n点击确定将跳转到主站。");
            if (confirmation) {
                var newPath = url.replace(/^(https?:\/\/)[a-zA-Z0-9]+\.com\//, "$1www.javdb.com/");
                window.location.href = newPath;
            }else{
                var temp;
                checkWebsites(Config.onlineWatch, 1500).then(function(results) {
                    temp = results.map(function(reslut) {
                        if (reslut.status == 200) {
                            return "可以连接至:"+ reslut.website;
                        } else {
                            return "无法连接至:"+ reslut.website;
                        }
                    }).join("\n");
                    window.alert(temp);
                });
            }
        }
    }

    // 检查是否滚动到页面底部或当前页面无下一页
    function isScrollAtBottom() {
        var scrollHeight = document.documentElement.scrollHeight;
        var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
        var clientHeight = document.documentElement.clientHeight;

        return (scrollHeight - scrollTop - clientHeight) < ((1 - Config.loadThreshold) * scrollHeight);
    }

    // 获取下页数据
    function getNextPage(pageurl){
        GM_xmlhttpRequest({
            method: 'GET',
            url: pageurl,
            headers: {
                '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"
            },
            onload: function(response) {
                try{
                    var parser = new DOMParser();
                    var doc = parser.parseFromString(response.responseText, 'text/html');
                    var targetDiv = doc.querySelector('div.movie-list.h');
                    var itemsArray = extractItems(targetDiv);
                    renderData(itemsArray);
                }
                catch{ return;}
            },
            onerror: function(error) {
                console.error('Error loading page:', error);
            }
        });
    }

    // 提取 <item> 标签的内容
    function extractItems(targetDiv) {
        var itemsArray = [];
        if (targetDiv) {
            var items = targetDiv.querySelectorAll('.item');
            items.forEach(function(item) {
                var cover = item.querySelector('.cover');
                cover.classList.add('contain');
                itemsArray.push(item.outerHTML.trim());
            });
        }
        return itemsArray;
    }

    // 模拟渲染数据到页面
    function renderData(items) {
        var container = document.querySelector('.movie-list.h');
        items.forEach(function(item){
            container.innerHTML += item;
        });
        Var.isLoading = false;
    }

    // 检测当前页面链接
    function checkPageUrl(){
        var currentUrl = window.location.href;
        if (currentUrl.includes("javdb")){ //=============================================================》JavDB
            if(!Regex.JAVDBvideo.test(currentUrl) && !Regex.JAVDBuser.test(currentUrl) && !Regex.JAVDBrankings.test(currentUrl)){ // 排除的页面
                if (Regex.JAVDBhome.test(currentUrl)) { // 如果当前页面是网站首页
                    if(!Var.lastDigit){Var.lastDigit=1;}
                    Var.lastDigit += 1;
                    Var.nextPageUrl = currentUrl + "?page=" + Var.lastDigit.toString();
                    return Var.nextPageUrl;
                }else if(Regex.JAVDBpages.test(currentUrl)){ // 在非首页的页面里
                    if(Regex.JAVDBpage.test(currentUrl)){ Var.lastDigit = parseInt(currentUrl.match(Regex.Num));}
                    else if(!Var.lastDigit){Var.lastDigit = 1}
                    Var.lastDigit += 1;
                    Var.nextPageUrl = currentUrl+ "&page=" +Var.lastDigit.toString();
                    return Var.nextPageUrl;
                }
            }
        }
    }

    // 添加页面下载按钮
    function downloadButton(){
        var pageUrl = window.location.href;
        if(Regex.JABLEvideo.test(pageUrl)){
            var my3 = document.querySelector('.my-3');
            var secondChild = my3.children[1];
            var buttonElement = '<button id="downloadBtn" data-fav-type="1" class="btn btn-action "><svg height="18" width="16"><use xlink:href="#icon-download"></use></svg></button>';
            secondChild.insertAdjacentHTML('afterend', buttonElement);
        }
    }

    // 移除推特敏感内容遮罩
    function removeXfilter(){
        GM_addStyle(`
                    .media-preview-with-warning > .js-media-preview-container,
                    .media-preview-with-warning > [class^='media-grid'] {
            filter: blur(0px) !important;
        }

        .js-media.full-bleed-media-preview-with-warning > .js-media-preview-container > .js-media-image-link,
            .js-media.full-bleed-media-preview-with-warning > [class^='media-grid'] {
                filter: blur(0px) !important;
            }

        .media-warning {
            display: none !important;
        }

        .r-yfv4eo {
            filter: blur(0px) !important;
        }
        .r-drfeu3 {
            display: none !important;
        }
        .r-yfv4eo + .r-1777fci {
            display: none !important;
        }
        `);
    }

    function codeJump(){
        //正则规则
        const pattern = /(^|\b|[^a-z0-9])([a-z]{3,6}-?\d{3})(\b|[^a-z0-9]|$)/gi;
        const walker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            { acceptNode: node => node.parentNode.closest('a') ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT }
        );

        const nodes = [];
        while (walker.nextNode()) nodes.push(walker.currentNode);

        nodes.forEach(node => {
            let lastIndex = 0;
            const newHTML = node.nodeValue.replace(pattern, (match, prefix, code, suffix, offset) => {
                // 边界验证(防止部分匹配)
                const validPrefix = !prefix || /[\s\[({]/.test(prefix);
                const validSuffix = !suffix || /[\s\])}]/.test(suffix);
                if (validPrefix && validSuffix) { // 总长度验证
                    return `${prefix}<a href="https://javdb.com/search?q=${encodeURIComponent(code.toUpperCase())}&f=all"
                        style="all:unset; cursor:pointer; color:inherit; text-decoration:underline"
                        target="_blank">${code}</a>${suffix}`;
                }
                return match;
            });

            if (newHTML !== node.nodeValue) {
                const wrapper = document.createElement('span');
                wrapper.innerHTML = newHTML;
                node.parentNode.replaceChild(wrapper, node);
            }
        });
    }

    //=========================================================================================================》Main
    // 监听滚动事件
    window.addEventListener('scroll', function() {
        if (isScrollAtBottom()) {
            if (Var.isLoading){return;}
            Var.isLoading = true;
            if(checkPageUrl()){
                getNextPage(Var.nextPageUrl);
            }
        }
    });

    function main(){
        if(Config.vpnNotice){vpnNotice();}
        if(Config.removeAppAD){removeAppAD();}
        if(Config.safeMode){safeMode();}
        if(Config.codeJump){codeJump();}
        if(!GM_getValue('init')){window.alert("注意!\n您正在使用测试中的版本,遇到任何问题可以点击设置按钮中的跳转按钮进行反馈!");GM_setValue('init', true);}
        removeXfilter();
    }
    downloadButton();
    window.onload = main();
    window.onload = addButton;

})();