HDRezkaSpeeds

Speeds Feedback Worker

Cloudflare Worker that receives feedback POSTs from HDRezkaSpeeds / VideoSpeeds browser extensions and forwards them to a Telegram bot (developer’s personal inbox).

One-time setup (~10 min)

1. Create the Telegram bot

  1. Open Telegram, search for @BotFather.
  2. Send /newbot, follow the prompts. Pick a name like Speeds Feedback Bot and a username like speeds_feedback_bot.
  3. Save the HTTP API token (long string starting with digits + :).
  4. Find your chat ID:
    • Open a chat with your new bot, send /start.
    • In a browser, open https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates (replace <YOUR_TOKEN>).
    • In the JSON response, look for "chat":{"id":<your-id>}. Copy the numeric id (positive for personal chats, negative for groups).

2. Install Wrangler

cd cloudflare-worker
npm install
npx wrangler login   # opens browser, authorise Cloudflare

3. Create the rate-limit KV namespace

npx wrangler kv namespace create RATE_LIMIT

It prints an id, e.g.

🌀 Creating namespace with title "speeds-feedback-RATE_LIMIT"
✨ Success!
Add the following to your wrangler.toml:
[[kv_namespaces]]
binding = "RATE_LIMIT"
id = "abcd1234ef5678"

Open wrangler.toml, replace REPLACE_WITH_KV_ID with that id.

4. Set secrets

npx wrangler secret put TELEGRAM_BOT_TOKEN
# paste the token, press Enter

npx wrangler secret put TELEGRAM_CHAT_ID
# paste the chat id, press Enter

# Random 32-byte hex key. The Worker HMACs each incoming IP with this
# secret before using it as a KV rate-limit key, so the rate-limit
# table can never be reverse-mapped to a real IP.
openssl rand -hex 32 | npx wrangler secret put IP_HASH_SECRET

5. Deploy

npm run deploy

Output ends with the public URL, e.g.

https://speeds-feedback.<your-subdomain>.workers.dev

Save this URL — both extensions will POST to <URL>/feedback.

6. Smoke test

The endpoint requires an Origin header from one of the two extension schemes (chrome-extension://* or moz-extension://*). Real browser fetches send this automatically; for curl you have to spoof it:

curl -X POST https://speeds-feedback.<sub>.workers.dev/feedback \
  -H "Content-Type: application/json" \
  -H "Origin: chrome-extension://smoke-test" \
  -d '{"app":"hdrezka","message":"hello from curl","rating":"positive"}'

Without -H "Origin: ..." the Worker returns 403 forbidden_origin (intended — that’s the abuse gate).

You should:

Endpoints

POST /feedback

Body (JSON):

Field Type Required Description
app "hdrezka" | "videospeeds" yes Which extension is sending
version string no Extension version, e.g. "0.2.0"
rating "positive" | "neutral" | "negative" no User’s mood
message string yes The feedback text (max 4 KB)
email string no Reply-to address (validated)
diagnostics string no JSON-stringified diagnostic report (max 16 KB)
userAgent string no UA string for context
url string no Page URL (origin only — content scripts strip the rest)

Required headers:

Response:

GET /health

Returns plain ok for liveness probes.

Development

npm run dev          # local server on http://localhost:8787
npm run typecheck    # tsc --noEmit
npm run logs         # tail production logs (wrangler tail)

Local dev needs the same secrets — put them in .dev.vars (gitignored):

TELEGRAM_BOT_TOKEN=...
TELEGRAM_CHAT_ID=...
IP_HASH_SECRET=...

Operations

License

GPL-3.0-or-later — same as the extensions it serves.