diff --git a/tubearchivist/api/README.md b/tubearchivist/api/README.md index 31ac2741..31724c4c 100644 --- a/tubearchivist/api/README.md +++ b/tubearchivist/api/README.md @@ -29,6 +29,10 @@ Note: - [Download Queue List](#download-queue-list-view) - [Download Queue Single](#download-queue-item-view) +**Snapshot management** +- [Snapshot List](#snapshot-list-view) +- [Snapshot Single](#snapshot-item-view) + **Additional** - [Login](#login-view) - [Task](#task-view) WIP @@ -207,6 +211,48 @@ Add to queue previously ignored video: DELETE /api/download/\/ Forget or delete from download queue +## Snapshot List View +GET /api/snapshot/ +Return snapshot config and a list of available snapshots. + +```json +{ + "next_exec": epoch, + "next_exec_str": "date_str", + "expire_after": "30d", + "snapshots": [] +} +``` + +POST /api/snapshot/ +Create new snapshot now, will return immediatly, task will run async in the background, will return snapshot name: +```json +{ + "snapshot_name": "ta_daily_ +} +``` + +## Snapshot Item View +GET /api/snapshot/\/ +Return metadata of a single snapshot +```json +{ + "id": "ta_daily_, + "state": "SUCCESS", + "es_version": "0.0.0", + "start_date": "date_str", + "end_date": "date_str", + "end_stamp": epoch, + "duration_s": 0 +} +``` + +GET /api/snapshot/\/ +Restore this snapshot + +DELETE /api/snapshot/\/ +Remove this snapshot from index + ## Login View Return token and user ID for username and password: POST /api/login diff --git a/tubearchivist/api/urls.py b/tubearchivist/api/urls.py index 34633443..e84ec052 100644 --- a/tubearchivist/api/urls.py +++ b/tubearchivist/api/urls.py @@ -13,6 +13,8 @@ from api.views import ( PlaylistApiVideoView, PlaylistApiView, SearchView, + SnapshotApiListView, + SnapshotApiView, TaskApiView, VideoApiListView, VideoApiView, @@ -89,6 +91,16 @@ urlpatterns = [ TaskApiView.as_view(), name="api-task", ), + path( + "snapshot/", + SnapshotApiListView.as_view(), + name="api-snapshot-list", + ), + path( + "snapshot//", + SnapshotApiView.as_view(), + name="api-snapshot", + ), path( "cookie/", CookieView.as_view(), diff --git a/tubearchivist/api/views.py b/tubearchivist/api/views.py index 70d2485e..2574db65 100644 --- a/tubearchivist/api/views.py +++ b/tubearchivist/api/views.py @@ -5,6 +5,7 @@ from api.src.task_processor import TaskHandler from home.src.download.queue import PendingInteract from home.src.download.yt_dlp_base import CookieHandler from home.src.es.connect import ElasticWrap +from home.src.es.snapshot import ElasticSnapshot from home.src.frontend.searching import SearchForm from home.src.index.generic import Pagination from home.src.index.video import SponsorBlock @@ -485,6 +486,70 @@ class TaskApiView(ApiBaseView): return Response(response) +class SnapshotApiListView(ApiBaseView): + """resolves to /api/snapshot/ + GET: returns snashot config plus list of existing snapshots + POST: take snapshot now + """ + + @staticmethod + def get(request): + """handle get request""" + # pylint: disable=unused-argument + snapshots = ElasticSnapshot().get_snapshot_stats() + + return Response(snapshots) + + @staticmethod + def post(request): + """take snapshot now with post request""" + # pylint: disable=unused-argument + response = ElasticSnapshot().take_snapshot_now() + + return Response(response) + + +class SnapshotApiView(ApiBaseView): + """resolves to /api/snapshot// + GET: return a single snapshot + POST: restore snapshot + DELETE: delete a snapshot + """ + + @staticmethod + def get(request, snapshot_id): + """handle get request""" + # pylint: disable=unused-argument + snapshot = ElasticSnapshot().get_single_snapshot(snapshot_id) + + if not snapshot: + return Response({"message": "snapshot not found"}, status=404) + + return Response(snapshot) + + @staticmethod + def post(request, snapshot_id): + """restore snapshot with post request""" + # pylint: disable=unused-argument + response = ElasticSnapshot().restore_all(snapshot_id) + if not response: + message = {"message": "failed to restore snapshot"} + return Response(message, status=400) + + return Response(response) + + @staticmethod + def delete(request, snapshot_id): + """delete snapshot from index""" + # pylint: disable=unused-argument + response = ElasticSnapshot().delete_single_snapshot(snapshot_id) + if not response: + message = {"message": "failed to delete snapshot"} + return Response(message, status=400) + + return Response(response) + + class CookieView(ApiBaseView): """resolves to /api/cookie/ GET: check if cookie is enabled