· 6 years ago · Mar 24, 2020, 07:48 PM
1'''
2 api
3 ---
4
5 Utilities to query the OpenDOTA API.
6'''
7
8import requests
9import sys
10import time
11
12# CONSTANTS
13# ---------
14
15# Domain name for OpenDota.
16HOST = 'https://api.opendota.com'
17# Time to sleep for free tier requests to avoid rate limits.
18FREE_TIER_RATE_LIMIT = 1
19# Time to sleep for premium tier requests to avoid rate limits.
20PREMIUM_TIER_RATE_LIMIT = 1 / 20
21# OpenDota API key (optional). Can be None or the API key as a string.
22API_KEY = None
23# Timeout for an API request.
24TIMEOUT = 5
25# Maximum number of retries for read timeout errors.
26MAX_RETRIES = 20
27
28# HELPERS
29# -------
30
31def api_key():
32 '''Format API key to the parameters.'''
33
34 if API_KEY is not None:
35 return {'api_key': API_KEY}
36 return {}
37
38def sleep(params=None):
39 '''Sleep to avoid incurring rate limits.'''
40
41 if params is None or params.get('api_key') is None:
42 time.sleep(FREE_TIER_RATE_LIMIT)
43 else:
44 time.sleep(PREMIUM_TIER_RATE_LIMIT)
45
46def single_get(url, params=None, timeout=TIMEOUT):
47 '''Single get request.'''
48
49 sleep(params)
50 response = requests.get(url, params=params, timeout=timeout)
51 response.raise_for_status()
52
53 return response.json()
54
55def persistent_get(url, params=None, timeout=TIMEOUT, retries=0, max_retries=MAX_RETRIES):
56 '''Persistent get request, whcih repeatedly retries if various connection errors occur.'''
57
58 try:
59 return single_get(url, params=params, timeout=timeout)
60 except (requests.exceptions.BaseHTTPError, requests.exceptions.RequestException) as error:
61 print(f'{error.__class__.__name__} error in request for URL "{url}"', file=sys.stderr)
62 if retries < max_retries:
63 return persistent_get(url, params=params, timeout=timeout, retries=retries+1)
64 else:
65 raise
66
67def get(url, params=None, timeout=TIMEOUT, persistent=False):
68 '''Make GET request to the OpenDOTA API, including rate limits.'''
69
70 if persistent:
71 return persistent_get(url, params=params, timeout=timeout)
72 return single_get(url, params=params, timeout=timeout)
73
74# RESOURCES
75# ---------
76
77# Methods to simplify calls to the OpenDota resources.
78
79def explorer(sql, persistent=False):
80 '''Make a request to the OpenDOTA explorer resource.'''
81
82 # Get our client URL and parameters.
83 url = f'{HOST}/api/explorer'
84 params = api_key()
85 params['sql'] = sql
86
87 # Make request and process result.
88 data = get(url, params=params, persistent=persistent)
89 if data['err'] is not None:
90 raise RuntimeError(f'Unexpected error, got {data["err"]}')
91
92 return data['rows']
93
94def match(match_id, persistent=False):
95 '''Make a request to the OpenDOTA matches resource.'''
96
97 url = f'{HOST}/api/matches/{match_id}'
98 params = api_key()
99
100 return get(url, params=params, persistent=persistent)