def postUpdateHook(cls, matches, updated_attr_list, is_new_list): ''' To run after the match has been updated. Send push notifications to subscribed users Only if the match is part of an active event ''' unplayed_match_events = [] for (match, updated_attrs, is_new) in zip(matches, updated_attr_list, is_new_list): event = match.event.get() # Only continue if the event is currently happening if event.within_a_day: if match.has_been_played: if is_new or 'alliances_json' in updated_attrs: # There is a score update for this match, push a notification logging.info("Sending push notifications for {}".format(match.key_name)) try: NotificationHelper.send_match_score_update(match) except Exception, exception: logging.error("Error sending match updates: {}".format(exception)) logging.error(traceback.format_exc()) else: if is_new or (set(['alliances_json', 'time', 'time_string']).intersection(set(updated_attrs)) != set()): # The match has not been played and we're changing a property that affects the event's schedule # So send a schedule update notification for the parent event if event not in unplayed_match_events: unplayed_match_events.append(event)
def add_subscription(cls, sub, device_key=""): current = Subscription.query(Subscription.model_key == sub.model_key, Subscription.model_type == sub.model_type, ancestor=ndb.Key(Account, sub.user_id)).get() if current is None: # Subscription doesn't exist, add it sub.put() # Send updates to user's other devices NotificationHelper.send_subscription_update( sub.user_id, device_key) return 200 else: if len( set(current.notification_types).symmetric_difference( set(sub.notification_types))) == 0: # Subscription already exists. Don't add it again return 304 else: # We're updating the settings current.notification_types = sub.notification_types current.put() # Send updates to user's other devices NotificationHelper.send_subscription_update( sub.user_id, device_key) return 200
def postUpdateHook(cls, events, updated_attr_list, is_new_list): """ To run after models have been updated """ for (event, updated_attrs) in zip(events, updated_attr_list): try: if event.within_a_day and "alliance_selections_json" in updated_attrs: # Send updated alliances notification logging.info( "Sending alliance notifications for {}".format( event.key_name)) NotificationHelper.send_alliance_update(event) except Exception: logging.error( "Error sending alliance update notification for {}".format( event.key_name)) logging.error(traceback.format_exc()) try: event.timezone_id = EventHelper.get_timezone_id( event.location, event.key.id()) cls.createOrUpdate(event, run_post_update_hook=False) except Exception: logging.warning("Timezone update for event {} failed!".format( event.key_name)) # Enqueue task to calculate district points for event in events: taskqueue.add(url='/tasks/math/do/district_points_calc/{}'.format( event.key.id()), method='GET')
def postUpdateHook(cls, matches, updated_attr_list, is_new_list): ''' To run after the match has been updated. Send push notifications to subscribed users Only if the match is part of an active event ''' unplayed_match_events = [] for (match, updated_attrs, is_new) in zip(matches, updated_attr_list, is_new_list): event = match.event.get() # Only continue if the event is currently happening if event.within_a_day: if match.has_been_played: if is_new or 'alliances_json' in updated_attrs: # There is a score update for this match, push a notification logging.info("Sending push notifications for {}".format(match.key_name)) try: NotificationHelper.send_match_score_update(match) except Exception, exception: logging.error("Error sending match updates: {}".format(exception)) logging.error(traceback.format_exc()) else: if is_new or (set(['alliances_json', 'time', 'time_string']).intersection(set(updated_attrs)) != set()): # The match has not been played and we're changing a property that affects the event's schedule # So send a schedule update notification for the parent event if event not in unplayed_match_events: unplayed_match_events.append(event)
def postUpdateHook(cls, awards, updated_attr_list, is_new_list): # Note, updated_attr_list will always be empty, for now # Still needs to be implemented in updateMerge # See helpers.EventManipulator events = [] for (award, updated_attrs) in zip(awards, updated_attr_list): event = award.event if event not in events: events.append(event) for event in events: if event.get().within_a_day: try: NotificationHelper.send_award_update(event.get()) except Exception: logging.error("Error sending award update for {}".format( event.id())) try: TBANSHelper.awards(event.get()) except Exception: logging.error("Error sending award update for {}".format( event.id())) # Enqueue task to calculate district points for event in events: taskqueue.add(url='/tasks/math/do/district_points_calc/{}'.format( event.id()), method='GET')
def postUpdateHook(cls, event_details_list, updated_attr_list, is_new_list): """ To run after models have been updated """ for (event_details, updated_attrs) in zip(event_details_list, updated_attr_list): event = Event.get_by_id(event_details.key.id()) try: if event.within_a_day and "alliance_selections" in updated_attrs: # Send updated alliances notification logging.info( "Sending alliance notifications for {}".format( event.key_name)) NotificationHelper.send_alliance_update(event) except Exception: logging.error( "Error sending alliance update notification for {}".format( event.key_name)) logging.error(traceback.format_exc()) # Enqueue task to calculate district points try: taskqueue.add( url='/tasks/math/do/district_points_calc/{}'.format( event.key.id()), method='GET') except Exception: logging.error( "Error enqueuing district_points_calc for {}".format( event.key.id())) logging.error(traceback.format_exc())
def postUpdateHook(cls, events, updated_attr_list, is_new_list): """ To run after models have been updated """ for (event, updated_attrs) in zip(events, updated_attr_list): try: if event.within_a_day and "alliance_selections_json" in updated_attrs: # Send updated alliances notification logging.info("Sending alliance notifications for {}".format(event.key_name)) NotificationHelper.send_alliance_update(event) except Exception: logging.error("Error sending alliance update notification for {}".format(event.key_name)) logging.error(traceback.format_exc()) try: event.timezone_id = EventHelper.get_timezone_id(event.location, event.key.id()) cls.createOrUpdate(event, run_post_update_hook=False) except Exception: logging.warning("Timezone update for event {} failed!".format(event.key_name)) # Enqueue task to calculate district points for event in events: taskqueue.add( url='/tasks/math/do/district_points_calc/{}'.format(event.key.id()), method='GET')
def remove_subscription(cls, userId, modelKey, device_key=""): to_delete = Subscription.query(Subscription.model_key == modelKey, ancestor=ndb.Key(Account, userId)).fetch(keys_only=True) if len(to_delete) > 0: ndb.delete_multi(to_delete) # Send updates to user's other devices NotificationHelper.send_subscription_update(userId, device_key) return 200 else: # Subscription doesn't exist. Can't delete it return 404
def add_favorite(cls, fav, device_key=""): if Favorite.query(Favorite.model_key == fav.model_key, ancestor=ndb.Key(Account, fav.user_id)).count() == 0: # Favorite doesn't exist, add it fav.put() # Send updates to user's other devices NotificationHelper.send_favorite_update(fav.user_id, device_key) return 200 else: # Favorite already exists. Don't add it again return 304
def remove_subscription(cls, userId, modelKey, device_key=""): to_delete = Subscription.query(Subscription.model_key == modelKey, ancestor=ndb.Key(Account, userId)).fetch(keys_only=True) if len(to_delete) > 0: ndb.delete_multi(to_delete) if device_key: # Send updates to user's other devices NotificationHelper.send_subscription_update(userId, device_key) return 200 else: # Subscription doesn't exist. Can't delete it return 404
def remove_favorite(cls, user_id, model_key, model_type, device_key=""): to_delete = Favorite.query(Favorite.model_key == model_key, Favorite.model_type == model_type, ancestor=ndb.Key(Account, user_id)).fetch(keys_only=True) if len(to_delete) > 0: ndb.delete_multi(to_delete) # Send updates to user's other devices NotificationHelper.send_favorite_update(user_id, device_key) return 200 else: # Favorite doesn't exist. Can't delete it return 404
def add_favorite(cls, fav, device_key=""): if Favorite.query(Favorite.model_key == fav.model_key, ancestor=ndb.Key(Account, fav.user_id)).count() == 0: # Favorite doesn't exist, add it fav.put() if device_key: # Send updates to user's other devices NotificationHelper.send_favorite_update(fav.user_id, device_key) return 200 else: # Favorite already exists. Don't add it again return 304
def remove_favorite(cls, userId, modelKey, device_key=""): to_delete = Favorite.query(Favorite.model_key == modelKey, ancestor=ndb.Key( Account, userId)).fetch(keys_only=True) if len(to_delete) > 0: ndb.delete_multi(to_delete) # Send updates to user's other devices NotificationHelper.send_favorite_update(userId, device_key) return 200 else: # Favorite doesn't exist. Can't delete it return 404
def postUpdateHook(cls, event_details_list, updated_attr_list, is_new_list): """ To run after models have been updated """ for (event_details, updated_attrs) in zip(event_details_list, updated_attr_list): event = Event.get_by_id(event_details.key.id()) if event.within_a_day and "alliance_selections" in updated_attrs: try: NotificationHelper.send_alliance_update(event) except Exception: logging.error( "Error sending alliance update notification for {}". format(event.key_name)) logging.error(traceback.format_exc()) try: TBANSHelper.alliance_selection(event) except Exception: logging.error( "Error sending alliance update notification for {}". format(event.key_name)) logging.error(traceback.format_exc()) # Enqueue task to calculate district points try: taskqueue.add( url='/tasks/math/do/district_points_calc/{}'.format( event.key.id()), method='GET') except Exception: logging.error( "Error enqueuing district_points_calc for {}".format( event.key.id())) logging.error(traceback.format_exc()) # Enqueue task to calculate event team status try: taskqueue.add(url='/tasks/math/do/event_team_status/{}'.format( event.key.id()), method='GET') except Exception: logging.error( "Error enqueuing event_team_status for {}".format( event.key.id())) logging.error(traceback.format_exc()) try: FirebasePusher.update_event_details(event_details) except Exception: logging.warning("Firebase update_event_details failed!")
def postUpdateHook(cls, event_details_list, updated_attr_list, is_new_list): """ To run after models have been updated """ for (event_details, updated_attrs) in zip(event_details_list, updated_attr_list): event = Event.get_by_id(event_details.key.id()) try: if event.within_a_day and "alliance_selections" in updated_attrs: # Send updated alliances notification logging.info("Sending alliance notifications for {}".format(event.key_name)) NotificationHelper.send_alliance_update(event) except Exception: logging.error("Error sending alliance update notification for {}".format(event.key_name)) logging.error(traceback.format_exc())
def post(self): self._require_registration() # Check to make sure that they aren't trying to edit another user current_user_account_id = self.user_bundle.account.key.id() target_account_id = self.request.get('account_id') if target_account_id == current_user_account_id: client_id = self.request.get('client_id') client = MobileClient.get_by_id(int(client_id), parent=ndb.Key(Account, current_user_account_id)) if client is not None: # This makes sure that the client actually exists and that this user owns it NotificationHelper.send_ping(client) return self.redirect('/account?ping_sent=1') self.redirect('/')
def postUpdateHook(cls, matches): ''' To run after the match has been updated. Send push notifications to subscribed users Only if the match is part of an active event ''' for match in matches: if match.event.get().now: logging.info("Sending push notifications for " + match.key_name) try: NotificationHelper.send_match_score_update(match) except Exception, exception: logging.error("Error sending match updates: " + str(exception))
def post(self): self._require_login() self._require_registration() # Check to make sure that they aren't trying to edit another user current_user_account_id = self.user_bundle.account.key.id() target_account_id = self.request.get('account_id') if target_account_id == current_user_account_id: url = self.request.get('url') secret_key = self.request.get('secret') query = MobileClient.query(MobileClient.messaging_id == url, ancestor=ndb.Key( Account, current_user_account_id)) if query.count() == 0: # Webhook doesn't exist, add it verification_key = NotificationHelper.verify_webhook( url, secret_key) client = MobileClient(parent=self.user_bundle.account.key, user_id=current_user_account_id, messaging_id=url, display_name=self.request.get('name'), secret=secret_key, client_type=ClientType.WEBHOOK, verified=False, verification_code=verification_key) client.put() else: # Webhook already exists. Update the secret current = query.fetch()[0] current.secret = secret_key current.put() self.redirect('/account') else: self.redirect('/')
def post(self): self._require_login() self._require_registration() current_user_account_id = self.user_bundle.account.key.id() target_account_id = self.request.get('account_id') if target_account_id == current_user_account_id: client_id = self.request.get('client_id') webhook = MobileClient.get_by_id(int(client_id), parent=ndb.Key( Account, current_user_account_id)) if webhook.client_type == ClientType.WEBHOOK and current_user_account_id == webhook.user_id: verification_key = NotificationHelper.verify_webhook( webhook.messaging_id, webhook.secret) webhook.verification_code = verification_key webhook.verified = False webhook.put() self.redirect('/account') return else: logging.warning("Not webhook, or wrong owner") else: logging.warning("Users don't match. " + current_user_account_id + "/" + target_account_id) self.redirect('/')
def postUpdateHook(cls, awards, updated_attr_list, is_new_list): # Note, updated_attr_list will always be empty, for now # Still needs to be implemented in updateMerge # See helpers.EventManipulator events = [] for (award, updated_attrs) in zip(awards, updated_attr_list): event = award.event if event not in events: events.append(event) for event in events: if event.get().within_a_day: try: NotificationHelper.send_award_update(event.get()) except Exception: logging.error("Error sending award update for {}".format(event.id()))
def ping_client(self, request): current_user = endpoints.get_current_user() if current_user is None: return BaseResponse(code=401, message="Unauthorized to ping client") user_id = PushHelper.user_email_to_id(current_user.email()) gcm_id = request.mobile_id # Find a Client for the current user with the passed GCM ID clients = MobileClient.query(MobileClient.messaging_id == gcm_id, ancestor=ndb.Key(Account, user_id)).fetch(1) if len(clients) == 0: # No Client for user with that push token - bailing return BaseResponse(code=404, message="Invalid push token for user") else: client = clients[0] response = NotificationHelper.send_ping(client) # If we got a response from the send_ping method, it was sent via TBANS # We'll bubble up any errors we got back if response: if response.code == 200: return BaseResponse(code=200, message="Ping sent") else: return BaseResponse(code=response.code, message="Error pinging client - {}".format(response.message)) else: return BaseResponse(code=200, message="Ping sent")
def ping_client(self, request): user_id = get_current_user_id(self.headers) if user_id is None: return BaseResponse(code=401, message="Unauthorized to ping client") gcm_id = request.mobile_id # Find a Client for the current user with the passed GCM ID clients = MobileClient.query(MobileClient.messaging_id == gcm_id, ancestor=ndb.Key(Account, user_id)).fetch(1) if len(clients) == 0: # No Client for user with that push token - bailing return BaseResponse(code=404, message="Invalid push token for user") else: client = clients[0] response = NotificationHelper.send_ping(client) # If we got a response from the send_ping method, it was sent via TBANS # We'll bubble up any errors we got back if response: if response.code == 200: return BaseResponse(code=200, message="Ping sent") else: return BaseResponse( code=response.code, message="Error pinging client - {}".format( response.message)) else: return BaseResponse(code=200, message="Ping sent")
def post(self): self._require_login("/account/register") self._require_registration("/account/register") # Check to make sure that they aren't trying to edit another user current_user_account_id = self.user_bundle.account.key.id() target_account_id = self.request.get("account_id") if target_account_id == current_user_account_id: url = self.request.get("url") secret_key = self.request.get("secret") query = MobileClient.query( MobileClient.messaging_id == url, ancestor=ndb.Key(Account, current_user_account_id) ) if query.count() == 0: # Webhook doesn't exist, add it verification_key = NotificationHelper.verify_webhook(url, secret_key) client = MobileClient( parent=self.user_bundle.account.key, user_id=current_user_account_id, messaging_id=url, display_name=self.request.get("name"), secret=secret_key, client_type=ClientType.WEBHOOK, verified=False, verification_code=verification_key, ) client.put() else: # Webhook already exists. Update the secret current = query.fetch()[0] current.secret = secret_key current.put() self.redirect("/account") else: self.redirect("/")
def ping_client(self, request): current_user = endpoints.get_current_user() if current_user is None: return BaseResponse(code=401, message="Unauthorized to ping client") user_id = PushHelper.user_email_to_id(current_user.email()) gcm_id = request.mobile_id # Find a Client for the current user with the passed GCM ID clients = MobileClient.query(MobileClient.messaging_id == gcm_id, ancestor=ndb.Key(Account, user_id)).fetch(1) if len(clients) == 0: # No Client for user with that push token - bailing return BaseResponse(code=404, message="Invalid push token for user") else: client = clients[0] NotificationHelper.send_ping(client) return BaseResponse(code=200, message="Ping sent")
def post(self): self._require_registration() # Check to make sure that they aren't trying to edit another user current_user_account_id = self.user_bundle.account.key.id() target_account_id = self.request.get('account_id') if target_account_id == current_user_account_id: client_id = self.request.get('client_id') client = MobileClient.get_by_id(int(client_id), parent=ndb.Key( Account, current_user_account_id)) if client is not None: # This makes sure that the client actually exists and that this user owns it NotificationHelper.send_ping(client) return self.redirect('/account?ping_sent=1') self.redirect('/')
class MatchManipulator(ManipulatorBase): """ Handle Match database writes. """ @classmethod def getCacheKeysAndControllers(cls, affected_refs): return CacheClearer.get_match_cache_keys_and_controllers(affected_refs) @classmethod def postDeleteHook(cls, matches): ''' To run after the match has been deleted. ''' for match in matches: try: FirebasePusher.delete_match(match) except Exception: logging.warning("Enqueuing Firebase delete failed!") @classmethod def postUpdateHook(cls, matches, updated_attr_list, is_new_list): ''' To run after the match has been updated. Send push notifications to subscribed users Only if the match is part of an active event ''' unplayed_match_events = [] for (match, updated_attrs, is_new) in zip(matches, updated_attr_list, is_new_list): event = match.event.get() # Only continue if the event is currently happening if event.within_a_day: if match.has_been_played: if is_new or 'alliances_json' in updated_attrs: # There is a score update for this match, push a notification logging.info("Sending push notifications for {}".format(match.key_name)) try: NotificationHelper.send_match_score_update(match) except Exception, exception: logging.error("Error sending match updates: {}".format(exception)) logging.error(traceback.format_exc()) else: if is_new or (set(['alliances_json', 'time', 'time_string']).intersection(set(updated_attrs)) != set()): # The match has not been played and we're changing a property that affects the event's schedule # So send a schedule update notification for the parent event if event not in unplayed_match_events: unplayed_match_events.append(event) ''' If we have an unplayed match during an event within a day, send out a schedule update notification ''' for event in unplayed_match_events: try: logging.info("Sending schedule updates for: {}".format(event.key_name)) NotificationHelper.send_schedule_update(event) except Exception, exception: logging.error("Eror sending schedule updates for: {}".format(event.key_name))
def add_subscription(cls, sub, device_key=""): current = Subscription.query(Subscription.model_key == sub.model_key, ancestor=ndb.Key(Account, sub.user_id)).get() if current is None: # Subscription doesn't exist, add it sub.put() # Send updates to user's other devices NotificationHelper.send_subscription_update(sub.user_id, device_key) return 200 else: if current.notification_types == sub.notification_types: # Subscription already exists. Don't add it again return 304 else: # We're updating the settings current.notification_types = sub.notification_types current.put() # Send updates to user's other devices NotificationHelper.send_subscription_update(sub.user_id, device_key) return 200
def postUpdateHook(cls, awards, updated_attr_list, is_new_list): # Note, updated_attr_list will always be empty, for now # Still needs to be implemented in updateMerge # See helpers.EventManipulator events = [] for (award, updated_attrs) in zip(awards, updated_attr_list): event = award.event if event not in events: events.append(event) for event in events: if event.get().within_a_day: try: NotificationHelper.send_award_update(event.get()) except Exception: logging.error("Error sending award update for {}".format(event.id())) # Enqueue task to calculate district points for event in events: taskqueue.add( url='/tasks/math/do/district_points_calc/{}'.format(event.id()), method='GET')
def postUpdateHook(cls, event_details_list, updated_attr_list, is_new_list): """ To run after models have been updated """ for (event_details, updated_attrs) in zip(event_details_list, updated_attr_list): event = Event.get_by_id(event_details.key.id()) try: if event.within_a_day and "alliance_selections" in updated_attrs: # Send updated alliances notification logging.info("Sending alliance notifications for {}".format(event.key_name)) NotificationHelper.send_alliance_update(event) except Exception: logging.error("Error sending alliance update notification for {}".format(event.key_name)) logging.error(traceback.format_exc()) # Enqueue task to calculate district points try: taskqueue.add( url='/tasks/math/do/district_points_calc/{}'.format(event.key.id()), method='GET') except Exception: logging.error("Error enqueuing district_points_calc for {}".format(event.key.id())) logging.error(traceback.format_exc())
def post(self): self._require_registration() current_user_account_id = self.user_bundle.account.key.id() target_account_id = self.request.get('account_id') if target_account_id == current_user_account_id: client_id = self.request.get('client_id') webhook = MobileClient.get_by_id(int(client_id), parent=ndb.Key(Account, current_user_account_id)) if webhook.client_type == ClientType.WEBHOOK and current_user_account_id == webhook.user_id: verification_key = NotificationHelper.verify_webhook(webhook.messaging_id, webhook.secret) webhook.verification_code = verification_key webhook.verified = False webhook.put() self.redirect('/account') return else: logging.warning("Not webhook, or wrong owner") else: logging.warning("Users don't match. "+current_user_account_id+"/"+target_account_id) self.redirect('/')
def get(self): live_events = EventHelper.getEventsWithinADay() NotificationHelper.send_upcoming_matches(live_events)
if '_video_added' in updated_attrs: try: NotificationHelper.send_match_video(match) except Exception, exception: logging.error( "Error sending match video updates: {}".format( exception)) logging.error(traceback.format_exc()) ''' If we have an unplayed match during an event within a day, send out a schedule update notification ''' for event in unplayed_match_events: try: logging.info("Sending schedule updates for: {}".format( event.key_name)) NotificationHelper.send_schedule_update(event) except Exception, exception: logging.error("Eror sending schedule updates for: {}".format( event.key_name)) ''' Enqueue firebase push ''' affected_stats_event_keys = set() for (match, updated_attrs, is_new) in zip(matches, updated_attr_list, is_new_list): # Only attrs that affect stats if is_new or set(['alliances_json', 'score_breakdown_json' ]).intersection(set(updated_attrs)) != set(): affected_stats_event_keys.add(match.event.id()) try: FirebasePusher.update_match(match)
def get(self): live_events = EventHelper.getEventsWithinADay() NotificationHelper.send_upcoming_matches(live_events)
# Try to send video notifications if '_video_added' in updated_attrs: try: NotificationHelper.send_match_video(match) except Exception, exception: logging.error("Error sending match video updates: {}".format(exception)) logging.error(traceback.format_exc()) ''' If we have an unplayed match during an event within a day, send out a schedule update notification ''' for event in unplayed_match_events: try: logging.info("Sending schedule updates for: {}".format(event.key_name)) NotificationHelper.send_schedule_update(event) except Exception, exception: logging.error("Eror sending schedule updates for: {}".format(event.key_name)) ''' Enqueue firebase push ''' affected_stats_event_keys = set() for (match, updated_attrs, is_new) in zip(matches, updated_attr_list, is_new_list): # Only attrs that affect stats if is_new or set(['alliances_json', 'score_breakdown_json']).intersection(set(updated_attrs)) != set(): affected_stats_event_keys.add(match.event.id()) try: FirebasePusher.update_match(match) except Exception: logging.warning("Firebase update_match failed!")