from __future__ import annotations import datetime as dt import json import sys from typing import TYPE_CHECKING, Any, Callable, Mapping import boto3 from src import config from src.api_client.dsp import AppleMusicApiClient, BaseDSPApiClient, DeezerApiClient, SpotifyApiClient, \ YoutubeApiClient from src.constants import AppExecutionTypes from src.enums import ServiceType from src.service_account.services import ServiceAccountService if TYPE_CHECKING: from src.logger import BoundLogger from src.service_account.models import ServiceAccount __all__ = ["func_name", "get_app_execution_type", "get_api_url", "get_dsp_api_client", "get_authorized_api_client"] _SERVICE_TYPE_API_MAP = { ServiceType.spotify: SpotifyApiClient, ServiceType.deezer: DeezerApiClient, ServiceType.youtube: YoutubeApiClient, ServiceType.apple_music: AppleMusicApiClient, } def get_app_execution_type() -> str: _type = config.APP_EXECUTION_TYPE if _type == AppExecutionTypes.MAIN and (not config.USER_EXECUTION_SQS_URL or not config.SCHEDULE_EXECUTION_SQS_URL): raise ValueError(f"Misconfigured. For {_type} app-execution type both USER_EXECUTION_SQS_URL and " f"SCHEDULE_EXECUTION_SQS_URL must be set.\n" f"Got USER_EXECUTION_SQS_URL={config.USER_EXECUTION_SQS_URL} and " f"SCHEDULE_EXECUTION_SQS_URL={config.SCHEDULE_EXECUTION_SQS_URL}.") return _type def invoke_lambda(payload: Mapping[str, Any]): if config.IS_LOCAL: client = boto3.client( "lambda", endpoint_url="http://127.0.0.1:8001", aws_access_key_id=config.AWS_ACCESS_KEY_ID, aws_secret_access_key=config.AWS_SECRET_ACCESS_KEY, ) else: client = boto3.client("lambda") client.invoke(FunctionName=config.LAMBDA_FUNCTION_NAME, InvocationType="Event", Payload=json.dumps(payload)) def get_api_url(schema: str, host: str) -> str: return f"{schema}://{host}{f'/{config.API_URL_PREFIX}' if config.API_URL_PREFIX else ''}" def get_dsp_api_client( service_type: ServiceType, logger: "BoundLogger", *, token_update_callback: Callable[[str, int, dt.datetime], Any] | None = None, refresh_token: str | None = None, access_token: str | None = None, expires_in: int | None = None, updated_at: dt.datetime | None = None, ) -> BaseDSPApiClient: api_client_cls = _SERVICE_TYPE_API_MAP[service_type] return api_client_cls( logger=logger, token_update_callback=token_update_callback, refresh_token=refresh_token, access_token=access_token, expires_in=expires_in, updated_at=updated_at, ) def get_authorized_api_client( service_account: "ServiceAccount", logger: "BoundLogger", ) -> BaseDSPApiClient | None: if service_account.service_type is None: return None def token_update_callback(access_token: str, expires_in: int, updated_at: dt.datetime): ServiceAccountService().update_by_pk( service_account.id, access_token=access_token, expires_in=expires_in, updated_at=updated_at ) return get_dsp_api_client( service_account.service_type, logger, token_update_callback=token_update_callback, refresh_token=service_account.refresh_token, access_token=service_account.access_token, expires_in=service_account.expires_in, updated_at=service_account.updated_at, ) def func_name(): return sys._getframe(1).f_code.co_name