def get_follow_events(user_ids: Tuple[int], min_ts: int, max_ts: int, count: int) -> List[APITimelineEvent]: """ Gets all follow events in the feed. """ follow_events_db = db_user_relationship.get_follow_events( user_ids=user_ids, min_ts=min_ts, max_ts=max_ts, count=count, ) events = [] for event in follow_events_db: try: follow_event = APIFollowEvent( user_name_0=event['user_name_0'], user_name_1=event['user_name_1'], relationship_type='follow', created=event['created'].timestamp(), ) events.append( APITimelineEvent( event_type=UserTimelineEventType.FOLLOW, user_name=follow_event.user_name_0, created=follow_event.created, metadata=follow_event, )) except pydantic.ValidationError as e: current_app.logger.error('Validation error: ' + str(e), exc_info=True) continue return events
def get_notification_events(user: dict, count: int) -> List[APITimelineEvent]: """ Gets notification events for the user in the feed.""" notification_events_db = db_user_timeline_event.get_user_notification_events(user_id=user['id'], count=count) events = [] for event in notification_events_db: events.append(APITimelineEvent( event_type=UserTimelineEventType.NOTIFICATION, user_name=event.metadata.creator, created=event.created.timestamp(), metadata=APINotificationEvent(message=event.metadata.message) )) return events
def get_listen_events( db_conn: TimescaleListenStore, musicbrainz_ids: List[str], min_ts: int, max_ts: int, count: int, time_range: int, ) -> List[APITimelineEvent]: """ Gets all listen events in the feed. """ # NOTE: For now, we get a bunch of listens for the users the current # user is following and take a max of 2 out of them per user. This # could be done better by writing a complex query to get exactly 2 listens for each user, # but I'm happy with this heuristic for now and we can change later. db_conn = webserver.create_timescale(current_app) listens = db_conn.fetch_listens_for_multiple_users_from_storage( musicbrainz_ids, limit=count, from_ts=min_ts, to_ts=max_ts, time_range=time_range, order=0, # descending ) user_listens_map = defaultdict(list) for listen in listens: if len(user_listens_map[ listen.user_name]) < MAX_LISTEN_EVENTS_PER_USER: user_listens_map[listen.user_name].append(listen) events = [] for user in user_listens_map: for listen in user_listens_map[user]: try: listen_dict = listen.to_api() listen_dict['inserted_at'] = listen_dict[ 'inserted_at'].timestamp() api_listen = APIListen(**listen_dict) events.append( APITimelineEvent( event_type=UserTimelineEventType.LISTEN, user_name=api_listen.user_name, created=api_listen.listened_at, metadata=api_listen, )) except pydantic.ValidationError as e: current_app.logger.error('Validation error: ' + str(e), exc_info=True) continue return events
def get_recording_recommendation_events(users_for_events: List[dict], min_ts: int, max_ts: int, count: int) -> List[APITimelineEvent]: """ Gets all recording recommendation events in the feed. """ id_username_map = { user['id']: user['musicbrainz_id'] for user in users_for_events } recording_recommendation_events_db = db_user_timeline_event.get_recording_recommendation_events_for_feed( user_ids=(user['id'] for user in users_for_events), min_ts=min_ts, max_ts=max_ts, count=count, ) events = [] for event in recording_recommendation_events_db: try: listen = APIListen( user_name=id_username_map[event.user_id], track_metadata=TrackMetadata( artist_name=event.metadata.artist_name, track_name=event.metadata.track_name, release_name=event.metadata.release_name, additional_info=AdditionalInfo( recording_msid=event.metadata.recording_msid, recording_mbid=event.metadata.recording_mbid, artist_msid=event.metadata.artist_msid, )), ) events.append( APITimelineEvent( id=event.id, event_type=UserTimelineEventType.RECORDING_RECOMMENDATION, user_name=listen.user_name, created=event.created.timestamp(), metadata=listen, )) except pydantic.ValidationError as e: current_app.logger.error('Validation error: ' + str(e), exc_info=True) continue return events
def get_recording_pin_events(users_for_events: List[dict], min_ts: int, max_ts: int, count: int) -> List[APITimelineEvent]: """ Gets all recording pin events in the feed.""" id_username_map = { user['id']: user['musicbrainz_id'] for user in users_for_events } recording_pin_events_db = get_pins_for_feed( user_ids=(user['id'] for user in users_for_events), min_ts=min_ts, max_ts=max_ts, count=count, ) recording_pin_events_db = fetch_track_metadata_for_pins( recording_pin_events_db) events = [] for pin in recording_pin_events_db: try: pinEvent = APIPinEvent( user_name=id_username_map[pin.user_id], blurb_content=pin.blurb_content, track_metadata=TrackMetadata( artist_name=pin.track_metadata["artist_name"], track_name=pin.track_metadata["track_name"], release_name=None, additional_info=AdditionalInfo( recording_msid=pin.recording_msid, recording_mbid=pin.recording_mbid, artist_msid=pin.track_metadata["artist_msid"], ))) events.append( APITimelineEvent( event_type=UserTimelineEventType.RECORDING_PIN, user_name=pinEvent.user_name, created=pin.created.timestamp(), metadata=pinEvent, )) except pydantic.ValidationError as e: current_app.logger.error('Validation error: ' + str(e), exc_info=True) continue return events
def get_listen_events( users: List[Dict], min_ts: int, max_ts: int, ) -> List[APITimelineEvent]: """ Gets all listen events in the feed. """ # to avoid timeouts while fetching listen events, we want to make # sure that both min_ts and max_ts are defined. if only one of those # is set, calculate the other from it using a default window length. # if neither is set, use current time as max_ts and subtract window # length to get min_ts. if not min_ts and max_ts: min_ts = max_ts - DEFAULT_LISTEN_EVENT_WINDOW elif min_ts and not max_ts: max_ts = min_ts + DEFAULT_LISTEN_EVENT_WINDOW elif not min_ts and not max_ts: max_ts = int(datetime.now().timestamp()) min_ts = max_ts - DEFAULT_LISTEN_EVENT_WINDOW listens = timescale_connection._ts.fetch_recent_listens_for_users( users, min_ts=min_ts, max_ts=max_ts, per_user_limit=MAX_LISTEN_EVENTS_PER_USER, limit=MAX_LISTEN_EVENTS_OVERALL) events = [] for listen in listens: try: listen_dict = listen.to_api() listen_dict['inserted_at'] = listen_dict['inserted_at'].timestamp() api_listen = APIListen(**listen_dict) events.append( APITimelineEvent( event_type=UserTimelineEventType.LISTEN, user_name=api_listen.user_name, created=api_listen.listened_at, metadata=api_listen, )) except pydantic.ValidationError as e: current_app.logger.error('Validation error: ' + str(e), exc_info=True) continue return events