Bridging RSS to Discord for free (using Google Cloud)
28.10.2026
3 min
Who said RSS is dead?
Recently one of my friends wanted to have a Discord channel where she could receive news feeds from all across the country. Because every Discord bot that does it sucks, I decided to do the bridge myself!
The main idea
In general, it is pretty simple. You make a Python script that queries an RSS feed, parses it, and sends the content via a Discord webhook, and you run it every few minutes/hours. Additionally, you will also need a file to store the last item sent, to avoid duplicates.
This is pretty simple to implement in just a few lines of Python with the feedparser and requests library. I simplified the script to only bridge a single feed but it is pretty simple to extend it to also bridge multiple feeds.
import json
import requests
import feedparser
import os
from pathlib import Path
source = "https://lorem-rss.herokuapp.com/feed?unit=second&interval=30"
webhook = os.environ['DISCORD_WEBHOOK']
if Path("cache.json").exists():
cache = json.loads(Path("cache.json").read_text(encoding="utf-8"))
else:
cache = {}
request = requests.get(source)
parsed = feedparser.parse(request.content)
if parsed.entries:
latest = parsed.entries[0]
if cache.get("feed") != latest.id:
url = latest.get("url") or latest.get("link")
payload = {
"content": f"{latest.title} - <{url}>"
}
requests.post(webhook, json=payload)
cache["feed"] = latest.id
with open("cache.json", "w+") as f:
json.dump(cache, f)
Now I could have stopped here, SSH'd into one of my servers, setup a cronjob and just forget about it but I have a gigantic problem: I CANNOT TRUST MYSELF TO HOST ANYTHING FOR MORE THAN A FEW MONTHS. Seriously. Every few months I get bored and I just refurbish literally everything. I guess I just really enjoy reinstalling linux for the Nth time. Anyways, where were we? Right.
Using Github Actions
My first idea for hosting this was by abusing Github Actions. So I setup a Github account, created a simple workflow that ran the script every 5 minutes, and thought that was the end of it. As I sadly learned, Github's cron scheduler is... well... not exactly the most accurate. Many of the jobs were running once an hour instead of once every 5 minutes and we were losing valuable news stories, such as Two men, sentenced by Alba Iulia magistrates after they went drunk driving with a stolen car.
I started looking around to see if anyone had any similar issues and I saw someone use a Google Cloud Cloud Scheduler to run a Google Cloud Cloud Function (what a mouthful!) that runs the Github Action every 5 minutes. But what is the point of having a Github workflow if you are gonna use something external to trigger it anyways? So I decided to drop Github.
Using Google Cloud
I'm sure there are houndreds of services offering this, but I decided to go with Google Cloud. Why?
- It's free
- It was the one that guy from earlier used
- Seems simple.. right?
Adapting the script to run via Cloud Functions required two new dependencies: functions-framework and google-cloud-storage. functions-framework is self explanatory, but why would you need google-cloud-storage? Well, it's for the cahce.json file from earlier. It needs to be stored in a bucket as file edits don't persist across function runs.
The script went from what was earlier to..
import functions_framework
import json
import requests
import feedparser
import os
from pathlib import Path
from google.cloud import storage
# note to anyone using this, I didn't test this but it should work, send me an email if it doesnt
@functions_framework.http
def brdige(request):
source = "https://lorem-rss.herokuapp.com/feed?unit=second&interval=30"
webhook = os.environ['DISCORD_WEBHOOK']
storage_client = storage.Client()
bucket = storage_client.bucket("[YOUR BUCKET HERE]")
blob = bucket.blob("cache.json")
if blob.exists():
cache = json.loads(blob.download_as_text())
else:
cache = {}
request = requests.get(source)
parsed = feedparser.parse(request.content)
if parsed.entries:
latest = parsed.entries[0]
if cache.get("feed") != latest.id:
url = latest.get("url") or latest.get("link")
payload = {
"content": f"{latest.title} - <{url}>"
}
requests.post(webhook, json=payload)
cache["feed"] = latest.id
blob.upload_from_string(
json.dumps(cache),
content_type="application/json",
)
return "success"
... this! If you are curious as to why the script has @functions_framework.http, well, everything is a http endpoint with Cloud Functions.
After setting up the Cloud Function, I setup a Cloud Scheduler to send a request to it every 5 minutes and bazinga! I can have a feed of the most important headlines from my country, such as: Romanians pay online with deferred payments six times a year. Women buy more often, men spend more. Analysis, from the comfort of my Discord client.