From 29857a9e3f6dffd30e2322a8ccbdc97981d216b9 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 23 Dec 2024 16:20:57 +0700 Subject: [PATCH] match video progress through API --- backend/common/src/search_processor.py | 24 +++++++++++++++++++++++- backend/common/views_base.py | 12 ++++++++---- backend/video/views.py | 4 ++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/backend/common/src/search_processor.py b/backend/common/src/search_processor.py index 8a4b98fb..eccacc91 100644 --- a/backend/common/src/search_processor.py +++ b/backend/common/src/search_processor.py @@ -8,15 +8,17 @@ import urllib.parse from common.src.env_settings import EnvironmentSettings from common.src.helper import date_parser, get_duration_str +from common.src.ta_redis import RedisArchivist from download.src.thumbnails import ThumbManager class SearchProcess: """process search results""" - def __init__(self, response): + def __init__(self, response, match_video_user_progress: None | int = None): self.response = response self.processed = False + self.position_index = self.get_user_progress(match_video_user_progress) def process(self): """detect type and process""" @@ -33,6 +35,19 @@ class SearchProcess: return self.processed + def get_user_progress(self, match_video_user_progress) -> dict | None: + """get user video watch progress""" + if not match_video_user_progress: + return None + + query = f"{match_video_user_progress}:progress:*" + all_positions = RedisArchivist().list_items(query) + if not all_positions: + return None + + pos_index = {i["youtube_id"]: i["position"] for i in all_positions} + return pos_index + def _process_result(self, result): """detect which type of data to process""" index = result["_index"] @@ -105,6 +120,13 @@ class SearchProcess: } ) + if self.position_index: + player_position = self.position_index.get(video_id) + total = video_dict["player"].get("duration") + if player_position and total: + progress = 100 * (player_position / total) + video_dict["player"].update({"progress": progress}) + return dict(sorted(video_dict.items())) @staticmethod diff --git a/backend/common/views_base.py b/backend/common/views_base.py index 138bb7b8..324ecb05 100644 --- a/backend/common/views_base.py +++ b/backend/common/views_base.py @@ -57,12 +57,14 @@ class ApiBaseView(APIView): self.context = False self.pagination_handler = False - def get_document(self, document_id): + def get_document(self, document_id, progress_match=None): """get single document from es""" path = f"{self.search_base}{document_id}" response, status_code = ElasticWrap(path).get() try: - self.response["data"] = SearchProcess(response).process() + self.response["data"] = SearchProcess( + response, match_video_user_progress=progress_match + ).process() except KeyError: print(f"item not found: {document_id}") self.response["data"] = False @@ -78,14 +80,16 @@ class ApiBaseView(APIView): } ) - def get_document_list(self, request, pagination=True): + def get_document_list(self, request, pagination=True, progress_match=None): """get a list of results""" if pagination: self.initiate_pagination(request) es_handler = ElasticWrap(self.search_base) response, status_code = es_handler.get(data=self.data) - self.response["data"] = SearchProcess(response).process() + self.response["data"] = SearchProcess( + response, match_video_user_progress=progress_match + ).process() if self.response["data"]: self.status_code = status_code else: diff --git a/backend/video/views.py b/backend/video/views.py index 294236f0..a3adbb9b 100644 --- a/backend/video/views.py +++ b/backend/video/views.py @@ -30,7 +30,7 @@ class VideoApiListView(ApiBaseView): return Response({"error": str(err)}, status=400) self.data = data - self.get_document_list(request) + self.get_document_list(request, progress_match=request.user.id) return Response(self.response) @@ -46,7 +46,7 @@ class VideoApiView(ApiBaseView): def get(self, request, video_id): # pylint: disable=unused-argument """get request""" - self.get_document(video_id) + self.get_document(video_id, progress_match=request.user.id) return Response(self.response, status=self.status_code) def delete(self, request, video_id):