from aiohttp import web from aiohttp_apispec import docs, querystring_schema from datetime import datetime, timedelta, timezone from server.client import services from server.constants import BASE_API_PREFIX from server.constants.market import Market from server.constants.youtube import YoutubeVideosOrder from server.schemas.youtube.track import TrackPerformance, TrackStreamsGraph, TrackVideos from server.utils.pagination import multikeysort from server.utils.response import dump_response_schema from server.utils.youtube.track import calculate_trends, define_biggest_source, fill_missing_dates router = web.RouteTableDef() @router.get(BASE_API_PREFIX + "/youtube/track/performance/") @docs(tags=["youtube"], summary="Youtube track performance data.") @querystring_schema(TrackPerformance.Request) @dump_response_schema(TrackPerformance.Response) async def get(request: web.Request): params = request["querystring"] video_id, latest_date, country_code_list = ( params["video_id"], params["latest_date"], params["country_code_list"], ) start_date = latest_date - timedelta(days=27) performance_data = await services.dsp.get_track_data( group_by="date,video_id", video_id=video_id, start_date=start_date, end_date=latest_date, country_code=country_code_list or Market.WORLDWIDE, only="traffic_sources,engagement,watch_times", ) performance_data = fill_missing_dates(performance_data, latest_date, 28) trends = calculate_trends(performance_data) # We only need 4 weeks for trends performance_data = performance_data[:14] biggest_traffic_source = define_biggest_source(performance_data) daily_metrics = [ { "date": i["dimensions"]["date"], "timestampt": int( datetime.strptime(i["dimensions"]["date"], "%Y-%m-%d").replace(tzinfo=timezone.utc).timestamp() ), **i["metrics"], } for i in performance_data ] result = { "biggest_traffic_source": biggest_traffic_source, "daily_metrics": daily_metrics, "trends": trends, } return result @router.get(BASE_API_PREFIX + "/youtube/track/streams-graph/") @docs(tags=["youtube"], summary="Youtube track streams graph.") @querystring_schema(TrackStreamsGraph.Request) @dump_response_schema(TrackStreamsGraph.Response) async def get(request: web.Request): params = request["querystring"] video_id, latest_date, country_code_list = ( params["video_id"], params["latest_date"], params["country_code_list"], ) start_date = latest_date - timedelta(days=13) performance_data = await services.dsp.get_track_data( group_by="date,video_id", video_id=video_id, start_date=start_date, end_date=latest_date, country_code=country_code_list or Market.WORLDWIDE, ) performance_data = fill_missing_dates(performance_data, latest_date, 14) result = [] for row in performance_data: x, y = None, None metrics = row["metrics"] views = metrics.get("views") if views: y = {"total": views, **metrics["traffic_source_types"]} x = int(datetime.strptime(row["dimensions"]["date"], "%Y-%m-%d").replace(tzinfo=timezone.utc).timestamp()) result.append({"x": x, "y": y}) result = sorted(result, key=lambda d: d["x"]) return {"coordinates": result} @router.get(BASE_API_PREFIX + "/youtube/track/videos/") @docs(tags=["youtube"], summary="Youtube track videos list.") @querystring_schema(TrackVideos.Request) @dump_response_schema(TrackVideos.Response) async def get(request: web.Request): params = request["querystring"] isrc, views = params["isrc"], params["views"] limit, offset, sort_by = params["limit"], params["offset"], params["sort_by"] items = await services.dsp.get_videos( isrc=isrc, group_by="date,video_id", views=views, content_type="partner_uploaded,premium_ugc", expand_to="related_isrcs", ) if YoutubeVideosOrder.VIDEO_TITLE_DESC.value not in sort_by and YoutubeVideosOrder.VIDEO_TITLE.value not in sort_by: sort_by.append("video_title") items = multikeysort(items, sort_by) items = items[offset : offset + limit] return {"items": items}