mirror of
https://git.vectorsigma.ru/public/tubearchivist.git
synced 2026-08-08 21:30:59 +00:00
use enums for validation
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from common.serializers import PaginationSerializer, ValidateUnknownFieldsMixin
|
from common.serializers import PaginationSerializer, ValidateUnknownFieldsMixin
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from video.src.constants import VideoTypeEnum
|
||||||
|
|
||||||
|
|
||||||
class DownloadItemSerializer(serializers.Serializer):
|
class DownloadItemSerializer(serializers.Serializer):
|
||||||
@@ -19,9 +20,7 @@ class DownloadItemSerializer(serializers.Serializer):
|
|||||||
timestamp = serializers.IntegerField()
|
timestamp = serializers.IntegerField()
|
||||||
title = serializers.CharField()
|
title = serializers.CharField()
|
||||||
vid_thumb_url = serializers.CharField()
|
vid_thumb_url = serializers.CharField()
|
||||||
vid_type = serializers.ChoiceField(
|
vid_type = serializers.ChoiceField(choices=VideoTypeEnum.values())
|
||||||
choices=["videos", "streams", "shorts", "unknown"]
|
|
||||||
)
|
|
||||||
youtube_id = serializers.CharField()
|
youtube_id = serializers.CharField()
|
||||||
_index = serializers.CharField(required=False)
|
_index = serializers.CharField(required=False)
|
||||||
_score = serializers.IntegerField(required=False)
|
_score = serializers.IntegerField(required=False)
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
# pylint: disable=abstract-method
|
# pylint: disable=abstract-method
|
||||||
|
|
||||||
|
from common.src.helper import get_stylesheets
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from user.models import Account
|
from user.models import Account
|
||||||
|
from video.src.constants import OrderEnum, SortEnum
|
||||||
|
|
||||||
|
|
||||||
class AccountSerializer(serializers.ModelSerializer):
|
class AccountSerializer(serializers.ModelSerializer):
|
||||||
@@ -25,24 +27,15 @@ class AccountSerializer(serializers.ModelSerializer):
|
|||||||
class UserMeConfigSerializer(serializers.Serializer):
|
class UserMeConfigSerializer(serializers.Serializer):
|
||||||
"""serialize user me config"""
|
"""serialize user me config"""
|
||||||
|
|
||||||
stylesheet = serializers.CharField()
|
stylesheet = serializers.ChoiceField(choices=get_stylesheets())
|
||||||
page_size = serializers.IntegerField()
|
page_size = serializers.IntegerField()
|
||||||
sort_by = serializers.ChoiceField(
|
sort_by = serializers.ChoiceField(choices=SortEnum.names())
|
||||||
choices=[
|
sort_order = serializers.ChoiceField(choices=OrderEnum.values())
|
||||||
"published",
|
|
||||||
"downloaded",
|
|
||||||
"views",
|
|
||||||
"likes",
|
|
||||||
"duration",
|
|
||||||
"filesize",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
sort_order = serializers.ChoiceField(choices=["asc", "desc"])
|
|
||||||
view_style_home = serializers.ChoiceField(choices=["grid", "list"])
|
view_style_home = serializers.ChoiceField(choices=["grid", "list"])
|
||||||
view_style_channel = serializers.ChoiceField(choices=["grid", "list"])
|
view_style_channel = serializers.ChoiceField(choices=["grid", "list"])
|
||||||
view_style_downloads = serializers.ChoiceField(choices=["grid", "list"])
|
view_style_downloads = serializers.ChoiceField(choices=["grid", "list"])
|
||||||
view_style_playlist = 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()
|
hide_watched = serializers.BooleanField()
|
||||||
show_ignored_only = serializers.BooleanField()
|
show_ignored_only = serializers.BooleanField()
|
||||||
show_subed_only = serializers.BooleanField()
|
show_subed_only = serializers.BooleanField()
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ Functionality:
|
|||||||
from typing import TypedDict
|
from typing import TypedDict
|
||||||
|
|
||||||
from common.src.es_connect import ElasticWrap
|
from common.src.es_connect import ElasticWrap
|
||||||
from common.src.helper import get_stylesheets
|
|
||||||
|
|
||||||
|
|
||||||
class UserConfigType(TypedDict, total=False):
|
class UserConfigType(TypedDict, total=False):
|
||||||
@@ -29,7 +28,10 @@ class UserConfigType(TypedDict, total=False):
|
|||||||
|
|
||||||
|
|
||||||
class UserConfig:
|
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(
|
_DEFAULT_USER_SETTINGS = UserConfigType(
|
||||||
stylesheet="dark.css",
|
stylesheet="dark.css",
|
||||||
@@ -47,19 +49,6 @@ class UserConfig:
|
|||||||
show_help_text=True,
|
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):
|
def __init__(self, user_id: str):
|
||||||
self._user_id: str = user_id
|
self._user_id: str = user_id
|
||||||
self._config: UserConfigType = self.get_config()
|
self._config: UserConfigType = self.get_config()
|
||||||
@@ -84,7 +73,6 @@ class UserConfig:
|
|||||||
|
|
||||||
def set_value(self, key: str, value: str | bool | int):
|
def set_value(self, key: str, value: str | bool | int):
|
||||||
"""Set or replace a configuration value for the user"""
|
"""Set or replace a configuration value for the user"""
|
||||||
self._validate(key, value)
|
|
||||||
data = {"doc": {"config": {key: value}}}
|
data = {"doc": {"config": {key: value}}}
|
||||||
response, status = ElasticWrap(self.es_update_url).post(data)
|
response, status = ElasticWrap(self.es_update_url).post(data)
|
||||||
if status < 200 or status > 299:
|
if status < 200 or status > 299:
|
||||||
@@ -92,43 +80,6 @@ class UserConfig:
|
|||||||
|
|
||||||
print(f"User {self._user_id} value '{key}' change: to {value}")
|
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:
|
def get_config(self) -> UserConfigType:
|
||||||
"""get config from ES or load from the application defaults"""
|
"""get config from ES or load from the application defaults"""
|
||||||
if not self._user_id:
|
if not self._user_id:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
from channel.serializers import ChannelSerializer
|
from channel.serializers import ChannelSerializer
|
||||||
from common.serializers import PaginationSerializer
|
from common.serializers import PaginationSerializer
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from video.src.constants import OrderEnum, SortEnum, VideoTypeEnum, WatchedEnum
|
||||||
|
|
||||||
|
|
||||||
class PlayerSerializer(serializers.Serializer):
|
class PlayerSerializer(serializers.Serializer):
|
||||||
@@ -91,7 +92,7 @@ class VideoSerializer(serializers.Serializer):
|
|||||||
title = serializers.CharField()
|
title = serializers.CharField()
|
||||||
vid_last_refresh = serializers.CharField()
|
vid_last_refresh = serializers.CharField()
|
||||||
vid_thumb_url = 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()
|
youtube_id = serializers.CharField()
|
||||||
_index = serializers.CharField(required=False)
|
_index = serializers.CharField(required=False)
|
||||||
_score = serializers.FloatField(required=False)
|
_score = serializers.FloatField(required=False)
|
||||||
@@ -110,22 +111,12 @@ class VideoListQuerySerializer(serializers.Serializer):
|
|||||||
playlist = serializers.CharField(required=False)
|
playlist = serializers.CharField(required=False)
|
||||||
channel = serializers.CharField(required=False)
|
channel = serializers.CharField(required=False)
|
||||||
watch = serializers.ChoiceField(
|
watch = serializers.ChoiceField(
|
||||||
choices=["watched", "unwatched", "continue"], required=False
|
choices=WatchedEnum.values(), required=False
|
||||||
)
|
)
|
||||||
sort = serializers.ChoiceField(
|
sort = serializers.ChoiceField(choices=SortEnum.names(), required=False)
|
||||||
choices=[
|
order = serializers.ChoiceField(choices=OrderEnum.values(), required=False)
|
||||||
"published",
|
|
||||||
"downloaded",
|
|
||||||
"views",
|
|
||||||
"likes",
|
|
||||||
"duration",
|
|
||||||
"filesize",
|
|
||||||
],
|
|
||||||
required=False,
|
|
||||||
)
|
|
||||||
order = serializers.ChoiceField(choices=["asc", "desc"], required=False)
|
|
||||||
type = serializers.ChoiceField(
|
type = serializers.ChoiceField(
|
||||||
choices=["videos", "streams", "shorts"], required=False
|
choices=VideoTypeEnum.values_known(), required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ class VideoTypeEnum(enum.Enum):
|
|||||||
SHORTS = "shorts"
|
SHORTS = "shorts"
|
||||||
UNKNOWN = "unknown"
|
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):
|
class SortEnum(enum.Enum):
|
||||||
"""all sort by options"""
|
"""all sort by options"""
|
||||||
@@ -22,9 +32,37 @@ class SortEnum(enum.Enum):
|
|||||||
DURATION = "player.duration"
|
DURATION = "player.duration"
|
||||||
MEDIASIZE = "media_size"
|
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):
|
class OrderEnum(enum.Enum):
|
||||||
"""all order by options"""
|
"""all order by options"""
|
||||||
|
|
||||||
ASC = "asc"
|
ASC = "asc"
|
||||||
DESC = "desc"
|
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]
|
||||||
|
|||||||
Reference in New Issue
Block a user