diff --git a/pyproject.toml b/pyproject.toml index 2d400ee..54c2ba2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,5 +40,5 @@ tblib = "1.6.0" coverage = "^5.1" [build-system] -requires = ["poetry>=0.12"] +requires = ["poetry>=1.0.10"] build-backend = "poetry.masonry.api" diff --git a/src/newsreader/accounts/migrations/0014_auto_20201218_2216.py b/src/newsreader/accounts/migrations/0014_auto_20201218_2216.py new file mode 100644 index 0000000..d809ed1 --- /dev/null +++ b/src/newsreader/accounts/migrations/0014_auto_20201218_2216.py @@ -0,0 +1,49 @@ +# Generated by Django 3.0.7 on 2020-12-18 21:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [("accounts", "0013_user_auto_mark_read")] + + operations = [ + migrations.AddField( + model_name="user", + name="reddit_allow_nfsw", + field=models.BooleanField(default=False, verbose_name="Allow NSFW posts"), + ), + migrations.AddField( + model_name="user", + name="reddit_allow_spoiler", + field=models.BooleanField(default=False, verbose_name="Allow spoilers"), + ), + migrations.AddField( + model_name="user", + name="reddit_allow_viewed", + field=models.BooleanField( + default=True, verbose_name="Allow already seen posts" + ), + ), + migrations.AddField( + model_name="user", + name="reddit_comments_min", + field=models.PositiveIntegerField( + default=0, verbose_name="Minimum amount of comments" + ), + ), + migrations.AddField( + model_name="user", + name="reddit_downvotes_max", + field=models.PositiveIntegerField( + default=0, verbose_name="Maximum amount of downvotes" + ), + ), + migrations.AddField( + model_name="user", + name="reddit_upvotes_min", + field=models.PositiveIntegerField( + default=0, verbose_name="Minimum amount of upvotes" + ), + ), + ] diff --git a/src/newsreader/accounts/models.py b/src/newsreader/accounts/models.py index c46dd93..fb1f408 100644 --- a/src/newsreader/accounts/models.py +++ b/src/newsreader/accounts/models.py @@ -39,9 +39,26 @@ class UserManager(DjangoUserManager): class User(AbstractUser): email = models.EmailField(_("email address"), unique=True) + # reddit settings reddit_refresh_token = models.CharField(max_length=255, blank=True, null=True) reddit_access_token = models.CharField(max_length=255, blank=True, null=True) + reddit_allow_nfsw = models.BooleanField(_("Allow NSFW posts"), default=False) + reddit_allow_spoiler = models.BooleanField(_("Allow spoilers"), default=False) + reddit_allow_viewed = models.BooleanField( + _("Allow already seen posts"), default=True + ) + reddit_upvotes_min = models.PositiveIntegerField( + _("Minimum amount of upvotes"), default=0 + ) + reddit_downvotes_max = models.PositiveIntegerField( + _("Maximum amount of downvotes"), default=0 + ) + reddit_comments_min = models.PositiveIntegerField( + _("Minimum amount of comments"), default=0 + ) + + # twitter settings twitter_oauth_token = models.CharField(max_length=255, blank=True, null=True) twitter_oauth_token_secret = models.CharField(max_length=255, blank=True, null=True) diff --git a/src/newsreader/news/collection/exceptions/builder.py b/src/newsreader/news/collection/exceptions/builder.py index 6fb2d60..0c2f520 100644 --- a/src/newsreader/news/collection/exceptions/builder.py +++ b/src/newsreader/news/collection/exceptions/builder.py @@ -19,3 +19,7 @@ class BuilderDuplicateException(BuilderException): class BuilderParseException(BuilderException): message = "Failed to parse payload" + + +class BuilderSkippedException(BuilderException): + message = "Payload does not meet filter criteria" diff --git a/src/newsreader/news/collection/reddit.py b/src/newsreader/news/collection/reddit.py index fecda54..fc75b81 100644 --- a/src/newsreader/news/collection/reddit.py +++ b/src/newsreader/news/collection/reddit.py @@ -32,6 +32,7 @@ from newsreader.news.collection.exceptions import ( BuilderException, BuilderMissingDataException, BuilderParseException, + BuilderSkippedException, StreamDeniedException, StreamException, StreamParseException, @@ -117,6 +118,8 @@ def revoke_reddit_token(user): return response.status_code == 204 +# TODO add filter tests +# TODO update fronted template class RedditBuilder(PostBuilder): rule_type = RuleTypeChoices.subreddit @@ -165,13 +168,39 @@ class RedditBuilder(PostBuilder): try: title = entry_data["title"] author = entry_data["author"] + post_url_fragment = entry_data["permalink"] direct_url = entry_data["url"] + is_text = entry_data["is_self"] is_video = entry_data["is_video"] + + is_nsfw = entry_data["over_18"] + is_spoiler = entry_data["spoiler"] + is_viewed = entry_data["clicked"] + upvotes = entry_data["ups"] + downvotes = entry_data["downs"] + comments = entry_data["num_comments"] except KeyError as e: raise BuilderMissingDataException(payload=entry) from e + user = rule.user + + if not user.reddit_allow_nfsw and is_nsfw: + raise BuilderSkippedException("User does not allow NSFW posts") + elif not user.reddit_allow_spoiler and is_spoiler: + raise BuilderSkippedException("User does not allow spoilers") + elif not user.reddit_allow_viewed and is_viewed: + raise BuilderSkippedException("Post was already seen by user") + elif not upvotes >= user.reddit_upvotes_min: + raise BuilderSkippedException( + "Post does not meet minimum amount of upvotes" + ) + elif downvotes >= user.reddit_downvotes_max: + raise BuilderSkippedException("Post has more downvotes than allowed") + elif not comments >= user.reddit_comments_min: + raise BuilderSkippedException("Post does not have enough comments") + title = truncate_text(Post, "title", title) author = truncate_text(Post, "author", author)