KamePT Badge Trial Tool

Try badges before purchase on KamePT

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         KamePT Badge Trial Tool
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Try badges before purchase on KamePT
// @author       Your name
// @match        https://kamept.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
  "use strict";

  // 从本地存储加载试用的徽章配置
  const TRIAL_BADGES_KEY = "kame_trial_badges";
  let trialBadges = JSON.parse(localStorage.getItem(TRIAL_BADGES_KEY) || "[]");

  // 创建单个徽章元素
  function createBadgeElement(badgeConfig) {
    const badge = document.createElement("img");
    badge.src = badgeConfig.src;
    badge.title = badgeConfig.title;
    badge.className = "nexus-username-medal preview";
    badge.style.maxHeight = "11px";
    badge.style.maxWidth = "11px";
    badge.style.marginLeft = "2pt";
    return badge;
  }

  // 添加试用按钮到勋章商店页面
  function addTrialButtons() {
    if (!window.location.href.includes("medal.php")) return;

    // 获取表格
    const table = document.querySelector('table[border="1"]');
    if (!table) return;

    // 获取表头行
    const headerRow = table.querySelector("thead tr");
    if (!headerRow) return;

    // 检查是否已经添加了试用列
    if (!headerRow.querySelector(".trial-header")) {
      // 添加"试用"列标题
      const trialHeader = document.createElement("td");
      trialHeader.className = "colhead trial-header";
      trialHeader.textContent = "试用";
      headerRow.appendChild(trialHeader);
    }

    // 为每个勋章行添加试用按钮
    const medalRows = table.querySelectorAll("tbody tr");
    medalRows.forEach((row) => {
      // 检查是否已经添加了试用按钮
      if (row.querySelector(".trial-button")) return;

      const imgElement = row.querySelector("td:first-child img");
      if (!imgElement) return;

      // 检查是否已购买
      const buyButton = row.querySelector(
        'input[type="button"][value="已经购买"]'
      );
      const isAlreadyBought = buyButton !== null;

      const badgeConfig = {
        src: imgElement.src,
        title: row.querySelector("h1")?.textContent || "勋章",
      };

      const trialCell = document.createElement("td");
      const trialButton = document.createElement("input");
      trialButton.type = "button";

      if (isAlreadyBought) {
        trialButton.value = "已拥有";
        trialButton.disabled = true;
        trialButton.style.opacity = "0.5";
      } else {
        trialButton.value = trialBadges.some((b) => b.src === badgeConfig.src)
          ? "取消试用"
          : "试用";
        trialButton.onclick = () => toggleTrialBadge(badgeConfig);
      }

      trialButton.className = "trial-button";
      trialButton.style.cursor = isAlreadyBought ? "not-allowed" : "pointer";
      trialButton.style.padding = "2px 8px";

      trialCell.appendChild(trialButton);
      row.appendChild(trialCell);
    });
  }

  // 切换徽章的试用状态
  function toggleTrialBadge(badgeConfig) {
    const index = trialBadges.findIndex((b) => b.src === badgeConfig.src);
    if (index === -1) {
      trialBadges.push(badgeConfig);
    } else {
      trialBadges.splice(index, 1);
    }

    // 保存到本地存储
    localStorage.setItem(TRIAL_BADGES_KEY, JSON.stringify(trialBadges));

    // 刷新页面以更新显示
    location.reload();
  }

  // 获取当前用户名
  function getCurrentUsername() {
    // 从页面顶部的info tab获取用户名
    const userLink = document.querySelector('#info_block a[class$="_Name"] b');
    return userLink ? userLink.textContent : "";
  }

  // 处理用户详情页面的勋章展示区域
  function processUserDetailsMedals() {
    const medalContainer = document.querySelector(
      'form > div[style*="display: flex"]'
    );
    if (!medalContainer) return;

    // 检查是否为其他用户的页面
    const pageUsername = document.querySelector(
      "h1 > span.nowrap > b"
    )?.textContent;
    const currentUsername = getCurrentUsername();

    if (!pageUsername || !currentUsername || pageUsername !== currentUsername) {
      console.log("当前为其他用户页面,跳过添加试用徽章");
      return;
    }

    // 添加保存按钮禁用逻辑
    const saveButton = document.getElementById("save-user-medal-btn");
    if (saveButton) {
      saveButton.disabled = trialBadges.length > 0;
      saveButton.title = trialBadges.length > 0 ? "试用期间禁止保存设置" : "";
      saveButton.style.opacity = trialBadges.length > 0 ? "0.5" : "1";
      saveButton.style.cursor =
        trialBadges.length > 0 ? "not-allowed" : "pointer";
    }

    // 为每个试用徽章创建展示卡片
    trialBadges.forEach((badgeConfig) => {
      // 检查是否已经存在该徽章
      const existingCard = Array.from(
        medalContainer.querySelectorAll("img.preview")
      ).find((img) => img.src === badgeConfig.src);

      if (!existingCard) {
        // 创建新的勋章卡片容器
        const cardDiv = document.createElement("div");
        cardDiv.style.display = "flex";
        cardDiv.style.flexDirection = "column";
        cardDiv.style.justifyContent = "space-between";
        cardDiv.style.marginRight = "10px";

        // 创建勋章图片容器
        const imgContainer = document.createElement("div");
        const img = document.createElement("img");
        img.src = badgeConfig.src;
        img.title = badgeConfig.title;
        img.className = "preview";
        img.style.maxHeight = "120px";
        img.style.maxWidth = "120px";
        imgContainer.appendChild(img);

        // 创建勋章信息容器
        const infoContainer = document.createElement("div");
        infoContainer.style.display = "flex";
        infoContainer.style.flexDirection = "column";
        infoContainer.style.alignItems = "flex-start";

        const myBadgeBtn = document.querySelector('input[type="button"][value="我的勋章"]');
        if (myBadgeBtn) {
          myBadgeBtn.parentElement.parentElement.remove();
        }

        // 组装卡片
        cardDiv.appendChild(imgContainer);
        // cardDiv.appendChild(infoContainer);

        // 插入到第一个保存按钮前
        const saveButtonDiv = medalContainer.querySelector(
          "div:has(#save-user-medal-btn)"
        );
        if (saveButtonDiv) {
          medalContainer.insertBefore(cardDiv, saveButtonDiv);
        } else {
          medalContainer.appendChild(cardDiv);
        }
      }
    });
  }

  // 添加试用中的徽章到用户名旁
  function addTrialBadges() {
    // 获取当前用户名
    const currentUsername = getCurrentUsername();
    if (!currentUsername) return;

    // 处理用户详情页面的标题
    function processUserDetailsTitle() {
      const titleUsername = document.querySelector("h1 > span.nowrap > b");
      if (titleUsername && titleUsername.textContent === currentUsername) {
        const container = titleUsername.closest(".nowrap");
        if (!container) return;

        // 查找现有徽章
        const existingBadges = Array.from(
          container.querySelectorAll("img.nexus-username-medal-big")
        );
        let lastBadge =
          existingBadges[existingBadges.length - 1] || titleUsername;

        // 添加试用徽章
        trialBadges.forEach((badgeConfig) => {
          const existingTrialBadge = existingBadges.find(
            (img) => img.src === badgeConfig.src
          );

          if (!existingTrialBadge) {
            const newBadge = document.createElement("img");
            newBadge.src = badgeConfig.src;
            newBadge.title = badgeConfig.title;
            newBadge.className = "nexus-username-medal-big preview";
            newBadge.style.maxHeight = "16px";
            newBadge.style.maxWidth = "16px";
            newBadge.style.marginLeft = "4pt";
            lastBadge.parentNode.insertBefore(newBadge, lastBadge.nextSibling);
            lastBadge = newBadge;
          }
        });
      }
    }

    // 处理页面上已有的用户名元素
    function processExistingElements() {
      const currentUsername = getCurrentUsername();
      if (!currentUsername) return;

      const userSpans = document.querySelectorAll('span.nowrap');
      userSpans.forEach(span => {
        const userNameElement = span.querySelector('a[class$="_Name"] b');
        if (userNameElement && userNameElement.textContent === currentUsername) {
          // 查找span后面的所有兄弟节点
          let nextNode = span.nextSibling;
          let foundSpecialPattern = false;

          while (nextNode) {
            if (nextNode.nodeType === Node.TEXT_NODE) {
              if (nextNode.textContent === ')' + '\u00A0\u00A0') {
                // 找到 ")  " 模式
                foundSpecialPattern = true;
                
                // 创建新的文本节点
                const closeBracket = document.createTextNode(')');
                const spaceNode = document.createTextNode('\u00A0\u00A0');
                
                // 替换原节点为 ")"
                nextNode.parentNode.replaceChild(closeBracket, nextNode);
                
                // 添加试用徽章和空格
                let lastInsertedNode = closeBracket;
                trialBadges.forEach(badgeConfig => {
                  const existingBadge = Array.from(span.querySelectorAll('img.nexus-username-medal'))
                    .find(img => img.src === badgeConfig.src);
                  
                  if (!existingBadge) {
                    const newBadge = createBadgeElement(badgeConfig);
                    lastInsertedNode.parentNode.insertBefore(newBadge, lastInsertedNode.nextSibling);
                    lastInsertedNode = newBadge;
                  }
                });
                
                // 在最后一个徽章后添加空格
                lastInsertedNode.parentNode.insertBefore(spaceNode, lastInsertedNode.nextSibling);
                break;
              } else if (nextNode.textContent === ')') {
                // 找到单独的 ")" 节点,继续查找 "  "
                let spaceNode = nextNode.nextSibling;
                while (spaceNode) {
                  if (spaceNode.nodeType === Node.TEXT_NODE && spaceNode.textContent === '\u00A0\u00A0') {
                    foundSpecialPattern = true;
                    // 在 "  " 前添加所有试用徽章
                    trialBadges.forEach(badgeConfig => {
                      const existingBadge = Array.from(span.querySelectorAll('img.nexus-username-medal'))
                        .find(img => img.src === badgeConfig.src);
                      
                      if (!existingBadge) {
                        const newBadge = createBadgeElement(badgeConfig);
                        spaceNode.parentNode.insertBefore(newBadge, spaceNode);
                      }
                    });
                    break;
                  }
                  spaceNode = spaceNode.nextSibling;
                }
                if (foundSpecialPattern) break;
              }
            }
            nextNode = nextNode.nextSibling;
          }

          // 如果没有找到特殊模式,使用原有逻辑
          if (!foundSpecialPattern) {
            const targetNode = Array.from(span.childNodes)
              .find(node => node.nodeType === Node.TEXT_NODE && node.textContent === '\u00A0\u00A0');

            trialBadges.forEach(badgeConfig => {
              const existingBadge = Array.from(span.querySelectorAll('img.nexus-username-medal'))
                .find(img => img.src === badgeConfig.src);
              
              if (!existingBadge) {
                const newBadge = createBadgeElement(badgeConfig);
                if (targetNode) {
                  targetNode.parentNode.insertBefore(newBadge, targetNode);
                } else {
                  span.appendChild(newBadge);
                }
              }
            });
          }
        }
      });
    }

    // 初始处理
    processUserDetailsTitle();
    processExistingElements();

    // 处理用户详情页面的勋章展示区域
    processUserDetailsMedals();

    // 监听动态加载的内容
    const observeTargets = [
      document.getElementById("peerlist"), // 做种用户列表
      document.querySelector(".text"), // 论坛内容区域
    ];

    observeTargets.forEach((target) => {
      if (target) {
        const observer = new MutationObserver((mutations) => {
          mutations.forEach((mutation) => {
            if (mutation.addedNodes.length > 0) {
              processExistingElements();
            }
          });
        });

        observer.observe(target, {
          childList: true,
          subtree: true,
        });
      }
    });
  }

  // 添加清理预览图片的功能
  function fixPreviewCleanup() {
    // 查找预览图片元素
    const previewImg = document.getElementById("nexus-preview");
    if (!previewImg) return;

    // 监听所有徽章的鼠标移出事件
    document.addEventListener(
      "mouseover",
      (e) => {
        if (!e.target.matches("img.nexus-username-medal")) {
          // 如果鼠标不在任何徽章上,隐藏预览
          previewImg.style.display = "none";
        }
      },
      true
    );

    // 监听页面滚动,确保预览不会停留
    window.addEventListener(
      "scroll",
      () => {
        previewImg.style.display = "none";
      },
      { passive: true }
    );

    // 监听鼠标离开页面
    document.addEventListener("mouseout", (e) => {
      if (!e.relatedTarget) {
        previewImg.style.display = "none";
      }
    });
  }

  // 初始化
  function init() {
    addTrialButtons();
    addTrialBadges();
    fixPreviewCleanup();
  }

  // 页面加载完成后运行
  window.addEventListener("load", init);
})();