diff --git a/backend/download/serializers.py b/backend/download/serializers.py index 7ced40ac..43c24cc1 100644 --- a/backend/download/serializers.py +++ b/backend/download/serializers.py @@ -4,6 +4,7 @@ from common.serializers import PaginationSerializer, ValidateUnknownFieldsMixin from rest_framework import serializers +from video.src.constants import VideoTypeEnum class DownloadItemSerializer(serializers.Serializer): @@ -19,9 +20,7 @@ class DownloadItemSerializer(serializers.Serializer): timestamp = serializers.IntegerField() title = serializers.CharField() vid_thumb_url = serializers.CharField() - vid_type = serializers.ChoiceField( - choices=["videos", "streams", "shorts", "unknown"] - ) + vid_type = serializers.ChoiceField(choices=VideoTypeEnum.values()) youtube_id = serializers.CharField() _index = serializers.CharField(required=False) _score = serializers.IntegerField(required=False) diff --git a/backend/user/serializers.py b/backend/user/serializers.py index 1b8f0fca..e8314b98 100644 --- a/backend/user/serializers.py +++ b/backend/user/serializers.py @@ -2,8 +2,10 @@ # pylint: disable=abstract-method +from common.src.helper import get_stylesheets from rest_framework import serializers from user.models import Account +from video.src.constants import OrderEnum, SortEnum class AccountSerializer(serializers.ModelSerializer): @@ -25,24 +27,15 @@ class AccountSerializer(serializers.ModelSerializer): class UserMeConfigSerializer(serializers.Serializer): """serialize user me config""" - stylesheet = serializers.CharField() + stylesheet = serializers.ChoiceField(choices=get_stylesheets()) page_size = serializers.IntegerField() - sort_by = serializers.ChoiceField( - choices=[ - "published", - "downloaded", - "views", - "likes", - "duration", - "filesize", - ] - ) - sort_order = serializers.ChoiceField(choices=["asc", "desc"]) + sort_by = serializers.ChoiceField(choices=SortEnum.names()) + sort_order = serializers.ChoiceField(choices=OrderEnum.values()) view_style_home = serializers.ChoiceField(choices=["grid", "list"]) view_style_channel = serializers.ChoiceField(choices=["grid", "list"]) view_style_downloads = serializers.ChoiceField(choices=["grid", "list"]) view_style_playlist = serializers.ChoiceField(choices=["grid", "list"]) - grid_items = serializers.IntegerField() + grid_items = serializers.IntegerField(max_value=7, min_value=3) hide_watched = serializers.BooleanField() show_ignored_only = serializers.BooleanField() show_subed_only = serializers.BooleanField() diff --git a/backend/user/src/user_config.py b/backend/user/src/user_config.py index 47cbaf80..a85ce5e3 100644 --- a/backend/user/src/user_config.py +++ b/backend/user/src/user_config.py @@ -7,7 +7,6 @@ Functionality: from typing import TypedDict from common.src.es_connect import ElasticWrap -from common.src.helper import get_stylesheets class UserConfigType(TypedDict, total=False): @@ -29,7 +28,10 @@ class UserConfigType(TypedDict, total=False): class UserConfig: - """Handle settings for an individual user""" + """ + Handle settings for an individual user + items are expected to be validated in the serializer + """ _DEFAULT_USER_SETTINGS = UserConfigType( stylesheet="dark.css", @@ -47,19 +49,6 @@ class UserConfig: show_help_text=True, ) - VALID_STYLESHEETS = get_stylesheets() - VALID_VIEW_STYLE = ["grid", "list"] - VALID_SORT_ORDER = ["asc", "desc"] - VALID_SORT_BY = [ - "published", - "downloaded", - "views", - "likes", - "duration", - "filesize", - ] - VALID_GRID_ITEMS = range(3, 8) - def __init__(self, user_id: str): self._user_id: str = user_id self._config: UserConfigType = self.get_config() @@ -84,7 +73,6 @@ class UserConfig: def set_value(self, key: str, value: str | bool | int): """Set or replace a configuration value for the user""" - self._validate(key, value) data = {"doc": {"config": {key: value}}} response, status = ElasticWrap(self.es_update_url).post(data) if status < 200 or status > 299: @@ -92,43 +80,6 @@ class UserConfig: print(f"User {self._user_id} value '{key}' change: to {value}") - def _validate(self, key, value): - """validate key and value""" - if not self._user_id: - raise ValueError("Unable to persist config for null user_id") - - if key not in self._DEFAULT_USER_SETTINGS: - raise KeyError( - f"Unable to persist config for an unknown key '{key}'" - ) - - valid_values = { - "stylesheet": self.VALID_STYLESHEETS, - "sort_by": self.VALID_SORT_BY, - "sort_order": self.VALID_SORT_ORDER, - "view_style_home": self.VALID_VIEW_STYLE, - "view_style_channel": self.VALID_VIEW_STYLE, - "view_style_download": self.VALID_VIEW_STYLE, - "view_style_playlist": self.VALID_VIEW_STYLE, - "grid_items": self.VALID_GRID_ITEMS, - "page_size": int, - "hide_watched": bool, - "show_ignored_only": bool, - "show_subed_only": bool, - "show_help_text": bool, - } - validation_value = valid_values.get(key) - - if isinstance(validation_value, (list, range)): - if value not in validation_value: - raise ValueError(f"Invalid value for {key}: {value}") - elif validation_value == int: - if not isinstance(value, int): - raise ValueError(f"Invalid value for {key}: {value}") - elif validation_value == bool: - if not isinstance(value, bool): - raise ValueError(f"Invalid value for {key}: {value}") - def get_config(self) -> UserConfigType: """get config from ES or load from the application defaults""" if not self._user_id: diff --git a/backend/video/serializers.py b/backend/video/serializers.py index 1efdb3c2..33cfd24a 100644 --- a/backend/video/serializers.py +++ b/backend/video/serializers.py @@ -5,6 +5,7 @@ from channel.serializers import ChannelSerializer from common.serializers import PaginationSerializer from rest_framework import serializers +from video.src.constants import OrderEnum, SortEnum, VideoTypeEnum, WatchedEnum class PlayerSerializer(serializers.Serializer): @@ -91,7 +92,7 @@ class VideoSerializer(serializers.Serializer): title = serializers.CharField() vid_last_refresh = serializers.CharField() vid_thumb_url = serializers.CharField() - vid_type = serializers.ChoiceField(choices=["video", "stream", "short"]) + vid_type = serializers.ChoiceField(choices=VideoTypeEnum.values_known()) youtube_id = serializers.CharField() _index = serializers.CharField(required=False) _score = serializers.FloatField(required=False) @@ -110,22 +111,12 @@ class VideoListQuerySerializer(serializers.Serializer): playlist = serializers.CharField(required=False) channel = serializers.CharField(required=False) watch = serializers.ChoiceField( - choices=["watched", "unwatched", "continue"], required=False + choices=WatchedEnum.values(), required=False ) - sort = serializers.ChoiceField( - choices=[ - "published", - "downloaded", - "views", - "likes", - "duration", - "filesize", - ], - required=False, - ) - order = serializers.ChoiceField(choices=["asc", "desc"], required=False) + sort = serializers.ChoiceField(choices=SortEnum.names(), required=False) + order = serializers.ChoiceField(choices=OrderEnum.values(), required=False) type = serializers.ChoiceField( - choices=["videos", "streams", "shorts"], required=False + choices=VideoTypeEnum.values_known(), required=False ) diff --git a/backend/video/src/constants.py b/backend/video/src/constants.py index 39dcfff3..12fc4b23 100644 --- a/backend/video/src/constants.py +++ b/backend/video/src/constants.py @@ -11,6 +11,16 @@ class VideoTypeEnum(enum.Enum): SHORTS = "shorts" UNKNOWN = "unknown" + @classmethod + def values(cls) -> list[str]: + """value list""" + return [i.value for i in cls] + + @classmethod + def values_known(cls) -> list[str]: + """values known""" + return [i.value for i in cls if i.value != "unknown"] + class SortEnum(enum.Enum): """all sort by options""" @@ -22,9 +32,37 @@ class SortEnum(enum.Enum): DURATION = "player.duration" MEDIASIZE = "media_size" + @classmethod + def values(cls) -> list[str]: + """value list""" + return [i.value for i in cls] + + @classmethod + def names(cls) -> list[str]: + """name list""" + return [i.name.lower() for i in cls] + class OrderEnum(enum.Enum): """all order by options""" ASC = "asc" DESC = "desc" + + @classmethod + def values(cls) -> list[str]: + """value list""" + return [i.value for i in cls] + + +class WatchedEnum(enum.Enum): + """watched state enum""" + + WATCHED = "watched" + UNWATCHED = "unwatched" + CONTINUE = "continue" + + @classmethod + def values(cls) -> list[str]: + """value list""" + return [i.value for i in cls]