diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..4c89c8a --- /dev/null +++ b/api/__init__.py @@ -0,0 +1 @@ +from .api import WallabagAPI diff --git a/api/api.py b/api/api.py new file mode 100644 index 0000000..fb631bc --- /dev/null +++ b/api/api.py @@ -0,0 +1,67 @@ +import hashlib +from datetime import datetime +from typing import Dict, List + +from requests import Session + + +class WallabagAPI: + def __init__(self, host: str, + user_agent="RSS2Wallabag +https://github.com/Findus23/rss2wallabag", + requests_session: Session = None + ) -> None: + + self.host = host + self.token = None + self.user_agent = user_agent + if requests_session: + self.s = requests_session + else: + self.s = Session() + self.s.headers.update({"User-Agent": user_agent}) + + def auth(self, client_id: str, client_secret: str, username: str, password: str) -> None: + r = self.s.post(self.host + "/oauth/v2/token", data={ + "grant_type": "password", + "client_id": client_id, + "client_secret": client_secret, + "username": username, + "password": password + }) + r.raise_for_status() + self.token = r.json()["access_token"] + + def check_auth(self): + if not self.token: + raise RuntimeError("call auth() first to log in") + + @property + def auth_headers(self) -> Dict[str, str]: + self.check_auth() + return {"Authorization": "Bearer " + self.token} + + def add_entry(self, url: str, title: str = None, + tags: List[str] = None, published: datetime = None) -> None: + if tags is None: + tags = [] + + data = { + "url": url, + } + if title: + data["title"] = title + if tags: + data["tags"] = ",".join(tags) + if published: + data["published_at"] = published.timestamp() + # TODO: doesn't seem to be working + r = self.s.post(self.host + "/api/entries.json", data=data, headers=self.auth_headers) + r.raise_for_status() + + def check_exist(self, url: str) -> bool: + sha1 = hashlib.sha1(url.encode()).hexdigest() + r = self.s.get(self.host + "/api/entries/exists.json", params={ + "hashed_url": sha1, + }, headers=self.auth_headers) + r.raise_for_status() + return r.json()["exists"] diff --git a/config.example.yaml b/config.example.yaml index 1a8eb97..0484cc4 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -5,4 +5,4 @@ wallabag: username: username password: password github_username: Findus23 -debug: false \ No newline at end of file +debug: false diff --git a/github_stars.py b/github_stars.py deleted file mode 100644 index e5b19cc..0000000 --- a/github_stars.py +++ /dev/null @@ -1,14 +0,0 @@ -import requests - - -def get_starred_repos(username, feeds): - r = requests.get("https://api.github.com/users/{user}/starred".format(user=username)) - stars = r.json() - for repo in stars: - if repo["full_name"] not in feeds: - feeds[repo["full_name"]] = { - "url": repo["html_url"] + "/releases.atom", - "tags": ["github", repo["name"]], - "github": True - } - return feeds diff --git a/main.py b/main.py index bdd63a2..38911b2 100644 --- a/main.py +++ b/main.py @@ -1,122 +1,165 @@ -import asyncio import logging import sys +from dataclasses import dataclass +from datetime import datetime from time import mktime +from typing import List, Optional, Dict from urllib.parse import urljoin -import aiohttp import feedparser -import sentry_sdk +import requests import yaml -from wallabag_api.wallabag import Wallabag +from feedparser import FeedParserDict -import github_stars - -logger = logging.getLogger() -logger.handlers = [] -formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') -logger.setLevel(logging.DEBUG) - -with open("config.yaml", 'r') as stream: - try: - config = yaml.safe_load(stream) - except (yaml.YAMLError, FileNotFoundError) as exception: - config = None - exit(1) - -production = "debug" not in config or not config["debug"] - -ch = logging.StreamHandler(stream=sys.stdout) -ch.setLevel(logging.WARNING if production else logging.DEBUG) -ch.setFormatter(formatter) -logger.addHandler(ch) - -fh = logging.FileHandler('debug.log') -fh.setFormatter(formatter) -fh.setLevel(logging.WARNING if production else logging.DEBUG) -logger.addHandler(fh) - -if "sentry_url" in config and (production): - sentry_sdk.init(dsn=config["sentry_url"]) - -with open("sites.yaml", 'r') as stream: - try: - sites = yaml.safe_load(stream) - except (yaml.YAMLError, FileNotFoundError) as exception: - logger.error(exception) - sites = None - exit(1) +from api import WallabagAPI -async def fetch(session, url): - try: - async with session.get(url) as response: - return await response.text() - except Exception as e: - logging.exception("failed to fetch {url}".format(url=url)) +@dataclass +class WallabagConfig: + host: str + client_id: str + client_secret: str + username: str + password: str -async def main(loop, sites): - token = await Wallabag.get_token(**config["wallabag"]) +class Config: + def __init__(self): + with open("config.yaml", 'r') as stream: + data = yaml.safe_load(stream) + self.wallabag = WallabagConfig(**data["wallabag"]) + if data["github_username"]: + self.github_username = data["github_username"] + else: + self.github_username = None + self.debug = data["debug"] - async with aiohttp.ClientSession(loop=loop) as session: - wall = Wallabag(host=config["wallabag"]["host"], client_secret=config["wallabag"]["client_secret"], - client_id=config["wallabag"]["client_id"], token=token, aio_sess=session) - - if "github_username" in config: - sites = github_stars.get_starred_repos(config["github_username"], sites) - - await asyncio.gather(*[handle_feed(session, wall, sitetitle, site) for sitetitle, site in sites.items()]) + @property + def production(self): + return not self.debug -async def handle_feed(session, wall, sitetitle, site): - logger.info("Downloading feed: " + sitetitle) - rss = await fetch(session, site["url"]) - logger.info("Parsing feed: " + sitetitle) +@dataclass +class Site: + title: str + url: str + github: bool + tags: List[str] + latest_article: Optional[str] + + +def load_sites() -> Dict[str, Site]: + with open("sites.yaml", 'r') as stream: + data = yaml.safe_load(stream) + sites: Dict[str, Site] = {} + for title, entry in data.items(): + if "latest_article" not in entry: + entry["latest_article"] = None + if "github" not in entry: + entry["github"] = None + sites[title] = Site(title, **entry) + return sites + + +def get_starred_repos(username, sites: Dict[str, Site]): + r = requests.get("https://api.github.com/users/{user}/starred".format(user=username)) + stars = r.json() + for repo in stars: + if repo["full_name"] not in sites: + sites[repo["full_name"]] = Site( + url=repo["html_url"] + "/releases.atom", + tags=["github", repo["name"]], + github=True, + title=repo["full_name"], + latest_article=None + ) + return sites + + +def main(): + sites = load_sites() + config = Config() + + logger = logging.getLogger() + logger.handlers = [] + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + logger.setLevel(logging.DEBUG) + + ch = logging.StreamHandler(stream=sys.stdout) + ch.setLevel(logging.WARNING if config.production else logging.DEBUG) + ch.setFormatter(formatter) + logger.addHandler(ch) + + fh = logging.FileHandler('debug.log') + fh.setFormatter(formatter) + fh.setLevel(logging.WARNING if config.production else logging.DEBUG) + logger.addHandler(fh) + + wallabag_config = config.wallabag + api = WallabagAPI(host=wallabag_config.host) + api.auth(client_secret=wallabag_config.client_secret, client_id=wallabag_config.client_id, + username=wallabag_config.username, password=wallabag_config.password) + + if config.github_username: + sites = get_starred_repos(config.github_username, sites) + + new_sites: Dict[str, Dict] = {} + for title, site in sites.items(): + new_site = handle_feed(api, site, logger, config) + new_sites[title] = new_site.__dict__ + del new_sites[title]["title"] + if config.production: + with open("sites.yaml", 'w') as stream: + yaml.dump(new_sites, stream, default_flow_style=False) + + +def handle_feed(api: WallabagAPI, site: Site, logger: logging.Logger, config: Config) -> Site: + logger.info("Downloading feed: " + site.title) + r = api.s.get(site.url) + if r.status_code != 404: + r.raise_for_status() + rss = r.text + logger.info("Parsing feed: " + site.title) f = feedparser.parse(rss) - logger.debug("finished parsing: " + sitetitle) - # feedtitle = f["feed"]["title"] - if "latest_article" in site: - for article in f.entries: - if article.title == site["latest_article"]: - logger.debug("already added: " + article.title) - break - logger.info("article found: " + article.title) - taglist = [sitetitle] - if site["tags"]: - taglist.extend(site["tags"]) - tags = ",".join(taglist) - if "published_parsed" in article: - published = mktime(article.published_parsed) - elif "updated_parsed" in article: - published = mktime(article.updated_parsed) - else: - published = None - logger.info("add to wallabag: " + article.title) - if "github" in site and site["github"]: - title = sitetitle + ": " + article.title - else: - title = article.title - if not hasattr(article, 'link'): - logger.info("no link, skipping!") - continue - url = urljoin(site["url"], article.link) - exists = await wall.entries_exists(url) - if exists["exists"]: - logger.info("already found in wallabag: " + article.title) - if production: - await wall.post_entries(url=url, title=title, tags=tags) - else: - logger.info("warning: running in debug mode - not adding links to wallabag") - else: - logger.debug("no latest_article: " + sitetitle) - if f.entries: - sites[sitetitle]["latest_article"] = f.entries[0].title + logger.debug("finished parsing: " + site.title) + + articles: List[FeedParserDict] = f.entries + for article in articles: + if article.title == site.latest_article: + logger.debug("already added: " + article.title) + break + logger.info("article found: " + article.title) + taglist = [site.title] + if site.tags: + taglist.extend(site.tags) + if "published_parsed" in article: + published = datetime.fromtimestamp(mktime(article.published_parsed)) + elif "updated_parsed" in article: + published = datetime.fromtimestamp(mktime(article.updated_parsed)) + else: + published = None + logger.info("add to wallabag: " + article.title) + if site.github: + title = site.title + ": " + article.title + else: + title = article.title + if not hasattr(article, 'link'): + logger.info("no link, skipping!") + continue + url = urljoin(site.url, article.link) + if api.check_exist(url): + logger.info("already found in wallabag: " + article.title) + continue + if config.production or True: + print(published) + api.add_entry(url=url, title=title, tags=taglist, published=published) + else: + logger.info("warning: running in debug mode - not adding links to wallabag") + if articles: + site.latest_article = articles[0].title + + return site if __name__ == '__main__': - loop = asyncio.get_event_loop() - loop.run_until_complete(main(loop, sites)) - if production: - with open("sites.yaml", 'w') as stream: - yaml.dump(sites, stream, default_flow_style=False) + main() diff --git a/poetry.lock b/poetry.lock index 3073d0a..52e67af 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,294 +1,128 @@ [[package]] -category = "main" -description = "Async http client/server framework (asyncio)" -name = "aiohttp" -optional = false -python-versions = ">=3.5.3" -version = "3.6.2" - -[package.dependencies] -async-timeout = ">=3.0,<4.0" -attrs = ">=17.3.0" -chardet = ">=2.0,<4.0" -multidict = ">=4.5,<5.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["aiodns", "brotlipy", "cchardet"] - -[[package]] -category = "main" -description = "Timeout context manager for asyncio programs" -name = "async-timeout" -optional = false -python-versions = ">=3.5.3" -version = "3.0.1" - -[[package]] -category = "main" -description = "Classes Without Boilerplate" -name = "attrs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "19.3.0" - -[package.extras] -azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"] -dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] -docs = ["sphinx", "zope.interface"] -tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] - -[[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." name = "certifi" +version = "2020.6.20" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = "*" -version = "2019.11.28" [[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" name = "chardet" +version = "3.0.4" +description = "Universal encoding detector for Python 2 and 3" +category = "main" optional = false python-versions = "*" -version = "3.0.4" [[package]] -category = "main" -description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" name = "feedparser" +version = "6.0.2" +description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" +category = "main" optional = false -python-versions = "*" -version = "6.0.0b1" +python-versions = ">=3.6" [package.dependencies] -[package.dependencies.sgmllib3k] -python = ">=3.0" -version = "*" +sgmllib3k = "*" [[package]] -category = "main" -description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" +version = "2.10" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8" [[package]] -category = "main" -description = "multidict implementation" -name = "multidict" -optional = false -python-versions = ">=3.5" -version = "4.7.3" - -[[package]] -category = "main" -description = "YAML parser and emitter for Python" name = "pyyaml" +version = "5.3.1" +description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "5.3" [[package]] -category = "main" -description = "Python HTTP for Humans." name = "requests" +version = "2.24.0" +description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" [package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] -category = "main" -description = "Python client for Sentry (https://getsentry.com)" -name = "sentry-sdk" -optional = false -python-versions = "*" -version = "0.13.5" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -flask = ["flask (>=0.11)", "blinker (>=1.1)"] -pyspark = ["pyspark (>=2.4.4)"] -rq = ["0.6"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -tornado = ["tornado (>=5)"] - -[[package]] -category = "main" -description = "Py3k port of sgmllib." -marker = "python_version >= \"3.0\"" name = "sgmllib3k" +version = "1.0.0" +description = "Py3k port of sgmllib." +category = "main" optional = false python-versions = "*" -version = "1.0.0" [[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" +version = "1.25.11" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.25.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] - -[[package]] -category = "main" -description = "Wallabag API to add every pages you want to your Wallabag account" -name = "wallabag-api" -optional = false -python-versions = "*" -version = "1.2.3" - -[package.dependencies] -aiohttp = "*" - -[[package]] -category = "main" -description = "Yet another URL library" -name = "yarl" -optional = false -python-versions = ">=3.5" -version = "1.4.2" - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [metadata] -content-hash = "d370238d5cce13de7e2d9c2c0d9a4040a4a406322d2e9ebf38d8cf97e49dc18b" +lock-version = "1.1" python-versions = "^3.7" +content-hash = "1804291feb860b5ec22fdd23269eb00a5e8d0dd0cb8537506e4f7df32c441de4" [metadata.files] -aiohttp = [ - {file = "aiohttp-3.6.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e"}, - {file = "aiohttp-3.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec"}, - {file = "aiohttp-3.6.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48"}, - {file = "aiohttp-3.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59"}, - {file = "aiohttp-3.6.2-cp36-cp36m-win32.whl", hash = "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a"}, - {file = "aiohttp-3.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17"}, - {file = "aiohttp-3.6.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a"}, - {file = "aiohttp-3.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd"}, - {file = "aiohttp-3.6.2-cp37-cp37m-win32.whl", hash = "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"}, - {file = "aiohttp-3.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654"}, - {file = "aiohttp-3.6.2-py3-none-any.whl", hash = "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4"}, - {file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"}, -] -async-timeout = [ - {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, - {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, -] -attrs = [ - {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, - {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, -] certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] feedparser = [ - {file = "feedparser-6.0.0b1-py2.py3-none-any.whl", hash = "sha256:87185443d6e12cf870125bdc9211168c60895e7dd7209b5c082897ddb1b11efb"}, - {file = "feedparser-6.0.0b1.tar.gz", hash = "sha256:150ccca4cfc3481f7ff503988a91bbdbbbc3406d6444bfe9cfe6c1001d378e73"}, + {file = "feedparser-6.0.2-py3-none-any.whl", hash = "sha256:f596c4b34fb3e2dc7e6ac3a8191603841e8d5d267210064e94d4238737452ddd"}, + {file = "feedparser-6.0.2.tar.gz", hash = "sha256:1b00a105425f492f3954fd346e5b524ca9cef3a4bbf95b8809470e9857aa1074"}, ] idna = [ - {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, - {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, -] -multidict = [ - {file = "multidict-4.7.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:ed5f3378c102257df9e2dc9ce6468dabf68bee9ec34969cfdc472631aba00316"}, - {file = "multidict-4.7.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:15a61c0df2d32487e06f6084eabb48fd9e8b848315e397781a70caf9670c9d78"}, - {file = "multidict-4.7.3-cp35-cp35m-win32.whl", hash = "sha256:d1f45e5bb126662ba66ee579831ce8837b1fd978115c9657e32eb3c75b92973d"}, - {file = "multidict-4.7.3-cp35-cp35m-win_amd64.whl", hash = "sha256:a02fade7b5476c4f88efe9593ff2f3286698d8c6d715ba4f426954f73f382026"}, - {file = "multidict-4.7.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:78bed18e7f1eb21f3d10ff3acde900b4d630098648fe1d65bb4abfb3e22c4900"}, - {file = "multidict-4.7.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0f04bf4c15d8417401a10a650c349ccc0285943681bfd87d3690587d7714a9b4"}, - {file = "multidict-4.7.3-cp36-cp36m-win32.whl", hash = "sha256:63ba2be08d82ea2aa8b0f7942a74af4908664d26cb4ff60c58eadb1e33e7da00"}, - {file = "multidict-4.7.3-cp36-cp36m-win_amd64.whl", hash = "sha256:3c5e2dcbe6b04cbb4303e47a896757a77b676c5e5db5528be7ff92f97ba7ab95"}, - {file = "multidict-4.7.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:c2bfc0db3166e68515bc4a2b9164f4f75ae9c793e9635f8651f2c9ffc65c8dad"}, - {file = "multidict-4.7.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c66d11870ae066499a3541963e6ce18512ca827c2aaeaa2f4e37501cee39ac5d"}, - {file = "multidict-4.7.3-cp37-cp37m-win32.whl", hash = "sha256:aacbde3a8875352a640efa2d1b96e5244a29b0f8df79cbf1ec6470e86fd84697"}, - {file = "multidict-4.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5e5fb8bfebf87f2e210306bf9dd8de2f1af6782b8b78e814060ae9254ab1f297"}, - {file = "multidict-4.7.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:5d2b32b890d9e933d3ced417924261802a857abdee9507b68c75014482145c03"}, - {file = "multidict-4.7.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cc7f2202b753f880c2e4123f9aacfdb94560ba893e692d24af271dac41f8b8d9"}, - {file = "multidict-4.7.3-cp38-cp38-win32.whl", hash = "sha256:bfcad6da0b8839f01a819602aaa5c5a5b4c85ecbfae9b261a31df3d9262fb31e"}, - {file = "multidict-4.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:73740fcdb38f0adcec85e97db7557615b50ec4e5a3e73e35878720bcee963382"}, - {file = "multidict-4.7.3.tar.gz", hash = "sha256:be813fb9e5ce41a5a99a29cdb857144a1bd6670883586f995b940a4878dc5238"}, + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] pyyaml = [ - {file = "PyYAML-5.3-cp27-cp27m-win32.whl", hash = "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d"}, - {file = "PyYAML-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6"}, - {file = "PyYAML-5.3-cp35-cp35m-win32.whl", hash = "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e"}, - {file = "PyYAML-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689"}, - {file = "PyYAML-5.3-cp36-cp36m-win32.whl", hash = "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994"}, - {file = "PyYAML-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e"}, - {file = "PyYAML-5.3-cp37-cp37m-win32.whl", hash = "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5"}, - {file = "PyYAML-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf"}, - {file = "PyYAML-5.3-cp38-cp38-win32.whl", hash = "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811"}, - {file = "PyYAML-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20"}, - {file = "PyYAML-5.3.tar.gz", hash = "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615"}, + {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"}, + {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"}, + {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"}, + {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"}, + {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"}, + {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"}, + {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"}, + {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, ] requests = [ - {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, - {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, -] -sentry-sdk = [ - {file = "sentry-sdk-0.13.5.tar.gz", hash = "sha256:c6b919623e488134a728f16326c6f0bcdab7e3f59e7f4c472a90eea4d6d8fe82"}, - {file = "sentry_sdk-0.13.5-py2.py3-none-any.whl", hash = "sha256:05285942901d38c7ce2498aba50d8e87b361fc603281a5902dda98f3f8c5e145"}, + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, ] sgmllib3k = [ {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"}, ] urllib3 = [ - {file = "urllib3-1.25.7-py2.py3-none-any.whl", hash = "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293"}, - {file = "urllib3-1.25.7.tar.gz", hash = "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"}, -] -wallabag-api = [ - {file = "wallabag_api-1.2.3.tar.gz", hash = "sha256:b0b6e56aa042da1fe313d9769698c11294e6b53de0c4af96a929c7c6bc2f4b61"}, -] -yarl = [ - {file = "yarl-1.4.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b"}, - {file = "yarl-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1"}, - {file = "yarl-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080"}, - {file = "yarl-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a"}, - {file = "yarl-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f"}, - {file = "yarl-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea"}, - {file = "yarl-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb"}, - {file = "yarl-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70"}, - {file = "yarl-1.4.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d"}, - {file = "yarl-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce"}, - {file = "yarl-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"}, - {file = "yarl-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce"}, - {file = "yarl-1.4.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b"}, - {file = "yarl-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae"}, - {file = "yarl-1.4.2-cp38-cp38-win32.whl", hash = "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462"}, - {file = "yarl-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6"}, - {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, + {file = "urllib3-1.25.11-py2.py3-none-any.whl", hash = "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"}, + {file = "urllib3-1.25.11.tar.gz", hash = "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2"}, ] diff --git a/pyproject.toml b/pyproject.toml index d49f460..3f748db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,11 +6,9 @@ authors = ["Lukas Winkler "] [tool.poetry.dependencies] python = "^3.7" -wallabag-api = "^1.2.3" -feedparser = "6.0.0b1" +feedparser = "^6.0.2" PyYAML = "^5.3" requests = "^2.22.0" -sentry-sdk = "^0.13.5" [tool.poetry.dev-dependencies] diff --git a/requirements.txt b/requirements.txt index 9373265..4d8020f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,8 @@ -aiohttp==3.6.2 -async-timeout==3.0.1 -attrs==19.3.0 -certifi==2019.11.28 -chardet==3.0.4 -feedparser==6.0.0b1 -idna==2.8 -multidict==4.7.3 -pyyaml==5.3 -requests==2.22.0 -sentry-sdk==0.13.5 -sgmllib3k==1.0.0; python_version >= "3.0" -urllib3==1.25.7 -wallabag-api==1.2.3 -yarl==1.4.2 +certifi==2020.6.20; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +chardet==3.0.4; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +feedparser==6.0.2; python_version >= "3.6" +idna==2.10; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +pyyaml==5.3.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") +requests==2.24.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") +sgmllib3k==1.0.0; python_version >= "3.6" +urllib3==1.25.11; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4"