def __init__(self, version, sim_time=None, save_response=False):
        self._sim_time = sim_time
        self._save_response = save_response and sim_time is None
        fms_api_secrets = Sitevar.get_by_id('fmsapi.secrets')
        if fms_api_secrets is None:
            if self._sim_time is None:
                raise Exception(
                    "Missing sitevar: fmsapi.secrets. Can't access FMS API.")
        else:
            fms_api_username = fms_api_secrets.contents['username']
            fms_api_authkey = fms_api_secrets.contents['authkey']
            self._fms_api_authtoken = base64.b64encode('{}:{}'.format(
                fms_api_username, fms_api_authkey))

        self._is_down_sitevar = Sitevar.get_by_id('apistatus.fmsapi_down')
        if not self._is_down_sitevar:
            self._is_down_sitevar = Sitevar(id="apistatus.fmsapi_down",
                                            description="Is FMSAPI down?")

        self.FMS_API_DOMAIN = 'https://frc-api.firstinspires.org/'
        if version == 'v1.0':
            FMS_API_URL_BASE = self.FMS_API_DOMAIN + 'api/v1.0'
            self.FMS_API_AWARDS_URL_PATTERN = FMS_API_URL_BASE + '/awards/%s/%s'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/schedule/%s/%s/qual/hybrid'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/schedule/%s/%s/playoff/hybrid'  # (year, event_short)
            self.FMS_API_EVENT_RANKINGS_URL_PATTERN = FMS_API_URL_BASE + '/rankings/%s/%s'  # (year, event_short)
            self.FMS_API_EVENT_ALLIANCES_URL_PATTERN = FMS_API_URL_BASE + '/alliances/%s/%s'  # (year, event_short)
            self.FMS_API_TEAM_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/teams/%s/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_TEAM_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_EVENT_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?eventCode=%s&page=%s'  # (year, eventCode, page)
            self.FMS_API_EVENT_LIST_URL_PATTERN = FMS_API_URL_BASE + '/events/season=%s'
            self.FMS_API_EVENTTEAM_LIST_URL_PATTERN = FMS_API_URL_BASE + '/teams/?season=%s&eventCode=%s&page=%s'  # (year, eventCode, page)
        elif version == 'v2.0':
            FMS_API_URL_BASE = self.FMS_API_DOMAIN + 'v2.0'
            self.FMS_API_AWARDS_URL_PATTERN = FMS_API_URL_BASE + '/%s/awards/%s'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/%s/schedule/%s/qual/hybrid'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/%s/schedule/%s/playoff/hybrid'  # (year, event_short)
            self.FMS_API_MATCH_DETAILS_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/%s/scores/%s/qual'  # (year, event_short)
            self.FMS_API_MATCH_DETAILS_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/%s/scores/%s/playoff'  # (year, event_short)
            self.FMS_API_EVENT_RANKINGS_URL_PATTERN = FMS_API_URL_BASE + '/%s/rankings/%s'  # (year, event_short)
            self.FMS_API_EVENT_ALLIANCES_URL_PATTERN = FMS_API_URL_BASE + '/%s/alliances/%s'  # (year, event_short)
            self.FMS_API_TEAM_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/%s/teams/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_TEAM_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_EVENT_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?eventCode=%s&page=%s'  # (year, eventCode, page)
            self.FMS_API_EVENT_LIST_URL_PATTERN = FMS_API_URL_BASE + '/%s/events'  # year
            self.FMS_API_EVENT_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/%s/events?eventCode=%s'  # (year, event_short)
            self.FMS_API_EVENTTEAM_LIST_URL_PATTERN = FMS_API_URL_BASE + '/%s/teams/?eventCode=%s&page=%s'  # (year, eventCode, page)
            self.FMS_API_DISTRICT_LIST_URL_PATTERN = FMS_API_URL_BASE + '/%s/districts'  # (year)
            self.FMS_API_DISTRICT_RANKINGS_PATTERN = FMS_API_URL_BASE + '/%s/rankings/district?districtCode=%s&page=%s'  # (year, district abbreviation, page)
        else:
            raise Exception("Unknown FMS API version: {}".format(version))
    def __init__(self, version, sim_time=None, save_response=False):
        self._sim_time = sim_time
        self._save_response = save_response and sim_time is None
        fms_api_secrets = Sitevar.get_by_id('fmsapi.secrets')
        if fms_api_secrets is None:
            if self._sim_time is None:
                raise Exception("Missing sitevar: fmsapi.secrets. Can't access FMS API.")
        else:
            fms_api_username = fms_api_secrets.contents['username']
            fms_api_authkey = fms_api_secrets.contents['authkey']
            self._fms_api_authtoken = base64.b64encode('{}:{}'.format(fms_api_username, fms_api_authkey))

        self._is_down_sitevar = Sitevar.get_by_id('apistatus.fmsapi_down')
        if not self._is_down_sitevar:
            self._is_down_sitevar = Sitevar(id="apistatus.fmsapi_down", description="Is FMSAPI down?")

        self.FMS_API_DOMAIN = 'https://frc-api.firstinspires.org/'
        if version == 'v1.0':
            FMS_API_URL_BASE = self.FMS_API_DOMAIN + 'api/v1.0'
            self.FMS_API_AWARDS_URL_PATTERN = FMS_API_URL_BASE + '/awards/%s/%s'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/schedule/%s/%s/qual/hybrid'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/schedule/%s/%s/playoff/hybrid'  # (year, event_short)
            self.FMS_API_EVENT_RANKINGS_URL_PATTERN = FMS_API_URL_BASE + '/rankings/%s/%s'  # (year, event_short)
            self.FMS_API_EVENT_ALLIANCES_URL_PATTERN = FMS_API_URL_BASE + '/alliances/%s/%s'  # (year, event_short)
            self.FMS_API_TEAM_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/teams/%s/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_TEAM_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_EVENT_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?eventCode=%s&page=%s'  # (year, eventCode, page)
            self.FMS_API_EVENT_LIST_URL_PATTERN = FMS_API_URL_BASE + '/events/season=%s'
            self.FMS_API_EVENTTEAM_LIST_URL_PATTERN = FMS_API_URL_BASE + '/teams/?season=%s&eventCode=%s&page=%s'  # (year, eventCode, page)
        elif version == 'v2.0':
            FMS_API_URL_BASE = self.FMS_API_DOMAIN + 'v2.0'
            self.FMS_API_AWARDS_URL_PATTERN = FMS_API_URL_BASE + '/%s/awards/%s'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/%s/schedule/%s/qual/hybrid'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/%s/schedule/%s/playoff/hybrid'  # (year, event_short)
            self.FMS_API_MATCH_DETAILS_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/%s/scores/%s/qual'  # (year, event_short)
            self.FMS_API_MATCH_DETAILS_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/%s/scores/%s/playoff'  # (year, event_short)
            self.FMS_API_EVENT_RANKINGS_URL_PATTERN = FMS_API_URL_BASE + '/%s/rankings/%s'  # (year, event_short)
            self.FMS_API_EVENT_ALLIANCES_URL_PATTERN = FMS_API_URL_BASE + '/%s/alliances/%s'  # (year, event_short)
            self.FMS_API_TEAM_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/%s/teams/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_TEAM_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?teamNumber=%s'  # (year, teamNumber)
            self.FMS_API_EVENT_AVATAR_URL_PATTERN = FMS_API_URL_BASE + '/%s/avatars/?eventCode=%s&page=%s'  # (year, eventCode, page)
            self.FMS_API_EVENT_LIST_URL_PATTERN = FMS_API_URL_BASE + '/%s/events'  # year
            self.FMS_API_EVENT_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/%s/events?eventCode=%s'  # (year, event_short)
            self.FMS_API_EVENTTEAM_LIST_URL_PATTERN = FMS_API_URL_BASE + '/%s/teams/?eventCode=%s&page=%s'  # (year, eventCode, page)
            self.FMS_API_DISTRICT_LIST_URL_PATTERN = FMS_API_URL_BASE + '/%s/districts'  # (year)
            self.FMS_API_DISTRICT_RANKINGS_PATTERN = FMS_API_URL_BASE + '/%s/rankings/district?districtCode=%s&page=%s'  # (year, district abbreviation, page)
        else:
            raise Exception("Unknown FMS API version: {}".format(version))
    def get(self, event_key):
        self._require_admin()

        event = Event.get_by_id(event_key)
        if not event:
            self.abort(404)
        event.prepAwardsMatchesTeams()

        reg_sitevar = Sitevar.get_by_id("cmp_registration_hacks")
        api_keys = ApiAuthAccess.query(ApiAuthAccess.event_list == ndb.Key(Event, event_key)).fetch()
        event_medias = Media.query(Media.references == event.key).fetch(500)

        self.template_values.update({
            "event": event,
            "medias": event_medias,
            "cache_key": event_controller.EventDetail('2016nyny').cache_key.format(event.key_name),
            "flushed": self.request.get("flushed"),
            "playoff_types": PlayoffType.type_names,
            "write_auths": api_keys,
            "event_sync_disable": reg_sitevar and event_key in reg_sitevar.contents.get('divisions_to_skip', []),
            "set_start_day_to_last": reg_sitevar and event_key in reg_sitevar.contents.get('set_start_to_last_day', []),
            "skip_eventteams": reg_sitevar and event_key in reg_sitevar.contents.get('skip_eventteams', []),
            "event_name_override": next(iter(filter(lambda e: e.get("event") == event_key, reg_sitevar.contents.get("event_name_override", []))), {}).get("name", "")
        })

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/event_details.html')
        self.response.out.write(template.render(path, self.template_values))
def track_call(api_action, api_details, x_tba_app_id):
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
        params = urllib.urlencode({
            'v': 1,
            'tid': GOOGLE_ANALYTICS_ID,
            'cid': uuid.uuid3(uuid.NAMESPACE_X500, str(x_tba_app_id)),
            't': 'event',
            'ec': 'api',
            'ea': api_action,
            'el': api_details,
            'cd1': x_tba_app_id,  # custom dimension 1
            'ni': 1,
            'sc': 'end',  # forces tracking session to end
        })

        # Sets up the call
        analytics_url = 'http://www.google-analytics.com/collect?%s' % params
        urlfetch.fetch(
            url=analytics_url,
            method=urlfetch.GET,
            deadline=10,
        )
def track_call(api_action, api_label, x_tba_app_id):
    """
    For more information about GAnalytics Protocol Parameters, visit
    https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
    """
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
        params = urllib.urlencode({
            'v': 1,
            'tid': GOOGLE_ANALYTICS_ID,
            'cid': uuid.uuid3(uuid.NAMESPACE_X500, str(x_tba_app_id)),
            't': 'event',
            'ec': 'api-v02',
            'ea': api_action,
            'el': api_label,
            'cd1': x_tba_app_id,  # custom dimension 1
            'ni': 1,
            'sc': 'end',  # forces tracking session to end
        })

        analytics_url = 'http://www.google-analytics.com/collect?%s' % params
        urlfetch.fetch(
            url=analytics_url,
            method=urlfetch.GET,
            deadline=10,
        )
    def oauth_req(self,
                  url,
                  http_method="GET",
                  post_body=None,
                  http_headers=None):

        twitter_secrets = Sitevar.get_by_id("twitter.secrets")
        if not twitter_secrets:
            raise Exception(
                "Missing sitevar: twitter.secrets. Cant scrape twitter.")

        TWITTER_CONSUMER_KEY = twitter_secrets.contents['TWITTER_CONSUMER_KEY']
        TWITTER_CONSUMER_SECRET = twitter_secrets.contents[
            'TWITTER_CONSUMER_SECRET']
        TWITTER_ACCESS_TOKEN = twitter_secrets.contents['TWITTER_ACCESS_TOKEN']
        TWITTER_ACCESS_TOKEN_SECRET = twitter_secrets.contents[
            'TWITTER_ACCESS_TOKEN_SECRET']

        consumer = oauth2.Consumer(key=TWITTER_CONSUMER_KEY,
                                   secret=TWITTER_CONSUMER_SECRET)
        token = oauth2.Token(key=TWITTER_ACCESS_TOKEN,
                             secret=TWITTER_ACCESS_TOKEN_SECRET)
        client = oauth2.Client(consumer, token)

        resp, content = client.request(url,
                                       method=http_method,
                                       body=post_body,
                                       headers=http_headers,
                                       force_auth_header=True)
        return content
Example #7
0
    def get_timezone_id(cls, location, event_key):
        if location is None:
            logging.warning(
                'Could not get timezone for event {} with no location!'.format(
                    event_key))
            return None

        google_secrets = Sitevar.get_by_id("google.secrets")
        google_api_key = None
        if google_secrets is None:
            logging.warning(
                "Missing sitevar: google.api_key. API calls rate limited by IP and may be over rate limit."
            )
        else:
            google_api_key = google_secrets.contents['api_key']

        # geocode request
        geocode_params = {
            'address': location,
            'sensor': 'false',
        }
        if google_api_key is not None:
            geocode_params['key'] = google_api_key
        geocode_url = 'https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(
            geocode_params)
        try:
            geocode_result = urlfetch.fetch(geocode_url)
        except Exception, e:
            logging.warning(
                'urlfetch for geocode request failed: {}'.format(geocode_url))
            logging.info(e)
            return None
Example #8
0
    def get_timezone_id(cls, location, event_key):
        if location is None:
            logging.warning('Could not get timezone for event {} with no location!'.format(event_key))
            return None

        google_secrets = Sitevar.get_by_id("google.secrets")
        google_api_key = None
        if google_secrets is None:
            logging.warning("Missing sitevar: google.api_key. API calls rate limited by IP and may be over rate limit.")
        else:
            google_api_key = google_secrets.contents['api_key']

        # geocode request
        geocode_params = {
            'address': location,
            'sensor': 'false',
        }
        if google_api_key is not None:
            geocode_params['key'] = google_api_key
        geocode_url = 'https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(geocode_params)
        try:
            geocode_result = urlfetch.fetch(geocode_url)
        except Exception, e:
            logging.warning('urlfetch for geocode request failed: {}'.format(geocode_url))
            logging.info(e)
            return None
Example #9
0
 def _get_secret(cls):
     firebase_secrets = Sitevar.get_by_id("firebase.secrets")
     if firebase_secrets is None:
         logging.error(
             "Missing sitevar: firebase.secrets. Can't write to Firebase.")
         return None
     return firebase_secrets.contents['FIREBASE_SECRET']
Example #10
0
    def get(self):
        live_events = EventHelper.getEventsWithinADay()
        for event in live_events:
            taskqueue.add(url='/tasks/math/do/predict_match_times/{}'.format(
                event.key_name),
                          method='GET')
        # taskqueue.add(url='/tasks/do/bluezone_update', method='GET')

        # Clear down events for events that aren't live
        status_sitevar = Sitevar.get_by_id('apistatus.down_events')
        if status_sitevar is not None:
            live_event_keys = set([e.key.id() for e in live_events])

            old_status = set(status_sitevar.contents)
            new_status = old_status.copy()
            for event_key in old_status:
                if event_key not in live_event_keys:
                    new_status.remove(event_key)
            status_sitevar.contents = list(new_status)
            status_sitevar.put()

            # Clear API Response cache
            ApiStatusController.clear_cache_if_needed(old_status, new_status)

        self.response.out.write(
            "Enqueued time prediction for {} events".format(len(live_events)))
    def get(self):
        access_token = self.get_oauth_token('https://www.googleapis.com/auth/datastore')
        app_id = app_identity.get_application_id()
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d')

        backup_entities = self.get_backup_entities()
        backup_bucket = self.get_backup_bucket()
        output_url_prefix = "gs://{}/{}".format(backup_bucket, timestamp)

        entity_filter = {
            'kinds': backup_entities,
        }
        request = {
            'project_id': app_id,
            'output_url_prefix': output_url_prefix,
            'entity_filter': entity_filter
        }
        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + access_token
        }
        url = 'https://datastore.googleapis.com/v1beta1/projects/%s:export' % app_id
        status, _ = self.fetch_url(
            url=url,
            payload=json.dumps(request),
            method=urlfetch.POST,
            headers=headers)

        status_sitevar = Sitevar.get_by_id('apistatus')
        if status == 200 and status_sitevar and 'backup' in status_sitevar.contents:
            status_sitevar.contents['backup']['db_export'] = timestamp
            status_sitevar.put()
Example #12
0
    def get(self):
        self._require_admin()

        all_clients = MobileClient.query()
        android = all_clients.filter(MobileClient.client_type == ClientType.OS_ANDROID).count()
        ios = all_clients.filter(MobileClient.client_type == ClientType.OS_IOS).count()
        webhook = all_clients.filter(MobileClient.client_type == ClientType.WEBHOOK).count()

        var = Sitevar.get_by_id('notifications.enable')
        if var is None or not var.values_json == "true":
            push_enabled = False
        else:
            push_enabled = True

        self.template_values.update({
            'mobile_users': all_clients.count(),
            'android_users': android,
            'ios_users': ios,
            'webhooks': webhook,
            'broadcast_success': self.request.get('broadcast_success'),
            'push_enabled': push_enabled,
        })

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/mobile_dashboard.html')
        self.response.out.write(template.render(path, self.template_values))
Example #13
0
    def get_timezone_id(cls, location, lat_lng=None):
        if lat_lng is None:
            result = cls.get_lat_lng(location)
            if result is None:
                return None
            else:
                lat, lng = result
        else:
            lat, lng = lat_lng.lat, lat_lng.lon

        google_secrets = Sitevar.get_by_id("google.secrets")
        google_api_key = None
        if google_secrets is None:
            logging.warning("Missing sitevar: google.api_key. API calls rate limited by IP and may be over rate limit.")
        else:
            google_api_key = google_secrets.contents['api_key']

        # timezone request
        tz_params = {
            'location': '%s,%s' % (lat, lng),
            'timestamp': 0,  # we only care about timeZoneId, which doesn't depend on timestamp
            'sensor': 'false',
        }
        if google_api_key is not None:
            tz_params['key'] = google_api_key
        tz_url = 'https://maps.googleapis.com/maps/api/timezone/json?%s' % urllib.urlencode(tz_params)
        try:
            tz_result = urlfetch.fetch(tz_url)
        except Exception, e:
            logging.warning('urlfetch for timezone request failed: {}'.format(tz_url))
            logging.info(e)
            return None
Example #14
0
def track_call(api_action, api_label, x_tba_app_id):
    """
    For more information about GAnalytics Protocol Parameters, visit
    https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
    """
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
        params = urllib.urlencode({
            'v': 1,
            'tid': GOOGLE_ANALYTICS_ID,
            'cid': uuid.uuid3(uuid.NAMESPACE_X500, str(x_tba_app_id)),
            't': 'event',
            'ec': 'api-v02',
            'ea': api_action,
            'el': api_label,
            'cd1': x_tba_app_id,  # custom dimension 1
            'ni': 1,
            'sc': 'end',  # forces tracking session to end
        })

        analytics_url = 'http://www.google-analytics.com/collect?%s' % params
        urlfetch.fetch(
            url=analytics_url,
            method=urlfetch.GET,
            deadline=10,
        )
Example #15
0
    def get(self):
        access_token = self.get_oauth_token(
            'https://www.googleapis.com/auth/datastore')
        app_id = app_identity.get_application_id()
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d')

        backup_entities = self.get_backup_entities()
        backup_bucket = self.get_backup_bucket()
        output_url_prefix = "gs://{}/{}".format(backup_bucket, timestamp)

        entity_filter = {
            'kinds': backup_entities,
        }
        request = {
            'project_id': app_id,
            'output_url_prefix': output_url_prefix,
            'entity_filter': entity_filter
        }
        headers = {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + access_token
        }
        url = 'https://datastore.googleapis.com/v1beta1/projects/%s:export' % app_id
        status, _ = self.fetch_url(url=url,
                                   payload=json.dumps(request),
                                   method=urlfetch.POST,
                                   headers=headers)

        status_sitevar = Sitevar.get_by_id('apistatus')
        if status == 200 and status_sitevar and 'backup' in status_sitevar.contents:
            status_sitevar.contents['backup']['db_export'] = timestamp
            status_sitevar.put()
    def get_timezone_id(cls, location, lat_lng=None):
        if lat_lng is None:
            result = cls.get_lat_lng(location)
            if result is None:
                return None
            else:
                lat, lng = result
        else:
            lat, lng = lat_lng.lat, lat_lng.lon

        google_secrets = Sitevar.get_by_id("google.secrets")
        google_api_key = None
        if google_secrets is None:
            logging.warning("Missing sitevar: google.api_key. API calls rate limited by IP and may be over rate limit.")
        else:
            google_api_key = google_secrets.contents['api_key']

        # timezone request
        tz_params = {
            'location': '%s,%s' % (lat, lng),
            'timestamp': 0,  # we only care about timeZoneId, which doesn't depend on timestamp
            'sensor': 'false',
        }
        if google_api_key is not None:
            tz_params['key'] = google_api_key
        tz_url = 'https://maps.googleapis.com/maps/api/timezone/json?%s' % urllib.urlencode(tz_params)
        try:
            tz_result = urlfetch.fetch(tz_url)
        except Exception, e:
            logging.warning('urlfetch for timezone request failed: {}'.format(tz_url))
            logging.info(e)
            return None
    def _render(self):
        status_sitevar = Sitevar.get_by_id('apistatus')
        fmsapi_sitevar = Sitevar.get_by_id('apistatus.fmsapi_down')
        down_events_sitevar = Sitevar.get_by_id('apistatus.down_events')

        # Error out of no sitevar found
        if not status_sitevar:
            self._errors = json.dumps({"404": "API Status Not Found"})
            self.abort(404)

        status_dict = status_sitevar.contents
        down_events_list = down_events_sitevar.contents if down_events_sitevar else None

        status_dict['is_datafeed_down'] = True if fmsapi_sitevar and fmsapi_sitevar.contents == True else False
        status_dict['down_events'] = down_events_list if down_events_list is not None else []
        return json.dumps(status_dict, ensure_ascii=True)
def track_call(api_action, api_details):
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
        params = urllib.urlencode({
            'v': 1,
            'tid': GOOGLE_ANALYTICS_ID,
            'cid': '1',
            't': 'event',
            'ec': 'api',
            'ea': api_action,
            'el': api_details,
            'ev': 1,
            'ni': 1
        })

        # Sets up the call
        analytics_url = 'http://www.google-analytics.com/collect'
        urlfetch.fetch(
            url=analytics_url,
            payload=params,
            method=urlfetch.POST,
            headers={'Content-Type': 'application/x-www-form-urlencoded'}
        )
def track_call(api_action, api_label, x_tba_app_id):
    """
    For more information about GAnalytics Protocol Parameters, visit
    https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
    """
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents["GOOGLE_ANALYTICS_ID"]
        params = urllib.urlencode(
            {
                "v": 1,
                "tid": GOOGLE_ANALYTICS_ID,
                "cid": uuid.uuid3(uuid.NAMESPACE_X500, str(x_tba_app_id)),
                "t": "event",
                "ec": "api-v02",
                "ea": api_action,
                "el": api_label,
                "cd1": x_tba_app_id,  # custom dimension 1
                "ni": 1,
                "sc": "end",  # forces tracking session to end
            }
        )

        analytics_url = "http://www.google-analytics.com/collect?%s" % params
        urlfetch.fetch(url=analytics_url, method=urlfetch.GET, deadline=10)
def track_call(api_action, api_label, auth_owner):
    """
    For more information about GAnalytics Protocol Parameters, visit
    https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
    """
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
        payload = urllib.urlencode({
            'v': 1,
            'tid': GOOGLE_ANALYTICS_ID,
            'cid': uuid.uuid3(uuid.NAMESPACE_X500, str(auth_owner)),
            't': 'event',
            'ec': 'api-v03',
            'ea': api_action,
            'el': api_label,
            'cd1': auth_owner,  # custom dimension 1
            'ni': 1,
            'sc': 'end',  # forces tracking session to end
        })

        urlfetch.fetch(
            url='https://www.google-analytics.com/collect',
            validate_certificate=True,
            method=urlfetch.POST,
            deadline=30,
            payload=payload,
        )
Example #21
0
    def track_notification(self, notification_type_enum, num_keys):
        """
        For more information about GAnalytics Protocol Parameters, visit
        https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
        """
        analytics_id = Sitevar.get_by_id("google_analytics.id")
        if analytics_id is None:
            logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
        else:
            GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
            params = urllib.urlencode({
                'v': 1,
                'tid': GOOGLE_ANALYTICS_ID,
                'cid': uuid.uuid3(uuid.NAMESPACE_X500, str('tba-notification-tracking')),
                't': 'event',
                'ec': 'notification',
                'ea': NotificationType.type_names[notification_type_enum],
                'ev': num_keys,
                'ni': 1,
                'sc': 'end',  # forces tracking session to end
            })

            analytics_url = 'http://www.google-analytics.com/collect?%s' % params
            urlfetch.fetch(
                url=analytics_url,
                method=urlfetch.GET,
                deadline=10,
            )
    def __init__(self, version):
        fms_api_secrets = Sitevar.get_by_id('fmsapi.secrets')
        if fms_api_secrets is None:
            raise Exception("Missing sitevar: fmsapi.secrets. Can't access FMS API.")

        fms_api_username = fms_api_secrets.contents['username']
        fms_api_authkey = fms_api_secrets.contents['authkey']
        self._fms_api_authtoken = base64.b64encode('{}:{}'.format(fms_api_username, fms_api_authkey))

        if version == 'v1.0':
            FMS_API_URL_BASE = 'https://frc-api.usfirst.org/api/v1.0'
            self.FMS_API_AWARDS_URL_PATTERN = FMS_API_URL_BASE + '/awards/%s/%s'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/schedule/%s/%s/qual/hybrid'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/schedule/%s/%s/playoff/hybrid'  # (year, event_short)
            self.FMS_API_EVENT_RANKINGS_URL_PATTERN = FMS_API_URL_BASE + '/rankings/%s/%s'  # (year, event_short)
            self.FMS_API_EVENT_ALLIANCES_URL_PATTERN = FMS_API_URL_BASE + '/alliances/%s/%s'  # (year, event_short)
            self.FMS_API_TEAM_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/teams/%s/?teamNumber=%s'  # (year, teamNumber)
        elif version == 'v2.0':
            FMS_API_URL_BASE = 'https://frc-api.usfirst.org/v2.0'
            self.FMS_API_AWARDS_URL_PATTERN = FMS_API_URL_BASE + '/%s/awards/%s'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/%s/schedule/%s/qual/hybrid'  # (year, event_short)
            self.FMS_API_HYBRID_SCHEDULE_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/%s/schedule/%s/playoff/hybrid'  # (year, event_short)
            self.FMS_API_MATCH_DETAILS_QUAL_URL_PATTERN = FMS_API_URL_BASE + '/%s/scores/%s/qual'  # (year, event_short)
            self.FMS_API_MATCH_DETAILS_PLAYOFF_URL_PATTERN = FMS_API_URL_BASE + '/%s/scores/%s/playoff'  # (year, event_short)
            self.FMS_API_EVENT_RANKINGS_URL_PATTERN = FMS_API_URL_BASE + '/%s/rankings/%s'  # (year, event_short)
            self.FMS_API_EVENT_ALLIANCES_URL_PATTERN = FMS_API_URL_BASE + '/%s/alliances/%s'  # (year, event_short)
            self.FMS_API_TEAM_DETAILS_URL_PATTERN = FMS_API_URL_BASE + '/%s/teams/?teamNumber=%s'  # (year, teamNumber)
        else:
            raise Exception("Unknown FMS API version: {}".formation(version))
    def oauth_req(self, url, http_method="GET", post_body=None,
                  http_headers=None):

        twitter_secrets = Sitevar.get_by_id("twitter.secrets")
        if not twitter_secrets:
            raise Exception("Missing sitevar: twitter.secrets. Cant scrape twitter.")

        TWITTER_CONSUMER_KEY = twitter_secrets.contents['TWITTER_CONSUMER_KEY']
        TWITTER_CONSUMER_SECRET = twitter_secrets.contents['TWITTER_CONSUMER_SECRET']
        TWITTER_ACCESS_TOKEN = twitter_secrets.contents['TWITTER_ACCESS_TOKEN']
        TWITTER_ACCESS_TOKEN_SECRET = twitter_secrets.contents['TWITTER_ACCESS_TOKEN_SECRET']

        consumer = oauth2.Consumer(key=TWITTER_CONSUMER_KEY, secret=TWITTER_CONSUMER_SECRET)
        token = oauth2.Token(key=TWITTER_ACCESS_TOKEN, secret=TWITTER_ACCESS_TOKEN_SECRET)
        client = oauth2.Client(consumer, token)
     
        resp, content = client.request(
            url,
            method=http_method,
            body=post_body,
            headers=http_headers,
            force_auth_header=True
        )
        return content
        
Example #24
0
    def _render(self):
        status_sitevar = Sitevar.get_by_id('apistatus')
        fmsapi_sitevar = Sitevar.get_by_id('apistatus.fmsapi_down')
        down_events_sitevar = Sitevar.get_by_id('apistatus.down_events')

        # Error out of no sitevar found
        if not status_sitevar:
            self._errors = json.dumps({"404": "API Status Not Found"})
            self.abort(404)

        status_dict = status_sitevar.contents
        down_events_list = down_events_sitevar.contents if down_events_sitevar else None

        status_dict[
            'is_datafeed_down'] = True if fmsapi_sitevar and fmsapi_sitevar.contents == True else False
        status_dict['down_events'] = down_events_list if down_events_list is not None else []
        return json.dumps(status_dict, ensure_ascii=True)
    def __init__(self, *args, **kw):
        fms_api_secrets = Sitevar.get_by_id('fmsapi.secrets')
        if fms_api_secrets is None:
            raise Exception("Missing sitevar: fmsapi.secrets. Can't access FMS API.")

        fms_api_username = fms_api_secrets.contents['username']
        fms_api_authkey = fms_api_secrets.contents['authkey']
        self._fms_api_authtoken = base64.b64encode('{}:{}'.format(fms_api_username, fms_api_authkey))
 def get_backup_config(self):
     if self.backup_config_sitevar:
         return self.backup_config_sitevar
     else:
         self.backup_config_sitevar = Sitevar.get_by_id('backup_config')
     if not self.backup_config_sitevar:
         self.abort(400)
     return self.backup_config_sitevar
Example #27
0
 def get_backup_config(self):
     if self.backup_config_sitevar:
         return self.backup_config_sitevar
     else:
         self.backup_config_sitevar = Sitevar.get_by_id('backup_config')
     if not self.backup_config_sitevar:
         self.abort(400)
     return self.backup_config_sitevar
Example #28
0
def _get_max_year():
    DEFAULT_YEAR = 2019
    try:
        status_sitevar = Sitevar.get_by_id('apistatus')
        return status_sitevar.contents.get(
            'max_season', DEFAULT_YEAR) if status_sitevar else DEFAULT_YEAR
    except Exception:
        return DEFAULT_YEAR
Example #29
0
def _get_max_year():
    DEFAULT_YEAR = 2018
    try:
        status_sitevar = Sitevar.get_by_id('apistatus')
        return status_sitevar.contents.get(
            'max_season', DEFAULT_YEAR) if status_sitevar else DEFAULT_YEAR
    except Exception:
        return DEFAULT_YEAR
    def post(self):
        if self.request.headers.get('X-TBA-APIAI-Auth') != Sitevar.get_by_id('apiai.secrets').contents['key']:
            return

        request = json.loads(self.request.body)

        self.response.headers['content-type'] = 'application/json; charset="utf-8"'
        self.response.out.write(json.dumps(APIAIHelper.process_request(request)))
 def get(self):
     self._require_admin()
     config = Sitevar.get_by_id('landing_config')
     config_data = config.contents if config else {}
     self.template_values['current_config'] = config_data
     self.template_values['current_landing'] = config_data.get('current_landing', '')
     self.template_values['landing_types'] = LandingType.NAMES
     path = os.path.join(os.path.dirname(__file__), '../../templates/admin/main_landing.html')
     self.response.out.write(template.render(path, self.template_values))
Example #32
0
    def google_maps_place_details_async(cls, place_id):
        """
        https://developers.google.com/places/web-service/details#PlaceDetailsRequests
        """
        if not cls.GOOGLE_API_KEY:
            GOOGLE_SECRETS = Sitevar.get_by_id("google.secrets")
            if GOOGLE_SECRETS:
                cls.GOOGLE_API_KEY = GOOGLE_SECRETS.contents['api_key']
            else:
                logging.warning(
                    "Must have sitevar google.api_key to use Google Maps PlaceDetails"
                )
                raise ndb.Return(None)

        cache_key = u'google_maps_place_details:{}'.format(place_id)
        result = memcache.get(cache_key)
        if result is None:
            place_details_params = {
                'placeid': place_id,
                'key': cls.GOOGLE_API_KEY,
            }
            place_details_url = 'https://maps.googleapis.com/maps/api/place/details/json?%s' % urllib.urlencode(
                place_details_params)
            try:
                # Make async urlfetch call
                context = ndb.get_context()
                place_details_result = yield context.urlfetch(
                    place_details_url)

                # Parse urlfetch call
                if place_details_result.status_code == 200:
                    place_details_dict = json.loads(
                        place_details_result.content)
                    if place_details_dict['status'] == 'ZERO_RESULTS':
                        logging.info(
                            'No place_details result for place_id: {}'.format(
                                place_id))
                    elif place_details_dict['status'] == 'OK':
                        result = place_details_dict['result']
                    else:
                        logging.warning(
                            'Placedetails failed with place_id: {}.'.format(
                                place_id))
                        logging.warning(place_details_dict)
                else:
                    logging.warning(
                        'Placedetails failed with place_id: {}.'.format(
                            place_id))
            except Exception, e:
                logging.warning(
                    'urlfetch for place_details request failed with place_id: {}.'
                    .format(place_id))
                logging.warning(e)

            if tba_config.CONFIG['memcache']:
                memcache.set(cache_key, result)
    def google_maps_placesearch_async(cls, query, lat_lng, textsearch=False):
        """
        https://developers.google.com/places/web-service/search#nearbysearchRequests
        https://developers.google.com/places/web-service/search#TextSearchRequests
        """
        if not cls.GOOGLE_API_KEY:
            GOOGLE_SECRETS = Sitevar.get_by_id("google.secrets")
            if GOOGLE_SECRETS:
                cls.GOOGLE_API_KEY = GOOGLE_SECRETS.contents['api_key']
            else:
                logging.warning("Must have sitevar google.api_key to use Google Maps nearbysearch")
                raise ndb.Return([])

        search_type = 'textsearch' if textsearch else 'nearbysearch'

        results = None
        if query:
            query = query.encode('ascii', 'ignore')
            cache_key = u'google_maps_{}:{}'.format(search_type, query)
            results = memcache.get(cache_key)
            if results is None:
                search_params = {
                    'key': cls.GOOGLE_API_KEY,
                    'location': '{},{}'.format(lat_lng[0], lat_lng[1]),
                    'radius': 25000,
                }
                if textsearch:
                    search_params['query'] = query
                else:
                    search_params['keyword'] = query

                search_url = 'https://maps.googleapis.com/maps/api/place/{}/json?{}'.format(search_type, urllib.urlencode(search_params))
                try:
                    # Make async urlfetch call
                    context = ndb.get_context()
                    search_result = yield context.urlfetch(search_url)

                    # Parse urlfetch result
                    if search_result.status_code == 200:
                        search_dict = json.loads(search_result.content)
                        if search_dict['status'] == 'ZERO_RESULTS':
                            logging.info('No {} results for query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                        elif search_dict['status'] == 'OK':
                            results = search_dict['results']
                        else:
                            logging.warning(u'{} failed with query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                            logging.warning(search_dict)
                    else:
                        logging.warning(u'{} failed with query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                        logging.warning(search_dict)
                except Exception, e:
                    logging.warning(u'urlfetch for {} request failed with query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                    logging.warning(e)

                memcache.set(cache_key, results if results else [])
    def get(self):
        redirect = self.request.get('redirect')
        if redirect:
            self._require_login(redirect)
        else:
            self._require_login('/account')
        # Redirects to registration page if account not registered
        self._require_registration('/account/register')

        push_sitevar = Sitevar.get_by_id('notifications.enable')
        if push_sitevar is None or not push_sitevar.values_json == "true":
            ping_enabled = "disabled"
        else:
            ping_enabled = ""

        # Compute myTBA statistics
        user = self.user_bundle.account.key
        num_favorites = Favorite.query(ancestor=user).count()
        num_subscriptions = Subscription.query(ancestor=user).count()

        # Compute suggestion statistics
        submissions_pending = Suggestion.query(
            Suggestion.review_state == Suggestion.REVIEW_PENDING,
            Suggestion.author == user).count()
        submissions_accepted = Suggestion.query(
            Suggestion.review_state == Suggestion.REVIEW_ACCEPTED,
            Suggestion.author == user).count()

        # Suggestion review statistics
        review_permissions = False
        num_reviewed = 0
        total_pending = 0
        if AccountPermissions.MUTATE_DATA in self.user_bundle.account.permissions:
            review_permissions = True
            num_reviewed = Suggestion.query(
                Suggestion.reviewer == user).count()
            total_pending = Suggestion.query(
                Suggestion.review_state == Suggestion.REVIEW_PENDING).count()

        self.template_values['status'] = self.request.get('status')
        self.template_values[
            'webhook_verification_success'] = self.request.get(
                'webhook_verification_success')
        self.template_values['ping_enabled'] = ping_enabled
        self.template_values['num_favorites'] = num_favorites
        self.template_values['num_subscriptions'] = num_subscriptions
        self.template_values['submissions_pending'] = submissions_pending
        self.template_values['submissions_accepted'] = submissions_accepted
        self.template_values['review_permissions'] = review_permissions
        self.template_values['num_reviewed'] = num_reviewed
        self.template_values['total_pending'] = total_pending

        self.response.out.write(
            jinja2_engine.render('account_overview.html',
                                 self.template_values))
Example #35
0
    def google_maps_placesearch_async(cls, query, lat_lng, textsearch=False):
        """
        https://developers.google.com/places/web-service/search#nearbysearchRequests
        https://developers.google.com/places/web-service/search#TextSearchRequests
        """
        if not cls.GOOGLE_API_KEY:
            GOOGLE_SECRETS = Sitevar.get_by_id("google.secrets")
            if GOOGLE_SECRETS:
                cls.GOOGLE_API_KEY = GOOGLE_SECRETS.contents['api_key']
            else:
                logging.warning("Must have sitevar google.api_key to use Google Maps nearbysearch")
                raise ndb.Return([])

        search_type = 'textsearch' if textsearch else 'nearbysearch'

        results = None
        if query:
            query = query.encode('ascii', 'ignore')
            cache_key = u'google_maps_{}:{}'.format(search_type, query)
            results = memcache.get(cache_key)
            if results is None:
                search_params = {
                    'key': cls.GOOGLE_API_KEY,
                    'location': '{},{}'.format(lat_lng[0], lat_lng[1]),
                    'radius': 25000,
                }
                if textsearch:
                    search_params['query'] = query
                else:
                    search_params['keyword'] = query

                search_url = 'https://maps.googleapis.com/maps/api/place/{}/json?{}'.format(search_type, urllib.urlencode(search_params))
                try:
                    # Make async urlfetch call
                    context = ndb.get_context()
                    search_result = yield context.urlfetch(search_url)

                    # Parse urlfetch result
                    if search_result.status_code == 200:
                        search_dict = json.loads(search_result.content)
                        if search_dict['status'] == 'ZERO_RESULTS':
                            logging.info('No {} results for query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                        elif search_dict['status'] == 'OK':
                            results = search_dict['results']
                        else:
                            logging.warning(u'{} failed with query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                            logging.warning(search_dict)
                    else:
                        logging.warning(u'{} failed with query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                        logging.warning(search_dict)
                except Exception, e:
                    logging.warning(u'urlfetch for {} request failed with query: {}, lat_lng: {}'.format(search_type, query, lat_lng))
                    logging.warning(e)

                memcache.set(cache_key, results if results else [])
Example #36
0
    def get(self):
        self._require_registration()

        push_sitevar = Sitevar.get_by_id('notifications.enable')
        if push_sitevar is None or not push_sitevar.values_json == "true":
            ping_enabled = "disabled"
        else:
            ping_enabled = ""

        # Compute myTBA statistics
        user = self.user_bundle.account.key
        num_favorites = Favorite.query(ancestor=user).count()
        num_subscriptions = Subscription.query(ancestor=user).count()

        # Compute suggestion statistics
        submissions_pending = Suggestion.query(
            Suggestion.review_state == Suggestion.REVIEW_PENDING,
            Suggestion.author == user).count()
        submissions_accepted = Suggestion.query(
            Suggestion.review_state == Suggestion.REVIEW_ACCEPTED,
            Suggestion.author == user).count()

        # Suggestion review statistics
        review_permissions = False
        num_reviewed = 0
        total_pending = 0
        if AccountPermissions.REVIEW_MEDIA in self.user_bundle.account.permissions:
            review_permissions = True
            num_reviewed = Suggestion.query(
                Suggestion.reviewer == user).count()
            total_pending = Suggestion.query(
                Suggestion.review_state == Suggestion.REVIEW_PENDING).count()

        # Fetch trusted API keys
        trusted_keys = ApiAuthAccess.query(ApiAuthAccess.owner == user).fetch()

        self.template_values['status'] = self.request.get('status')
        self.template_values[
            'webhook_verification_success'] = self.request.get(
                'webhook_verification_success')
        self.template_values['ping_enabled'] = ping_enabled
        self.template_values['num_favorites'] = num_favorites
        self.template_values['num_subscriptions'] = num_subscriptions
        self.template_values['submissions_pending'] = submissions_pending
        self.template_values['submissions_accepted'] = submissions_accepted
        self.template_values['review_permissions'] = review_permissions
        self.template_values['num_reviewed'] = num_reviewed
        self.template_values['total_pending'] = total_pending
        self.template_values['trusted_keys'] = trusted_keys
        self.template_values['auth_type_names'] = AuthType.type_names

        self.response.out.write(
            jinja2_engine.render('account_overview.html',
                                 self.template_values))
 def get(self):
     self._require_admin()
     config = Sitevar.get_by_id('landing_config')
     config_data = config.contents if config else {}
     self.template_values['current_config'] = config_data
     self.template_values['current_landing'] = config_data.get(
         'current_landing', '')
     self.template_values['landing_types'] = LandingType.NAMES
     path = os.path.join(os.path.dirname(__file__),
                         '../../templates/admin/main_landing.html')
     self.response.out.write(template.render(path, self.template_values))
Example #38
0
    def post(self):
        if self.request.headers.get('X-TBA-APIAI-Auth') != Sitevar.get_by_id(
                'apiai.secrets').contents['key']:
            return

        request = json.loads(self.request.body)

        self.response.headers[
            'content-type'] = 'application/json; charset="utf-8"'
        self.response.out.write(
            json.dumps(APIAIHelper.process_request(request)))
    def get(self, sitevar_key):
        sitevar = Sitevar.get_by_id(sitevar_key)

        success = self.request.get("success")
        
        template_values = {
            "sitevar": sitevar,
            "success": success,
        }

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/sitevar_edit.html')
        self.response.out.write(template.render(path, template_values))
Example #40
0
    def __init__(self):
        self.LOCALHOST = False
        self.SERVER_KEY = Sitevar.get_by_id('gcm.serverKey')
        if self.SERVER_KEY is None:
            raise Exception("Missing sitevar: gcm.serverKey. Can't send FCM messages.")
        self.GCM_CONFIG = {'gcm_api_key': self.SERVER_KEY.contents['gcm_key']}
        self.GOOGLE_LOGIN_URL = 'https://www.google.com/accounts/ClientLogin'
        # Can't use https on localhost due to Google cert bug
        self.GOOGLE_GCM_SEND_URL = 'https://fcm.googleapis.com/fcm/send'

        self.GCM_QUEUE_NAME = 'gcm-retries'
        self.GCM_QUEUE_CALLBACK_URL = '/gae_python_gcm/send_request'
    def get(self):
        self._require_admin()

        self.template_values['memcache_stats'] = memcache.get_stats()
        self.template_values['databasequery_stats'] = {
            'hits':
            sum(
                filter(None, [
                    memcache.get(key)
                    for key in DatabaseQuery.DATABASE_HITS_MEMCACHE_KEYS
                ])),
            'misses':
            sum(
                filter(None, [
                    memcache.get(key)
                    for key in DatabaseQuery.DATABASE_MISSES_MEMCACHE_KEYS
                ]))
        }

        # Gets the 5 recently created users
        users = Account.query().order(-Account.created).fetch(5)
        self.template_values['users'] = users

        self.template_values['suggestions_count'] = Suggestion.query().filter(
            Suggestion.review_state == Suggestion.REVIEW_PENDING).count()

        # Continuous deployment info
        status_sitevar = Sitevar.get_by_id('apistatus')
        self.template_values[
            'contbuild_enabled'] = status_sitevar.contents.get(
                'contbuild_enabled') if status_sitevar else None

        # version info
        try:
            fname = os.path.join(os.path.dirname(__file__),
                                 '../../version_info.json')

            with open(fname, 'r') as f:
                data = json.loads(f.read().replace('\r\n', '\n'))

            self.template_values['git_branch_name'] = data['git_branch_name']
            self.template_values['build_time'] = data['build_time']
            self.template_values['build_number'] = data.get('build_number')

            commit_parts = re.split("[\n]+", data['git_last_commit'])
            self.template_values['commit_hash'] = commit_parts[0].split(" ")
            self.template_values['commit_author'] = commit_parts[1]
            self.template_values['commit_date'] = commit_parts[2]
            self.template_values['commit_msg'] = commit_parts[3]

        except Exception, e:
            logging.warning("version_info.json parsing failed: %s" % e)
            pass
Example #42
0
    def send_upcoming_matches(cls, live_events):
        from helpers.match_helper import MatchHelper  # PJL: Hacky :P
        # Causes circular import, otherwise
        # https://github.com/the-blue-alliance/the-blue-alliance/pull/1098#discussion_r25128966

        down_events = []
        now = datetime.datetime.utcnow()
        for event in live_events:
            matches = event.matches
            if not matches:
                continue
            last_matches = MatchHelper.recentMatches(matches, num=1)
            next_matches = MatchHelper.upcomingMatches(matches, num=2)

            # First, compare the difference between scheduled times of next/last match
            # Send an upcoming notification if it's <10 minutes, to account for events ahead of schedule
            if last_matches != []:
                last_match = last_matches[0]
                for i, next_match in enumerate(next_matches):
                    if not next_match.push_sent and last_match.time and next_match.time:
                        diff = next_match.time - last_match.time
                        if diff < datetime.timedelta(minutes=10 * (i + 1)):
                            cls.send_upcoming_match_notification(
                                next_match, event)

            for match in next_matches:
                if match and not match.push_sent:
                    # Only continue sending for the next match if a push hasn't already been sent for it
                    if match.time is None or match.time + datetime.timedelta(
                            minutes=-7) <= now:
                        # Only send notifications for matches no more than 7 minutes (average-ish match cycle time) before it's scheduled to start
                        # Unless, the match has no time info. Then #yolo and send it
                        cls.send_upcoming_match_notification(match, event)

            # Determine if event is down
            if cls.is_event_down(last_matches[0] if last_matches else None,
                                 next_matches[0] if next_matches else None):
                down_events.append(event.key_name)

        # Update the status sitevar
        status_sitevar = Sitevar.get_by_id('apistatus.down_events')
        if status_sitevar is None:
            status_sitevar = Sitevar(id="apistatus.down_events",
                                     description="A list of down event keys",
                                     values_json="[]")
        old_status = status_sitevar.contents

        status_sitevar.contents = down_events
        status_sitevar.put()

        # Clear API Response cache
        ApiStatusController.clear_cache_if_needed(old_status, down_events)
    def get(self):
        self._require_admin()
        gd_sitevar = Sitevar.get_by_id("gameday.special_webcasts")
        special_webcasts = gd_sitevar.contents.get("webcasts", []) if gd_sitevar else []
        path_aliases = gd_sitevar.contents.get("aliases", {}) if gd_sitevar else {}

        self.template_values.update({
            "webcasts": special_webcasts,
            "aliases": path_aliases,
        })

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/gameday_dashboard.html')
        self.response.out.write(template.render(path, self.template_values))
    def __init__(self):
        self.LOCALHOST = False
        self.SERVER_KEY = Sitevar.get_by_id("gcm.serverKey")
        if self.SERVER_KEY is None:
            raise Exception("Missing sitevar: gcm.serverKey. Can't send GCM messages.")
        self.GCM_CONFIG = {"gcm_api_key": self.SERVER_KEY.contents["gcm_key"]}
        self.GOOGLE_LOGIN_URL = "https://www.google.com/accounts/ClientLogin"
        # Can't use https on localhost due to Google cert bug
        self.GOOGLE_GCM_SEND_URL = "https://android.apis.google.com/gcm/send"
        self.GOOGLE_GCM_SEND_URL = "https://android.googleapis.com/gcm/send"

        self.GCM_QUEUE_NAME = "gcm-retries"
        self.GCM_QUEUE_CALLBACK_URL = "/gae_python_gcm/send_request"
 def get(self):
     key = self.request.get('key')
     payload_json = self.request.get('payload_json')
     
     firebase_secrets = Sitevar.get_by_id("firebase.secrets")
     if firebase_secrets == None:
         raise Exception("Missing sitevar: firebase.secrets. Can't write to Firebase.")
     FIREBASE_SECRET = firebase_secrets.contents['FIREBASE_SECRET']
     
     url = tba_config.CONFIG['firebase-url'].format(key, FIREBASE_SECRET)
     result = urlfetch.fetch(url, payload_json, 'POST')
     if result.status_code not in self.SUCCESS_STATUS_CODES:
         logging.warning("Error pushing data to Firebase: {}. ERROR {}: {}".format(payload_json, result.status_code, result.content))
Example #46
0
    def get_special_webcasts(cls):  # TODO: Break this out of FirebasePusher 2017-03-01 -fangeugene
        special_webcasts_temp = Sitevar.get_by_id('gameday.special_webcasts')
        if special_webcasts_temp:
            special_webcasts_temp = special_webcasts_temp.contents.get('webcasts', [])
        else:
            special_webcasts_temp = []

        special_webcasts = []
        for webcast in special_webcasts_temp:
            WebcastOnlineHelper.add_online_status_async(webcast)
            special_webcasts.append(webcast)

        return special_webcasts
Example #47
0
    def google_maps_geocode_async(cls, location):
        cache_key = u'google_maps_geocode:{}'.format(location)
        results = memcache.get(cache_key)
        if not results:
            context = ndb.get_context()

            if not location:
                raise ndb.Return([])

            location = location.encode('utf-8')

            google_secrets = Sitevar.get_by_id("google.secrets")
            google_api_key = None
            if google_secrets is None:
                logging.warning(
                    "Missing sitevar: google.api_key. API calls rate limited by IP and may be over rate limit."
                )
            else:
                google_api_key = google_secrets.contents['api_key']

            geocode_params = {
                'address': location,
                'sensor': 'false',
            }
            if google_api_key:
                geocode_params['key'] = google_api_key
            geocode_url = 'https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(
                geocode_params)
            try:
                geocode_results = yield context.urlfetch(geocode_url)
                if geocode_results.status_code == 200:
                    geocode_dict = json.loads(geocode_results.content)
                    if geocode_dict['status'] == 'ZERO_RESULTS':
                        logging.info(
                            'No geocode results for location: {}'.format(
                                location))
                    elif geocode_dict['status'] == 'OK':
                        results = geocode_dict['results']
                    else:
                        logging.warning('Geocoding failed!')
                        logging.warning(geocode_dict)
                else:
                    logging.warning(
                        'Geocoding failed for location {}.'.format(location))
            except Exception, e:
                logging.warning(
                    'urlfetch for geocode request failed for location {}.'.
                    format(location))
                logging.warning(e)

            memcache.set(cache_key, results if results else [])
    def get(self, sitevar_key):
        self._require_admin()
        sitevar = Sitevar.get_by_id(sitevar_key)

        success = self.request.get("success")

        self.template_values.update({
            "sitevar": sitevar,
            "success": success,
        })

        path = os.path.join(os.path.dirname(__file__),
                            '../../templates/admin/sitevar_edit.html')
        self.response.out.write(template.render(path, self.template_values))
Example #49
0
    def get(self):
        sv = Sitevar.get_by_id('apistatus')
        current_year = sv.contents['current_season']
        max_year = sv.contents['max_season']
        years = range(current_year, max_year + 1)
        for year in years:
            taskqueue.add(queue_name='datafeed',
                          target='backend-tasks',
                          url='/backend-tasks/get/event_list/%d' % year,
                          method='GET')

        if 'X-Appengine-Taskname' not in self.request.headers:  # Only write out if not in taskqueue
            self.response.out.write(
                "Enqueued fetching events for {}".format(years))
Example #50
0
    def get(self, event_key):
        import pytz

        event = Event.get_by_id(event_key)
        if not event:
            self.abort(404)

        matches = event.matches
        if not matches or not event.timezone_id:
            return

        timezone = pytz.timezone(event.timezone_id)
        played_matches = MatchHelper.recentMatches(matches, num=0)
        unplayed_matches = MatchHelper.upcomingMatches(matches,
                                                       num=len(matches))
        MatchTimePredictionHelper.predict_future_matches(
            event_key, played_matches, unplayed_matches, timezone,
            event.within_a_day)

        # Detect whether the event is down
        # An event NOT down if ANY unplayed match's predicted time is within its scheduled time by a threshold and
        # the last played match (if it exists) wasn't too long ago.
        event_down = len(unplayed_matches) > 0
        for unplayed_match in unplayed_matches:
            if ((unplayed_match.predicted_time and unplayed_match.time
                 and unplayed_match.predicted_time <
                 unplayed_match.time + datetime.timedelta(minutes=30)) or
                (played_matches == [] or played_matches[-1].actual_time is None
                 or played_matches[-1].actual_time >
                 datetime.datetime.now() - datetime.timedelta(minutes=30))):
                event_down = False
                break

        status_sitevar = Sitevar.get_by_id('apistatus.down_events')
        if status_sitevar is None:
            status_sitevar = Sitevar(id="apistatus.down_events",
                                     description="A list of down event keys",
                                     values_json="[]")
        old_status = set(status_sitevar.contents)
        new_status = old_status.copy()
        if event_down:
            new_status.add(event_key)
        elif event_key in new_status:
            new_status.remove(event_key)

        status_sitevar.contents = list(new_status)
        status_sitevar.put()

        # Clear API Response cache
        ApiStatusController.clear_cache_if_needed(old_status, new_status)
Example #51
0
    def __init__(self, *args, **kw):
        super(MainLandingHandler, self).__init__(*args, **kw)
        config_sitevar = Sitevar.get_by_id('landing_config')
        handler = None
        if config_sitevar:
            self.template_values.update(config_sitevar.contents)
            handler_type = config_sitevar.contents.get('current_landing')
            handler = self.HANDLER_MAP.get(handler_type, None)
        if not handler:
            # Default to build season handler
            handler = MainBuildseasonHandler

        self.handler_instance = handler()
        self._cache_expiration = self.handler_instance._cache_expiration
        self._partial_cache_key = self.handler_instance._partial_cache_key
    def _get_cache_expiration(self):
        turbo_sitevar = Sitevar.get_by_id('turbo_mode')
        if not turbo_sitevar or not turbo_sitevar.contents:
            return self._cache_expiration
        contents = turbo_sitevar.contents
        regex = contents['regex'] if 'regex' in contents else "$^"
        pattern = re.compile(regex)
        valid_until = contents.get('valid_until', -1)  # UNIX time
        cache_length = contents.get('cache_length', self._cache_expiration)
        now = time.time()

        if now <= int(valid_until) and pattern.match(self.cache_key):
            return cache_length
        else:
            return self._cache_expiration
    def __init__(self, *args, **kw):
        super(MainLandingHandler, self).__init__(*args, **kw)
        config_sitevar = Sitevar.get_by_id('landing_config')
        handler = None
        if config_sitevar:
            self.template_values.update(config_sitevar.contents)
            handler_type = config_sitevar.contents.get('current_landing')
            handler = self.HANDLER_MAP.get(handler_type, None)
        if not handler:
            # Default to build season handler
            handler = MainBuildseasonHandler

        self.handler_instance = handler()
        self._cache_expiration = self.handler_instance._cache_expiration
        self._partial_cache_key = self.handler_instance._partial_cache_key
    def get(self):
        self._require_registration()

        push_sitevar = Sitevar.get_by_id('notifications.enable')
        if push_sitevar is None or not push_sitevar.values_json == "true":
            ping_enabled = "disabled"
        else:
            ping_enabled = ""

        # Compute myTBA statistics
        user = self.user_bundle.account.key
        num_favorites = Favorite.query(ancestor=user).count()
        num_subscriptions = Subscription.query(ancestor=user).count()

        # Compute suggestion statistics
        submissions_pending = Suggestion.query(Suggestion.review_state==Suggestion.REVIEW_PENDING, Suggestion.author==user).count()
        submissions_accepted = Suggestion.query(Suggestion.review_state==Suggestion.REVIEW_ACCEPTED, Suggestion.author==user).count()

        # Suggestion review statistics
        review_permissions = False
        num_reviewed = 0
        total_pending = 0
        if self.user_bundle.account.permissions:
            review_permissions = True
            num_reviewed = Suggestion.query(Suggestion.reviewer==user).count()
            total_pending = Suggestion.query(Suggestion.review_state==Suggestion.REVIEW_PENDING).count()

        # Fetch trusted API keys
        api_keys = ApiAuthAccess.query(ApiAuthAccess.owner == user).fetch()
        write_keys = filter(lambda key: key.is_write_key, api_keys)
        read_keys = filter(lambda key: key.is_read_key, api_keys)

        self.template_values['status'] = self.request.get('status')
        self.template_values['webhook_verification_success'] = self.request.get('webhook_verification_success')
        self.template_values['ping_sent'] = self.request.get('ping_sent')
        self.template_values['ping_enabled'] = ping_enabled
        self.template_values['num_favorites'] = num_favorites
        self.template_values['num_subscriptions'] = num_subscriptions
        self.template_values['submissions_pending'] = submissions_pending
        self.template_values['submissions_accepted'] = submissions_accepted
        self.template_values['review_permissions'] = review_permissions
        self.template_values['num_reviewed'] = num_reviewed
        self.template_values['total_pending'] = total_pending
        self.template_values['read_keys'] = read_keys
        self.template_values['write_keys'] = write_keys
        self.template_values['auth_write_type_names'] = AuthType.write_type_names

        self.response.out.write(jinja2_engine.render('account_overview.html', self.template_values))