JAVBUS助手

JAVBUS网站增加自动翻页,论坛页面精简

As of 2023-06-02. See the latest version.

// ==UserScript==
// @name         JAVBUS助手
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  JAVBUS网站增加自动翻页,论坛页面精简
// @author       A9
// @match        https://www.javbus.com/
// @include      /^https?:\/\/(?:[A-Za-z0-9]+\.)*(?:javbus|busjav|busfan|fanbus|buscdn|cdnbus|dmmsee|seedmm|busdmm|dmmbus|javsee|seejav)(?:\.[A-Za-z0-9]+)(?:[\S]*)$/
// @grant        GM_addStyle
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABFElEQVQ4ja2TMU4CQRSGvzfuKkQ2bqORRpKNV6CjIaGgovQK1LRs7R24AoECbrAHWE7glhQkJO4SEgt1GQsCBhmG1fjKee//8v/zZiSGJ+AZeOR3lQChxPDyB/EeIjFo28SuKSf6jk0sjoPXaHDh+6yjiDzLjmaUDaDKZe77fR4GAy5rNaNVK2DnQlwXEXOIs4Bz9f8AU85TG4CfW1AKv93mul7ndTjkfT4HETSgN5sCAK256XS47XZRlQrrKOIqCMjTlDxNjU7UoV6TTSZ8Lpfc9XoEoxFutUo6HvOxWBgdHL1EcRy8ZhOv1UKVSrzNZmTTKflqVQwA2wOBbX6trZeo2P6qQ+p3JqsYSBQQmiAFKgHCL3I+UIXeDJynAAAAAElFTkSuQmCC
// @license      MIT
// ==/UserScript==

(function () {
  "use strict";

  //脚本设置项
  let settings = {
    enable_forum_style_override: 1, // 是否开启论坛排版样式优化,0 关闭;1 开启。开启后页面间距更紧凑,可使浏览更加高效
    enable_forum_auto_pager: 1, // 是否开启论坛自动翻页功能,0 关闭;1 开启
    enable_main_auto_pager: 1, // 是否开启主站自动翻页功能,0 关闭;1 开启
  };

  /**
   * 当前页面的浏览模式 forumdisplay 板块列表页 | viewthread 帖子详情页 | default 默认适用于其他所有页面 | actresses 演员页 | favorite 收藏页(论坛) | forum 论坛搜索结果 | thread 个人主题/回复页 | guide 新帖导读页 | friend 好友页 | notice 我的通知
   * @type { "forumdisplay" | "viewthread" | "default" | "actresses" | "favorite" | "forum" | "thread" | "guide" | "friend" | "notice"}
   */
  let PAGE_MOD = "default";
  let CURRENT_SETTING = null; //当前页翻页规则
  let isForum = false; //当前页是否是论坛页面
  const PAGE_SETTINGS = {
    default: {
      listDomSelector: "#waterfall.masonry",
      itemDomSelector: "#waterfall > .item:has(.movie-box)",
      pagerDomSelector: ".pagination.pagination-lg",
      nextPageDomSelector: "#next",
      nodeAfterAddCall: () => {
        //重新计算瀑布流的布局
        jQuery("#waterfall").masonry("reload");
      },
    },
    actresses: {
      listDomSelector: "#waterfall.masonry",
      itemDomSelector: "#waterfall > .item:has(.avatar-box)",
      pagerDomSelector: ".pagination.pagination-lg",
      nextPageDomSelector: "#next",
      nodeAfterAddCall: () => {
        //重新计算瀑布流的布局
        jQuery("#waterfall").masonry("reload");
      },
    },
    viewthread: {
      listDomSelector: "#postlist",
      itemDomSelector: "#postlist > .nthread_postbox",
      pagerDomSelector: "div.pgs.mtm.mbm.cl .pg",
      nextPageDomSelector: ".nxt",
      nodeBeforeAddCall: (node) => {
        node.querySelector(".imicn a[title='查看個人網站']")?.remove(); //删除多余的元素
        node.querySelector(".showmenu").style.display = "none"; //隐藏‘使用道具’菜单
      },
    },
    forumdisplay: {
      listDomSelector: "#threadlisttableid",
      itemDomSelector: "#threadlisttableid > tbody",
      pagerDomSelector: "#fd_page_bottom > .pg",
      nextPageDomSelector: ".nxt",
    },
    forum: {
      listDomSelector: "#threadlist ul",
      itemDomSelector: "#threadlist ul > li",
      pagerDomSelector: "div.pgs.cl.mbm > .pg",
      nextPageDomSelector: ".nxt",
    },
    guide: {
      listDomSelector: "#threadlist table",
      itemDomSelector: "#threadlist table > tbody",
      pagerDomSelector: ".pg:has(.nxt)",
      nextPageDomSelector: ".nxt",
    },
    favorite: {
      listDomSelector: "#favorite_ul",
      itemDomSelector: "#favorite_ul > li",
      pagerDomSelector: "div.pgs.cl.mtm > .pg",
      nextPageDomSelector: ".nxt",
    },
    thread: {
      listDomSelector: ".tl table tbody",
      itemDomSelector: ".tl table tbody > tr:not(.th)",
      pagerDomSelector: "div.pgs.cl.mtm > .pg",
      nextPageDomSelector: ".nxt",
    },
    friend: {
      listDomSelector: "ul.buddy.cl",
      itemDomSelector: "ul.buddy.cl > li",
      pagerDomSelector: "div.mtm.pgs.cl > .pg",
      nextPageDomSelector: ".nxt",
    },
    notice: {
      listDomSelector: "div.nts",
      itemDomSelector: "div.nts > dl",
      pagerDomSelector: "div.pgs.cl > .pg",
      nextPageDomSelector: ".nxt",
    },
  };

  //脚本入口点,排除frame或iframe
  if (window !== window.top) return;

  initialized();
  overrideForumStyle();
  autoPager();

  function initialized() {
    let url = new URL(window.location.href);
    let mod = url.searchParams.get("mod");
    if (mod) {
      isForum = true;
      //论坛中的二级页面
      let doType = url.searchParams.get("do");
      if (doType) {
        PAGE_MOD = doType;
      } else {
        PAGE_MOD = mod;
      }
    } else if (url.pathname.includes("actresses")) {
      PAGE_MOD = "actresses";
    }
    //根据不同的页面,使用不同的翻页规则
    CURRENT_SETTING = PAGE_SETTINGS[PAGE_MOD];
  }

  function autoPager() {
    if (!CURRENT_SETTING) return;

    //翻页dom
    const obTarget = document.querySelector(CURRENT_SETTING.pagerDomSelector);
    //当前页面只有一页或已经是最后一页,无需翻页
    if (!obTarget || !obTarget.querySelector(CURRENT_SETTING.nextPageDomSelector)) {
      console.log("当前页面只有一页或已经是最后一页,无需翻页");
      return;
    }
    // if (!settings.enable_forum_auto_pager && isForum) return;
    // if (!settings.enable_main_auto_pager && !isForum) return;

    //观察器配置
    const observerOptions = {
      root: null,
      rootMargin: "0px",
    };
    //观察器回调
    const intersectionCallback = function (entries) {
      if (entries[0].intersectionRatio <= 0) return;
      //下一页的链接
      let nextPageLink = obTarget.querySelector(
        CURRENT_SETTING.nextPageDomSelector
      )?.href;
      //到尾页,停止观察器
      if (!nextPageLink) {
        autoPagerOB.disconnect();
        console.log("停止观察器");
      } else {
        //加载下一页的内容
        loadNextPage(nextPageLink);
      }
    };
    //创建交叉观察器
    let autoPagerOB = new IntersectionObserver(intersectionCallback, observerOptions);

    //在顶部导航栏的右侧增加控制按钮
    let navBar = document.querySelector(isForum ? "#toptb" : "#navbar");
    let toggleAutoPager = document.createElement("a");
    toggleAutoPager.href = "javascript:void(0)";
    toggleAutoPager.innerText = `${
      settings.enable_main_auto_pager ? "关闭" : "开启"
    }自动翻页`;
    toggleAutoPager.className = "nav navbar-nav navbar-right";    
    toggleAutoPager.style.cssText=`
      display: block;
      padding: ${isForum?"11":"15"}px;
      color: rgb(119, 119, 119);
      float: right;
      font-size: 14px;
    `;

    toggleAutoPager.addEventListener("click", () => {
      if (settings.enable_main_auto_pager) {
        autoPagerOB?.unobserve(obTarget); //停止观察
        settings.enable_main_auto_pager = 0;
      } else {
        autoPagerOB?.observe(obTarget); //继续观察
        settings.enable_main_auto_pager = 1;
      }
      toggleAutoPager.innerText = `${
        settings.enable_main_auto_pager ? "关闭" : "开启"
      }自动翻页`;
    });
    navBar?.append(toggleAutoPager);
    if (
      (settings.enable_main_auto_pager && !isForum) ||
      (settings.enable_forum_auto_pager && isForum)
    )
      autoPagerOB.observe(obTarget);
  }

  function loadNextPage(nextPageURL) {
    fetch(nextPageURL)
      .then((resp) => resp.text())
      .then((text) => {
        let doc = convertTextToDOM(text);
        const comments = doc.querySelectorAll(CURRENT_SETTING.itemDomSelector);
        //追加内容之前对每个item的预处理回调
        if (CURRENT_SETTING.nodeBeforeAddCall) {
          comments.forEach(CURRENT_SETTING.nodeBeforeAddCall);
        }
        let postlist = document.querySelector(CURRENT_SETTING.listDomSelector);
        //用新页面的分页DOM元素来替换上一页的分页DOM
        document.querySelector(CURRENT_SETTING.pagerDomSelector).innerHTML =
          doc.querySelector(CURRENT_SETTING.pagerDomSelector).innerHTML;
        postlist?.append(...Array.from(comments));
        //追加内容之后的处理回调
        if (CURRENT_SETTING.nodeAfterAddCall) {
          CURRENT_SETTING.nodeAfterAddCall.call();
        }
      })
      .catch((e) => {
        console.log("加载内容出错");
        return;
      });
  }

  function convertTextToDOM(text) {
    const parser = new DOMParser();
    return parser.parseFromString(text, "text/html");
  }

  function overrideForumStyle() {
    //只对论坛页面生效
    if (!isForum) return;

    if (PAGE_MOD === "viewthread") {
      //将上传图片和发表评论组合到一起
      //#Form1.parentElement 表示的是上传图片附件的DOM元素
      let f_pst = document.querySelector("#f_pst");
      f_pst?.append(document.querySelector("#Form1").parentElement);
      let firstPost = document.querySelector(".nthread_firstpost"); //#1楼的帖子
      //将回复帖子的Form移动到1楼下面
      firstPost?.insertAdjacentElement("afterend", f_pst);

      //增加一个快速定位回复框的按钮
      let goReply = document.createElement("a");
      goReply.id = "goReply";
      goReply.href = "javascript:void(0)";
      goReply.addEventListener("click", () => {
        f_pst.scrollIntoView();
      });
      goReply.style.cssText = `
        display: block;
        position: fixed;
        bottom: 370px;
        width: 50px;
        height: 50px;
        background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAD1BMVEUAAADvSETxSETySEPxSEOfb+sGAAAABHRSTlMAQIC/o1TdDAAAAGJJREFUeNrty4EGgEAQBuFp/3v/Zw4r54rVL6LuBgx8tDsFvQW+DiLT8BUgi+EfgdypQd0CPwKKou0KRN0ZCA8IDwgPiKNodQmEB4QHhAl4D9TJBcgFhAW6wBW4AlfgClyxA0shFWNNOTW7AAAAAElFTkSuQmCC) no-repeat 50% 50%;
        background-color: #fff;
        background-size: 28px 28px;
      `;
      document.querySelector(".biaoqi-fix-area").appendChild(goReply);
    }

    let styleRules = `
      #goReply:hover{background-blend-mode: screen;background-color: #F14843 !important;}
      #toptb{position: sticky; top: 0; z-index: 99;}
    `;

    // 如果不想显示签名图,可以解开下面这一行代码
    // styleRules+=".plc > .sign { display:none; }"

    if (settings.enable_forum_style_override) {
      styleRules += `
        .psth {margin:1em 0 1em 0px}
        .pls .avatar img { border-radius:50%; height: 50px; }
        tr .plm { padding-top: 10px !important }
        .hin .pob { padding-bottom: 4px; padding-top: 4px; }
        .t_fsz { min-height: auto; }
        .pct { padding-bottom: 0em; }
        #postlist .ad .pls, #postlist .ad .plc { display: none; }
        .pcb .cm .psth { margin-top: 0px; }
        .pcb .cm .psth { margin-bottom: 10px; }
        .t_f, .t_f td { line-height: 1.6; }
        .pcb .psth { font-size: 14px !important; font-weight: 500; }
        #p_btn { padding:0 0 10px 0; }
        .jav-footer { display: none; }        
        #postlist { padding: 0 20px 0px 20px; }
        a[rel="nofollow"]{display:none;}        
        .ct2 .mn {margin-bottom: 0;}
      `;
    }
    GM_addStyle(styleRules);
  }
})();