├── README.md ├── LICENSE └── lobsters-bisque.py /README.md: -------------------------------------------------------------------------------- 1 | # lobsters-bisque 2 | 3 | Simple script to generate a RSS feed for [Lobsters](https://lobste.rs) that 4 | does the following: 5 | 6 | - Filter articles by a minimum score 7 | - Utilizes the comments link rather than original article link 8 | 9 | Inspired by [Hacker News RSS](https://edavis.github.io/hnrss/). 10 | 11 | # CRONTAB 12 | 13 | Here is an example of how to use `cron` to execute the script every `10` 14 | minutes: 15 | 16 | ``` 17 | */10 * * * * /path/to/lobsters-bisque/lobsters-bisque.py > /path/to/lobsters-bisque.rss 18 | ``` 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Peter Bui 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lobsters-bisque.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import dbm.gnu 4 | import feedparser 5 | import os 6 | import requests 7 | import time 8 | 9 | # Constants 10 | 11 | LOBSTERS_FEED_URL = 'https://lobste.rs/rss' 12 | LOBSTERS_MINIMUM_SCORE = 10 13 | LOBSTERS_SCORES_CACHE = os.path.expanduser('~/.cache/lobsters.scores') 14 | 15 | # Functions 16 | 17 | def fetch_article_score(url, cache): 18 | if url not in cache or int(cache[url]) < LOBSTERS_MINIMUM_SCORE: 19 | response = requests.get(url + '.json') 20 | cache[url] = str(response.json()['score']) 21 | time.sleep(0.1) # Workaround rate limit 22 | 23 | return int(cache[url]) 24 | 25 | def fetch_all_articles(url=LOBSTERS_FEED_URL): 26 | feed = feedparser.parse(url) 27 | 28 | with dbm.open(LOBSTERS_SCORES_CACHE, 'c') as cache: 29 | for entry in feed.entries: 30 | yield { 31 | 'title' : entry.title, 32 | 'author' : entry.author.split('@')[0], 33 | 'link' : entry.comments, 34 | 'published': entry.published, 35 | 'timestamp': entry.published_parsed, 36 | 'guid' : entry.guid, 37 | 'score' : fetch_article_score(entry.comments, cache), 38 | } 39 | 40 | def write_articles_feed(articles): 41 | print(''' 42 | 43 | 44 | Lobsters 45 | https://lobste.rs 46 | ''') 47 | 48 | for article in sorted(articles, key=lambda a: a['timestamp'], reverse=True): 49 | print(''' 50 | {article_title} 51 | {article_author} 52 | {article_link} 53 | {article_guid} 54 | {article_published} 55 | '''.format(article_title = article['title'], 56 | article_author = article['author'], 57 | article_link = article['link'], 58 | article_guid = article['guid'], 59 | article_published = article['published'])) 60 | print(''' 61 | ''') 62 | 63 | # Main Execution 64 | 65 | if __name__ == '__main__': 66 | write_articles_feed(a for a in fetch_all_articles() if a['score'] > LOBSTERS_MINIMUM_SCORE) 67 | --------------------------------------------------------------------------------