Skip to content

Commit b456838

Browse files
authored
Minor Tweaks (#1)
* Added api_request_maker class * added renew_rand method to api_request_maker * added get_response method * shortened code a bit by adding a utility function for checking responses * random is now guaranteed to be max. 6 digits, less digits are allowed again
1 parent e3fcc5d commit b456838

File tree

2 files changed

+136
-134
lines changed

2 files changed

+136
-134
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
2+
import random
3+
import time
4+
import hashlib
5+
import collections
6+
7+
class CodeforcesApiRequestMaker():
8+
9+
api_key = ""
10+
secret = ""
11+
rand = 0
12+
assigned_rand = False
13+
anonimus = False
14+
15+
def __init__(self, api_key=None, secret=None, random_number=1000000):
16+
"""
17+
Initializes main variables: api_key, secret, random (default is between 1
18+
and 1000000 unless specified)
19+
"""
20+
21+
if random_number == 1000000 :
22+
random_number = random.randint(100000, 999999)
23+
self.assigned_rand = True
24+
elif random_number < 100000 and random_number > 999999:
25+
raise Exception(
26+
"Non 6-digit number passed as random_number for API Signature",
27+
random_number
28+
)
29+
if api_key is None and secret is None:
30+
self.anonimus = True
31+
else:
32+
self.api_key = api_key
33+
self.secret = secret
34+
self.anonimus = False
35+
self.rand = random_number
36+
37+
def generate_url(self, method_name, **fields):
38+
"""
39+
Generates request URL for API.
40+
"""
41+
42+
if not self.anonimus:
43+
44+
#Renew Rand
45+
if not self.assigned_rand:
46+
self.renew_rand()
47+
48+
current_time = time.time()
49+
fields["apiKey"] = str(self.api_key)
50+
fields["time"] = str(int(current_time))
51+
api_signature = str(self.rand) + "/" + method_name + "?"
52+
fields = collections.OrderedDict(sorted(fields.items()))
53+
for i in fields:
54+
api_signature += str(i) + "="
55+
if isinstance(fields[i], list):
56+
for j in fields[i]:
57+
api_signature += str(j) + ";"
58+
else:
59+
api_signature += str(fields[i])
60+
api_signature += "&"
61+
api_signature = api_signature[:-1]
62+
api_signature += "#" + str(self.secret)
63+
hashed_signature = hashlib.sha512(api_signature.encode("utf-8"))
64+
65+
request_url = "https://codeforces.com/api/" + str(method_name) + "?"
66+
for i in fields:
67+
request_url += str(i) + "="
68+
if isinstance(fields[i], list):
69+
for j in fields[i]:
70+
request_url += str(j) + ";"
71+
else:
72+
request_url += str(fields[i])
73+
request_url += "&"
74+
request_url += (
75+
"apiSig=" + str(self.rand) + str(hashed_signature.hexdigest())
76+
)
77+
else:
78+
request_url = "https://codeforces.com/api/" + str(method_name) + "?"
79+
for i in fields:
80+
request_url += str(i) + "="
81+
if isinstance(fields[i], list):
82+
for j in fields[i]:
83+
request_url += str(j) + ";"
84+
else:
85+
request_url += str(fields[i])
86+
request_url += "&"
87+
request_url = request_url[:-1]
88+
return request_url
89+
90+
def check_return_code(self, response):
91+
"""
92+
Checks if a returned response is OK.
93+
If not OK Exception will be raised will additional info.
94+
"""
95+
if response["status"] != "OK":
96+
raise Exception(
97+
"Request returned not OK status",
98+
response["status"],
99+
response["comment"],
100+
)
101+
102+
def renew_rand(self, random_number=1000000):
103+
"""
104+
It's recommended that you renew your apiSig for each request
105+
default is between 100000 and 1000000 unless specified)
106+
"""
107+
if random_number == 1000000 :
108+
random_number = random.randint(100000, 999999)
109+
elif random_number < 100000 and random_number > 999999:
110+
raise Exception(
111+
"Non 6-digit number passed as random_number for renew_rand",
112+
random_number
113+
)
114+
115+
def get_response(self, request):
116+
response = request.json()
117+
self.check_return_code(response)
118+
return response

codeforces_api/api_requests.py

Lines changed: 18 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,15 @@
11
"""
22
Main class for requests.
33
"""
4-
import collections
5-
import hashlib
6-
import random
7-
import time
8-
94
import requests
105

6+
from api_request_maker import *
117

12-
class CodeforcesApi:
8+
class CodeforcesApi(CodeforcesApiRequestMaker):
139
"""
1410
Class for using official API requests.
1511
"""
1612

17-
api_key = ""
18-
secret = ""
19-
random = 0
20-
anonimus = False
21-
22-
def __init__(self, api_key=None, secret=None, rand=1000000):
23-
"""
24-
Initializes main variables: api_key, secret, random (default is between 1 and 1000000),
25-
but when you set it it will be yours.
26-
"""
27-
if rand == 1000000:
28-
rand = random.randint(1, 1000000)
29-
if api_key is None and secret is None:
30-
self.anonimus = True
31-
else:
32-
self.api_key = api_key
33-
self.secret = secret
34-
self.anonimus = False
35-
self.random = rand
36-
37-
def generate_url(self, method_name, **fields):
38-
"""
39-
Generates request URL for API.
40-
"""
41-
if not self.anonimus:
42-
current_time = time.time()
43-
fields["apiKey"] = str(self.api_key)
44-
fields["time"] = str(int(current_time))
45-
api_signature = str(self.random) + "/" + method_name + "?"
46-
fields = collections.OrderedDict(sorted(fields.items()))
47-
for i in fields:
48-
api_signature += str(i) + "="
49-
if isinstance(fields[i], list):
50-
for j in fields[i]:
51-
api_signature += str(j) + ";"
52-
else:
53-
api_signature += str(fields[i])
54-
api_signature += "&"
55-
api_signature = api_signature[:-1]
56-
api_signature += "#" + str(self.secret)
57-
hashed_signature = hashlib.sha512(api_signature.encode("utf-8"))
58-
59-
request_url = "https://codeforces.com/api/" + str(method_name) + "?"
60-
for i in fields:
61-
request_url += str(i) + "="
62-
if isinstance(fields[i], list):
63-
for j in fields[i]:
64-
request_url += str(j) + ";"
65-
else:
66-
request_url += str(fields[i])
67-
request_url += "&"
68-
request_url += (
69-
"apiSig=" + str(self.random) + str(hashed_signature.hexdigest())
70-
)
71-
else:
72-
request_url = "https://codeforces.com/api/" + str(method_name) + "?"
73-
for i in fields:
74-
request_url += str(i) + "="
75-
if isinstance(fields[i], list):
76-
for j in fields[i]:
77-
request_url += str(j) + ";"
78-
else:
79-
request_url += str(fields[i])
80-
request_url += "&"
81-
request_url = request_url[:-1]
82-
return request_url
83-
84-
def check_return_code(self, response):
85-
"""
86-
Checks if a returned response is OK.
87-
If not OK Exception will be raised will additional info.
88-
"""
89-
if response["status"] != "OK":
90-
raise Exception(
91-
"Request returned not OK status",
92-
response["status"],
93-
response["comment"],
94-
)
95-
9613
def blog_entry_comments(self, blog_entry_id):
9714
"""
9815
Get blogEntry.commnets for blog, blog_entry_id required.
@@ -103,9 +20,7 @@ def blog_entry_comments(self, blog_entry_id):
10320
"blogEntry.comments", **{"blogEntryId": str(blog_entry_id)}
10421
)
10522
)
106-
response = request.json()
107-
self.check_return_code(response)
108-
return response
23+
return self.get_response(request)
10924

11025
def blog_entry_view(self, blog_entry_id):
11126
"""
@@ -116,9 +31,7 @@ def blog_entry_view(self, blog_entry_id):
11631
"blogEntry.view", **{"blogEntryId": str(blog_entry_id)}
11732
)
11833
request = requests.get(request_url)
119-
response = request.json()
120-
self.check_return_code(response)
121-
return response
34+
return self.get_response(request)
12235

12336
def contest_hacks(self, contest_id):
12437
"""
@@ -129,9 +42,7 @@ def contest_hacks(self, contest_id):
12942
"contest.hacks", **{"contestId": str(contest_id)}
13043
)
13144
request = requests.get(request_url)
132-
response = request.json()
133-
self.check_return_code(response)
134-
return response
45+
return self.get_response(request)
13546

13647
def contest_list(self, gym=False):
13748
"""
@@ -140,9 +51,7 @@ def contest_list(self, gym=False):
14051
"""
14152
request_url = self.generate_url("contest.list", **{"gym": str(gym)})
14253
request = requests.get(request_url)
143-
response = request.json()
144-
self.check_return_code(response)
145-
return response
54+
return self.get_response(request)
14655

14756
def contest_rating_changes(self, contest_id):
14857
"""
@@ -153,9 +62,7 @@ def contest_rating_changes(self, contest_id):
15362
"contest.ratingChanges", **{"contestId": str(contest_id)}
15463
)
15564
request = requests.get(request_url)
156-
response = request.json()
157-
self.check_return_code(response)
158-
return response
65+
return self.get_response(request)
15966

16067
def contest_standings(
16168
self,
@@ -195,9 +102,7 @@ def contest_standings(
195102
parameters["room"] = str(room)
196103
request_url = self.generate_url("contest.standings", **parameters)
197104
request = requests.get(request_url)
198-
response = request.json()
199-
self.check_return_code(response)
200-
return response
105+
return self.get_response(request)
201106

202107
def contest_status(self, contest_id, handle="", start=-1, count=-1):
203108
"""
@@ -218,9 +123,7 @@ def contest_status(self, contest_id, handle="", start=-1, count=-1):
218123
parameters["count"] = str(count)
219124
request_url = self.generate_url("contest.status", **parameters)
220125
request = requests.get(request_url)
221-
response = request.json()
222-
self.check_return_code(response)
223-
return response
126+
return self.get_response(request)
224127

225128
def problemset_problems(self, tags=[""], problemset_name=""):
226129
"""
@@ -239,9 +142,7 @@ def problemset_problems(self, tags=[""], problemset_name=""):
239142
parameters["problemsetName"] = problemset_name
240143
request_url = self.generate_url("problemset.problems", **parameters)
241144
request = requests.get(request_url)
242-
response = request.json()
243-
self.check_return_code(response)
244-
return response
145+
return self.get_response(request)
245146

246147
def problemset_recent_status(self, count, problemset_name=""):
247148
"""
@@ -260,9 +161,7 @@ def problemset_recent_status(self, count, problemset_name=""):
260161
parameters["problemsetName"] = problemset_name
261162
request_url = self.generate_url("problemset.recentStatus", **parameters)
262163
request = requests.get(request_url)
263-
response = request.json()
264-
self.check_return_code(response)
265-
return response
164+
return self.get_response(request)
266165

267166
def recent_actions(self, max_count=100):
268167
"""
@@ -275,9 +174,7 @@ def recent_actions(self, max_count=100):
275174
raise OverflowError("Max_count should be less or equal to 1000")
276175
request_url = self.generate_url("recentActions", **{"maxCount": str(max_count)})
277176
request = requests.get(request_url)
278-
response = request.json()
279-
self.check_return_code(response)
280-
return response
177+
return self.get_response(request)
281178

282179
def user_blog_entries(self, handle):
283180
"""
@@ -289,9 +186,7 @@ def user_blog_entries(self, handle):
289186
raise TypeError("Handle should not be empty")
290187
request_url = self.generate_url("user.blogEntries", **{"handle": str(handle)})
291188
request = requests.get(request_url)
292-
response = request.json()
293-
self.check_return_code(response)
294-
return response
189+
return self.get_response(request)
295190

296191
def user_friends(self, only_online=False):
297192
"""
@@ -306,9 +201,7 @@ def user_friends(self, only_online=False):
306201
"user.friends", **{"onlyOnline": str(only_online)}
307202
)
308203
request = requests.get(request_url)
309-
response = request.json()
310-
self.check_return_code(response)
311-
return response
204+
return self.get_response(request)
312205

313206
def user_info(self, handles):
314207
"""
@@ -322,9 +215,7 @@ def user_info(self, handles):
322215
raise OverflowError("Max count of handles should be less or equal to 10000")
323216
request_url = self.generate_url("user.info", **{"handles": handles})
324217
request = requests.get(request_url)
325-
response = request.json()
326-
self.check_return_code(response)
327-
return response
218+
return self.get_response(request)
328219

329220
def user_rated_list(self, active_only=False):
330221
"""
@@ -336,9 +227,7 @@ def user_rated_list(self, active_only=False):
336227
"user.ratedList", **{"activeOnly": str(active_only)}
337228
)
338229
request = requests.get(request_url)
339-
response = request.json()
340-
self.check_return_code(response)
341-
return response
230+
return self.get_response(request)
342231

343232
def user_rating(self, handle):
344233
"""
@@ -348,9 +237,7 @@ def user_rating(self, handle):
348237
"""
349238
request_url = self.generate_url("user.rating", **{"handle": str(handle)})
350239
request = requests.get(request_url)
351-
response = request.json()
352-
self.check_return_code(response)
353-
return response
240+
return self.get_response(request)
354241

355242
def user_status(self, handle, start=-1, count=-1):
356243
"""
@@ -369,7 +256,4 @@ def user_status(self, handle, start=-1, count=-1):
369256
parameters["count"] = str(count)
370257
request_url = self.generate_url("user.status", **parameters)
371258
request = requests.get(request_url)
372-
response = request.json()
373-
self.check_return_code(response)
374-
return response
375-
259+
return self.get_response(request)

0 commit comments

Comments
 (0)