diff --git a/pyteamsnap/api.py b/pyteamsnap/api.py deleted file mode 100644 index d516427..0000000 --- a/pyteamsnap/api.py +++ /dev/null @@ -1,737 +0,0 @@ -__all__ = ['TeamSnap', 'Team', 'Event', 'Availability', 'Member', 'Location', 'Me'] - -import apiclient.exceptions -from apiclient import APIClient, HeaderAuthentication, JsonResponseHandler, JsonRequestFormatter -import datetime - -class ApiObject(): - rel = None - version = None - template = None - - def __init__(self, client, rel=rel, data={}): - self.client = client - self.data = data - self.rel = rel - - @classmethod - def search(cls, client, **kwargs): - try: - results = client.query(cls.rel, "search", **kwargs) - except apiclient.exceptions.ServerError as e: - pass - return [cls(client,rel=cls.rel, data=r) for r in results] - - @classmethod - def get(cls, client, id): - r = client.get(f"{client.link(cls.rel)}/{id}") - return cls(client, cls.rel, client.parse_response(r)[0]) - - @classmethod - def new(cls, client): - return cls(client, cls.rel) - - def post(self): - data = { - "template":{ - "data": [{ - "name":k, - "value":v - } for k,v in self.data.items()] - } - } - r = self.client.post_item(self.rel, data=data) - self.data = r - return r - - def put(self): - data = { - "template":{ - "data": [{ - "name":k, - "value":str(v) - } for k,v in self.data.items()] - } - } - id = self.data.get('id') - r = self.client.put_item(self.rel, id=id, data=data) - self.data = r - return r - - def delete(self): - self.client.delete_item(self.rel, id=self.data['id']) - -class Me (ApiObject): - rel = "me" - type = "user" - version = "3.866.0" - template = { - "data": [ - { - "name": "first_name" - }, - { - "name": "last_name" - }, - { - "name": "password" - }, - { - "name": "birthday" - }, - { - "name": "email" - }, - { - "name": "facebook_id", - "deprecated": True, - "prompt": "facebook_id is deprecated and has been removed. Continued use of facebook_id is not recommended it will no longer be stored." - }, - { - "name": "facebook_access_token", - "deprecated": True, - "prompt": "facebook_access_token is deprecated and has been removed. Continued use of facebook_access_token is not recommended it will no longer be stored." - }, - { - "name": "type", - "value": "user" - }, - { - "name": "is_lab_rat" - }, - { - "name": "receives_newsletter" - } - ] - } - - def __init__(self, client): - data = client.parse_response(client.get(client.link(self.rel)))[0] - super().__init__(client=client, rel=self.rel, data=data) - -class User (ApiObject): - rel = "users" - type = "user" - version = "3.866.0" - template = { - "data": [ - { - "name": "first_name" - }, - { - "name": "last_name" - }, - { - "name": "password" - }, - { - "name": "birthday" - }, - { - "name": "email" - }, - { - "name": "facebook_id", - "deprecated": True, - "prompt": "facebook_id is deprecated and has been removed. Continued use of facebook_id is not recommended it will no longer be stored." - }, - { - "name": "facebook_access_token", - "deprecated": True, - "prompt": "facebook_access_token is deprecated and has been removed. Continued use of facebook_access_token is not recommended it will no longer be stored." - }, - { - "name": "type", - "value": "user" - }, - { - "name": "is_lab_rat" - }, - { - "name": "receives_newsletter" - } - ] - } - -class Event (ApiObject): - rel = "events" - type = "event" - version = "3.866.0" - template = { - "data": [ - { - "name": "type", - "value": "event" - }, - { - "name": "additional_location_details" - }, - { - "name": "browser_time_zone" - }, - { - "name": "division_location_id" - }, - { - "name": "doesnt_count_towards_record" - }, - { - "name": "duration_in_minutes" - }, - { - "name": "game_type_code" - }, - { - "name": "icon_color" - }, - { - "name": "is_canceled" - }, - { - "name": "is_game" - }, - { - "name": "is_overtime" - }, - { - "name": "is_shootout" - }, - { - "name": "is_tbd" - }, - { - "name": "label" - }, - { - "name": "location_id" - }, - { - "name": "minutes_to_arrive_early" - }, - { - "name": "name" - }, - { - "name": "notes" - }, - { - "name": "notify_opponent" - }, - { - "name": "notify_opponent_contacts_email" - }, - { - "name": "notify_opponent_contacts_name" - }, - { - "name": "notify_opponent_notes" - }, - { - "name": "notify_team" - }, - { - "name": "notify_team_as_member_id" - }, - { - "name": "opponent_id" - }, - { - "name": "points_for_opponent" - }, - { - "name": "points_for_team" - }, - { - "name": "repeating_include", - "prompt": "When updating a repeating event, this is a required field. Values are: \"all\" - updates all events in this series, \"future\" - updates this event and all that occur after, \"none\" - only updates a single event." - }, - { - "name": "repeating_type_code", - "prompt": "A app for the frequency of the repeated event, this is required with the \"repeating_include\" attribute when creating a repeating event. Valid values are: \"1\" - repeat an event daily, \"2\" - repeat an event weekly." - }, - { - "name": "repeating_until", - "prompt": "A date when the repeating event should end, this is inclusive so an event will be created on this day if it falls before the next event specified by \"repeating_type_code\". This attribute is required with \"repeating_type_code\" when creating a repeating event." - }, - { - "name": "results" - }, - { - "name": "results_url" - }, - { - "name": "shootout_points_for_opponent" - }, - { - "name": "shootout_points_for_team" - }, - { - "name": "start_date" - }, - { - "name": "team_id" - }, - { - "name": "time_zone" - }, - { - "name": "tracks_availability" - }, - { - "name": "uniform" - } - ]} - -class Team (ApiObject): - rel = "teams" - type = "team" - version = "3.866.0" - template = { - "data": [ - { - "name": "name" - }, - { - "name": "location_country" - }, - { - "name": "location_postal_code" - }, - { - "name": "time_zone", - "prompt": "The time_zone parameter is required when creating a team, but for changing a team's time_zone, use the update_time_zone command" - }, - { - "name": "sport_id" - }, - { - "name": "division_id" - }, - { - "name": "division_name" - }, - { - "name": "season_name" - }, - { - "name": "league_name" - }, - { - "name": "league_url" - }, - { - "name": "owner_first_name" - }, - { - "name": "owner_last_name" - }, - { - "name": "owner_email" - }, - { - "name": "is_ownership_pending" - }, - { - "name": "ad_unit_hero_id" - }, - { - "name": "ad_unit_hero_template_id" - }, - { - "name": "ad_unit_inline_id" - }, - { - "name": "type", - "value": "team" - } - ] - } - -class Availability (ApiObject): - rel = "availabilities" - type = "availability" - version = "3.866.0" - template = { - "data": [ - { - "name": "status_code" - }, - { - "name": "notes" - }, - { - "name": "event_id" - }, - { - "name": "member_id" - }, - { - "name": "notes_author_member_id" - }, - { - "name": "source" - }, - { - "name": "type", - "value": "availability" - } - ] - } - -class Member (ApiObject): - rel = "members" - type = "member" - version = "3.866.0" - template = { - "data": [ - { - "name": "first_name" - }, - { - "name": "last_name" - }, - { - "name": "gender" - }, - { - "name": "position" - }, - { - "name": "is_manager" - }, - { - "name": "birthday" - }, - { - "name": "hide_age", - "deprecated": True, - "prompt": "hide_age is deprecated and will be removed in a future version, use is_age_hidden instead." - }, - { - "name": "is_age_hidden" - }, - { - "name": "hide_address", - "deprecated": True, - "prompt": "hide_address is deprecated and will be removed in a future version, use is_address_hidden instead." - }, - { - "name": "is_address_hidden" - }, - { - "name": "is_non_player" - }, - { - "name": "address_street1" - }, - { - "name": "address_street2" - }, - { - "name": "address_city" - }, - { - "name": "address_state" - }, - { - "name": "address_zip" - }, - { - "name": "jersey_number" - }, - { - "name": "team_id" - }, - { - "name": "is_ownership_pending" - }, - { - "name": "source_action" - }, - { - "name": "type", - "value": "member" - } - ] - }, - -class Location (ApiObject): - rel = "locations" - type = "location" - version = "3.866.0" - template = { - "data": [ - { - "name": "name" - }, - { - "name": "url" - }, - { - "name": "phone" - }, - { - "name": "notes" - }, - { - "name": "address" - }, - { - "name": "latitude" - }, - { - "name": "longitude" - }, - { - "name": "team_id" - }, - { - "name": "is_retired" - }, - { - "name": "type", - "value": "location" - } - ] - } - -class Opponent (ApiObject): - rel = "opponents" - type = "opponent" - version = "3.866.0" - template = { - "data": [ - { - "name": "name" - }, - { - "name": "contacts_name" - }, - { - "name": "contacts_phone" - }, - { - "name": "contacts_email" - }, - { - "name": "notes" - }, - { - "name": "team_id" - }, - { - "name": "type", - "value": "opponent" - } - ] - } - -class EventLineupEntry (ApiObject): - rel = "event_lineup_entries" - type = "event_lineup_entry" - version = "3.866.0" - template = { - "data": [ - { - "name": "event_lineup_id" - }, - { - "name": "member_id" - }, - { - "name": "sequence" - }, - { - "name": "label" - }, - { - "name": "type", - "value": "event_lineup_entry" - } - ] - } - - @classmethod - def search(cls, client, **kwargs): - # For some reason the query listed for search at this endpoint is for EventLineup, not EventLineupEntry - # this is a workaround - r = client.get(f"{client.link(cls.rel)}/search", params=kwargs) - results = client.parse_response(r) - [cls(client, rel=cls.rel, data=r) for r in results] - return [cls(client, rel=cls.rel, data=r) for r in results] - -class EventLineup (ApiObject): - rel = "event_lineups" - type = "event_lineup" - version = "3.866.0" - template = {} - -class AvailabilitySummary (ApiObject): - rel = "availability_summaries" - type = "availability_summary" - version = "3.866.0" - template = {} - -class Statistics (ApiObject): - rel = "statistics" - type = "statistic" - version = "3.866.0" - template = { - "data": [ - { - "name": "acronym" - }, - { - "name": "always_display_decimals" - }, - { - "name": "formula" - }, - { - "name": "is_in_descending_order" - }, - { - "name": "display_zero_totals" - }, - { - "name": "is_percentage" - }, - { - "name": "is_private" - }, - { - "name": "is_team_statistic" - }, - { - "name": "is_top_statistic" - }, - { - "name": "name" - }, - { - "name": "precision" - }, - { - "name": "statistic_group_id" - }, - { - "name": "team_id" - }, - { - "name": "type", - "value": "statistic" - } - ] - } - -class MemberStatistics (ApiObject): - rel = "member_statistics" - -class TeamSnap(APIClient): - base_url = 'https://api.teamsnap.com/v3' - - def __init__(self, token, *args, **kwargs): - super().__init__(*args, - authentication_method=HeaderAuthentication(token=token), - response_handler=JsonResponseHandler, - request_formatter=JsonRequestFormatter, - **kwargs) - self._root_collection = self.get(self.base_url)['collection'] - self._links = self._by_rel(self.base_url, 'links') - self._queries = self._by_rel(self.base_url, 'queries') - self._commands = self._by_rel(self.base_url, 'commands') - pass - - def link(self, link_name): - d = {l['rel']:l['href'] for l in self._root_collection["links"]} - return d.get(link_name) - - def bulk_load(self, team_id, types, **kwargs): - """ - Returns a heterogeneous collection of the specified types for a specified team or teams. - Additional filters can be passed into requested types by passing them in the url's querystring - as type__filter=value (i.e. ?event__start_date=2015-01-01). - Any filter can be passed that is available on the search for the specified type. - :param team_id: - :param types: - :param kwargs: - :return: - """ - types_dict = {t.type:t for t in types} - r = self.query( - rel="self", - query="bulk_load", - types=",".join(types_dict.keys()), - team_id=team_id, - **kwargs - ) - - result = [] - for item in r: - cls = types_dict[item['type']] - instance = cls(self, rel=cls.rel, data=item) - result.append(instance) - return result - - def _by_rel (self, url, k): - try: - {l['rel']: l for l in self._root_collection[k]} - except Exception as e: - return {} - self.get(url)['collection'][k] - return {l['rel']:l for l in self.get(url)['collection'][k]} - - def query (self, rel, query, **kwargs): - queries = self._by_rel(self._get_href(rel), 'queries') - response = self.get(self._get_href(query, queries), params=kwargs) - return self.parse_response(response) - - def command (self, rel, command, **kwargs): - commands = self._by_rel(self._get_href(rel), 'commands') - response = self.get(self._get_href(command, commands), params=kwargs) - return self.parse_response(response) - - def _get_href (self, rel: str, links:dict = None, url = base_url) -> str: - """returns a hyperlink from a the links dictionary. Each item in the links dictionary is a - dictionary with a rel and href key""" - if links is None: links = self._by_rel(url, 'links') - link = links[rel]['href'] - return link - - def get_item (self, rel, id): - r = self.get(f"{self.link(rel)}/{id}") - return self.parse_response(r)[0] - - def post_item(self, rel, data): - r = super(TeamSnap, self).post(f"{self.link(rel)}", data=data) - return self.parse_response(r)[0] - - def put_item(self, rel, id, data): - r = super(TeamSnap, self).put(f"{self.link(rel)}/{id}", data=data) - return self.parse_response(r)[0] - - def delete_item(self, rel, id): - r = super(TeamSnap, self).delete(f"{self.link(rel)}/{id}") - return None - - @classmethod - def parse_response(self, response): - result = [] - items = [item['data'] for item in response['collection'].get('items',[])] - for item in response['collection'].get('items',[]): - details = {} - for detail in item['data']: - value = detail['value'] - value_type = detail['type'] - if value: - if value_type == 'DateTime': - value = datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S%z') - elif value_type == 'Boolean': - value = value == True - elif value_type == 'Integer': - value = int(value) - details[detail['name']] = value - result.append(details) - - return result - # return [{detail['name']: detail['value'] for detail in item} for item in items] \ No newline at end of file