Skip to content

Commit

Permalink
feat: initialize project
Browse files Browse the repository at this point in the history
  • Loading branch information
ivangabriele committed Jul 13, 2023
0 parents commit 637ee1a
Show file tree
Hide file tree
Showing 18 changed files with 11,686 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# https://editorconfig.org
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 120
trim_trailing_whitespace = true

[*.md]
max_line_length = 0
trim_trailing_whitespace = false

[COMMIT_EDITMSG]
max_line_length = 0
156 changes: 156 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
###############################################################################
# Node.js

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
# .yarn/cache
# .yarn/unplugged
# .yarn/build-state.yml
# .yarn/install-state.gz
# .pnp.*

### Node Patch ###
# Serverless Webpack directories
.webpack/

# Optional stylelint cache

# SvelteKit build / generate output
.svelte-kit

################################################################################
# Yarn (without Zero-Installs)

# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

################################################################################
# Custom
874 changes: 874 additions & 0 deletions .yarn/releases/yarn-3.6.1.cjs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-3.6.1.cjs
Empty file added CHANGELOG.md
Empty file.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# OpenAI Forge Browser Extension
Binary file added assets/icon-128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon-48x48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions assets/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"manifest_version": 2,
"name": "OpenAI Forge",
"version": "0.0.0",
"background": {
"scripts": ["background.js"],
"persistent": true
},
"browser_action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["https://chat.openai.com/*"],
"js": ["content.js"]
}
],
"permissions": ["webRequest", "*://*/*"],
"icons": {
"16": "icon-16x16.png",
"48": "icon-48x48.png",
"128": "icon-128x128.png"
}
}
19 changes: 19 additions & 0 deletions assets/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>My Extension</title>
<style>
body {
width: 200px;
padding: 10px;
}
</style>
</head>
<body>
<button id="connect">Connect</button>
<button id="disconnect">Disconnect</button>
<ul id="messages"></ul>

<script src="foreground.js"></script>
</body>
</html>
125 changes: 125 additions & 0 deletions background/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
const TAB_SOCKETS: Record<number, WebSocket> = {}
const TAB_RETRY_COUNTS: Record<number, number> = {}

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status !== 'complete') {
if (!changeInfo.status) {
return
}

let previousWebSocket = TAB_SOCKETS[tabId]
if (previousWebSocket) {
debug(tabId, 'STATE', 'CLOSING')

previousWebSocket.close()
}

return
}

let url: URL
try {
url = new URL(tab.url!)
} catch (_err) {
return
}

if (url.hostname !== 'chat.openai.com' || !url.pathname.startsWith('/c/')) {
return
}

debug(tabId, 'STATE', 'MATCHED')

startWebSocketClient(tabId)
})

chrome.tabs.onRemoved.addListener(tabId => {
let previousWebSocket = TAB_SOCKETS[tabId]
if (previousWebSocket) {
debug(tabId, 'STATE', 'CLOSING')

previousWebSocket.close()
delete TAB_SOCKETS[tabId]
}
})

function debug(tabId: number, type: 'STATE', ...args: any[]): void {
console.debug('[OpenAI Forge]', type, ...args)

chrome.tabs.query({ active: true, currentWindow: true }, () => {
chrome.tabs.sendMessage(tabId, {
type,
value: args.join(' '),
})
})
}

function restartWebSocketClient(tabId: number): void {
const tabRetryCount = TAB_RETRY_COUNTS[tabId]
if (!tabRetryCount) {
return
}

if (tabRetryCount < 60) {
TAB_RETRY_COUNTS[tabId] = tabRetryCount + 1

setTimeout(() => startWebSocketClient(tabId, true), 5000)
} else {
debug(tabId, 'STATE', 'TOO_MANY_RETRIES')
}
}

function startWebSocketClient(tabId: number, isRetry: boolean = false): void {
try {
debug(tabId, 'STATE', isRetry ? 'RECONNECTING' : 'CONNECTING')

if (!isRetry) {
TAB_RETRY_COUNTS[tabId] = 0
}

const webSocket = new WebSocket('ws://localhost:4242')
TAB_SOCKETS[tabId] = webSocket

webSocket.onopen = () => {
debug(tabId, 'STATE', 'CONNECTED')

chrome.tabs.query({ active: true, currentWindow: true }, () => {
chrome.tabs.sendMessage(tabId, {
type: 'STATE',
value: 'CONNECTED',
})
})
}

webSocket.onmessage = event => {
console.debug('[OpenAI Forge]', 'MESSAGE', event.type, event.data)

chrome.tabs.query({ active: true, currentWindow: true }, () => {
const data = JSON.parse(event.data)

chrome.tabs.sendMessage(tabId, {
type: 'DATA',
value: data,
})
})
}

webSocket.onerror = error => {
console.debug('[OpenAI Forge]', 'ERROR', String(error))
}

webSocket.onclose = event => {
if (event.wasClean) {
debug(tabId, 'STATE', 'CLOSED', event.code, event.reason)
} else {
debug(tabId, 'STATE', 'DIED', event.code, event.reason)

restartWebSocketClient(tabId)
}
}
} catch (err) {
console.debug('[OpenAI Forge]', 'ERROR', String(err))

restartWebSocketClient(tabId)
}
}
42 changes: 42 additions & 0 deletions content/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Toastify from 'toastify-js'

import 'toastify-js/src/toastify.css'

function showToast(message: string) {
Toastify({
close: true,
duration: 3000,
gravity: 'top',
position: 'right',
stopOnFocus: true,
text: message,
}).showToast()
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.debug('[OpenAI Forge]', request.type, request.value)

if (request.type === 'DATA') {
if (request.value.action === 'ASK') {
const promptTextarea: HTMLTextAreaElement | null = document.querySelector('textarea#prompt-textarea')
if (!promptTextarea) {
return
}

const promptButton: HTMLButtonElement | null | undefined = promptTextarea.parentElement?.querySelector('button')
if (!promptButton) {
return
}

promptTextarea.value = request.value.message
promptTextarea.dispatchEvent(new Event('input', { bubbles: true }))
promptButton.click()
}

return
}

if (request.type === 'STATE') {
showToast(`STATE: ${request.value}`)
}
})
Loading

0 comments on commit 637ee1a

Please sign in to comment.