def send_award_update(cls, event):
        users = PushHelper.get_users_subscribed_to_event(
            event, NotificationType.AWARDS)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = AwardsUpdatedNotification(event)
        notification.send(keys)
Example #2
0
    def add_subscription(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to add subscription")
        userId = PushHelper.user_email_to_id(current_user.email())
        modelKey = request.model_key

        sub = Subscription.query( Subscription.user_id == userId, Subscription.model_key == modelKey).get()
        if sub is None:
            # Subscription doesn't exist, add it
            Subscription( user_id = userId, model_key = modelKey, notification_types = PushHelper.notification_enums_from_string(request.notifications)).put()
            if request.device_key:
                # Send updates to user's other devices
                GCMMessageHelper.send_subscription_update(userId, request.device_key)
            return BaseResponse(code=200, message="Subscription added")
        else:
            if sub.notification_types == PushHelper.notification_enums_from_string(request.notifications):
                # Subscription already exists. Don't add it again
                return BaseResponse(code=304, message="Subscription already exists")
            else:
                # We're updating the settings
                sub.notification_types = PushHelper.notification_enums_from_string(request.notifications)
                sub.put()
                if request.device_key:
                    # Send updates to user's other devices
                    GCMMessageHelper.send_subscription_update(userId, request.device_key)
                return BaseResponse(code=200, message="Subscription updated")
    def send_alliance_update(cls, event):
        users = PushHelper.get_users_subscribed_for_alliances(
            event, NotificationType.ALLIANCE_SELECTION)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = AllianceSelectionNotification(event)
        notification.send(keys)
    def send_match_score_update(cls, match):
        users = PushHelper.get_users_subscribed_to_match(
            match, NotificationType.MATCH_SCORE)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = MatchScoreNotification(match)
        notification.send(keys)
    def send_schedule_update(cls, event):
        users = PushHelper.get_users_subscribed_to_event(
            event, NotificationType.SCHEDULE_UPDATED)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = ScheduleUpdatedNotification(event)
        notification.send(keys)
    def send_match_score_update(cls, match):
        users = PushHelper.get_users_subscribed_to_match(match, NotificationType.MATCH_SCORE)
        gcm_keys = PushHelper.get_client_ids_for_users(ClientType.names[ClientType.OS_ANDROID], users)

        if len(gcm_keys) == 0:
            return

        notification = MatchScoreNotification(match)
        message = notification.build(ClientType.OS_ANDROID, {ClientType.OS_ANDROID: gcm_keys})
        gcm_connection = GCMConnection()
        gcm_connection.notify_device(message)
Example #7
0
    def list_subscriptions(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return SubscriptionCollection(subscriptions=[])
        user_id = PushHelper.user_email_to_id(current_user.email())

        subscriptions = Subscription.query(ancestor=ndb.Key(Account, user_id)).fetch()
        output = []
        for subscription in subscriptions:
            output.append(SubscriptionMessage(
                    model_key=subscription.model_key,
                    notifications=PushHelper.notification_string_from_enums(subscription.notification_types),
                    model_type=subscription.model_type))
        return SubscriptionCollection(subscriptions=output)
    def list_subscriptions(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return SubscriptionCollection(subscriptions=[])
        user_id = PushHelper.user_email_to_id(current_user.email())

        subscriptions = Subscription.query(ancestor=ndb.Key(Account, user_id)).fetch()
        output = []
        for subscription in subscriptions:
            output.append(SubscriptionMessage(
                    model_key=subscription.model_key,
                    notifications=PushHelper.notification_string_from_enums(subscription.notification_types),
                    model_type=subscription.model_type))
        return SubscriptionCollection(subscriptions=output)
 def send_match_video(cls, match):
     """
     Sends match_video and event_match_video notifications
     If the match is current, MatchVideoNotification is sent.
     Otherwise, EventMatchVideoNotification is sent
     """
     match_users = set(PushHelper.get_users_subscribed_to_match(match, NotificationType.MATCH_VIDEO))
     event_users = set(PushHelper.get_users_subscribed_to_event(match.event.get(), NotificationType.MATCH_VIDEO))
     users = match_users.union(event_users)
     if match.within_seconds(60*10):
         user_keys = PushHelper.get_client_ids_for_users(users)
         MatchVideoNotification(match).send(user_keys)
     else:
         user_keys = PushHelper.get_client_ids_for_users(users)
         EventMatchVideoNotification(match).send(user_keys)
Example #10
0
    def broadcast(cls, client_types, title, message, url=None, app_version=None):
        from models.notifications.broadcast import BroadcastNotification
        notification = BroadcastNotification(title, message, url, app_version)

        # Send to FCM clients
        fcm_client_types = [ct for ct in client_types if ct in ClientType.FCM_CLIENTS]
        if fcm_client_types:
            clients = MobileClient.query(MobileClient.client_type.IN(fcm_client_types)).fetch()
            if clients:
                cls._defer_fcm(clients, notification)

        # Send to webhooks
        if ClientType.WEBHOOK in client_types:
            clients = MobileClient.query(MobileClient.client_type == ClientType.WEBHOOK).fetch()
            if clients:
                cls._defer_webhook(clients, notification)

        if ClientType.OS_ANDROID in client_types:
            clients = MobileClient.query(MobileClient.client_type == ClientType.OS_ANDROID).fetch()
            from helpers.push_helper import PushHelper
            keys = PushHelper.get_client_ids_for_clients(clients)

            from notifications.broadcast import BroadcastNotification
            notification = BroadcastNotification(title, message, url, app_version)
            notification.send(keys)
    def send_upcoming_match_notification(cls, match, event):
        users = PushHelper.get_users_subscribed_to_match(match, NotificationType.UPCOMING_MATCH)
        keys = PushHelper.get_client_ids_for_users(users)

        if match.set_number == 1 and match.match_number == 1:
            # First match of a new type, send level starting notifications
            start_users = PushHelper.get_users_subscribed_to_match(match, NotificationType.LEVEL_STARTING)
            start_keys = PushHelper.get_client_ids_for_users(start_users)
            level_start = CompLevelStartingNotification(match, event)
            level_start.send(start_keys)

        # Send upcoming match notification
        notification = UpcomingMatchNotification(match, event)
        notification.send(keys)
        match.push_sent = True  # Make sure we don't send updates for this match again
        match.put()
    def register_client(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to register")
        userId = PushHelper.user_email_to_id(current_user.email())
        gcmId = request.mobile_id
        os = ClientType.enums[request.operating_system]
        name = request.name
        uuid = request.device_uuid

        query = MobileClient.query( MobileClient.user_id == userId, MobileClient.device_uuid == uuid, MobileClient.client_type == os )
        # trying to figure out an elusive dupe bug
        logging.info("DEBUGGING")
        logging.info("User ID: {}".format(userId))
        logging.info("UUID: {}".format(uuid))
        logging.info("Count: {}".format(query.count()))
        if query.count() == 0:
            # Record doesn't exist yet, so add it
            MobileClient(
                parent=ndb.Key(Account, userId),
                user_id=userId,
                messaging_id=gcmId,
                client_type=os,
                device_uuid=uuid,
                display_name=name ).put()
            return BaseResponse(code=200, message="Registration successful")
        else:
            # Record already exists, update it
            client = query.fetch(1)[0]
            client.messaging_id = gcmId
            client.display_name = name
            client.put()
            return BaseResponse(code=304, message="Client already exists")
Example #13
0
    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")
Example #14
0
    def suggest_team_media(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to make suggestions")
        user_id = PushHelper.user_email_to_id(current_user.email())

        # For now, only allow team media suggestions
        if request.reference_type != "team":
            # Trying to suggest a media for an invalid model type
            return BaseResponse(code=400, message="Bad model type")

        # Need to split deletehash out into its own private dict. Don't want that to be exposed via API...
        private_details_json = None
        if request.details_json:
            incoming_details = json.loads(request.details_json)
            private_details = None
            if 'deletehash' in incoming_details:
                private_details = {'deletehash': incoming_details.pop('deletehash')}
            private_details_json = json.dumps(private_details) if private_details else None

        status = SuggestionCreator.createTeamMediaSuggestion(
            author_account_key=ndb.Key(Account, user_id),
            media_url=request.media_url,
            team_key=request.reference_key,
            year_str=str(request.year),
            private_details_json=private_details_json)

        if status != 'bad_url':
            if status == 'success':
                return BaseResponse(code=200, message="Suggestion added")
            else:
                return BaseResponse(code=304, message="Suggestion already exists")
        else:
            return BaseResponse(code=400, message="Bad suggestion url")
    def send_subscription_update(cls, user_id, sending_device_key=""):
        clients = PushHelper.get_client_ids_for_users(
            [user_id], os_types=[ClientType.OS_ANDROID])

        notification = UpdateSubscriptionsNotification(user_id,
                                                       sending_device_key)
        notification.send(clients)
Example #16
0
    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]
            from helpers.tbans_helper import TBANSHelper
            success = TBANSHelper.ping(client)
            if success:
                return BaseResponse(code=200, message="Ping sent")
            else:
                return BaseResponse(code=500, message="Failed to ping client")
Example #17
0
    def suggest_team_media(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to make suggestions")
        user_id = PushHelper.user_email_to_id(current_user.email())

        # For now, only allow team media suggestions
        if request.reference_type != "team":
            # Trying to suggest a media for an invalid model type
            return BaseResponse(code=400, message="Bad model type")

        # Need to split deletehash out into its own private dict. Don't want that to be exposed via API...
        private_details_json = None
        if request.details_json:
            incoming_details = json.loads(request.details_json)
            private_details = None
            if 'deletehash' in incoming_details:
                private_details = {'deletehash': incoming_details.pop('deletehash')}
            private_details_json = json.dumps(private_details) if private_details else None

        status = SuggestionCreator.createTeamMediaSuggestion(
            author_account_key=ndb.Key(Account, user_id),
            media_url=request.media_url,
            team_key=request.reference_key,
            year_str=str(request.year),
            private_details_json=private_details_json)

        if status != 'bad_url':
            if status == 'success':
                return BaseResponse(code=200, message="Suggestion added")
            else:
                return BaseResponse(code=304, message="Suggestion already exists")
        else:
            return BaseResponse(code=400, message="Bad suggestion url")
    def send_schedule_update(cls, event):
        users = Subscription.users_subscribed_to_event(
            event, NotificationType.SCHEDULE_UPDATED)
        keys = PushHelper.get_client_ids_for_users(
            users, os_types=[ClientType.OS_ANDROID])

        notification = ScheduleUpdatedNotification(event)
        notification.send(keys)
    def send_award_update(cls, event):
        users = Subscription.users_subscribed_to_event(event,
                                                       NotificationType.AWARDS)
        keys = PushHelper.get_client_ids_for_users(
            users, os_types=[ClientType.OS_ANDROID])

        notification = AwardsUpdatedNotification(event)
        notification.send(keys)
Example #20
0
    def list_favorites(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return FavoriteCollection(favorites=[])
        user_id = PushHelper.user_email_to_id(current_user.email())

        favorites = Favorite.query(ancestor=ndb.Key(Account, user_id)).fetch()
        output = []
        for favorite in favorites:
            output.append(FavoriteMessage(model_key=favorite.model_key, model_type=favorite.model_type))
        return FavoriteCollection(favorites=output)
    def get(self, type):
        self._require_registration('/account/')
        user_id = self.user_bundle.account.key.id()

        logging.info("Sending for {}".format(type))
        try:
            type = int(type)
        except ValueError:
            # Not passed a valid int, just stop here
            logging.info("Invalid number passed")
            self.redirect('/apidocs/webhooks')
            return

        event = Event.get_by_id('2014necmp')
        match = Match.get_by_id('2014necmp_f1m1')
        district = District.get_by_id('2014ne')

        if type == NotificationType.UPCOMING_MATCH:
            notification = UpcomingMatchNotification(match, event)
        elif type == NotificationType.MATCH_SCORE:
            notification = MatchScoreNotification(match)
        elif type == NotificationType.LEVEL_STARTING:
            notification = CompLevelStartingNotification(match, event)
        elif type == NotificationType.ALLIANCE_SELECTION:
            notification = AllianceSelectionNotification(event)
        elif type == NotificationType.AWARDS:
            notification = AwardsUpdatedNotification(event)
        elif type == NotificationType.MEDIA_POSTED:
            # Not implemented yet
            pass
        elif type == NotificationType.DISTRICT_POINTS_UPDATED:
            notification = DistrictPointsUpdatedNotification(district)
        elif type == NotificationType.SCHEDULE_UPDATED:
            notification = ScheduleUpdatedNotification(event, match)
        elif type == NotificationType.FINAL_RESULTS:
            # Not implemented yet
            pass
        elif type == NotificationType.MATCH_VIDEO:
            notification = MatchVideoNotification(match)
        elif type == NotificationType.EVENT_MATCH_VIDEO:
            notification = EventMatchVideoNotification(match)
        else:
            # Not passed a valid int, return
            self.redirect('/apidocs/webhooks')
            return

        keys = PushHelper.get_client_ids_for_users([user_id])
        logging.info("Keys: {}".format(keys))
        if notification:
            # This page should not push notifications to the firebase queue
            # Nor should its notifications be tracked in analytics
            notification.send(keys, push_firebase=False, track_call=False)

        self.redirect('/apidocs/webhooks')
    def list_favorites(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return FavoriteCollection(favorites=[])
        user_id = PushHelper.user_email_to_id(current_user.email())

        favorites = Favorite.query(ancestor=ndb.Key(Account, user_id)).fetch()
        output = []
        for favorite in favorites:
            output.append(FavoriteMessage(model_key=favorite.model_key, model_type=favorite.model_type))
        return FavoriteCollection(favorites=output)
Example #23
0
    def get(self, type):
        self._require_registration('/account/')
        user_id = self.user_bundle.account.key.id()

        logging.info("Sending for {}".format(type))
        try:
            type = int(type)
        except ValueError:
            # Not passed a valid int, just stop here
            logging.info("Invalid number passed")
            self.redirect('/apidocs/webhooks')
            return

        event = Event.get_by_id('2014necmp')
        match = Match.get_by_id('2014necmp_f1m1')
        district = District.get_by_id('2014ne')

        if type == NotificationType.UPCOMING_MATCH:
            notification = UpcomingMatchNotification(match, event)
        elif type == NotificationType.MATCH_SCORE:
            notification = MatchScoreNotification(match)
        elif type == NotificationType.LEVEL_STARTING:
            notification = CompLevelStartingNotification(match, event)
        elif type == NotificationType.ALLIANCE_SELECTION:
            notification = AllianceSelectionNotification(event)
        elif type == NotificationType.AWARDS:
            notification = AwardsUpdatedNotification(event)
        elif type == NotificationType.MEDIA_POSTED:
            # Not implemented yet
            pass
        elif type == NotificationType.DISTRICT_POINTS_UPDATED:
            notification = DistrictPointsUpdatedNotification(district)
        elif type == NotificationType.SCHEDULE_UPDATED:
            notification = ScheduleUpdatedNotification(event, match)
        elif type == NotificationType.FINAL_RESULTS:
            # Not implemented yet
            pass
        elif type == NotificationType.MATCH_VIDEO:
            notification = MatchVideoNotification(match)
        elif type == NotificationType.EVENT_MATCH_VIDEO:
            notification = EventMatchVideoNotification(match)
        else:
            # Not passed a valid int, return
            self.redirect('/apidocs/webhooks')
            return

        keys = PushHelper.get_client_ids_for_users([user_id])
        logging.info("Keys: {}".format(keys))
        if notification:
            # This page should not push notifications to the firebase queue
            # Nor should its notifications be tracked in analytics
            notification.send(keys, push_firebase=False, track_call=False)

        self.redirect('/apidocs/webhooks')
    def send_subscription_update(cls, user_id, sending_device_key):

        clients = PushHelper.get_client_ids_for_users("android", [user_id])
        if sending_device_key in clients:
            clients.remove(sending_device_key)
        if len(clients) == 0:
            return

        notification = UpdateSubscriptionsNotification(user_id)
        message = notification.build(ClientType.OS_ANDROID, {ClientType.OS_ANDROID: clients})
        gcm_connection = GCMConnection()
        gcm_connection.notify_device(message)
 def unregister_client(self, request):
     current_user = endpoints.get_current_user()
     if current_user is None:
         return BaseResponse(code=401, message="Unauthorized to unregister")
     userID = PushHelper.user_email_to_id(current_user.email())
     gcmId = request.mobile_id
     query = MobileClient.query(MobileClient.messaging_id == gcmId, ancestor=ndb.Key(Account, userID)).fetch(keys_only=True)
     if len(query) == 0:
         # Record doesn't exist, so we can't remove it
         return BaseResponse(code=404, message="User doesn't exist. Can't remove it")
     else:
         ndb.delete_multi(query)
         return BaseResponse(code=200, message="User deleted")
    def send_upcoming_match_notification(cls, match, event):
        users = PushHelper.get_users_subscribed_to_match(
            match, NotificationType.UPCOMING_MATCH)
        keys = PushHelper.get_client_ids_for_users(
            users, os_types=[ClientType.OS_ANDROID])

        if match.set_number == 1 and match.match_number == 1:
            # First match of a new type, send level starting notifications
            start_users = PushHelper.get_users_subscribed_to_match(
                match, NotificationType.LEVEL_STARTING)
            start_keys = PushHelper.get_client_ids_for_users(
                start_users, os_types=[ClientType.OS_ANDROID])
            level_start = CompLevelStartingNotification(match, event)
            level_start.send(start_keys)

        # Send upcoming match notification
        notification = UpcomingMatchNotification(match, event)
        notification.send(keys)
        match.push_sent = True  # Make sure we don't send updates for this match again
        match.dirty = True
        from helpers.match_manipulator import MatchManipulator
        MatchManipulator.createOrUpdate(match)
    def list_subscriptions(self, request):
        user_id = get_current_user_id(self.headers)
        if user_id is None:
            return SubscriptionCollection(subscriptions=[])

        subscriptions = Subscription.query(ancestor=ndb.Key(Account, user_id)).fetch()
        output = []
        for subscription in subscriptions:
            output.append(SubscriptionMessage(
                    model_key=subscription.model_key,
                    notifications=PushHelper.notification_string_from_enums(subscription.notification_types),
                    model_type=subscription.model_type))
        return SubscriptionCollection(subscriptions=output)
Example #28
0
 def unregister_client(self, request):
     current_user = endpoints.get_current_user()
     if current_user is None:
         return BaseResponse(code=401, message="Unauthorized to unregister")
     userID = PushHelper.user_email_to_id(current_user.email())
     gcmId = request.mobile_id
     query = MobileClient.query(MobileClient.messaging_id == gcmId, MobileClient.user_id == userID).fetch(keys_only=True)
     if len(query) == 0:
         # Record doesn't exist, so we can't remove it
         return BaseResponse(code=404, message="User doesn't exist. Can't remove it")
     else:
         ndb.delete_multi(query)
         return BaseResponse(code=200, message="User deleted")
Example #29
0
    def broadcast(cls, client_types, title, message, url=None, app_version=None):
        from models.notifications.broadcast import BroadcastNotification
        notification = BroadcastNotification(title, message, url, app_version)

        # Send to FCM clients
        fcm_client_types = [ct for ct in client_types if ct in ClientType.FCM_CLIENTS]
        if fcm_client_types:
            clients = MobileClient.query(MobileClient.client_type.IN(fcm_client_types)).fetch()
            if clients:
                deferred.defer(
                    cls._send_fcm,
                    clients,
                    notification,
                    _queue="push-notifications",
                    _url='/_ah/queue/deferred_notification_send'
                )

        # Send to webhooks
        if ClientType.WEBHOOK in client_types:
            clients = MobileClient.query(MobileClient.client_type == ClientType.WEBHOOK).fetch()
            if clients:
                deferred.defer(
                    cls._send_webhook,
                    clients,
                    notification,
                    _queue="push-notifications",
                    _url='/_ah/queue/deferred_notification_send'
                )

        if ClientType.OS_ANDROID in client_types:
            from helpers.push_helper import PushHelper
            users = PushHelper.get_all_mobile_clients([ClientType.OS_ANDROID])
            keys = PushHelper.get_client_ids_for_users(users)

            from notifications.broadcast import BroadcastNotification
            notification = BroadcastNotification(title, message, url, app_version)
            notification.send(keys)
def get_current_user_id(headers):
    auth = headers.get('Authorization')
    if not auth:
        return None

    id_token = auth.split(' ').pop()
    try:
        claims = google.oauth2.id_token.verify_firebase_token(id_token, HTTP_REQUEST)
    except ValueError:
        return None

    if not claims:
        return None
    else:
        return PushHelper.user_email_to_id(claims['email'])
    def suggest_team_media(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401,
                                message="Unauthorized to make suggestions")
        user_id = PushHelper.user_email_to_id(current_user.email())

        # For now, only allow team media suggestions
        if request.reference_type != "team":
            # Trying to suggest a media for an invalid model type
            return BaseResponse(code=400, message="Bad model type")

        media_dict = MediaParser.partial_media_dict_from_url(
            request.media_url.strip())
        if media_dict is not None:
            existing_media = Media.get_by_id(
                Media.render_key_name(media_dict['media_type_enum'],
                                      media_dict['foreign_key']))
            if existing_media is None \
                    or request.reference_key not in [reference.id() for reference in existing_media.references]:
                media_dict['year'] = request.year
                media_dict['reference_type'] = request.reference_type
                media_dict['reference_key'] = request.reference_key

                # Need to split deletehash out into its own private dict. Don't want that to be exposed via API...
                if request.details_json:
                    incoming_details = json.loads(request.details_json)
                    private_details = None
                    if 'deletehash' in incoming_details:
                        private_details = {
                            'deletehash': incoming_details.pop('deletehash')
                        }

                    media_dict['private_details_json'] = json.dumps(
                        private_details) if private_details else None
                    media_dict['details_json'] = json.dumps(incoming_details)

                suggestion = Suggestion(author=ndb.Key(Account, user_id),
                                        target_model="media")
                suggestion.contents = media_dict
                suggestion.put()

                return BaseResponse(code=200, message="Suggestion added")
            else:
                return BaseResponse(code=304,
                                    message="Suggestion already exists")
        else:
            return BaseResponse(code=400, message="Bad suggestion url")
Example #32
0
def get_current_user_id(headers):
    auth = headers.get('Authorization')
    if not auth:
        return None

    id_token = auth.split(' ').pop()
    try:
        claims = google.oauth2.id_token.verify_firebase_token(
            id_token, HTTP_REQUEST)
    except ValueError:
        return None

    if not claims:
        return None
    else:
        return PushHelper.user_email_to_id(claims['email'])
Example #33
0
    def list_subscriptions(self, request):
        user_id = get_current_user_id(self.headers)
        if user_id is None:
            return SubscriptionCollection(subscriptions=[])

        subscriptions = Subscription.query(
            ancestor=ndb.Key(Account, user_id)).fetch()
        output = []
        for subscription in subscriptions:
            output.append(
                SubscriptionMessage(
                    model_key=subscription.model_key,
                    notifications=PushHelper.notification_string_from_enums(
                        subscription.notification_types),
                    model_type=subscription.model_type))
        return SubscriptionCollection(subscriptions=output)
Example #34
0
 def register_client(self, request):
     current_user = endpoints.get_current_user()
     if current_user is None:
         return BaseResponse(code=401, message="Unauthorized to register")
     userId = PushHelper.user_email_to_id(current_user.email())
     gcmId = request.mobile_id
     os = ClientType.enums[request.operating_system]
     if MobileClient.query( MobileClient.messaging_id==gcmId ).count() == 0:
         # Record doesn't exist yet, so add it
         MobileClient(   messaging_id = gcmId,
                         user_id = userId,
                         client_type = os ).put()
         return BaseResponse(code=200, message="Registration successful")
     else:
         # Record already exists, don't bother updating it again
         return BaseResponse(code=304, message="Client already exists")
Example #35
0
    def remove_subscription(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to remove subscription")
        userId = PushHelper.user_email_to_id(current_user.email())
        modelKey = request.model_key

        to_delete = Subscription.query( Subscription.user_id == userId, Subscription.model_key == modelKey).fetch(keys_only=True)
        if len(to_delete) > 0:
            ndb.delete_multi(to_delete)
            if request.device_key:
                # Send updates to user's other devices
                GCMMessageHelper.send_subscription_update(userId, request.device_key)
            return BaseResponse(code=200, message="Subscriptions deleted")
        else:
            # Subscription doesn't exist. Can't delete it
            return BaseResponse(code=404, message="Subscription not found")
Example #36
0
    def add_favorite(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to add favorite")
        userId = PushHelper.user_email_to_id(current_user.email())
        modelKey = request.model_key

        if Favorite.query( Favorite.user_id == userId, Favorite.model_key == modelKey).count() == 0:
            # Favorite doesn't exist, add it
            Favorite( user_id = userId, model_key = modelKey).put()
            if request.device_key:
                # Send updates to user's other devices
                logging.info("Sending favorite update to user other devices")
                GCMMessageHelper.send_favorite_update(userId, request.device_key)
            return BaseResponse(code=200, message="Favorite added")
        else:
            # Favorite already exists. Don't add it again
            return BaseResponse(code=304, message="Favorite already exists")
    def suggest_team_media(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to make suggestions")
        user_id = PushHelper.user_email_to_id(current_user.email())

        # For now, only allow team media suggestions
        if request.reference_type != "team":
            # Trying to suggest a media for an invalid model type
            return BaseResponse(code=400, message="Bad model type")

        media_dict = MediaParser.partial_media_dict_from_url(request.media_url.strip())
        if media_dict is not None:
            existing_media = Media.get_by_id(
                    Media.render_key_name(media_dict['media_type_enum'], media_dict['foreign_key']))
            if existing_media is None \
                    or request.reference_key not in [reference.id() for reference in existing_media.references]:
                media_dict['year'] = request.year
                media_dict['reference_type'] = request.reference_type
                media_dict['reference_key'] = request.reference_key

                # Need to split deletehash out into its own private dict. Don't want that to be exposed via API...
                if request.details_json:
                    incoming_details = json.loads(request.details_json)
                    private_details = None
                    if 'deletehash' in incoming_details:
                        private_details = {'deletehash': incoming_details.pop('deletehash')}

                    media_dict['private_details_json'] = json.dumps(private_details) if private_details else None
                    media_dict['details_json'] = json.dumps(incoming_details)

                suggestion = Suggestion(
                    author=ndb.Key(Account, user_id),
                    target_model="media"
                )
                suggestion.contents = media_dict
                suggestion.put()

                return BaseResponse(code=200, message="Suggestion added")
            else:
                return BaseResponse(code=304, message="Suggestion already exists")
        else:
            return BaseResponse(code=400, message="Bad suggestion url")
    def register_client(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to register")
        user_id = PushHelper.user_email_to_id(current_user.email())
        gcm_id = request.mobile_id
        os = ClientType.enums[request.operating_system]
        name = request.name
        uuid = request.device_uuid

        query = MobileClient.query(
                MobileClient.user_id == user_id,
                MobileClient.device_uuid == uuid,
                MobileClient.client_type == os)
        # trying to figure out an elusive dupe bug
        logging.info("DEBUGGING")
        logging.info("User ID: {}".format(user_id))
        logging.info("UUID: {}".format(uuid))
        logging.info("Count: {}".format(query.count()))
        if query.count() == 0:
            # Record doesn't exist yet, so add it
            MobileClient(
                parent=ndb.Key(Account, user_id),
                user_id=user_id,
                messaging_id=gcm_id,
                client_type=os,
                device_uuid=uuid,
                display_name=name).put()
            return BaseResponse(code=200, message="Registration successful")
        else:
            # Record already exists, update it
            client = query.fetch(1)[0]
            client.messaging_id = gcm_id
            client.display_name = name
            client.put()
            return BaseResponse(code=304, message="Client already exists")
    def send_match_score_update(cls, match):
        users = PushHelper.get_users_subscribed_to_match(match, NotificationType.MATCH_SCORE)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = MatchScoreNotification(match)
        notification.send(keys)
Example #40
0
    def send_broadcast(cls, client_types, title, message, url, app_version=''):
        users = PushHelper.get_all_mobile_clients(client_types)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = BroadcastNotification(title, message, url, app_version)
        notification.send(keys)
    def send_award_update(cls, event):
        users = PushHelper.get_users_subscribed_to_event(event, NotificationType.AWARDS)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = AwardsUpdatedNotification(event)
        notification.send(keys)
    def send_alliance_update(cls, event):
        users = PushHelper.get_users_subscribed_for_alliances(event, NotificationType.ALLIANCE_SELECTION)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = AllianceSelectionNotification(event)
        notification.send(keys)
    def send_schedule_update(cls, event):
        users = PushHelper.get_users_subscribed_to_event(event, NotificationType.SCHEDULE_UPDATED)
        keys = PushHelper.get_client_ids_for_users(users)

        notification = ScheduleUpdatedNotification(event)
        notification.send(keys)
Example #44
0
    def post(self, type):
        self._require_registration('/account/')
        event_key = self.request.get('event_key')
        match_key = self.request.get('match_key')
        district_key = self.request.get('district_key')
        user_id = self.user_bundle.account.key.id()

        logging.info("Sending for {}".format(type))
        try:
            type = int(type)
        except ValueError:
            # Not passed a valid int, just stop here
            logging.info("Invalid number passed")
            return

        event = None

        if type != NotificationType.DISTRICT_POINTS_UPDATED:
            if event_key == "":
                logging.info("No event key")
                self.response.out.write("No event key specified!")
                return

            event = Event.get_by_id(event_key)

            if event is None:
                logging.info("Invalid event key passed")
                self.response.out.write("Invalid event key!")
                return

        if type == NotificationType.UPCOMING_MATCH:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = UpcomingMatchNotification(match, event)
        elif type == NotificationType.MATCH_SCORE:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = MatchScoreNotification(match)
        elif type == NotificationType.LEVEL_STARTING:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = CompLevelStartingNotification(match, event)
        elif type == NotificationType.ALLIANCE_SELECTION:
            notification = AllianceSelectionNotification(event)
        elif type == NotificationType.AWARDS:
            notification = AwardsUpdatedNotification(event)
        elif type == NotificationType.MEDIA_POSTED:
            # Not implemented yet
            pass
        elif type == NotificationType.DISTRICT_POINTS_UPDATED:
            if district_key == "":
                logging.info("No district key")
                self.response.out.write("No district key specified!")
                return

            district = District.get_by_id(district_key)

            if district is None:
                logging.info("Invalid district key passed")
                self.response.out.write("Invalid district key!")
                return
            notification = DistrictPointsUpdatedNotification(district)
        elif type == NotificationType.SCHEDULE_UPDATED:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = ScheduleUpdatedNotification(event, match)
        elif type == NotificationType.FINAL_RESULTS:
            # Not implemented yet
            pass
        elif type == NotificationType.MATCH_VIDEO:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = MatchVideoNotification(match)
        elif type == NotificationType.EVENT_MATCH_VIDEO:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = EventMatchVideoNotification(match)
        else:
            # Not passed a valid int, return
            return

        keys = PushHelper.get_client_ids_for_users([user_id])
        logging.info("Keys: {}".format(keys))
        if notification:
            # This page should not push notifications to the firebase queue
            # Nor should its notifications be tracked in analytics
            notification.send(keys, push_firebase=False, track_call=False)

        self.response.out.write("ok")
Example #45
0
 def delete_bad_token(self, bad_device_token):
     PushHelper.delete_bad_gcm_token(bad_device_token)
Example #46
0
    def update_model_preferences(self, request):
        user_id = get_current_user_id(self.headers)
        if user_id is None:
            return BaseResponse(
                code=401, message="Unauthorized to update model preferences")
        model_key = request.model_key
        model_type = request.model_type
        output = {}
        code = 0

        if request.favorite:
            fav = Favorite(parent=ndb.Key(Account, user_id),
                           user_id=user_id,
                           model_key=model_key,
                           model_type=model_type)
            result = MyTBAHelper.add_favorite(fav, request.device_key)
            if result == 200:
                output['favorite'] = {"code": 200, "message": "Favorite added"}
                code += 100
            elif result == 304:
                output['favorite'] = {
                    "code": 304,
                    "message": "Favorite already exists"
                }
                code += 304
            else:
                output['favorite'] = {
                    "code": 500,
                    "message": "Unknown error adding favorite"
                }
                code += 500
        else:
            result = MyTBAHelper.remove_favorite(user_id, model_key,
                                                 model_type,
                                                 request.device_key)
            if result == 200:
                output['favorite'] = {
                    "code": 200,
                    "message": "Favorite deleted"
                }
                code += 100
            elif result == 404:
                output['favorite'] = {
                    "code": 404,
                    "message": "Favorite not found"
                }
                code += 404
            else:
                output['favorite'] = {
                    "code": 500,
                    "message": "Unknown error removing favorite"
                }
                code += 500

        if request.notifications:
            sub = Subscription(
                parent=ndb.Key(Account, user_id),
                user_id=user_id,
                model_key=model_key,
                model_type=request.model_type,
                notification_types=PushHelper.notification_enums_from_string(
                    request.notifications))
            result = MyTBAHelper.add_subscription(sub, request.device_key)
            if result == 200:
                output['subscription'] = {
                    "code": 200,
                    "message": "Subscription updated"
                }
                code += 100
            elif result == 304:
                output['subscription'] = {
                    "code": 304,
                    "message": "Subscription already exists"
                }
                code += 304
            else:
                output['subscription'] = {
                    "code": 500,
                    "message": "Unknown error adding favorite"
                }
                code += 500
        else:
            result = MyTBAHelper.remove_subscription(user_id, model_key,
                                                     model_type,
                                                     request.device_key)
            if result == 200:
                output['subscription'] = {
                    "code": 200,
                    "message": "Subscription removed"
                }
                code += 100
            elif result == 404:
                output['subscription'] = {
                    "code": 404,
                    "message": "Subscription not found"
                }
                code += 404
            else:
                output['subscription'] = {
                    "code": 500,
                    "message": "Unknown error removing subscription"
                }
                code += 500

        return BaseResponse(code=code, message=json.dumps(output))
Example #47
0
 def update_token(self, old_device_token, new_device_token):
     PushHelper.update_token(old_device_token, new_device_token)
    def update_model_preferences(self, request):
        current_user = endpoints.get_current_user()
        if current_user is None:
            return BaseResponse(code=401, message="Unauthorized to update model preferences")
        user_id = PushHelper.user_email_to_id(current_user.email())
        model_key = request.model_key
        output = {}
        code = 0

        if request.favorite:
            fav = Favorite(
                parent=ndb.Key(Account, user_id),
                user_id=user_id,
                model_key=model_key,
                model_type=request.model_type
            )
            result = MyTBAHelper.add_favorite(fav, request.device_key)
            if result == 200:
                output['favorite'] = {"code":    200,
                                      "message": "Favorite added"}
                code += 100
            elif result == 304:
                output['favorite'] = {"code":    304,
                                      "message": "Favorite already exists"}
                code += 304
            else:
                output['favorite'] = {"code":    500,
                                      "message": "Unknown error adding favorite"}
                code += 500
        else:
            result = MyTBAHelper.remove_favorite(user_id, model_key, request.device_key)
            if result == 200:
                output['favorite'] = {"code":    200,
                                      "message": "Favorite deleted"}
                code += 100
            elif result == 404:
                output['favorite'] = {"code":    404,
                                      "message": "Favorite not found"}
                code += 404
            else:
                output['favorite'] = {"code":    500,
                                      "message": "Unknown error removing favorite"}
                code += 500

        if request.notifications:
            sub = Subscription(
                parent=ndb.Key(Account, user_id),
                user_id=user_id,
                model_key=model_key,
                model_type=request.model_type,
                notification_types=PushHelper.notification_enums_from_string(request.notifications)
            )
            result = MyTBAHelper.add_subscription(sub, request.device_key)
            if result == 200:
                output['subscription'] = {"code":    200,
                                          "message": "Subscription updated"}
                code += 100
            elif result == 304:
                output['subscription'] = {"code":    304,
                                          "message": "Subscription already exists"}
                code += 304
            else:
                output['subscription'] = {"code":    500,
                                          "message": "Unknown error adding favorite"}
                code += 500
        else:
            result = MyTBAHelper.remove_subscription(user_id, model_key, request.device_key)
            if result == 200:
                output['subscription'] = {"code":    200,
                                          "message": "Subscription removed"}
                code += 100
            elif result == 404:
                output['subscription'] = {"code":    404,
                                          "message": "Subscription not found"}
                code += 404
            else:
                output['subscription'] = {"code":    500,
                                          "message": "Unknown error removing subscription"}
                code += 500

        return BaseResponse(code=code, message=json.dumps(output))
    def post(self, type):
        self._require_registration('/account/')
        event_key = self.request.get('event_key')
        match_key = self.request.get('match_key')
        district_key = self.request.get('district_key')
        user_id = self.user_bundle.account.key.id()

        logging.info("Sending for {}".format(type))
        try:
            type = int(type)
        except ValueError:
            # Not passed a valid int, just stop here
            logging.info("Invalid number passed")
            return

        event = None

        if type != NotificationType.DISTRICT_POINTS_UPDATED:
            if event_key == "":
                logging.info("No event key")
                self.response.out.write("No event key specified!")
                return

            event = Event.get_by_id(event_key)

            if event is None:
                logging.info("Invalid event key passed")
                self.response.out.write("Invalid event key!")
                return

        if type == NotificationType.UPCOMING_MATCH:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = UpcomingMatchNotification(match, event)
        elif type == NotificationType.MATCH_SCORE:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = MatchScoreNotification(match)
        elif type == NotificationType.LEVEL_STARTING:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = CompLevelStartingNotification(match, event)
        elif type == NotificationType.ALLIANCE_SELECTION:
            notification = AllianceSelectionNotification(event)
        elif type == NotificationType.AWARDS:
            notification = AwardsUpdatedNotification(event)
        elif type == NotificationType.MEDIA_POSTED:
            # Not implemented yet
            pass
        elif type == NotificationType.DISTRICT_POINTS_UPDATED:
            if district_key == "":
                logging.info("No district key")
                self.response.out.write("No district key specified!")
                return

            district = District.get_by_id(district_key)

            if district is None:
                logging.info("Invalid district key passed")
                self.response.out.write("Invalid district key!")
                return
            notification = DistrictPointsUpdatedNotification(district)
        elif type == NotificationType.SCHEDULE_UPDATED:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = ScheduleUpdatedNotification(event, match)
        elif type == NotificationType.FINAL_RESULTS:
            # Not implemented yet
            pass
        elif type == NotificationType.MATCH_VIDEO:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = MatchVideoNotification(match)
        elif type == NotificationType.EVENT_MATCH_VIDEO:
            if match_key == "":
                logging.info("No match key")
                self.response.out.write("No match key specified!")
                return

            match = Match.get_by_id(match_key)

            if match is None:
                logging.info("Invalid match key passed")
                self.response.out.write("Invalid match key!")
                return

            notification = EventMatchVideoNotification(match)
        else:
            # Not passed a valid int, return
            return

        keys = PushHelper.get_client_ids_for_users([user_id])
        logging.info("Keys: {}".format(keys))
        if notification:
            # This page should not push notifications to the firebase queue
            # Nor should its notifications be tracked in analytics
            notification.send(keys, push_firebase=False, track_call=False)

        self.response.out.write("ok")
Example #50
0
    def send_favorite_update(cls, user_id, sending_device_key=""):
        clients = PushHelper.get_client_ids_for_users([user_id])

        notification = UpdateFavoritesNotification(user_id, sending_device_key)
        notification.send(clients)
Example #51
0
 def delete_bad_token(self, bad_device_token):
     PushHelper.delete_bad_gcm_token(bad_device_token)
    def send_subscription_update(cls, user_id, sending_device_key=""):
        clients = PushHelper.get_client_ids_for_users([user_id])

        notification = UpdateSubscriptionsNotification(user_id, sending_device_key)
        notification.send(clients)
Example #53
0
 def update_token(self, old_device_token, new_device_token):
     PushHelper.update_token(old_device_token, new_device_token)