'''
- Functions for interacting with the web services Live API
'''
from . import auth
from . import error
AUDIENCE: str = auth.AUDIENCE_LIVE
URL: str = auth.URL_LIVE
######################################################### BASE #########################################################
[docs]
def delete(token: auth.WebServicesToken, endpoint: str, params: dict = {}, body: dict = {}) -> dict | list:
'''
- sends a DELETE request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
body: dict
- request body, if applicable
- default: `{}` (empty)
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._delete(token, URL, endpoint, params, body)
[docs]
def get(token: auth.WebServicesToken, endpoint: str, params: dict = {}) -> dict | list:
'''
- sends a GET request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._get(token, URL, endpoint, params)
[docs]
def head(token: auth.WebServicesToken, endpoint: str, params: dict = {}) -> dict | list:
'''
- sends a HEAD request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._head(token, URL, endpoint, params)
[docs]
def options(token: auth.WebServicesToken, endpoint: str, params: dict = {}, body: dict = {}) -> dict | list:
'''
- sends an OPTIONS request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
body: dict
- request body, if applicable
- default: `{}` (empty)
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._options(token, URL, endpoint, params, body)
[docs]
def patch(token: auth.WebServicesToken, endpoint: str, params: dict = {}, body: dict = {}) -> dict | list:
'''
- sends a PATCH request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
body: dict
- request body, if applicable
- default: `{}` (empty)
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._patch(token, URL, endpoint, params, body)
[docs]
def post(token: auth.WebServicesToken, endpoint: str, params: dict = {}, body: dict = {}) -> dict | list:
'''
- sends a POST request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
body: dict
- request body, if applicable
- default: `{}` (empty)
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._post(token, URL, endpoint, params, body)
[docs]
def put(token: auth.WebServicesToken, endpoint: str, params: dict = {}, body: dict = {}) -> dict | list:
'''
- sends a PUT request to the Live API
Parameters
----------
token: auth.WebServicesToken
- authentication token
endpoint: str
- desired endpoint
- base URL is optional
- leading forward slash is optional
- trailing parameters are optional, e.g. `?param1=true¶m2=0`
params: dict
- request parameters, if applicable
- if you put parameters at the end of the `endpoint`, do not put them here or they will be duplicated
body: dict
- request body, if applicable
- default: `{}` (empty)
Returns
-------
dict | list
- response body
'''
auth.WebServicesToken.check_type(token)
token.check_audience(AUDIENCE)
return auth._put(token, URL, endpoint, params, body)
###################################################### ENDPOINTS #######################################################
[docs]
def get_club_campaign(token: auth.WebServicesToken, club_id: int, campaign_id: int) -> dict:
'''
- gets info on a campaign in a club
- https://webservices.openplanet.dev/live/clubs/campaign-by-id
Parameters
----------
token: auth.WebServicesToken
- authentication token
club_id: int
- the ID of the club
campaign_id: int
- the ID of the campaign (not activity ID - campaign ID should be a lot smaller)
Returns
-------
dict
- info on campaign
'''
return get(token, f'api/token/club/{club_id}/campaign/{campaign_id}')
[docs]
def get_map_leaderboard(token: auth.WebServicesToken, map_uid: str, group_uid: str = 'Personal_Best', only_world: bool = True, length: int = 5, offset: int = 0) -> dict:
'''
- gets the top leaderboard records for a map
- can only retrieve records in the top 10,000
- https://webservices.openplanet.dev/live/leaderboards/top
Parameters
----------
token: auth.WebServicesToken
- authentication token
map_uid: str
- the UID of the map
group_uid: str
- the UID of the group/season
- default: `'Personal_Best'`
only_world: bool
- whether to only get records from the global leaderboard
- if `False`, a service account is required and `length` and `offset` are ignored
- default: `True`
length: int
- number of records to get (max 100)
- default: `5`
offset: int
- number of records to skip
- default: `0`
'''
if only_world:
if length > 100:
raise error.ParameterError('you can only request 100 records at a time')
if length + offset > 10_000:
raise error.ParameterError('you can only retrieve records in the top 10,000')
return get(token, f'api/token/leaderboard/group/{group_uid}/map/{map_uid}/top?onlyWorld=true&length={length}&offset={offset}')
auth.ServiceToken.check_type(token, 'this endpoint requires a service account when only_world is False')
return get(token, f'api/token/leaderboard/group/{group_uid}/map/{map_uid}/top?onlyWorld=false')
[docs]
def get_map_review_connect(token: auth.ServiceToken, review_type: str) -> dict:
'''
- gets information to connect to a map review server
- https://webservices.openplanet.dev/live/map-review/connect
Parameters
----------
token: auth.ServiceToken
- authentication token
review_type: str
- type of review server
- examples: `'totd'`, `'weekly-shorts'`
Returns
-------
dict
- info on active server
'''
auth.ServiceToken.check_type(token)
return get(token, f'api/token/map-review/{review_type}/connect')
[docs]
def get_map_review_submitted(token: auth.ServiceToken, review_type: str, length: int = 144, offset: int = 0) -> dict:
'''
- gets information on maps submitted to map review
- https://webservices.openplanet.dev/live/map-review/submitted
Parameters
----------
token: auth.ServiceToken
- authentication token
review_type: str
- type of review server
- examples: `'totd'`, `'weekly-shorts'`
length: int
- number of maps to get
- default: `144` (used by game)
offset: int
- number of maps to skip
- default: `0`
Returns
-------
dict
- info on submitted maps
'''
auth.ServiceToken.check_type(token)
return get(token, f'api/token/map-review/{review_type}/submitted-map', {'length': length, 'offset': offset})
[docs]
def get_map_review_waiting_time(token: auth.WebServicesToken, review_type: str) -> dict:
'''
- gets information on how long a player must wait before their map is the current one if they were to submit it to a map review server
- https://webservices.openplanet.dev/live/map-review/waiting-time
Parameters
----------
token: auth.WebServicesToken
- authentication token
review_type: str
- type of review server
- examples: `'totd'`, `'weekly-shorts'`
Returns
-------
dict
- info on active server
'''
return get(token, f'api/token/map-review/{review_type}/waiting-time')
[docs]
def get_maps_royal(token: auth.WebServicesToken, length: int = 51, offset: int = 0) -> dict:
'''
- gets Royal maps
- note: no longer being updated so it's probably fine to cache this data permanently
- https://webservices.openplanet.dev/live/campaigns/totds
Parameters
----------
token: auth.WebServicesToken
- authentication token
length: int
- number of months to get
- default: `51` (total released)
offset: int
- number of months to skip, looking backwards from the current month
- note: the last Royal maps are from June 2025, but this endpoint still looks back from the current month
- default: `0`
Returns
-------
dict
- maps by month sorted newest to oldest
'''
return get(token, 'api/token/campaign/month', {'length': length, 'offset': offset, 'royal': 'true'})
[docs]
def get_maps_seasonal(token: auth.WebServicesToken, length: int = 1, offset: int = 0) -> dict:
'''
- gets official Nadeo seasonal campaigns
- https://webservices.openplanet.dev/live/campaigns/campaigns-v2
Parameters
----------
token: auth.WebServicesToken
- authentication token
length: int
- number of campaigns to get
- default: `1`
offset: int
- number of campaigns to skip, looking backwards from the current campaign
- default: `0`
Returns
-------
dict
- campaigns sorted newest to oldest
'''
return get(token, 'api/campaign/official', {'length': length, 'offset': offset})
[docs]
def get_maps_totd(token: auth.WebServicesToken, length: int = 1, offset: int = 0) -> dict:
'''
- gets Tracks of the Day
- https://webservices.openplanet.dev/live/campaigns/totds
Parameters
----------
token: auth.WebServicesToken
- authentication token
length: int
- number of months to get
- default: `1`
offset: int
- number of months to skip, looking backwards from the current month
- default: `0`
Returns
-------
dict
- maps by month sorted newest to oldest
'''
return get(token, 'api/token/campaign/month', {'length': length, 'offset': offset})
[docs]
def get_maps_weekly_grand(token: auth.WebServicesToken, length: int = 1, offset: int = 0) -> dict:
'''
- gets Weekly Grands
- https://webservices.openplanet.dev/live/campaigns/weekly-grands
Parameters
----------
token: auth.WebServicesToken
- authentication token
length: int
- number of weeks to get
- default: `1`
offset: int
- number of weeks to skip, looking backwards from the current week
- default: `0`
Returns
-------
dict
- maps by week sorted newest to oldest
'''
return get(token, 'api/campaign/weekly-grands', {'length': length, 'offset': offset})
[docs]
def get_maps_weekly_short(token: auth.WebServicesToken, length: int = 1, offset: int = 0) -> dict:
'''
- gets Weekly Shorts
- https://webservices.openplanet.dev/live/campaigns/weekly-shorts
Parameters
----------
token: auth.WebServicesToken
- authentication token
length: int
- number of weeks to get
- default: `1`
offset: int
- number of weeks to skip, looking backwards from the current week
- default: `0`
Returns
-------
dict
- maps by week sorted newest to oldest
'''
return get(token, 'api/campaign/weekly-shorts', {'length': length, 'offset': offset})
[docs]
def get_player_club_record(token: auth.ServiceToken, map_uid: str, club_id: int, group_uid: str = 'Personal_Best') -> dict:
'''
- gets the currently authenticated user's map record and leaderboard position in reference to a club
- https://webservices.openplanet.dev/live/leaderboards/player-club-record
Parameters
----------
token: auth.ServiceToken
- authentication token
map_uid: str
- the UID of the map
club_id: int
- the ID of the club
- the current user must be a member of this club
group_uid: str
- the UID of the group/season
- default: `'Personal_Best'`
Returns
-------
dict
- record info
'''
auth.ServiceToken.check_type(token)
return get(token, f'api/token/leaderboard/group/{group_uid}/map/{map_uid}/club/{club_id}')
[docs]
def get_server_accounts(token: auth.ServiceToken) -> dict:
'''
- gets the currently authenticated user's dedicated server accounts
- https://webservices.openplanet.dev/live/accounts/server
Parameters
----------
token: auth.ServiceToken
- authentication token
Returns
-------
dict
- dedicated server accounts
'''
auth.ServiceToken.check_type(token)
return get(token, 'api/token/server/player-server/account')