From 0b0de12968525122fb6e8518f7a56dad3cff3196 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 30 Oct 2020 11:21:02 -0700 Subject: [PATCH] Allow users to set privacy on imported reviews or not import them at all. Fixes #252 --- bookwyrm/goodreads_import.py | 14 +++++++---- .../migrations/0059_auto_20201030_1755.py | 23 +++++++++++++++++++ bookwyrm/models/base_model.py | 8 +++++++ bookwyrm/models/import_job.py | 8 +++++++ bookwyrm/models/status.py | 9 +------- bookwyrm/outgoing.py | 7 +++--- bookwyrm/templates/import.html | 20 ++++++++++++++-- bookwyrm/view_actions.py | 6 ++++- 8 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 bookwyrm/migrations/0059_auto_20201030_1755.py diff --git a/bookwyrm/goodreads_import.py b/bookwyrm/goodreads_import.py index 73057e43..9e2bcd1d 100644 --- a/bookwyrm/goodreads_import.py +++ b/bookwyrm/goodreads_import.py @@ -11,9 +11,13 @@ from bookwyrm.status import create_notification MAX_ENTRIES = 500 -def create_job(user, csv_file): +def create_job(user, csv_file, include_reviews, privacy): ''' check over a csv and creates a database entry for the job''' - job = ImportJob.objects.create(user=user) + job = ImportJob.objects.create( + user=user, + include_reviews=include_reviews, + privacy=privacy + ) for index, entry in enumerate(list(csv.DictReader(csv_file))[:MAX_ENTRIES]): if not all(x in entry for x in ('ISBN13', 'Title', 'Author')): raise ValueError("Author, title, and isbn must be in data.") @@ -42,8 +46,10 @@ def import_data(job_id): if item.book: item.save() results.append(item) - # shelves book and handles reviews - outgoing.handle_imported_book(job.user, item) + + if job.include_reviews: + # shelves book and handles reviews + outgoing.handle_imported_book(job.user, item, job.privacy) else: item.fail_reason = "Could not find a match for book" item.save() diff --git a/bookwyrm/migrations/0059_auto_20201030_1755.py b/bookwyrm/migrations/0059_auto_20201030_1755.py new file mode 100644 index 00000000..9004ed2f --- /dev/null +++ b/bookwyrm/migrations/0059_auto_20201030_1755.py @@ -0,0 +1,23 @@ +# Generated by Django 3.0.7 on 2020-10-30 17:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0058_remove_importjob_import_status'), + ] + + operations = [ + migrations.AddField( + model_name='importjob', + name='include_reviews', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='importjob', + name='privacy', + field=models.CharField(choices=[('public', 'Public'), ('unlisted', 'Unlisted'), ('followers', 'Followers'), ('direct', 'Direct')], default='public', max_length=255), + ), + ] diff --git a/bookwyrm/models/base_model.py b/bookwyrm/models/base_model.py index 978c3d1e..d5f4a899 100644 --- a/bookwyrm/models/base_model.py +++ b/bookwyrm/models/base_model.py @@ -14,6 +14,14 @@ from django.dispatch import receiver from bookwyrm import activitypub from bookwyrm.settings import DOMAIN + +PrivacyLevels = models.TextChoices('Privacy', [ + 'public', + 'unlisted', + 'followers', + 'direct' +]) + class BookWyrmModel(models.Model): ''' shared fields ''' created_date = models.DateTimeField(auto_now_add=True) diff --git a/bookwyrm/models/import_job.py b/bookwyrm/models/import_job.py index 54b6c438..f7b5e8a2 100644 --- a/bookwyrm/models/import_job.py +++ b/bookwyrm/models/import_job.py @@ -9,6 +9,8 @@ from bookwyrm import books_manager from bookwyrm.connectors import ConnectorException from bookwyrm.models import ReadThrough, User, Book from bookwyrm.utils.fields import JSONField +from .base_model import PrivacyLevels + # Mapping goodreads -> bookwyrm shelf titles. GOODREADS_SHELVES = { @@ -40,6 +42,12 @@ class ImportJob(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) created_date = models.DateTimeField(default=timezone.now) task_id = models.CharField(max_length=100, null=True) + include_reviews = models.BooleanField(default=True) + privacy = models.CharField( + max_length=255, + default='public', + choices=PrivacyLevels.choices + ) class ImportItem(models.Model): diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index b1283c9d..533868e8 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -7,16 +7,9 @@ from model_utils.managers import InheritanceManager from bookwyrm import activitypub from .base_model import ActivitypubMixin, OrderedCollectionPageMixin -from .base_model import ActivityMapping, BookWyrmModel +from .base_model import ActivityMapping, BookWyrmModel, PrivacyLevels -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) diff --git a/bookwyrm/outgoing.py b/bookwyrm/outgoing.py index eca3a2c8..2ff8c9fa 100644 --- a/bookwyrm/outgoing.py +++ b/bookwyrm/outgoing.py @@ -155,7 +155,7 @@ def handle_unshelve(user, book, shelf): broadcast(user, activity) -def handle_imported_book(user, item): +def handle_imported_book(user, item, privacy): ''' process a goodreads csv and then post about it ''' if isinstance(item.book, models.Work): item.book = item.book.default_edition @@ -171,7 +171,7 @@ def handle_imported_book(user, item): shelf_book, created = models.ShelfBook.objects.get_or_create( book=item.book, shelf=desired_shelf, added_by=user) if created: - broadcast(user, shelf_book.to_add_activity(user)) + broadcast(user, shelf_book.to_add_activity(user), privacy=privacy) # only add new read-throughs if the item isn't already shelved for read in item.reads: @@ -194,10 +194,11 @@ def handle_imported_book(user, item): content=item.review, rating=item.rating, published_date=published_date_guess, + privacy=privacy, ) # we don't need to send out pure activities because non-bookwyrm # instances don't need this data - broadcast(user, review.to_create_activity(user)) + broadcast(user, review.to_create_activity(user), privacy=privacy) def handle_delete_status(user, status): diff --git a/bookwyrm/templates/import.html b/bookwyrm/templates/import.html index 3b8708be..414ba59e 100644 --- a/bookwyrm/templates/import.html +++ b/bookwyrm/templates/import.html @@ -5,8 +5,24 @@

Import Books from GoodReads

{% csrf_token %} - {{ import_form.as_p }} - +
+ {{ import_form.as_p }} +
+
+ +
+
+ +
+ +
+
+

Imports are limited in size, and only the first {{ limit }} items will be imported. diff --git a/bookwyrm/view_actions.py b/bookwyrm/view_actions.py index c3c93784..299ead10 100644 --- a/bookwyrm/view_actions.py +++ b/bookwyrm/view_actions.py @@ -491,12 +491,16 @@ def import_data(request): ''' ingest a goodreads csv ''' form = forms.ImportForm(request.POST, request.FILES) if form.is_valid(): + include_reviews = request.POST.get('include_reviews') == 'on' + privacy = request.POST.get('privacy') try: job = goodreads_import.create_job( request.user, TextIOWrapper( request.FILES['csv_file'], - encoding=request.encoding) + encoding=request.encoding), + include_reviews, + privacy, ) except (UnicodeDecodeError, ValueError): return HttpResponseBadRequest('Not a valid csv file')