选译替换器TransReplace

翻译选中的文本并替换

// ==UserScript==
// @name        选译替换器TransReplace
// @namespace   vurses
// @license     Mit
// @author      layenh
// @match       https://web.telegram.org/*
// @match       https://webk.telegram.org/*
// @match       https://webz.telegram.org/*
// @match       https://fanyi.sogou.com/*
// @match       *://*/*
// @grant       GM.xmlhttpRequest
// @grant       GM_xmlhttpRequest
// @grant       GM.getValue
// @grant       GM_getValue
// @grant       GM.setValue
// @grant       GM_setValue
// @connect     fanyi.sogou.com
// @run-at      document-end
// @version     1.0
// @noframes
// @require     https://update.greasyfork.org/scripts/533087/1572495/WbiSign.js
// @require     https://update.greasyfork.org/scripts/534967/1583188/langSwitcher.js
// @description 翻译选中的文本并替换
// ==/UserScript==

// 获取cookie和secretCode
let sogouCookie = GM_getValue("sogouCookie", "");
let secretCode = GM_getValue("secretCode", "");
if (location.href.includes("fanyi.sogou.com")) {
  sogouCookie = document.cookie;
  GM_setValue("sogouCookie", sogouCookie);
  window.addEventListener("load", () => {
    secretCode = unsafeWindow.__INITIAL_STATE__.common.CONFIG.secretCode;
    GM_setValue("secretCode", secretCode);
  });
}
// 注入语言菜单
window.addEventListener("load", () => {
  document.documentElement.appendChild(createLangSwitcher(GM_setValue, GM_getValue));
});
// uuid生成
function uuidGen() {
  let t,
    n,
    r = "";
  for (t = 0; t < 32; t++) {
    (n = (16 * Math.random()) | 0),
      (8 !== t && 12 !== t && 16 !== t && 20 !== t) || (r += "-");
    const e = 3 & n,
      o = 16 === t ? 8 | e : n;
    r += (12 === t ? 4 : o).toString(16);
  }
  return r;
}
// 简易封装xhr
const gm_xhr = function (data) {
  return new Promise((resolve, reject) => {
    GM_xmlhttpRequest({
      method: "POST",
      url: "https://fanyi.sogou.com/api/transpc/text/result",
      data: JSON.stringify(data),
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json, text/plain, */*",
      },
      cookie: sogouCookie,
      onload: resolve,
      onerror: reject,
    });
  }).then((response) => {
    return response.responseText;
  });
};
// 监听是否替换翻译文本
document.addEventListener("keydown", (event) => {
  if (event.shiftKey) {
    const activeElement = document.activeElement;
    console.log(activeElement)
    if (
      activeElement.tagName === "INPUT" ||
      activeElement.tagName === "TEXTAREA" ||
      activeElement.isContentEditable
    ) {
      const selectedText = window.getSelection().toString().trim();
      console.log(selectedText)
      if (selectedText) {
        // 初始语言类型,可以是auto
        const from = "auto";
        // 目标语言类型
        const to = GM_getValue("selectedLang", "zh-CHS");
        // 初始语言内容
        const text = selectedText;
        const keyS = SparkMD5.hash(
          "".concat(from).concat(to).concat(text).concat(secretCode)
        );
        const uuid = uuidGen();
        const data = {
          client: "pc",
          exchange: false,
          fr: "browser_pc",
          from,
          needQc: 1,
          s: keyS,
          text,
          to: GM_getValue("selectedLang", "zh-CHS"),
          uuid: uuid,
        };
        gm_xhr(data)
          .then((res) => {
            const translatedText = JSON.parse(res).data.translate.dit || "";
            if (translatedText === "") throw "api 错误";
            if (
              activeElement.tagName === "INPUT" ||
              activeElement.tagName === "TEXTAREA"
            ) {
              const start = activeElement.selectionStart;
              const end = activeElement.selectionEnd;
              const originalValue = activeElement.value;
              activeElement.value =
                originalValue.slice(0, start) +
                translatedText +
                originalValue.slice(end);
              // 可选:重新设置光标位置
              activeElement.selectionStart = activeElement.selectionEnd =
                start + translatedText.length;
              // ✅ 触发 input 事件(使得 Vue/React 等响应变化)
              const event = new Event("input", { bubbles: true });
              activeElement.dispatchEvent(event);
            } else if (activeElement.isContentEditable) {
              const selection = window.getSelection();
              if (!selection.rangeCount) return;
              const range = selection.getRangeAt(0);
              range.deleteContents();
              range.insertNode(document.createTextNode(translatedText));
              // 可选:移动光标到插入后的位置
              range.collapse(false);
              selection.removeAllRanges();
              selection.addRange(range);
            }
          })
          .catch((e) => {
            console.log(e);
            location.href = "https://fanyi.sogou.com";
          });
      }
    }
  }
});