Update to newest version of Reader, fix webhooks and fix tests

This commit is contained in:
2022-09-26 19:43:51 +02:00
parent 4dd9b2b6b3
commit b8a94b6009
4 changed files with 334 additions and 117 deletions

View File

@ -1,18 +1,24 @@
import logging
import os import os
import sys
import time
from contextlib import closing from contextlib import closing
from pathlib import Path from pathlib import Path
from shutil import copyfile from shutil import copyfile
import sys
import time
import typer import typer
from dhooks import Webhook from discord_webhook import DiscordWebhook
from reader import FeedExistsError, make_reader from reader import FeedExistsError, make_reader
from reader._plugins import global_metadata
from reader.exceptions import FeedMetadataNotFoundError # Add logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
app = typer.Typer() app = typer.Typer()
app_dir = typer.get_app_dir("discord-rss-bot") app_dir = typer.get_app_dir("discord-rss-bot")
logging.debug(f"App dir: {app_dir}")
# Create the data directory if it doesn't exist # Create the data directory if it doesn't exist
os.makedirs(app_dir, exist_ok=True) os.makedirs(app_dir, exist_ok=True)
@ -20,6 +26,11 @@ os.makedirs(app_dir, exist_ok=True)
# Store the database file in the data directory # Store the database file in the data directory
db_name = os.getenv("DATABASE_NAME", "db.sqlite") db_name = os.getenv("DATABASE_NAME", "db.sqlite")
db_file: Path = Path(os.path.join(app_dir, db_name)) db_file: Path = Path(os.path.join(app_dir, db_name))
logging.debug(f"Database file: {db_file}")
# Convert Path to string
db_file_str: str = str(db_file)
logging.debug(f"Database file as string: {db_file_str}")
@app.command() @app.command()
@ -32,13 +43,12 @@ def add(
Args: Args:
feed_url (str): The url of the feed to add feed_url (str): The url of the feed to add
notify_discord (bool): Whether to send a message to Discord when notify_discord (bool): Whether to send a message to Discord when
the feed is added the feed is added.
""" """
with closing(make_reader(db_file, plugins=[global_metadata.init_reader])) as reader: with closing(make_reader(db_file_str)) as reader:
try: try:
# Add the feed to the database # Add the feed to the database
reader.add_feed(feed_url) reader.add_feed(feed_url)
except FeedExistsError: except FeedExistsError:
# If the feed already exists, print a message # If the feed already exists, print a message
typer.echo(f"{feed_url} already exists") typer.echo(f"{feed_url} already exists")
@ -50,25 +60,35 @@ def add(
# Mark the feed as read # Mark the feed as read
entries = reader.get_entries(feed=feed_url, read=False) entries = reader.get_entries(feed=feed_url, read=False)
for entry in entries: for entry in entries:
logging.debug(f"Marking {entry.title} as read")
reader.mark_entry_as_read(entry) reader.mark_entry_as_read(entry)
if notify_discord: if notify_discord:
# Send a message to Discord # Send a message to Discord
webhook_url = reader.get_global_metadata_item("webhook") webhook_msg = (
hook = Webhook(webhook_url)
hook.send(
f"discord-rss-bot: {feed_url} added to the database.\n" f"discord-rss-bot: {feed_url} added to the database.\n"
f"You now have {reader.get_feed_counts()} feeds." f"You now have {reader.get_feed_counts()} feeds."
) )
webhook_url = reader.get_tag((), "webhook")
logging.debug(f"Webhook URL: {webhook_url}")
if not webhook_url:
typer.echo("No webhook URL found in the database.")
sys.exit()
webhook = DiscordWebhook(url=str(webhook_url), content=webhook_msg, rate_limit_retry=True)
response = webhook.execute()
if response.status_code != 204:
typer.echo(f"Error sending message to Discord - {response.status_code}\n{response.text}")
typer.echo(f"{feed_url} added") typer.echo(f"{feed_url} added")
@app.command() @app.command()
def stats() -> None: def stats() -> None:
"""Print the number of feeds and entries in the database""" """Print the amount feeds and entries in the database"""
with closing(make_reader(db_file, plugins=[global_metadata.init_reader])) as reader: with closing(make_reader(db_file_str)) as reader:
feed_count = reader.get_feed_counts() feed_count = reader.get_feed_counts()
entry_count = reader.get_entry_counts() entry_count = reader.get_entry_counts()
@ -95,7 +115,7 @@ def stats() -> None:
@app.command() @app.command()
def check() -> None: def check() -> None:
"""Check new entries for every feed""" """Check new entries for every feed"""
with closing(make_reader(db_file, plugins=[global_metadata.init_reader])) as reader: with closing(make_reader(db_file_str)) as reader:
# Update the feeds # Update the feeds
reader.update_feeds() reader.update_feeds()
@ -105,12 +125,20 @@ def check() -> None:
for entry in entries: for entry in entries:
# Mark the entry as read # Mark the entry as read
reader.mark_entry_as_read(entry) reader.mark_entry_as_read(entry)
logging.debug(f"Marking {entry.title} as read")
webhook_url = reader.get_global_metadata_item("webhook") webhook_url = reader.get_tag((), "webhook")
hook = Webhook(webhook_url) logging.debug(f"Webhook URL: {webhook_url}")
if not webhook_url:
typer.echo("No webhook URL found in the database.")
sys.exit()
# Send the entries to Discord webhook = DiscordWebhook(url=str(webhook_url), content=f":robot: :mega: {entry.title}\n{entry.link}",
hook.send(f":robot: :mega: {entry.title}\n{entry.link}") rate_limit_retry=True)
response = webhook.execute()
if response.status_code != 204:
typer.echo(f"Error sending message to Discord - {response.status_code}\n{response.text}")
@app.command() @app.command()
@ -134,34 +162,43 @@ def delete() -> None:
feed_dict = {} feed_dict = {}
feed_number = 0 feed_number = 0
message = "" message = ""
with closing(make_reader(db_file)) as reader: with closing(make_reader(db_file_str)) as reader:
for feed in reader.get_feeds(): for feed in reader.get_feeds():
logging.debug(f"Feed: {feed}")
feed_number += 1 feed_number += 1
feed_dict[feed_number] = feed.object_id logging.debug(f"Feed number: {feed_number}")
logging.debug(f"Feed URL: {feed.url}")
feed_dict[str(feed_number)] = feed.url
logging.debug(f"Feed dict: {feed_dict}")
message += f"{feed_number}: {feed.title}\n" message += f"{feed_number}: {feed.title}\n"
typer.echo(message) typer.echo(message)
feed_to_delete: int = typer.prompt("What feed do you want to remove?") feed_to_delete: str = typer.prompt("What feed do you want to remove?")
feed_id = feed_dict.get(feed_to_delete) feed_url = feed_dict.get(str(feed_to_delete))
if not feed_url:
typer.echo("Invalid feed number")
sys.exit()
logging.debug(f"Feed URL: {feed_url}")
confirm_delete = typer.confirm( confirm_delete = typer.confirm(
f"Are you sure you want to delete {feed_id}?", f"Are you sure you want to delete {feed_url}?",
) )
if not confirm_delete: if not confirm_delete:
typer.echo("Not deleting") typer.echo("Not deleting")
raise typer.Abort() raise typer.Abort()
reader.delete_feed(feed_id) reader.delete_feed(feed_url)
typer.echo(f"{feed_id} deleted") typer.echo(f"{feed_url} deleted")
@app.command() @app.command()
def webhook_add(webhook_url: str) -> None: def webhook_add(webhook_url: str) -> None:
"""Add a webhook to the database""" """Add a webhook to the database"""
with closing(make_reader(db_file, plugins=[global_metadata.init_reader])) as reader: with closing(make_reader(db_file_str)) as reader:
reader.set_global_metadata_item("webhook", webhook_url) reader.set_tag((), "webhook", webhook_url)
typer.echo(f"Webhook set to {webhook_url}") typer.echo(f"Webhook set to {webhook_url}")
@ -169,12 +206,13 @@ def webhook_add(webhook_url: str) -> None:
def webhook_get() -> None: def webhook_get() -> None:
"""Get the webhook url""" """Get the webhook url"""
# TODO: Add name to output # TODO: Add name to output
with closing(make_reader(db_file, plugins=[global_metadata.init_reader])) as reader: with closing(make_reader(db_file_str)) as reader:
try: try:
webhook_url = reader.get_global_metadata_item("webhook") webhook_url = reader.get_tag((), "webhook")
typer.echo(f"Webhook: {webhook_url}") typer.echo(f"Webhook: {webhook_url}")
except FeedMetadataNotFoundError: except Exception as e:
typer.echo("No webhook was found. Use `webhook add` to add one.") typer.echo("No webhook was found. Use `webhook add` to add one.")
typer.echo(f"Error: {e}\nPlease report this error to the developer.")
sys.exit() sys.exit()

337
poetry.lock generated
View File

@ -1,3 +1,17 @@
[[package]]
name = "attrs"
version = "22.1.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=3.5"
[package.extras]
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[[package]] [[package]]
name = "beautifulsoup4" name = "beautifulsoup4"
version = "4.11.1" version = "4.11.1"
@ -15,45 +29,56 @@ lxml = ["lxml"]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2021.10.8" version = "2022.9.24"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = ">=3.6"
[[package]] [[package]]
name = "charset-normalizer" name = "charset-normalizer"
version = "2.0.12" version = "2.1.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.5.0" python-versions = ">=3.6.0"
[package.extras] [package.extras]
unicode_backport = ["unicodedata2"] unicode_backport = ["unicodedata2"]
[[package]] [[package]]
name = "click" name = "click"
version = "8.1.2" version = "8.1.3"
description = "Composable command line interface toolkit" description = "Composable command line interface toolkit"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
colorama = { version = "*", markers = "platform_system == \"Windows\"" } colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]] [[package]]
name = "colorama" name = "colorama"
version = "0.4.4" version = "0.4.5"
description = "Cross-platform colored terminal text." description = "Cross-platform colored terminal text."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "commonmark"
version = "0.9.1"
description = "Python parser for the CommonMark Markdown spec"
category = "main"
optional = false
python-versions = "*"
[package.extras]
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
[[package]] [[package]]
name = "discord-webhook" name = "discord-webhook"
version = "0.16.0" version = "0.17.0"
description = "execute discord webhooks" description = "execute discord webhooks"
category = "main" category = "main"
optional = false optional = false
@ -67,7 +92,7 @@ async = ["httpx (>=0.20.0)"]
[[package]] [[package]]
name = "feedparser" name = "feedparser"
version = "6.0.8" version = "6.0.10"
description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" 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" category = "main"
optional = false optional = false
@ -78,12 +103,20 @@ sgmllib3k = "*"
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.3" version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)" description = "Internationalized Domain Names in Applications (IDNA)"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
[[package]]
name = "iniconfig"
version = "1.1.1"
description = "iniconfig: brain-dead simple config-ini parsing"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "iso8601" name = "iso8601"
version = "1.0.2" version = "1.0.2"
@ -93,46 +126,133 @@ optional = false
python-versions = ">=3.6.2,<4.0" python-versions = ">=3.6.2,<4.0"
[[package]] [[package]]
name = "reader" name = "packaging"
version = "2.12" version = "21.3"
description = "A Python feed reader library." description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "pluggy"
version = "1.0.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "py"
version = "1.11.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "Pygments"
version = "2.13.0"
description = "Pygments is a syntax highlighting package written in Python."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6"
[package.extras]
plugins = ["importlib-metadata"]
[[package]]
name = "pyparsing"
version = "3.0.9"
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
category = "dev"
optional = false
python-versions = ">=3.6.8"
[package.extras]
diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "pytest"
version = "7.1.3"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
beautifulsoup4 = ">=4.5" attrs = ">=19.2.0"
feedparser = ">=6" colorama = {version = "*", markers = "sys_platform == \"win32\""}
iso8601 = "*" iniconfig = "*"
requests = ">=2.18" packaging = "*"
typing-extensions = "*" pluggy = ">=0.12,<2.0"
py = ">=1.8.2"
tomli = ">=1.0.0"
[package.extras] [package.extras]
app = ["flask (>=0.10)", "humanize", "pyyaml"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
cli = ["click (>=7)", "pyyaml"]
dev = ["tox", "pre-commit", "build", "twine"] [[package]]
docs = ["sphinx", "sphinx-rtd-theme (>=1.0,<2.0)", "click (>=7)", "sphinx-click", "sphinx-issues", "sphinx-hoverxref", "sphinxcontrib-log-cabinet"] name = "reader"
readtime = ["readtime"] version = "3.2"
tests = ["pytest (>=4)", "pytest-randomly", "pytest-subtests", "flaky", "coverage", "pytest-cov", "requests-mock", "requests-wsgi-adapter", "html5lib", "werkzeug", "types-requests", "mypy", "mechanicalsoup", "lxml"] description = "A Python feed reader library."
unstable-plugins = ["requests", "mutagen", "beautifulsoup4", "blinker (>=1.4)"] category = "main"
optional = false
python-versions = ">=3.8"
[package.dependencies]
beautifulsoup4 = ">=4.5"
feedparser = ">=6"
iso8601 = ">=1"
requests = ">=2.18"
typing-extensions = ">=4"
[package.extras]
app = ["PyYAML", "flask (>=0.10)", "humanize"]
cli = ["PyYAML", "click (>=7)"]
dev = ["build", "pre-commit", "reader[app,cli,docs,tests,unstable-plugins]", "tox", "twine"]
docs = ["click (>=7)", "sphinx", "sphinx-click", "sphinx-hoverxref", "sphinx-issues", "sphinx-rtd-theme (>=1.0,<2.0)", "sphinxcontrib-log-cabinet"]
tests = ["coverage", "flaky", "html5lib", "lxml", "mechanicalsoup", "mypy", "pytest (>=4)", "pytest-cov", "pytest-randomly", "pytest-subtests", "requests-mock", "requests-wsgi-adapter", "types-requests", "werkzeug"]
unstable-plugins = ["Jinja2 (>=3)", "beautifulsoup4", "blinker (>=1.4)", "mutagen", "requests", "tweepy"]
[[package]] [[package]]
name = "requests" name = "requests"
version = "2.27.1" version = "2.28.1"
description = "Python HTTP for Humans." description = "Python HTTP for Humans."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" python-versions = ">=3.7, <4"
[package.dependencies] [package.dependencies]
certifi = ">=2017.4.17" certifi = ">=2017.4.17"
charset-normalizer = { version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\"" } charset-normalizer = ">=2,<3"
idna = { version = ">=2.5,<4", markers = "python_version >= \"3\"" } idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27" urllib3 = ">=1.21.1,<1.27"
[package.extras] [package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "rich"
version = "12.5.1"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
category = "main"
optional = false
python-versions = ">=3.6.3,<4.0.0"
[package.dependencies]
commonmark = ">=0.9.0,<0.10.0"
pygments = ">=2.6.0,<3.0.0"
[package.extras]
jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
[[package]] [[package]]
name = "sgmllib3k" name = "sgmllib3k"
@ -144,23 +264,31 @@ python-versions = "*"
[[package]] [[package]]
name = "shellingham" name = "shellingham"
version = "1.4.0" version = "1.5.0"
description = "Tool to Detect Surrounding Shell" description = "Tool to Detect Surrounding Shell"
category = "main" category = "main"
optional = false optional = false
python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,>=2.6" python-versions = ">=3.4"
[[package]] [[package]]
name = "soupsieve" name = "soupsieve"
version = "2.3.2" version = "2.3.2.post1"
description = "A modern CSS selector implementation for Beautiful Soup." description = "A modern CSS selector implementation for Beautiful Soup."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
category = "dev"
optional = false
python-versions = ">=3.7"
[[package]] [[package]]
name = "typer" name = "typer"
version = "0.4.1" version = "0.6.1"
description = "Typer, build great CLIs. Easy to code. Based on Python type hints." description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
category = "main" category = "main"
optional = false optional = false
@ -168,106 +296,151 @@ python-versions = ">=3.6"
[package.dependencies] [package.dependencies]
click = ">=7.1.1,<9.0.0" click = ">=7.1.1,<9.0.0"
colorama = { version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\"" } colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
shellingham = { version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\"" } rich = {version = ">=10.11.0,<13.0.0", optional = true, markers = "extra == \"all\""}
shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
[package.extras] [package.extras]
all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"] all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)"] dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)"] doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
test = ["shellingham (>=1.3.0,<2.0.0)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "coverage (>=5.2,<6.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "mypy (==0.910)", "black (>=22.3.0,<23.0.0)", "isort (>=5.0.6,<6.0.0)"] test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.1.1" version = "4.3.0"
description = "Backported and Experimental Type Hints for Python 3.6+" description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.7"
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "1.26.9" version = "1.26.12"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
[package.extras] [package.extras]
brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "53b5b383ba400929d442e09fecdcb8178308ba3783cb70426a0be5f730d7aaf0" content-hash = "ac76e6768f510ad14b7f105a76b34c70ab2bb0b3a0aa99d1a875dff9944b7f3b"
[metadata.files] [metadata.files]
attrs = [
{file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"},
{file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"},
]
beautifulsoup4 = [ beautifulsoup4 = [
{ file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30" }, {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"},
{ file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693" }, {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"},
] ]
certifi = [ certifi = [
{ file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" }, {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"},
{ file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872" }, {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"},
] ]
charset-normalizer = [ charset-normalizer = [
{ file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597" }, {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"},
{ file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" }, {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"},
] ]
click = [ click = [
{ file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e" }, {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
{ file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72" }, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
] ]
colorama = [ colorama = [
{ file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" }, {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
{ file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b" }, {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
]
commonmark = [
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
] ]
discord-webhook = [ discord-webhook = [
{ file = "discord-webhook-0.16.0.tar.gz", hash = "sha256:6318c2bfab20e35927503cd32f49a449b0aba61f5a848e415fdf5e94e361870c" }, {file = "discord-webhook-0.17.0.tar.gz", hash = "sha256:bb47e5fc83f73614d7b2a3764b84359b52c96a94aadf3302bc3c067dd21b43cc"},
{ file = "discord_webhook-0.16.0-py3-none-any.whl", hash = "sha256:b142eadc0588c161840a21496052a97c8d72b44457cf3bd3cf4dc0a6f9b5f50a" }, {file = "discord_webhook-0.17.0-py3-none-any.whl", hash = "sha256:d869849c4834f928f5c22597dc7600b1a30f9e797d1aeb1d4196711a243d9a73"},
] ]
feedparser = [ feedparser = [
{ file = "feedparser-6.0.8-py3-none-any.whl", hash = "sha256:1b7f57841d9cf85074deb316ed2c795091a238adb79846bc46dccdaf80f9c59a" }, {file = "feedparser-6.0.10-py3-none-any.whl", hash = "sha256:79c257d526d13b944e965f6095700587f27388e50ea16fd245babe4dfae7024f"},
{ file = "feedparser-6.0.8.tar.gz", hash = "sha256:5ce0410a05ab248c8c7cfca3a0ea2203968ee9ff4486067379af4827a59f9661" }, {file = "feedparser-6.0.10.tar.gz", hash = "sha256:27da485f4637ce7163cdeab13a80312b93b7d0c1b775bef4a47629a3110bca51"},
] ]
idna = [ idna = [
{ file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff" }, {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{ file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" }, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
] ]
iso8601 = [ iso8601 = [
{ file = "iso8601-1.0.2-py3-none-any.whl", hash = "sha256:d7bc01b1c2a43b259570bb307f057abc578786ea734ba2b87b836c5efc5bd443" }, {file = "iso8601-1.0.2-py3-none-any.whl", hash = "sha256:d7bc01b1c2a43b259570bb307f057abc578786ea734ba2b87b836c5efc5bd443"},
{ file = "iso8601-1.0.2.tar.gz", hash = "sha256:27f503220e6845d9db954fb212b95b0362d8b7e6c1b2326a87061c3de93594b1" }, {file = "iso8601-1.0.2.tar.gz", hash = "sha256:27f503220e6845d9db954fb212b95b0362d8b7e6c1b2326a87061c3de93594b1"},
]
packaging = [
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
pluggy = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
]
py = [
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
Pygments = [
{file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"},
{file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"},
]
pyparsing = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
]
pytest = [
{file = "pytest-7.1.3-py3-none-any.whl", hash = "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7"},
{file = "pytest-7.1.3.tar.gz", hash = "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39"},
] ]
reader = [ reader = [
{ file = "reader-2.12-py3-none-any.whl", hash = "sha256:e5e776266e6563fd06c6ab0c6fb01e7b66f74c38066fe8f577d2dd889fc10543" }, {file = "reader-3.2-py3-none-any.whl", hash = "sha256:5c50f44e782cc0bff6a0b25134839ccd1e83ceb87b3ff879130dd3febc44d377"},
{ file = "reader-2.12.tar.gz", hash = "sha256:f36a2d579c14074fc6ef6e9322de88aaa006debd5edcb08ee42e7ed32661416a" }, {file = "reader-3.2.tar.gz", hash = "sha256:e065a52e40657701d8a7543f2a1de4556b18daf83d58680e9e1d1c5b2016a245"},
] ]
requests = [ requests = [
{ file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d" }, {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
{ file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61" }, {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
]
rich = [
{file = "rich-12.5.1-py3-none-any.whl", hash = "sha256:2eb4e6894cde1e017976d2975ac210ef515d7548bc595ba20e195fb9628acdeb"},
{file = "rich-12.5.1.tar.gz", hash = "sha256:63a5c5ce3673d3d5fbbf23cd87e11ab84b6b451436f1b7f19ec54b6bc36ed7ca"},
] ]
sgmllib3k = [ sgmllib3k = [
{ file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9" }, {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
] ]
shellingham = [ shellingham = [
{ file = "shellingham-1.4.0-py2.py3-none-any.whl", hash = "sha256:536b67a0697f2e4af32ab176c00a50ac2899c5a05e0d8e2dadac8e58888283f9" }, {file = "shellingham-1.5.0-py2.py3-none-any.whl", hash = "sha256:a8f02ba61b69baaa13facdba62908ca8690a94b8119b69f5ec5873ea85f7391b"},
{ file = "shellingham-1.4.0.tar.gz", hash = "sha256:4855c2458d6904829bd34c299f11fdeed7cfefbf8a2c522e4caea6cd76b3171e" }, {file = "shellingham-1.5.0.tar.gz", hash = "sha256:72fb7f5c63103ca2cb91b23dee0c71fe8ad6fbfd46418ef17dbe40db51592dad"},
] ]
soupsieve = [ soupsieve = [
{ file = "soupsieve-2.3.2-py3-none-any.whl", hash = "sha256:a714129d3021ec17ce5be346b1007300558b378332c289a1a20e7d4de6ff18a5" }, {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"},
{ file = "soupsieve-2.3.2.tar.gz", hash = "sha256:0bcc6d7432153063e3df09c3ac9442af3eba488715bfcad6a4c38ccb2a523124" }, {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"},
]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
] ]
typer = [ typer = [
{ file = "typer-0.4.1-py3-none-any.whl", hash = "sha256:e8467f0ebac0c81366c2168d6ad9f888efdfb6d4e1d3d5b4a004f46fa444b5c3" }, {file = "typer-0.6.1-py3-none-any.whl", hash = "sha256:54b19e5df18654070a82f8c2aa1da456a4ac16a2a83e6dcd9f170e291c56338e"},
{ file = "typer-0.4.1.tar.gz", hash = "sha256:5646aef0d936b2c761a10393f0384ee6b5c7fe0bb3e5cd710b17134ca1d99cff" }, {file = "typer-0.6.1.tar.gz", hash = "sha256:2d5720a5e63f73eaf31edaa15f6ab87f35f0690f8ca233017d7d23d743a91d73"},
] ]
typing-extensions = [ typing-extensions = [
{ file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2" }, {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"},
{ file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42" }, {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"},
] ]
urllib3 = [ urllib3 = [
{ file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14" }, {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
{ file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e" }, {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
] ]

View File

@ -6,9 +6,12 @@ authors = ["Joakim Hellsén <tlovinator@gmail.com>"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.9" python = "^3.9"
reader = "^2.12" reader = "^3.2"
typer = { extras = ["all"], version = "^0.4.1" } typer = { extras = ["all"], version = "^0.6.1" }
discord-webhook = "^0.16.0" discord-webhook = "^0.17.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.1.3"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]

View File

@ -22,6 +22,9 @@ def test_backup():
# Where we store backups # Where we store backups
backup_dir = os.path.join(app_dir, "backup") backup_dir = os.path.join(app_dir, "backup")
# Make sure the backup directory exists
os.makedirs(backup_dir, exist_ok=True)
# Check how many files in the backup directory # Check how many files in the backup directory
files_before = len(os.listdir(backup_dir)) files_before = len(os.listdir(backup_dir))