from aiohttp import web from aiohttp_apispec import docs, querystring_schema from datetime import timedelta from server.client import services from server.client.utils import str_to_date from server.constants import BASE_API_PREFIX, DSP from server.constants.charts import TiktokChartInclude from server.domains.charts.tiktok import calc_chart, fix_count_and_positions, get_chart_id from server.schemas.charts.tiktok import TracksTiktokCharts, TracksTiktokPositions from server.utils.response import dump_response_schema router = web.RouteTableDef() @router.get(BASE_API_PREFIX + "/charts/tracks/tiktok/positions/") @docs( tags=["positions", "tracks", "tiktok"], summary="Get tiktok track positions for dates range.", description="Returns track positions over time.", ) @querystring_schema(TracksTiktokPositions.Request) @dump_response_schema(TracksTiktokPositions.Response, apply=True) async def get_tracks_tiktok_positions(request: web.Request) -> web.Response: params = request["querystring"] isrc, market, chart_type, chart_days, start_date, end_date = ( params["isrc"], params["market"], params["chart_type"], params["chart_days"], params["start_date"], params["end_date"], ) top_chart_id = get_chart_id(market, chart_days=chart_days, chart_type=chart_type) response = await services.dsp.get_tiktok_top_tracks_analytics( top_chart_id=top_chart_id, isrc=isrc, start_date=start_date, end_date=end_date, metrics="positions", ) start_date = str_to_date(response["min_date"]) response_items = [] days_count = 0 if start_date: for index, position in enumerate(response["metrics"]["positions"]): if position is None: continue days_count += 1 response_items.append({"date": start_date + timedelta(days=index), "value": position}) response.update({"items": response_items, "days_on_list": days_count, "total_tracks_in_chart": 50}) return response @router.get(BASE_API_PREFIX + "/charts/tracks/tiktok/") @docs( tags=["charts", "tracks", "tiktok"], summary="Get tiktok charts for selected types, date and market.", description="Returns tiktok charts tracks.", ) @querystring_schema(TracksTiktokCharts.Request) @dump_response_schema(TracksTiktokCharts.Response(many=True)) async def get_tracks_tiktok_charts(request: web.Request) -> web.Response: params = request["querystring"] market, chart_type, chart_days, chart_date, image_size = ( params["market"], params["chart_type"], params["chart_days"], params["chart_date"], params["image_size"], ) top_chart_id = get_chart_id(market, chart_days=chart_days, chart_type=chart_type) response = await services.dsp.get_tiktok_top_tracks( top_chart_id=top_chart_id, date=chart_date, track_state_includes=[ TiktokChartInclude.METRICS.value, TiktokChartInclude.AGGREGATED_METRICS.value, TiktokChartInclude.LIFETIME_METRICS.value, TiktokChartInclude.SOURCE_META.value, ], ) # TODO: potentially temporary fix to have only 50 items in chart response = fix_count_and_positions(response, chart_days, chart_type) isrc_list = list(set(i["source_meta"]["isrc"] for i in response if i["source_meta"].get("isrc"))) # hotfix: get meta from US market for CN as CN does not exist in Spotify API tracks_meta = await services.vendor.get_tracks( DSP.SPOTIFY, isrc=isrc_list, market=("us" if market == "cn" else market) ) tracks_meta = {i["external_ids"]["isrc"]: i for i in tracks_meta if "isrc" in i.get("external_ids", {})} result = calc_chart(chart_days, image_size, response, tracks_meta) return result