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 ## Run
either be outputted into `stdout` or a file, as specifed by program arguments,
and configured by the environment variables.
# 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 ``` shell
feed to, _IF_ `SINGLERSS_FEED_OUT_TYPE` is set to `file`. If chmod +x rssingle
`SINGLERSS_FEED_OUT_TYPE` is set to `stdout`, you must redirect output to the ```
file you want it written to.
`SINGLERSS_FEED_LIST_PATH` must be set to the input list of feeds you want to be 3. In the same directory as the binary, you can create a local `config.yml` file in this format:
collated into one feed. This _must_ be a newline delimited file of URLs.
## 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, If not, you can download the example in the repository.
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.
# 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 feedgen==0.9.0
feedparser==5.2.1 feedparser==6.0.10
lxml==4.6.5 listparser==0.19.0
python-dateutil==2.8.1 lxml==4.9.0
six==1.15.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 #!/usr/bin/env python3
# Copyright (c) Dom Rodriguez 2020 # Copyright (c) Dom Rodriguez 2020
# Copyright (c) Andros Fenollosa 2022
# Licensed under the Apache License 2.0 # Licensed under the Apache License 2.0
import os import os
@ -11,18 +12,23 @@ import listparser
from os import environ from os import environ
from feedgen.feed import FeedGenerator from feedgen.feed import FeedGenerator
import json import json
import yaml
# Varaibles
log = None log = None
CONFIG_PATH = "config.yml"
LOG_LEVEL = environ.get("SR_LOG_LEVEl", "ERROR") LOG_LEVEL = environ.get("SR_LOG_LEVEl", "ERROR")
fg = None fg = None
FEED_OUT_PATH = None FEED_OUT_PATH = None
FEED_OUT_TYPE = None
FEED_LIST_PATH = None FEED_LIST_PATH = None
FEEDS = [] FEEDS = []
CFG = None CFG = None
def setup_logging() -> None: def setup_logging() -> None:
""" """
This function intiialises the logger framework. This function intiialises the logger framework.
@ -38,6 +44,11 @@ def setup_logging() -> None:
return 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: def init_feed() -> None:
""" """
@ -51,11 +62,11 @@ def init_feed() -> None:
try: try:
fg = FeedGenerator() fg = FeedGenerator()
# Setup [root] feed attributes # Setup [root] feed attributes
fg.id("https://rss.shymega.org.uk/feed.xml") fg.id(get_url_from_feed(CONFIG))
fg.title("SingleRSS - Combined Feed") fg.title(CONFIG["title"])
fg.generator("SingleRSS/v1.0.0") fg.generator("RSSingle/v1.0.0")
fg.link(href="https:/rss.shymega.org.uk/feed.xml", rel="self") fg.link(get_url_from_feed(CONFIG), rel="self")
fg.subtitle("Combined feed for RSS feeds") fg.subtitle(CONFIG["description"])
fg.language('en') fg.language('en')
except: except:
log.error("Error initialising the feed!") log.error("Error initialising the feed!")
@ -80,7 +91,7 @@ def parse_rss_feed(url) -> feedparser.FeedParserDict:
def main(): def main():
log.debug("Loading feed list into memory..") log.debug("Loading feed list into memory..")
feeds = None feeds = None
with open(FEED_LIST_PATH, "r") as infile: with open(CONFIG_PATH, "r") as infile:
feeds = infile.read().splitlines() feeds = infile.read().splitlines()
log.debug("Iterating over feed list..") log.debug("Iterating over feed list..")
@ -180,44 +191,39 @@ if __name__ == "__main__":
setup_logging() setup_logging()
log.debug("Initialising...") log.debug("Initialising...")
global CONFIG
with open('config.yml', 'r') as file:
CONFIG = yaml.safe_load(file)
log.debug("Assiging variables..") log.debug("Assiging variables..")
try: try:
# Configuration is specified with environemnt variables. # Configuration is specified with configure variables.
log.debug("Assignment attempt: SINGLERSS_FEED_OUT_PATH") log.debug("Assignment attempt: output")
FEED_OUT_PATH = os.environ["SINGLERSS_FEED_OUT_PATH"] FEED_OUT_PATH = CONFIG["output"]
except KeyError: except KeyError:
log.error("*** Environment variable missing! ***") log.error("*** Configure variable missing! ***")
log.error("`SINGLERSS_FEED_OUT_PATH` variable missing.") log.error("`output` variable missing.")
log.error("This program will NOT run without that set.") log.error("This program will NOT run without that set.")
sys.exit(1) sys.exit(1)
try: try:
FEED_LIST_PATH = os.environ["SINGLERSS_FEED_LIST_PATH"] FEED_LIST_PATH = CONFIG["url"]
except: except:
log.error("*** Environment variable missing! ***") log.error("*** Configure variable missing! ***")
log.error("`SINGLERSS_FEED_LIST_PATH` variable missing.") log.error("`url` variable missing.")
sys.exit(1) sys.exit(1)
try: try:
FEED_OUT_TYPE = os.environ["SINGLERSS_FEED_OUT_TYPE"] FEED_LIST_PATH = CONFIG["feeds"]
except KeyError: except:
log.error("*** Environment variable missing! ***") log.error("*** Configure variable missing! ***")
log.error("`SINGLERSS_FEED_OUT_TYPE` variable missing.") log.error("`feeds` variable missing.")
log.error("This program will NOT run without that set.")
sys.exit(1) sys.exit(1)
log.debug("Begin initialising variables..")
init_feed() init_feed()
log.debug("Begin processing feeds...") log.debug("Begin processing feeds...")
main() 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) fg.rss_file(FEED_OUT_PATH)
else:
log.error("Unknown type of output preference, cannot run.")
sys.exit(1)