real-chatgpt-extension/background.js
2024-11-28 15:34:42 +01:00

198 lines
9.3 KiB
JavaScript

let originTabId = null;
// Create context menu
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: "improveMail",
title: "Verbessere Mail",
contexts: ["selection"], // Show only when text is selected
});
chrome.contextMenus.create({
id: "improveText",
title: "Verbessere Text",
contexts: ["selection"], // Show only when text is selected
});
chrome.contextMenus.create({
id: "seoText",
title: "Erstelle ein SEO-Text",
contexts: ["selection"], // Show only when text is selected
});
chrome.contextMenus.create({
id: "explainMe",
title: "Erkläre Text",
contexts: ["selection"], // Show only when text is selected
});
});
// Utility function to handle menu item click dynamically
function handleMenuItemClick(info, tab, prefixText) {
originTabId = tab.id;
if (info.selectionText) {
const selectedText = prefixText + info.selectionText;
chrome.tabs.create({ url: "https://chatgpt.com/?temporary-chat=true" }, (newTab) => {
chrome.tabs.onUpdated.addListener(function listener(tabId, info) {
if (tabId === newTab.id && info.status === "complete") {
chrome.tabs.onUpdated.removeListener(listener);
chrome.scripting.executeScript({
target: { tabId: newTab.id },
func: pasteToChatGPT,
args: [selectedText, newTab.id],
});
}
});
});
}
}
// Handle context menu clicks
chrome.contextMenus.onClicked.addListener((info, tab) => {
const menuActions = {
explainMe: 'Erkläre mir folgenden Text, fasse es kurz und gut lesbar zusammen. Erstelle keine eigenen Kommentare, zeige rein nur den text als Ausgabe: ',
improveMail: 'Verbessere folgende Mail, erstelle keine eigenen Kommentare, zeige rein nur den text als ausgabe: ',
improveText: 'Verbessere folgenden Text, mach es nicht viel länger oder kürzer als es jetzt schon ist, erstelle keine eigenen Kommentare, zeige rein nur den text als Ausgabe: ',
seoText: 'Du bist der Weltbeste SEO-Text Author. Schreibe einen SEO-optimierten Text mit 400-500 Wörtern basierend auf dem folgenden Inhalt. Identifiziere das Haupt-Keyword und integriere es mit einer Keyword-Dichte von 2-3 %. Strukturierte den Text mit HTML-Elementen (h1, h2, h3, p). Hebe das Keyword mit dem strong-Tag hervor. Gib nur den HTML-Code aus, ohne HTML-, Head- oder Body-Tags und ohne Kommentare. Die Ausgabe sollte als reiner Text erscheinen, nicht in einem Codefeld. Hier ist der relevante Text/Keyword: ',
};
if (menuActions[info.menuItemId]) {
handleMenuItemClick(info, tab, menuActions[info.menuItemId]);
}
});
// Listen for a message to close the current tab and switch back
chrome.runtime.onMessage.addListener((message, sender) => {
if (message.action === "closeGPTAndSwitchBack") {
const currentTabId = sender.tab.id;
// Close the current tab
chrome.tabs.remove(currentTabId, () => {
console.log("Closed current tab:", currentTabId);
// Switch back to the original tab
if (originTabId) {
chrome.tabs.update(originTabId, { active: true });
}
});
}
});
// Function to paste text into ChatGPT input and send it
function pasteToChatGPT(text, gptTab) {
const newChatButton = document.querySelector('a[href="/"]');
if (newChatButton) newChatButton.click();
let sendInterval;
const interval = setInterval(() => {
const contentEditableDiv = document.querySelector('div[contenteditable="true"]');
if (contentEditableDiv) {
clearInterval(interval); // Stop retrying once the div is found
// Insert text into the contenteditable div
contentEditableDiv.innerHTML = `<p>${text}</p>`;
// Dispatch input events to trigger the mirroring mechanism
contentEditableDiv.dispatchEvent(new Event('input', { bubbles: true }));
sendInterval = setInterval(() => {
// Simulate clicking the Send button
const sendButton = document.querySelector('button[data-testid="send-button"]');
if (sendButton) {
clearInterval(sendInterval);
sendButton.click();
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed"; // Prevent scrolling
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
console.log(successful ? "Fallback: Copied to clipboard!" : "Fallback: Failed to copy!");
} catch (err) {
console.error("Fallback: Could not copy text:", err);
}
document.body.removeChild(textArea);
}
function waitForElement(selector, checkForDisappearance = false) {
return new Promise((resolve) => {
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if ((element && !checkForDisappearance) || (!element && checkForDisappearance)) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.body, { childList: true, subtree: true });
});
}
// Function to copy text to the clipboard with fallback
function copyTextToClipboard(text) {
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement("textarea");
textArea.value = text.trim(); // Ensure plain text without leading/trailing whitespace
textArea.style.position = "fixed"; // Prevent scrolling
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand("copy");
console.log(successful ? "Fallback: Copied to clipboard!" : "Fallback: Failed to copy!");
} catch (err) {
console.error("Fallback: Could not copy text:", err);
}
document.body.removeChild(textArea);
}
if (navigator.clipboard && document.hasFocus()) {
navigator.clipboard.writeText(text.trim())
.then(() => console.log("Copied to clipboard!"))
.catch((err) => {
console.error("Clipboard API failed, falling back:", err);
fallbackCopyTextToClipboard(text);
});
} else {
fallbackCopyTextToClipboard(text);
}
}
waitForElement('button[data-testid="stop-button"]').then(() => {
return new Promise((resolve) => {
const observer = new MutationObserver(() => {
const stopButton = document.querySelector('button[data-testid="stop-button"]');
if (!stopButton) {
observer.disconnect();
setTimeout(() => { resolve(); }, 1500);
}
});
observer.observe(document.body, { childList: true, subtree: true });
});
}).then(() => {
const assistantMessages = document.querySelectorAll('div[data-message-author-role="assistant"]');
const latestResponse = assistantMessages[assistantMessages.length - 1]?.innerText || "";
if (latestResponse) {
setTimeout(() => {
copyTextToClipboard(latestResponse)
console.log("Action complete. Closing tab...");
chrome.runtime.sendMessage({ action: "closeGPTAndSwitchBack" });
}, 1000);
}
});
} else {
console.error("Send button not found!");
}
}, 100); // Check every 100ms
}
}, 100); // Check every 100ms
let timeout = setTimeout(() => {
clearInterval(interval);
clearInterval(sendInterval);
}, 5000);
}