From 49cfbd5796f0896bda49724a20c0cfdabda904e5 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 2 Aug 2024 23:51:01 +0200 Subject: [PATCH] add playlist data query building --- tubearchivist/playlist/src/constants.py | 10 ++++ tubearchivist/playlist/src/query_building.py | 53 +++++++++++++++++++ tubearchivist/playlist/tests/__init__.py | 0 .../playlist/tests/test_src/__init__.py | 0 .../tests/test_src/test_query_building.py | 30 +++++++++++ tubearchivist/playlist/views.py | 30 +++++------ 6 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 tubearchivist/playlist/src/constants.py create mode 100644 tubearchivist/playlist/src/query_building.py create mode 100644 tubearchivist/playlist/tests/__init__.py create mode 100644 tubearchivist/playlist/tests/test_src/__init__.py create mode 100644 tubearchivist/playlist/tests/test_src/test_query_building.py diff --git a/tubearchivist/playlist/src/constants.py b/tubearchivist/playlist/src/constants.py new file mode 100644 index 00000000..3cec371d --- /dev/null +++ b/tubearchivist/playlist/src/constants.py @@ -0,0 +1,10 @@ +"""playlist constants""" + +import enum + + +class PlaylistTypesEnum(enum.Enum): + """all playlist_type options""" + + REGULAR = "regular" + CUSTOM = "custom" diff --git a/tubearchivist/playlist/src/query_building.py b/tubearchivist/playlist/src/query_building.py new file mode 100644 index 00000000..4751144f --- /dev/null +++ b/tubearchivist/playlist/src/query_building.py @@ -0,0 +1,53 @@ +"""build query for playlists""" + +from playlist.src.constants import PlaylistTypesEnum + + +class QueryBuilder: + """contain functionality""" + + def __init__(self, **kwargs): + self.request_params = kwargs + + def build_data(self) -> dict: + """build data dict""" + data = {} + data["query"] = self.build_query() + if sort := self.parse_sort(): + data.update(sort) + + return data + + def build_query(self) -> dict: + """build query key""" + must_list = [] + channel = self.request_params.get("channel") + if channel: + must_list.append({"match": {"playlist_channel_id": channel[0]}}) + + subscribed = self.request_params.get("subscribed") + if subscribed: + subed_bool = subscribed[0] == "true" + must_list.append({"match": {"playlist_subscribed": subed_bool}}) + + playlist_type = self.request_params.get("type") + if playlist_type: + type_list = self.parse_type(playlist_type[0]) + must_list.append(type_list) + + query = {"bool": {"must": must_list}} + + return query + + def parse_type(self, playlist_type: str) -> dict: + """parse playlist type""" + if not hasattr(PlaylistTypesEnum, playlist_type.upper()): + raise ValueError(f"'{playlist_type}' not in PlaylistTypesEnum") + + type_parsed = getattr(PlaylistTypesEnum, playlist_type.upper()).value + + return {"match": {"playlist_type.keyword": type_parsed}} + + def parse_sort(self) -> dict: + """return sort""" + return {"sort": [{"playlist_name.keyword": {"order": "asc"}}]} diff --git a/tubearchivist/playlist/tests/__init__.py b/tubearchivist/playlist/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tubearchivist/playlist/tests/test_src/__init__.py b/tubearchivist/playlist/tests/test_src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tubearchivist/playlist/tests/test_src/test_query_building.py b/tubearchivist/playlist/tests/test_src/test_query_building.py new file mode 100644 index 00000000..40404f12 --- /dev/null +++ b/tubearchivist/playlist/tests/test_src/test_query_building.py @@ -0,0 +1,30 @@ +"""test playlist query building""" + +import pytest +from playlist.src.query_building import QueryBuilder + + +def test_build_data(): + """test for correct key building""" + qb = QueryBuilder( + channel=["test_channel"], + subscribed=["true"], + type=["regular"], + ) + result = qb.build_data() + must_list = result["query"]["bool"]["must"] + assert "query" in result + assert "sort" in result + assert result["sort"] == [{"playlist_name.keyword": {"order": "asc"}}] + assert {"match": {"playlist_channel_id": "test_channel"}} in must_list + assert {"match": {"playlist_subscribed": True}} in must_list + + +def test_parse_type(): + """validate type""" + qb = QueryBuilder(type=["regular"]) + with pytest.raises(ValueError): + qb.parse_type("invalid") + + result = qb.parse_type("custom") + assert result == {"match": {"playlist_type.keyword": "custom"}} diff --git a/tubearchivist/playlist/views.py b/tubearchivist/playlist/views.py index 696ad688..ba5a2c72 100644 --- a/tubearchivist/playlist/views.py +++ b/tubearchivist/playlist/views.py @@ -3,6 +3,7 @@ from common.views_base import AdminWriteOnly, ApiBaseView from download.src.subscriptions import PlaylistSubscription from playlist.src.index import YoutubePlaylist +from playlist.src.query_building import QueryBuilder from rest_framework import status from rest_framework.response import Response from task.tasks import subscribe_to @@ -12,31 +13,26 @@ from user.src.user_config import UserConfig class PlaylistApiListView(ApiBaseView): """resolves to /api/playlist/ GET: returns list of indexed playlists + params: + - channel:str= + - subscribed: bool + - type:enum=regular|custom + POST: change subscribe state """ search_base = "ta_playlist/_search/" permission_classes = [AdminWriteOnly] - valid_playlist_type = ["regular", "custom"] def get(self, request): - """handle get request""" - playlist_type = request.GET.get("playlist_type", None) - query = {"sort": [{"playlist_name.keyword": {"order": "asc"}}]} - if playlist_type is not None: - if playlist_type not in self.valid_playlist_type: - message = f"invalid playlist_type {playlist_type}" - return Response({"message": message}, status=400) + """get request""" + try: + data = QueryBuilder(**request.GET).build_data() + except ValueError as err: + return Response({"error": str(err)}, status=400) - query.update( - { - "query": { - "term": {"playlist_type": {"value": playlist_type}} - }, - } - ) - - self.data.update(query) + self.data = data self.get_document_list(request) + return Response(self.response) def post(self, request):