From 22768324650831cc414ff09d30d2abffb75fb30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Wed, 19 Feb 2025 06:44:21 +0100 Subject: [PATCH] Return web archive fallback URL from REST API (#993) --- bookmarks/api/serializers.py | 10 +++++++++- bookmarks/tests/test_bookmarks_api.py | 25 ++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/bookmarks/api/serializers.py b/bookmarks/api/serializers.py index 153341e..124a55b 100644 --- a/bookmarks/api/serializers.py +++ b/bookmarks/api/serializers.py @@ -10,6 +10,7 @@ from bookmarks.services.bookmarks import ( enhance_with_website_metadata, ) from bookmarks.services.tags import get_or_create_tag +from bookmarks.services.wayback import generate_fallback_webarchive_url class TagListField(serializers.ListField): @@ -59,9 +60,10 @@ class BookmarkSerializer(serializers.ModelSerializer): # Custom tag_names field to allow passing a list of tag names to create/update tag_names = TagListField(required=False) - # Custom fields to return URLs for favicon and preview image + # Custom fields to generate URLs for favicon, preview image, and web archive snapshot favicon_url = serializers.SerializerMethodField() preview_image_url = serializers.SerializerMethodField() + web_archive_snapshot_url = serializers.SerializerMethodField() # Add dummy website title and description fields for backwards compatibility but keep them empty website_title = serializers.SerializerMethodField() website_description = serializers.SerializerMethodField() @@ -82,6 +84,12 @@ class BookmarkSerializer(serializers.ModelSerializer): preview_image_url = request.build_absolute_uri(preview_image_file_path) return preview_image_url + def get_web_archive_snapshot_url(self, obj: Bookmark): + if obj.web_archive_snapshot_url: + return obj.web_archive_snapshot_url + + return generate_fallback_webarchive_url(obj.url, obj.date_added) + def get_website_title(self, obj: Bookmark): return None diff --git a/bookmarks/tests/test_bookmarks_api.py b/bookmarks/tests/test_bookmarks_api.py index 2166773..c53967f 100644 --- a/bookmarks/tests/test_bookmarks_api.py +++ b/bookmarks/tests/test_bookmarks_api.py @@ -1,15 +1,18 @@ +import datetime import urllib.parse from collections import OrderedDict from unittest.mock import patch from django.contrib.auth.models import User from django.urls import reverse +from django.utils import timezone from rest_framework import status from rest_framework.authtoken.models import Token from rest_framework.response import Response from bookmarks.models import Bookmark, BookmarkSearch, UserProfile from bookmarks.services import website_loader +from bookmarks.services.wayback import generate_fallback_webarchive_url from bookmarks.services.website_loader import WebsiteMetadata from bookmarks.tests.helpers import LinkdingApiTestCase, BookmarkFactoryMixin @@ -33,7 +36,10 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin): expectation["title"] = bookmark.title expectation["description"] = bookmark.description expectation["notes"] = bookmark.notes - expectation["web_archive_snapshot_url"] = bookmark.web_archive_snapshot_url + expectation["web_archive_snapshot_url"] = ( + bookmark.web_archive_snapshot_url + or generate_fallback_webarchive_url(bookmark.url, bookmark.date_added) + ) expectation["favicon_url"] = ( f"http://testserver/static/{bookmark.favicon_file}" if bookmark.favicon_file @@ -590,6 +596,23 @@ class BookmarksApiTestCase(LinkdingApiTestCase, BookmarkFactoryMixin): response = self.get(url, expected_status_code=status.HTTP_200_OK) self.assertBookmarkListEqual([response.data], [bookmark]) + def test_get_bookmark_returns_fallback_webarchive_url(self): + self.authenticate() + bookmark = self.setup_bookmark( + web_archive_snapshot_url="", + url="https://example.com/", + added=timezone.datetime( + 2023, 8, 11, 21, 45, 11, tzinfo=datetime.timezone.utc + ), + ) + + url = reverse("bookmarks:bookmark-detail", args=[bookmark.id]) + response = self.get(url, expected_status_code=status.HTTP_200_OK) + self.assertEqual( + response.data["web_archive_snapshot_url"], + "https://web.archive.org/web/20230811214511/https://example.com/", + ) + def test_update_bookmark(self): self.authenticate() bookmark = self.setup_bookmark()