mirror of
https://github.com/tanrax/RSSingle.git
synced 2025-03-03 03:35:46 +01:00
Compare commits
29 Commits
v1.0.0
...
add-limit-
Author | SHA1 | Date | |
---|---|---|---|
0dfb71de00 | |||
124a57c033 | |||
16e80795cd | |||
4cd87527bd | |||
0a075bbdc9 | |||
62f24bb204 | |||
e8c77f3398 | |||
dd16696103 | |||
846de90642 | |||
e101803091 | |||
c3708e8899 | |||
cf60155018 | |||
82b3ff5cfd | |||
f64d68fb8f | |||
d2813ee689 | |||
9014c78d29 | |||
758733d025 | |||
bbe24f6364 | |||
52ccc2e676 | |||
df52406dfe | |||
3347b233de | |||
ff30f5807b | |||
1460f92f02 | |||
8f499d4c22 | |||
1a94b51f1a | |||
7a8721f6a1 | |||
d622931090 | |||
6eeda374da | |||
cafef51765 |
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
github: tanrax
|
||||
ko_fi: androsfenollosa
|
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
19
README.md
19
README.md
@ -2,6 +2,10 @@
|
||||
|
||||
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.
|
||||
|
||||
<p align="center">
|
||||
<img src="rssingle.png" width="200" alt="RRSingle">
|
||||
</p>
|
||||
|
||||
## Run
|
||||
|
||||
1. Download the binary.
|
||||
@ -12,9 +16,11 @@ Generates an RSS file from the list of other feeds (RSS/Atom/JSON). Very handy w
|
||||
wget https://github.com/tanrax/RSSingle/releases/download/v1.0.0/rssingle
|
||||
```
|
||||
|
||||
**MacOS and Windows**
|
||||
**Windows**
|
||||
|
||||
Coming soon
|
||||
``` shell
|
||||
wget https://github.com/tanrax/RSSingle/releases/download/v1.0.0/rssingle.exe
|
||||
```
|
||||
|
||||
2. Gives execution permissions.
|
||||
|
||||
@ -29,6 +35,7 @@ title: My RSS Feed
|
||||
description: My customised RSS feed with technology news
|
||||
url: https://www.example.com
|
||||
output: rss.xml
|
||||
max_entries: 5 # Delete this line to get all
|
||||
feeds:
|
||||
- https://programadorwebvalencia.com/feed/
|
||||
- https://republicaweb.es/feed/
|
||||
@ -43,13 +50,19 @@ curl -o config.yml https://raw.githubusercontent.com/tanrax/RSSingle/master/conf
|
||||
4. Run the binary.
|
||||
|
||||
``` shell
|
||||
./rssingle
|
||||
./rssingle
|
||||
```
|
||||
|
||||
A file called `rss.xml` will be created.
|
||||
|
||||
## Development
|
||||
|
||||
Activate Debug messages by console.
|
||||
|
||||
```
|
||||
export SR_LOG_LEVEl=DEBUG
|
||||
```
|
||||
|
||||
### Compiling
|
||||
|
||||
```shell
|
||||
|
@ -2,6 +2,7 @@ title: My RSS Feed
|
||||
description: My customised RSS feed with technology news
|
||||
url: https://www.example.com
|
||||
output: rss.xml
|
||||
max_entries: 2 # Delete this line to get all
|
||||
feeds:
|
||||
- https://programadorwebvalencia.com/feed/
|
||||
- https://republicaweb.es/feed/
|
||||
- https://republicaweb.es/feed/
|
||||
|
@ -1,7 +1,7 @@
|
||||
feedgen==0.9.0
|
||||
feedparser==6.0.10
|
||||
listparser==0.19.0
|
||||
lxml==4.9.0
|
||||
lxml==4.9.3
|
||||
python-dateutil==2.8.2
|
||||
pyyaml==6.0
|
||||
pyinstaller==5.1
|
||||
pyinstaller==6.0.0
|
@ -1,5 +0,0 @@
|
||||
# For stdout to file
|
||||
0 * * * * cd /opt/rss && . ./.env && /opt/rss/singlerss.py > /var/www/html/feeds.xml
|
||||
|
||||
# For file direct.
|
||||
0 * * * * cd /opt/rss && . ./.env && /opt/rss/singlerss.py
|
@ -1,26 +0,0 @@
|
||||
[Unit]
|
||||
Description=Generate combined RSS feed.
|
||||
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
# Make sure to set user and group
|
||||
# to your setup.
|
||||
User=nginx
|
||||
Group=nobody
|
||||
|
||||
# Make sure to customise these to your
|
||||
# system!
|
||||
WorkingDirectory=/var/www/html/feed.xml
|
||||
# And this.
|
||||
EnvironmentFile=/opt/singlerss/.env
|
||||
# And this.
|
||||
ExecStart=/opt/rss/singlerss.py
|
||||
|
||||
# These don't work on older systemd versions.
|
||||
# In that case, you should configure singlerss
|
||||
# to output to file, as documented in the README,
|
||||
# and comment these directives out.
|
||||
StandardInput=null
|
||||
StandardError=journal
|
||||
StandardOutput=file:$SINGLERSS_FEED_OUT_PATH
|
@ -1,8 +0,0 @@
|
||||
[Unit]
|
||||
Description=Hourly refresh of singlerss
|
||||
|
||||
[Timer]
|
||||
OnCalendar=hourly
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
BIN
rssingle.png
Normal file
BIN
rssingle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
44
rssingle.py
44
rssingle.py
@ -22,7 +22,6 @@ CONFIG_PATH = "config.yml"
|
||||
LOG_LEVEL = environ.get("SR_LOG_LEVEl", "ERROR")
|
||||
fg = None
|
||||
FEED_OUT_PATH = None
|
||||
FEED_LIST_PATH = None
|
||||
FEEDS = []
|
||||
CFG = None
|
||||
|
||||
@ -45,7 +44,7 @@ def setup_logging() -> None:
|
||||
return None
|
||||
|
||||
|
||||
def get_url_from_feed(config):
|
||||
def get_url_from_feed(config) -> str:
|
||||
"""
|
||||
This function returns the URL from a feed.
|
||||
"""
|
||||
@ -70,9 +69,8 @@ def init_feed() -> None:
|
||||
fg.link(href=get_url_from_feed(CONFIG), rel="self")
|
||||
fg.subtitle(CONFIG["description"])
|
||||
fg.language("en")
|
||||
except:
|
||||
log.error("Error initialising the feed!")
|
||||
sys.exit(1)
|
||||
except BaseException: # find out what exceptions FeedGenerator can cause as well as KeyError.
|
||||
logging.exception("Error initialising the feed!")
|
||||
|
||||
log.debug("Feed initialised!")
|
||||
|
||||
@ -85,7 +83,7 @@ def parse_rss_feed(url) -> feedparser.FeedParserDict:
|
||||
try:
|
||||
# Hopefully this should parse..
|
||||
return feedparser.parse(url)
|
||||
except Exception:
|
||||
except BaseException: # find out what exceptions .parse() call can cause.
|
||||
log.warning("Failed to parse RSS feed.")
|
||||
# Now, we could handle gracefully.
|
||||
|
||||
@ -99,7 +97,7 @@ def main():
|
||||
rss = parse_rss_feed(feed)
|
||||
entries = rss.get("entries")
|
||||
log.debug("Iterating over [input] feed entries..")
|
||||
for entry in entries:
|
||||
for entry in entries[:CONFIG["max_entries"]] if "max_entries" in CONFIG else entries:
|
||||
log.debug("New feed entry created.")
|
||||
|
||||
fe = fg.add_entry()
|
||||
@ -108,21 +106,21 @@ def main():
|
||||
|
||||
try:
|
||||
fe.id(entry["id"])
|
||||
except:
|
||||
# Deifnitely weird...
|
||||
except KeyError:
|
||||
# Definitely weird...
|
||||
log.warning("Empty id attribute, defaulting..")
|
||||
fe.id("about:blank")
|
||||
|
||||
try:
|
||||
fe.title(entry["title"])
|
||||
except:
|
||||
except KeyError:
|
||||
# OK, this is a definite malformed feed!
|
||||
log.warning("Empty title attribute, defaulting..")
|
||||
fe.title("Unspecified")
|
||||
|
||||
try:
|
||||
fe.link(href=entry["link"])
|
||||
except:
|
||||
except KeyError:
|
||||
# When we have a empty link attribute, this isn't ideal
|
||||
# to set a default value.. :/
|
||||
log.warning("Empty link attribute, defaulting..")
|
||||
@ -136,12 +134,12 @@ def main():
|
||||
try:
|
||||
for author in entry["authors"]:
|
||||
fe.author(author)
|
||||
except:
|
||||
except KeyError:
|
||||
log.debug("Oh dear, a malformed feed! Adjusting.")
|
||||
# This is a ugly hack to fix broken feed entries with the author attribute!
|
||||
author["email"] = author.pop("href")
|
||||
fe.author(author)
|
||||
except:
|
||||
except KeyError:
|
||||
# Sometimes we don't have ANY author attributes, so we
|
||||
# have to set a dummy attribute.
|
||||
log.warning("Empty authors attribute, defaulting..")
|
||||
@ -155,7 +153,7 @@ def main():
|
||||
fe.description(entry["description"])
|
||||
fe.summary(entry["description"])
|
||||
fe.content(entry["description"])
|
||||
except:
|
||||
except KeyError:
|
||||
# Sometimes feeds don't provide a summary OR description, so we
|
||||
# have to set an empty value.
|
||||
# This is pretty useless for a feed, so hopefully we
|
||||
@ -169,11 +167,11 @@ def main():
|
||||
try:
|
||||
fe.published(entry["published"])
|
||||
fe.updated(entry["published"])
|
||||
except:
|
||||
except KeyError:
|
||||
fe.published("1970-01/01T00:00:00+00:00")
|
||||
fe.updated("1970-01/01T00:00:00+00:00")
|
||||
continue
|
||||
except:
|
||||
except Exception:
|
||||
# Sometimes feeds don't even provide a publish date, so we default to
|
||||
# the start date &time of the Unix epoch.
|
||||
log.warning("Empty publish attribute, defaulting..")
|
||||
@ -201,20 +199,6 @@ if __name__ == "__main__":
|
||||
log.error("This program will NOT run without that set.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
FEED_LIST_PATH = CONFIG["url"]
|
||||
except:
|
||||
log.error("*** Configure variable missing! ***")
|
||||
log.error("`url` variable missing.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
FEED_LIST_PATH = CONFIG["feeds"]
|
||||
except:
|
||||
log.error("*** Configure variable missing! ***")
|
||||
log.error("`feeds` variable missing.")
|
||||
sys.exit(1)
|
||||
|
||||
init_feed()
|
||||
|
||||
log.debug("Begin processing feeds...")
|
||||
|
Reference in New Issue
Block a user