Repository navigation
Expand file tree
/
Copy pathapi.py
More file actions
66 lines (50 loc) · 1.76 KB
/
Copy pathapi.py
File metadata and controls
66 lines (50 loc) · 1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"""Functions to call the codeforces api."""
import hashlib
import json
import secrets
import time
import urllib.parse
import requests
from . import error
__all__ = ['call']
CODEFORCES_API_URL = "https://codeforces.com/api/"
def _generate_api_sig(method, args, secret):
rand = "%06d" % secrets.randbelow(999999)
url_args = urllib.parse.urlencode(sorted(args.items()))
return rand + hashlib.sha512(("%s/%s?%s#%s" % (rand, method, url_args, secret)).encode('utf-8')).hexdigest()
def call(method, key=None, secret=None, **kwargs):
"""
Call a Codeforces API method.
Parameters
----------
method: str
Name of method to call, list of all methods can be found at
https://codeforces.com/api/help.
key: str, optional
Your api key (needed for authorized calls)
secret: str, optional
Secret for your api key.
**kwargs
Arguments for the api call
Returns
-------
any
A python object containing the results of the api call.
"""
params = kwargs.copy()
if (key is not None) and (secret is not None):
params['time'] = int(time.time())
params['apiKey'] = key
params['apiSig'] = _generate_api_sig(method, params, secret)
url = urllib.parse.urljoin(CODEFORCES_API_URL, "%s" % method)
with requests.get(url, params=params) as res:
if res.status_code == 404:
data = {'status': 'FAILED', 'comment': "%s: No such method" % method}
elif res.status_code in (429, 503):
time.sleep(1)
return call(method, key, secret, **kwargs)
else:
data = json.loads(res.text)
if data['status'] == 'FAILED':
raise error.CodeforcesAPIError(data['comment'], method, kwargs)
return data['result']