diff --git a/bookwyrm/views/author.py b/bookwyrm/views/author.py index c6683aaac..d25b82779 100644 --- a/bookwyrm/views/author.py +++ b/bookwyrm/views/author.py @@ -12,7 +12,7 @@ from bookwyrm import forms, models from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.connectors import connector_manager from bookwyrm.settings import PAGE_LENGTH -from bookwyrm.views.helpers import is_api_request +from bookwyrm.views.helpers import is_api_request, maybe_redirect_local_path # pylint: disable= no-self-use @@ -26,6 +26,9 @@ class Author(View): if is_api_request(request): return ActivitypubResponse(author.to_activity()) + if r := maybe_redirect_local_path(request, author): + return r + books = ( models.Work.objects.filter(Q(authors=author) | Q(editions__authors=author)) .annotate(Avg("editions__review__rating")) diff --git a/bookwyrm/views/books/books.py b/bookwyrm/views/books/books.py index 3b5021734..1e88f19f6 100644 --- a/bookwyrm/views/books/books.py +++ b/bookwyrm/views/books/books.py @@ -15,7 +15,7 @@ from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.connectors import connector_manager from bookwyrm.connectors.abstract_connector import get_image from bookwyrm.settings import PAGE_LENGTH -from bookwyrm.views.helpers import is_api_request +from bookwyrm.views.helpers import is_api_request, maybe_redirect_local_path # pylint: disable=no-self-use @@ -43,6 +43,9 @@ class Book(View): .first() ) + if r := maybe_redirect_local_path(request, book): + return r + if not book or not book.parent_work: raise Http404() diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py index 92120ea1a..fe30b0d20 100644 --- a/bookwyrm/views/feed.py +++ b/bookwyrm/views/feed.py @@ -15,7 +15,7 @@ from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH, STREAMS from bookwyrm.suggested_users import suggested_users from .helpers import filter_stream_by_status_type, get_user_from_username -from .helpers import is_api_request, is_bookwyrm_request +from .helpers import is_api_request, is_bookwyrm_request, maybe_redirect_local_path from .annual_summary import get_annual_summary_year @@ -130,6 +130,9 @@ class Status(View): status.to_activity(pure=not is_bookwyrm_request(request)) ) + if r := maybe_redirect_local_path(request, status): + return r + visible_thread = ( models.Status.privacy_filter(request.user) .filter(thread_id=status.thread_id) diff --git a/bookwyrm/views/group.py b/bookwyrm/views/group.py index 1284e9881..dca534ace 100644 --- a/bookwyrm/views/group.py +++ b/bookwyrm/views/group.py @@ -14,7 +14,7 @@ from django.db.models.functions import Greatest from bookwyrm import forms, models from bookwyrm.suggested_users import suggested_users -from .helpers import get_user_from_username +from .helpers import get_user_from_username, maybe_redirect_local_path # pylint: disable=no-self-use class Group(View): @@ -25,6 +25,10 @@ class Group(View): group = get_object_or_404(models.Group, id=group_id) group.raise_visible_to_user(request.user) + + if r := maybe_redirect_local_path(request, group): + return r + lists = ( models.List.privacy_filter(request.user) .filter(group=group) diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 74d867b66..d62812e1c 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -8,6 +8,7 @@ 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.shortcuts import redirect from django.http import Http404 from django.utils import translation @@ -201,3 +202,17 @@ def filter_stream_by_status_type(activities, allowed_types=None): ) return activities + +def maybe_redirect_local_path(request, model): + """ + if the request had an invalid path, return a permanent redirect response to the correct one, including a slug if any. + if path is valid, returns False. + """ + if request.path == model.local_path: + return False + + new_path = model.local_path + if len(request.GET) > 0: + new_path = f"{model.local_path}?{request.GET.urlencode()}" + + return redirect(new_path, permanent=True) diff --git a/bookwyrm/views/list/list.py b/bookwyrm/views/list/list.py index 6a9fd8b72..baf704707 100644 --- a/bookwyrm/views/list/list.py +++ b/bookwyrm/views/list/list.py @@ -18,7 +18,7 @@ from django.views.decorators.http import require_POST from bookwyrm import book_search, forms, models from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH -from bookwyrm.views.helpers import is_api_request +from bookwyrm.views.helpers import is_api_request, maybe_redirect_local_path # pylint: disable=no-self-use @@ -36,6 +36,9 @@ class List(View): if is_api_request(request): return ActivitypubResponse(book_list.to_activity(**request.GET)) + if r := maybe_redirect_local_path(request, book_list): + return r; + query = request.GET.get("q") suggestions = None diff --git a/bookwyrm/views/shelf/shelf.py b/bookwyrm/views/shelf/shelf.py index beeb70430..b92a79173 100644 --- a/bookwyrm/views/shelf/shelf.py +++ b/bookwyrm/views/shelf/shelf.py @@ -14,7 +14,7 @@ from django.views import View from bookwyrm import forms, models from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH -from bookwyrm.views.helpers import is_api_request, get_user_from_username +from bookwyrm.views.helpers import is_api_request, get_user_from_username, maybe_redirect_local_path # pylint: disable=no-self-use @@ -56,6 +56,9 @@ class Shelf(View): if is_api_request(request) and shelf_identifier: return ActivitypubResponse(shelf.to_activity(**request.GET)) + if r := maybe_redirect_local_path(request, shelf): + return r + reviews = models.Review.objects if not is_self: reviews = models.Review.privacy_filter(request.user)