Roles: - JakeBreathild is now staff + superuser (the real account); the 'jake' smoke-test account was demoted to a regular user - /me exposes is_superuser and the account page shows an admin badge e621 metadata: - MediaItem gains e621_post_id and e621_data (trimmed post payload: tags by category, rating, score, favourites, comments, sources, description, pools, relationships, file info, uploader) - Download to Library accepts the post payload from the SPA and stores it; the item's custom rating is seeded from the e621 rating when empty - Library detail shows an e621 metadata card: link to the in-app post, score/favourites/comments, taxonomy-coloured tags, DText description, sources and pools; grid cards get an e621 badge and fall back to the e621 rating for their colour (display_rating) - Guest visibility now also considers e621 tags, so downloaded explicit content is hidden from anonymous visitors
95 lines
2.8 KiB
Python
95 lines
2.8 KiB
Python
import os
|
|
|
|
from rest_framework import serializers
|
|
|
|
from .models import MediaItem, MediaLocation
|
|
from .services import VIDEO_EXTENSIONS
|
|
|
|
|
|
class MediaLocationSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = MediaLocation
|
|
fields = ["id", "path", "rel_path", "mtime"]
|
|
|
|
|
|
class MediaItemSerializer(serializers.ModelSerializer):
|
|
tags = serializers.ListField(
|
|
child=serializers.CharField(max_length=100), required=False
|
|
)
|
|
rating = serializers.ChoiceField(choices=["", "s", "q", "e"], required=False)
|
|
locations = MediaLocationSerializer(many=True, read_only=True)
|
|
j_id = serializers.SerializerMethodField()
|
|
display_rating = serializers.SerializerMethodField()
|
|
filename = serializers.SerializerMethodField()
|
|
extension = serializers.SerializerMethodField()
|
|
kind = serializers.SerializerMethodField()
|
|
uploaded_by = serializers.SerializerMethodField()
|
|
uploaded_by_id = serializers.IntegerField(read_only=True)
|
|
|
|
class Meta:
|
|
model = MediaItem
|
|
fields = [
|
|
"id",
|
|
"j_id",
|
|
"md5",
|
|
"size",
|
|
"rating",
|
|
"display_rating",
|
|
"tags",
|
|
"notes",
|
|
"filename",
|
|
"extension",
|
|
"kind",
|
|
"uploaded_by",
|
|
"uploaded_by_id",
|
|
"e621_post_id",
|
|
"e621_data",
|
|
"locations",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
read_only_fields = [
|
|
"id",
|
|
"j_id",
|
|
"md5",
|
|
"size",
|
|
"display_rating",
|
|
"filename",
|
|
"extension",
|
|
"kind",
|
|
"uploaded_by",
|
|
"uploaded_by_id",
|
|
"e621_post_id",
|
|
"e621_data",
|
|
"locations",
|
|
"created_at",
|
|
"updated_at",
|
|
]
|
|
|
|
def get_j_id(self, obj):
|
|
return f"J-{obj.id}"
|
|
|
|
def get_display_rating(self, obj):
|
|
if obj.rating:
|
|
return obj.rating
|
|
data = obj.e621_data or {}
|
|
rating = data.get("rating") if isinstance(data, dict) else None
|
|
return rating if rating in {"s", "q", "e"} else ""
|
|
|
|
def get_uploaded_by(self, obj):
|
|
return obj.uploaded_by.username if obj.uploaded_by else None
|
|
|
|
def _first_location(self, obj):
|
|
locations = list(obj.locations.all())
|
|
return locations[0] if locations else None
|
|
|
|
def get_filename(self, obj):
|
|
location = self._first_location(obj)
|
|
return os.path.basename(location.rel_path) if location else obj.md5
|
|
|
|
def get_extension(self, obj):
|
|
return os.path.splitext(self.get_filename(obj))[1].lstrip(".").lower()
|
|
|
|
def get_kind(self, obj):
|
|
return "video" if "." + self.get_extension(obj) in VIDEO_EXTENSIONS else "image"
|