Skip to content

Heaven Live — Cloudflare Worker + Discord go-live announcements#1

Draft
RSPNOIZY wants to merge 2 commits into
mainfrom
claude/heaven-live-feature-rRuQ7
Draft

Heaven Live — Cloudflare Worker + Discord go-live announcements#1
RSPNOIZY wants to merge 2 commits into
mainfrom
claude/heaven-live-feature-rRuQ7

Conversation

@RSPNOIZY
Copy link
Copy Markdown
Owner

What this does

HEAVEN goes from BUILT to LIVE.

Adds heaven-live/ — a Cloudflare Worker that manages stream state and fires Discord webhook announcements when Noizy.AI goes live or offline.

New files

File Purpose
heaven-live/src/index.ts Worker: /go-live, /go-offline, /status endpoints
heaven-live/src/discord.ts Discord webhook module (username: Noizy.AI, avatar: logo.png)
heaven-live/src/stream.ts KV-backed stream state
heaven-live/wrangler.toml Cloudflare Worker config
heaven-live/go-live.sh 1-command shell trigger — goes LIVE
heaven-live/go-offline.sh 1-command shell trigger — goes OFFLINE
wisdom/prompts/HEAVEN_PROMPT.md Updated: status BUILT → LIVE, documents the new Live Layer

API surface

  • GET /status — public, returns current stream state
  • POST /go-live — sets KV state, fires Discord 🚀 LIVE announcement (auth: X-Heaven-Key)
  • POST /go-offline — clears KV state, fires Discord 📴 OFFLINE announcement (auth: X-Heaven-Key)

Deploy checklist

  • wrangler kv:namespace create HEAVEN_KV → paste ID into wrangler.toml
  • wrangler secret put DISCORD_WEBHOOK_URL (your Discord webhook URL)
  • wrangler secret put HEAVEN_API_KEY (pick a strong key)
  • cd heaven-live && wrangler deploy
  • Test: HEAVEN_API_KEY=xxx ./heaven-live/go-live.sh

Go live (after deploy)

HEAVEN_API_KEY=xxx STREAM_URL=https://your-stream-url ./heaven-live/go-live.sh

GORUNFREE.


Generated by Claude Code

HEAVEN goes LIVE. Adds heaven-live/ Cloudflare Worker with:
- POST /go-live  → sets KV state + fires Discord webhook
- POST /go-offline → clears KV state + fires Discord webhook
- GET /status   → public stream state
- go-live.sh / go-offline.sh — 1-command shell triggers
- X-Heaven-Key auth on write endpoints
- Updates HEAVEN_PROMPT.md: status BUILT → LIVE
KV namespace 'HEAVEN_KV' already exists in Cloudflare account Fishmusicinc.
ID: 1f88de7bc13b4fb9984887bb0d0aa200
Ready to deploy — just set secrets and run wrangler deploy.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces a new Cloudflare Worker (“heaven-live”) that tracks live-stream state in KV and posts Discord webhook announcements when the stream goes live/offline, plus updates HEAVEN documentation to reflect the new “LIVE layer”.

Changes:

  • Adds heaven-live Worker with /status, /go-live, and /go-offline endpoints (API-key protected for mutating actions).
  • Implements Discord webhook announcement formatting and KV-backed stream state storage.
  • Adds deployment/local trigger tooling (Wrangler config + shell scripts) and updates HEAVEN_PROMPT.md to document the live layer.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
wisdom/prompts/HEAVEN_PROMPT.md Documents the new Live Layer, endpoints, secrets, and deploy/go-live instructions.
heaven-live/wrangler.toml Worker configuration and KV binding for stream state.
heaven-live/tsconfig.json TypeScript config for the Worker project.
heaven-live/src/stream.ts KV read/write helpers for stream state persistence.
heaven-live/src/index.ts Worker routing + auth + live/offline state transitions + Discord notifications.
heaven-live/src/discord.ts Discord webhook payload creation and POST logic.
heaven-live/package.json Wrangler/TypeScript tooling scripts and dev dependencies.
heaven-live/go-live.sh CLI trigger to call /go-live.
heaven-live/go-offline.sh CLI trigger to call /go-offline.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread heaven-live/src/index.ts
const authError = requireApiKey(request, env);
if (authError) return authError;

const body = await request.json<{ showName?: string; streamUrl?: string; platform?: string }>();
Comment thread heaven-live/src/index.ts
Comment on lines +52 to +59
await setStreamState(env.HEAVEN_KV, state);
await postDiscordAnnouncement(env.DISCORD_WEBHOOK_URL, {
showName,
status: 'LIVE',
platform,
streamUrl,
});

Comment thread heaven-live/src/index.ts
Comment on lines +35 to +37
if (method === 'POST' && url.pathname === '/go-live') {
const authError = requireApiKey(request, env);
if (authError) return authError;
Comment thread heaven-live/src/stream.ts
Comment on lines +12 to +17
export async function getStreamState(kv: KVNamespace): Promise<StreamState> {
const raw = await kv.get(STATE_KEY);
if (!raw) {
return { isLive: false, showName: '', platform: 'Cloudflare Stream' };
}
return JSON.parse(raw) as StreamState;
Comment on lines +14 to +30

const content = isLive
? `🚀 **LIVE**\n🎛️ **Show:** ${announcement.showName}\n🌐 **Platform:** ${announcement.platform}\n🕒 **Time:** ${time}${announcement.streamUrl ? `\n🔗 **Watch:** ${announcement.streamUrl}` : ''}`
: `📴 **OFFLINE**\n🎛️ **Show:** ${announcement.showName}\n🌐 **Platform:** ${announcement.platform}\n🕒 **Ended:** ${time}`;

const response = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'Noizy.AI',
avatar_url: 'https://noizy.ai/logo.png',
content,
}),
});

if (!response.ok) {
throw new Error(`Discord webhook failed: ${response.status} ${await response.text()}`);
Comment thread heaven-live/go-live.sh
Comment on lines +11 to +17
PAYLOAD=$(cat <<EOF
{
"showName": "${SHOW_NAME}",
"platform": "${PLATFORM}",
"streamUrl": "${STREAM_URL}"
}
EOF
Comment thread heaven-live/go-live.sh
Comment on lines +1 to +4
#!/usr/bin/env zsh
# Heaven Live — go-live trigger for Noizy.AI
# Usage: HEAVEN_API_KEY=xxx [SHOW_NAME="..."] [STREAM_URL="https://..."] ./go-live.sh

Comment thread heaven-live/wrangler.toml

[[kv_namespaces]]
binding = "HEAVEN_KV"
id = "1f88de7bc13b4fb9984887bb0d0aa200"
Comment thread heaven-live/go-offline.sh
Comment on lines +1 to +4
#!/usr/bin/env zsh
# Heaven Live — go-offline trigger for Noizy.AI
# Usage: HEAVEN_API_KEY=xxx ./go-offline.sh

@rspplowman-cloud
Copy link
Copy Markdown

Heaven Live — review & deploy notes

This is a clean, well-scoped implementation. Architecture is solid: KV-backed state, secret-authenticated mutations, public read endpoint, Discord webhook announcements, 1-command shell triggers. The separation into discord.ts / stream.ts / index.ts is the right call. Strong work.

Before marking ready and merging, here's what I'd address:

Must-fix before deploy

1. wrangler.toml has a real account KV namespace ID committed
The id = "1f88de7bc13b4fb9984887bb0d0aa200" in [[kv_namespaces]] is account-specific and will fail for anyone else deploying. Replace with a placeholder and document that wrangler kv:namespace create HEAVEN_KV output must be pasted in, per the deploy checklist. Copilot flagged this too.

2. No idempotency guard on /go-live and /go-offline
Calling /go-live twice fires two Discord announcements. Add a check: if getStreamState already shows isLive: true, return early (or accept a force=true param). Same for /go-offline.

3. KV write happens before Discord webhook — divergence risk
If Discord is down, /status will show LIVE but no announcement was posted. Flip the order: post Discord first, then persist to KV. If the webhook throws, the KV write never happens and the state stays consistent.

Should-fix (low effort, high value)

4. Wrap request.json() in try/catch (index.ts line ~39)
An empty body or non-JSON content-type throws a 500 instead of a 400. One try/catch fixes it cleanly. Copilot's suggested changeset for this is exactly right.

5. JSON.parse(raw) in stream.ts can throw
If the KV value is corrupted or manually edited into invalid JSON, /status and /go-offline crash. Wrap in try/catch and return the safe default state on parse failure.

6. Add an AbortController timeout to the Discord fetch() in discord.ts
Cloudflare Workers have a hard CPU/wall-clock budget. A hanging Discord call will consume the whole budget. A 5-second timeout abort is a 4-line fix and makes the failure mode explicit.

7. Shell scripts: zshbash + set -euo pipefail
go-live.sh and go-offline.sh use #!/usr/bin/env zsh. CI containers and most Linux servers don't have zsh. Switch to bash and add set -euo pipefail so the script hard-fails on any error instead of silently continuing. Copilot's diffs for both scripts look correct.

8. Shell scripts: use jq for JSON serialisation
SHOW_NAME or STREAM_URL containing a " or \ will produce malformed JSON. jq -n --arg showName "$SHOW_NAME" ... is the safe fix — Copilot's suggested changeset is right.

Nice-to-have / future

  • A preview env block in wrangler.toml with its own KV binding makes dev/prod separation explicit.
    • Rate-limit headers or a simple time-gate on /go-live would prevent Discord spam if the shell script is accidentally looped.
    • HEAVEN_PROMPT.md update looks great — good to keep the wisdom layer in sync with the live layer.

Deploy checklist status

  • Replace hardcoded KV namespace ID in wrangler.toml with a placeholder
  • - [ ] Apply idempotency guard to /go-live and /go-offline
  • - [ ] Swap Discord-post and KV-write order in both handlers
  • - [ ] Wrap request.json() in try/catch
  • - [ ] Wrap JSON.parse(raw) in try/catch in stream.ts
  • - [ ] Add AbortController timeout to Discord fetch
  • - [ ] Change shell scripts to bash + set -euo pipefail + jq
    Once those are in, mark ready for review and this is good to merge. GORUNFREE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants