from structlog import BoundLogger from src.api_utils.errors import BadRequest, Conflict, NotFound, Unauthorized from src.api_utils.handler import api_handler from src.api_utils.request import Request from src.api_utils.response import Response from src.api_utils.spec import docs, path_schema, request_schema, response_schema from src.config import USER_EXECUTION_SQS_URL from src.handlers.job_handler import schedule_playlists_sync from src.playlist_sync.schemas import ApplicationRequestSchema, CreatePlaylistSyncRequestSchema, \ CreatePlaylistSyncResponseSchema, GetPlaylistSyncResponseSchema, ListPlaylistSyncResponseSchema, \ SyncRequestSchema, UpdatePlaylistSyncRequestSchema, UpdatePlaylistSyncResponseSchema from src.playlist_sync.services import PlaylistSyncService from src.synchronizer import SyncManager @api_handler @docs(tags=("playlist_sync",), summary="List playlist sync") @path_schema(ApplicationRequestSchema) @response_schema(ListPlaylistSyncResponseSchema(many=True), description="Returns list of playlist sync objects") @response_schema(code=Unauthorized.status_code, description="Unauthorized") def list_playlists_sync(_request: Request, logger: BoundLogger, app_id: int) -> Response: result = PlaylistSyncService().select_many_with_log(app_id) return Response(ListPlaylistSyncResponseSchema().dumps(result, many=True)) @api_handler @docs(tags=("playlist_sync",), summary="Get playlist sync") @path_schema(SyncRequestSchema) @response_schema(GetPlaylistSyncResponseSchema, description="Returns playlist sync object") @response_schema(code=NotFound.status_code, description="playlist sync doesn't exists") @response_schema(code=Unauthorized.status_code, description="Unauthorized") def get_playlist_sync(_request: Request, logger: BoundLogger, app_id: int, sync_id: int) -> Response: result = PlaylistSyncService().select_one_with_log(app_id, sync_id) if result is None: raise NotFound() return Response(GetPlaylistSyncResponseSchema().dumps(result)) @api_handler @docs(tags=("playlist_sync",), summary="Create playlist sync") @path_schema(ApplicationRequestSchema) @request_schema(CreatePlaylistSyncRequestSchema) @response_schema(CreatePlaylistSyncResponseSchema, description="playlist sync successfully created") @response_schema(code=Conflict.status_code, description="playlist sync with same target playlist id already exists") @response_schema(code=Unauthorized.status_code, description="Unauthorized") @response_schema(code=BadRequest.status_code, description="BadRequest") def create_playlist_sync(request: Request, logger: BoundLogger, app_id: int) -> Response: if request.json is None: raise BadRequest() data = CreatePlaylistSyncRequestSchema().load(request.json) service = PlaylistSyncService() if service.check_unique(data["to_playlist_id"]): raise Conflict() playlist_info = SyncManager(logger).check_playlists( data.get("from_playlist_id"), data.get("to_playlist_id"), data.get("to_service_account_id") ) instance = service.model( application_id=app_id, source_title=playlist_info.title, source_image=playlist_info.image_url, source_track_count=playlist_info.total_tracks, source_service_account_id=playlist_info.user_id, source_service_account_name=playlist_info.user_name, **data, ) service.insert_instance(instance) return Response(CreatePlaylistSyncResponseSchema().dumps(instance)) @api_handler @docs(tags=("playlist_sync",), summary="Update playlist sync") @path_schema(SyncRequestSchema) @request_schema(UpdatePlaylistSyncRequestSchema) @response_schema(UpdatePlaylistSyncResponseSchema, description="playlist sync successfully updated") @response_schema(code=NotFound.status_code, description="playlist sync doesn't exists") @response_schema(code=Conflict.status_code, description="playlist sync with same target playlist id already exists") @response_schema(code=Unauthorized.status_code, description="Unauthorized") @response_schema(code=BadRequest.status_code, description="BadRequest") def update_playlist_sync(request: Request, logger: BoundLogger, app_id: int, sync_id: int) -> Response: if request.json is None: raise BadRequest() data = UpdatePlaylistSyncRequestSchema().load(request.json) service = PlaylistSyncService() instance = service.select_by_pk(sync_id) if instance is None: raise NotFound() if service.check_unique(data["to_playlist_id"], instance.id): raise Conflict() playlist_info = SyncManager(logger).check_playlists( data.get("from_playlist_id"), data.get("to_playlist_id"), data.get("to_service_account_id") ) service.update_by_pk( instance.id, **dict( source_title=playlist_info.title, source_image=playlist_info.image_url, source_track_count=playlist_info.total_tracks, source_service_account_id=playlist_info.user_id, source_service_account_name=playlist_info.user_name, **data, ), ) return Response(UpdatePlaylistSyncResponseSchema().dumps(instance)) @api_handler @docs(tags=("playlist_sync",), summary="Delete playlist sync") @path_schema(SyncRequestSchema) @response_schema(code=202, description="playlist sync successfully deleted") @response_schema(code=NotFound.status_code, description="playlist sync doesn't exists") @response_schema(code=Unauthorized.status_code, description="Unauthorized") def delete_playlist_sync(_request: Request, logger: BoundLogger, app_id: int, sync_id: int) -> Response: service = PlaylistSyncService() if not service.exists_by_pk(sync_id): raise NotFound() service.delete_by_pk(sync_id) return Response(status_code=202) @api_handler @docs(tags=("playlist_sync",), summary="Run playlist sync process") @path_schema(SyncRequestSchema) @response_schema(description="playlist sync successfully executed") @response_schema(code=NotFound.status_code, description="playlist sync doesn't exists") @response_schema(code=Unauthorized.status_code, description="Unauthorized") def execute_playlist_sync(_request: Request, logger: BoundLogger, app_id: int, sync_id: int) -> Response: service = PlaylistSyncService() instance = service.select_by_pk(sync_id) if instance is None: raise NotFound() schedule_playlists_sync([{"sync_ids": [instance.id], "triggered_manually": True}], USER_EXECUTION_SQS_URL, logger) return Response()