from aiohttp import web from aiohttp_apispec import docs, headers_schema, json_schema, querystring_schema from apollo_utils.service.clients.aiohttp.utils.response import dump_response_schema from apollo_utils.service.exceptions import BadRequest, NotFound from server.constants.core import LEGACY_API_PREFIX, ApolloEntityType from server.db.models.users import Favorites from server.domains import favorites as favorites_dom from server.domains.accounts import get_account from server.schemas.favorites.core import FavoritesResponse from server.schemas.favorites.playlists import FavoritePlaylistCreateDeleteRequest, FavoritePlaylistsGetByAccount from server.schemas.headers import AccountHeader from server.utils.favorites import add_tag_filters from server.utils.pagination import paginate router = web.RouteTableDef() @router.get(LEGACY_API_PREFIX + "/favorites/playlists/") @docs( tags=["favorites", "playlists", "legacy"], summary="Get starred playlists by account (legacy version).", ) @headers_schema(AccountHeader) @querystring_schema(FavoritePlaylistsGetByAccount.Request) @dump_response_schema(FavoritePlaylistsGetByAccount.Response, apply=True) @paginate() async def get_favorite_playlists_by_account(request: web.Request) -> web.Response: headers, params, filters = request["headers"], request["querystring"], [] tag_id = params.pop("tag_id", []) if tag_id: add_tag_filters(filters, tag_id=tag_id) q = Favorites.q_filter_by_account(app_slug=headers["app"], user_id=headers["user_id"]) result = await Favorites.list( q, order_by=Favorites.created_at.desc(), entity_type=ApolloEntityType.PLAYLIST.value, filters=filters, **params ) return result @router.post(LEGACY_API_PREFIX + "/favorites/playlists/") @docs( tags=["favorites", "playlists", "legacy"], summary="Add playlist to favorites (legacy version).", ) @headers_schema(AccountHeader) @json_schema(FavoritePlaylistCreateDeleteRequest) @dump_response_schema(FavoritesResponse, code=201, apply=True) async def add_playlist_to_favorites(request: web.Request) -> web.Response: headers, data = request["headers"], request["json"] app_slug, user_id = headers["app"], headers["user_id"] account, _ = await get_account(app_slug=app_slug, user_id=user_id) account_id = account.id entity_id = favorites_dom.get_entity_id(_type=ApolloEntityType.PLAYLIST, **data) is_starred = await Favorites.get( account_id=account_id, entity_id=entity_id, entity_type=ApolloEntityType.PLAYLIST.value ) if is_starred: raise BadRequest("Playlist is already starred.") country_code = data.get("country_code") return await Favorites.create( dict( entity_id=entity_id, entity_type=ApolloEntityType.PLAYLIST.value, data={ "id": data["id"], "vendor": data["vendor"], **({"country_code": country_code} if country_code else {}), }, account_id=account_id, ) ) @router.delete(LEGACY_API_PREFIX + "/favorites/playlists/") @docs( tags=["favorites", "playlists", "legacy"], summary="Remove playlist from favorites (legacy version).", ) @headers_schema(AccountHeader) @json_schema(FavoritePlaylistCreateDeleteRequest) @dump_response_schema(FavoritesResponse, code=204, apply=True) async def remove_playlist_from_favorites(request: web.Request) -> web.Response: headers, data = request["headers"], request["json"] result = await Favorites.delete( account_id=Favorites.q_account_id(app_slug=headers["app"], user_id=headers["user_id"]), entity_id=favorites_dom.get_entity_id(ApolloEntityType.PLAYLIST, **data), entity_type=ApolloEntityType.PLAYLIST.value, ) if not result: raise NotFound("This playlist is not starred.") return web.Response(status=204) @router.delete(LEGACY_API_PREFIX + "/favorites/playlists/{entity_id}/") @docs( tags=["favorites", "playlists", "legacy"], summary="Remove playlist from favorites (legacy version).", ) @headers_schema(AccountHeader) @dump_response_schema(FavoritesResponse, code=204, apply=True) async def remove_playlist_from_favorites_by_id(request: web.Request) -> web.Response: headers, entity_id = request["headers"], request.match_info["entity_id"] result = await Favorites.delete( account_id=Favorites.q_account_id(app_slug=headers["app"], user_id=headers["user_id"]), entity_id=entity_id, entity_type=ApolloEntityType.PLAYLIST.value, ) if not result: raise NotFound("This playlist is not starred.") return web.Response(status=204)