Add user manageable reddit filters
This commit is contained in:
parent
73e823bb05
commit
c0f4139210
5 changed files with 100 additions and 1 deletions
|
|
@ -40,5 +40,5 @@ tblib = "1.6.0"
|
||||||
coverage = "^5.1"
|
coverage = "^5.1"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry>=0.12"]
|
requires = ["poetry>=1.0.10"]
|
||||||
build-backend = "poetry.masonry.api"
|
build-backend = "poetry.masonry.api"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -39,9 +39,26 @@ class UserManager(DjangoUserManager):
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
email = models.EmailField(_("email address"), unique=True)
|
email = models.EmailField(_("email address"), unique=True)
|
||||||
|
|
||||||
|
# reddit settings
|
||||||
reddit_refresh_token = models.CharField(max_length=255, blank=True, null=True)
|
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_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 = models.CharField(max_length=255, blank=True, null=True)
|
||||||
twitter_oauth_token_secret = models.CharField(max_length=255, blank=True, null=True)
|
twitter_oauth_token_secret = models.CharField(max_length=255, blank=True, null=True)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,3 +19,7 @@ class BuilderDuplicateException(BuilderException):
|
||||||
|
|
||||||
class BuilderParseException(BuilderException):
|
class BuilderParseException(BuilderException):
|
||||||
message = "Failed to parse payload"
|
message = "Failed to parse payload"
|
||||||
|
|
||||||
|
|
||||||
|
class BuilderSkippedException(BuilderException):
|
||||||
|
message = "Payload does not meet filter criteria"
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ from newsreader.news.collection.exceptions import (
|
||||||
BuilderException,
|
BuilderException,
|
||||||
BuilderMissingDataException,
|
BuilderMissingDataException,
|
||||||
BuilderParseException,
|
BuilderParseException,
|
||||||
|
BuilderSkippedException,
|
||||||
StreamDeniedException,
|
StreamDeniedException,
|
||||||
StreamException,
|
StreamException,
|
||||||
StreamParseException,
|
StreamParseException,
|
||||||
|
|
@ -117,6 +118,8 @@ def revoke_reddit_token(user):
|
||||||
return response.status_code == 204
|
return response.status_code == 204
|
||||||
|
|
||||||
|
|
||||||
|
# TODO add filter tests
|
||||||
|
# TODO update fronted template
|
||||||
class RedditBuilder(PostBuilder):
|
class RedditBuilder(PostBuilder):
|
||||||
rule_type = RuleTypeChoices.subreddit
|
rule_type = RuleTypeChoices.subreddit
|
||||||
|
|
||||||
|
|
@ -165,13 +168,39 @@ class RedditBuilder(PostBuilder):
|
||||||
try:
|
try:
|
||||||
title = entry_data["title"]
|
title = entry_data["title"]
|
||||||
author = entry_data["author"]
|
author = entry_data["author"]
|
||||||
|
|
||||||
post_url_fragment = entry_data["permalink"]
|
post_url_fragment = entry_data["permalink"]
|
||||||
direct_url = entry_data["url"]
|
direct_url = entry_data["url"]
|
||||||
|
|
||||||
is_text = entry_data["is_self"]
|
is_text = entry_data["is_self"]
|
||||||
is_video = entry_data["is_video"]
|
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:
|
except KeyError as e:
|
||||||
raise BuilderMissingDataException(payload=entry) from 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)
|
title = truncate_text(Post, "title", title)
|
||||||
author = truncate_text(Post, "author", author)
|
author = truncate_text(Post, "author", author)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue