让 ChatGPT 和 Grok 看起来像 Qwen

让 ChatGPT 和 Grok 网页版使用起来看起来像 qwen.ai

// ==UserScript==
// @name         让 ChatGPT 和 Grok 看起来像 Qwen
// @namespace    npm/vite-plugin-monkey
// @version      0.0.1
// @description  让 ChatGPT 和 Grok 网页版使用起来看起来像 qwen.ai
// @match        https://chatgpt.com/*
// @match        https://grok.com/*
// ==/UserScript==

(function () {
  'use strict';

  const getElements$1 = (node, selector, isSelf = false) => {
    if (isSelf && node.matches(selector)) {
      return [node];
    }
    return Array.from(node.querySelectorAll(selector));
  };
  const initTitle = () => {
    if (document.title === "ChatGPT") {
      document.title = "Qwen";
      console.log("Updated page title");
    }
  };
  const updateHeaderText = (node) => {
    const headerTexts = getElements$1(node, ".text-page-header");
    headerTexts.forEach((header) => {
      const deepestText = header.querySelector(":last-child");
      if (deepestText && deepestText.textContent !== "询问Qwen,了解更多。") {
        deepestText.textContent = "询问Qwen,了解更多。";
        console.log("Updated header text");
      }
    });
  };
  const updateModelButtonText = (node) => {
    const modelButtons = getElements$1(
      node,
      ".flex.items-center > button[data-testid] > div",
      node.matches(".flex.items-center > button[data-testid] > div")
    );
    modelButtons.forEach((button) => {
      if (button.textContent === "ChatGPT") {
        button.textContent = "Qwen3-Max-Preview";
        console.log("Updated model button text");
      }
    });
  };
  const handlePlusButton = (node) => {
    const getPlusButtons = getElements$1(
      node,
      "#page-header button",
      node.matches("#page-header button")
    );
    getPlusButtons.forEach((button) => {
      if (button.textContent?.includes("Get Plus")) {
        button.remove();
        console.log("Removed Get Plus button");
      }
    });
  };
  const clearSvgIcon = (node) => {
    const svgIcons = getElements$1(
      node,
      "button > div.icon > svg",
      node.matches("button > div.icon > svg")
    );
    if (svgIcons.length > 0 && svgIcons[0].innerHTML !== "") {
      const img = document.createElement("img");
      img.src = "https://registry.npmmirror.com/@lobehub/icons-static-png/1.65.0/files/dark/qwen.png";
      img.alt = "Qwen Icon";
      img.className = svgIcons[0].getAttribute("class") || "";
      img.style.cssText = Array.from(svgIcons[0].style).map(
        (prop) => `${prop}: ${svgIcons[0].style.getPropertyValue(prop)}`
      ).join("; ");
      img.style.width = "1.5rem";
      img.style.height = "1.25rem";
      svgIcons[0].replaceWith(img);
      console.log("Replaced SVG icon with Qwen image");
    }
  };
  const updateFooterText = (node) => {
    const footerTexts = getElements$1(node, ".text-token-text-secondary>div", node.matches(".text-token-text-secondary>div"));
    footerTexts.forEach((div) => {
      if (div.textContent === "ChatGPT can make mistakes. Check important info.") {
        div.textContent = "向 Qwen 发送消息即表示,您同意我们的用户条款并已阅读我们的隐私协议。";
        console.log("Updated footer text");
      }
    });
  };
  const processNode$1 = (node) => {
    updateHeaderText(node);
    updateModelButtonText(node);
    handlePlusButton(node);
    clearSvgIcon(node);
    updateFooterText(node);
    initTitle();
  };
  function handleGpt() {
    const observer = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        for (const node of mutation.addedNodes) {
          if (!(node instanceof HTMLElement)) continue;
          processNode$1(node);
        }
      }
    });
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true,
      attributes: true
    });
    processNode$1(document.body);
    setTimeout(() => processNode$1(document.body), 3250);
  }
  const getElements = (node, selector, isSelf = false) => {
    if (isSelf && node.matches(selector)) {
      return [node];
    }
    return Array.from(node.querySelectorAll(selector));
  };
  const removeUpsell = (node) => {
    const upsellElements = getElements(node, ".upsell-small");
    upsellElements.forEach((element) => {
      element.remove();
      console.log("Removed upsell element");
    });
  };
  const updateCenterText = (node) => {
    const svgs = getElements(node, "div.flex.items-center.justify-center > div > svg");
    svgs.forEach((svg) => {
      const div = document.createElement("div");
      div.textContent = "询问Qwen,了解更多。";
      div.style.textAlign = "center";
      div.style.fontSize = "1rem";
      svg.parentNode?.replaceChild(div, svg);
      console.log("Replaced SVG with center text");
    });
  };
  const replaceSvgWithQwenIcon = (node) => {
    const svgs = getElements(node, "svg.fill-primary");
    svgs.forEach((svg) => {
      const img = document.createElement("img");
      img.src = "https://registry.npmmirror.com/@lobehub/icons-static-png/1.65.0/files/dark/qwen.png";
      svg.replaceWith(img);
      console.log("Replaced SVG with Qwen icon");
    });
  };
  const updateTitle = () => {
    if (document.title === "Grok") {
      document.title = "Qwen";
      console.log("Updated page title");
    }
  };
  const updateModelNames = (node) => {
    const modelSpans = getElements(node, "span.inline-block");
    modelSpans.forEach((span) => {
      if (span.textContent === "Grok 4") {
        span.textContent = "Qwen3-Max-Preview";
        console.log("Updated model name to Qwen3-Max-Preview");
      } else if (span.textContent === "Grok 3") {
        span.textContent = "Qwen2.5-Max";
        console.log("Updated model name to Qwen2.5-Max");
      }
    });
  };
  const processNode = (node) => {
    removeUpsell(node);
    updateCenterText(node);
    replaceSvgWithQwenIcon(node);
    updateModelNames(node);
    updateTitle();
  };
  function handleGrok() {
    const observer = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        for (const node of mutation.addedNodes) {
          if (!(node instanceof HTMLElement)) continue;
          processNode(node);
        }
      }
    });
    observer.observe(document.body, {
      childList: true,
      subtree: true,
      characterData: true,
      attributes: true
    });
    processNode(document.body);
    setTimeout(() => processNode(document.body), 3250);
  }
  const url = window.location.href;
  const routeMatcher = [
    {
      pattern: /^https:\/\/chatgpt\.com/,
      handler: handleGpt
    },
    {
      pattern: /^https:\/\/grok\.com/,
      handler: handleGrok
    }
  ];
  console.log("Current URL:", url);
  for (const route of routeMatcher) {
    if (route.pattern.test(url)) {
      route.handler();
      break;
    }
  }

})();