NGA Auto Pagerize

简单的自动翻页

当前为 2021-08-23 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        NGA Auto Pagerize
// @namespace   https://greasyfork.org/users/263018
// @version     1.2.0
// @author      snyssss
// @description 简单的自动翻页

// @match       *://bbs.nga.cn/*
// @match       *://ngabbs.com/*
// @match       *://nga.178.com/*

// @grant       GM_registerMenuCommand
// @grant       GM_setValue
// @grant       GM_getValue
// @noframes
// ==/UserScript==

((ui, n = {}, api = {}) => {
  if (!ui) return;

  // KEY
  const ATTACHMENT_STYLE_ENABLE_KEY = "ATTACHMENT_STYLE_ENABLE";
  const FORUM_NAME_ENABLE_KEY = "FORUM_NAME_ENABLE_KEY";

  // 附件样式
  const attachmentStyleEnable =
    GM_getValue(ATTACHMENT_STYLE_ENABLE_KEY) || false;

  // 版面名称
  const forumNameEnable = GM_getValue(FORUM_NAME_ENABLE_KEY) || false;

  // 钩子
  const hookFunction = (object, functionName, callback) => {
    ((originalFunction) => {
      object[functionName] = function () {
        const returnValue = originalFunction.apply(this, arguments);

        callback.apply(this, [returnValue, originalFunction, arguments]);

        return returnValue;
      };
    })(object[functionName]);
  };

  // 翻页
  if (ui.pageBtn) {
    const delay = (interval) =>
      new Promise((resolve) => setTimeout(resolve, interval));

    const retry = async (fn, retriesLeft = 10, interval = 160) => {
      try {
        return await fn();
      } catch (error) {
        await delay(interval);

        if (retriesLeft > 0) {
          return await retry(fn, retriesLeft - 1, interval);
        }
      }
    };

    const execute = (() => {
      const observer = new IntersectionObserver((entries) => {
        if (entries.find((item) => item.isIntersecting)) {
          retry(() => {
            if (ui.loadReadHidden.lock) {
              throw new Error();
            }

            ui.loadReadHidden(0, 2);
          });
        }
      });

      return () => {
        const anchor = document.querySelector('[title="加载下一页"]');

        if (anchor) {
          observer.observe(anchor);
        } else {
          observer.disconnect();
        }
      };
    })();

    hookFunction(ui, "pageBtn", execute);

    execute();
  }

  // 移除重复内容
  if (ui.topicArg) {
    const execute = () => {
      if (location.search.indexOf("searchpost=1") > 0) {
        return;
      }

      ui.topicArg.data = ui.topicArg.data.reduce(
        (accumulator, currentValue) => {
          const index = accumulator.findIndex(
            (item) => item[8] === currentValue[8]
          );

          if (index < 0) {
            return [...accumulator, currentValue];
          }

          currentValue[0].closest("TBODY").remove();

          return accumulator;
        },
        []
      );
    };

    hookFunction(ui.topicArg, "loadAll", execute);

    execute();
  }

  // 附件样式
  if (ui.topicArg && attachmentStyleEnable) {
    const execute = () => {
      const elements = document.querySelectorAll('[title="主题中有附件"]');

      elements.forEach((element) => {
        element.className = "block_txt white nobr vertmod";
        element.style = "background-color: #BD7E6D";
        element.innerHTML = "附件";
      });
    };

    hookFunction(ui.topicArg, "loadAll", execute);

    execute();
  }

  // 版面名称
  if (ui.topicArg && forumNameEnable) {
    if (!n.doRequest || !api.indexForumList) {
      return;
    }

    class Queue {
      execute(task) {
        task(this.data).finally(() => {
          if (this.waitingQueue.length) {
            const next = this.waitingQueue.shift();

            this.execute(next);
          } else {
            this.isRunning = false;
          }
        });
      }

      enqueue(task) {
        if (this.initialized === false) {
          this.initialized = true;
          this.init();
        }

        if (this.isRunning) {
          this.waitingQueue.push(task);
        } else {
          this.isRunning = true;

          this.execute(task);
        }
      }

      init() {
        this.enqueue(async () => {
          this.data = await new Promise((resolve) => {
            try {
              n.doRequest({
                u: api.indexForumList(),
                f: function (res) {
                  if (res.data) {
                    resolve(res.data[0]);
                  } else {
                    resolve({});
                  }
                },
              });
            } catch (e) {
              resolve({});
            }
          });
        });
      }

      constructor() {
        this.waitingQueue = [];
        this.isRunning = false;

        this.initialized = false;
      }
    }

    const deepSearch = (content = {}, fid = 0) => {
      const children = Object.values(content);

      for (let i = 0; i < children.length; i += 1) {
        const item = children[i];

        if (item.fid === fid) {
          return item;
        }

        if (item.content) {
          const result = deepSearch(item.content || [], fid);

          if (result !== null) {
            return result;
          }
        }
      }

      return null;
    };

    const queue = new Queue();

    const execute = () => {
      if (location.search.indexOf("authorid") < 0) {
        return;
      }

      ui.topicArg.data.forEach((item) => {
        const parentNode = item[1].closest(".c2");

        if (parentNode.querySelector(".titleadd2") === null) {
          const fid = item[7];

          queue.enqueue(async (data) => {
            const result = deepSearch(data.all, parseInt(fid, 10));

            if (result) {
              const anchor = parentNode.querySelector(".topic_content");

              const title = document.createElement("SPAN");

              title.className = "titleadd2";
              title.innerHTML = `<a href="/thread.php?fid=${fid}" class="silver">[${result.name}]</a>`;

              if (anchor) {
                anchor.before(title);
              } else {
                parentNode.append(title);
              }
            }
          });
        }
      });
    };

    hookFunction(ui.topicArg, "loadAll", execute);

    execute();
  }

  if (attachmentStyleEnable) {
    GM_registerMenuCommand("附件样式:启用", () => {
      GM_setValue(ATTACHMENT_STYLE_ENABLE_KEY, false);
      location.reload();
    });
  } else {
    GM_registerMenuCommand("附件样式:禁用", () => {
      GM_setValue(ATTACHMENT_STYLE_ENABLE_KEY, true);
      location.reload();
    });
  }

  if (forumNameEnable) {
    GM_registerMenuCommand("版面名称:启用", () => {
      GM_setValue(FORUM_NAME_ENABLE_KEY, false);
      location.reload();
    });
  } else {
    GM_registerMenuCommand("版面名称:禁用", () => {
      GM_setValue(FORUM_NAME_ENABLE_KEY, true);
      location.reload();
    });
  }
})(commonui, __NUKE, __API);