diff --git a/recipes/substack.recipe b/recipes/substack.recipe new file mode 100644 index 0000000000..eaa9d4e4b9 --- /dev/null +++ b/recipes/substack.recipe @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8 +# +# Title: Substack +# License: GNU General Public License v3 – https://www.gnu.org/licenses/gpl-3.0.html +# Copyright: Nathan Cook (nathan.cook@gmail.com) +## +# Written: 2020-12-18 +## + +__license__ = 'GNU General Public License v3 – https://www.gnu.org/licenses/gpl-3.0.html' +__copyright__ = 'Nathan Cook – 2020-12-19' +__version__ = 'v0.1.1' +__date__ = '2020-12-19' +__author__ = 'topynate' + +import json +from mechanize import Request + +from calibre.web.feeds.news import BasicNewsRecipe + + +class Substack(BasicNewsRecipe): + title = 'Substack' + __author__ ='topynate' + oldest_article = 7 + language = 'en' + max_articles_per_feed = 100 + auto_cleanup = True + needs_subscription = 'optional' + +# Every Substack publication has an RSS feed at https://{name}.substack.com/feed. +# The same URL provides either all posts, or all free posts + previews of paid posts, +# depending on whether you're logged in. + feeds = [ + ('Novum Lumen', 'https://novumlumen.substack.com/feed'), # gratuitously self-promotional example + ] + + def get_browser(self): + br = BasicNewsRecipe.get_browser(self) + if self.username is not None and self.password is not None: + br.open('https://substack.com/account/login?redirect=%2F&email=&with_password=') + data = json.dumps({'email': self.username, 'password': self.password, 'captch_response':None}) + req = Request( + url='https://substack.com/api/v1/login', + headers={ + 'Accept': '*/*', + 'Content-Type': 'application/json', + 'Origin': 'https://substack.com', + 'Referer': 'https://substack.com/account/login?redirect=%2F&email=&with_password=', + }, + data=data, + method='POST') + res = br.open(req) + if res.getcode() != 200: + raise ValueError('Login failed, check username and password') + return br