NodeSeek+

load post detail information is automatically loaded when the button is clicked

目前为 2023-11-22 提交的版本。查看 最新版本

// ==UserScript==
// @name         NodeSeek+
// @namespace    http://tampermonkey.net/
// @version      0.3.1
// @description  load post detail information is automatically loaded when the button is clicked
// @author       tsd
// @match        https://www.nodeseek.com/*
// @match        https://www.nodeseek.com/*
// @icon         https://www.nodeseek.com/static/image/favicon/android-chrome-192x192.png
// @license      GPLv3
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_removeValueChangeListener
// @grant        GM_addValueChangeListener
// @grant    GM_registerMenuCommand
// @grant    GM_unregisterMenuCommand

// ==/UserScript==

(function () {
  "use strict";
  console.log("script");

  //GM_setValue
  //allCollectionData   收藏的post的id列表
  //checkInTime         签到的时间
  //isRandom            是否摸奖签到
  //isAuto              是否自动签到

  //默认抽奖
  if (GM_getValue("isRandom") === undefined) {
    GM_setValue("isRandom", true);
  }
  //默认手动
  if (GM_getValue("isAuto") === undefined) {
    GM_setValue("isAuto", false);
  }

  //注册(不可用)菜单
  let switchCheckType;
  let switchAutoType;
  let listenerswitchCheckType;
  let listenerswitchAutoType;
  function createMenu() {
    switchCheckType = GM_registerMenuCommand(
      GM_getValue("isRandom") === true
        ? "切换签到模式,当前为随机"
        : "切换签到模式,当前为固定",
      menuRandomClick
    );
    switchAutoType = GM_registerMenuCommand(
      GM_getValue("isAuto") === true
        ? "切换自动模式,当前为自动"
        : "切换自动模式,当前为手动",
      menuAutoClick
    );
    //是否有变动
    listenerswitchCheckType = GM_addValueChangeListener(
      "isRandom",
      function (name, old_value, new_value, remote) {
        if (old_value !== new_value) {
          alert(new_value === true ? "已切换为随机" : "已切换为固定");
        }
      }
    );
    listenerswitchAutoType = GM_addValueChangeListener(
      "isAuto",
      function (name, old_value, new_value, remote) {
        if (old_value !== new_value) {
          alert(new_value === true ? "已切换为自动" : "已切换为手动");
        }
      }
    );
  }
  //菜单点击刷新签到信息
  function menuRandomClick() {
    GM_unregisterMenuCommand(switchCheckType);
    GM_getValue("isRandom") === true
      ? GM_setValue("isRandom", false)
      : GM_setValue("isRandom", true);
    //重新注册(不可用)
    GM_removeValueChangeListener(listenerswitchCheckType);
    GM_removeValueChangeListener(listenerswitchAutoType);
    createMenu();
    checkIn();
  }
  //菜单点击刷新自动信息
  function menuAutoClick() {
    GM_unregisterMenuCommand(switchAutoType);
    GM_getValue("isAuto") === true
      ? GM_setValue("isAuto", false)
      : GM_setValue("isAuto", true);
    //重新注册(不可用)
    GM_removeValueChangeListener(listenerswitchCheckType);
    GM_removeValueChangeListener(listenerswitchAutoType);
    createMenu();
    checkIn();
  }

  // 检查是否登陆
  let loginStatus = false;
  if (document.querySelector("#nsk-right-panel-container>.user-card")) {
    loginStatus = true;
  }

  if (loginStatus) {
    //注册(不可用)油猴菜单
    createMenu();
    //处理登录(不可用);
    checkIn();
    //维护一个全部的收藏id列表
    if (GM_getValue("allCollectionData") === undefined) {
      loadUntilEmpty();
    }
  } else {
    //清除收藏的post的id列表
    //GM_deleteValue("allCollectionData");
    //清除签到的时间
    //GM_deleteValue("checkInTime");
    //清除签到方式
    //GM_deleteValue("isRandom");
    //清除自动方式
    //GM_deleteValue("isAuto");
  }

  //签到判断
  function checkIn() {
    let timeNow =
      new Date().getFullYear() +
      "/" +
      (new Date().getMonth() + 1) +
      "/" +
      new Date().getDate();
    let oldTime = GM_getValue("checkInTime");
    if (!oldTime || oldTime !== timeNow) {
      //允许执行签到
      if (GM_getValue("isAuto") === true) {
        //执行自动签到
        getChicken(GM_getValue("isRandom")).then((responseData) => {
          if (responseData.success === true) {
            //签到成功之后存下时间
            GM_setValue("checkInTime", timeNow);
            console.log(`[NodeSeek] 签到:`, responseData.message);
          } else if (responseData.message === "今天已完成签到,请勿重复操作") {
            //存下时间
            GM_setValue("checkInTime", timeNow);
            console.log(`[NodeSeek] 签到:`, responseData.message);
          } else {
            console.error("Error in checkIn:", error);
          }
        });
      } else {
        //执行手动签到
        //处理按钮
        let right_panel = document.querySelector("#nsk-right-panel-container");
        let new_check = document.createElement("div");
        let publish_btn = document.querySelector(".btn.new-discussion");
        let publish_btn_parent = publish_btn.parentNode;
        new_check.innerHTML = '<a class="btn new-discussion">签到</a>';
        //展示签到按钮
        right_panel.insertBefore(new_check, publish_btn_parent);
        setupCursorStyle(new_check);
        new_check.onclick = function () {
          getChicken(GM_getValue("isRandom")).then((responseData) => {
            console.log(responseData.message);
            if (responseData.success === true) {
              //签到成功之后存下时间
              GM_setValue("checkInTime", timeNow);
              //弹窗示意多少鸡腿
              alert(responseData.message);
              //隐藏
              new_check.style.display = "none";
            } else if (
              responseData.message === "今天已完成签到,请勿重复操作"
            ) {
              //存下时间
              GM_setValue("checkInTime", timeNow);
              alert(responseData.message);
              //隐藏
              new_check.style.display = "none";
            } else {
              console.error("Error in checkIn:", error);
            }
          });
        };
      }
    } else {
      //返回已经签到按钮或隐藏
    }
  }

  // 签到
  async function getChicken(random) {
    const url = "https://www.nodeseek.com/api/attendance";
    const data = {
      random: random,
    };
    try {
      const responseData = await postData(url, data);
      return responseData;
    } catch (error) {
      console.error("Error in getChicken:", error);
      return null;
    }
  }

  //查看帖子中的回复消息
  initializePage();

  // 定义一个函数来发送GET请求
  async function loadData(page) {
    const url = `https://www.nodeseek.com/api/statistics/list-collection?page=${page}`;
    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      return data;
    } catch (error) {
      console.error("Error:", error);
      return null;
    }
  }
  async function loadUntilEmpty(page = 1) {
    //收藏列表数组
    let allCollectionData = [];
    while (true) {
      const data = await loadData(page);
      data.collections.forEach((item) => {
        // 将获取到的数据加到数组中
        allCollectionData.push(item.post_id);
      });
      // 如果没有获取到数据或获取到的数据为空,停止加载
      if (!data || data.collections.length === 0) {
        //丢进去方便存取
        GM_setValue("allCollectionData", allCollectionData);
        break;
      }
      page++;
    }
  }

  function initializePage() {
    let lists = document.querySelectorAll(".post-list");
    lists.forEach((list) => {
      let items = list.childNodes;
      items.forEach((element) => {
        setupPostItem(element);
      });
    });
  }

  function setupPostItem(element) {
    let post_item = element.querySelector(".post-title>a");
    let new_div = document.createElement("span");
    new_div.className = "info-triganle";
    new_div.innerHTML = '<span class="triangle">▼</span>';
    element.querySelector(".post-info").append(new_div);
    setupCursorStyle(new_div);
    new_div.onclick = function () {
      togglePostContent(post_item, element, new_div);
    };
  }

  function togglePostContent(post_item, element, new_div) {
    let id = post_item.href.replace("https://www.nodeseek.com", "");
    let content = document.getElementById(id);
    if (content) {
      toggleDisplay(content, new_div);
    } else {
      new_div.firstElementChild.innerText = "○";
      document.body.style.cursor = "wait";
      new_div.firstElementChild.className = "content-loaded";
      fetchContent(post_item.href, element, (contents, targetEle) => {
        insertContentAfter(contents, targetEle);
        loadNextPage(contents, targetEle, 1);
        new_div.firstElementChild.innerText = "▲";
        document.body.style.cursor = "auto";
      });
    }
  }
  //显隐箭头
  function toggleDisplay(content, new_div) {
    if (content.style.display === "none") {
      content.style.display = "block";
      new_div.firstElementChild.innerText = "▲";
    } else {
      content.style.display = "none";
      new_div.firstElementChild.innerText = "▼";
    }
  }
  //获取div框中的内容
  //TODO:重构一下这坨狗屎
  function fetchContent(url, targetEle, callback) {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.onload = function () {
      if (xhr.status === 200) {
        const tempContainer = document.createElement("div");
        tempContainer.innerHTML = xhr.responseText;
        let contents = document.createElement("div");
        contents.id = url.replace("https://www.nodeseek.com", "");
        contents.className = "content-div";

        //content
        let post_contents = tempContainer.querySelectorAll(".post-content");
        contents.innerHTML += '<div class="post-content-box"></div>';
        //menu
        let colloct = contents.firstChild;
        colloct.innerHTML +=
          //TODO:免费鸡腿和like处理
          '<div data-v-372de460="" class="comment-menu">' +
          // +'<div data-v-372de460="" title="加鸡腿" class="menu-item"><svg data-v-372de460="" class="iconpark-icon"><use data-v-372de460="" href="#chicken-leg"></use></svg><span data-v-372de460="">0</span></div>'
          //  +'<div data-v-372de460="" title="反对" class="menu-item"><svg data-v-372de460="" class="iconpark-icon"><use data-v-372de460="" href="#bad-one"></use></svg><span data-v-372de460="">0</span></div> '
          '<div data-v-372de460="" title="收藏" class="menu-item"><svg data-v-372de460="" class="iconpark-icon"><use data-v-372de460="" href="#star-6negdgdk"></use></svg></div>' +
          //  +'<div data-v-372de460="" class="menu-item"><svg data-v-372de460="" class="iconpark-icon"><use data-v-372de460="" href="#quote"></use></svg><span data-v-372de460="">引用</span></div> <!----> '
          //  +'<div data-v-372de460="" class="menu-item"><svg data-v-372de460="" class="iconpark-icon"><use data-v-372de460="" href="#back"></use></svg><span data-v-372de460="">回复</span></div> <!---->
          "</div>";
        //找收藏的id
        let regex = /\/post-(\d+)-1/;
        let match = contents.id.match(regex);
        //先将就着用
        let post_id;
        let is_collected;
        let icon;
        icon = colloct.firstElementChild.querySelector(".menu-item");
        if (match != null) {
          //当前展开的post的id
          post_id = match[1];
          post_id = parseInt(post_id);
          is_collected = GM_getValue("allCollectionData").some(
            (item) => item === post_id
          );
          //判断是否已收藏
          if (is_collected) {
            icon.style.color = "red";
          }
        }
        setupCursorStyle(icon);
        icon.onclick = function () {
          colloctContent(post_id, colloct);
        };
        post_contents.forEach((e) => {
          contents.firstChild.appendChild(e.parentElement);
        });

        if (callback && typeof callback === "function") {
          callback(contents, targetEle);
        }
      } else {
        console.info("加载完毕");
      }
    };
    xhr.onerror = function () {
      console.error("Network error occurred while loading content.");
    };
    xhr.send();
  }
  //帖子的收藏处理
  function colloctContent(post_id, colloct) {
    let icon = colloct.firstElementChild.querySelector(".menu-item");
    if (icon.style.color === "red") {
      //取消收藏处理
      let result = confirm("您确定要取消收藏吗?");
      if (result) {
        collection_del("remove", post_id).then((success) => {
          if (success === true) {
            icon.style.color = "";
            //维护一个全部的收藏id列表
            loadUntilEmpty();
          }
        });
      }
    } else {
      //收藏帖子
      collection_add("add", post_id).then((success) => {
        if (success === true) {
          icon.style.color = "red";
          //维护一个全部的收藏id列表
          loadUntilEmpty();
        }
      });
    }
  }
  //收藏方法
  async function collection_add(action_type, post_id) {
    const url = "https://www.nodeseek.com/api/statistics/collection";
    const data = {
      action: action_type,
      postId: post_id,
    };
    try {
      const responseData = await postData(url, data);
      if (responseData && responseData.success === true) {
        alert("收藏成功!");
      }
      //   else if (responseData && responseData.success === false) {
      //     alert("你已经收藏过了!");
      //   }
      return responseData ? responseData.success : null;
    } catch (error) {
      console.error("Error in collection_add:", error);
      return null;
    }
  }

  //取消收藏方法
  async function collection_del(action_type, post_id) {
    const url = "https://www.nodeseek.com/api/statistics/collection";
    const data = {
      action: action_type,
      postId: post_id,
    };
    try {
      const responseData = await postData(url, data);
      if (responseData && responseData.success === true) {
        alert("取消收藏成功!");
      }
      return responseData ? responseData.success : null;
    } catch (error) {
      console.error("Error in collection_del:", error);
      return null;
    }
  }

  //POST请求
  async function postData(url = "", data = {}) {
    try {
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(data),
      });
      const responseData = await response.json();
      return responseData;
    } catch (error) {
      console.error("Error in postData:", error);
    }
  }

  function insertContentAfter(content, targetEle) {
    let ul = targetEle.parentNode;
    ul.insertBefore(content, targetEle.nextSibling);
  }

  function loadNextPage(contentDiv, targetEle, currentPage) {
    let nextPage = currentPage + 1;
    let nextPageUrl = targetEle
      .querySelector(".post-title>a")
      .href.replace(/(\d+)$/, nextPage);
    fetchContent(nextPageUrl, targetEle, (nextContents, targetEle) => {
      let postContentBox = contentDiv.querySelector(".post-content-box");
      if (nextContents.querySelector(".post-content")) {
        let nextPostContents = nextContents.querySelectorAll(".post-content");
        nextPostContents.forEach((e) => {
          postContentBox.appendChild(e.parentElement);
        });
        // 递归调用以加载后续页面,延迟1秒
        setTimeout(() => {
          loadNextPage(contentDiv, targetEle, nextPage);
        }, 1000);
      }
    });
  }

  function setupCursorStyle(element) {
    element.addEventListener("mouseover", function () {
      document.body.style.cursor = "pointer";
    });
    element.addEventListener("mouseout", function () {
      document.body.style.cursor = "auto";
    });
  }

  let css = `
     .content-div {
        height: 600px;
        padding: 20px;
        margin: 10px auto;
        border: 1px solid gray;
        border-radius: 10px;
        overflow: scroll;
    }

    .post-content-box {
        border-bottom: 2px dashed gray;
        padding-bottom: 10px;
        margin-bottom: 10px;
    }

    .triangle {
        font-size: medium;
        color: gray;
    }
    .info-triganle{
        position: absolute;
        right: 54px;
    }

    .content-loaded {
        font-size: medium;
        color: red;
    }
    ::-webkit-scrollbar {
        width: 6px;
        height: 6px;
    }
    ::-webkit-scrollbar-track {
        border-radius: 3px;
        background: rgba(0,0,0,0.06);
        -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.08);
    }
    ::-webkit-scrollbar-thumb {
        border-radius: 3px;
        background: rgba(0,0,0,0.12);
        -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.2);
    }

    `;
  GM_addStyle(css);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址