diff --git a/.env.dev.example b/.env.dev.example deleted file mode 100644 index 0a9865cd..00000000 --- a/.env.dev.example +++ /dev/null @@ -1,85 +0,0 @@ -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY="7(2w1sedok=aznpq)ta1mc4i%4h=xx@hxwx*o57ctsuml0x%fr" - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG=true -USE_HTTPS=false - -DOMAIN=your.domain.here -#EMAIL=your@email.here - -# Used for deciding which editions to prefer -DEFAULT_LANGUAGE="English" - -## Leave unset to allow all hosts -# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]" - -MEDIA_ROOT=images/ - -# Database configuration -PGPORT=5432 -POSTGRES_PASSWORD=securedbypassword123 -POSTGRES_USER=fedireads -POSTGRES_DB=fedireads -POSTGRES_HOST=db - -# Redis activity stream manager -MAX_STREAM_LENGTH=200 -REDIS_ACTIVITY_HOST=redis_activity -REDIS_ACTIVITY_PORT=6379 -REDIS_ACTIVITY_PASSWORD=redispassword345 - -# Redis as celery broker -REDIS_BROKER_PORT=6379 -REDIS_BROKER_PASSWORD=redispassword123 - -# Monitoring for celery -FLOWER_PORT=8888 -FLOWER_USER=mouse -FLOWER_PASSWORD=changeme - -# Email config -EMAIL_HOST=smtp.mailgun.org -EMAIL_PORT=587 -EMAIL_HOST_USER=mail@your.domain.here -EMAIL_HOST_PASSWORD=emailpassword123 -EMAIL_USE_TLS=true -EMAIL_USE_SSL=false -EMAIL_SENDER_NAME=admin -# defaults to DOMAIN -EMAIL_SENDER_DOMAIN= - -# Query timeouts -SEARCH_TIMEOUT=15 -QUERY_TIMEOUT=5 - -# Thumbnails Generation -ENABLE_THUMBNAIL_GENERATION=false - -# S3 configuration -USE_S3=false -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= - -# Commented are example values if you use a non-AWS, S3-compatible service -# AWS S3 should work with only AWS_STORAGE_BUCKET_NAME and AWS_S3_REGION_NAME -# non-AWS S3-compatible services will need AWS_STORAGE_BUCKET_NAME, -# along with both AWS_S3_CUSTOM_DOMAIN and AWS_S3_ENDPOINT_URL - -# AWS_STORAGE_BUCKET_NAME= # "example-bucket-name" -# AWS_S3_CUSTOM_DOMAIN=None # "example-bucket-name.s3.fr-par.scw.cloud" -# AWS_S3_REGION_NAME=None # "fr-par" -# AWS_S3_ENDPOINT_URL=None # "https://s3.fr-par.scw.cloud" - - -# Preview image generation can be computing and storage intensive -# ENABLE_PREVIEW_IMAGES=True - -# Specify RGB tuple or RGB hex strings, -# or use_dominant_color_light / use_dominant_color_dark -PREVIEW_BG_COLOR=use_dominant_color_light -# Change to #FFF if you use use_dominant_color_dark -PREVIEW_TEXT_COLOR=#363636 -PREVIEW_IMG_WIDTH=1200 -PREVIEW_IMG_HEIGHT=630 -PREVIEW_DEFAULT_COVER_COLOR=#002549 diff --git a/.env.prod.example b/.env.example similarity index 100% rename from .env.prod.example rename to .env.example diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 4cba9939..f2dd43fb 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -397,9 +397,15 @@ def populate_streams_on_account_create(sender, instance, created, *args, **kwarg """build a user's feeds when they join""" if not created or not instance.local: return + transaction.on_commit( + lambda: populate_streams_on_account_create_command(instance.id) + ) + +def populate_streams_on_account_create_command(instance_id): + """wait for the transaction to complete""" for stream in streams: - populate_stream_task.delay(stream, instance.id) + populate_stream_task.delay(stream, instance_id) @receiver(signals.pre_save, sender=models.ShelfBook) diff --git a/bookwyrm/lists_stream.py b/bookwyrm/lists_stream.py new file mode 100644 index 00000000..f6a35cc2 --- /dev/null +++ b/bookwyrm/lists_stream.py @@ -0,0 +1,251 @@ +""" access the list streams stored in redis """ +from django.dispatch import receiver +from django.db import transaction +from django.db.models import signals, Count, Q + +from bookwyrm import models +from bookwyrm.redis_store import RedisStore +from bookwyrm.tasks import app, MEDIUM, HIGH + + +class ListsStream(RedisStore): + """all the lists you can see""" + + def stream_id(self, user): # pylint: disable=no-self-use + """the redis key for this user's instance of this stream""" + if isinstance(user, int): + # allows the function to take an int or an obj + return f"{user}-lists" + return f"{user.id}-lists" + + def get_rank(self, obj): # pylint: disable=no-self-use + """lists are sorted by updated date""" + return obj.updated_date.timestamp() + + def add_list(self, book_list): + """add a list to users' feeds""" + # the pipeline contains all the add-to-stream activities + self.add_object_to_related_stores(book_list) + + def add_user_lists(self, viewer, user): + """add a user's lists to another user's feed""" + # only add the lists that the viewer should be able to see + lists = models.List.privacy_filter(viewer).filter(user=user) + self.bulk_add_objects_to_store(lists, self.stream_id(viewer)) + + def remove_user_lists(self, viewer, user, exclude_privacy=None): + """remove a user's list from another user's feed""" + # remove all so that followers only lists are removed + lists = user.list_set + if exclude_privacy: + lists = lists.exclude(privacy=exclude_privacy) + self.bulk_remove_objects_from_store(lists.all(), self.stream_id(viewer)) + + def get_list_stream(self, user): + """load the lists to be displayed""" + lists = self.get_store(self.stream_id(user)) + return ( + models.List.objects.filter(id__in=lists) + .annotate(item_count=Count("listitem", filter=Q(listitem__approved=True))) + # hide lists with no approved books + .filter(item_count__gt=0) + .select_related("user") + .prefetch_related("listitem_set") + .order_by("-updated_date") + .distinct() + ) + + def populate_lists(self, user): + """go from zero to a timeline""" + self.populate_store(self.stream_id(user)) + + def get_audience(self, book_list): # pylint: disable=no-self-use + """given a list, what users should see it""" + # everybody who could plausibly see this list + audience = models.User.objects.filter( + is_active=True, + local=True, # we only create feeds for users of this instance + ).exclude( # not blocked + Q(id__in=book_list.user.blocks.all()) | Q(blocks=book_list.user) + ) + + group = book_list.group + # only visible to the poster and mentioned users + if book_list.privacy == "direct": + if group: + audience = audience.filter( + Q(id=book_list.user.id) # if the user is the post's author + | ~Q(groups=group.memberships) # if the user is in the group + ) + else: + audience = audience.filter( + Q(id=book_list.user.id) # if the user is the post's author + ) + # only visible to the poster's followers and tagged users + elif book_list.privacy == "followers": + if group: + audience = audience.filter( + Q(id=book_list.user.id) # if the user is the list's owner + | Q(following=book_list.user) # if the user is following the pwmer + # if a user is in the group + | Q(memberships__group__id=book_list.group.id) + ) + else: + audience = audience.filter( + Q(id=book_list.user.id) # if the user is the list's owner + | Q(following=book_list.user) # if the user is following the pwmer + ) + return audience.distinct() + + def get_stores_for_object(self, obj): + return [self.stream_id(u) for u in self.get_audience(obj)] + + def get_lists_for_user(self, user): # pylint: disable=no-self-use + """given a user, what lists should they see on this stream""" + return models.List.privacy_filter( + user, + privacy_levels=["public", "followers"], + ) + + def get_objects_for_store(self, store): + user = models.User.objects.get(id=store.split("-")[0]) + return self.get_lists_for_user(user) + + +@receiver(signals.post_save, sender=models.List) +# pylint: disable=unused-argument +def add_list_on_create(sender, instance, created, *args, **kwargs): + """add newly created lists streamsstreams""" + if not created: + return + # when creating new things, gotta wait on the transaction + transaction.on_commit(lambda: add_list_on_create_command(instance.id)) + + +@receiver(signals.post_delete, sender=models.List) +# pylint: disable=unused-argument +def remove_list_on_delete(sender, instance, *args, **kwargs): + """remove deleted lists to streams""" + remove_list_task.delay(instance.id) + + +def add_list_on_create_command(instance_id): + """runs this code only after the database commit completes""" + add_list_task.delay(instance_id) + + +@receiver(signals.post_save, sender=models.UserFollows) +# pylint: disable=unused-argument +def add_lists_on_follow(sender, instance, created, *args, **kwargs): + """add a newly followed user's lists to feeds""" + if not created or not instance.user_subject.local: + return + add_user_lists_task.delay(instance.user_subject.id, instance.user_object.id) + + +@receiver(signals.post_delete, sender=models.UserFollows) +# pylint: disable=unused-argument +def remove_lists_on_unfollow(sender, instance, *args, **kwargs): + """remove lists from a feed on unfollow""" + if not instance.user_subject.local: + return + # remove all but public lists + remove_user_lists_task.delay( + instance.user_subject.id, instance.user_object.id, exclude_privacy="public" + ) + + +@receiver(signals.post_save, sender=models.UserBlocks) +# pylint: disable=unused-argument +def remove_lists_on_block(sender, instance, *args, **kwargs): + """remove lists from all feeds on block""" + # blocks apply ot all feeds + if instance.user_subject.local: + remove_user_lists_task.delay(instance.user_subject.id, instance.user_object.id) + + # and in both directions + if instance.user_object.local: + remove_user_lists_task.delay(instance.user_object.id, instance.user_subject.id) + + +@receiver(signals.post_delete, sender=models.UserBlocks) +# pylint: disable=unused-argument +def add_lists_on_unblock(sender, instance, *args, **kwargs): + """add lists back to all feeds on unblock""" + # make sure there isn't a block in the other direction + if models.UserBlocks.objects.filter( + user_subject=instance.user_object, + user_object=instance.user_subject, + ).exists(): + return + + # add lists back to streams with lists from anyone + if instance.user_subject.local: + add_user_lists_task.delay( + instance.user_subject.id, + instance.user_object.id, + ) + + # add lists back to streams with lists from anyone + if instance.user_object.local: + add_user_lists_task.delay( + instance.user_object.id, + instance.user_subject.id, + ) + + +@receiver(signals.post_save, sender=models.User) +# pylint: disable=unused-argument +def populate_lists_on_account_create(sender, instance, created, *args, **kwargs): + """build a user's feeds when they join""" + if not created or not instance.local: + return + transaction.on_commit(lambda: add_list_on_account_create_command(instance.id)) + + +def add_list_on_account_create_command(user_id): + """wait for the transaction to complete""" + populate_lists_task.delay(user_id) + + +# ---- TASKS +@app.task(queue=MEDIUM) +def populate_lists_task(user_id): + """background task for populating an empty list stream""" + user = models.User.objects.get(id=user_id) + ListsStream().populate_lists(user) + + +@app.task(queue=MEDIUM) +def remove_list_task(list_id): + """remove a list from any stream it might be in""" + stores = models.User.objects.filter(local=True, is_active=True).values_list( + "id", flat=True + ) + + # delete for every store + stores = [ListsStream().stream_id(idx) for idx in stores] + ListsStream().remove_object_from_related_stores(list_id, stores=stores) + + +@app.task(queue=HIGH) +def add_list_task(list_id): + """add a list to any stream it should be in""" + book_list = models.List.objects.get(id=list_id) + ListsStream().add_list(book_list) + + +@app.task(queue=MEDIUM) +def remove_user_lists_task(viewer_id, user_id, exclude_privacy=None): + """remove all lists by a user from a viewer's stream""" + viewer = models.User.objects.get(id=viewer_id) + user = models.User.objects.get(id=user_id) + ListsStream().remove_user_lists(viewer, user, exclude_privacy=exclude_privacy) + + +@app.task(queue=MEDIUM) +def add_user_lists_task(viewer_id, user_id): + """add all lists by a user to a viewer's stream""" + viewer = models.User.objects.get(id=viewer_id) + user = models.User.objects.get(id=user_id) + ListsStream().add_user_lists(viewer, user) diff --git a/bookwyrm/management/commands/populate_lists_streams.py b/bookwyrm/management/commands/populate_lists_streams.py new file mode 100644 index 00000000..c08b36d5 --- /dev/null +++ b/bookwyrm/management/commands/populate_lists_streams.py @@ -0,0 +1,34 @@ +""" Re-create list streams """ +from django.core.management.base import BaseCommand +from bookwyrm import lists_stream, models + + +def populate_lists_streams(): + """build all the lists streams for all the users""" + print("Populating lists streams") + users = models.User.objects.filter( + local=True, + is_active=True, + ).order_by("-last_active_date") + print("This may take a long time! Please be patient.") + for user in users: + print(".", end="") + lists_stream.populate_lists_task.delay(user.id) + + +class Command(BaseCommand): + """start all over with lists streams""" + + help = "Populate list streams for all users" + + def add_arguments(self, parser): + parser.add_argument( + "--stream", + default=None, + help="Specifies which time of stream to populate", + ) + + # pylint: disable=no-self-use,unused-argument + def handle(self, *args, **options): + """run feed builder""" + populate_lists_streams() diff --git a/bookwyrm/management/commands/populate_streams.py b/bookwyrm/management/commands/populate_streams.py index 0b09ea6c..5f83670c 100644 --- a/bookwyrm/management/commands/populate_streams.py +++ b/bookwyrm/management/commands/populate_streams.py @@ -1,6 +1,6 @@ """ Re-create user streams """ from django.core.management.base import BaseCommand -from bookwyrm import activitystreams, models +from bookwyrm import activitystreams, lists_stream, models def populate_streams(stream=None): @@ -13,6 +13,8 @@ def populate_streams(stream=None): ).order_by("-last_active_date") print("This may take a long time! Please be patient.") for user in users: + print(".", end="") + lists_stream.populate_lists_task.delay(user.id) for stream_key in streams: print(".", end="") activitystreams.populate_stream_task.delay(stream_key, user.id) diff --git a/bookwyrm/migrations/0124_auto_20220106_1759.py b/bookwyrm/migrations/0124_auto_20220106_1759.py new file mode 100644 index 00000000..068bedbb --- /dev/null +++ b/bookwyrm/migrations/0124_auto_20220106_1759.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.10 on 2022-01-06 17:59 + +from django.contrib.auth.models import AbstractUser +from django.db import migrations + + +def get_admins(apps, schema_editor): + """add any superusers to the "admin" group""" + + db_alias = schema_editor.connection.alias + groups = apps.get_model("auth", "Group") + try: + group = groups.objects.using(db_alias).get(name="admin") + except groups.DoesNotExist: + # for tests + return + + users = apps.get_model("bookwyrm", "User") + admins = users.objects.using(db_alias).filter(is_superuser=True) + + for admin in admins: + admin.groups.add(group) + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0123_alter_user_preferred_language"), + ] + + operations = [ + migrations.RunPython(get_admins, reverse_code=migrations.RunPython.noop), + ] diff --git a/bookwyrm/redis_store.py b/bookwyrm/redis_store.py index 595868ff..964409e8 100644 --- a/bookwyrm/redis_store.py +++ b/bookwyrm/redis_store.py @@ -30,7 +30,8 @@ class RedisStore(ABC): # add the status to the feed pipeline.zadd(store, value) # trim the store - pipeline.zremrangebyrank(store, 0, -1 * self.max_length) + if self.max_length: + pipeline.zremrangebyrank(store, 0, -1 * self.max_length) if not execute: return pipeline # and go! @@ -38,10 +39,15 @@ class RedisStore(ABC): def remove_object_from_related_stores(self, obj, stores=None): """remove an object from all stores""" + # if the stoers are provided, the object can just be an id + if stores and isinstance(obj, int): + obj_id = obj + else: + obj_id = obj.id stores = self.get_stores_for_object(obj) if stores is None else stores pipeline = r.pipeline() for store in stores: - pipeline.zrem(store, -1, obj.id) + pipeline.zrem(store, -1, obj_id) pipeline.execute() def bulk_add_objects_to_store(self, objs, store): @@ -49,7 +55,7 @@ class RedisStore(ABC): pipeline = r.pipeline() for obj in objs[: self.max_length]: pipeline.zadd(store, self.get_value(obj)) - if objs: + if objs and self.max_length: pipeline.zremrangebyrank(store, 0, -1 * self.max_length) pipeline.execute() @@ -73,7 +79,7 @@ class RedisStore(ABC): pipeline.zadd(store, self.get_value(obj)) # only trim the store if objects were added - if queryset.exists(): + if queryset.exists() and self.max_length: pipeline.zremrangebyrank(store, 0, -1 * self.max_length) pipeline.execute() diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 4d316c63..c06b17bf 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -9,7 +9,7 @@ from django.utils.translation import gettext_lazy as _ env = Env() env.read_env() DOMAIN = env("DOMAIN") -VERSION = "0.1.0" +VERSION = "0.1.1" PAGE_LENGTH = env("PAGE_LENGTH", 15) DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English") diff --git a/bookwyrm/suggested_users.py b/bookwyrm/suggested_users.py index b30e8412..ea6bc886 100644 --- a/bookwyrm/suggested_users.py +++ b/bookwyrm/suggested_users.py @@ -2,6 +2,7 @@ import math import logging from django.dispatch import receiver +from django.db import transaction from django.db.models import signals, Count, Q, Case, When, IntegerField from bookwyrm import models @@ -192,7 +193,7 @@ def update_user(sender, instance, created, update_fields=None, **kwargs): """an updated user, neat""" # a new user is found, create suggestions for them if created and instance.local: - rerank_suggestions_task.delay(instance.id) + transaction.on_commit(lambda: update_new_user_command(instance.id)) # we know what fields were updated and discoverability didn't change if not instance.bookwyrm_user or ( @@ -212,6 +213,11 @@ def update_user(sender, instance, created, update_fields=None, **kwargs): remove_user_task.delay(instance.id) +def update_new_user_command(instance_id): + """wait for transaction to complete""" + rerank_suggestions_task.delay(instance_id) + + @receiver(signals.post_save, sender=models.FederatedServer) def domain_level_update(sender, instance, created, update_fields=None, **kwargs): """remove users on a domain block""" diff --git a/bookwyrm/templates/about/about.html b/bookwyrm/templates/about/about.html new file mode 100644 index 00000000..aa241375 --- /dev/null +++ b/bookwyrm/templates/about/about.html @@ -0,0 +1,141 @@ +{% extends 'about/layout.html' %} +{% load humanize %} +{% load i18n %} +{% load utilities %} +{% load bookwyrm_tags %} +{% load cache %} + +{% block title %} +{% trans "About" %} +{% endblock %} + +{% block about_content %} +{# seven day cache #} +{% cache 604800 about_page %} +{% get_book_superlatives as superlatives %} +
+

+ {% blocktrans with site_name=site.name %}Welcome to {{ site_name }}!{% endblocktrans %} +

+ +

+ {% blocktrans trimmed with site_name=site.name %} + {{ site_name }} is part of BookWyrm, a network of independent, self-directed communities for readers. + While you can interact seemlessly with users anywhere in the BookWyrm network, this community is unique. + {% endblocktrans %} +

+ +
+ {% if top_rated %} + {% with book=superlatives.top_rated.default_edition rating=top_rated.rating %} +
+
+ +
+ {% blocktrans trimmed with title=book|book_title book_path=book.local_path site_name=site.name rating=rating|floatformat:1 %} + {{ title }} is {{ site_name }}'s most beloved book, with an average rating of {{ rating }} out of 5. + {% endblocktrans %} +
+
+
+ {% endwith %} + {% endif %} + + {% if wanted %} + {% with book=superlatives.wanted.default_edition %} +
+
+ +
+ {% blocktrans trimmed with title=book|book_title book_path=book.local_path site_name=site.name %} + More {{ site_name }} users want to read {{ title }} than any other book. + {% endblocktrans %} +
+
+
+ {% endwith %} + {% endif %} + + {% if controversial %} + {% with book=superlatives.controversial.default_edition %} +
+
+ +
+ {% blocktrans trimmed with title=book|book_title book_path=book.local_path site_name=site.name %} + {{ title }} has the most divisive ratings of any book on {{ site_name }}. + {% endblocktrans %} +
+
+
+ {% endwith %} + {% endif %} +
+ +

+ {% trans "Track your reading, talk about books, write reviews, and discover what to read next. Always ad-free, anti-corporate, and community-oriented, BookWyrm is human-scale software, designed to stay small and personal. If you have feature requests, bug reports, or grand dreams, reach out and make yourself heard." %} +

+ +
+ +
+
+

{% trans "Meet your admins" %}

+

+ {% url "conduct" as coc_path %} + {% blocktrans with site_name=site.name %} + {{ site_name }}'s moderators and administrators keep the site up and running, enforce the code of conduct, and respond when users report spam and bad behavior. + {% endblocktrans %} +

+
+ +
+ {% for user in admins %} +
+
+ {% with role=user.groups.first.name %} +
+ + {% if role == "moderator" %} + {% trans "Moderator" %} + {% else %} + {% trans "Admin" %} + {% endif %} + +
+ {% endwith %} + +
+ {% include 'user/user_preview.html' with user=user %} +
+ + {% if request.user.is_authenticated and user.id != request.user.id %} + + {% endif %} +
+
+ {% endfor %} +
+
+ +{% endcache %} +{% endblock %} diff --git a/bookwyrm/templates/about/conduct.html b/bookwyrm/templates/about/conduct.html new file mode 100644 index 00000000..a38a0168 --- /dev/null +++ b/bookwyrm/templates/about/conduct.html @@ -0,0 +1,15 @@ +{% extends 'about/layout.html' %} +{% load i18n %} + +{% block title %}{% trans "Code of Conduct" %}{% endblock %} + + +{% block about_content %} +
+

{% trans "Code of Conduct" %}

+
+ {{ site.code_of_conduct | safe }} +
+
+ +{% endblock %} diff --git a/bookwyrm/templates/about/layout.html b/bookwyrm/templates/about/layout.html new file mode 100644 index 00000000..458e4b1d --- /dev/null +++ b/bookwyrm/templates/about/layout.html @@ -0,0 +1,57 @@ +{% extends 'landing/layout.html' %} +{% load humanize %} +{% load i18n %} + +{% block about_panel %} +
+ {% include "snippets/about.html" with size="m" %} + {% if active_users %} + + {% endif %} +
+{% endblock %} + +{% block panel %} +
+ + +
+ {% block about_content %}{% endblock %} +
+
+{% endblock %} diff --git a/bookwyrm/templates/about/privacy.html b/bookwyrm/templates/about/privacy.html new file mode 100644 index 00000000..c43b9da1 --- /dev/null +++ b/bookwyrm/templates/about/privacy.html @@ -0,0 +1,15 @@ +{% extends 'about/layout.html' %} +{% load i18n %} + +{% block title %}{% trans "Privacy Policy" %}{% endblock %} + +{% block about_content %} + +
+

{% trans "Privacy Policy" %}

+
+ {{ site.privacy_policy | safe }} +
+
+ +{% endblock %} diff --git a/bookwyrm/templates/landing/about.html b/bookwyrm/templates/landing/about.html deleted file mode 100644 index c3b1e84e..00000000 --- a/bookwyrm/templates/landing/about.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends 'landing/layout.html' %} -{% load i18n %} - -{% block panel %} -
- - -
-
-

{% trans "Code of Conduct" %}

-
- {{ site.code_of_conduct | safe }} -
-
- - - -
-

{% trans "Privacy Policy" %}

-
- {{ site.privacy_policy | safe }} -
-
-
-
- -{% endblock %} diff --git a/bookwyrm/templates/landing/layout.html b/bookwyrm/templates/landing/layout.html index 56985768..afe8cecc 100644 --- a/bookwyrm/templates/landing/layout.html +++ b/bookwyrm/templates/landing/layout.html @@ -31,6 +31,7 @@ +{% block about_panel %}
@@ -89,6 +90,7 @@ {% endif %}
+{% endblock %} {% block panel %}{% endblock %} diff --git a/bookwyrm/templates/snippets/about.html b/bookwyrm/templates/snippets/about.html index c9a9db80..786c8f72 100644 --- a/bookwyrm/templates/snippets/about.html +++ b/bookwyrm/templates/snippets/about.html @@ -2,7 +2,7 @@
-
+
BookWyrm logo
diff --git a/bookwyrm/templates/snippets/status/content_status.html b/bookwyrm/templates/snippets/status/content_status.html index 01734cc7..034e29e9 100644 --- a/bookwyrm/templates/snippets/status/content_status.html +++ b/bookwyrm/templates/snippets/status/content_status.html @@ -3,6 +3,7 @@ {% load i18n %} {% load static %} {% load humanize %} +{% load cache %} {% with status_type=status.status_type %}
{% if not hide_book %} + {% cache 259200 content_status_book status.id %} {% with book=status.book|default:status.mention_books.first %} {% if book %}
@@ -34,6 +36,7 @@
{% endif %} {% endwith %} + {% endcache %} {% endif %}
diff --git a/bookwyrm/templates/snippets/status/generated_status.html b/bookwyrm/templates/snippets/status/generated_status.html index e73b9c32..1234ae7c 100644 --- a/bookwyrm/templates/snippets/status/generated_status.html +++ b/bookwyrm/templates/snippets/status/generated_status.html @@ -3,8 +3,10 @@ {% load bookwyrm_tags %} {% load markdown %} {% load i18n %} +{% load cache %} {% if not hide_book %} + {% cache 259200 generated_status_book status.id %} {% with book=status.book|default:status.mention_books.first %}
{% endwith %} + {% endcache %} {% endif %} {% endspaceless %} diff --git a/bookwyrm/templates/user/user_preview.html b/bookwyrm/templates/user/user_preview.html index c6b3ea84..c46563e5 100755 --- a/bookwyrm/templates/user/user_preview.html +++ b/bookwyrm/templates/user/user_preview.html @@ -21,23 +21,23 @@

{{ user.username }}

{% blocktrans with date=user.created_date|naturaltime %}Joined {{ date }}{% endblocktrans %}

- {% if is_self %} + {% if request.user.id == user.id %} - {% blocktrans count counter=user.followers.count %}{{ counter }} follower{% plural %}{{ counter }} followers{% endblocktrans %}, - {% blocktrans with counter=user.following.count %}{{ counter }} following{% endblocktrans %} + {% blocktrans count counter=user.followers.count %}{{ counter }} follower{% plural %}{{ counter }} followers{% endblocktrans %}, + {% blocktrans with counter=user.following.count %}{{ counter }} following{% endblocktrans %} {% elif request.user.is_authenticated %} - {% mutuals_count user as mutuals %} - - {% if mutuals %} - {% blocktrans with mutuals_display=mutuals|intcomma count counter=mutuals %}{{ mutuals_display }} follower you follow{% plural %}{{ mutuals_display }} followers you follow{% endblocktrans %} - {% elif request.user in user.following.all %} - {% trans "Follows you" %} - {% else %} - {% trans "No followers you follow" %} - {% endif %} - + {% mutuals_count user as mutuals %} + + {% if mutuals %} + {% blocktrans with mutuals_display=mutuals|intcomma count counter=mutuals %}{{ mutuals_display }} follower you follow{% plural %}{{ mutuals_display }} followers you follow{% endblocktrans %} + {% elif request.user in user.following.all %} + {% trans "Follows you" %} + {% else %} + {% trans "No followers you follow" %} + {% endif %} + {% endif %}

diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index f173e052..f24219d2 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -1,6 +1,6 @@ """ template filters """ from django import template -from django.db.models import Avg +from django.db.models import Avg, StdDev, Count, F, Q from bookwyrm import models from bookwyrm.views.feed import get_suggested_books @@ -68,6 +68,57 @@ def load_subclass(status): return status +@register.simple_tag(takes_context=False) +def get_book_superlatives(): + """get book stats for the about page""" + total_ratings = models.Review.objects.filter(local=True, deleted=False).count() + data = {} + data["top_rated"] = ( + models.Work.objects.annotate( + rating=Avg( + "editions__review__rating", + filter=Q(editions__review__local=True, editions__review__deleted=False), + ), + rating_count=Count( + "editions__review", + filter=Q(editions__review__local=True, editions__review__deleted=False), + ), + ) + .annotate(weighted=F("rating") * F("rating_count") / total_ratings) + .filter(rating__gt=4, weighted__gt=0) + .order_by("-weighted") + .first() + ) + + data["controversial"] = ( + models.Work.objects.annotate( + deviation=StdDev( + "editions__review__rating", + filter=Q(editions__review__local=True, editions__review__deleted=False), + ), + rating_count=Count( + "editions__review", + filter=Q(editions__review__local=True, editions__review__deleted=False), + ), + ) + .annotate(weighted=F("deviation") * F("rating_count") / total_ratings) + .filter(weighted__gt=0) + .order_by("-weighted") + .first() + ) + + data["wanted"] = ( + models.Work.objects.annotate( + shelf_count=Count( + "editions__shelves", filter=Q(editions__shelves__identifier="to-read") + ) + ) + .order_by("-shelf_count") + .first() + ) + return data + + @register.simple_tag(takes_context=False) def related_status(notification): """for notifications""" diff --git a/bookwyrm/tests/activitypub/test_base_activity.py b/bookwyrm/tests/activitypub/test_base_activity.py index b951c7ab..973e57bf 100644 --- a/bookwyrm/tests/activitypub/test_base_activity.py +++ b/bookwyrm/tests/activitypub/test_base_activity.py @@ -31,7 +31,7 @@ class BaseActivity(TestCase): """we're probably going to re-use this so why copy/paste""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/activitystreams/test_abstractstream.py b/bookwyrm/tests/activitystreams/test_abstractstream.py index 17a1b587..2c5cf610 100644 --- a/bookwyrm/tests/activitystreams/test_abstractstream.py +++ b/bookwyrm/tests/activitystreams/test_abstractstream.py @@ -16,7 +16,7 @@ class Activitystreams(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/activitystreams/test_booksstream.py b/bookwyrm/tests/activitystreams/test_booksstream.py index 347e7a94..c001d6dd 100644 --- a/bookwyrm/tests/activitystreams/test_booksstream.py +++ b/bookwyrm/tests/activitystreams/test_booksstream.py @@ -16,7 +16,7 @@ class Activitystreams(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/activitystreams/test_homestream.py b/bookwyrm/tests/activitystreams/test_homestream.py index d48bdfba..10c806c8 100644 --- a/bookwyrm/tests/activitystreams/test_homestream.py +++ b/bookwyrm/tests/activitystreams/test_homestream.py @@ -16,7 +16,7 @@ class Activitystreams(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/activitystreams/test_localstream.py b/bookwyrm/tests/activitystreams/test_localstream.py index fa1a6741..d8bfb4fa 100644 --- a/bookwyrm/tests/activitystreams/test_localstream.py +++ b/bookwyrm/tests/activitystreams/test_localstream.py @@ -16,7 +16,7 @@ class Activitystreams(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/activitystreams/test_signals.py b/bookwyrm/tests/activitystreams/test_signals.py index 34aeb947..4db1875f 100644 --- a/bookwyrm/tests/activitystreams/test_signals.py +++ b/bookwyrm/tests/activitystreams/test_signals.py @@ -5,6 +5,8 @@ from bookwyrm import activitystreams, models @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") +@patch("bookwyrm.lists_stream.add_user_lists_task.delay") +@patch("bookwyrm.lists_stream.remove_user_lists_task.delay") class ActivitystreamsSignals(TestCase): """using redis to build activity streams""" @@ -12,7 +14,7 @@ class ActivitystreamsSignals(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) @@ -32,11 +34,11 @@ class ActivitystreamsSignals(TestCase): work = models.Work.objects.create(title="test work") self.book = models.Edition.objects.create(title="test book", parent_work=work) - def test_add_status_on_create_ignore(self, _): + def test_add_status_on_create_ignore(self, *_): """a new statuses has entered""" activitystreams.add_status_on_create(models.User, self.local_user, False) - def test_add_status_on_create_deleted(self, _): + def test_add_status_on_create_deleted(self, *_): """a new statuses has entered""" with patch("bookwyrm.activitystreams.remove_status_task.delay"): status = models.Status.objects.create( @@ -48,7 +50,7 @@ class ActivitystreamsSignals(TestCase): args = mock.call_args[0] self.assertEqual(args[0], status.id) - def test_add_status_on_create_created(self, _): + def test_add_status_on_create_created(self, *_): """a new statuses has entered""" status = models.Status.objects.create( user=self.remote_user, content="hi", privacy="public" @@ -60,18 +62,18 @@ class ActivitystreamsSignals(TestCase): self.assertEqual(args["args"][0], status.id) self.assertEqual(args["queue"], "high_priority") - def test_populate_streams_on_account_create(self, _): + def test_populate_streams_on_account_create_command(self, *_): """create streams for a user""" with patch("bookwyrm.activitystreams.populate_stream_task.delay") as mock: - activitystreams.populate_streams_on_account_create( - models.User, self.local_user, True + activitystreams.populate_streams_on_account_create_command( + self.local_user.id ) self.assertEqual(mock.call_count, 3) args = mock.call_args[0] self.assertEqual(args[0], "books") self.assertEqual(args[1], self.local_user.id) - def test_remove_statuses_on_block(self, _): + def test_remove_statuses_on_block(self, *_): """don't show statuses from blocked users""" with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") as mock: models.UserBlocks.objects.create( @@ -83,7 +85,7 @@ class ActivitystreamsSignals(TestCase): self.assertEqual(args[0], self.local_user.id) self.assertEqual(args[1], self.remote_user.id) - def test_add_statuses_on_unblock(self, _): + def test_add_statuses_on_unblock(self, *_): """re-add statuses on unblock""" with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"): block = models.UserBlocks.objects.create( @@ -100,7 +102,7 @@ class ActivitystreamsSignals(TestCase): self.assertEqual(args[1], self.remote_user.id) self.assertEqual(kwargs["stream_list"], ["local", "books"]) - def test_add_statuses_on_unblock_reciprocal_block(self, _): + def test_add_statuses_on_unblock_reciprocal_block(self, *_): """re-add statuses on unblock""" with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"): block = models.UserBlocks.objects.create( diff --git a/bookwyrm/tests/activitystreams/test_tasks.py b/bookwyrm/tests/activitystreams/test_tasks.py index f5750763..af05cf18 100644 --- a/bookwyrm/tests/activitystreams/test_tasks.py +++ b/bookwyrm/tests/activitystreams/test_tasks.py @@ -11,7 +11,7 @@ class Activitystreams(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/importers/test_goodreads_import.py b/bookwyrm/tests/importers/test_goodreads_import.py index 0a421df4..04fb886b 100644 --- a/bookwyrm/tests/importers/test_goodreads_import.py +++ b/bookwyrm/tests/importers/test_goodreads_import.py @@ -30,7 +30,7 @@ class GoodreadsImport(TestCase): self.csv = open(datafile, "r", encoding=self.importer.encoding) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True ) diff --git a/bookwyrm/tests/importers/test_importer.py b/bookwyrm/tests/importers/test_importer.py index 4599568b..c8da8a27 100644 --- a/bookwyrm/tests/importers/test_importer.py +++ b/bookwyrm/tests/importers/test_importer.py @@ -33,7 +33,7 @@ class GenericImporter(TestCase): self.csv = open(datafile, "r", encoding=self.importer.encoding) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True ) diff --git a/bookwyrm/tests/importers/test_librarything_import.py b/bookwyrm/tests/importers/test_librarything_import.py index 49354b36..57d55520 100644 --- a/bookwyrm/tests/importers/test_librarything_import.py +++ b/bookwyrm/tests/importers/test_librarything_import.py @@ -32,7 +32,7 @@ class LibrarythingImport(TestCase): self.csv = open(datafile, "r", encoding=self.importer.encoding) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mmai", "mmai@mmai.mmai", "password", local=True ) diff --git a/bookwyrm/tests/importers/test_openlibrary_import.py b/bookwyrm/tests/importers/test_openlibrary_import.py index 6a25c191..a775c596 100644 --- a/bookwyrm/tests/importers/test_openlibrary_import.py +++ b/bookwyrm/tests/importers/test_openlibrary_import.py @@ -30,7 +30,7 @@ class OpenLibraryImport(TestCase): self.csv = open(datafile, "r", encoding=self.importer.encoding) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True ) diff --git a/bookwyrm/tests/importers/test_storygraph_import.py b/bookwyrm/tests/importers/test_storygraph_import.py index 8db459dc..670c6e5e 100644 --- a/bookwyrm/tests/importers/test_storygraph_import.py +++ b/bookwyrm/tests/importers/test_storygraph_import.py @@ -30,7 +30,7 @@ class StorygraphImport(TestCase): self.csv = open(datafile, "r", encoding=self.importer.encoding) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True ) diff --git a/bookwyrm/tests/lists_stream/__init__.py b/bookwyrm/tests/lists_stream/__init__.py new file mode 100644 index 00000000..b6e690fd --- /dev/null +++ b/bookwyrm/tests/lists_stream/__init__.py @@ -0,0 +1 @@ +from . import * diff --git a/bookwyrm/tests/lists_stream/test_signals.py b/bookwyrm/tests/lists_stream/test_signals.py new file mode 100644 index 00000000..f82dba3a --- /dev/null +++ b/bookwyrm/tests/lists_stream/test_signals.py @@ -0,0 +1,109 @@ +""" testing lists_stream """ +from unittest.mock import patch +from django.test import TestCase +from bookwyrm import lists_stream, models + + +@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") +class ListsStreamSignals(TestCase): + """using redis to build activity streams""" + + def setUp(self): + """use a test csv""" + with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( + "bookwyrm.activitystreams.populate_stream_task.delay" + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): + self.local_user = models.User.objects.create_user( + "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" + ) + self.another_user = models.User.objects.create_user( + "fish", "fish@fish.fish", "password", local=True, localname="fish" + ) + with patch("bookwyrm.models.user.set_remote_server.delay"): + self.remote_user = models.User.objects.create_user( + "rat", + "rat@rat.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) + + def test_add_list_on_create_command(self, _): + """a new lists has entered""" + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) + with patch("bookwyrm.lists_stream.add_list_task.delay") as mock: + lists_stream.add_list_on_create_command(book_list.id) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], book_list.id) + + def test_remove_list_on_delete(self, _): + """delete a list""" + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) + with patch("bookwyrm.lists_stream.remove_list_task.delay") as mock: + lists_stream.remove_list_on_delete(models.List, book_list) + args = mock.call_args[0] + self.assertEqual(args[0], book_list.id) + + def test_populate_lists_on_account_create_command(self, _): + """create streams for a user""" + with patch("bookwyrm.lists_stream.populate_lists_task.delay") as mock: + lists_stream.add_list_on_account_create_command(self.local_user.id) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user.id) + + @patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") + def test_remove_lists_on_block(self, *_): + """don't show lists from blocked users""" + with patch("bookwyrm.lists_stream.remove_user_lists_task.delay") as mock: + models.UserBlocks.objects.create( + user_subject=self.local_user, + user_object=self.remote_user, + ) + + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user.id) + self.assertEqual(args[1], self.remote_user.id) + + @patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") + @patch("bookwyrm.activitystreams.add_user_statuses_task.delay") + def test_add_lists_on_unblock(self, *_): + """re-add lists on unblock""" + with patch("bookwyrm.lists_stream.remove_user_lists_task.delay"): + block = models.UserBlocks.objects.create( + user_subject=self.local_user, + user_object=self.remote_user, + ) + + with patch("bookwyrm.lists_stream.add_user_lists_task.delay") as mock: + block.delete() + + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user.id) + self.assertEqual(args[1], self.remote_user.id) + + @patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") + @patch("bookwyrm.activitystreams.add_user_statuses_task.delay") + def test_add_lists_on_unblock_reciprocal_block(self, *_): + """dont' re-add lists on unblock if there's a block the other way""" + with patch("bookwyrm.lists_stream.remove_user_lists_task.delay"): + block = models.UserBlocks.objects.create( + user_subject=self.local_user, + user_object=self.remote_user, + ) + block = models.UserBlocks.objects.create( + user_subject=self.remote_user, + user_object=self.local_user, + ) + + with patch("bookwyrm.lists_stream.add_user_lists_task.delay") as mock: + block.delete() + + self.assertFalse(mock.called) diff --git a/bookwyrm/tests/lists_stream/test_stream.py b/bookwyrm/tests/lists_stream/test_stream.py new file mode 100644 index 00000000..4d8aa52b --- /dev/null +++ b/bookwyrm/tests/lists_stream/test_stream.py @@ -0,0 +1,171 @@ +""" testing activitystreams """ +from datetime import datetime +from unittest.mock import patch + +from django.test import TestCase +from bookwyrm import lists_stream, models + + +@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") +@patch("bookwyrm.activitystreams.add_status_task.delay") +@patch("bookwyrm.activitystreams.add_book_statuses_task.delay") +@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") +@patch("bookwyrm.activitystreams.populate_stream_task.delay") +class ListsStream(TestCase): + """using redis to build activity streams""" + + def setUp(self): + """use a test csv""" + with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( + "bookwyrm.activitystreams.populate_stream_task.delay" + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): + self.local_user = models.User.objects.create_user( + "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" + ) + self.another_user = models.User.objects.create_user( + "nutria", + "nutria@nutria.nutria", + "password", + local=True, + localname="nutria", + ) + with patch("bookwyrm.models.user.set_remote_server.delay"): + self.remote_user = models.User.objects.create_user( + "rat", + "rat@rat.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) + self.stream = lists_stream.ListsStream() + + def test_lists_stream_ids(self, *_): + """the abstract base class for stream objects""" + self.assertEqual( + self.stream.stream_id(self.local_user), + f"{self.local_user.id}-lists", + ) + + def test_get_rank(self, *_): + """sort order for lists""" + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) + book_list.updated_date = datetime(2020, 1, 1, 0, 0, 0) + self.assertEqual(self.stream.get_rank(book_list), 1577836800.0) + + def test_add_user_lists(self, *_): + """add all of a user's lists""" + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) + with patch( + "bookwyrm.lists_stream.ListsStream.bulk_add_objects_to_store" + ) as mock: + self.stream.add_user_lists(self.local_user, self.remote_user) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0][0], book_list) + self.assertEqual(args[1], f"{self.local_user.id}-lists") + + def test_remove_user_lists(self, *_): + """remove user's lists""" + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) + with patch( + "bookwyrm.lists_stream.ListsStream.bulk_remove_objects_from_store" + ) as mock: + self.stream.remove_user_lists(self.local_user, self.remote_user) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0][0], book_list) + self.assertEqual(args[1], f"{self.local_user.id}-lists") + + def test_get_audience(self, *_): + """get a list of users that should see a list""" + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="public" + ) + users = self.stream.get_audience(book_list) + # remote users don't have feeds + self.assertFalse(self.remote_user in users) + self.assertTrue(self.local_user in users) + self.assertTrue(self.another_user in users) + + def test_get_audience_direct(self, *_): + """get a list of users that should see a list""" + book_list = models.List.objects.create( + user=self.remote_user, + name="hi", + privacy="direct", + ) + users = self.stream.get_audience(book_list) + self.assertFalse(users.exists()) + + book_list = models.List.objects.create( + user=self.local_user, + name="hi", + privacy="direct", + ) + users = self.stream.get_audience(book_list) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + self.assertFalse(self.remote_user in users) + + def test_get_audience_followers_remote_user(self, *_): + """get a list of users that should see a list""" + book_list = models.List.objects.create( + user=self.remote_user, + name="hi", + privacy="followers", + ) + users = self.stream.get_audience(book_list) + self.assertFalse(users.exists()) + + def test_get_audience_followers_self(self, *_): + """get a list of users that should see a list""" + book_list = models.List.objects.create( + user=self.local_user, + name="hi", + privacy="followers", + ) + users = self.stream.get_audience(book_list) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + self.assertFalse(self.remote_user in users) + + def test_get_audience_followers_with_relationship(self, *_): + """get a list of users that should see a list""" + self.remote_user.followers.add(self.local_user) + book_list = models.List.objects.create( + user=self.remote_user, + name="hi", + privacy="followers", + ) + users = self.stream.get_audience(book_list) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + + def test_get_audience_followers_with_group(self, *_): + """get a list of users that should see a list""" + group = models.Group.objects.create(name="test group", user=self.remote_user) + models.GroupMember.objects.create( + group=group, + user=self.local_user, + ) + + book_list = models.List.objects.create( + user=self.remote_user, name="hi", privacy="followers", curation="group" + ) + users = self.stream.get_audience(book_list) + self.assertFalse(self.local_user in users) + + book_list.group = group + book_list.save(broadcast=False) + + users = self.stream.get_audience(book_list) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) diff --git a/bookwyrm/tests/lists_stream/test_tasks.py b/bookwyrm/tests/lists_stream/test_tasks.py new file mode 100644 index 00000000..1da36b71 --- /dev/null +++ b/bookwyrm/tests/lists_stream/test_tasks.py @@ -0,0 +1,109 @@ +""" testing lists_stream """ +from unittest.mock import patch +from django.test import TestCase +from bookwyrm import lists_stream, models + + +@patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") +@patch("bookwyrm.activitystreams.add_user_statuses_task.delay") +class Activitystreams(TestCase): + """using redis to build activity streams""" + + def setUp(self): + """use a test csv""" + with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( + "bookwyrm.activitystreams.populate_stream_task.delay" + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): + self.local_user = models.User.objects.create_user( + "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" + ) + self.another_user = models.User.objects.create_user( + "nutria", + "nutria@nutria.nutria", + "password", + local=True, + localname="nutria", + ) + with patch("bookwyrm.models.user.set_remote_server.delay"): + self.remote_user = models.User.objects.create_user( + "rat", + "rat@rat.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + self.list = models.List.objects.create( + user=self.local_user, name="hi", privacy="public" + ) + + def test_populate_lists_task(self, *_): + """populate lists cache""" + with patch("bookwyrm.lists_stream.ListsStream.populate_lists") as mock: + lists_stream.populate_lists_task(self.local_user.id) + self.assertTrue(mock.called) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user) + + with patch("bookwyrm.lists_stream.ListsStream.populate_lists") as mock: + lists_stream.populate_lists_task(self.local_user.id) + self.assertTrue(mock.called) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user) + + def test_remove_list_task(self, *_): + """remove a list from all streams""" + with patch( + "bookwyrm.lists_stream.ListsStream.remove_object_from_related_stores" + ) as mock: + lists_stream.remove_list_task(self.list.id) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.list.id) + + def test_add_list_task(self, *_): + """add a list to all streams""" + with patch("bookwyrm.lists_stream.ListsStream.add_list") as mock: + lists_stream.add_list_task(self.list.id) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.list) + + def test_remove_user_lists_task(self, *_): + """remove all lists by a user from another users' feeds""" + with patch("bookwyrm.lists_stream.ListsStream.remove_user_lists") as mock: + lists_stream.remove_user_lists_task( + self.local_user.id, self.another_user.id + ) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user) + self.assertEqual(args[1], self.another_user) + + with patch("bookwyrm.lists_stream.ListsStream.remove_user_lists") as mock: + lists_stream.remove_user_lists_task( + self.local_user.id, self.another_user.id + ) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user) + self.assertEqual(args[1], self.another_user) + + def test_add_user_lists_task(self, *_): + """add a user's lists to another users feeds""" + with patch("bookwyrm.lists_stream.ListsStream.add_user_lists") as mock: + lists_stream.add_user_lists_task(self.local_user.id, self.another_user.id) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user) + self.assertEqual(args[1], self.another_user) + + with patch("bookwyrm.lists_stream.ListsStream.add_user_lists") as mock: + lists_stream.add_user_lists_task(self.local_user.id, self.another_user.id) + self.assertEqual(mock.call_count, 1) + args = mock.call_args[0] + self.assertEqual(args[0], self.local_user) + self.assertEqual(args[1], self.another_user) diff --git a/bookwyrm/tests/management/test_populate_lists_streams.py b/bookwyrm/tests/management/test_populate_lists_streams.py new file mode 100644 index 00000000..2cce7b7a --- /dev/null +++ b/bookwyrm/tests/management/test_populate_lists_streams.py @@ -0,0 +1,54 @@ +""" test populating user streams """ +from unittest.mock import patch +from django.test import TestCase + +from bookwyrm import models +from bookwyrm.management.commands.populate_lists_streams import populate_lists_streams + + +@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") +@patch("bookwyrm.activitystreams.add_status_task.delay") +@patch("bookwyrm.activitystreams.populate_stream_task.delay") +class Activitystreams(TestCase): + """using redis to build activity streams""" + + def setUp(self): + """we need some stuff""" + with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( + "bookwyrm.activitystreams.populate_stream_task.delay" + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): + self.local_user = models.User.objects.create_user( + "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" + ) + self.another_user = models.User.objects.create_user( + "nutria", + "nutria@nutria.nutria", + "password", + local=True, + localname="nutria", + ) + models.User.objects.create_user( + "gerbil", + "gerbil@nutria.nutria", + "password", + local=True, + localname="gerbil", + is_active=False, + ) + with patch("bookwyrm.models.user.set_remote_server.delay"): + self.remote_user = models.User.objects.create_user( + "rat", + "rat@rat.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) + self.book = models.Edition.objects.create(title="test book") + + def test_populate_streams(self, *_): + """make sure the function on the redis manager gets called""" + with patch("bookwyrm.lists_stream.populate_lists_task.delay") as list_mock: + populate_lists_streams() + self.assertEqual(list_mock.call_count, 2) # 2 users diff --git a/bookwyrm/tests/management/test_populate_streams.py b/bookwyrm/tests/management/test_populate_streams.py index 5be1774d..c20a21ac 100644 --- a/bookwyrm/tests/management/test_populate_streams.py +++ b/bookwyrm/tests/management/test_populate_streams.py @@ -14,7 +14,7 @@ class Activitystreams(TestCase): """we need some stuff""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) @@ -25,6 +25,14 @@ class Activitystreams(TestCase): local=True, localname="nutria", ) + models.User.objects.create_user( + "gerbil", + "gerbil@gerbil.gerbil", + "password", + local=True, + localname="gerbil", + is_active=False, + ) with patch("bookwyrm.models.user.set_remote_server.delay"): self.remote_user = models.User.objects.create_user( "rat", @@ -44,6 +52,11 @@ class Activitystreams(TestCase): user=self.local_user, content="hi", book=self.book ) - with patch("bookwyrm.activitystreams.populate_stream_task.delay") as redis_mock: + with patch( + "bookwyrm.activitystreams.populate_stream_task.delay" + ) as redis_mock, patch( + "bookwyrm.lists_stream.populate_lists_task.delay" + ) as list_mock: populate_streams() self.assertEqual(redis_mock.call_count, 6) # 2 users x 3 streams + self.assertEqual(list_mock.call_count, 2) # 2 users diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py index 91a1fe7c..f1279ddf 100644 --- a/bookwyrm/tests/models/test_activitypub_mixin.py +++ b/bookwyrm/tests/models/test_activitypub_mixin.py @@ -29,7 +29,7 @@ class ActivitypubMixins(TestCase): """shared data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse" ) @@ -332,7 +332,7 @@ class ActivitypubMixins(TestCase): self.assertEqual(activity["id"], "https://example.com/status/1/activity") self.assertEqual(activity["actor"], self.local_user.remote_id) self.assertEqual(activity["type"], "Delete") - self.assertEqual(activity["to"], ["%s/followers" % self.local_user.remote_id]) + self.assertEqual(activity["to"], [f"{self.local_user.remote_id}/followers"]) self.assertEqual( activity["cc"], ["https://www.w3.org/ns/activitystreams#Public"] ) @@ -374,7 +374,7 @@ class ActivitypubMixins(TestCase): for number in range(0, 2 * PAGE_LENGTH): models.Status.objects.create( user=self.local_user, - content="test status {:d}".format(number), + content=f"test status {number}", ) page_1 = to_ordered_collection_page( models.Status.objects.all(), "http://fish.com/", page=1 @@ -400,7 +400,7 @@ class ActivitypubMixins(TestCase): for number in range(0, 2 * PAGE_LENGTH): models.Status.objects.create( user=self.local_user, - content="test status {:d}".format(number), + content=f"test status {number}", ) MockSelf = namedtuple("Self", ("remote_id")) diff --git a/bookwyrm/tests/models/test_base_model.py b/bookwyrm/tests/models/test_base_model.py index 7c7b48de..ae6d1207 100644 --- a/bookwyrm/tests/models/test_base_model.py +++ b/bookwyrm/tests/models/test_base_model.py @@ -16,7 +16,7 @@ class BaseModel(TestCase): """shared data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/models/test_fields.py b/bookwyrm/tests/models/test_fields.py index 940b8e7d..935a6263 100644 --- a/bookwyrm/tests/models/test_fields.py +++ b/bookwyrm/tests/models/test_fields.py @@ -27,6 +27,7 @@ from bookwyrm.settings import DOMAIN # pylint: disable=too-many-public-methods @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") class ModelFields(TestCase): """overwrites standard model feilds to work with activitypub""" diff --git a/bookwyrm/tests/models/test_group.py b/bookwyrm/tests/models/test_group.py index 25bbaf42..8739f7fe 100644 --- a/bookwyrm/tests/models/test_group.py +++ b/bookwyrm/tests/models/test_group.py @@ -14,21 +14,15 @@ class Group(TestCase): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.owner_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" ) - with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( - "bookwyrm.activitystreams.populate_stream_task.delay" - ): self.rat = models.User.objects.create_user( "rat", "rat@rat.rat", "ratword", local=True, localname="rat" ) - with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( - "bookwyrm.activitystreams.populate_stream_task.delay" - ): self.badger = models.User.objects.create_user( "badger", "badger@badger.badger", @@ -37,9 +31,6 @@ class Group(TestCase): localname="badger", ) - with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( - "bookwyrm.activitystreams.populate_stream_task.delay" - ): self.capybara = models.User.objects.create_user( "capybara", "capybara@capybara.capybara", diff --git a/bookwyrm/tests/models/test_import_model.py b/bookwyrm/tests/models/test_import_model.py index e67a0345..7cecfe41 100644 --- a/bookwyrm/tests/models/test_import_model.py +++ b/bookwyrm/tests/models/test_import_model.py @@ -20,7 +20,7 @@ class ImportJob(TestCase): """data is from a goodreads export of The Raven Tower""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True ) diff --git a/bookwyrm/tests/models/test_list.py b/bookwyrm/tests/models/test_list.py index 824de835..e4ecfe89 100644 --- a/bookwyrm/tests/models/test_list.py +++ b/bookwyrm/tests/models/test_list.py @@ -1,7 +1,7 @@ """ testing models """ +from uuid import UUID from unittest.mock import patch from django.test import TestCase -from uuid import UUID from bookwyrm import models, settings @@ -14,7 +14,7 @@ class List(TestCase): """look, a list""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" ) @@ -27,7 +27,7 @@ class List(TestCase): book_list = models.List.objects.create( name="Test List", user=self.local_user ) - expected_id = "https://%s/list/%d" % (settings.DOMAIN, book_list.id) + expected_id = f"https://{settings.DOMAIN}/list/{book_list.id}" self.assertEqual(book_list.get_remote_id(), expected_id) def test_to_activity(self, _): diff --git a/bookwyrm/tests/models/test_readthrough_model.py b/bookwyrm/tests/models/test_readthrough_model.py index 5d8450a1..7e3963cf 100644 --- a/bookwyrm/tests/models/test_readthrough_model.py +++ b/bookwyrm/tests/models/test_readthrough_model.py @@ -15,7 +15,7 @@ class ReadThrough(TestCase): """look, a shelf""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/models/test_relationship_models.py b/bookwyrm/tests/models/test_relationship_models.py index 2b388398..a5b4dbff 100644 --- a/bookwyrm/tests/models/test_relationship_models.py +++ b/bookwyrm/tests/models/test_relationship_models.py @@ -1,12 +1,16 @@ """ testing models """ import json from unittest.mock import patch +from django.db import IntegrityError from django.test import TestCase from bookwyrm import models @patch("bookwyrm.activitystreams.add_user_statuses_task.delay") +@patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") +@patch("bookwyrm.lists_stream.add_user_lists_task.delay") +@patch("bookwyrm.lists_stream.remove_user_lists_task.delay") class Relationship(TestCase): """following, blocking, stuff like that""" @@ -24,14 +28,39 @@ class Relationship(TestCase): ) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.com", "mouseword", local=True, localname="mouse" ) self.local_user.remote_id = "http://local.com/user/mouse" self.local_user.save(broadcast=False, update_fields=["remote_id"]) - def test_user_follows_from_request(self, _): + def test_user_follows(self, *_): + """basic functionality of user follows""" + relationship = models.UserFollows.objects.create( + user_subject=self.local_user, user_object=self.remote_user + ) + self.assertEqual(relationship.status, "follows") + activity = relationship.to_activity() + self.assertEqual(activity.type, "Follow") + self.assertEqual( + relationship.remote_id, + f"http://local.com/user/mouse#follows/{relationship.id}", + ) + + def test_user_follows_blocks(self, *_): + """can't follow if you're blocked""" + with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + models.UserBlocks.objects.create( + user_subject=self.local_user, user_object=self.remote_user + ) + + with self.assertRaises(IntegrityError): + models.UserFollows.objects.create( + user_subject=self.local_user, user_object=self.remote_user + ) + + def test_user_follows_from_request(self, *_): """convert a follow request into a follow""" with patch( "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" @@ -42,19 +71,19 @@ class Relationship(TestCase): activity = json.loads(mock.call_args[1]["args"][1]) self.assertEqual(activity["type"], "Follow") self.assertEqual( - request.remote_id, "http://local.com/user/mouse#follows/%d" % request.id + request.remote_id, f"http://local.com/user/mouse#follows/{request.id}" ) self.assertEqual(request.status, "follow_request") rel = models.UserFollows.from_request(request) self.assertEqual( - rel.remote_id, "http://local.com/user/mouse#follows/%d" % request.id + rel.remote_id, f"http://local.com/user/mouse#follows/{request.id}" ) self.assertEqual(rel.status, "follows") self.assertEqual(rel.user_subject, self.local_user) self.assertEqual(rel.user_object, self.remote_user) - def test_user_follows_from_request_custom_remote_id(self, _): + def test_user_follows_from_request_custom_remote_id(self, *_): """store a specific remote id for a relationship provided by remote""" with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): request = models.UserFollowRequest.objects.create( @@ -72,7 +101,7 @@ class Relationship(TestCase): self.assertEqual(rel.user_object, self.remote_user) @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") - def test_follow_request_activity(self, broadcast_mock, _): + def test_follow_request_activity(self, broadcast_mock, *_): """accept a request and make it a relationship""" models.UserFollowRequest.objects.create( user_subject=self.local_user, @@ -84,7 +113,7 @@ class Relationship(TestCase): self.assertEqual(activity["type"], "Follow") @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") - def test_follow_request_accept(self, broadcast_mock, _): + def test_follow_request_accept(self, broadcast_mock, *_): """accept a request and make it a relationship""" self.local_user.manually_approves_followers = True self.local_user.save( @@ -110,7 +139,7 @@ class Relationship(TestCase): self.assertEqual(rel.user_object, self.local_user) @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") - def test_follow_request_reject(self, broadcast_mock, _): + def test_follow_request_reject(self, broadcast_mock, *_): """accept a request and make it a relationship""" self.local_user.manually_approves_followers = True self.local_user.save( diff --git a/bookwyrm/tests/models/test_shelf_model.py b/bookwyrm/tests/models/test_shelf_model.py index 0683fbef..4f7f3589 100644 --- a/bookwyrm/tests/models/test_shelf_model.py +++ b/bookwyrm/tests/models/test_shelf_model.py @@ -9,6 +9,7 @@ from bookwyrm import models, settings # pylint: disable=unused-argument @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.remove_book_statuses_task.delay") class Shelf(TestCase): @@ -18,7 +19,7 @@ class Shelf(TestCase): """look, a shelf""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" ) @@ -31,7 +32,7 @@ class Shelf(TestCase): shelf = models.Shelf.objects.create( name="Test Shelf", identifier="test-shelf", user=self.local_user ) - expected_id = "https://%s/user/mouse/books/test-shelf" % settings.DOMAIN + expected_id = f"https://{settings.DOMAIN}/user/mouse/books/test-shelf" self.assertEqual(shelf.get_remote_id(), expected_id) def test_to_activity(self, *_): diff --git a/bookwyrm/tests/models/test_site.py b/bookwyrm/tests/models/test_site.py index b7c19c4b..d23f7988 100644 --- a/bookwyrm/tests/models/test_site.py +++ b/bookwyrm/tests/models/test_site.py @@ -16,7 +16,7 @@ class SiteModels(TestCase): """we need basic test data and mocks""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 822d837a..6520094c 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -28,7 +28,7 @@ class Status(TestCase): """useful things for creating a status""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "mouseword", local=True, localname="mouse" ) diff --git a/bookwyrm/tests/models/test_user_model.py b/bookwyrm/tests/models/test_user_model.py index 389928cd..aa62dce3 100644 --- a/bookwyrm/tests/models/test_user_model.py +++ b/bookwyrm/tests/models/test_user_model.py @@ -15,7 +15,7 @@ class User(TestCase): def setUp(self): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse@%s" % DOMAIN, "mouse@mouse.mouse", diff --git a/bookwyrm/tests/templatetags/test_bookwyrm_tags.py b/bookwyrm/tests/templatetags/test_bookwyrm_tags.py index 04f6a5d4..7b8d199d 100644 --- a/bookwyrm/tests/templatetags/test_bookwyrm_tags.py +++ b/bookwyrm/tests/templatetags/test_bookwyrm_tags.py @@ -16,7 +16,7 @@ class BookWyrmTags(TestCase): """create some filler objects""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/templatetags/test_interaction.py b/bookwyrm/tests/templatetags/test_interaction.py index d32548e4..a48b3364 100644 --- a/bookwyrm/tests/templatetags/test_interaction.py +++ b/bookwyrm/tests/templatetags/test_interaction.py @@ -16,7 +16,7 @@ class InteractionTags(TestCase): """create some filler objects""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/templatetags/test_status_display.py b/bookwyrm/tests/templatetags/test_status_display.py index b3eaeab8..50c5571e 100644 --- a/bookwyrm/tests/templatetags/test_status_display.py +++ b/bookwyrm/tests/templatetags/test_status_display.py @@ -17,7 +17,7 @@ class StatusDisplayTags(TestCase): """create some filler objects""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/templatetags/test_utilities.py b/bookwyrm/tests/templatetags/test_utilities.py index f40d24dc..e41cd21a 100644 --- a/bookwyrm/tests/templatetags/test_utilities.py +++ b/bookwyrm/tests/templatetags/test_utilities.py @@ -17,7 +17,7 @@ class UtilitiesTags(TestCase): """create some filler objects""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.mouse", @@ -50,3 +50,10 @@ class UtilitiesTags(TestCase): """uuid functionality""" uuid = utilities.get_uuid("hi") self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid)) + + def test_get_title(self, *_): + """the title of a book""" + self.assertEqual(utilities.get_title(None), "") + self.assertEqual(utilities.get_title(self.book), "Test Book") + book = models.Edition.objects.create(title="Oh", subtitle="oh my") + self.assertEqual(utilities.get_title(book), "Oh: oh my") diff --git a/bookwyrm/tests/test_emailing.py b/bookwyrm/tests/test_emailing.py index 2f24122e..ecfbd944 100644 --- a/bookwyrm/tests/test_emailing.py +++ b/bookwyrm/tests/test_emailing.py @@ -16,7 +16,7 @@ class Emailing(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/test_preview_images.py b/bookwyrm/tests/test_preview_images.py index f95e623c..79ee195d 100644 --- a/bookwyrm/tests/test_preview_images.py +++ b/bookwyrm/tests/test_preview_images.py @@ -32,7 +32,7 @@ class PreviewImages(TestCase): ) with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "possum@local.com", "possum@possum.possum", diff --git a/bookwyrm/tests/test_signing.py b/bookwyrm/tests/test_signing.py index d33687a5..da67a8de 100644 --- a/bookwyrm/tests/test_signing.py +++ b/bookwyrm/tests/test_signing.py @@ -39,19 +39,19 @@ class Signature(TestCase): """create users and test data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.mouse = models.User.objects.create_user( - "mouse@%s" % DOMAIN, + f"mouse@{DOMAIN}", "mouse@example.com", "", local=True, localname="mouse", ) self.rat = models.User.objects.create_user( - "rat@%s" % DOMAIN, "rat@example.com", "", local=True, localname="rat" + f"rat@{DOMAIN}", "rat@example.com", "", local=True, localname="rat" ) self.cat = models.User.objects.create_user( - "cat@%s" % DOMAIN, "cat@example.com", "", local=True, localname="cat" + f"cat@{DOMAIN}", "cat@example.com", "", local=True, localname="cat" ) private_key, public_key = create_key_pair() @@ -75,7 +75,7 @@ class Signature(TestCase): "HTTP_DIGEST": digest, "HTTP_CONTENT_TYPE": "application/activity+json; charset=utf-8", "HTTP_HOST": DOMAIN, - } + }, ) def send_test_request( # pylint: disable=too-many-arguments diff --git a/bookwyrm/tests/test_suggested_users.py b/bookwyrm/tests/test_suggested_users.py index dce5d770..77b82e7e 100644 --- a/bookwyrm/tests/test_suggested_users.py +++ b/bookwyrm/tests/test_suggested_users.py @@ -13,6 +13,7 @@ from bookwyrm.suggested_users import suggested_users, get_annotated_users @patch("bookwyrm.activitystreams.add_status_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.suggested_users.rerank_user_task.delay") @patch("bookwyrm.suggested_users.remove_user_task.delay") @@ -23,7 +24,7 @@ class SuggestedUsers(TestCase): """use a test csv""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" ) @@ -235,12 +236,3 @@ class SuggestedUsers(TestCase): ) user_1_annotated = result.get(id=user_1.id) self.assertEqual(user_1_annotated.mutuals, 3) - - def test_create_user_signal(self, *_): - """build suggestions for new users""" - with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") as mock: - models.User.objects.create_user( - "nutria", "nutria@nu.tria", "password", local=True, localname="nutria" - ) - - self.assertEqual(mock.call_count, 1) diff --git a/bookwyrm/tests/views/admin/test_announcements.py b/bookwyrm/tests/views/admin/test_announcements.py index fadd3d86..3d21e621 100644 --- a/bookwyrm/tests/views/admin/test_announcements.py +++ b/bookwyrm/tests/views/admin/test_announcements.py @@ -16,7 +16,7 @@ class AnnouncementViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/admin/test_dashboard.py b/bookwyrm/tests/views/admin/test_dashboard.py index f0238eef..d05772c2 100644 --- a/bookwyrm/tests/views/admin/test_dashboard.py +++ b/bookwyrm/tests/views/admin/test_dashboard.py @@ -16,7 +16,7 @@ class DashboardViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/admin/test_email_blocks.py b/bookwyrm/tests/views/admin/test_email_blocks.py index 6d676fd2..4fe9412e 100644 --- a/bookwyrm/tests/views/admin/test_email_blocks.py +++ b/bookwyrm/tests/views/admin/test_email_blocks.py @@ -17,7 +17,7 @@ class EmailBlocklistViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/admin/test_federation.py b/bookwyrm/tests/views/admin/test_federation.py index fbbd540e..deed5bd3 100644 --- a/bookwyrm/tests/views/admin/test_federation.py +++ b/bookwyrm/tests/views/admin/test_federation.py @@ -19,7 +19,7 @@ class FederationViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/admin/test_ip_blocklist.py b/bookwyrm/tests/views/admin/test_ip_blocklist.py index 25694d07..e23abd8b 100644 --- a/bookwyrm/tests/views/admin/test_ip_blocklist.py +++ b/bookwyrm/tests/views/admin/test_ip_blocklist.py @@ -16,7 +16,7 @@ class IPBlocklistViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/admin/test_reports.py b/bookwyrm/tests/views/admin/test_reports.py index 8b9fe9f5..137d17cb 100644 --- a/bookwyrm/tests/views/admin/test_reports.py +++ b/bookwyrm/tests/views/admin/test_reports.py @@ -18,7 +18,7 @@ class ReportViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/admin/test_user_admin.py b/bookwyrm/tests/views/admin/test_user_admin.py index 486fe45e..4cb3702d 100644 --- a/bookwyrm/tests/views/admin/test_user_admin.py +++ b/bookwyrm/tests/views/admin/test_user_admin.py @@ -18,7 +18,7 @@ class UserAdminViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/books/test_book.py b/bookwyrm/tests/views/books/test_book.py index 90f686d5..e536ef73 100644 --- a/bookwyrm/tests/views/books/test_book.py +++ b/bookwyrm/tests/views/books/test_book.py @@ -28,7 +28,7 @@ class BookViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/books/test_edit_book.py b/bookwyrm/tests/views/books/test_edit_book.py index cd957858..cfb0d766 100644 --- a/bookwyrm/tests/views/books/test_edit_book.py +++ b/bookwyrm/tests/views/books/test_edit_book.py @@ -21,7 +21,7 @@ class EditBookViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/books/test_editions.py b/bookwyrm/tests/views/books/test_editions.py index 17f15654..70a95051 100644 --- a/bookwyrm/tests/views/books/test_editions.py +++ b/bookwyrm/tests/views/books/test_editions.py @@ -18,7 +18,7 @@ class BookViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/imports/test_import.py b/bookwyrm/tests/views/imports/test_import.py index c1c5472f..3bbfb43f 100644 --- a/bookwyrm/tests/views/imports/test_import.py +++ b/bookwyrm/tests/views/imports/test_import.py @@ -19,7 +19,7 @@ class ImportViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/imports/test_import_review.py b/bookwyrm/tests/views/imports/test_import_review.py index 2ab48468..9ed4532e 100644 --- a/bookwyrm/tests/views/imports/test_import_review.py +++ b/bookwyrm/tests/views/imports/test_import_review.py @@ -16,7 +16,7 @@ class ImportManualReviewViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/imports/test_import_troubleshoot.py b/bookwyrm/tests/views/imports/test_import_troubleshoot.py index 5359cc1e..b39f6d9e 100644 --- a/bookwyrm/tests/views/imports/test_import_troubleshoot.py +++ b/bookwyrm/tests/views/imports/test_import_troubleshoot.py @@ -16,7 +16,7 @@ class ImportTroubleshootViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/inbox/test_inbox.py b/bookwyrm/tests/views/inbox/test_inbox.py index 47e6a86e..e328b1ba 100644 --- a/bookwyrm/tests/views/inbox/test_inbox.py +++ b/bookwyrm/tests/views/inbox/test_inbox.py @@ -22,7 +22,7 @@ class Inbox(TestCase): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/inbox/test_inbox_add.py b/bookwyrm/tests/views/inbox/test_inbox_add.py index 33e6c55b..a9a80982 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_add.py +++ b/bookwyrm/tests/views/inbox/test_inbox_add.py @@ -15,7 +15,7 @@ class InboxAdd(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/inbox/test_inbox_announce.py b/bookwyrm/tests/views/inbox/test_inbox_announce.py index a291552d..01580c92 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_announce.py +++ b/bookwyrm/tests/views/inbox/test_inbox_announce.py @@ -15,7 +15,7 @@ class InboxActivities(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/inbox/test_inbox_block.py b/bookwyrm/tests/views/inbox/test_inbox_block.py index f6898fc6..eb73af09 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_block.py +++ b/bookwyrm/tests/views/inbox/test_inbox_block.py @@ -14,7 +14,7 @@ class InboxBlock(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", @@ -57,7 +57,7 @@ class InboxBlock(TestCase): with patch( "bookwyrm.activitystreams.remove_user_statuses_task.delay" - ) as redis_mock: + ) as redis_mock, patch("bookwyrm.lists_stream.remove_user_lists_task.delay"): views.inbox.activity_task(activity) self.assertTrue(redis_mock.called) views.inbox.activity_task(activity) @@ -70,7 +70,9 @@ class InboxBlock(TestCase): self.assertFalse(models.UserFollowRequest.objects.exists()) @patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") - def test_handle_unblock(self, _): + @patch("bookwyrm.lists_stream.add_user_lists_task.delay") + @patch("bookwyrm.lists_stream.remove_user_lists_task.delay") + def test_handle_unblock(self, *_): """unblock a user""" self.remote_user.blocks.add(self.local_user) diff --git a/bookwyrm/tests/views/inbox/test_inbox_create.py b/bookwyrm/tests/views/inbox/test_inbox_create.py index 53b17d68..4ee366cf 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_create.py +++ b/bookwyrm/tests/views/inbox/test_inbox_create.py @@ -19,7 +19,7 @@ class InboxCreate(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/inbox/test_inbox_delete.py b/bookwyrm/tests/views/inbox/test_inbox_delete.py index dd603352..b4863aad 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_delete.py +++ b/bookwyrm/tests/views/inbox/test_inbox_delete.py @@ -15,7 +15,7 @@ class InboxActivities(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", @@ -51,7 +51,7 @@ class InboxActivities(TestCase): "type": "Delete", "to": ["https://www.w3.org/ns/activitystreams#Public"], "cc": ["https://example.com/user/mouse/followers"], - "id": "%s/activity" % self.status.remote_id, + "id": f"{self.status.remote_id}/activity", "actor": self.remote_user.remote_id, "object": {"id": self.status.remote_id, "type": "Tombstone"}, } @@ -80,7 +80,7 @@ class InboxActivities(TestCase): "type": "Delete", "to": ["https://www.w3.org/ns/activitystreams#Public"], "cc": ["https://example.com/user/mouse/followers"], - "id": "%s/activity" % self.status.remote_id, + "id": f"{self.status.remote_id}/activity", "actor": self.remote_user.remote_id, "object": {"id": self.status.remote_id, "type": "Tombstone"}, } @@ -152,5 +152,7 @@ class InboxActivities(TestCase): "cc": [], }, } - views.inbox.activity_task(activity) + with patch("bookwyrm.lists_stream.remove_list_task.delay") as mock: + views.inbox.activity_task(activity) + self.assertTrue(mock.called) self.assertFalse(models.List.objects.exists()) diff --git a/bookwyrm/tests/views/inbox/test_inbox_follow.py b/bookwyrm/tests/views/inbox/test_inbox_follow.py index 71f101ca..13e46ff8 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_follow.py +++ b/bookwyrm/tests/views/inbox/test_inbox_follow.py @@ -15,7 +15,7 @@ class InboxRelationships(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", @@ -188,7 +188,8 @@ class InboxRelationships(TestCase): self.assertIsNone(self.local_user.followers.first()) @patch("bookwyrm.activitystreams.add_user_statuses_task.delay") - def test_follow_accept(self, _): + @patch("bookwyrm.lists_stream.add_user_lists_task.delay") + def test_follow_accept(self, *_): """a remote user approved a follow request from local""" with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): rel = models.UserFollowRequest.objects.create( diff --git a/bookwyrm/tests/views/inbox/test_inbox_like.py b/bookwyrm/tests/views/inbox/test_inbox_like.py index 2f1b6629..ea4d4a65 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_like.py +++ b/bookwyrm/tests/views/inbox/test_inbox_like.py @@ -14,7 +14,7 @@ class InboxActivities(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/inbox/test_inbox_remove.py b/bookwyrm/tests/views/inbox/test_inbox_remove.py index 55cc8120..53288e0d 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_remove.py +++ b/bookwyrm/tests/views/inbox/test_inbox_remove.py @@ -14,7 +14,7 @@ class InboxRemove(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/inbox/test_inbox_update.py b/bookwyrm/tests/views/inbox/test_inbox_update.py index 248c1ad2..052b47c4 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_update.py +++ b/bookwyrm/tests/views/inbox/test_inbox_update.py @@ -16,7 +16,7 @@ class InboxUpdate(TestCase): """basic user and book data""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@example.com", "mouse@mouse.com", @@ -78,6 +78,7 @@ class InboxUpdate(TestCase): @patch("bookwyrm.suggested_users.rerank_user_task.delay") @patch("bookwyrm.activitystreams.add_user_statuses_task.delay") + @patch("bookwyrm.lists_stream.add_user_lists_task.delay") def test_update_user(self, *_): """update an existing user""" models.UserFollows.objects.create( diff --git a/bookwyrm/tests/views/landing/test_invite.py b/bookwyrm/tests/views/landing/test_invite.py index a93821a9..a5877187 100644 --- a/bookwyrm/tests/views/landing/test_invite.py +++ b/bookwyrm/tests/views/landing/test_invite.py @@ -19,7 +19,7 @@ class InviteViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/landing/test_landing.py b/bookwyrm/tests/views/landing/test_landing.py index 82991917..a82d093d 100644 --- a/bookwyrm/tests/views/landing/test_landing.py +++ b/bookwyrm/tests/views/landing/test_landing.py @@ -18,7 +18,7 @@ class LandingViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", @@ -49,7 +49,27 @@ class LandingViews(TestCase): def test_about_page(self): """there are so many views, this just makes sure it LOADS""" - view = views.About.as_view() + view = views.about + request = self.factory.get("") + request.user = self.local_user + result = view(request) + self.assertIsInstance(result, TemplateResponse) + validate_html(result.render()) + self.assertEqual(result.status_code, 200) + + def test_conduct_page(self): + """there are so many views, this just makes sure it LOADS""" + view = views.conduct + request = self.factory.get("") + request.user = self.local_user + result = view(request) + self.assertIsInstance(result, TemplateResponse) + validate_html(result.render()) + self.assertEqual(result.status_code, 200) + + def test_privacy_page(self): + """there are so many views, this just makes sure it LOADS""" + view = views.privacy request = self.factory.get("") request.user = self.local_user result = view(request) diff --git a/bookwyrm/tests/views/landing/test_login.py b/bookwyrm/tests/views/landing/test_login.py index 0f86fb79..24987c8e 100644 --- a/bookwyrm/tests/views/landing/test_login.py +++ b/bookwyrm/tests/views/landing/test_login.py @@ -21,7 +21,7 @@ class LoginViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@your.domain.here", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/landing/test_password.py b/bookwyrm/tests/views/landing/test_password.py index f01565ef..b1f7e59f 100644 --- a/bookwyrm/tests/views/landing/test_password.py +++ b/bookwyrm/tests/views/landing/test_password.py @@ -21,7 +21,7 @@ class PasswordViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/landing/test_register.py b/bookwyrm/tests/views/landing/test_register.py index 99f38da2..deb16552 100644 --- a/bookwyrm/tests/views/landing/test_register.py +++ b/bookwyrm/tests/views/landing/test_register.py @@ -16,6 +16,7 @@ from bookwyrm.tests.validate_html import validate_html # pylint: disable=too-many-public-methods @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") class RegisterViews(TestCase): """login and password management""" @@ -24,7 +25,7 @@ class RegisterViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@your.domain.here", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/preferences/test_block.py b/bookwyrm/tests/views/preferences/test_block.py index 975142a1..46de8f48 100644 --- a/bookwyrm/tests/views/preferences/test_block.py +++ b/bookwyrm/tests/views/preferences/test_block.py @@ -18,7 +18,7 @@ class BlockViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", @@ -61,7 +61,9 @@ class BlockViews(TestCase): request = self.factory.post("") request.user = self.local_user - with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"): + with patch("bookwyrm.activitystreams.remove_user_statuses_task.delay"), patch( + "bookwyrm.lists_stream.remove_user_lists_task.delay" + ): view(request, self.remote_user.id) block = models.UserBlocks.objects.get() self.assertEqual(block.user_subject, self.local_user) @@ -76,7 +78,9 @@ class BlockViews(TestCase): request = self.factory.post("") request.user = self.local_user - with patch("bookwyrm.activitystreams.add_user_statuses_task.delay"): + with patch("bookwyrm.activitystreams.add_user_statuses_task.delay"), patch( + "bookwyrm.lists_stream.add_user_lists_task.delay" + ): views.unblock(request, self.remote_user.id) self.assertFalse(models.UserBlocks.objects.exists()) diff --git a/bookwyrm/tests/views/preferences/test_change_password.py b/bookwyrm/tests/views/preferences/test_change_password.py index d13c2af5..61837c4e 100644 --- a/bookwyrm/tests/views/preferences/test_change_password.py +++ b/bookwyrm/tests/views/preferences/test_change_password.py @@ -17,7 +17,7 @@ class ChangePasswordViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/preferences/test_delete_user.py b/bookwyrm/tests/views/preferences/test_delete_user.py index b6d87ccd..95bfa4df 100644 --- a/bookwyrm/tests/views/preferences/test_delete_user.py +++ b/bookwyrm/tests/views/preferences/test_delete_user.py @@ -20,7 +20,7 @@ class DeleteUserViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/preferences/test_edit_user.py b/bookwyrm/tests/views/preferences/test_edit_user.py index 7a845fbe..11d33340 100644 --- a/bookwyrm/tests/views/preferences/test_edit_user.py +++ b/bookwyrm/tests/views/preferences/test_edit_user.py @@ -23,7 +23,7 @@ class EditUserViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/shelf/test_shelf.py b/bookwyrm/tests/views/shelf/test_shelf.py index b5f36df2..4a74ffb6 100644 --- a/bookwyrm/tests/views/shelf/test_shelf.py +++ b/bookwyrm/tests/views/shelf/test_shelf.py @@ -14,6 +14,7 @@ from bookwyrm.tests.validate_html import validate_html @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.remove_book_statuses_task.delay") class ShelfViews(TestCase): @@ -24,7 +25,7 @@ class ShelfViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/shelf/test_shelf_actions.py b/bookwyrm/tests/views/shelf/test_shelf_actions.py index 1a7d56fd..93ff0a38 100644 --- a/bookwyrm/tests/views/shelf/test_shelf_actions.py +++ b/bookwyrm/tests/views/shelf/test_shelf_actions.py @@ -12,6 +12,7 @@ from bookwyrm import forms, models, views @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.activitystreams.add_book_statuses_task.delay") @patch("bookwyrm.activitystreams.remove_book_statuses_task.delay") class ShelfActionViews(TestCase): @@ -22,7 +23,7 @@ class ShelfActionViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", @@ -178,7 +179,7 @@ class ShelfActionViews(TestCase): """delete a brand new custom shelf""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): rat = models.User.objects.create_user( "rat@local.com", "rat@mouse.mouse", diff --git a/bookwyrm/tests/views/test_annual_summary.py b/bookwyrm/tests/views/test_annual_summary.py index 32439eab..2d597be7 100644 --- a/bookwyrm/tests/views/test_annual_summary.py +++ b/bookwyrm/tests/views/test_annual_summary.py @@ -26,7 +26,7 @@ class AnnualSummary(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_author.py b/bookwyrm/tests/views/test_author.py index 03166932..ad5c069d 100644 --- a/bookwyrm/tests/views/test_author.py +++ b/bookwyrm/tests/views/test_author.py @@ -21,7 +21,7 @@ class AuthorViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_directory.py b/bookwyrm/tests/views/test_directory.py index 4fe2aa05..bceb0e7a 100644 --- a/bookwyrm/tests/views/test_directory.py +++ b/bookwyrm/tests/views/test_directory.py @@ -18,7 +18,7 @@ class DirectoryViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", @@ -34,6 +34,7 @@ class DirectoryViews(TestCase): @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") + @patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.suggested_users.rerank_user_task.delay") def test_directory_page(self, *_): """there are so many views, this just makes sure it LOADS""" diff --git a/bookwyrm/tests/views/test_discover.py b/bookwyrm/tests/views/test_discover.py index dcfc2bf2..b0989da8 100644 --- a/bookwyrm/tests/views/test_discover.py +++ b/bookwyrm/tests/views/test_discover.py @@ -16,7 +16,7 @@ class DiscoverViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/test_feed.py b/bookwyrm/tests/views/test_feed.py index 475bebeb..99b2a396 100644 --- a/bookwyrm/tests/views/test_feed.py +++ b/bookwyrm/tests/views/test_feed.py @@ -10,8 +10,7 @@ from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory -from bookwyrm import models -from bookwyrm import views +from bookwyrm import forms, models, views from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.tests.validate_html import validate_html @@ -20,6 +19,7 @@ from bookwyrm.tests.validate_html import validate_html @patch("bookwyrm.activitystreams.add_status_task.delay") @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.suggested_users.remove_user_task.delay") class FeedViews(TestCase): """activity feed, statuses, dms""" @@ -29,7 +29,7 @@ class FeedViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", @@ -62,6 +62,25 @@ class FeedViews(TestCase): validate_html(result.render()) self.assertEqual(result.status_code, 200) + @patch("bookwyrm.suggested_users.SuggestedUsers.get_suggestions") + def test_save_feed_settings(self, *_): + """update display preferences""" + self.assertEqual( + self.local_user.feed_status_types, + ["review", "comment", "quotation", "everything"], + ) + view = views.Feed.as_view() + form = forms.FeedStatusTypesForm(instance=self.local_user) + form.data["feed_status_types"] = "review" + request = self.factory.post("", form.data) + request.user = self.local_user + + result = view(request, "home") + + self.assertEqual(result.status_code, 200) + self.local_user.refresh_from_db() + self.assertEqual(self.local_user.feed_status_types, ["review"]) + def test_status_page(self, *_): """there are so many views, this just makes sure it LOADS""" view = views.Status.as_view() diff --git a/bookwyrm/tests/views/test_follow.py b/bookwyrm/tests/views/test_follow.py index 046fe3d9..d18e24f8 100644 --- a/bookwyrm/tests/views/test_follow.py +++ b/bookwyrm/tests/views/test_follow.py @@ -13,6 +13,7 @@ from bookwyrm.tests.validate_html import validate_html @patch("bookwyrm.activitystreams.add_user_statuses_task.delay") +@patch("bookwyrm.lists_stream.add_user_lists_task.delay") class FollowViews(TestCase): """follows""" @@ -22,7 +23,7 @@ class FollowViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", @@ -56,7 +57,7 @@ class FollowViews(TestCase): parent_work=self.work, ) - def test_handle_follow_remote(self, _): + def test_handle_follow_remote(self, *_): """send a follow request""" request = self.factory.post("", {"user": self.remote_user.username}) request.user = self.local_user @@ -71,11 +72,11 @@ class FollowViews(TestCase): self.assertEqual(rel.user_object, self.remote_user) self.assertEqual(rel.status, "follow_request") - def test_handle_follow_local_manually_approves(self, _): + def test_handle_follow_local_manually_approves(self, *_): """send a follow request""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): rat = models.User.objects.create_user( "rat@local.com", "rat@rat.com", @@ -97,11 +98,11 @@ class FollowViews(TestCase): self.assertEqual(rel.user_object, rat) self.assertEqual(rel.status, "follow_request") - def test_handle_follow_local(self, _): + def test_handle_follow_local(self, *_): """send a follow request""" with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): rat = models.User.objects.create_user( "rat@local.com", "rat@rat.com", @@ -124,6 +125,7 @@ class FollowViews(TestCase): self.assertEqual(rel.status, "follows") @patch("bookwyrm.activitystreams.remove_user_statuses_task.delay") + @patch("bookwyrm.lists_stream.remove_user_lists_task.delay") def test_handle_unfollow(self, *_): """send an unfollow""" request = self.factory.post("", {"user": self.remote_user.username}) @@ -140,7 +142,7 @@ class FollowViews(TestCase): self.assertEqual(self.remote_user.followers.count(), 0) - def test_handle_accept(self, _): + def test_handle_accept(self, *_): """accept a follow request""" self.local_user.manually_approves_followers = True self.local_user.save( @@ -159,7 +161,7 @@ class FollowViews(TestCase): # follow relationship should exist self.assertEqual(self.local_user.followers.first(), self.remote_user) - def test_handle_reject(self, _): + def test_handle_reject(self, *_): """reject a follow request""" self.local_user.manually_approves_followers = True self.local_user.save( @@ -178,7 +180,7 @@ class FollowViews(TestCase): # follow relationship should not exist self.assertEqual(models.UserFollows.objects.filter(id=rel.id).count(), 0) - def test_ostatus_follow_request(self, _): + def test_ostatus_follow_request(self, *_): """check ostatus subscribe template loads""" request = self.factory.get( "", {"acct": "https%3A%2F%2Fexample.com%2Fusers%2Frat"} @@ -189,7 +191,7 @@ class FollowViews(TestCase): validate_html(result.render()) self.assertEqual(result.status_code, 200) - def test_remote_follow_page(self, _): + def test_remote_follow_page(self, *_): """check remote follow page loads""" request = self.factory.get("", {"acct": "mouse@local.com"}) request.user = self.remote_user @@ -198,7 +200,7 @@ class FollowViews(TestCase): validate_html(result.render()) self.assertEqual(result.status_code, 200) - def test_ostatus_follow_success(self, _): + def test_ostatus_follow_success(self, *_): """check remote follow success page loads""" request = self.factory.get("") request.user = self.remote_user @@ -208,7 +210,7 @@ class FollowViews(TestCase): validate_html(result.render()) self.assertEqual(result.status_code, 200) - def test_remote_follow(self, _): + def test_remote_follow(self, *_): """check follow from remote page loads""" request = self.factory.post("", {"user": self.remote_user.id}) request.user = self.remote_user diff --git a/bookwyrm/tests/views/test_get_started.py b/bookwyrm/tests/views/test_get_started.py index 84ad966d..28b6a4d3 100644 --- a/bookwyrm/tests/views/test_get_started.py +++ b/bookwyrm/tests/views/test_get_started.py @@ -17,7 +17,7 @@ class GetStartedViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/test_goal.py b/bookwyrm/tests/views/test_goal.py index 73207240..0faeef11 100644 --- a/bookwyrm/tests/views/test_goal.py +++ b/bookwyrm/tests/views/test_goal.py @@ -20,7 +20,7 @@ class GoalViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_group.py b/bookwyrm/tests/views/test_group.py index f0395490..7c82b475 100644 --- a/bookwyrm/tests/views/test_group.py +++ b/bookwyrm/tests/views/test_group.py @@ -20,7 +20,7 @@ class GroupViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/test_helpers.py b/bookwyrm/tests/views/test_helpers.py index 1aae830f..8fe04f51 100644 --- a/bookwyrm/tests/views/test_helpers.py +++ b/bookwyrm/tests/views/test_helpers.py @@ -23,7 +23,7 @@ class ViewsHelpers(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): with patch("bookwyrm.suggested_users.rerank_user_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", diff --git a/bookwyrm/tests/views/test_interaction.py b/bookwyrm/tests/views/test_interaction.py index aa402952..1d729f9a 100644 --- a/bookwyrm/tests/views/test_interaction.py +++ b/bookwyrm/tests/views/test_interaction.py @@ -17,7 +17,7 @@ class InteractionViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_isbn.py b/bookwyrm/tests/views/test_isbn.py index bdf72f75..7c18b4ab 100644 --- a/bookwyrm/tests/views/test_isbn.py +++ b/bookwyrm/tests/views/test_isbn.py @@ -18,7 +18,7 @@ class IsbnViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", @@ -49,3 +49,13 @@ class IsbnViews(TestCase): self.assertEqual(len(data), 1) self.assertEqual(data[0]["title"], "Test Book") self.assertEqual(data[0]["key"], f"https://{DOMAIN}/book/{self.book.id}") + + def test_isbn_html_response(self): + """searches local data only and returns book data in json format""" + view = views.Isbn.as_view() + request = self.factory.get("") + with patch("bookwyrm.views.isbn.is_api_request") as is_api: + is_api.return_value = False + response = view(request, isbn="1234567890123") + self.assertEqual(response.status_code, 200) + response.render() diff --git a/bookwyrm/tests/views/test_list.py b/bookwyrm/tests/views/test_list.py index dc764326..d36f88e5 100644 --- a/bookwyrm/tests/views/test_list.py +++ b/bookwyrm/tests/views/test_list.py @@ -21,7 +21,7 @@ class ListViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", @@ -72,10 +72,13 @@ class ListViews(TestCase): models.SiteSettings.objects.create() - def test_lists_page(self): + @patch("bookwyrm.lists_stream.ListsStream.get_list_stream") + def test_lists_page(self, _): """there are so many views, this just makes sure it LOADS""" view = views.Lists.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): + with patch( + "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" + ), patch("bookwyrm.lists_stream.add_list_task.delay"): models.List.objects.create(name="Public list", user=self.local_user) models.List.objects.create( name="Private list", privacy="direct", user=self.local_user @@ -346,16 +349,16 @@ class ListViews(TestCase): def test_curate_page(self): """there are so many views, this just makes sure it LOADS""" view = views.Curate.as_view() + request = self.factory.get("") + request.user = self.local_user with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): models.ListItem.objects.create( - user=self.local_user, book_list=self.list, + user=self.local_user, book=self.book, approved=False, order=1, ) - request = self.factory.get("") - request.user = self.local_user result = view(request, self.list.id) self.assertIsInstance(result, TemplateResponse) diff --git a/bookwyrm/tests/views/test_list_actions.py b/bookwyrm/tests/views/test_list_actions.py index 1d9f46b3..7f57fae3 100644 --- a/bookwyrm/tests/views/test_list_actions.py +++ b/bookwyrm/tests/views/test_list_actions.py @@ -18,7 +18,7 @@ class ListActionViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", @@ -90,8 +90,9 @@ class ListActionViews(TestCase): request.user = self.local_user with patch( "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async" - ) as mock: + ) as mock, patch("bookwyrm.lists_stream.remove_list_task.delay") as redis_mock: views.delete_list(request, self.list.id) + self.assertTrue(redis_mock.called) activity = json.loads(mock.call_args[1]["args"][1]) self.assertEqual(activity["type"], "Delete") self.assertEqual(activity["actor"], self.local_user.remote_id) @@ -123,10 +124,7 @@ class ListActionViews(TestCase): request = self.factory.post( "", - { - "item": pending.id, - "approved": "true", - }, + {"item": pending.id, "approved": "true"}, ) request.user = self.local_user @@ -553,12 +551,7 @@ class ListActionViews(TestCase): ) self.assertTrue(self.list.listitem_set.exists()) - request = self.factory.post( - "", - { - "item": item.id, - }, - ) + request = self.factory.post("", {"item": item.id}) request.user = self.local_user with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"): @@ -572,14 +565,22 @@ class ListActionViews(TestCase): book_list=self.list, user=self.local_user, book=self.book, order=1 ) self.assertTrue(self.list.listitem_set.exists()) - request = self.factory.post( - "", - { - "item": item.id, - }, - ) + request = self.factory.post("", {"item": item.id}) request.user = self.rat with self.assertRaises(PermissionDenied): views.list.remove_book(request, self.list.id) self.assertTrue(self.list.listitem_set.exists()) + + def test_save_unsave_list(self): + """bookmark a list""" + self.assertFalse(self.local_user.saved_lists.exists()) + request = self.factory.post("") + request.user = self.local_user + views.save_list(request, self.list.id) + self.local_user.refresh_from_db() + self.assertEqual(self.local_user.saved_lists.first(), self.list) + + views.unsave_list(request, self.list.id) + self.local_user.refresh_from_db() + self.assertFalse(self.local_user.saved_lists.exists()) diff --git a/bookwyrm/tests/views/test_notifications.py b/bookwyrm/tests/views/test_notifications.py index 5df62b1d..2a5cf798 100644 --- a/bookwyrm/tests/views/test_notifications.py +++ b/bookwyrm/tests/views/test_notifications.py @@ -17,7 +17,7 @@ class NotificationViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/test_outbox.py b/bookwyrm/tests/views/test_outbox.py index 5c5d47b0..598cce51 100644 --- a/bookwyrm/tests/views/test_outbox.py +++ b/bookwyrm/tests/views/test_outbox.py @@ -20,7 +20,7 @@ class OutboxView(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_reading.py b/bookwyrm/tests/views/test_reading.py index 4ec50165..0d6c13aa 100644 --- a/bookwyrm/tests/views/test_reading.py +++ b/bookwyrm/tests/views/test_reading.py @@ -20,7 +20,7 @@ class ReadingViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_readthrough.py b/bookwyrm/tests/views/test_readthrough.py index 5b554748..6697c0e0 100644 --- a/bookwyrm/tests/views/test_readthrough.py +++ b/bookwyrm/tests/views/test_readthrough.py @@ -27,7 +27,7 @@ class ReadThrough(TestCase): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.user = models.User.objects.create_user( "cinco", "cinco@example.com", "seissiete", local=True, localname="cinco" ) diff --git a/bookwyrm/tests/views/test_rss_feed.py b/bookwyrm/tests/views/test_rss_feed.py index 409c306d..8b3ecf58 100644 --- a/bookwyrm/tests/views/test_rss_feed.py +++ b/bookwyrm/tests/views/test_rss_feed.py @@ -15,7 +15,7 @@ class RssFeedView(TestCase): def setUp(self): with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "rss_user", "rss@test.rss", "password", local=True ) diff --git a/bookwyrm/tests/views/test_search.py b/bookwyrm/tests/views/test_search.py index 0efb2278..2df04f58 100644 --- a/bookwyrm/tests/views/test_search.py +++ b/bookwyrm/tests/views/test_search.py @@ -23,7 +23,7 @@ class Views(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_status.py b/bookwyrm/tests/views/test_status.py index b5d7ac16..35507157 100644 --- a/bookwyrm/tests/views/test_status.py +++ b/bookwyrm/tests/views/test_status.py @@ -13,6 +13,7 @@ from bookwyrm.tests.validate_html import validate_html # pylint: disable=invalid-name @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") @patch("bookwyrm.activitystreams.populate_stream_task.delay") +@patch("bookwyrm.lists_stream.populate_lists_task.delay") @patch("bookwyrm.activitystreams.remove_status_task.delay") @patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async") class StatusViews(TestCase): @@ -23,7 +24,7 @@ class StatusViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.com", diff --git a/bookwyrm/tests/views/test_updates.py b/bookwyrm/tests/views/test_updates.py index e7b466cc..4ca704fc 100644 --- a/bookwyrm/tests/views/test_updates.py +++ b/bookwyrm/tests/views/test_updates.py @@ -2,7 +2,7 @@ import json from unittest.mock import patch -from django.http import JsonResponse +from django.http import Http404, JsonResponse from django.test import TestCase from django.test.client import RequestFactory @@ -17,7 +17,7 @@ class UpdateViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", @@ -54,6 +54,7 @@ class UpdateViews(TestCase): "bookwyrm.activitystreams.ActivityStream.get_unread_count" ) as mock_count: with patch( + # pylint:disable=line-too-long "bookwyrm.activitystreams.ActivityStream.get_unread_count_by_status_type" ) as mock_count_by_status: mock_count.return_value = 3 @@ -64,3 +65,11 @@ class UpdateViews(TestCase): data = json.loads(result.getvalue()) self.assertEqual(data["count"], 3) self.assertEqual(data["count_by_type"]["review"], 5) + + def test_get_unread_status_count_invalid_stream(self): + """there are so many views, this just makes sure it LOADS""" + request = self.factory.get("") + request.user = self.local_user + + with self.assertRaises(Http404): + views.get_unread_status_count(request, "fish") diff --git a/bookwyrm/tests/views/test_user.py b/bookwyrm/tests/views/test_user.py index 74c9dfc6..f65ffa51 100644 --- a/bookwyrm/tests/views/test_user.py +++ b/bookwyrm/tests/views/test_user.py @@ -20,7 +20,7 @@ class UserViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/tests/views/test_wellknown.py b/bookwyrm/tests/views/test_wellknown.py index ecb6a67a..465f39b4 100644 --- a/bookwyrm/tests/views/test_wellknown.py +++ b/bookwyrm/tests/views/test_wellknown.py @@ -18,7 +18,7 @@ class WellknownViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch( "bookwyrm.activitystreams.populate_stream_task.delay" - ): + ), patch("bookwyrm.lists_stream.populate_lists_task.delay"): self.local_user = models.User.objects.create_user( "mouse@local.com", "mouse@mouse.mouse", diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index bd36f3d8..33199225 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -197,7 +197,9 @@ urlpatterns = [ ), re_path(r"^report/?$", views.make_report, name="report"), # landing pages - re_path(r"^about/?$", views.About.as_view(), name="about"), + re_path(r"^about/?$", views.about, name="about"), + re_path(r"^privacy/?$", views.privacy, name="privacy"), + re_path(r"^conduct/?$", views.conduct, name="conduct"), path("", views.Home.as_view(), name="landing"), re_path(r"^discover/?$", views.Discover.as_view(), name="discover"), re_path(r"^notifications/?$", views.Notifications.as_view(), name="notifications"), diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index f77a3b50..35058ffa 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -34,7 +34,8 @@ from .books.edit_book import EditBook, ConfirmEditBook from .books.editions import Editions, switch_edition # landing -from .landing.landing import About, Home, Landing +from .landing.about import about, privacy, conduct +from .landing.landing import Home, Landing from .landing.login import Login, Logout from .landing.register import Register, ConfirmEmail, ConfirmEmailCode, resend_link from .landing.password import PasswordResetRequest, PasswordReset diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index e060ae61..cb16371b 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -29,7 +29,9 @@ class Feed(View): filters_applied = False form = forms.FeedStatusTypesForm(request.POST, instance=request.user) if form.is_valid(): - form.save() + # workaround to avoid broadcasting this change + user = form.save(commit=False) + user.save(broadcast=False, update_fields=["feed_status_types"]) filters_applied = True return self.get(request, tab, filters_applied) diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 93aac9c4..8cc0aea8 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -1,12 +1,13 @@ """ helper functions used in various views """ import re -from datetime import datetime +from datetime import datetime, timedelta import dateutil.parser import dateutil.tz from dateutil.parser import ParserError from requests import HTTPError from django.db.models import Q +from django.conf import settings as django_settings from django.http import Http404 from django.utils import translation @@ -186,7 +187,11 @@ def set_language(user, response): """Updates a user's language""" if user.preferred_language: translation.activate(user.preferred_language) - response.set_cookie(settings.LANGUAGE_COOKIE_NAME, user.preferred_language) + response.set_cookie( + settings.LANGUAGE_COOKIE_NAME, + user.preferred_language, + expires=datetime.now() + timedelta(seconds=django_settings.SESSION_COOKIE_AGE), + ) return response diff --git a/bookwyrm/views/landing/about.py b/bookwyrm/views/landing/about.py new file mode 100644 index 00000000..9f6236e2 --- /dev/null +++ b/bookwyrm/views/landing/about.py @@ -0,0 +1,38 @@ +""" non-interactive pages """ +from dateutil.relativedelta import relativedelta +from django.template.response import TemplateResponse +from django.utils import timezone +from django.views.decorators.http import require_GET + +from bookwyrm import models, settings + + +@require_GET +def about(request): + """more information about the instance""" + six_months_ago = timezone.now() - relativedelta(months=6) + six_month_count = models.User.objects.filter( + is_active=True, local=True, last_active_date__gt=six_months_ago + ).count() + data = { + "active_users": six_month_count, + "status_count": models.Status.objects.filter( + user__local=True, deleted=False + ).count(), + "admins": models.User.objects.filter(groups__name__in=["admin", "moderator"]), + "version": settings.VERSION, + } + + return TemplateResponse(request, "about/about.html", data) + + +@require_GET +def conduct(request): + """more information about the instance""" + return TemplateResponse(request, "about/conduct.html") + + +@require_GET +def privacy(request): + """more information about the instance""" + return TemplateResponse(request, "about/privacy.html") diff --git a/bookwyrm/views/landing/landing.py b/bookwyrm/views/landing/landing.py index c8bba066..c1db28c7 100644 --- a/bookwyrm/views/landing/landing.py +++ b/bookwyrm/views/landing/landing.py @@ -8,14 +8,6 @@ from bookwyrm.views.feed import Feed # pylint: disable= no-self-use -class About(View): - """create invites""" - - def get(self, request): - """more information about the instance""" - return TemplateResponse(request, "landing/about.html") - - class Home(View): """landing page or home feed depending on auth""" diff --git a/bookwyrm/views/list.py b/bookwyrm/views/list.py index e04f6df4..804234ac 100644 --- a/bookwyrm/views/list.py +++ b/bookwyrm/views/list.py @@ -5,7 +5,7 @@ from urllib.parse import urlencode from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from django.db import IntegrityError, transaction -from django.db.models import Avg, Count, DecimalField, Q, Max +from django.db.models import Avg, DecimalField, Q, Max from django.db.models.functions import Coalesce from django.http import HttpResponseBadRequest, HttpResponse, Http404 from django.shortcuts import get_object_or_404, redirect @@ -18,6 +18,7 @@ from django.views.decorators.clickjacking import xframe_options_exempt from bookwyrm import book_search, forms, models from bookwyrm.activitypub import ActivitypubResponse +from bookwyrm.lists_stream import ListsStream from bookwyrm.settings import PAGE_LENGTH from .helpers import is_api_request from .helpers import get_user_from_username @@ -29,18 +30,7 @@ class Lists(View): def get(self, request): """display a book list""" - # hide lists with no approved books - lists = ( - models.List.privacy_filter( - request.user, privacy_levels=["public", "followers"] - ) - .annotate(item_count=Count("listitem", filter=Q(listitem__approved=True))) - .filter(item_count__gt=0) - .select_related("user") - .prefetch_related("listitem_set") - .order_by("-updated_date") - .distinct() - ) + lists = ListsStream().get_list_stream(request.user) paginated = Paginator(lists, 12) data = { "lists": paginated.get_page(request.GET.get("page")), diff --git a/bookwyrm/views/updates.py b/bookwyrm/views/updates.py index 2bbc5477..765865ef 100644 --- a/bookwyrm/views/updates.py +++ b/bookwyrm/views/updates.py @@ -1,6 +1,6 @@ """ endpoints for getting updates about activity """ from django.contrib.auth.decorators import login_required -from django.http import JsonResponse +from django.http import Http404, JsonResponse from bookwyrm import activitystreams @@ -21,7 +21,7 @@ def get_unread_status_count(request, stream="home"): """any unread statuses for this feed?""" stream = activitystreams.streams.get(stream) if not stream: - return JsonResponse({}) + raise Http404 return JsonResponse( { "count": stream.get_unread_count(request.user), diff --git a/bw-dev b/bw-dev index 55846b59..6bf5a125 100755 --- a/bw-dev +++ b/bw-dev @@ -139,6 +139,9 @@ case "$CMD" in populate_streams) runweb python manage.py populate_streams "$@" ;; + populate_lists_streams) + runweb python manage.py populate_lists_streams $@ + ;; populate_suggestions) runweb python manage.py populate_suggestions ;; diff --git a/complete_bwdev.sh b/complete_bwdev.sh index e7a036cc..85115fba 100644 --- a/complete_bwdev.sh +++ b/complete_bwdev.sh @@ -22,6 +22,7 @@ clean black prettier populate_streams +populate_lists_streams populate_suggestions generate_thumbnails generate_preview_images