from datetime import datetime from typing import Dict, Optional, Type from marshmallow import Schema from apollo_messages_views.config import EVENT_VIEW from apollo_messages_views.constants.base import EventType, EventView from apollo_messages_views.schemas.feed_messages.charts import ChartsEntryMessage, ChartsExitMessage, ChartsMoveMessage, \ ChartsUpdateMessage from apollo_messages_views.schemas.feed_messages.playlists import (PlaylistStarredEntryMessage, PlaylistTopEntryMessage, PlaylistUpdateMessage, PlaylistTopExitMessage, PlaylistStarredExitMessage, PlaylistTopMajorMoveMessage, PlaylistStarredMajorMoveMessage) from apollo_messages_views.schemas.push_messages.input import (PlaylistInputMessage, TrackChartInputMessage, TrackPlaylistInputMessage, ChartInputMessage) from apollo_messages_views.schemas.push_messages.output import (PlaylistStarredEntryPushMessageOutput, PlaylistTopEntryPushMessageOutput, PlaylistUpdatePushMessageOutput, PushMessageOutput, PlaylistTopExitPushMessageOutput, PlaylistTopMajorMovePushMessageOutput, PlaylistStarredExitPushMessageOutput, PlaylistStarredMajorMovePushMessageOutput, ChartUpdatePushMessageOutput) FEED_MESSAGE_TYPE_TO_SCHEMA = { EventType.TOP_CHART_ENTRY.value: ChartsEntryMessage, EventType.TOP_CHART_EXIT.value: ChartsExitMessage, EventType.TOP_CHART_MOVE.value: ChartsMoveMessage, EventType.TOP_CHART_UPDATE.value: ChartsUpdateMessage, EventType.TOP_PLAYLIST_ENTRY.value: PlaylistTopEntryMessage, EventType.TOP_PLAYLIST_EXIT.value: PlaylistTopExitMessage, EventType.TOP_PLAYLIST_MAJOR_MOVE.value: PlaylistTopMajorMoveMessage, EventType.STARRED_PLAYLIST_ENTRY.value: PlaylistStarredEntryMessage, EventType.STARRED_PLAYLIST_EXIT.value: PlaylistStarredExitMessage, EventType.STARRED_PLAYLIST_MAJOR_MOVE.value: PlaylistStarredMajorMoveMessage, EventType.STARRED_PLAYLIST_UPDATE.value: PlaylistUpdateMessage, } PUSH_MESSAGE_TYPE_TO_INPUT_SCHEMA = { EventType.TOP_CHART_ENTRY.value: TrackChartInputMessage, EventType.TOP_CHART_EXIT.value: TrackChartInputMessage, EventType.TOP_CHART_MOVE.value: TrackChartInputMessage, EventType.TOP_CHART_UPDATE.value: ChartInputMessage, EventType.TOP_PLAYLIST_ENTRY.value: TrackPlaylistInputMessage, EventType.TOP_PLAYLIST_EXIT.value: TrackPlaylistInputMessage, EventType.TOP_PLAYLIST_MAJOR_MOVE.value: TrackPlaylistInputMessage, EventType.STARRED_PLAYLIST_ENTRY.value: TrackPlaylistInputMessage, EventType.STARRED_PLAYLIST_EXIT.value: TrackPlaylistInputMessage, EventType.STARRED_PLAYLIST_MAJOR_MOVE.value: TrackPlaylistInputMessage, EventType.STARRED_PLAYLIST_UPDATE.value: PlaylistInputMessage, } PUSH_MESSAGE_TYPE_TO_OUTPUT_SCHEMA = { EventType.TOP_CHART_ENTRY.value: PushMessageOutput, EventType.TOP_CHART_EXIT.value: PushMessageOutput, EventType.TOP_CHART_MOVE.value: PushMessageOutput, EventType.TOP_CHART_UPDATE.value: ChartUpdatePushMessageOutput, EventType.TOP_PLAYLIST_ENTRY.value: PlaylistTopEntryPushMessageOutput, EventType.TOP_PLAYLIST_EXIT.value: PlaylistTopExitPushMessageOutput, EventType.TOP_PLAYLIST_MAJOR_MOVE.value: PlaylistTopMajorMovePushMessageOutput, EventType.STARRED_PLAYLIST_ENTRY.value: PlaylistStarredEntryPushMessageOutput, EventType.STARRED_PLAYLIST_EXIT.value: PlaylistStarredExitPushMessageOutput, EventType.STARRED_PLAYLIST_MAJOR_MOVE.value: PlaylistStarredMajorMovePushMessageOutput, EventType.STARRED_PLAYLIST_UPDATE.value: PlaylistUpdatePushMessageOutput, } class SchemaFactory: def __init__(self, cls_map: Dict[EventType, Type[Schema]]): self._cls_map = cls_map self._obj_map = {} def __getitem__(self, item) -> Schema: value = self._obj_map.get(item) if value is None: value = self._cls_map[item]() self._obj_map[item] = value return value feed_schemas = SchemaFactory(FEED_MESSAGE_TYPE_TO_SCHEMA) push_input_schemas = SchemaFactory(PUSH_MESSAGE_TYPE_TO_INPUT_SCHEMA) push_output_schemas = SchemaFactory(PUSH_MESSAGE_TYPE_TO_OUTPUT_SCHEMA) _EVENT_VIEW_TO_INPUT_SCHEMA_FACTORY = {EventView.FEED.value: feed_schemas, EventView.PUSH.value: push_input_schemas} def _set_ctx(schema: Schema, current_dt: Optional[datetime]): if current_dt: schema.context["current_dt"] = current_dt else: schema.context.pop("current_dt", None) def get_schema(event_type: str, event_view: str = None, current_dt: datetime = None) -> Schema: schema = _EVENT_VIEW_TO_INPUT_SCHEMA_FACTORY[event_view or EVENT_VIEW][event_type] _set_ctx(schema, current_dt) return schema def get_output_push_messages_schema(event_type: str, current_dt: datetime = None) -> PushMessageOutput: schema = push_output_schemas[event_type] _set_ctx(schema, current_dt) return schema