Skip to content

Commit 8090161

Browse files
committed
Adding final extension
0 parents  commit 8090161

10 files changed

+241
-0
lines changed

assets/144.png

2.02 KB
Loading

assets/48.png

897 Bytes
Loading

assets/72.png

1.08 KB
Loading

assets/96.png

1.48 KB
Loading

index.css

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
body {
2+
min-width: 250px;
3+
}
4+
5+
#key_entered {
6+
display: none;
7+
}

index.html

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<html>
2+
<head>
3+
<link rel="stylesheet" href="index.css">
4+
</head>
5+
<body>
6+
<div id="key_needed">
7+
<p>To get started, add your OpenAI API Key!</p>
8+
<input id="key_input" />
9+
<button id="save_key_button">Add key</button>
10+
</div>
11+
<div id="key_entered">
12+
<p>You entered your OpenAI API Key.</p>
13+
<button id="change_key_button">Change key</button>
14+
</div>
15+
</body>
16+
<script src="index.js"></script>
17+
</html>

index.js

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const checkForKey = () => {
2+
return new Promise((resolve, reject) => {
3+
chrome.storage.local.get(['openai-key'], (result) => {
4+
resolve(result['openai-key']);
5+
});
6+
});
7+
};
8+
9+
const encode = (input) => {
10+
return btoa(input);
11+
};
12+
13+
const saveKey = async () => {
14+
try {
15+
await navigator.clipboard.writeText('hello world');
16+
console.log('success!');
17+
} catch (error) {
18+
console.log(error);
19+
}
20+
const input = document.getElementById('key_input');
21+
22+
if (input) {
23+
const { value } = input;
24+
25+
// Encode String
26+
const encodedValue = encode(value);
27+
28+
// Save to google storage
29+
chrome.storage.local.set({ 'openai-key': encodedValue }, () => {
30+
document.getElementById('key_needed').style.display = 'none';
31+
document.getElementById('key_entered').style.display = 'block';
32+
});
33+
}
34+
};
35+
36+
const changeKey = () => {
37+
document.getElementById('key_needed').style.display = 'block';
38+
document.getElementById('key_entered').style.display = 'none';
39+
};
40+
41+
document.getElementById('save_key_button').addEventListener('click', saveKey);
42+
document
43+
.getElementById('change_key_button')
44+
.addEventListener('click', changeKey);
45+
46+
checkForKey().then((response) => {
47+
if (response) {
48+
document.getElementById('key_needed').style.display = 'none';
49+
document.getElementById('key_entered').style.display = 'block';
50+
}
51+
});

manifest.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "GPT-3 Writer",
3+
"description": "Write your first song in the style of your favorite artist anywhere!",
4+
"version": "1.0",
5+
"manifest_version": 3,
6+
"icons": {
7+
"48": "assets/48.png",
8+
"72": "assets/72.png",
9+
"96": "assets/96.png",
10+
"144": "assets/144.png"
11+
},
12+
"action": {
13+
"default_popup": "index.html",
14+
"default_title": "Generate song"
15+
},
16+
"permissions": ["contextMenus", "tabs", "storage"],
17+
"background": {
18+
"service_worker": "scripts/contextMenuServiceWorker.js"
19+
},
20+
"content_scripts": [
21+
{
22+
"matches": ["http://*/*", "https://*/*"],
23+
"js": ["scripts/content.js"]
24+
}
25+
]
26+
}

scripts/content.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Get Calmly editor spot
2+
const insert = (content) => {
3+
// Find calmly editor
4+
const elements = document.getElementsByClassName('droid');
5+
6+
if (elements.length === 0) {
7+
return;
8+
}
9+
10+
const element = elements[0];
11+
const pToRemove = element.childNodes[0];
12+
13+
// Remove the first p tag in div
14+
pToRemove.remove();
15+
16+
// Split content by \n
17+
const splitContent = content.split('\n');
18+
19+
// Wrap in p tags
20+
const pTagContent = splitContent.forEach((content) => {
21+
const p = document.createElement('p');
22+
// This means newline character
23+
if (content === '') {
24+
const br = document.createElement('br');
25+
p.appendChild(br);
26+
} else {
27+
p.textContent = content;
28+
}
29+
30+
// Insert into HTML one at a time
31+
element.appendChild(p);
32+
});
33+
34+
return true;
35+
};
36+
37+
// Setup listener
38+
chrome.runtime.onMessage.addListener(
39+
// this is the message listener
40+
(request, sender, sendResponse) => {
41+
if (request.message === 'inject') {
42+
const { content } = request;
43+
44+
const result = insert(content);
45+
46+
if (!result) {
47+
sendResponse({ status: 'failed' });
48+
}
49+
50+
sendResponse({ status: 'success' });
51+
}
52+
}
53+
);

scripts/contextMenuServiceWorker.js

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Actions
2+
const getKey = () => {
3+
return new Promise((resolve, reject) => {
4+
chrome.storage.local.get(['openai-key'], (result) => {
5+
if (result['openai-key']) {
6+
const decodedKey = atob(result['openai-key']);
7+
resolve(decodedKey);
8+
}
9+
});
10+
});
11+
};
12+
13+
const sendMessage = (content) => {
14+
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
15+
const activeTab = tabs[0].id;
16+
17+
chrome.tabs.sendMessage(
18+
activeTab,
19+
{ message: 'inject', content },
20+
(response) => {
21+
if (response.status === 'failed') {
22+
console.log('injection failed.');
23+
}
24+
}
25+
);
26+
});
27+
};
28+
29+
const generate = async (prompt) => {
30+
// Get openai key
31+
const key = await getKey();
32+
const url = 'https://api.openai.com/v1/completions';
33+
const completionResponse = await fetch(url, {
34+
method: 'POST',
35+
headers: {
36+
'Content-Type': 'application/json',
37+
Authorization: `Bearer ${key}`,
38+
},
39+
body: JSON.stringify({
40+
model: 'text-davinci-002',
41+
prompt: prompt,
42+
max_tokens: 2048,
43+
temperature: 0.7,
44+
}),
45+
});
46+
47+
const completion = await completionResponse.json();
48+
return completion.choices.pop();
49+
};
50+
51+
const generateCompletionAction = async (info, tab) => {
52+
try {
53+
sendMessage('generating...');
54+
55+
const { selectionText } = info;
56+
const basePromptPrefix =
57+
'Help me write lyrics in the style of Drake, Canadian Rapper\n';
58+
const finalPromptPrefix =
59+
'Take the lyrics below and generate 5 song titles:\n';
60+
61+
// Base Prompt
62+
const baseChoice = await generate(`${basePromptPrefix}${selectionText}`);
63+
64+
// Final prompt
65+
const finalChoice = await generate(
66+
`${finalPromptPrefix}${selectionText}${baseChoice.text}`
67+
);
68+
69+
// Combine base and final choices
70+
const output = `Your next song titles:${finalChoice.text}\n\nYour next song:\n${selectionText}${baseChoice.text}`;
71+
72+
// Send to frontend
73+
sendMessage(output);
74+
} catch (error) {
75+
console.log(error);
76+
sendMessage(error.toString());
77+
}
78+
};
79+
80+
chrome.contextMenus.create({
81+
id: 'context-run',
82+
title: 'Generate Lyrics',
83+
contexts: ['selection'],
84+
});
85+
86+
// Add listener
87+
chrome.contextMenus.onClicked.addListener(generateCompletionAction);

0 commit comments

Comments
 (0)