您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Modifies the behavior of the chat interface on the OpenAI website
当前为
- // ==UserScript==
- // @name ChatGPT Utils
- // @description Modifies the behavior of the chat interface on the OpenAI website
- // @namespace ChatGPTUtils
- // @version 1.6.3
- // @author CriDos
- // @match https://chat.openai.com/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=chat.openai.com
- // @grant GM_xmlhttpRequest
- // @run-at document-end
- // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js
- // @license MIT
- // ==/UserScript==
- 'use strict';
- console.log(`ChatGPT Utils initializing...`);
- let debug = false;
- setInterval(() => {
- try {
- addAutoTranslate();
- //addTranslateButtons();
- } catch (error) {
- console.error(error);
- }
- try {
- findAndHookTextareaElement();
- } catch (error) {
- console.error(error);
- }
- }, 100);
- function addAutoTranslate() {
- var messages = document.querySelectorAll(".markdown.prose");
- for (var i = 0; i < messages.length; i++) {
- const msgMarkdownNode = messages[i];
- const parentMsgMarkdown = msgMarkdownNode.parentElement;
- if (parentMsgMarkdown.isAutoTranslate) {
- continue;
- }
- parentMsgMarkdown.isAutoTranslate = true;
- setInterval(async () => {
- await translateNode(msgMarkdownNode);
- }, 500);
- }
- }
- function addTranslateButtons() {
- var messages = document.querySelectorAll(".markdown.prose");
- for (var i = 0; i < messages.length; i++) {
- const msgMarkdownNode = messages[i];
- const msgIcon = msgMarkdownNode.parentElement.parentElement.parentElement.previousElementSibling;
- if (!msgIcon.querySelector(".translate-button")) {
- var btn = document.createElement("button");
- btn.textContent = "Tr";
- btn.classList.add("translate-button");
- btn.style.cssText = "width: 30px; height: 30px;";
- msgIcon.insertBefore(btn, msgIcon.firstChild);
- btn.addEventListener("click", async () => {
- await translateNode(msgMarkdownNode);
- });
- }
- }
- }
- function findAndHookTextareaElement() {
- const targetElement = document.querySelector("textarea");
- if (targetElement === null) {
- return;
- }
- if (targetElement.isAddHookKeydownEvent === true) {
- return;
- }
- targetElement.isAddHookKeydownEvent = true;
- console.log(`Textarea element found. Adding keydown event listener.`);
- targetElement.addEventListener("keydown", async event => await handleSubmit(event, targetElement), true);
- }
- async function handleSubmit(event, targetElement) {
- console.log(`Keydown event detected: type - ${event.type}, key - ${event.key}`);
- if (event.shiftKey && event.key === "Enter") {
- return;
- }
- if (window.isActiveOnSubmit === true) {
- return;
- }
- if (event.key === "Enter") {
- window.isActiveOnSubmit = true;
- event.stopImmediatePropagation();
- const request = targetElement.value;
- targetElement.value = "";
- const translatedText = await translateText(request, "ru", "en");
- targetElement.focus();
- targetElement.value = translatedText;
- const enterEvent = new KeyboardEvent("keydown", {
- bubbles: true,
- cancelable: true,
- key: "Enter",
- code: "Enter"
- });
- targetElement.dispatchEvent(enterEvent);
- window.isActiveOnSubmit = false;
- }
- }
- async function translateNode(msgMarkdownNode) {
- const translateClassName = "translate-markdown";
- const parentMsgMarkdown = msgMarkdownNode.parentElement;
- const msgMarkdownContent = msgMarkdownNode.outerHTML;
- if (msgMarkdownNode.storeContent == msgMarkdownContent) {
- return;
- }
- msgMarkdownNode.storeContent = msgMarkdownContent;
- var translateNode = parentMsgMarkdown.querySelector(`.${translateClassName}`);
- if (translateNode == null) {
- translateNode = msgMarkdownNode.cloneNode(true);
- translateNode.classList.add(translateClassName);
- parentMsgMarkdown.insertBefore(translateNode, parentMsgMarkdown.firstChild);
- }
- var msgMarkdownClone = msgMarkdownNode.cloneNode(true);
- msgMarkdownClone.classList.add(translateClassName);
- const msgMarkdownCloneContent = msgMarkdownClone.outerHTML;
- msgMarkdownClone = null;
- const translatedContent = await translateHTML(msgMarkdownCloneContent, "auto", navigator.language)
- let index = translatedContent.lastIndexOf('</div>');
- let before = translatedContent.slice(0, index);
- const endTranslate = `<p>.......... конец_перевода ..........</p>`;
- translateNode.outerHTML = before.concat(endTranslate, '</div>');
- }
- async function translateHTML(html, sLang, tLang) {
- const excludeTagRegex = /<(pre|code)[^>]*>([\s\S]*?)<\/(pre|code)>/g;
- const excludeTags = [];
- const excludePlaceholder = 'e0x';
- let translateHTML = html;
- let excludeTagsMatch;
- while (excludeTagsMatch = excludeTagRegex.exec(html)) {
- excludeTags.push(excludeTagsMatch[0]);
- translateHTML = translateHTML.replace(excludeTagsMatch[0], `[${excludePlaceholder}${excludeTags.length - 1}]`);
- }
- if (debug) {
- console.log(`preTranslateHTML: ${html}`);
- }
- translateHTML = await translateText(translateHTML, sLang, tLang);
- translateHTML = removeSpaces(translateHTML);
- for (let i = 0; i < excludeTags.length; i++) {
- translateHTML = translateHTML.replace(`[${excludePlaceholder}${i}]`, excludeTags[i]);
- }
- if (debug) {
- console.log(`postTranslateHTML: ${translateHTML}`);
- }
- return translateHTML;
- }
- async function translateText(text, sLang, tLang) {
- const url = `https://translate.googleapis.com/translate_a/single?client=gtx&format=text&sl=${sLang}&tl=${tLang}&dt=t&q=${encodeURIComponent(text)}`;
- try {
- if (debug) {
- console.log(`preTranslate: ${text}`);
- }
- const response = await doXHR(url);
- const responseText = JSON.parse(response.responseText);
- let postTranslate = "";
- responseText[0].forEach(part => {
- postTranslate += part[0];
- });
- if (debug) {
- console.log(`postTranslate: ${postTranslate}`);
- }
- return postTranslate;
- } catch (error) {
- console.error(error);
- }
- }
- async function doXHR(url) {
- return new Promise((resolve, reject) => {
- const xhr = new XMLHttpRequest();
- xhr.open("GET", url);
- xhr.onload = () => resolve(xhr);
- xhr.onerror = () => reject(xhr.statusText);
- xhr.send();
- });
- }
- function removeSpaces(string) {
- const regex = /\[([^\[\]]*)\]/g;
- let result;
- while ((result = regex.exec(string)) !== null) {
- string = string.replace(result[1], result[1].replace(/\s/g, ''));
- }
- return string;
- }