Skip to content

Commit 1234be2

Browse files
committed
feat: Add function to make api calls
1 parent 9a755ed commit 1234be2

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

codeforces/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from . import error
2+
from . import api

codeforces/api.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import time
2+
import os
3+
import json
4+
import random
5+
import hashlib
6+
import urllib.request
7+
import urllib.error
8+
import urllib.parse
9+
from . import error
10+
11+
12+
__all__ = ['call']
13+
14+
15+
CODEFORCES_API_URL = "https://codeforces.com/api/"
16+
17+
18+
def __generate_api_sig(method, args, secret):
19+
rand = "%06d" % random.randint(0, 999999)
20+
url_args = urllib.parse.urlencode(sorted(args.items()))
21+
return rand + hashlib.sha512(
22+
("%s/%s?%s#%s" % (rand, method, url_args, secret)).encode('utf-8')
23+
).hexdigest()
24+
25+
26+
def call(method, key=None, secret=None, **kargs):
27+
"""call a Codeforces API method"""
28+
args = kargs.copy()
29+
30+
if (key is not None) and (secret is not None):
31+
args['time'] = int(time.time())
32+
args['apiKey'] = key
33+
args['apiSig'] = __generate_api_sig(method, args, secret)
34+
35+
url_args = urllib.parse.urlencode(args)
36+
url = os.path.join(CODEFORCES_API_URL, "%s?%s" % (method, url_args))
37+
38+
try:
39+
with urllib.request.urlopen(url) as res:
40+
data = json.loads(res.read().decode('utf-8'))
41+
except urllib.error.HTTPError as err:
42+
if err.code == 400:
43+
data = json.loads(err.read())
44+
elif err.code == 404:
45+
data = {'status': 'FAILED', 'comment': "%s: No such method" % method}
46+
elif (err.code in (429, 503)):
47+
time.sleep(1)
48+
return call(method, key, secret, **kargs)
49+
else:
50+
raise
51+
52+
if data['status'] == 'FAILED':
53+
raise error.CodeforcesAPIError(data['comment'], method, kargs)
54+
55+
return data['result']

0 commit comments

Comments
 (0)