Sleazy Fork is available in English.

Porn_Plus

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

  1. // ==UserScript==
  2. // @name Porn_Plus
  3. // @namespace J8Trade
  4. // @version 0.3.1_beta
  5. // @description Make a better Porn Website browsing experience!</br> 让你有一个更好的簧片站浏览体验!
  6. // @author Lord2333
  7. // @include /^https?:\/\/(\w*\.)?javdb(\d)*\.com.*$/
  8. // @match http*://jable.tv/*
  9. // @match http*://twitter.com/*
  10. // @match http*://x.com/*
  11. // @match http*://www.summer-plus.net/*
  12. // @match https://jinjier.art/*
  13. // @icon https://c0.jdbstatic.com/images/logo_120x120.png
  14. // @connect jable.tv
  15. // @connect missav.com
  16. // @connect avgle.com
  17. // @grant GM_setValue
  18. // @grant GM_getValue
  19. // @grant GM_xmlhttpRequest
  20. // @grant GM_addStyle
  21. // ==/UserScript==
  22.  
  23. (function() {
  24. 'use strict';
  25. const Config={
  26. MyPage: ["https://www.summer-plus.net/read.php?tid=2080398", "https://t.me/MrHenti"],
  27. javDBOfficial: "https://javdb.com",//==============================================================》JAVDB主站
  28. onlineWatch: ["https://jable.tv", "https://missav.com", "https://avgle.com"],//====================》在线观看网站
  29. removeAppAD: true, //==============================================================================》*关闭广告和APP推广
  30. vpnNotice: true, //================================================================================》*镜像网站提示
  31. loadThreshold: 0.75,//=============================================================================》*瀑布流预加载滚动阈值(滚动到页面的哪里才开始加载下一页),填写1.1即可关闭全部瀑布流功能
  32. loadForTextinfo: false,//==========================================================================》瀑布流加载是否在文字页面启用(关闭则只在首页和搜索结果页面启用瀑布流)
  33. settingMenu: true,//===============================================================================》设置按钮
  34. autoDarkMode: false,//=============================================================================》自动切换暗色模式
  35. safeMode: 0,//=====================================================================================》*安全标题模式,0-关闭;1-宽松模式;2-伪装模式;3-自毁模式
  36. titleInfo: ["百度一下,你就知道", "https://www.baidu.com/favicon.ico", "passwd"],//================》伪装页面的参数,第一个是favicon地址,第二个是标题,第三个是伪装页面的密码
  37. codeJump:true,//===================================================================================》自动搜索全局文本,替换疑似番号的文本为Javdb的链接
  38. }
  39.  
  40. var Var = {
  41. nextPageUrl: "",
  42. isLoading: false,
  43. lastDigit: 0
  44. }
  45.  
  46. //=====================================================================================================》正则匹配公式
  47. var Regex = {
  48. Num: /\d+$/, //=============================================================================》匹配链接最后的数字
  49. JAVDBhome: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/$/,//======================================》匹配JAVDB首页
  50. JAVDBpages: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/[a-zA-Z]+/,//=============================》匹配JAVDB列表页面
  51. JAVDBpage: /https:\/\/javdb\.com\/.*\?[^=]+=[^&]+&page=\d+/,//==============================》匹配page参数
  52. JAVDBvideo: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/v\/[a-zA-Z0-9]+$/,//======================》匹配JAVDB视频详情页
  53. JAVDBuser: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/users+$/,//================================》匹配JAVDB个人页面
  54. JAVDBrankings: /^https?:\/\/(\w*\.)?javdb(\d)*\.com\/rankings+/, //=========================》匹配JAVDB推荐
  55. JABLEvideo: /https?:\/\/(\w*\.)?jable.tv\/videos+/,//=======================================》匹配JABLE视频页面
  56. CodeForm: /\b([a-zA-Z]{4,}-?\d{3,})\b/g,//==================================================》匹配番号
  57. };
  58.  
  59. //=========================================================================================================》toolkit
  60. // 安全模式,不怕社死啦
  61. function safeMode(){
  62. // 宽松模式,修改title和favicon
  63. var existingFavicons = document.querySelectorAll('link[rel="icon"]');
  64. existingFavicons.forEach(function(fav){fav.remove();});
  65. existingFavicons = document.querySelector('link[rel="apple-touch-icon"]');
  66. existingFavicons.remove();
  67.  
  68. var newFavicon = document.createElement('link');
  69. newFavicon.rel = 'icon';
  70. newFavicon.type = 'image/png';
  71. newFavicon.href = Config.titleInfo[1];
  72. document.title = Config.titleInfo[0];
  73. document.head.appendChild(newFavicon);
  74. if(Config.safeMode == 2){ // 严格模式,添加蒙版伪装为百度
  75. fakePage(Config.titleInfo[2]);
  76. }else if(Config.safeMode == 3){ // 自毁模式,在切回原页面时直接关闭
  77. document.addEventListener('visibilitychange', function() {
  78. if (document.visibilityState != 'visible'){
  79. try {
  80. window.opener = window;
  81. var win = window.open("", "_self");
  82. win.close();
  83. } catch (e) {
  84. }
  85. }
  86. });
  87. }
  88. }
  89.  
  90. // 伪装页面
  91. function fakePage(passwd){
  92. var overlay = document.createElement('div');
  93. overlay.id = 'page-overlay';
  94. overlay.innerHTML = `
  95. <div class="baidu-bg">
  96. <div class="baidu-container">
  97. <img src="https://www.baidu.com/img/flexible/logo/pc/result.png" alt="Baidu Logo" class="baidu-logo">
  98. <div class="baidu-box">
  99. <input type="text" class="baidu-input" placeholder="百度一下,你就知道">
  100. <button class="baidu-btn">百度一下</button>
  101. </div>
  102. </div>
  103. </div>
  104. `;
  105. document.body.appendChild(overlay);
  106.  
  107. // 添加样式
  108. GM_addStyle(`
  109. #page-overlay {
  110. position: fixed;
  111. top: 0;
  112. left: 0;
  113. width: 100%;
  114. height: 100%;
  115. background-color: white;
  116. display: none;
  117. z-index: 9999;
  118. text-align: center;
  119. font-family: 'Arial', sans-serif;
  120. }
  121.  
  122. .baidu-bg {
  123. background-size: cover;
  124. height: 100%;
  125. display: flex;
  126. align-items: center;
  127. justify-content: center;
  128. margin-left: auto;
  129. margin-right: auto;
  130. margin-top: auto;
  131. }
  132.  
  133. .baidu-container {
  134. background-color: rgba(255, 255, 255, 0.8);
  135. padding: 20px;
  136. border-radius: 8px;
  137. box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  138. text-align: center;
  139. max-width: 400px;
  140. width: 100%;
  141. }
  142.  
  143. .baidu-logo {
  144. width: 100px;
  145. margin-bottom: 20px;
  146. }
  147.  
  148. .baidu-box {
  149. display: flex;
  150. flex-direction: center;
  151. align-items: center;
  152. }
  153.  
  154. .baidu-input {
  155. width: 100%;
  156. padding: 10px;
  157. font-size: 16px;
  158. border: 1px solid #ddd;
  159. border-radius: 5px;
  160. margin-bottom: 10px;
  161. }
  162.  
  163. .baidu-btn {
  164. width: 40%;
  165. padding: 10px;
  166. font-size: 16px;
  167. background-color: #3385ff;
  168. color: white;
  169. border: none;
  170. border-radius: 5px;
  171. margin-bottom: 10px;
  172. cursor: pointer;
  173. }
  174. `);
  175.  
  176. // 监听可见性变化事件
  177. document.addEventListener('visibilitychange', function() {
  178. if (document.visibilityState === 'visible') {
  179. overlay.style.display = 'flex';
  180. } else {
  181. overlay.style.display = 'none';
  182. }
  183. });
  184.  
  185. // 监听搜索按钮点击事件
  186. var searchBtn = document.querySelector('.baidu-btn');
  187. searchBtn.addEventListener('click', function() {
  188. var searchInput = document.querySelector('.baidu-input');
  189. if (searchInput.value === passwd) {
  190. overlay.style.display = 'none';
  191. searchInput.value = ''; // 清空搜索框防止露馅
  192. }else{
  193. window.open('https://www.baidu.com/s?wd=' + searchInput.value, '_blank');
  194. }
  195. });
  196. }
  197.  
  198. // 获取Cookie参数
  199. function getCookieValue(cookieName) {
  200. var name = cookieName + '=';
  201. var decodedCookie = decodeURIComponent(document.cookie);
  202. var cookieArray = decodedCookie.split(';');
  203. for (var i = 0; i < cookieArray.length; i++) {
  204. var cookie = cookieArray[i];
  205. while (cookie.charAt(0) === ' ') {
  206. cookie = cookie.substring(1);
  207. }
  208. if (cookie.indexOf(name) === 0) {
  209. return cookie.substring(name.length, cookie.length);
  210. }
  211. }
  212. return '';
  213. }
  214.  
  215. // 修改回到顶部按钮并添加菜单按钮
  216. function addButton(){
  217. var navbars = document.querySelectorAll('.navbar-link');
  218. navbars[5].remove();
  219. navbars[6].remove();
  220. var settingButton = document.createElement('div');
  221. settingButton.className = 'setting-button';
  222. settingButton.textContent = '⚙设置';
  223. document.body.appendChild(settingButton);
  224.  
  225. var menuContainer = document.createElement('div');
  226. menuContainer.className = 'menu-container';
  227. menuContainer.innerHTML = `
  228. <button id="darkModeButton">🌙黑暗模式</button><br>
  229. <button id="languageButton">🔤English</button><br>
  230. <button id="nanjia">南加:shixiong</button>
  231. <button id="tg">TG:隔壁的混子</button>
  232. `;
  233.  
  234. // 将弹窗添加到页面
  235. document.body.appendChild(menuContainer);
  236.  
  237. // 添加菜单按钮
  238. GM_addStyle(`
  239. .setting-button {
  240. position: fixed;
  241. top: 60px;
  242. right: 5px;
  243. overflow: show;
  244. outline: none;
  245. border: none;
  246. cursor: hand;
  247. font-size: .8rem;
  248. z-index: 1000;
  249. display: table
  250. }
  251. .menu-container {
  252. position: fixed;
  253. top: 60px;
  254. right: 5px;
  255. width: 150px;
  256. padding: 10px;
  257. background-color: RGBA(255,255,255, 0.3);
  258. border: 1px solid #ccc;
  259. border-radius: 5px;
  260. display: none;
  261. z-index: 1001;
  262. }
  263. `);
  264.  
  265. // 按钮点击事件处理
  266. settingButton.addEventListener('click', function() {
  267. settingButton.style.display = (settingButton.style.display === 'table') ? 'none' : 'table';
  268. menuContainer.style.display = (menuContainer.style.display === 'none') ? 'block' : 'none';
  269. });
  270. var darkModeButton = document.getElementById('darkModeButton');
  271. var languageButton = document.getElementById('languageButton');
  272. var nanjiaButton = document.getElementById('nanjia');
  273. var tgButton = document.getElementById('tg');
  274.  
  275. var theme, langUrl;
  276. if(getCookieValue("locale") == "zh"){langUrl = window.location.origin+"/?locale=en";languageButton.innerText="English";}else{langUrl = window.location.origin+"/?locale=zh";languageButton.innerText="中文";}
  277. darkModeButton.addEventListener('click', function() {
  278. theme = document.documentElement.getAttribute('data-theme');
  279. if(theme == "auto" || theme == "light"){theme = "dark";darkModeButton.innerText="☀️亮色模式";}else{theme = "light";darkModeButton.innerText="🌙黑暗模式";}
  280. document.documentElement.setAttribute('data-theme', theme)
  281. });
  282. languageButton.addEventListener('click', function() {
  283. GM_xmlhttpRequest({
  284. method: 'GET',
  285. url: langUrl,
  286. headers: {
  287. '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"
  288. },
  289. onload: function(response) {
  290. window.location.reload();
  291. },
  292. });
  293. });
  294. nanjiaButton.addEventListener('click', function(){window.open(Config.MyPage[0], "_blank");});
  295. tgButton.addEventListener('click', function(){window.open(Config.MyPage[1], "_blank");});
  296. document.addEventListener('click', function(event) {
  297. if (!settingButton.contains(event.target) && event.target !== settingButton) {
  298. menuContainer.style.display = 'none';
  299. settingButton.style.display = 'table';
  300. }
  301. });
  302. }
  303.  
  304. // 关闭顶部和底部安装APP提示,和页面内广告
  305. function removeAppAD(){
  306. var app = document.querySelector(".app-desktop-banner");
  307. var sub_header = document.querySelector(".sub-header");
  308. var page_AD = document.querySelector(".top-meta");
  309. if(app){try{
  310. app.remove();sub_header.remove();page_AD.remove();
  311. }catch{}}
  312. }
  313.  
  314. // 检查网站连通性
  315. function checkWebsites(websites, outtime) {
  316. var promises = websites.map(function(website) {
  317. return new Promise(function(resolve) {
  318. GM_xmlhttpRequest({
  319. method: "GET",
  320. url: website,
  321. outtime: outtime,
  322. onload: function(response) {
  323. resolve({ website: website, status: response.status });
  324. },
  325. onerror: function(error) {
  326. resolve({ website: website, error: error.message });
  327. }
  328. });
  329. });
  330. });
  331. return Promise.all(promises);
  332. }
  333.  
  334. // 镜像站检测
  335. function vpnNotice(){
  336. const url = window.location.href;
  337. if(!Regex.JAVDBhome.test(url)){return;}
  338. if (!url.startsWith(Config.javDBOfficial) ) {
  339. var confirmation = confirm("您正在使用镜像站,javPlus脚本可能无法正常工作!\n点击确定将跳转到主站。");
  340. if (confirmation) {
  341. var newPath = url.replace(/^(https?:\/\/)[a-zA-Z0-9]+\.com\//, "$1www.javdb.com/");
  342. window.location.href = newPath;
  343. }else{
  344. var temp;
  345. checkWebsites(Config.onlineWatch, 1500).then(function(results) {
  346. temp = results.map(function(reslut) {
  347. if (reslut.status == 200) {
  348. return "可以连接至:"+ reslut.website;
  349. } else {
  350. return "无法连接至:"+ reslut.website;
  351. }
  352. }).join("\n");
  353. window.alert(temp);
  354. });
  355. }
  356. }
  357. }
  358.  
  359. // 检查是否滚动到页面底部或当前页面无下一页
  360. function isScrollAtBottom() {
  361. var scrollHeight = document.documentElement.scrollHeight;
  362. var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  363. var clientHeight = document.documentElement.clientHeight;
  364.  
  365. return (scrollHeight - scrollTop - clientHeight) < ((1 - Config.loadThreshold) * scrollHeight);
  366. }
  367.  
  368. // 获取下页数据
  369. function getNextPage(pageurl){
  370. GM_xmlhttpRequest({
  371. method: 'GET',
  372. url: pageurl,
  373. headers: {
  374. '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"
  375. },
  376. onload: function(response) {
  377. try{
  378. var parser = new DOMParser();
  379. var doc = parser.parseFromString(response.responseText, 'text/html');
  380. var targetDiv = doc.querySelector('div.movie-list.h');
  381. var itemsArray = extractItems(targetDiv);
  382. renderData(itemsArray);
  383. }
  384. catch{ return;}
  385. },
  386. onerror: function(error) {
  387. console.error('Error loading page:', error);
  388. }
  389. });
  390. }
  391.  
  392. // 提取 <item> 标签的内容
  393. function extractItems(targetDiv) {
  394. var itemsArray = [];
  395. if (targetDiv) {
  396. var items = targetDiv.querySelectorAll('.item');
  397. items.forEach(function(item) {
  398. var cover = item.querySelector('.cover');
  399. cover.classList.add('contain');
  400. itemsArray.push(item.outerHTML.trim());
  401. });
  402. }
  403. return itemsArray;
  404. }
  405.  
  406. // 模拟渲染数据到页面
  407. function renderData(items) {
  408. var container = document.querySelector('.movie-list.h');
  409. items.forEach(function(item){
  410. container.innerHTML += item;
  411. });
  412. Var.isLoading = false;
  413. }
  414.  
  415. // 检测当前页面链接
  416. function checkPageUrl(){
  417. var currentUrl = window.location.href;
  418. if (currentUrl.includes("javdb")){ //=============================================================》JavDB
  419. if(!Regex.JAVDBvideo.test(currentUrl) && !Regex.JAVDBuser.test(currentUrl) && !Regex.JAVDBrankings.test(currentUrl)){ // 排除的页面
  420. if (Regex.JAVDBhome.test(currentUrl)) { // 如果当前页面是网站首页
  421. if(!Var.lastDigit){Var.lastDigit=1;}
  422. Var.lastDigit += 1;
  423. Var.nextPageUrl = currentUrl + "?page=" + Var.lastDigit.toString();
  424. return Var.nextPageUrl;
  425. }else if(Regex.JAVDBpages.test(currentUrl)){ // 在非首页的页面里
  426. if(Regex.JAVDBpage.test(currentUrl)){ Var.lastDigit = parseInt(currentUrl.match(Regex.Num));}
  427. else if(!Var.lastDigit){Var.lastDigit = 1}
  428. Var.lastDigit += 1;
  429. Var.nextPageUrl = currentUrl+ "&page=" +Var.lastDigit.toString();
  430. return Var.nextPageUrl;
  431. }
  432. }
  433. }
  434. }
  435.  
  436. // 添加页面下载按钮
  437. function downloadButton(){
  438. var pageUrl = window.location.href;
  439. if(Regex.JABLEvideo.test(pageUrl)){
  440. var my3 = document.querySelector('.my-3');
  441. var secondChild = my3.children[1];
  442. 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>';
  443. secondChild.insertAdjacentHTML('afterend', buttonElement);
  444. }
  445. }
  446.  
  447. // 移除推特敏感内容遮罩
  448. function removeXfilter(){
  449. GM_addStyle(`
  450. .media-preview-with-warning > .js-media-preview-container,
  451. .media-preview-with-warning > [class^='media-grid'] {
  452. filter: blur(0px) !important;
  453. }
  454.  
  455. .js-media.full-bleed-media-preview-with-warning > .js-media-preview-container > .js-media-image-link,
  456. .js-media.full-bleed-media-preview-with-warning > [class^='media-grid'] {
  457. filter: blur(0px) !important;
  458. }
  459.  
  460. .media-warning {
  461. display: none !important;
  462. }
  463.  
  464. .r-yfv4eo {
  465. filter: blur(0px) !important;
  466. }
  467. .r-drfeu3 {
  468. display: none !important;
  469. }
  470. .r-yfv4eo + .r-1777fci {
  471. display: none !important;
  472. }
  473. `);
  474. }
  475.  
  476. function codeJump(){
  477. //正则规则
  478. const pattern = /(^|\b|[^a-z0-9])([a-z]{3,6}-?\d{3})(\b|[^a-z0-9]|$)/gi;
  479. const walker = document.createTreeWalker(
  480. document.body,
  481. NodeFilter.SHOW_TEXT,
  482. { acceptNode: node => node.parentNode.closest('a') ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT }
  483. );
  484.  
  485. const nodes = [];
  486. while (walker.nextNode()) nodes.push(walker.currentNode);
  487.  
  488. nodes.forEach(node => {
  489. let lastIndex = 0;
  490. const newHTML = node.nodeValue.replace(pattern, (match, prefix, code, suffix, offset) => {
  491. // 边界验证(防止部分匹配)
  492. const validPrefix = !prefix || /[\s\[({]/.test(prefix);
  493. const validSuffix = !suffix || /[\s\])}]/.test(suffix);
  494. if (validPrefix && validSuffix) { // 总长度验证
  495. return `${prefix}<a href="https://javdb.com/search?q=${encodeURIComponent(code.toUpperCase())}&f=all"
  496. style="all:unset; cursor:pointer; color:inherit; text-decoration:underline"
  497. target="_blank">${code}</a>${suffix}`;
  498. }
  499. return match;
  500. });
  501.  
  502. if (newHTML !== node.nodeValue) {
  503. const wrapper = document.createElement('span');
  504. wrapper.innerHTML = newHTML;
  505. node.parentNode.replaceChild(wrapper, node);
  506. }
  507. });
  508. }
  509.  
  510. //=========================================================================================================》Main
  511. // 监听滚动事件
  512. window.addEventListener('scroll', function() {
  513. if (isScrollAtBottom()) {
  514. if (Var.isLoading){return;}
  515. Var.isLoading = true;
  516. if(checkPageUrl()){
  517. getNextPage(Var.nextPageUrl);
  518. }
  519. }
  520. });
  521.  
  522. function main(){
  523. if(Config.vpnNotice){vpnNotice();}
  524. if(Config.removeAppAD){removeAppAD();}
  525. if(Config.safeMode){safeMode();}
  526. if(Config.codeJump){codeJump();}
  527. if(!GM_getValue('init')){window.alert("注意!\n您正在使用测试中的版本,遇到任何问题可以点击设置按钮中的跳转按钮进行反馈!");GM_setValue('init', true);}
  528. removeXfilter();
  529. }
  530. downloadButton();
  531. window.onload = main();
  532. window.onload = addButton;
  533.  
  534. })();