diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 7b18a2ff..0c3b19ba 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -52,47 +52,31 @@ class RegisterForm(CustomForm): class RatingForm(CustomForm): class Meta: model = models.Review - fields = ['rating'] + fields = ['user', 'book', 'content', 'rating', 'privacy'] class ReviewForm(CustomForm): class Meta: model = models.Review - fields = ['name', 'content'] - help_texts = {f: None for f in fields} - labels = { - 'name': 'Title', - 'content': 'Review', - } + fields = ['user', 'book', 'name', 'content', 'rating', 'privacy'] class CommentForm(CustomForm): class Meta: model = models.Comment - fields = ['content'] - help_texts = {f: None for f in fields} - labels = { - 'content': 'Comment', - } + fields = ['user', 'book', 'content', 'privacy'] class QuotationForm(CustomForm): class Meta: model = models.Quotation - fields = ['quote', 'content'] - help_texts = {f: None for f in fields} - labels = { - 'quote': 'Quote', - 'content': 'Comment', - } + fields = ['user', 'book', 'quote', 'content', 'privacy'] class ReplyForm(CustomForm): class Meta: model = models.Status - fields = ['content'] - help_texts = {f: None for f in fields} - labels = {'content': 'Comment'} + fields = ['user', 'content', 'reply_parent', 'privacy'] class EditUserForm(CustomForm): diff --git a/bookwyrm/migrations/0057_auto_20201026_2131.py b/bookwyrm/migrations/0057_auto_20201026_2131.py new file mode 100644 index 00000000..cc414e98 --- /dev/null +++ b/bookwyrm/migrations/0057_auto_20201026_2131.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.7 on 2020-10-26 21:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0056_auto_20201021_0150'), + ] + + operations = [ + migrations.AlterField( + model_name='status', + name='privacy', + field=models.CharField(choices=[('public', 'Public'), ('unlisted', 'Unlisted'), ('followers', 'Followers'), ('direct', 'Direct')], default='public', max_length=255), + ), + ] diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 61e9c500..b1283c9d 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -10,6 +10,13 @@ from .base_model import ActivitypubMixin, OrderedCollectionPageMixin from .base_model import ActivityMapping, BookWyrmModel +PrivacyLevels = models.TextChoices('Privacy', [ + 'public', + 'unlisted', + 'followers', + 'direct' +]) + class Status(OrderedCollectionPageMixin, BookWyrmModel): ''' any post, like a reply to a review, etc ''' user = models.ForeignKey('User', on_delete=models.PROTECT) @@ -18,7 +25,11 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): mention_books = models.ManyToManyField( 'Edition', related_name='mention_book') local = models.BooleanField(default=True) - privacy = models.CharField(max_length=255, default='public') + privacy = models.CharField( + max_length=255, + default='public', + choices=PrivacyLevels.choices + ) sensitive = models.BooleanField(default=False) # the created date can't be this, because of receiving federated posts published_date = models.DateTimeField(default=timezone.now) @@ -181,9 +192,14 @@ class Review(Status): @property def ap_pure_name(self): ''' clarify review names for mastodon serialization ''' - return 'Review of "%s" (%d stars): %s' % ( + if self.rating: + return 'Review of "%s" (%d stars): %s' % ( + self.book.title, + self.rating, + self.name + ) + return 'Review of "%s": %s' % ( self.book.title, - self.rating, self.name ) diff --git a/bookwyrm/outgoing.py b/bookwyrm/outgoing.py index f496a211..4681a670 100644 --- a/bookwyrm/outgoing.py +++ b/bookwyrm/outgoing.py @@ -9,9 +9,7 @@ import requests from bookwyrm import activitypub from bookwyrm import models from bookwyrm.broadcast import broadcast -from bookwyrm.status import create_review, create_status -from bookwyrm.status import create_quotation, create_comment -from bookwyrm.status import create_tag, create_notification, create_rating +from bookwyrm.status import create_tag, create_notification from bookwyrm.status import create_generated_note from bookwyrm.status import delete_status from bookwyrm.remote_user import get_or_create_remote_user @@ -178,15 +176,16 @@ def handle_import_books(user, items): broadcast(user, activity) if item.rating or item.review: - review_title = "Review of {!r} on Goodreads".format( + review_title = 'Review of {!r} on Goodreads'.format( item.book.title, - ) if item.review else "" - handle_review( - user, - item.book, - review_title, - item.review, - item.rating, + ) if item.review else '' + + models.Review.objects.create( + user=user, + book=item.book, + name=review_title, + content=item.review, + rating=item.rating, ) for read in item.reads: read.book = item.book @@ -209,44 +208,25 @@ def handle_delete_status(user, status): broadcast(user, status.to_activity()) -def handle_rate(user, book, rating): - ''' a review that's just a rating ''' - builder = create_rating - handle_status(user, book, builder, rating) - - -def handle_review(user, book, name, content, rating): - ''' post a review ''' - # validated and saves the review in the database so it has an id - builder = create_review - handle_status(user, book, builder, name, content, rating) - - -def handle_quotation(user, book, content, quote): - ''' post a review ''' - # validated and saves the review in the database so it has an id - builder = create_quotation - handle_status(user, book, builder, content, quote) - - -def handle_comment(user, book, content): - ''' post a comment ''' - # validated and saves the review in the database so it has an id - builder = create_comment - handle_status(user, book, builder, content) - - -def handle_status(user, book_id, builder, *args): +def handle_status(user, form): ''' generic handler for statuses ''' - book = models.Edition.objects.get(id=book_id) - status = builder(user, book, *args) + status = form.save() + + # notify reply parent or (TODO) tagged users + if status.reply_parent and status.reply_parent.user.local: + create_notification( + status.reply_parent.user, + 'REPLY', + related_user=user, + related_status=status + ) broadcast(user, status.to_create_activity(user), software='bookwyrm') # re-format the activity for non-bookwyrm servers - remote_activity = status.to_create_activity(user, pure=True) - - broadcast(user, remote_activity, software='other') + if hasattr(status, 'pure_activity_serializer'): + remote_activity = status.to_create_activity(user, pure=True) + broadcast(user, remote_activity, software='other') def handle_tag(user, book, name): @@ -265,21 +245,6 @@ def handle_untag(user, book, name): broadcast(user, tag_activity) -def handle_reply(user, review, content): - ''' respond to a review or status ''' - # validated and saves the comment in the database so it has an id - reply = create_status(user, content, reply_parent=review) - if reply.reply_parent: - create_notification( - reply.reply_parent.user, - 'REPLY', - related_user=user, - related_status=reply, - ) - - broadcast(user, reply.to_create_activity(user)) - - def handle_favorite(user, status): ''' a user likes a status ''' try: diff --git a/bookwyrm/status.py b/bookwyrm/status.py index 25619839..258734b3 100644 --- a/bookwyrm/status.py +++ b/bookwyrm/status.py @@ -13,100 +13,6 @@ def delete_status(status): status.deleted_date = datetime.now() status.save() -def create_rating(user, book, rating): - ''' a review that's just a rating ''' - if not rating or rating < 1 or rating > 5: - raise ValueError('Invalid rating') - return models.Review.objects.create( - user=user, - book=book, - rating=rating, - ) - - -def create_review(user, book, name, content, rating): - ''' a book review has been added ''' - name = sanitize(name) - content = sanitize(content) - - # no ratings outside of 0-5 - if rating: - rating = rating if 1 <= rating <= 5 else None - else: - rating = None - - return models.Review.objects.create( - user=user, - book=book, - name=name, - rating=rating, - content=content, - ) - - -def create_quotation_from_activity(author, activity): - ''' parse an activity json blob into a status ''' - book_id = activity['inReplyToBook'] - book = get_or_create_book(book_id) - quote = activity.get('quote') - content = activity.get('content') - published = activity.get('published') - remote_id = activity['id'] - - quotation = create_quotation(author, book, content, quote) - quotation.published_date = published - quotation.remote_id = remote_id - quotation.save() - return quotation - - -def create_quotation(user, book, content, quote): - ''' a quotation has been added ''' - # throws a value error if the book is not found - content = sanitize(content) - quote = sanitize(quote) - - return models.Quotation.objects.create( - user=user, - book=book, - content=content, - quote=quote, - ) - - -def create_comment_from_activity(author, activity): - ''' parse an activity json blob into a status ''' - book_id = activity['inReplyToBook'] - book = get_or_create_book(book_id) - content = activity.get('content') - published = activity.get('published') - remote_id = activity['id'] - - comment = create_comment(author, book, content) - comment.published_date = published - comment.remote_id = remote_id - comment.save() - return comment - - -def create_comment(user, book, content): - ''' a book comment has been added ''' - # throws a value error if the book is not found - content = sanitize(content) - - return models.Comment.objects.create( - user=user, - book=book, - content=content, - ) - - -def get_status(remote_id): - ''' find a status in the database ''' - return models.Status.objects.select_subclasses().filter( - remote_id=remote_id - ).first() - def create_generated_note(user, content, mention_books=None): ''' a note created by the app about user activity ''' @@ -127,28 +33,6 @@ def create_generated_note(user, content, mention_books=None): return status -def create_status(user, content, reply_parent=None, mention_books=None): - ''' a status update ''' - # TODO: handle @'ing users - - # sanitize input html - parser = InputHtmlParser() - parser.feed(content) - content = parser.get_output() - - status = models.Status.objects.create( - user=user, - content=content, - reply_parent=reply_parent, - ) - - if mention_books: - for book in mention_books: - status.mention_books.add(book) - - return status - - def create_tag(user, possible_book, name): ''' add a tag to a book ''' book = get_or_create_book(possible_book) @@ -174,10 +58,3 @@ def create_notification(user, notification_type, related_user=None, \ related_import=related_import, notification_type=notification_type, ) - - -def sanitize(content): - ''' remove invalid html from free text ''' - parser = InputHtmlParser() - parser.feed(content) - return parser.get_output() diff --git a/bookwyrm/templates/snippets/create_status.html b/bookwyrm/templates/snippets/create_status.html index 88558df9..28eded97 100644 --- a/bookwyrm/templates/snippets/create_status.html +++ b/bookwyrm/templates/snippets/create_status.html @@ -22,6 +22,8 @@