Skip to content

Commit 07f97bd

Browse files
authored
Merge pull request #102 from doluk/master
Allow coc.py to handle API requests for unlimited&uncached API endpoints
2 parents 322b2ae + 4d8bab5 commit 07f97bd

File tree

2 files changed

+59
-36
lines changed

2 files changed

+59
-36
lines changed

coc/client.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ class Client:
138138
"cache_max_size",
139139
"stats_max_size",
140140
"http",
141+
"realtime",
141142
"_ready",
142143
"correct_tags",
143144
"load_game_data",
@@ -166,6 +167,7 @@ def __init__(
166167
cache_max_size: int = 10000,
167168
stats_max_size: int = 1000,
168169
load_game_data: LoadGameData = LoadGameData(default=True),
170+
realtime = False,
169171
**_,
170172
):
171173

@@ -186,6 +188,7 @@ def __init__(
186188
self.stats_max_size = stats_max_size
187189

188190
self.http = None # set in method login()
191+
self.realtime = realtime
189192
self.correct_tags = correct_tags
190193
self.load_game_data = load_game_data
191194

@@ -586,7 +589,12 @@ async def get_clan_war(self, clan_tag: str, cls: Type[ClanWar] = ClanWar, **kwar
586589
clan_tag = correct_tag(clan_tag)
587590

588591
try:
589-
data = await self.http.get_clan_current_war(clan_tag)
592+
realtime = kwargs.get("realtime")
593+
except KeyError:
594+
realtime = None
595+
596+
try:
597+
data = await self.http.get_clan_current_war(clan_tag, realtime=realtime)
590598
except Forbidden as exception:
591599
raise PrivateWarLog(exception.response, exception.reason) from exception
592600

@@ -693,7 +701,12 @@ async def get_league_group(
693701
clan_tag = correct_tag(clan_tag)
694702

695703
try:
696-
data = await self.http.get_clan_war_league_group(clan_tag)
704+
realtime = kwargs.get("realtime")
705+
except KeyError:
706+
realtime = None
707+
708+
try:
709+
data = await self.http.get_clan_war_league_group(clan_tag, realtime=realtime)
697710
except Forbidden as exception:
698711
raise PrivateWarLog(exception.response, exception.reason) from exception
699712
except asyncio.TimeoutError:
@@ -741,7 +754,12 @@ async def get_league_war(self, war_tag: str, cls: Type[ClanWar] = ClanWar, **kwa
741754
war_tag = correct_tag(war_tag)
742755

743756
try:
744-
data = await self.http.get_cwl_wars(war_tag)
757+
realtime = kwargs.get("realtime")
758+
except KeyError:
759+
realtime = None
760+
761+
try:
762+
data = await self.http.get_cwl_wars(war_tag, realtime=realtime)
745763
except Forbidden as exception:
746764
raise PrivateWarLog(exception.response, exception.reason) from exception
747765

@@ -869,7 +887,7 @@ async def get_current_war(
869887
return get_war
870888

871889
try:
872-
league_group = await self.get_league_group(clan_tag)
890+
league_group = await self.get_league_group(clan_tag,**kwargs)
873891
except (NotFound, GatewayError) as exception:
874892
# either they're not in cwl (NotFound)
875893
# or it's an API bug where league group endpoint will timeout when the clan is searching (GatewayError)

coc/http.py

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -166,18 +166,18 @@ class HTTPClient:
166166

167167
# pylint: disable=too-many-arguments, missing-docstring, protected-access, too-many-branches
168168
def __init__(
169-
self,
170-
client,
171-
loop,
172-
email,
173-
password,
174-
key_names,
175-
key_count,
176-
key_scopes,
177-
throttle_limit,
178-
throttler=BasicThrottler,
179-
cache_max_size=10000,
180-
stats_max_size=1000,
169+
self,
170+
client,
171+
loop,
172+
email,
173+
password,
174+
key_names,
175+
key_count,
176+
key_scopes,
177+
throttle_limit,
178+
throttler=BasicThrottler,
179+
cache_max_size=10000,
180+
stats_max_size=1000
181181
):
182182
self.client = client
183183
self.loop = loop
@@ -187,7 +187,6 @@ def __init__(
187187
self.key_count = key_count
188188
self.key_scopes = key_scopes
189189
self.throttle_limit = throttle_limit
190-
191190
per_second = key_count * throttle_limit
192191

193192
self.__session = None
@@ -226,7 +225,7 @@ async def request(self, route, **kwargs):
226225
url = route.url
227226

228227
headers = {
229-
"Accept": "application/json",
228+
"Accept" : "application/json",
230229
"authorization": "Bearer {}".format(next(self.keys)),
231230
}
232231
kwargs["headers"] = headers
@@ -237,7 +236,7 @@ async def request(self, route, **kwargs):
237236
cache_control_key = route.url
238237
cache = self.cache
239238
# the cache will be cleaned once it becomes stale / a new object is available from the api.
240-
if cache is not None:
239+
if cache is not None and not self.client.realtime:
241240
try:
242241
return cache[cache_control_key]
243242
except KeyError:
@@ -261,7 +260,7 @@ async def request(self, route, **kwargs):
261260
# set a callback to remove the item from cache once it's stale.
262261
delta = int(response.headers["Cache-Control"].strip("max-age="))
263262
data["_response_retry"] = delta
264-
if cache is not None:
263+
if cache is not None and not self.client.realtime:
265264
self.cache[cache_control_key] = data
266265
LOG.debug("Cache-Control max age: %s seconds, key: %s", delta, cache_control_key)
267266
self.loop.call_later(delta, self._cache_remove, cache_control_key)
@@ -294,8 +293,8 @@ async def request(self, route, **kwargs):
294293
raise NotFound(response, data)
295294
if response.status == 429:
296295
LOG.error(
297-
"We have been rate-limited by the API. "
298-
"Reconsider the number of requests you are allowing per second."
296+
"We have been rate-limited by the API. "
297+
"Reconsider the number of requests you are allowing per second."
299298
)
300299
raise HTTPException(response, data)
301300

@@ -346,14 +345,20 @@ def get_clan_members(self, tag):
346345
def get_clan_warlog(self, tag):
347346
return self.request(Route("GET", "/clans/{}/warlog".format(tag)))
348347

349-
def get_clan_current_war(self, tag):
350-
return self.request(Route("GET", "/clans/{}/currentwar".format(tag)))
348+
def get_clan_current_war(self, tag, realtime = None):
349+
return self.request(Route("GET", "/clans/{}/currentwar".format(tag) + (
350+
'?realtime=true' if realtime or (realtime is None and self.client.realtime)
351+
else '')))
351352

352-
def get_clan_war_league_group(self, tag):
353-
return self.request(Route("GET", "/clans/{}/currentwar/leaguegroup".format(tag)))
353+
def get_clan_war_league_group(self, tag, realtime = None):
354+
return self.request(Route("GET", "/clans/{}/currentwar/leaguegroup".format(tag) + (
355+
'?realtime=true' if realtime or (realtime is None and self.client.realtime)
356+
else '')))
354357

355-
def get_cwl_wars(self, war_tag):
356-
return self.request(Route("GET", "/clanwarleagues/wars/{}".format(war_tag)))
358+
def get_cwl_wars(self, war_tag, realtime = None):
359+
return self.request(Route("GET", "/clanwarleagues/wars/{}".format(war_tag) + (
360+
'?realtime=true' if realtime or (realtime is None and self.client.realtime)
361+
else '')))
357362

358363
# locations
359364

@@ -433,17 +438,17 @@ async def initialise_keys(self):
433438
if len(self._keys) < self.key_count:
434439
for key in (k for k in keys if k["name"] == self.key_names and ip not in k["cidrRanges"]):
435440
LOG.info(
436-
"Deleting key with the name %s and IP %s (not matching our current IP address).",
437-
self.key_names, key["cidrRanges"],
441+
"Deleting key with the name %s and IP %s (not matching our current IP address).",
442+
self.key_names, key["cidrRanges"],
438443
)
439444
await session.post("https://developer.clashofclans.com/api/apikey/revoke", json={"id": key["id"]})
440445

441446
while len(self._keys) < self.key_count and len(keys) < KEY_MAXIMUM:
442447
data = {
443-
"name": self.key_names,
448+
"name" : self.key_names,
444449
"description": "Created on {}".format(datetime.now().strftime("%c")),
445-
"cidrRanges": [ip],
446-
"scopes": [self.key_scopes],
450+
"cidrRanges" : [ip],
451+
"scopes" : [self.key_scopes],
447452
}
448453

449454
LOG.info("Creating key with data %s.", str(data))
@@ -462,9 +467,9 @@ async def initialise_keys(self):
462467
if len(self._keys) == 0:
463468
await self.close()
464469
raise RuntimeError(
465-
"There are {} API keys already created and none match a key_name of '{}'."
466-
"Please specify a key_name kwarg, or go to 'https://developer.clashofclans.com' to delete "
467-
"unused keys.".format(len(keys), self.key_names)
470+
"There are {} API keys already created and none match a key_name of '{}'."
471+
"Please specify a key_name kwarg, or go to 'https://developer.clashofclans.com' to delete "
472+
"unused keys.".format(len(keys), self.key_names)
468473
)
469474

470475
await session.close()

0 commit comments

Comments
 (0)