<s> """<STR_LIT>""" <EOL> __authors__ = [ '<STR_LIT>' , <EOL> '<STR_LIT>' ] <EOL> import json <EOL> import logging <EOL> from tornado import gen <EOL> from viewfinder . backend . base import util <EOL> from viewfinder . backend . db . activity import Activity <EOL> from viewfinder . backend . db . contact import Contact <EOL> from viewfinder . backend . db . device import Device <EOL> from viewfinder . backend . db . followed import Followed <EOL> from viewfinder . backend . db . notification import Notification <EOL> from viewfinder . backend . db . operation import Operation <EOL> from viewfinder . backend . db . settings import AccountSettings <EOL> class NotificationManager ( object ) : <EOL> """<STR_LIT>""" <EOL> MAX_INLINE_COMMENT_LEN = <NUM_LIT> <EOL> """<STR_LIT>""" <EOL> _QUERY_LIMIT = <NUM_LIT:100> <EOL> """<STR_LIT>""" <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def QuerySince ( cls , client , user_id , device_id , start_key , limit = None , scan_forward = True ) : <EOL> """<STR_LIT>""" <EOL> from viewfinder . backend . op . alert_manager import AlertManager <EOL> limit = NotificationManager . _QUERY_LIMIT if limit is None else limit <EOL> notifications = yield gen . Task ( Notification . RangeQuery , <EOL> client , <EOL> hash_key = user_id , <EOL> range_desc = None , <EOL> limit = limit , <EOL> col_names = None , <EOL> excl_start_key = start_key , <EOL> consistent_read = True , <EOL> scan_forward = scan_forward ) <EOL> if len ( notifications ) < limit and scan_forward : <EOL> if len ( notifications ) == <NUM_LIT:0> : <EOL> last_notification = yield Notification . QueryLast ( client , user_id , consistent_read = True ) <EOL> else : <EOL> last_notification = notifications [ - <NUM_LIT:1> ] <EOL> if last_notification is None or last_notification . badge == <NUM_LIT:0> : <EOL> raise gen . Return ( notifications ) <EOL> notification_id = last_notification . notification_id + <NUM_LIT:1> if last_notification else <NUM_LIT:0> <EOL> success = yield Notification . TryClearBadge ( client , user_id , device_id , notification_id ) <EOL> if not success : <EOL> results = yield NotificationManager . QuerySince ( client , user_id , device_id , start_key , scan_forward = scan_forward ) <EOL> raise gen . Return ( results ) <EOL> AlertManager . SendClearBadgesAlert ( client , user_id , exclude_device_id = device_id ) <EOL> raise gen . Return ( notifications ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyAddFollowers ( cls , client , viewpoint_id , existing_followers , new_followers , contact_user_ids , <EOL> act_dict , timestamp ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateAddFollowers , contact_user_ids ) <EOL> new_follower_ids = set ( follower . user_id for follower in new_followers ) <EOL> def _GetInvalidate ( follower_id ) : <EOL> if follower_id in new_follower_ids : <EOL> return { '<STR_LIT>' : [ NotificationManager . _CreateViewpointInvalidation ( viewpoint_id ) ] } <EOL> else : <EOL> return { '<STR_LIT>' : [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> viewpoint_id , <EOL> existing_followers + new_followers , <EOL> _GetInvalidate , <EOL> activity_func ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyCreateProspective ( cls , client , prospective_identity_keys , timestamp ) : <EOL> """<STR_LIT>""" <EOL> yield [ NotificationManager . _NotifyUsersWithContact ( client , <EOL> '<STR_LIT>' , <EOL> identity_key , <EOL> timestamp ) <EOL> for identity_key in prospective_identity_keys ] <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyFetchContacts ( cls , client , user_id , timestamp , reload_all ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : { '<STR_LIT>' : Contact . CreateSortKey ( None , <NUM_LIT:0> if reload_all else timestamp ) } } <EOL> if reload_all : <EOL> invalidate [ '<STR_LIT>' ] [ '<STR_LIT:all>' ] = True <EOL> yield NotificationManager . CreateForUser ( client , user_id , '<STR_LIT>' , invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyHidePhotos ( cls , client , user_id , ep_dicts ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : ep_dict [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : True } for ep_dict in ep_dicts ] } <EOL> yield NotificationManager . CreateForUser ( client , user_id , '<STR_LIT>' , invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyLinkIdentity ( cls , client , target_user_id , identity_key , timestamp ) : <EOL> """<STR_LIT>""" <EOL> yield NotificationManager . _NotifyUsersWithContact ( client , '<STR_LIT>' , identity_key , timestamp ) <EOL> yield NotificationManager . _NotifyUserInvalidateSelf ( client , '<STR_LIT>' , target_user_id ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyMergeIdentities ( cls , client , target_user_id , identity_keys , timestamp ) : <EOL> """<STR_LIT>""" <EOL> yield [ NotificationManager . _NotifyUsersWithContact ( client , '<STR_LIT>' , identity_key , timestamp ) <EOL> for identity_key in identity_keys ] <EOL> yield NotificationManager . _NotifyUserInvalidateSelf ( client , '<STR_LIT>' , target_user_id ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyMergeViewpoint ( cls , client , viewpoint_id , existing_followers , target_follower , <EOL> source_user_id , act_dict , timestamp ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , <EOL> Activity . CreateMergeAccounts , <EOL> target_follower . user_id , <EOL> source_user_id ) <EOL> def _GetInvalidate ( follower_id ) : <EOL> if follower_id == target_follower . user_id : <EOL> return { '<STR_LIT>' : [ NotificationManager . _CreateViewpointInvalidation ( viewpoint_id ) ] } <EOL> else : <EOL> return { '<STR_LIT>' : [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> viewpoint_id , <EOL> existing_followers + [ target_follower ] , <EOL> _GetInvalidate , <EOL> activity_func ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyPostComment ( cls , client , followers , act_dict , cm_dict ) : <EOL> """<STR_LIT>""" <EOL> from viewfinder . backend . db . comment import Comment <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreatePostComment , cm_dict ) <EOL> if len ( cm_dict [ '<STR_LIT:message>' ] ) > NotificationManager . MAX_INLINE_COMMENT_LEN : <EOL> start_key = Comment . ConstructCommentId ( cm_dict [ '<STR_LIT>' ] , <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : cm_dict [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : start_key } ] } <EOL> else : <EOL> invalidate = None <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> cm_dict [ '<STR_LIT>' ] , <EOL> followers , <EOL> invalidate , <EOL> activity_func , <EOL> inc_badge = True ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyRecordSubscription ( cls , client , user_id ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : [ user_id ] } <EOL> yield NotificationManager . CreateForUser ( client , <EOL> user_id , <EOL> '<STR_LIT>' , <EOL> invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyRegisterUser ( cls , client , user_dict , ident_dict , timestamp , is_first_register , is_linking ) : <EOL> """<STR_LIT>""" <EOL> from viewfinder . backend . op . alert_manager import AlertManager <EOL> if is_first_register or is_linking : <EOL> name = '<STR_LIT>' if is_first_register else '<STR_LIT>' <EOL> yield NotificationManager . _NotifyUsersWithContact ( client , name , ident_dict [ '<STR_LIT:key>' ] , timestamp ) <EOL> if any ( attr_name != '<STR_LIT>' for attr_name in user_dict . keys ( ) ) : <EOL> invalidate = { '<STR_LIT>' : [ user_dict [ '<STR_LIT>' ] ] } <EOL> yield NotificationManager . _NotifyFriends ( client , '<STR_LIT>' , user_dict [ '<STR_LIT>' ] , invalidate ) <EOL> elif is_first_register or is_linking : <EOL> yield NotificationManager . _NotifyUserInvalidateSelf ( client , '<STR_LIT>' , user_dict [ '<STR_LIT>' ] ) <EOL> if is_first_register : <EOL> @ gen . coroutine <EOL> def _VisitContactUserId ( contact_user_id ) : <EOL> settings = yield gen . Task ( AccountSettings . QueryByUser , client , contact_user_id , None ) <EOL> yield AlertManager . SendRegisterAlert ( client , user_dict [ '<STR_LIT>' ] , contact_user_id , settings ) <EOL> yield gen . Task ( Contact . VisitContactUserIds , client , ident_dict [ '<STR_LIT:key>' ] , _VisitContactUserId ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyRemoveContacts ( cls , client , user_id , timestamp , reload_all ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : { '<STR_LIT>' : Contact . CreateSortKey ( None , <NUM_LIT:0> if reload_all else timestamp ) } } <EOL> if reload_all : <EOL> invalidate [ '<STR_LIT>' ] [ '<STR_LIT:all>' ] = True <EOL> yield NotificationManager . CreateForUser ( client , user_id , '<STR_LIT>' , invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyRemoveFollowers ( cls , client , viewpoint_id , existing_followers , remove_ids , act_dict ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateRemoveFollowers , remove_ids ) <EOL> remove_id_set = set ( remove_ids ) <EOL> def _GetInvalidate ( follower_id ) : <EOL> if follower_id in remove_id_set : <EOL> return { '<STR_LIT>' : [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] } <EOL> else : <EOL> return { '<STR_LIT>' : [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> viewpoint_id , <EOL> existing_followers , <EOL> _GetInvalidate , <EOL> activity_func , <EOL> always_notify = True ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyRemovePhotos ( cls , client , user_id , ep_dicts ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : ep_dict [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : True } for ep_dict in ep_dicts ] } <EOL> yield NotificationManager . CreateForUser ( client , user_id , '<STR_LIT>' , invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyRemoveViewpoint ( cls , client , user_id , viewpoint_id ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] } <EOL> yield NotificationManager . CreateForUser ( client , <EOL> user_id , <EOL> '<STR_LIT>' , <EOL> invalidate = invalidate , <EOL> viewpoint_id = viewpoint_id ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyReviveFollowers ( cls , client , viewpoint_id , revive_follower_ids , timestamp ) : <EOL> """<STR_LIT>""" <EOL> if len ( revive_follower_ids ) > <NUM_LIT:0> : <EOL> invalidate = { '<STR_LIT>' : [ NotificationManager . _CreateViewpointInvalidation ( viewpoint_id ) ] } <EOL> yield [ NotificationManager . CreateForUser ( client , <EOL> follower_id , <EOL> '<STR_LIT>' , <EOL> invalidate = invalidate , <EOL> viewpoint_id = viewpoint_id ) <EOL> for follower_id in revive_follower_ids ] <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifySavePhotos ( cls , client , viewpoint_id , follower , act_dict , ep_dicts ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateSavePhotos , ep_dicts ) <EOL> invalidate = { '<STR_LIT>' : [ NotificationManager . _CreateEpisodeInvalidation ( ep_dict [ '<STR_LIT>' ] ) <EOL> for ep_dict in ep_dicts ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , viewpoint_id , [ follower ] , invalidate , activity_func ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyShareExisting ( cls , client , viewpoint_id , followers , act_dict , ep_dicts , viewpoint_updated ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateShareExisting , ep_dicts ) <EOL> invalidate = { '<STR_LIT>' : [ NotificationManager . _CreateEpisodeInvalidation ( ep_dict [ '<STR_LIT>' ] ) <EOL> for ep_dict in ep_dicts ] } <EOL> if viewpoint_updated : <EOL> invalidate [ '<STR_LIT>' ] = [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> viewpoint_id , <EOL> followers , <EOL> invalidate , <EOL> activity_func , <EOL> inc_badge = True ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyShareNew ( cls , client , vp_dict , followers , contact_user_ids , act_dict , ep_dicts , timestamp ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , <EOL> Activity . CreateShareNew , <EOL> ep_dicts , <EOL> contact_user_ids ) <EOL> invalidate = { '<STR_LIT>' : [ NotificationManager . _CreateViewpointInvalidation ( vp_dict [ '<STR_LIT>' ] ) ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> vp_dict [ '<STR_LIT>' ] , <EOL> followers , <EOL> invalidate , <EOL> activity_func , <EOL> inc_badge = True ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyTerminateAccount ( cls , client , user_id ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : [ user_id ] } <EOL> yield NotificationManager . _NotifyFriends ( client , '<STR_LIT>' , user_id , invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUnshare ( cls , client , viewpoint_id , followers , act_dict , ep_dicts , viewpoint_updated ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateUnshare , ep_dicts ) <EOL> invalidate = { '<STR_LIT>' : [ NotificationManager . _CreateEpisodeInvalidation ( ep_dict [ '<STR_LIT>' ] ) <EOL> for ep_dict in ep_dicts ] } <EOL> if viewpoint_updated : <EOL> invalidate [ '<STR_LIT>' ] = [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] <EOL> yield NotificationManager . _NotifyFollowers ( client , <EOL> viewpoint_id , <EOL> followers , <EOL> invalidate , <EOL> activity_func , <EOL> inc_badge = True ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUpdateEpisode ( cls , client , viewpoint_id , followers , act_dict , ep_dict ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateUpdateEpisode , ep_dict ) <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : ep_dict [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : True } ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , viewpoint_id , followers , invalidate , activity_func ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUpdateFriend ( cls , client , friend_dict ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : [ friend_dict [ '<STR_LIT>' ] ] } <EOL> yield NotificationManager . CreateForUser ( client , <EOL> NotificationManager . _GetOperation ( ) . user_id , <EOL> '<STR_LIT>' , <EOL> invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUpdateFollower ( cls , client , foll_dict ) : <EOL> """<STR_LIT>""" <EOL> viewpoint_id = foll_dict [ '<STR_LIT>' ] <EOL> seq_num_pair = None <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : viewpoint_id , <EOL> '<STR_LIT>' : True } ] } <EOL> if '<STR_LIT>' in foll_dict : <EOL> seq_num_pair = ( None , foll_dict [ '<STR_LIT>' ] ) <EOL> if len ( foll_dict ) == <NUM_LIT:2> : <EOL> invalidate = None <EOL> yield NotificationManager . CreateForUser ( client , <EOL> NotificationManager . _GetOperation ( ) . user_id , <EOL> '<STR_LIT>' , <EOL> invalidate = invalidate , <EOL> viewpoint_id = viewpoint_id , <EOL> seq_num_pair = seq_num_pair ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUpdateUser ( cls , client , user_dict , settings_dict , timestamp ) : <EOL> """<STR_LIT>""" <EOL> user_id = user_dict [ '<STR_LIT>' ] <EOL> if any ( attr_name not in ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) for attr_name in user_dict . keys ( ) ) : <EOL> invalidate = { '<STR_LIT>' : [ user_id ] } <EOL> yield NotificationManager . _NotifyFriends ( client , '<STR_LIT>' , user_dict [ '<STR_LIT>' ] , invalidate ) <EOL> else : <EOL> invalidate = { '<STR_LIT>' : [ user_dict [ '<STR_LIT>' ] ] } <EOL> yield NotificationManager . CreateForUser ( client , user_id , '<STR_LIT>' , invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUpdateViewpoint ( cls , client , vp_dict , followers , prev_values , act_dict ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateUpdateViewpoint , prev_values ) <EOL> invalidate = { '<STR_LIT>' : [ { '<STR_LIT>' : vp_dict [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : True } ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , vp_dict [ '<STR_LIT>' ] , followers , invalidate , activity_func ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUnlinkIdentity ( cls , client , user_id , identity_key , timestamp ) : <EOL> """<STR_LIT>""" <EOL> yield NotificationManager . _NotifyUsersWithContact ( client , '<STR_LIT>' , identity_key , timestamp ) <EOL> yield NotificationManager . _NotifyUserInvalidateSelf ( client , '<STR_LIT>' , user_id ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUploadContacts ( cls , client , user_id , timestamp ) : <EOL> """<STR_LIT>""" <EOL> invalidate = { '<STR_LIT>' : { '<STR_LIT>' : Contact . CreateSortKey ( None , timestamp ) } } <EOL> yield NotificationManager . CreateForUser ( client , user_id , '<STR_LIT>' , invalidate = invalidate ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def NotifyUploadEpisode ( cls , client , viewpoint_id , follower , act_dict , ep_dict , ph_dicts ) : <EOL> """<STR_LIT>""" <EOL> activity_func = NotificationManager . _CreateActivityFunc ( act_dict , Activity . CreateUploadEpisode , <EOL> ep_dict , ph_dicts ) <EOL> invalidate = { '<STR_LIT>' : [ NotificationManager . _CreateEpisodeInvalidation ( ep_dict [ '<STR_LIT>' ] ) ] } <EOL> yield NotificationManager . _NotifyFollowers ( client , viewpoint_id , [ follower ] , invalidate , activity_func ) <EOL> @ classmethod <EOL> def _GetOperation ( cls ) : <EOL> """<STR_LIT>""" <EOL> operation = Operation . GetCurrent ( ) <EOL> assert operation . operation_id is not None , '<STR_LIT>' <EOL> return operation <EOL> @ classmethod <EOL> def _CreateActivityFunc ( cls , act_dict , create_func , * args ) : <EOL> """<STR_LIT>""" <EOL> @ gen . coroutine <EOL> def _CreateActivity ( client , user_id , viewpoint_id , update_seq ) : <EOL> activity = yield create_func ( client , <EOL> user_id , <EOL> viewpoint_id , <EOL> act_dict [ '<STR_LIT>' ] , <EOL> act_dict [ '<STR_LIT>' ] , <EOL> update_seq , <EOL> * args ) <EOL> raise gen . Return ( activity ) <EOL> return _CreateActivity <EOL> @ classmethod <EOL> def _CreateViewpointInvalidation ( cls , viewpoint_id ) : <EOL> """<STR_LIT>""" <EOL> return { '<STR_LIT>' : viewpoint_id , '<STR_LIT>' : True , '<STR_LIT>' : True , <EOL> '<STR_LIT>' : True , '<STR_LIT>' : True , '<STR_LIT>' : True } <EOL> @ classmethod <EOL> def _CreateEpisodeInvalidation ( cls , episode_id ) : <EOL> """<STR_LIT>""" <EOL> return { '<STR_LIT>' : episode_id , '<STR_LIT>' : True , '<STR_LIT>' : True } <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def _NotifyUsersWithContact ( cls , client , name , identity_key , timestamp ) : <EOL> """<STR_LIT>""" <EOL> @ gen . coroutine <EOL> def _VisitContactUserId ( contact_user_id ) : <EOL> yield NotificationManager . CreateForUser ( client , <EOL> contact_user_id , <EOL> name , <EOL> invalidate = invalidate ) <EOL> invalidate = { '<STR_LIT>' : { '<STR_LIT>' : Contact . CreateSortKey ( None , timestamp ) } } <EOL> yield gen . Task ( Contact . VisitContactUserIds , client , identity_key , _VisitContactUserId ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def _NotifyUserInvalidateSelf ( cls , client , name , user_id ) : <EOL> """<STR_LIT>""" <EOL> yield NotificationManager . CreateForUser ( client , <EOL> user_id , <EOL> name , <EOL> invalidate = { '<STR_LIT>' : [ user_id ] } ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def _NotifyFriends ( cls , client , name , user_id , invalidate ) : <EOL> """<STR_LIT>""" <EOL> from viewfinder . backend . db . friend import Friend <EOL> @ gen . coroutine <EOL> def _VisitFriend ( friend ) : <EOL> yield NotificationManager . CreateForUser ( client , <EOL> friend . friend_id , <EOL> name , <EOL> invalidate = invalidate ) <EOL> yield gen . Task ( Friend . VisitRange , client , user_id , None , None , _VisitFriend ) <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def _NotifyFollowers ( cls , client , viewpoint_id , followers , invalidate , activity_func , <EOL> inc_badge = False , always_notify = False ) : <EOL> """<STR_LIT>""" <EOL> from viewfinder . backend . db . viewpoint import Viewpoint <EOL> from viewfinder . backend . op . alert_manager import AlertManager <EOL> operation = NotificationManager . _GetOperation ( ) <EOL> @ gen . coroutine <EOL> def _NotifyOneFollower ( viewpoint , seq_num_pair , activity , follower , follower_settings ) : <EOL> """<STR_LIT>""" <EOL> if follower . IsRemoved ( ) and not always_notify : <EOL> return <EOL> if invalidate is None or isinstance ( invalidate , dict ) : <EOL> foll_invalidate = invalidate <EOL> else : <EOL> foll_invalidate = invalidate ( follower . user_id ) <EOL> is_sending_user = follower . user_id == operation . user_id <EOL> notification = yield Notification . CreateForUser ( client , <EOL> operation , <EOL> follower . user_id , <EOL> activity . name , <EOL> invalidate = foll_invalidate , <EOL> activity_id = activity . activity_id , <EOL> viewpoint_id = viewpoint_id , <EOL> seq_num_pair = seq_num_pair , <EOL> inc_badge = inc_badge and not is_sending_user ) <EOL> if not is_sending_user : <EOL> yield AlertManager . SendFollowerAlert ( client , <EOL> follower . user_id , <EOL> notification . badge , <EOL> viewpoint , <EOL> follower , <EOL> follower_settings , <EOL> activity ) <EOL> Viewpoint . AssertViewpointLockAcquired ( viewpoint_id ) <EOL> viewpoint = yield gen . Task ( Viewpoint . Query , client , viewpoint_id , None ) <EOL> sending_follower = next ( ( follower for follower in followers if follower . user_id == operation . user_id ) , None ) <EOL> viewpoint . update_seq += <NUM_LIT:1> <EOL> if sending_follower is not None : <EOL> sending_follower . viewed_seq += <NUM_LIT:1> <EOL> seq_num_pair = ( viewpoint . update_seq , sending_follower . viewed_seq ) <EOL> else : <EOL> seq_num_pair = ( viewpoint . update_seq , None ) <EOL> activity_task = activity_func ( client , operation . user_id , viewpoint_id , viewpoint . update_seq ) <EOL> follower_keys = [ AccountSettings . ConstructKey ( follower . user_id ) for follower in followers ] <EOL> settings_task = gen . Task ( AccountSettings . BatchQuery , client , follower_keys , None , must_exist = False ) <EOL> followed_task = gen . Multi ( [ gen . Task ( Followed . UpdateDateUpdated , <EOL> client , <EOL> follower . user_id , <EOL> viewpoint_id , <EOL> viewpoint . last_updated , <EOL> operation . timestamp ) <EOL> for follower in followers ] ) <EOL> activity , all_follower_settings , _ = yield [ activity_task , settings_task , followed_task ] <EOL> if operation . timestamp > viewpoint . last_updated : <EOL> viewpoint . last_updated = operation . timestamp <EOL> yield [ gen . Task ( viewpoint . Update , client ) , <EOL> gen . Task ( sending_follower . Update , client ) if sending_follower is not None else util . GenConstant ( None ) ] <EOL> yield [ _NotifyOneFollower ( viewpoint , seq_num_pair , activity , follower , follower_settings ) <EOL> for follower , follower_settings in zip ( followers , all_follower_settings ) ] <EOL> @ classmethod <EOL> @ gen . coroutine <EOL> def CreateForUser ( cls , client , user_id , name , invalidate = None , <EOL> activity_id = None , viewpoint_id = None , seq_num_pair = None , <EOL> inc_badge = False , consistent_read = False ) : <EOL> """<STR_LIT>""" <EOL> operation = NotificationManager . _GetOperation ( ) <EOL> notification = yield Notification . CreateForUser ( client , <EOL> operation , <EOL> user_id , <EOL> name , <EOL> invalidate , <EOL> activity_id , <EOL> viewpoint_id , <EOL> seq_num_pair , <EOL> inc_badge , <EOL> consistent_read ) <EOL> raise gen . Return ( notification ) </s>
