From 7555d76c3ffd7674bcfecbbaf2624cabd3f78870 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Wed, 13 Jan 2021 12:33:48 -0800 Subject: [PATCH] Adds reading acitivity views --- bookwyrm/outgoing.py | 10 +-- bookwyrm/urls.py | 12 +-- bookwyrm/view_actions.py | 158 ---------------------------------- bookwyrm/views/__init__.py | 2 + bookwyrm/views/reading.py | 171 +++++++++++++++++++++++++++++++++++++ bookwyrm/views/shelf.py | 4 +- 6 files changed, 182 insertions(+), 175 deletions(-) create mode 100644 bookwyrm/views/reading.py diff --git a/bookwyrm/outgoing.py b/bookwyrm/outgoing.py index 18c1eaea..9b259012 100644 --- a/bookwyrm/outgoing.py +++ b/bookwyrm/outgoing.py @@ -1,23 +1,15 @@ ''' handles all the activity coming out of the server ''' -import re - -from django.db import IntegrityError, transaction +from django.db import transaction from django.http import JsonResponse from django.shortcuts import get_object_or_404 from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_GET -from markdown import markdown from requests import HTTPError from bookwyrm import activitypub from bookwyrm import models from bookwyrm.connectors import get_data, ConnectorException from bookwyrm.broadcast import broadcast -from bookwyrm.sanitize_html import InputHtmlParser -from bookwyrm.status import create_notification -from bookwyrm.status import create_generated_note -from bookwyrm.settings import DOMAIN -from bookwyrm.utils import regex @csrf_exempt diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index ee70ae2a..96fcd2c5 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -119,13 +119,15 @@ urlpatterns = [ re_path(r'^shelve/?$', views.shelve), re_path(r'^unshelve/?$', views.unshelve), - re_path(r'^edit-readthrough/?$', actions.edit_readthrough), - re_path(r'^delete-readthrough/?$', actions.delete_readthrough), - re_path(r'^create-readthrough/?$', actions.create_readthrough), + # reading progress + re_path(r'^edit-readthrough/?$', views.edit_readthrough), + re_path(r'^delete-readthrough/?$', views.delete_readthrough), + re_path(r'^create-readthrough/?$', views.create_readthrough), - re_path(r'^start-reading/(?P\d+)/?$', actions.start_reading), - re_path(r'^finish-reading/(?P\d+)/?$', actions.finish_reading), + re_path(r'^start-reading/(?P\d+)/?$', views.start_reading), + re_path(r'^finish-reading/(?P\d+)/?$', views.finish_reading), + # following re_path(r'^follow/?$', actions.follow), re_path(r'^unfollow/?$', actions.unfollow), re_path(r'^accept-follow-request/?$', actions.accept_follow_request), diff --git a/bookwyrm/view_actions.py b/bookwyrm/view_actions.py index 20e4f300..50506203 100644 --- a/bookwyrm/view_actions.py +++ b/bookwyrm/view_actions.py @@ -1,11 +1,7 @@ ''' views for actions you can take in the application ''' -import dateutil.parser -from dateutil.parser import ParserError - from django.contrib.auth.decorators import login_required from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.shortcuts import get_object_or_404, redirect -from django.utils import timezone from django.views.decorators.http import require_POST from bookwyrm import models, outgoing @@ -25,122 +21,6 @@ def get_user_from_username(username): except models.User.DoesNotExist: return models.User.objects.get(username=username) - -@login_required -@require_POST -def start_reading(request, book_id): - ''' begin reading a book ''' - book = get_edition(book_id) - shelf = models.Shelf.objects.filter( - identifier='reading', - user=request.user - ).first() - - # create a readthrough - readthrough = update_readthrough(request, book=book) - if readthrough.start_date: - readthrough.save() - - # shelve the book - if request.POST.get('reshelve', True): - try: - current_shelf = models.Shelf.objects.get( - user=request.user, - edition=book - ) - outgoing.handle_unshelve(request.user, book, current_shelf) - except models.Shelf.DoesNotExist: - # this just means it isn't currently on the user's shelves - pass - outgoing.handle_shelve(request.user, book, shelf) - - # post about it (if you want) - if request.POST.get('post-status'): - privacy = request.POST.get('privacy') - outgoing.handle_reading_status(request.user, shelf, book, privacy) - - return redirect(request.headers.get('Referer', '/')) - - -@login_required -@require_POST -def finish_reading(request, book_id): - ''' a user completed a book, yay ''' - book = get_edition(book_id) - shelf = models.Shelf.objects.filter( - identifier='read', - user=request.user - ).first() - - # update or create a readthrough - readthrough = update_readthrough(request, book=book) - if readthrough.start_date or readthrough.finish_date: - readthrough.save() - - # shelve the book - if request.POST.get('reshelve', True): - try: - current_shelf = models.Shelf.objects.get( - user=request.user, - edition=book - ) - outgoing.handle_unshelve(request.user, book, current_shelf) - except models.Shelf.DoesNotExist: - # this just means it isn't currently on the user's shelves - pass - outgoing.handle_shelve(request.user, book, shelf) - - # post about it (if you want) - if request.POST.get('post-status'): - privacy = request.POST.get('privacy') - outgoing.handle_reading_status(request.user, shelf, book, privacy) - - return redirect(request.headers.get('Referer', '/')) - - -@login_required -@require_POST -def edit_readthrough(request): - ''' can't use the form because the dates are too finnicky ''' - readthrough = update_readthrough(request, create=False) - if not readthrough: - return HttpResponseNotFound() - - # don't let people edit other people's data - if request.user != readthrough.user: - return HttpResponseBadRequest() - readthrough.save() - - return redirect(request.headers.get('Referer', '/')) - - -@login_required -@require_POST -def delete_readthrough(request): - ''' remove a readthrough ''' - readthrough = get_object_or_404( - models.ReadThrough, id=request.POST.get('id')) - - # don't let people edit other people's data - if request.user != readthrough.user: - return HttpResponseBadRequest() - - readthrough.delete() - return redirect(request.headers.get('Referer', '/')) - - -@login_required -@require_POST -def create_readthrough(request): - ''' can't use the form because the dates are too finnicky ''' - book = get_object_or_404(models.Edition, id=request.POST.get('book')) - readthrough = update_readthrough(request, create=True, book=book) - if not readthrough: - return redirect(book.local_path) - readthrough.save() - return redirect(request.headers.get('Referer', '/')) - - @login_required @require_POST def follow(request): @@ -217,41 +97,3 @@ def delete_follow_request(request): outgoing.handle_reject(follow_request) return redirect('/user/%s' % request.user.localname) - - -def update_readthrough(request, book=None, create=True): - ''' updates but does not save dates on a readthrough ''' - try: - read_id = request.POST.get('id') - if not read_id: - raise models.ReadThrough.DoesNotExist - readthrough = models.ReadThrough.objects.get(id=read_id) - except models.ReadThrough.DoesNotExist: - if not create or not book: - return None - readthrough = models.ReadThrough( - user=request.user, - book=book, - ) - - start_date = request.POST.get('start_date') - if start_date: - try: - start_date = timezone.make_aware(dateutil.parser.parse(start_date)) - readthrough.start_date = start_date - except ParserError: - pass - - finish_date = request.POST.get('finish_date') - if finish_date: - try: - finish_date = timezone.make_aware( - dateutil.parser.parse(finish_date)) - readthrough.finish_date = finish_date - except ParserError: - pass - - if not readthrough.start_date and not readthrough.finish_date: - return None - - return readthrough diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 62b046a3..38b03f48 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -10,6 +10,8 @@ from .interaction import Favorite, Unfavorite, Boost, Unboost from .invite import ManageInvites, Invite from .landing import About, Home, Feed, Discover from .notifications import Notifications +from .reading import edit_readthrough, create_readthrough, delete_readthrough +from .reading import start_reading, finish_reading from .password import PasswordResetRequest, PasswordReset, ChangePassword from .tag import Tag, AddTag, RemoveTag from .search import Search diff --git a/bookwyrm/views/reading.py b/bookwyrm/views/reading.py new file mode 100644 index 00000000..51fb2419 --- /dev/null +++ b/bookwyrm/views/reading.py @@ -0,0 +1,171 @@ +''' the good stuff! the books! ''' +import dateutil.parser +from dateutil.parser import ParserError + +from django.contrib.auth.decorators import login_required +from django.http import HttpResponseBadRequest, HttpResponseNotFound +from django.shortcuts import get_object_or_404, redirect +from django.utils import timezone +from django.views.decorators.http import require_POST + +from bookwyrm import models +from bookwyrm.broadcast import broadcast +from .helpers import get_edition, handle_reading_status, handle_unshelve + + +# pylint: disable= no-self-use +@login_required +@require_POST +def start_reading(request, book_id): + ''' begin reading a book ''' + book = get_edition(book_id) + shelf = models.Shelf.objects.filter( + identifier='reading', + user=request.user + ).first() + + # create a readthrough + readthrough = update_readthrough(request, book=book) + if readthrough.start_date: + readthrough.save() + + # shelve the book + if request.POST.get('reshelve', True): + try: + current_shelf = models.Shelf.objects.get( + user=request.user, + edition=book + ) + handle_unshelve(request.user, book, current_shelf) + except models.Shelf.DoesNotExist: + # this just means it isn't currently on the user's shelves + pass + shelfbook = models.ShelfBook.objects.create( + book=book, shelf=shelf, added_by=request.user) + broadcast(request.user, shelfbook.to_add_activity(request.user)) + + # post about it (if you want) + if request.POST.get('post-status'): + privacy = request.POST.get('privacy') + handle_reading_status(request.user, shelf, book, privacy) + + return redirect(request.headers.get('Referer', '/')) + + +@login_required +@require_POST +def finish_reading(request, book_id): + ''' a user completed a book, yay ''' + book = get_edition(book_id) + shelf = models.Shelf.objects.filter( + identifier='read', + user=request.user + ).first() + + # update or create a readthrough + readthrough = update_readthrough(request, book=book) + if readthrough.start_date or readthrough.finish_date: + readthrough.save() + + # shelve the book + if request.POST.get('reshelve', True): + try: + current_shelf = models.Shelf.objects.get( + user=request.user, + edition=book + ) + handle_unshelve(request.user, book, current_shelf) + except models.Shelf.DoesNotExist: + # this just means it isn't currently on the user's shelves + pass + shelfbook = models.ShelfBook.objects.create( + book=book, shelf=shelf, added_by=request.user) + broadcast(request.user, shelfbook.to_add_activity(request.user)) + + # post about it (if you want) + if request.POST.get('post-status'): + privacy = request.POST.get('privacy') + handle_reading_status(request.user, shelf, book, privacy) + + return redirect(request.headers.get('Referer', '/')) + + +@login_required +@require_POST +def edit_readthrough(request): + ''' can't use the form because the dates are too finnicky ''' + readthrough = update_readthrough(request, create=False) + if not readthrough: + return HttpResponseNotFound() + + # don't let people edit other people's data + if request.user != readthrough.user: + return HttpResponseBadRequest() + readthrough.save() + + return redirect(request.headers.get('Referer', '/')) + + +@login_required +@require_POST +def delete_readthrough(request): + ''' remove a readthrough ''' + readthrough = get_object_or_404( + models.ReadThrough, id=request.POST.get('id')) + + # don't let people edit other people's data + if request.user != readthrough.user: + return HttpResponseBadRequest() + + readthrough.delete() + return redirect(request.headers.get('Referer', '/')) + + +@login_required +@require_POST +def create_readthrough(request): + ''' can't use the form because the dates are too finnicky ''' + book = get_object_or_404(models.Edition, id=request.POST.get('book')) + readthrough = update_readthrough(request, create=True, book=book) + if not readthrough: + return redirect(book.local_path) + readthrough.save() + return redirect(request.headers.get('Referer', '/')) + + +def update_readthrough(request, book=None, create=True): + ''' updates but does not save dates on a readthrough ''' + try: + read_id = request.POST.get('id') + if not read_id: + raise models.ReadThrough.DoesNotExist + readthrough = models.ReadThrough.objects.get(id=read_id) + except models.ReadThrough.DoesNotExist: + if not create or not book: + return None + readthrough = models.ReadThrough( + user=request.user, + book=book, + ) + + start_date = request.POST.get('start_date') + if start_date: + try: + start_date = timezone.make_aware(dateutil.parser.parse(start_date)) + readthrough.start_date = start_date + except ParserError: + pass + + finish_date = request.POST.get('finish_date') + if finish_date: + try: + finish_date = timezone.make_aware( + dateutil.parser.parse(finish_date)) + readthrough.finish_date = finish_date + except ParserError: + pass + + if not readthrough.start_date and not readthrough.finish_date: + return None + + return readthrough diff --git a/bookwyrm/views/shelf.py b/bookwyrm/views/shelf.py index 968f0cbe..ce836955 100644 --- a/bookwyrm/views/shelf.py +++ b/bookwyrm/views/shelf.py @@ -134,10 +134,8 @@ def shelve(request): except models.Shelf.DoesNotExist: # this just means it isn't currently on the user's shelves pass - shelfbook = models.ShelfBook( + shelfbook = models.ShelfBook.objects.create( book=book, shelf=desired_shelf, added_by=request.user) - shelfbook.save() - broadcast(request.user, shelfbook.to_add_activity(request.user)) # post about "want to read" shelves