def get(self): self._require_admin() status_sitevar = Sitevar.get_or_insert('apistatus', values_json="{}") trusted_sitevar = Sitevar.get_or_insert( 'trustedapi', values_json='{"enabled": true}') status = status_sitevar.contents android_status = status.get('android', None) ios_status = status.get('ios', None) self.template_values.update({ 'max_year': status.get('max_season', 2016), 'current_year': status.get('current_season', 2016), 'android_latest_version': android_status.get('latest_app_version', -1) if android_status else -1, 'android_min_version': android_status.get('min_app_version', -1) if android_status else -1, 'ios_latest_version': ios_status.get('latest_app_version', -1) if ios_status else -1, 'ios_min_version': ios_status.get('min_app_version', -1) if ios_status else -1, 'enable_trustedapi': trusted_sitevar.contents, }) path = os.path.join(os.path.dirname(__file__), '../../templates/admin/apistatus.html') self.response.out.write(template.render(path, self.template_values))
def post(self): self._require_admin() trusted_sitevar = Sitevar.get_or_insert('trustedapi') sitevar = Sitevar.get_or_insert('apistatus') old_value = sitevar.contents status = {} status['android'] = {} status['ios'] = {} status['max_season'] = int(self.request.get('max_year')) status['current_season'] = int(self.request.get('current_year')) status['android']['latest_app_version'] = int(self.request.get('android_latest_version')) status['android']['min_app_version'] = int(self.request.get('android_min_version')) status['ios']['latest_app_version'] = int(self.request.get('ios_latest_version')) status['ios']['min_app_version'] = int(self.request.get('ios_min_version')) sitevar.contents = status sitevar.put() trusted_status = { 1: True if self.request.get('enable_match_video') else False, 2: True if self.request.get('enable_event_teams') else False, 3: True if self.request.get('enable_event_matches') else False, 4: True if self.request.get('enable_event_rankings') else False, 5: True if self.request.get('enable_event_alliances') else False, 6: True if self.request.get('enable_event_awards') else False, } trusted_sitevar.contents = trusted_status trusted_sitevar.put() ApiStatusController.clear_cache_if_needed(old_value, status) self.redirect('/admin/apistatus')
def _render(self): status_sitevar_future = Sitevar.get_by_id_async('apistatus') fmsapi_sitevar_future = Sitevar.get_by_id_async( 'apistatus.fmsapi_down') down_events_sitevar_future = Sitevar.get_by_id_async( 'apistatus.down_events') # Error out of no sitevar found status_sitevar = status_sitevar_future.get_result() if not status_sitevar: self._errors = {"404": "API Status Not Found"} self.abort(404) status_dict = status_sitevar.contents down_events_sitevar = down_events_sitevar_future.get_result() down_events_list = down_events_sitevar.contents if down_events_sitevar else None fmsapi_sitevar = fmsapi_sitevar_future.get_result() 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 [] last_modified_times = [status_sitevar.updated] if down_events_sitevar: last_modified_times.append(down_events_sitevar.updated) if fmsapi_sitevar: last_modified_times.append(fmsapi_sitevar.updated) self._last_modified = max(last_modified_times) return json.dumps(status_dict, ensure_ascii=True, indent=2, sort_keys=True)
def _render(self): status_sitevar_future = Sitevar.get_by_id_async('apistatus') fmsapi_sitevar_future = Sitevar.get_by_id_async('apistatus.fmsapi_down') down_events_sitevar_future = Sitevar.get_by_id_async('apistatus.down_events') # Error out of no sitevar found status_sitevar = status_sitevar_future.get_result() if not status_sitevar: self._errors = {"404": "API Status Not Found"} self.abort(404) status_dict = status_sitevar.contents down_events_sitevar = down_events_sitevar_future.get_result() down_events_list = down_events_sitevar.contents if down_events_sitevar else None fmsapi_sitevar = fmsapi_sitevar_future.get_result() 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 [] last_modified_times = [status_sitevar.updated] if down_events_sitevar: last_modified_times.append(down_events_sitevar.updated) if fmsapi_sitevar: last_modified_times.append(fmsapi_sitevar.updated) self._last_modified = max(last_modified_times) return json.dumps(status_dict, ensure_ascii=True, indent=2, sort_keys=True)
def test_parse_2017_events_with_cmp_hacks(self): hack_sitevar = Sitevar(id='cmp_registration_hacks') hack_sitevar.contents = { "event_name_override": [ {"event": "2017cmpmo", "name": "FIRST Championship Event", "short_name": "Championship"}, {"event": "2017cmptx", "name": "FIRST Championship Event", "short_name": "Championship"}], "set_start_to_last_day": ["2017cmptx", "2017cmpmo"], "divisions_to_skip": ["2017arc", "2017cars", "2017cur", "2017dal", "2017dar"], } hack_sitevar.put() with open('test_data/fms_api/2017_event_list.json', 'r') as f: events, districts = FMSAPIEventListParser(2017).parse(json.loads(f.read())) self.assertEqual(len(events), 159) self.assertEqual(len(districts), 10) non_einstein_types = EventType.CMP_EVENT_TYPES non_einstein_types.remove(EventType.CMP_FINALS) for key in hack_sitevar.contents['divisions_to_skip']: self.assertFalse(filter(lambda e: e.key_name == key, events)) einstein_stl = next(e for e in events if e.key_name == '2017cmpmo') self.assertIsNotNone(einstein_stl) self.assertEqual(einstein_stl.name, "FIRST Championship Event (St. Louis)") self.assertEqual(einstein_stl.short_name, "Championship (St. Louis)") self.assertEquals(einstein_stl.start_date, datetime.datetime(year=2017, month=4, day=29, hour=0, minute=0, second=0)) self.assertEquals(einstein_stl.end_date, datetime.datetime(year=2017, month=4, day=29, hour=23, minute=59, second=59)) einstein_hou = next(e for e in events if e.key_name == '2017cmptx') self.assertIsNotNone(einstein_hou) self.assertEqual(einstein_hou.name, "FIRST Championship Event (Houston)") self.assertEqual(einstein_hou.short_name, "Championship (Houston)") self.assertEquals(einstein_hou.start_date, datetime.datetime(year=2017, month=4, day=22, hour=0, minute=0, second=0)) self.assertEquals(einstein_hou.end_date, datetime.datetime(year=2017, month=4, day=22, hour=23, minute=59, second=59))
def get(self): self._require_admin() google_secrets = Sitevar.get_or_insert('google.secrets') firebase_secrets = Sitevar.get_or_insert('firebase.secrets') fmsapi_secrets = Sitevar.get_or_insert('fmsapi.secrets') mobile_clientIds = Sitevar.get_or_insert('mobile.clientIds') gcm_serverKey = Sitevar.get_or_insert('gcm.serverKey') fmsapi_keys = fmsapi_secrets.contents if fmsapi_secrets and isinstance( fmsapi_secrets.contents, dict) else {} clientIds = mobile_clientIds.contents if mobile_clientIds and isinstance( mobile_clientIds.contents, dict) else {} self.template_values.update({ 'google_secret': google_secrets.contents.get('api_key', "") if google_secrets else "", 'firebase_secret': firebase_secrets.contents.get('FIREBASE_SECRET', "") if firebase_secrets else "", 'fmsapi_user': fmsapi_keys.get('username', ''), 'fmsapi_secret': fmsapi_keys.get('authkey', ''), 'web_client_id': clientIds.get('web', ''), 'android_client_id': clientIds.get('android', ''), 'gcm_key': gcm_serverKey.contents.get("gcm_key", "") if gcm_serverKey else "", }) path = os.path.join(os.path.dirname(__file__), '../../templates/admin/authkeys.html') self.response.out.write(template.render(path, self.template_values))
def post(self): self._require_admin() google_secrets = Sitevar.get_or_insert('google.secrets') firebase_secrets = Sitevar.get_or_insert('firebase.secrets') fmsapi_secrets = Sitevar.get_or_insert('fmsapi.secrets') mobile_clientIds = Sitevar.get_or_insert('mobile.clientIds') gcm_serverKey = Sitevar.get_or_insert('gcm.serverKey') google_key = self.request.get("google_secret") firebase_key = self.request.get("firebase_secret") fmsapi_user = self.request.get("fmsapi_user") fmsapi_secret = self.request.get("fmsapi_secret") web_client_id = self.request.get("web_client_id") android_client_id = self.request.get("android_client_id") ios_client_id = self.request.get("ios_client_id") gcm_key = self.request.get("gcm_key") google_secrets.contents = {'api_key': google_key} firebase_secrets.contents = {'FIREBASE_SECRET': firebase_key} fmsapi_secrets.contents = {'username': fmsapi_user, 'authkey': fmsapi_secret} mobile_clientIds.contents = {'web': web_client_id, 'android': android_client_id, 'ios': ios_client_id} gcm_serverKey.contents = {'gcm_key': gcm_key} google_secrets.put() firebase_secrets.put() fmsapi_secrets.put() mobile_clientIds.put() gcm_serverKey.put() self.redirect('/admin/authkeys')
def post(self, sitevar_key): #note, we don't use sitevar_key sitevar = Sitevar( id = self.request.get("key"), description = self.request.get("description"), values_json = self.request.get("values_json"), ) sitevar.put() self.redirect("/admin/sitevar/edit/" + sitevar.key.id() + "?success=true")
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 post(self, sitevar_key): self._require_admin() # note, we don't use sitevar_key sitevar = Sitevar( id=self.request.get("key"), description=self.request.get("description"), values_json=self.request.get("values_json"), ) sitevar.put() self.redirect("/admin/sitevar/edit/" + sitevar.key.id() + "?success=true")
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 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 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 _render(self, event_key, webcast_number): self.response.headers["Cache-Control"] = "public, max-age=%d" % (5 * 60) self.response.headers["Pragma"] = "Public" self.response.headers.add_header("content-type", "application/json", charset="utf-8") output = {} if not webcast_number.isdigit(): return json.dumps(output) webcast_number = int(webcast_number) - 1 event = Event.get_by_id(event_key) if event and event.webcast: webcast = event.webcast[webcast_number] if "type" in webcast and "channel" in webcast: output["player"] = self._renderPlayer(webcast) else: special_webcasts_future = Sitevar.get_by_id_async("gameday.special_webcasts") special_webcasts = special_webcasts_future.get_result() if special_webcasts: special_webcasts = special_webcasts.contents else: special_webcasts = {} if event_key in special_webcasts: webcast = special_webcasts[event_key] if "type" in webcast and "channel" in webcast: output["player"] = self._renderPlayer(webcast) return json.dumps(output)
def _render(self, event_key, webcast_number): self.response.headers['Cache-Control'] = "public, max-age=%d" % (5 * 60) self.response.headers['Pragma'] = 'Public' self.response.headers.add_header('content-type', 'application/json', charset='utf-8') output = {} if not webcast_number.isdigit(): return json.dumps(output) webcast_number = int(webcast_number) - 1 event = Event.get_by_id(event_key) if event and event.webcast: webcast = event.webcast[webcast_number] if 'type' in webcast and 'channel' in webcast: output['player'] = self._renderPlayer(webcast) else: special_webcasts_future = Sitevar.get_by_id_async( 'gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() if special_webcasts: special_webcasts = special_webcasts.contents else: special_webcasts = {} if event_key in special_webcasts: webcast = special_webcasts[event_key] if 'type' in webcast and 'channel' in webcast: output['player'] = self._renderPlayer(webcast) return json.dumps(output)
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 __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 update_champ_numbers(cls, match): champ_numbers_sitevar = Sitevar.get_or_insert( 'champ_numbers', values_json=json.dumps({ 'kpa_accumulated': 0, 'rotors_engaged': 0, 'ready_for_takeoff': 0, })) old_contents = champ_numbers_sitevar.contents for color in ['red', 'blue']: old_contents['kpa_accumulated'] += match.score_breakdown[color]['autoFuelPoints'] + match.score_breakdown[color]['teleopFuelPoints'] if match.score_breakdown[color]['rotor4Engaged']: old_contents['rotors_engaged'] += 4 elif match.score_breakdown[color]['rotor3Engaged']: old_contents['rotors_engaged'] += 3 elif match.score_breakdown[color]['rotor2Engaged']: old_contents['rotors_engaged'] += 2 elif match.score_breakdown[color]['rotor1Engaged']: old_contents['rotors_engaged'] += 1 old_contents['ready_for_takeoff'] += match.score_breakdown[color]['teleopTakeoffPoints'] / 50 champ_numbers_sitevar.contents = old_contents champ_numbers_sitevar.put() deferred.defer( cls._patch_data, 'champ_numbers', json.dumps(old_contents), _queue="firebase")
def _render(self, *args, **kw): special_webcasts_future = Sitevar.get_by_id_async( 'gameday.special_webcasts') special_webcasts_temp = special_webcasts_future.get_result() if special_webcasts_temp: default_chat = special_webcasts_temp.contents.get( "default_chat", "") special_webcasts_temp = special_webcasts_temp.contents.get( "webcasts", []) else: default_chat = "" special_webcasts_temp = [] special_webcasts = [] for webcast in special_webcasts_temp: toAppend = {} for key, value in webcast.items(): toAppend[str(key)] = str(value) special_webcasts.append(toAppend) webcasts_json = { 'special_webcasts': special_webcasts, } self.template_values.update({ 'webcasts_json': json.dumps(webcasts_json), 'default_chat': default_chat, }) path = os.path.join(os.path.dirname(__file__), '../templates/gameday2.html') return template.render(path, self.template_values)
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 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 get(self, alias): special_webcasts_future = Sitevar.get_by_id_async( 'gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() aliases = special_webcasts.contents.get( "aliases", {}) if special_webcasts else {} if alias in aliases: self.redirect("/gameday{}".format(aliases[alias])) return # Allow an alias to be an event key if not ValidationHelper.event_id_validator(alias): event = Event.get_by_id(alias) if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return # Allow an alias to be a team number team_key = "frc{}".format(alias) if not ValidationHelper.team_id_validator(team_key): now = datetime.datetime.now() team_events_future = TeamYearEventsQuery(team_key, now.year).fetch_async() team_events = team_events_future.get_result() for event in team_events: if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return self.redirect("/gameday") return
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 setUp(self): self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() Sitevar(id='website_blacklist', values_json=json.dumps({'websites': ['http://blacklist.com/']})).put() self.website_blacklist = WebsiteBlacklist()
def _render(self, *args, **kw): special_webcasts_future = Sitevar.get_by_id_async('gameday.special_webcasts') special_webcasts_temp = special_webcasts_future.get_result() if special_webcasts_temp: default_chat = special_webcasts_temp.contents.get("default_chat", "") special_webcasts_temp = special_webcasts_temp.contents.get("webcasts", []) else: default_chat = "" special_webcasts_temp = [] special_webcasts = [] for webcast in special_webcasts_temp: toAppend = {} for key, value in webcast.items(): toAppend[str(key)] = str(value) special_webcasts.append(toAppend) webcasts_json = { 'special_webcasts': special_webcasts, } self.template_values.update({ 'webcasts_json': json.dumps(webcasts_json), 'default_chat': default_chat, }) path = os.path.join(os.path.dirname(__file__), '../templates/gameday2.html') return template.render(path, self.template_values)
def _update_live_events_helper(cls): week_events = EventHelper.getWeekEvents() events_by_key = {} live_events = [] for event in week_events: if event.now: event._webcast = event.current_webcasts # Only show current webcasts for webcast in event.webcast: WebcastOnlineHelper.add_online_status_async(webcast) events_by_key[event.key.id()] = event if event.within_a_day: live_events.append(event) # To get Champ events to show up before they are actually going on forced_live_events = Sitevar.get_or_insert( 'forced_live_events', values_json=json.dumps([])) for event in ndb.get_multi([ndb.Key('Event', ekey) for ekey in forced_live_events.contents]): if event.webcast: for webcast in event.webcast: WebcastOnlineHelper.add_online_status_async(webcast) events_by_key[event.key.id()] = event # # Add in the Fake TBA BlueZone event (watch for circular imports) # from helpers.bluezone_helper import BlueZoneHelper # bluezone_event = BlueZoneHelper.update_bluezone(live_events) # if bluezone_event: # for webcast in bluezone_event.webcast: # WebcastOnlineHelper.add_online_status_async(webcast) # events_by_key[bluezone_event.key_name] = bluezone_event return events_by_key
def setUp(self): self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_datastore_v3_stub() self.testbed.init_memcache_stub() ndb.get_context().clear_cache() # Prevent data from leaking between tests Sitevar(id='website_blacklist', values_json=json.dumps({'websites': ['http://blacklist.com/']})).put()
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 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, 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 _render(self, *args, **kw): special_webcasts_future = Sitevar.get_by_id_async('gameday.special_webcasts') special_webcasts_temp = special_webcasts_future.get_result() 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: toAppend = {} for key, value in webcast.items(): toAppend[str(key)] = str(value) special_webcasts.append(toAppend) ongoing_events = [] ongoing_events_w_webcasts = [] week_events = EventHelper.getWeekEvents() for event in week_events: if event.now: ongoing_events.append(ModelToDict.eventConverter(event)) if event.webcast: ongoing_events_w_webcasts.append(ModelToDict.eventConverter(event)) webcasts_json = { 'special_webcasts': special_webcasts, 'ongoing_events': ongoing_events, 'ongoing_events_w_webcasts': ongoing_events_w_webcasts } self.template_values.update({ 'webcasts_json': json.dumps(webcasts_json) }) path = os.path.join(os.path.dirname(__file__), '../templates/gameday2.html') return template.render(path, self.template_values)
def _render(self, event_key, webcast_number): self.response.headers.add_header("content-type", "application/json", charset="utf-8") output = {} if not webcast_number.isdigit(): return json.dumps(output) webcast_number = int(webcast_number) - 1 event = Event.get_by_id(event_key) if event and event.webcast: webcast = event.webcast[webcast_number] if "type" in webcast and "channel" in webcast: output["player"] = self._renderPlayer(webcast) else: special_webcasts_future = Sitevar.get_by_id_async("gameday.special_webcasts") special_webcasts = special_webcasts_future.get_result() if special_webcasts: special_webcasts = special_webcasts.contents else: special_webcasts = [] special_webcasts_dict = {} for webcast in special_webcasts: special_webcasts_dict[webcast["key_name"]] = webcast if event_key in special_webcasts_dict: webcast = special_webcasts_dict[event_key] if "type" in webcast and "channel" in webcast: output["player"] = self._renderPlayer(webcast) return json.dumps(output)
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(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(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, 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 _render(self, event_key, webcast_number): self.response.headers.add_header('content-type', 'application/json', charset='utf-8') output = {} if not webcast_number.isdigit(): return json.dumps(output) webcast_number = int(webcast_number) - 1 event = Event.get_by_id(event_key) if event and event.webcast: webcast = event.webcast[webcast_number] if 'type' in webcast and 'channel' in webcast: output['player'] = self._renderPlayer(webcast) else: special_webcasts_future = Sitevar.get_by_id_async('gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() if special_webcasts: special_webcasts = special_webcasts.contents else: special_webcasts = {} if event_key in special_webcasts: webcast = special_webcasts[event_key] if 'type' in webcast and 'channel' in webcast: output['player'] = self._renderPlayer(webcast) return json.dumps(output)
def post(self): self._require_registration() event_key = self.request.get("event_key") status, suggestion = SuggestionCreator.createEventMediaSuggestion( author_account_key=self.user_bundle.account.key, media_url=self.request.get("media_url"), event_key=event_key) if status == 'success': # Send an update to the FUN slack slack_sitevar = Sitevar.get_or_insert('slack.hookurls') if slack_sitevar: slack_url = slack_sitevar.contents.get('fun', '') if slack_url: message_body = "{0} ({1}) has suggested a video for <https://thebluealliance.com/event/{2}|{2}>: https://youtu.be/{3}.\nSee all suggestions at https://www.thebluealliance.com/suggest/event/media/review".format( self.user_bundle.account.display_name, self.user_bundle.account.email, event_key, suggestion.contents['foreign_key']) OutgoingNotificationHelper.send_slack_alert( slack_url, message_body, []) self.redirect('/suggest/event/media?event_key=%s&status=%s' % (event_key, status))
def _validate_auth(self, auth, event_key): status_sitevar_future = Sitevar.get_by_id_async('trustedapi') allowed_event_keys = [ekey.id() for ekey in auth.event_list] if event_key not in allowed_event_keys: return "Only allowed to edit events: {}".format( ', '.join(allowed_event_keys)) missing_auths = self.REQUIRED_AUTH_TYPES.difference( set(auth.auth_types_enum)) if missing_auths != set(): return "You do not have permission to edit: {}. If this is incorrect, please contact TBA admin.".format( ",".join( [AuthType.write_type_names[ma] for ma in missing_auths])) if auth.expiration and auth.expiration < datetime.datetime.now(): return "These keys expired on {}. Contact TBA admin to make changes".format( auth.expiration) status_sitevar = status_sitevar_future.get_result() if status_sitevar: for auth_type in self.REQUIRED_AUTH_TYPES: if not status_sitevar.contents.get(str(auth_type), True): # Fail open return "The trusted API has been temporarily disabled by the TBA admins. Please contact them for more details." return None
def _render(self, event_key, webcast_number): self.response.headers.add_header('content-type', 'application/json', charset='utf-8') output = {} if not webcast_number.isdigit(): return json.dumps(output) webcast_number = int(webcast_number) - 1 event = Event.get_by_id(event_key) if event and event.webcast: webcast = event.webcast[webcast_number] if 'type' in webcast and 'channel' in webcast: output['player'] = self._renderPlayer(webcast) else: special_webcasts_future = Sitevar.get_by_id_async( 'gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() if special_webcasts: special_webcasts = special_webcasts.contents else: special_webcasts = [] special_webcasts_dict = {} for webcast in special_webcasts: special_webcasts_dict[webcast['key_name']] = webcast if event_key in special_webcasts_dict: webcast = special_webcasts_dict[event_key] if 'type' in webcast and 'channel' in webcast: output['player'] = self._renderPlayer(webcast) return json.dumps(output)
def get(self, alias): special_webcasts_future = Sitevar.get_by_id_async('gameday.special_webcasts') special_webcasts = special_webcasts_future.get_result() aliases = special_webcasts.contents.get("aliases", {}) if special_webcasts else {} if alias in aliases: self.redirect("/gameday{}".format(aliases[alias])) return # Allow an alias to be an event key if not ValidationHelper.event_id_validator(alias): event = Event.get_by_id(alias) if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return # Allow an alias to be a team number team_key = "frc{}".format(alias) if not ValidationHelper.team_id_validator(team_key): now = datetime.datetime.now() team_events_future = TeamYearEventsQuery(team_key, now.year).fetch_async() team_events = team_events_future.get_result() for event in team_events: if event and event.webcast and event.within_a_day: params = self.get_param_string_for_event(event) self.redirect("/gameday{}".format(params)) return self.redirect("/gameday") return
def post(self): self._require_registration() event_key = self.request.get("event_key") status, suggestion = SuggestionCreator.createEventMediaSuggestion( author_account_key=self.user_bundle.account.key, media_url=self.request.get("media_url"), event_key=event_key) if status == 'success': # Send an update to the FUN slack slack_sitevar = Sitevar.get_or_insert('slack.hookurls') if slack_sitevar: slack_url = slack_sitevar.contents.get('fun', '') if slack_url: message_body = u"{0} ({1}) has suggested a video for <https://www.thebluealliance.com/event/{2}|{2}>: https://youtu.be/{3}.\nSee all suggestions at https://www.thebluealliance.com/suggest/event/media/review".format( self.user_bundle.account.display_name, self.user_bundle.account.email, event_key, suggestion.contents['foreign_key']).encode('utf-8') OutgoingNotificationHelper.send_slack_alert(slack_url, message_body, []) self.redirect('/suggest/event/media?event_key=%s&status=%s' % (event_key, status))
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 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 _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 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 blacklist(website): website_blacklist_sitevar = Sitevar.get_or_insert('website_blacklist', values_json=json.dumps({'websites': []})) website_blacklist = website_blacklist_sitevar.contents.get('websites', []) if website in website_blacklist: return website_blacklist.append(website) website_blacklist_sitevar.contents = {'websites': website_blacklist} website_blacklist_sitevar.put()