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
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
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
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']
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()
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))
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 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 _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, )
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
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
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
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))
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))
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))
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))
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
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))
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
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))
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))
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)
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 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))