Backend: GET /api/random/ (aliases /random and /random/) returns a random library image with: - rating=s,q,e filtering (comma separated, default any); - fastfetch mode (?fastfetch=1 or any User-Agent containing "fastfetch") that only considers png/jpg/gif - what terminal viewers can show; - JSON with j_id, filename, extension, rating, size, e621 id plus absolute url/download_url/thumbnail_url. Authenticated callers get signed URLs so fastfetch and image viewers can load them without headers; guests get unsigned URLs and never receive hidden_from_guests items. Tests: apps/library/tests/test_random.py (8 tests) covering the response contract, guest signatures, image-only default, the fastfetch format restriction (flag and User-Agent), rating filters, guest visibility and the short alias. Frontend: /random page with rating pills, R to roll, Open/Download and a library link, plus navigation and command palette entries; needs a backend, hidden in local mode. nginx: /random negotiates on Accept so browsers keep getting the SPA while scripts get the JSON (verified with the proxy and frontend containers). Also fixes a regression from the SSRF change: the guest download proxy still referenced the removed 'parsed' variable on its success path, so every proxied download would have 500'd. Redirect hops are now covered by tests with a mocked requests.get.
54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
from django.urls import include, path
|
|
from rest_framework.routers import DefaultRouter
|
|
|
|
from .tools import (
|
|
ClearTempView,
|
|
DeleteFilesView,
|
|
ExactDuplicatesView,
|
|
StorageView,
|
|
TagCloudView,
|
|
VisualGroupsView,
|
|
VisualMatchesView,
|
|
)
|
|
from .similarity import SimilarityCheckViewSet
|
|
from .uploads import TempUploadViewSet
|
|
from .views import (
|
|
ClientDownloadView,
|
|
DownloadTaskViewSet,
|
|
MatchTaskViewSet,
|
|
MediaItemViewSet,
|
|
RandomItemView,
|
|
)
|
|
|
|
router = DefaultRouter()
|
|
router.register("files", MediaItemViewSet, basename="file")
|
|
router.register("uploads", TempUploadViewSet, basename="upload")
|
|
router.register("online/downloads", DownloadTaskViewSet, basename="download")
|
|
router.register("matches", MatchTaskViewSet, basename="match")
|
|
router.register("similarity", SimilarityCheckViewSet, basename="similarity")
|
|
|
|
urlpatterns = [
|
|
path("", include(router.urls)),
|
|
path("random/", RandomItemView.as_view(), name="random_item"),
|
|
path("online/file/", ClientDownloadView.as_view(), name="client_download"),
|
|
path(
|
|
"duplicates/md5/",
|
|
ExactDuplicatesView.as_view(),
|
|
name="duplicates_md5",
|
|
),
|
|
path(
|
|
"duplicates/visual/",
|
|
VisualMatchesView.as_view(),
|
|
name="duplicates_visual",
|
|
),
|
|
path(
|
|
"duplicates/visual_groups/",
|
|
VisualGroupsView.as_view(),
|
|
name="duplicates_groups",
|
|
),
|
|
path("delete/", DeleteFilesView.as_view(), name="delete_files"),
|
|
path("temp/clear/", ClearTempView.as_view(), name="clear_temp"),
|
|
path("tags/cloud/", TagCloudView.as_view(), name="tag_cloud"),
|
|
path("storage/", StorageView.as_view(), name="storage_info"),
|
|
]
|