from pathlib import Path from django.contrib.auth.password_validation import validate_password from rest_framework import serializers from apps.library.services import VIDEO_EXTENSIONS from apps.library.services import signed_media_url as signed_library_url from .models import User def signed_media_url(request, item): """A signed media URL an tag can load for an authenticated user.""" if item is None: return None user = getattr(request, "user", None) if user is None or not getattr(user, "is_authenticated", False): return None location = item.locations.first() is_video = ( location is not None and Path(location.rel_path).suffix.lower() in VIDEO_EXTENSIONS ) action = "thumbnail" if is_video else "raw" return signed_library_url(item, user, action, request=request) class UserSerializer(serializers.ModelSerializer): e621_configured = serializers.BooleanField(read_only=True) can_upload = serializers.BooleanField(read_only=True) avatar_j_id = serializers.SerializerMethodField() avatar_url = serializers.SerializerMethodField() class Meta: model = User fields = [ "id", "username", "email", "is_staff", "is_superuser", "date_joined", "role", "can_upload", "avatar_j_id", "avatar_url", "e621_username", "e621_configured", "preferences", ] read_only_fields = fields def get_avatar_j_id(self, obj): return f"J-{obj.avatar_id}" if obj.avatar_id else None def get_avatar_url(self, obj): return signed_media_url(self.context.get("request"), obj.avatar) class UserListSerializer(serializers.ModelSerializer): avatar_j_id = serializers.SerializerMethodField() avatar_url = serializers.SerializerMethodField() uploads_count = serializers.IntegerField(read_only=True) class Meta: model = User fields = [ "id", "username", "email", "role", "is_staff", "is_superuser", "date_joined", "avatar_j_id", "avatar_url", "uploads_count", ] read_only_fields = fields def get_avatar_j_id(self, obj): return f"J-{obj.avatar_id}" if obj.avatar_id else None def get_avatar_url(self, obj): return signed_media_url(self.context.get("request"), obj.avatar) class UserUpdateSerializer(serializers.Serializer): avatar_j_id = serializers.CharField( required=False, allow_blank=True, allow_null=True ) role = serializers.ChoiceField(choices=User.ROLE_CHOICES, required=False) class RegisterSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True, validators=[validate_password]) class Meta: model = User fields = ["username", "email", "password"] def create(self, validated_data): return User.objects.create_user(**validated_data) class E621CredentialsSerializer(serializers.Serializer): username = serializers.CharField(max_length=100, allow_blank=True) api_key = serializers.CharField( max_length=100, allow_blank=True, trim_whitespace=True ) base_url = serializers.URLField( max_length=200, required=False, allow_blank=True ) class PreferencesSerializer(serializers.Serializer): """Per-user browse preferences; unknown keys are ignored.""" LANDING_PAGES = ["library", "online", "pools", "followed"] landing_page = serializers.ChoiceField(choices=LANDING_PAGES, required=False) ratings = serializers.ListField( child=serializers.ChoiceField(choices=["s", "q", "e"]), required=False, max_length=3, ) ordering = serializers.CharField(max_length=30, required=False) per_page = serializers.IntegerField(min_value=12, max_value=200, required=False) zoom = serializers.IntegerField(min_value=120, max_value=400, required=False) # Open Online with the order:hot metatag when no search is given. online_hot_default = serializers.BooleanField(required=False)