Skip to content
Merged
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
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ body:
- type: textarea
id: screenshot-or-link
attributes:
label: Screenshot and/or share link
description: Run `/share` to get a share link, or attach a screenshot
placeholder: Paste link or drag and drop screenshot here
label: Screenshot
description: Attach a screenshot or recording
placeholder: Drag and drop screenshot here
validations:
required: false

Expand Down
3 changes: 0 additions & 3 deletions infra/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ const bucket = new sst.cloudflare.Bucket("Bucket")
export const api = new sst.cloudflare.Worker("Api", {
domain: `api.${domain}`,
handler: "packages/function/src/api.ts",
environment: {
WEB_DOMAIN: domain,
},
url: true,
link: [
bucket,
Expand Down
80 changes: 0 additions & 80 deletions packages/function/src/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Hono } from "hono"
import { DurableObject } from "cloudflare:workers"
import { randomUUID } from "node:crypto"
import { jwtVerify, createRemoteJWKSet } from "jose"
import { createAppAuth } from "@octokit/auth-app"
import { Octokit } from "@octokit/rest"
Expand All @@ -10,7 +9,6 @@ import { parseRepositoryClaim } from "./github"
type Env = {
SYNC_SERVER: DurableObjectNamespace<SyncServer>
Bucket: R2Bucket
WEB_DOMAIN: string
}

export class SyncServer extends DurableObject<Env> {
Expand Down Expand Up @@ -43,55 +41,13 @@ export class SyncServer extends DurableObject<Env> {
ws.close(code, "Durable Object is closing WebSocket")
}

async publish(key: string, content: any) {
const sessionID = await this.getSessionID()
if (
!key.startsWith(`session/info/${sessionID}`) &&
!key.startsWith(`session/message/${sessionID}/`) &&
!key.startsWith(`session/part/${sessionID}/`)
)
return new Response("Error: Invalid key", { status: 400 })

// store message
await this.env.Bucket.put(`share/${key}.json`, JSON.stringify(content), {
httpMetadata: {
contentType: "application/json",
},
})
await this.ctx.storage.put(key, content)
const clients = this.ctx.getWebSockets()
console.log("SyncServer publish", key, "to", clients.length, "subscribers")
for (const client of clients) {
client.send(JSON.stringify({ key, content }))
}
}

public async share(sessionID: string) {
let secret = await this.getSecret()
if (secret) return secret
secret = randomUUID()

await this.ctx.storage.put("secret", secret)
await this.ctx.storage.put("sessionID", sessionID)

return secret
}

public async getData() {
const data = (await this.ctx.storage.list()) as Map<string, any>
return Array.from(data.entries())
.filter(([key, _]) => key.startsWith("session/"))
.map(([key, content]) => ({ key, content }))
}

public async assertSecret(secret: string) {
if (secret !== (await this.getSecret())) throw new Error("Invalid secret")
}

private async getSecret() {
return this.ctx.storage.get<string>("secret")
}

private async getSessionID() {
return this.ctx.storage.get<string>("sessionID")
}
Expand All @@ -116,28 +72,6 @@ export class SyncServer extends DurableObject<Env> {

export default new Hono<{ Bindings: Env }>()
.get("/", (c) => c.text("Hello, world!"))
.post("/share_create", async (c) => {
const body = await c.req.json<{ sessionID: string }>()
const sessionID = body.sessionID
const short = SyncServer.shortName(sessionID)
const id = c.env.SYNC_SERVER.idFromName(short)
const stub = c.env.SYNC_SERVER.get(id)
const secret = await stub.share(sessionID)
return c.json({
secret,
url: `https://${c.env.WEB_DOMAIN}/s/${short}`,
})
})
.post("/share_delete", async (c) => {
const body = await c.req.json<{ sessionID: string; secret: string }>()
const sessionID = body.sessionID
const secret = body.secret
const id = c.env.SYNC_SERVER.idFromName(SyncServer.shortName(sessionID))
const stub = c.env.SYNC_SERVER.get(id)
await stub.assertSecret(secret)
await stub.clear()
return c.json({})
})
.post("/share_delete_admin", async (c) => {
const body = await c.req.json<{ sessionShortName: string; adminSecret: string }>()
const sessionShortName = body.sessionShortName
Expand All @@ -148,20 +82,6 @@ export default new Hono<{ Bindings: Env }>()
await stub.clear()
return c.json({})
})
.post("/share_sync", async (c) => {
const body = await c.req.json<{
sessionID: string
secret: string
key: string
content: any
}>()
const name = SyncServer.shortName(body.sessionID)
const id = c.env.SYNC_SERVER.idFromName(name)
const stub = c.env.SYNC_SERVER.get(id)
await stub.assertSecret(body.secret)
await stub.publish(body.key, body.content)
return c.json({})
})
.get("/share_poll", async (c) => {
const upgradeHeader = c.req.header("Upgrade")
if (!upgradeHeader || upgradeHeader !== "websocket") {
Expand Down
Loading