Cloudflare worker to watch RSS feeds and post updates to Discord webhooks
1# bzzrt
2
3A Cloudflare Worker that polls RSS and Atom feeds for new entries and posts them to Discord channels via webhooks.
4
5## Features
6
7- **Multi-format feed support** — Handles RSS, Atom, RDF, and JSON Feed via [feedsmith](https://github.com/macieklamberski/feedsmith)
8- **Multi-feed, multi-channel** — Monitor any number of feeds and route each to one or more Discord channels
9- **Deduplication** — Tracks the last-seen entry date per feed in Cloudflare KV to avoid reposting
10- **Cron-driven** — Runs automatically every 5 minutes via Cloudflare's cron triggers
11- **Manual trigger** — `GET /check` to trigger a feed check on demand
12- **Discord embeds** — Posts entries as rich embeds with title, link, summary, timestamp, and author
13
14## Architecture
15
16```
17feeds.json — Feed URL → Discord channel mapping
18worker.js — Main worker: cron handler, fetch handler, feed checking, Discord posting
19wrangler.toml — Cloudflare Worker configuration
20.dev.vars — Local-only secrets (WEBHOOKS)
21```
22
23**Flow:**
24
251. Every 5 minutes (or on `GET /check`), the worker iterates over feeds defined in `feeds.json`
262. For each feed, it fetches the URL, parses it with `parseFeed()`, and normalizes entries into a common shape
273. It compares entry dates against the last-posted timestamp stored in Cloudflare KV
284. New entries are posted as embeds to the configured Discord webhook(s)
295. The latest entry date is saved back to KV
30
31## Setup
32
33### Prerequisites
34
35- Node.js
36- A Cloudflare account with Workers enabled
37- A Cloudflare KV namespace
38- One or more Discord webhook URLs
39
40### Configuration
41
42**feeds.json** — Map feed URLs to Discord channel names:
43
44```json
45{
46 "https://example.com/feed.xml": ["general"],
47 "https://example.com/blog/atom.xml": ["blog", "general"]
48}
49```
50
51**WEBHOOKS secret** — A JSON object mapping channel names to Discord webhook URLs. Set it as a Cloudflare secret:
52
53```bash
54npx wrangler secret put WEBHOOKS
55# Paste: {"general":"https://discord.com/api/webhooks/...","blog":"https://discord.com/api/webhooks/..."}
56```
57
58For local development, put the same value in `.dev.vars`:
59
60```
61WEBHOOKS = {"general":"https://discord.com/api/webhooks/..."}
62```
63
64**wrangler.toml** — Update the KV namespace ID if creating a new one:
65
66```bash
67npx wrangler kv namespace create KV
68# Update the id in wrangler.toml
69```
70
71## Development
72
73```bash
74npm install
75npx wrangler dev --test-scheduled
76```
77
78The worker runs locally at `http://localhost:8787`. Visit `/check` to trigger a feed check, or `/__scheduled` to simulate a cron trigger.
79
80## Deployment
81
82```bash
83npx wrangler deploy
84```
85
86Wrangler bundles the worker and deploys it to Cloudflare with the cron trigger active.