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?

  1. It's free
  2. It was the one that guy from earlier used
  3. 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.