// ==UserScript==
// @name Porn_Plus
// @namespace J8Trade
// @version 0.2_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/*
// @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: 1,//=====================================================================================》*安全标题模式,0-关闭;1-宽松模式;2-伪装模式;3-自毁模式
titleInfo: ["百度一下,你就知道", "https://www.baidu.com/favicon.ico", "passwd"],//================》伪装页面的参数,第一个是favicon地址,第二个是标题,第三个是伪装页面的密码
}
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视频页面
};
//=========================================================================================================》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;
}
`);
}
//=========================================================================================================》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(!GM_getValue('init')){window.alert("注意!\n您正在使用测试中的版本,遇到任何问题可以点击设置按钮中的跳转按钮进行反馈!");GM_setValue('init', true);}
removeXfilter();
}
downloadButton();
window.onload = main();
window.onload = addButton;
})();