From 8d5630e059391e5ff976694a2cc374be8faaf82c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 23 Mar 2021 17:52:58 -0700 Subject: [PATCH 01/18] Adds css transitions to notification and unread statuses --- bookwyrm/static/css/format.css | 23 +++++++++++++++++++++++ bookwyrm/templates/feed/feed.html | 2 +- bookwyrm/templates/layout.html | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/bookwyrm/static/css/format.css b/bookwyrm/static/css/format.css index c68eb40d2..6a1167b26 100644 --- a/bookwyrm/static/css/format.css +++ b/bookwyrm/static/css/format.css @@ -34,6 +34,29 @@ html { .hidden { display: none !important; } +.hidden.transition-y, .hidden.transition-x { + display: block !important; + visibility: hidden !important; + height: 0; + width: 0; + margin: 0; + padding: 0; +} +.transition-y { + transition-property: height, margin-top, margin-bottom, padding-top, padding-bottom; + transition-duration: 0.5s; + transition-timing-function: ease; +} +.transition-x { + transition-property: width, margin-left, margin-right, padding-left, padding-right; + transition-duration: 0.5s; + transition-timing-function: ease; +} +@media (prefers-reduced-motion: reduce) { + .transition-x, .transition-y { + transition-duration: 0.001ms !important; + } +} /* --- STARS --- */ .rate-stars button.icon { diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html index 379bf9272..bc35d3b90 100644 --- a/bookwyrm/templates/feed/feed.html +++ b/bookwyrm/templates/feed/feed.html @@ -28,7 +28,7 @@ {# announcements and system messages #} {% if not activities.number > 1 %} - diff --git a/bookwyrm/templates/layout.html b/bookwyrm/templates/layout.html index d08b18202..4f6573582 100644 --- a/bookwyrm/templates/layout.html +++ b/bookwyrm/templates/layout.html @@ -139,7 +139,7 @@ {% trans "Notifications" %} - + {{ request.user | notification_count }} From a67b0ae8a781f6e240671a7485c0998d89bbce3d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 08:29:12 -0700 Subject: [PATCH 03/18] Adds stream length to .env --- .env.example | 1 + bookwyrm/settings.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 7f80a72ce..cf3705af0 100644 --- a/.env.example +++ b/.env.example @@ -23,6 +23,7 @@ POSTGRES_DB=fedireads POSTGRES_HOST=db # Redis activity stream manager +MAX_STREAM_LENGTH=200 REDIS_ACTIVITY_HOST=redis_activity REDIS_ACTIVITY_PORT=6379 diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 368064355..b615fa293 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -96,7 +96,7 @@ WSGI_APPLICATION = "bookwyrm.wsgi.application" REDIS_ACTIVITY_HOST = env("REDIS_ACTIVITY_HOST", "localhost") REDIS_ACTIVITY_PORT = env("REDIS_ACTIVITY_PORT", 6379) -MAX_STREAM_LENGTH = env("MAX_STREAM_LENGTH", 200) +MAX_STREAM_LENGTH = int(env("MAX_STREAM_LENGTH", 200)) STREAMS = ["home", "local", "federated"] # Database From 1707bba8a8aa610006808c0ed7d144f6f14a52e8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 08:37:25 -0700 Subject: [PATCH 04/18] Adds ordering to status model --- bookwyrm/migrations/0058_auto_20210324_1536.py | 17 +++++++++++++++++ bookwyrm/models/status.py | 4 ++++ 2 files changed, 21 insertions(+) create mode 100644 bookwyrm/migrations/0058_auto_20210324_1536.py diff --git a/bookwyrm/migrations/0058_auto_20210324_1536.py b/bookwyrm/migrations/0058_auto_20210324_1536.py new file mode 100644 index 000000000..d69dbab08 --- /dev/null +++ b/bookwyrm/migrations/0058_auto_20210324_1536.py @@ -0,0 +1,17 @@ +# Generated by Django 3.1.6 on 2021-03-24 15:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0057_user_discoverable'), + ] + + operations = [ + migrations.AlterModelOptions( + name='status', + options={'ordering': ('-published_date',)}, + ), + ] diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 77ac4b582..e90c2dec0 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -58,6 +58,10 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): serialize_reverse_fields = [("attachments", "attachment", "id")] deserialize_reverse_fields = [("attachments", "attachment")] + class Meta: + """ default sorting """ + ordering = ("-published_date",) + def save(self, *args, **kwargs): """ save and notify """ super().save(*args, **kwargs) From 320dfd1a59f06148ea8cab988e4ccf80886e0526 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 08:39:37 -0700 Subject: [PATCH 05/18] Python formatting --- bookwyrm/migrations/0058_auto_20210324_1536.py | 6 +++--- bookwyrm/models/status.py | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bookwyrm/migrations/0058_auto_20210324_1536.py b/bookwyrm/migrations/0058_auto_20210324_1536.py index d69dbab08..0fa8c90b6 100644 --- a/bookwyrm/migrations/0058_auto_20210324_1536.py +++ b/bookwyrm/migrations/0058_auto_20210324_1536.py @@ -6,12 +6,12 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0057_user_discoverable'), + ("bookwyrm", "0057_user_discoverable"), ] operations = [ migrations.AlterModelOptions( - name='status', - options={'ordering': ('-published_date',)}, + name="status", + options={"ordering": ("-published_date",)}, ), ] diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index e90c2dec0..0ddcfd173 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -60,6 +60,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): class Meta: """ default sorting """ + ordering = ("-published_date",) def save(self, *args, **kwargs): From bde6ce8525c6d16205a5a4bd784fbf83572e9783 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 09:31:45 -0700 Subject: [PATCH 06/18] Fixes review name in pure serialization --- bookwyrm/models/fields.py | 3 +++ bookwyrm/models/status.py | 15 +++++++-------- .../generated_status/review_pure_name.html | 10 ++++++++++ 3 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 bookwyrm/templates/snippets/generated_status/review_pure_name.html diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index 247c6aca6..a5985e8de 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -448,3 +448,6 @@ class IntegerField(ActivitypubFieldMixin, models.IntegerField): class DecimalField(ActivitypubFieldMixin, models.DecimalField): """ activitypub-aware boolean field """ + + def field_to_activity(self, value): + return float(value) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 0ddcfd173..56f30020f 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -304,13 +304,12 @@ class Review(Status): @property def pure_name(self): """ clarify review names for mastodon serialization """ - if self.rating: - return 'Review of "{}" ({:d} stars): {}'.format( - self.book.title, - self.rating, - self.name, - ) - return 'Review of "{}": {}'.format(self.book.title, self.name) + template = get_template("snippets/generated_status/review_pure_name.html") + return template.render({ + "book": self.book, + "rating": int(self.rating), + "name": self.name + }).strip() @property def pure_content(self): @@ -332,7 +331,7 @@ class ReviewRating(Review): @property def pure_content(self): template = get_template("snippets/generated_status/rating.html") - return template.render({"book": self.book, "rating": self.rating}).strip() + return template.render({"book": self.book, "rating": int(self.rating)}).strip() activity_serializer = activitypub.Rating pure_type = "Note" diff --git a/bookwyrm/templates/snippets/generated_status/review_pure_name.html b/bookwyrm/templates/snippets/generated_status/review_pure_name.html new file mode 100644 index 000000000..3c133678b --- /dev/null +++ b/bookwyrm/templates/snippets/generated_status/review_pure_name.html @@ -0,0 +1,10 @@ +{% load i18n %} +{% if rating %} + +{% blocktrans with book_title=book.title rating=rating review_title=name count counter=rating %}Review of {{ book_title }} ({{ rating }} star): {{ review_title }}{% plural %}Review of {{ book_title }} ({{ rating }} stars): {{ review_title }}{% endblocktrans %} + +{% else %} + +{% blocktrans with book_title=book.title review_title=name %}Review of {{ book_title }}: {{ review_title }}{% endblocktrans %} + +{% endif %} From 9dc19b8bffe77012bda489c7a408b5db96cf2669 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 09:34:21 -0700 Subject: [PATCH 07/18] Python formatting --- bookwyrm/models/status.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 56f30020f..e655616fa 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -305,11 +305,9 @@ class Review(Status): def pure_name(self): """ clarify review names for mastodon serialization """ template = get_template("snippets/generated_status/review_pure_name.html") - return template.render({ - "book": self.book, - "rating": int(self.rating), - "name": self.name - }).strip() + return template.render( + {"book": self.book, "rating": int(self.rating), "name": self.name} + ).strip() @property def pure_content(self): From 1d53a06e35dd5b89e1deb0fcf5e458fe1b9d76c0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 09:51:49 -0700 Subject: [PATCH 08/18] Fixes decimaal formatting --- bookwyrm/models/fields.py | 2 ++ bookwyrm/models/status.py | 4 ++-- bookwyrm/templates/snippets/generated_status/rating.html | 2 +- .../templates/snippets/generated_status/review_pure_name.html | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bookwyrm/models/fields.py b/bookwyrm/models/fields.py index a5985e8de..e034d59ee 100644 --- a/bookwyrm/models/fields.py +++ b/bookwyrm/models/fields.py @@ -450,4 +450,6 @@ class DecimalField(ActivitypubFieldMixin, models.DecimalField): """ activitypub-aware boolean field """ def field_to_activity(self, value): + if not value: + return None return float(value) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index e655616fa..adc9d39d6 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -306,7 +306,7 @@ class Review(Status): """ clarify review names for mastodon serialization """ template = get_template("snippets/generated_status/review_pure_name.html") return template.render( - {"book": self.book, "rating": int(self.rating), "name": self.name} + {"book": self.book, "rating": self.rating, "name": self.name} ).strip() @property @@ -329,7 +329,7 @@ class ReviewRating(Review): @property def pure_content(self): template = get_template("snippets/generated_status/rating.html") - return template.render({"book": self.book, "rating": int(self.rating)}).strip() + return template.render({"book": self.book, "rating": self.rating}).strip() activity_serializer = activitypub.Rating pure_type = "Note" diff --git a/bookwyrm/templates/snippets/generated_status/rating.html b/bookwyrm/templates/snippets/generated_status/rating.html index 13afd94de..c23d0eb8c 100644 --- a/bookwyrm/templates/snippets/generated_status/rating.html +++ b/bookwyrm/templates/snippets/generated_status/rating.html @@ -1,3 +1,3 @@ {% load i18n %}{% load humanize %} -{% blocktrans with title=book.title path=book.remote_id rating=rating count counter=rating %}Rated {{ title }}: {{ rating }} star{% plural %}Rated {{ title }}: {{ rating }} stars{% endblocktrans %} +{% blocktrans with title=book.title path=book.remote_id rating=rating|floatformat:"0" count counter=rating %}Rated {{ title }}: {{ rating }} star{% plural %}Rated {{ title }}: {{ rating }} stars{% endblocktrans %} diff --git a/bookwyrm/templates/snippets/generated_status/review_pure_name.html b/bookwyrm/templates/snippets/generated_status/review_pure_name.html index 3c133678b..f58643840 100644 --- a/bookwyrm/templates/snippets/generated_status/review_pure_name.html +++ b/bookwyrm/templates/snippets/generated_status/review_pure_name.html @@ -1,7 +1,7 @@ {% load i18n %} {% if rating %} -{% blocktrans with book_title=book.title rating=rating review_title=name count counter=rating %}Review of {{ book_title }} ({{ rating }} star): {{ review_title }}{% plural %}Review of {{ book_title }} ({{ rating }} stars): {{ review_title }}{% endblocktrans %} +{% blocktrans with book_title=book.title rating=rating|floatformat:"0" review_title=name count counter=rating %}Review of {{ book_title }} ({{ rating }} star): {{ review_title }}{% plural %}Review of {{ book_title }} ({{ rating }} stars): {{ review_title }}{% endblocktrans %} {% else %} From 73e38f9050af0bf7c1f63a233add9ec4fe67f316 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 10:07:39 -0700 Subject: [PATCH 09/18] Fixes formatting rating value in template --- .../generated_status/review_pure_name.html | 2 +- bookwyrm/tests/models/test_status_model.py | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/bookwyrm/templates/snippets/generated_status/review_pure_name.html b/bookwyrm/templates/snippets/generated_status/review_pure_name.html index f58643840..a8d3fa5b8 100644 --- a/bookwyrm/templates/snippets/generated_status/review_pure_name.html +++ b/bookwyrm/templates/snippets/generated_status/review_pure_name.html @@ -1,7 +1,7 @@ {% load i18n %} {% if rating %} -{% blocktrans with book_title=book.title rating=rating|floatformat:"0" review_title=name count counter=rating %}Review of {{ book_title }} ({{ rating }} star): {{ review_title }}{% plural %}Review of {{ book_title }} ({{ rating }} stars): {{ review_title }}{% endblocktrans %} +{% blocktrans with book_title=book.title display_rating=rating|floatformat:"0" review_title=name count counter=rating %}Review of {{ book_title }} ({{ display_rating }} star): {{ review_title }}{% plural %}Review of {{ book_title }} ({{ display_rating }} stars): {{ review_title }}{% endblocktrans %} {% else %} diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 54fe7fee9..05cd2f000 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -277,7 +277,30 @@ class Status(TestCase): self.assertEqual(activity["id"], status.remote_id) self.assertEqual(activity["type"], "Article") self.assertEqual( - activity["name"], 'Review of "%s" (3 stars): Review name' % self.book.title + activity["name"], + "Review of %s (3 stars): Review name" % self.book.title, + ) + self.assertEqual(activity["content"], "test content") + self.assertEqual(activity["attachment"][0].type, "Document") + self.assertEqual( + activity["attachment"][0].url, + "https://%s%s" % (settings.DOMAIN, self.book.cover.url), + ) + self.assertEqual(activity["attachment"][0].name, "Test Edition") + + def test_review_to_pure_activity_no_rating(self, *_): + """ subclass of the base model version with a "pure" serializer """ + status = models.Review.objects.create( + name="Review name", + content="test content", + user=self.local_user, + book=self.book, + ) + activity = status.to_activity(pure=True) + self.assertEqual(activity["id"], status.remote_id) + self.assertEqual(activity["type"], "Article") + self.assertEqual( + activity["name"], "Review of %s: Review name" % self.book.title ) self.assertEqual(activity["content"], "test content") self.assertEqual(activity["attachment"][0].type, "Document") From 30cebc017fcd8653b81034a2ac562e194d9c9244 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 10:17:45 -0700 Subject: [PATCH 10/18] Updates tests to catch decimal/float/int errors in status serialization --- .../snippets/generated_status/rating.html | 2 +- bookwyrm/tests/models/test_status_model.py | 26 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/snippets/generated_status/rating.html b/bookwyrm/templates/snippets/generated_status/rating.html index c23d0eb8c..b70171cde 100644 --- a/bookwyrm/templates/snippets/generated_status/rating.html +++ b/bookwyrm/templates/snippets/generated_status/rating.html @@ -1,3 +1,3 @@ {% load i18n %}{% load humanize %} -{% blocktrans with title=book.title path=book.remote_id rating=rating|floatformat:"0" count counter=rating %}Rated {{ title }}: {{ rating }} star{% plural %}Rated {{ title }}: {{ rating }} stars{% endblocktrans %} +{% blocktrans with title=book.title path=book.remote_id display_rating=rating|floatformat:"0" count counter=rating %}Rated {{ title }}: {{ display_rating }} star{% plural %}Rated {{ title }}: {{ display_rating }} stars{% endblocktrans %} diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 05cd2f000..97df315f9 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -252,7 +252,7 @@ class Status(TestCase): status = models.Review.objects.create( name="Review name", content="test content", - rating=3, + rating=3.0, user=self.local_user, book=self.book, ) @@ -269,7 +269,7 @@ class Status(TestCase): status = models.Review.objects.create( name="Review name", content="test content", - rating=3, + rating=3.0, user=self.local_user, book=self.book, ) @@ -310,6 +310,28 @@ class Status(TestCase): ) self.assertEqual(activity["attachment"][0].name, "Test Edition") + def test_reviewrating_to_pure_activity(self, *_): + """ subclass of the base model version with a "pure" serializer """ + status = models.ReviewRating.objects.create( + rating=3.0, + user=self.local_user, + book=self.book, + ) + activity = status.to_activity(pure=True) + self.assertEqual(activity["id"], status.remote_id) + self.assertEqual(activity["type"], "Note") + self.assertEqual( + activity["content"], + 'Rated %s: 3 stars' + % (self.book.remote_id, self.book.title), + ) + self.assertEqual(activity["attachment"][0].type, "Document") + self.assertEqual( + activity["attachment"][0].url, + "https://%s%s" % (settings.DOMAIN, self.book.cover.url), + ) + self.assertEqual(activity["attachment"][0].name, "Test Edition") + def test_favorite(self, *_): """ fav a status """ real_broadcast = models.Favorite.broadcast From c1e0471d1ad4578cc8f120c72fadef03405d639f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 10:57:17 -0700 Subject: [PATCH 11/18] Don't use html in article names for mastodon --- .../templates/snippets/generated_status/review_pure_name.html | 4 ++-- bookwyrm/tests/models/test_status_model.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templates/snippets/generated_status/review_pure_name.html b/bookwyrm/templates/snippets/generated_status/review_pure_name.html index a8d3fa5b8..90a6936ed 100644 --- a/bookwyrm/templates/snippets/generated_status/review_pure_name.html +++ b/bookwyrm/templates/snippets/generated_status/review_pure_name.html @@ -1,10 +1,10 @@ {% load i18n %} {% if rating %} -{% blocktrans with book_title=book.title display_rating=rating|floatformat:"0" review_title=name count counter=rating %}Review of {{ book_title }} ({{ display_rating }} star): {{ review_title }}{% plural %}Review of {{ book_title }} ({{ display_rating }} stars): {{ review_title }}{% endblocktrans %} +{% blocktrans with book_title=book.title display_rating=rating|floatformat:"0" review_title=name count counter=rating %}Review of "{{ book_title }}" ({{ display_rating }} star): {{ review_title }}{% plural %}Review of "{{ book_title }}" ({{ display_rating }} stars): {{ review_title }}{% endblocktrans %} {% else %} -{% blocktrans with book_title=book.title review_title=name %}Review of {{ book_title }}: {{ review_title }}{% endblocktrans %} +{% blocktrans with book_title=book.title review_title=name %}Review of "{{ book_title }}": {{ review_title }}{% endblocktrans %} {% endif %} diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 97df315f9..10c09cd9e 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -278,7 +278,7 @@ class Status(TestCase): self.assertEqual(activity["type"], "Article") self.assertEqual( activity["name"], - "Review of %s (3 stars): Review name" % self.book.title, + "Review of \"%s\" (3 stars): Review name" % self.book.title, ) self.assertEqual(activity["content"], "test content") self.assertEqual(activity["attachment"][0].type, "Document") @@ -300,7 +300,7 @@ class Status(TestCase): self.assertEqual(activity["id"], status.remote_id) self.assertEqual(activity["type"], "Article") self.assertEqual( - activity["name"], "Review of %s: Review name" % self.book.title + activity["name"], "Review of \"%s\": Review name" % self.book.title ) self.assertEqual(activity["content"], "test content") self.assertEqual(activity["attachment"][0].type, "Document") From 61a773cbe227771bda6619abd00d1570a55c991f Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 11:01:23 -0700 Subject: [PATCH 12/18] Python formatting --- bookwyrm/tests/models/test_status_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 10c09cd9e..c3cdf17e2 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -278,7 +278,7 @@ class Status(TestCase): self.assertEqual(activity["type"], "Article") self.assertEqual( activity["name"], - "Review of \"%s\" (3 stars): Review name" % self.book.title, + 'Review of "%s" (3 stars): Review name' % self.book.title, ) self.assertEqual(activity["content"], "test content") self.assertEqual(activity["attachment"][0].type, "Document") @@ -300,7 +300,7 @@ class Status(TestCase): self.assertEqual(activity["id"], status.remote_id) self.assertEqual(activity["type"], "Article") self.assertEqual( - activity["name"], "Review of \"%s\": Review name" % self.book.title + activity["name"], 'Review of "%s": Review name' % self.book.title ) self.assertEqual(activity["content"], "test content") self.assertEqual(activity["attachment"][0].type, "Document") From 81bd3f5be8994751214232c1a6281974ba1972f3 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 12:05:00 -0700 Subject: [PATCH 13/18] Tests not showing notifications for self boosts --- bookwyrm/models/status.py | 2 +- bookwyrm/tests/views/test_interaction.py | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index adc9d39d6..c5ba79931 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -349,7 +349,7 @@ class Boost(ActivityMixin, Status): def save(self, *args, **kwargs): """ save and notify """ super().save(*args, **kwargs) - if not self.boosted_status.user.local: + if not self.boosted_status.user.local or self.boosted_status.user == self.user: return notification_model = apps.get_model("bookwyrm.Notification", require_ready=True) diff --git a/bookwyrm/tests/views/test_interaction.py b/bookwyrm/tests/views/test_interaction.py index 40152c0fb..297eeb73d 100644 --- a/bookwyrm/tests/views/test_interaction.py +++ b/bookwyrm/tests/views/test_interaction.py @@ -95,6 +95,23 @@ class InteractionViews(TestCase): self.assertEqual(notification.related_user, self.remote_user) self.assertEqual(notification.related_status, status) + def test_handle_self_boost(self, _): + """ boost your own status """ + view = views.Boost.as_view() + request = self.factory.post("") + request.user = self.local_user + with patch("bookwyrm.activitystreams.ActivityStream.add_status"): + status = models.Status.objects.create(user=self.local_user, content="hi") + + view(request, status.id) + + boost = models.Boost.objects.get() + self.assertEqual(boost.boosted_status, status) + self.assertEqual(boost.user, self.local_user) + self.assertEqual(boost.privacy, "public") + + self.assertFalse(models.Notification.objects.exists()) + def test_handle_boost_unlisted(self, _): """ boost a status """ view = views.Boost.as_view() @@ -135,23 +152,21 @@ class InteractionViews(TestCase): view(request, status.id) self.assertEqual(models.Boost.objects.count(), 1) - def test_handle_unboost(self, broadcast_mock): + def test_handle_unboost(self, _): """ undo a boost """ view = views.Unboost.as_view() request = self.factory.post("") - request.user = self.local_user + request.user = self.remote_user with patch("bookwyrm.activitystreams.ActivityStream.add_status"): status = models.Status.objects.create(user=self.local_user, content="hi") views.Boost.as_view()(request, status.id) self.assertEqual(models.Boost.objects.count(), 1) self.assertEqual(models.Notification.objects.count(), 1) - broadcast_mock.call_count = 0 with patch( "bookwyrm.activitystreams.ActivityStream.remove_status" ) as redis_mock: view(request, status.id) - self.assertEqual(broadcast_mock.call_count, 1) self.assertTrue(redis_mock.called) self.assertEqual(models.Boost.objects.count(), 0) self.assertEqual(models.Notification.objects.count(), 0) From 28dc67bf5c0d5bfb24dba3ed6a6fc958afc7a036 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 12:37:42 -0700 Subject: [PATCH 14/18] Fixes ignore test for valid remote statuses --- bookwyrm/activitypub/base_activity.py | 7 ++++++- bookwyrm/models/status.py | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index 791502d01..c1f81bb02 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -248,7 +248,9 @@ def get_model_from_type(activity_type): return model[0] -def resolve_remote_id(remote_id, model=None, refresh=False, save=True): +def resolve_remote_id( + remote_id, model=None, refresh=False, save=True, get_activity=False +): """ take a remote_id and return an instance, creating if necessary """ if model: # a bonus check we can do if we already know the model result = model.find_existing_by_remote_id(remote_id) @@ -272,5 +274,8 @@ def resolve_remote_id(remote_id, model=None, refresh=False, save=True): return result item = model.activity_serializer(**data) + if get_activity: + return item + # if we're refreshing, "result" will be set and we'll update it return item.to_model(model=model, instance=result, save=save) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index c5ba79931..c471a4d98 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -123,12 +123,14 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): """ keep notes if they are replies to existing statuses """ if activity.type == "Announce": try: - boosted = activitypub.resolve_remote_id(activity.object, save=False) + boosted = activitypub.resolve_remote_id( + activity.object, get_activity=True + ) except activitypub.ActivitySerializerError: # if we can't load the status, definitely ignore it return True # keep the boost if we would keep the status - return cls.ignore_activity(boosted.to_activity_dataclass()) + return cls.ignore_activity(boosted) # keep if it if it's a custom type if activity.type != "Note": From d8c83fa31c84553723cc0e43bbac5a77472cf19a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 12:58:39 -0700 Subject: [PATCH 15/18] Return activities for existing objs in resolve_remote_id --- .github/workflows/django-tests.yml | 2 +- bookwyrm/activitypub/base_activity.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml index e734d18ec..3ce368ecd 100644 --- a/.github/workflows/django-tests.yml +++ b/.github/workflows/django-tests.yml @@ -65,4 +65,4 @@ jobs: EMAIL_HOST_PASSWORD: "" EMAIL_USE_TLS: true run: | - python manage.py test -v 3 + python manage.py test diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index c1f81bb02..768eb2084 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -255,7 +255,7 @@ def resolve_remote_id( if model: # a bonus check we can do if we already know the model result = model.find_existing_by_remote_id(remote_id) if result and not refresh: - return result + return result if not get_activity else result.to_activity_dataclass() # load the data and create the object try: @@ -271,7 +271,7 @@ def resolve_remote_id( # check for existing items with shared unique identifiers result = model.find_existing(data) if result and not refresh: - return result + return result if not get_activity else result.to_activity_dataclass() item = model.activity_serializer(**data) if get_activity: From 3fe3b0b2d590d809db16ceeea4c8a7bb75ac38e4 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 13:25:00 -0700 Subject: [PATCH 16/18] Adds published date field to boost activity --- bookwyrm/activitypub/verbs.py | 1 + bookwyrm/models/status.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/activitypub/verbs.py b/bookwyrm/activitypub/verbs.py index d684171e9..900c9a219 100644 --- a/bookwyrm/activitypub/verbs.py +++ b/bookwyrm/activitypub/verbs.py @@ -191,6 +191,7 @@ class Like(Verb): class Announce(Verb): """ boosting a status """ + published: str object: str type: str = "Announce" diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index c471a4d98..aa330d613 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -377,7 +377,7 @@ class Boost(ActivityMixin, Status): """ the user field is "actor" here instead of "attributedTo" """ super().__init__(*args, **kwargs) - reserve_fields = ["user", "boosted_status"] + reserve_fields = ["user", "boosted_status", "published_date"] self.simple_fields = [f for f in self.simple_fields if f.name in reserve_fields] self.activity_fields = self.simple_fields self.many_to_many_fields = [] From 9acb8e53d8259f0f34d439a30e356934870d9c1b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 13:35:49 -0700 Subject: [PATCH 17/18] Adds privacy fields to boost activities --- bookwyrm/activitypub/verbs.py | 4 +++- bookwyrm/models/status.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/bookwyrm/activitypub/verbs.py b/bookwyrm/activitypub/verbs.py index 900c9a219..3686b3f3e 100644 --- a/bookwyrm/activitypub/verbs.py +++ b/bookwyrm/activitypub/verbs.py @@ -1,5 +1,5 @@ """ undo wrapper activity """ -from dataclasses import dataclass +from dataclasses import dataclass, field from typing import List from django.apps import apps @@ -192,6 +192,8 @@ class Announce(Verb): """ boosting a status """ published: str + to: List[str] = field(default_factory=lambda: []) + cc: List[str] = field(default_factory=lambda: []) object: str type: str = "Announce" diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index aa330d613..8038e3ee5 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -377,7 +377,7 @@ class Boost(ActivityMixin, Status): """ the user field is "actor" here instead of "attributedTo" """ super().__init__(*args, **kwargs) - reserve_fields = ["user", "boosted_status", "published_date"] + reserve_fields = ["user", "boosted_status", "published_date", "privacy"] self.simple_fields = [f for f in self.simple_fields if f.name in reserve_fields] self.activity_fields = self.simple_fields self.many_to_many_fields = [] From ae6c2b6375097c9165aef45bc9195b0a0ea7f088 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 24 Mar 2021 14:19:12 -0700 Subject: [PATCH 18/18] Updates tests --- bookwyrm/tests/models/test_status_model.py | 3 +++ bookwyrm/tests/views/test_inbox.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index c3cdf17e2..208bf3ab4 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -441,6 +441,9 @@ class Status(TestCase): id="http://www.faraway.com/boost/12", actor=self.remote_user.remote_id, object="http://fish.com/nothing", + published="2021-03-24T18:59:41.841208+00:00", + cc="", + to="", ) responses.add(responses.GET, "http://fish.com/nothing", status=404) diff --git a/bookwyrm/tests/views/test_inbox.py b/bookwyrm/tests/views/test_inbox.py index 7d08a1e49..37cf00ddc 100644 --- a/bookwyrm/tests/views/test_inbox.py +++ b/bookwyrm/tests/views/test_inbox.py @@ -559,6 +559,9 @@ class Inbox(TestCase): "id": "%s/boost" % self.status.remote_id, "actor": self.remote_user.remote_id, "object": self.status.remote_id, + "to": ["https://www.w3.org/ns/activitystreams#public"], + "cc": ["https://example.com/user/mouse/followers"], + "published": "Mon, 25 May 2020 19:31:20 GMT", } with patch("bookwyrm.models.status.Status.ignore_activity") as discarder: discarder.return_value = False @@ -607,6 +610,9 @@ class Inbox(TestCase): "id": boost.remote_id, "actor": self.remote_user.remote_id, "object": self.status.remote_id, + "to": ["https://www.w3.org/ns/activitystreams#public"], + "cc": ["https://example.com/user/mouse/followers"], + "published": "Mon, 25 May 2020 19:31:20 GMT", }, } with patch( @@ -614,6 +620,7 @@ class Inbox(TestCase): ) as redis_mock: views.inbox.activity_task(activity) self.assertTrue(redis_mock.called) + self.assertFalse(models.Boost.objects.exists()) def test_handle_unboost_unknown_boost(self): """ undo a boost """