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))
예제 #6
0
    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")
예제 #9
0
    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")
예제 #11
0
    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))
예제 #12
0
    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)
예제 #15
0
    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)
예제 #16
0
    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)
예제 #17
0
    def get(self):
        live_events = EventHelper.getEventsWithinADay()
        for event in live_events:
            taskqueue.add(url='/tasks/math/do/predict_match_times/{}'.format(
                event.key_name),
                          method='GET')
        # taskqueue.add(url='/tasks/do/bluezone_update', method='GET')

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

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

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

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

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

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

        status_sitevar = Sitevar.get_by_id('apistatus')
        if status == 200 and status_sitevar and 'backup' in status_sitevar.contents:
            status_sitevar.contents['backup']['db_export'] = timestamp
            status_sitevar.put()
예제 #19
0
    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))
예제 #20
0
    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")
예제 #22
0
    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)
예제 #23
0
 def _get_secret(cls):
     firebase_secrets = Sitevar.get_by_id("firebase.secrets")
     if firebase_secrets is None:
         logging.error(
             "Missing sitevar: firebase.secrets. Can't write to Firebase.")
         return None
     return firebase_secrets.contents['FIREBASE_SECRET']
예제 #24
0
def track_call(api_action, api_label, x_tba_app_id):
    """
    For more information about GAnalytics Protocol Parameters, visit
    https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
    """
    analytics_id = Sitevar.get_by_id("google_analytics.id")
    if analytics_id is None:
        logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
    else:
        GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
        params = urllib.urlencode({
            'v': 1,
            'tid': GOOGLE_ANALYTICS_ID,
            'cid': uuid.uuid3(uuid.NAMESPACE_X500, str(x_tba_app_id)),
            't': 'event',
            'ec': 'api-v02',
            'ea': api_action,
            'el': api_label,
            'cd1': x_tba_app_id,  # custom dimension 1
            'ni': 1,
            'sc': 'end',  # forces tracking session to end
        })

        analytics_url = 'http://www.google-analytics.com/collect?%s' % params
        urlfetch.fetch(
            url=analytics_url,
            method=urlfetch.GET,
            deadline=10,
        )
    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
예제 #26
0
    def get_timezone_id(cls, location, lat_lng=None):
        if lat_lng is None:
            result = cls.get_lat_lng(location)
            if result is None:
                return None
            else:
                lat, lng = result
        else:
            lat, lng = lat_lng.lat, lat_lng.lon

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

        # timezone request
        tz_params = {
            'location': '%s,%s' % (lat, lng),
            'timestamp': 0,  # we only care about timeZoneId, which doesn't depend on timestamp
            'sensor': 'false',
        }
        if google_api_key is not None:
            tz_params['key'] = google_api_key
        tz_url = 'https://maps.googleapis.com/maps/api/timezone/json?%s' % urllib.urlencode(tz_params)
        try:
            tz_result = urlfetch.fetch(tz_url)
        except Exception, e:
            logging.warning('urlfetch for timezone request failed: {}'.format(tz_url))
            logging.info(e)
            return None
예제 #27
0
 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()
예제 #28
0
    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)
예제 #29
0
    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
예제 #30
0
 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()
예제 #31
0
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))
예제 #33
0
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,
        )
예제 #35
0
    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)
예제 #37
0
    def get_timezone_id(cls, location, event_key):
        if location is None:
            logging.warning(
                'Could not get timezone for event {} with no location!'.format(
                    event_key))
            return None

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

        # geocode request
        geocode_params = {
            'address': location,
            'sensor': 'false',
        }
        if google_api_key is not None:
            geocode_params['key'] = google_api_key
        geocode_url = 'https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(
            geocode_params)
        try:
            geocode_result = urlfetch.fetch(geocode_url)
        except Exception, e:
            logging.warning(
                'urlfetch for geocode request failed: {}'.format(geocode_url))
            logging.info(e)
            return None
예제 #38
0
    def get(self):
        self._require_admin()

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

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

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

        path = os.path.join(os.path.dirname(__file__), '../../templates/admin/mobile_dashboard.html')
        self.response.out.write(template.render(path, self.template_values))
예제 #39
0
    def get(self):
        access_token = self.get_oauth_token('https://www.googleapis.com/auth/datastore')
        app_id = app_identity.get_application_id()
        timestamp = datetime.datetime.now().strftime('%Y-%m-%d')

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

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

        status_sitevar = Sitevar.get_by_id('apistatus')
        if status == 200 and status_sitevar and 'backup' in status_sitevar.contents:
            status_sitevar.contents['backup']['db_export'] = timestamp
            status_sitevar.put()
예제 #40
0
    def get_timezone_id(cls, location, event_key):
        if location is None:
            logging.warning('Could not get timezone for event {} with no location!'.format(event_key))
            return None

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

        # geocode request
        geocode_params = {
            'address': location,
            'sensor': 'false',
        }
        if google_api_key is not None:
            geocode_params['key'] = google_api_key
        geocode_url = 'https://maps.googleapis.com/maps/api/geocode/json?%s' % urllib.urlencode(geocode_params)
        try:
            geocode_result = urlfetch.fetch(geocode_url)
        except Exception, e:
            logging.warning('urlfetch for geocode request failed: {}'.format(geocode_url))
            logging.info(e)
            return None
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.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))
예제 #44
0
    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)
예제 #46
0
    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
예제 #47
0
    def get_timezone_id(cls, location, lat_lng=None):
        if lat_lng is None:
            result = cls.get_lat_lng(location)
            if result is None:
                return None
            else:
                lat, lng = result
        else:
            lat, lng = lat_lng.lat, lat_lng.lon

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

        # timezone request
        tz_params = {
            'location': '%s,%s' % (lat, lng),
            'timestamp': 0,  # we only care about timeZoneId, which doesn't depend on timestamp
            'sensor': 'false',
        }
        if google_api_key is not None:
            tz_params['key'] = google_api_key
        tz_url = 'https://maps.googleapis.com/maps/api/timezone/json?%s' % urllib.urlencode(tz_params)
        try:
            tz_result = urlfetch.fetch(tz_url)
        except Exception, e:
            logging.warning('urlfetch for timezone request failed: {}'.format(tz_url))
            logging.info(e)
            return None
    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))
예제 #49
0
    def track_notification(self, notification_type_enum, num_keys):
        """
        For more information about GAnalytics Protocol Parameters, visit
        https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
        """
        analytics_id = Sitevar.get_by_id("google_analytics.id")
        if analytics_id is None:
            logging.warning("Missing sitevar: google_analytics.id. Can't track API usage.")
        else:
            GOOGLE_ANALYTICS_ID = analytics_id.contents['GOOGLE_ANALYTICS_ID']
            params = urllib.urlencode({
                'v': 1,
                'tid': GOOGLE_ANALYTICS_ID,
                'cid': uuid.uuid3(uuid.NAMESPACE_X500, str('tba-notification-tracking')),
                't': 'event',
                'ec': 'notification',
                'ea': NotificationType.type_names[notification_type_enum],
                'ev': num_keys,
                'ni': 1,
                'sc': 'end',  # forces tracking session to end
            })

            analytics_url = 'http://www.google-analytics.com/collect?%s' % params
            urlfetch.fetch(
                url=analytics_url,
                method=urlfetch.GET,
                deadline=10,
            )
    def 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)
예제 #51
0
    def _render(self):
        status_sitevar = Sitevar.get_by_id('apistatus')
        fmsapi_sitevar = Sitevar.get_by_id('apistatus.fmsapi_down')
        down_events_sitevar = Sitevar.get_by_id('apistatus.down_events')

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

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

        status_dict[
            'is_datafeed_down'] = True if fmsapi_sitevar and fmsapi_sitevar.contents == True else False
        status_dict['down_events'] = down_events_list if down_events_list is not None else []
        return json.dumps(status_dict, ensure_ascii=True)
예제 #52
0
 def get_backup_config(self):
     if self.backup_config_sitevar:
         return self.backup_config_sitevar
     else:
         self.backup_config_sitevar = Sitevar.get_by_id('backup_config')
     if not self.backup_config_sitevar:
         self.abort(400)
     return self.backup_config_sitevar
예제 #53
0
def _get_max_year():
    DEFAULT_YEAR = 2019
    try:
        status_sitevar = Sitevar.get_by_id('apistatus')
        return status_sitevar.contents.get(
            'max_season', DEFAULT_YEAR) if status_sitevar else DEFAULT_YEAR
    except Exception:
        return DEFAULT_YEAR
 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()