From a9423ae89a122d61eab6b232fd41baac68930a15 Mon Sep 17 00:00:00 2001 From: JaiBo <65864145+iafhurtado@users.noreply.github.com> Date: Mon, 20 Feb 2023 08:53:57 +0100 Subject: [PATCH] latest build --- index.css | 7 ++ index.html | 17 +++++ index.js | 42 +++++++++++ manifest.json | 41 +++++++---- scripts/content.js | 51 +++++++++++++ scripts/contextMenuServiceWorker.js | 106 ++++++++++++++++++++++++++++ 6 files changed, 249 insertions(+), 15 deletions(-) create mode 100644 index.css create mode 100644 index.html create mode 100644 index.js create mode 100644 scripts/content.js create mode 100644 scripts/contextMenuServiceWorker.js diff --git a/index.css b/index.css new file mode 100644 index 00000000..5daa52c8 --- /dev/null +++ b/index.css @@ -0,0 +1,7 @@ +body { + min-width: 250px; +} + +#key_entered { + display: none; +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..1d5eb23e --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + +
+

To get started, add your OpenAI API Key!

+ + +
+
+

You entered your OpenAI API Key.

+ +
+ + + \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 00000000..4d1c5b5e --- /dev/null +++ b/index.js @@ -0,0 +1,42 @@ +const checkForKey = () => { + return new Promise((resolve, reject) => { + chrome.storage.local.get(["openai-key"], (result) => { + resolve(result["openai-key"]); + }); + }); +}; + +const encode = (input) => { + return btoa(input); +}; + +const saveKey = () => { + const input = document.getElementById("key_input"); + + if (input) { + const { value } = input; + + // Encode String + const encodedValue = encode(value); + + // Save to google storage + chrome.storage.local.set({ "openai-key": encodedValue }, () => { + document.getElementById("key_needed").style.display = "none"; + document.getElementById("key_entered").style.display = "block"; + }); + } +}; + +const changeKey = () => {}; + +document.getElementById("save_key_button").addEventListener("click", saveKey); +document + .getElementById("change_key_button") + .addEventListener("click", changeKey); + +checkForKey().then((response) => { + if (response) { + document.getElementById("key_needed").style.display = "none"; + document.getElementById("key_entered").style.display = "block"; + } +}); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 554d2715..f2dc035b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,16 +1,27 @@ { - "name": "GPT-3 Writer", - "description": "Write a blog post in the style of your favorite thinker anywhere!", - "version": "1.0", - "manifest_version": 3, - "icons": { - "48": "assets/48.png", - "72": "assets/72.png", - "96": "assets/96.png", - "144": "assets/144.png" - }, - "action": { - "default_popup": "index.html", - "default_title": "Generate blog post" - } -} + "name": "magic blog post generator", + "description": "highlight your blog post title, we'll generate the rest", + "version": "1.0", + "manifest_version": 3, + "icons": { + "48": "assets/48.png", + "72": "assets/72.png", + "96": "assets/96.png", + "144": "assets/144.png" + }, + "action": { + "default_popup": "index.html", + "default_title": "Generate blog post" + }, + "background": { + "service_worker": "./scripts/contextMenuServiceWorker.js" + }, + "permissions": ["contextMenus", "tabs", "storage"], + "host_permissions": ["https://*/*"], + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*"], + "js": ["scripts/content.js"] + } + ] +} \ No newline at end of file diff --git a/scripts/content.js b/scripts/content.js new file mode 100644 index 00000000..f2b9c783 --- /dev/null +++ b/scripts/content.js @@ -0,0 +1,51 @@ +const insert = (content) => { + // Find Calmly editor input section + const elements = document.getElementsByClassName("droid"); + + if (elements.length === 0) { + return; + } + + const element = elements[0]; + + // Grab the first p tag so we can replace it with our injection + const pToRemove = element.childNodes[0]; + pToRemove.remove(); + + // Split content by \n + const splitContent = content.split("\n"); + + // Wrap in p tags + splitContent.forEach((content) => { + const p = document.createElement("p"); + + if (content === "") { + const br = document.createElement("br"); + p.appendChild(br); + } else { + p.textContent = content; + } + + // Insert into HTML one at a time + element.appendChild(p); + }); + + // On success return true + return true; +}; + +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.message === "inject") { + const { content } = request; + + // Call this insert function + const result = insert(content); + + // If something went wrong, send a failed status + if (!result) { + sendResponse({ status: "failed" }); + } + + sendResponse({ status: "success" }); + } +}); \ No newline at end of file diff --git a/scripts/contextMenuServiceWorker.js b/scripts/contextMenuServiceWorker.js new file mode 100644 index 00000000..f4b5469a --- /dev/null +++ b/scripts/contextMenuServiceWorker.js @@ -0,0 +1,106 @@ +// Function to get + decode API key +const getKey = () => { + return new Promise((resolve, reject) => { + chrome.storage.local.get(["openai-key"], (result) => { + if (result["openai-key"]) { + const decodedKey = atob(result["openai-key"]); + resolve(decodedKey); + } + }); + }); +}; + +const sendMessage = (content) => { + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + const activeTab = tabs[0].id; + + chrome.tabs.sendMessage( + activeTab, + { message: "inject", content }, + (response) => { + if (response.status === "failed") { + console.log("injection failed."); + } + } + ); + }); +}; + +// Setup our generate function +const generate = async (prompt) => { + // Get your API key from storage + const key = await getKey(); + const url = "https://api.openai.com/v1/completions"; + + // Call completions endpoint + const completionResponse = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${key}`, + }, + body: JSON.stringify({ + model: "text-davinci-003", + prompt: prompt, + max_tokens: 1250, + temperature: 0.7, + }), + }); + + // Select the top choice and send back + const completion = await completionResponse.json(); + return completion.choices.pop(); +}; + +// New function here +const generateCompletionAction = async (info) => { + try { + // Send mesage with generating text (this will be like a loading indicator) + sendMessage("generating..."); + + const { selectionText } = info; + const basePromptPrefix = ` + Escribe una tabla de contenido para una sesion informativa con el presidente de Mexico. + + Titulo: + `; + + // Add this to call GPT-3 + const baseCompletion = await generate( + `${basePromptPrefix}${selectionText}` + ); + + // Add your second prompt here + const secondPrompt = ` + Toma la tabla de contenido y el titulo de la sesion informativa y genera una respuesta escrita en el estilo de Andres Manuel Lopez Obrador. Haz que se sienta como una historia. No solo enumere los puntos. Profundice en cada uno. Explique por que. + Title: ${selectionText} + + Tabla de contenido: ${baseCompletion.text} + + Respuesta: + `; + + // Call your second prompt + const secondPromptCompletion = await generate(secondPrompt); + + // Send the output when we're all done + sendMessage(secondPromptCompletion.text); + } catch (error) { + console.log(error); + + // Add this here as well to see if we run into any errors! + sendMessage(error.toString()); + } +}; + +// Add this in scripts/contextMenuServiceWorker.js +chrome.runtime.onInstalled.addListener(() => { + chrome.contextMenus.create({ + id: "context-run", + title: "Preguntale a AMLO", + contexts: ["selection"], + }); +}); + +// Add listener +chrome.contextMenus.onClicked.addListener(generateCompletionAction);