Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

latest build #7

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
body {
min-width: 250px;
}

#key_entered {
display: none;
}
17 changes: 17 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="key_needed">
<p>To get started, add your OpenAI API Key!</p>
<input id="key_input" />
<button id="save_key_button">Add key</button>
</div>
<div id="key_entered">
<p>You entered your OpenAI API Key.</p>
<button id="change_key_button">Change key</button>
</div>
</body>
<script src="index.js"></script>
</html>
42 changes: 42 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -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";
}
});
41 changes: 26 additions & 15 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -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"]
}
]
}
51 changes: 51 additions & 0 deletions scripts/content.js
Original file line number Diff line number Diff line change
@@ -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" });
}
});
106 changes: 106 additions & 0 deletions scripts/contextMenuServiceWorker.js
Original file line number Diff line number Diff line change
@@ -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);