First commit

This commit is contained in:
Andros Fenollosa 2022-06-19 18:17:57 +02:00
parent e1536c89dd
commit 5edf3eeda1
6 changed files with 79 additions and 61 deletions

View File

@ -1,3 +0,0 @@
SINGLERSS_FEED_OUT_PATH=
SINGLERSS_FEED_LIST_PATH=
SINGLERSS_FEED_OUT_TYPE=

View File

@ -1,37 +1,41 @@
singlerss
=========
# RSSingle
# Description
Generates an RSS file from the list of other feeds (RSS/Atom/JSON). Very handy when you want to centralise the list of your feeds in one place and all your devices feed from the same place.
singlerss combines all feeds described in a OPML file into one feed. This can
either be outputted into `stdout` or a file, as specifed by program arguments,
and configured by the environment variables.
## Run
# Configuration
1. Download the binary.
SingleRSS is configured by environment variables.
``` shell
wget
```
See `.env.sample`. You _must_ copy `.env.sample` to `.env`.
2. Gives execution permissions.
`SINGLERSS_FEED_OUT_PATH` defines the relative OR absolute path to output the
feed to, _IF_ `SINGLERSS_FEED_OUT_TYPE` is set to `file`. If
`SINGLERSS_FEED_OUT_TYPE` is set to `stdout`, you must redirect output to the
file you want it written to.
``` shell
chmod +x rssingle
```
`SINGLERSS_FEED_LIST_PATH` must be set to the input list of feeds you want to be
collated into one feed. This _must_ be a newline delimited file of URLs.
3. In the same directory as the binary, you can create a local `config.yml` file in this format:
## Running
``` yaml
title: My RSS Feed
description: My customised RSS feed with technology news
feeds:
- https://programadorwebvalencia.com/feed/
- https://republicaweb.es/feed/
```
You may run this directly, after sourcing `.env` and exporting the variables,
with `./singlerss.py`. Alternatively, I have provided a systemd unit and timer,
which I will offer support for, and a basic crontab. I do not use cron, so I
cannot offer support for it.
If not, you can download the example in the repository.
# Licensing
4. Run the binary.
This program is [licensed][license] under the Apache License 2.0.
``` shell
./rssingle
```
Copyright (c) Dom Rodriguez (shymega) 2020.
A file called `rss.xml` will be created.
[license]: /LICENSE
## Thanks
@shymega for his original project [singlerss](https://github.com/shymega/singlerss).

7
config.yml Normal file
View File

@ -0,0 +1,7 @@
title: My RSS Feed
description: My customised RSS feed with technology news
url: https://www.example.com
output: rss.xml
feeds:
- https://programadorwebvalencia.com/feed/
- https://republicaweb.es/feed/

View File

@ -1,5 +1,7 @@
feedgen==0.9.0
feedparser==5.2.1
lxml==4.6.5
python-dateutil==2.8.1
six==1.15.0
feedparser==6.0.10
listparser==0.19.0
lxml==4.9.0
python-dateutil==2.8.2
pyyaml==6.0
pyinstaller==5.1

2
rss.xml Normal file
View File

@ -0,0 +1,2 @@
<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>My RSS Feed</title><link>https://www.example.com/index.xml</link><description>My customised RSS feed with technology news</description><atom:link href="https://www.example.com/index.xml" rel="self"/><docs>http://www.rssboard.org/rss-specification</docs><generator>RSSingle/v1.0.0</generator><language>en</language><lastBuildDate>Sun, 19 Jun 2022 16:09:40 +0000</lastBuildDate></channel></rss>

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
# Copyright (c) Dom Rodriguez 2020
# Copyright (c) Andros Fenollosa 2022
# Licensed under the Apache License 2.0
import os
@ -11,18 +12,23 @@ import listparser
from os import environ
from feedgen.feed import FeedGenerator
import json
import yaml
# Varaibles
log = None
CONFIG_PATH = "config.yml"
LOG_LEVEL = environ.get("SR_LOG_LEVEl", "ERROR")
fg = None
FEED_OUT_PATH = None
FEED_OUT_TYPE = None
FEED_LIST_PATH = None
FEEDS = []
CFG = None
def setup_logging() -> None:
"""
This function intiialises the logger framework.
@ -38,6 +44,11 @@ def setup_logging() -> None:
return None
def get_url_from_feed(config):
"""
This function returns the URL from a feed.
"""
return config["url"] + "/" + config["output"]
def init_feed() -> None:
"""
@ -51,11 +62,11 @@ def init_feed() -> None:
try:
fg = FeedGenerator()
# Setup [root] feed attributes
fg.id("https://rss.shymega.org.uk/feed.xml")
fg.title("SingleRSS - Combined Feed")
fg.generator("SingleRSS/v1.0.0")
fg.link(href="https:/rss.shymega.org.uk/feed.xml", rel="self")
fg.subtitle("Combined feed for RSS feeds")
fg.id(get_url_from_feed(CONFIG))
fg.title(CONFIG["title"])
fg.generator("RSSingle/v1.0.0")
fg.link(get_url_from_feed(CONFIG), rel="self")
fg.subtitle(CONFIG["description"])
fg.language('en')
except:
log.error("Error initialising the feed!")
@ -80,7 +91,7 @@ def parse_rss_feed(url) -> feedparser.FeedParserDict:
def main():
log.debug("Loading feed list into memory..")
feeds = None
with open(FEED_LIST_PATH, "r") as infile:
with open(CONFIG_PATH, "r") as infile:
feeds = infile.read().splitlines()
log.debug("Iterating over feed list..")
@ -180,44 +191,39 @@ if __name__ == "__main__":
setup_logging()
log.debug("Initialising...")
global CONFIG
with open('config.yml', 'r') as file:
CONFIG = yaml.safe_load(file)
log.debug("Assiging variables..")
try:
# Configuration is specified with environemnt variables.
log.debug("Assignment attempt: SINGLERSS_FEED_OUT_PATH")
FEED_OUT_PATH = os.environ["SINGLERSS_FEED_OUT_PATH"]
# Configuration is specified with configure variables.
log.debug("Assignment attempt: output")
FEED_OUT_PATH = CONFIG["output"]
except KeyError:
log.error("*** Environment variable missing! ***")
log.error("`SINGLERSS_FEED_OUT_PATH` variable missing.")
log.error("*** Configure variable missing! ***")
log.error("`output` variable missing.")
log.error("This program will NOT run without that set.")
sys.exit(1)
try:
FEED_LIST_PATH = os.environ["SINGLERSS_FEED_LIST_PATH"]
FEED_LIST_PATH = CONFIG["url"]
except:
log.error("*** Environment variable missing! ***")
log.error("`SINGLERSS_FEED_LIST_PATH` variable missing.")
log.error("*** Configure variable missing! ***")
log.error("`url` variable missing.")
sys.exit(1)
try:
FEED_OUT_TYPE = os.environ["SINGLERSS_FEED_OUT_TYPE"]
except KeyError:
log.error("*** Environment variable missing! ***")
log.error("`SINGLERSS_FEED_OUT_TYPE` variable missing.")
log.error("This program will NOT run without that set.")
FEED_LIST_PATH = CONFIG["feeds"]
except:
log.error("*** Configure variable missing! ***")
log.error("`feeds` variable missing.")
sys.exit(1)
log.debug("Begin initialising variables..")
init_feed()
log.debug("Begin processing feeds...")
main()
if FEED_OUT_TYPE == "stdout":
log.debug("stdout output specified, outputting to stdout.")
print(fg.rss_str().decode('utf-8'))
elif FEED_OUT_TYPE == "file":
log.debug("File output specified, outputting to specified file..")
fg.rss_file(FEED_OUT_PATH)
else:
log.error("Unknown type of output preference, cannot run.")
sys.exit(1)
fg.rss_file(FEED_OUT_PATH)