Skip to content

Commit ed849ba

Browse files
committed
Add on_token_reset function which is called when a token is reset. By default this does nothing, however you can override it by either subclassing client, or adding the decorator @client.event() to your new on_token_reset function. This can be either a regular or coroutine function.
1 parent 22ecada commit ed849ba

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

coc/client.py

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def __init__(self, token, *, loop=None, email=None, password=None, update_tokens
117117
if update_tokens is True and (not email) or (not password):
118118
raise RuntimeError('An email and password must be set if update_tokens is True')
119119

120-
self.http = HTTPClient(token=token, loop=self.loop, email=email,
120+
self.http = HTTPClient(client=self, token=token, loop=self.loop, email=email,
121121
password=password, update_tokens=update_tokens)
122122
log.info('Clash of Clans API client created')
123123
self._add_cache()
@@ -130,6 +130,74 @@ async def close(self):
130130
log.info('Clash of Clans client logging out...')
131131
await self.http.close()
132132

133+
async def on_token_reset(self, new_token):
134+
"""Event: called when the client's token is reset.
135+
136+
By default this does nothing.
137+
138+
Example
139+
---------
140+
141+
You can manually override this by either:
142+
143+
Subclassing Client:
144+
145+
.. code-block:: python3
146+
147+
class Client(coc.Client):
148+
def __init__(self, token, email, password):
149+
super().__init__(token=token, email=email,
150+
password=password, update_token=True)
151+
152+
def on_token_reset(token):
153+
print('My new token is {}'.format(token))
154+
155+
Using the event decorator:
156+
157+
.. code-block:: python3
158+
159+
@client.event()
160+
async def on_token_reset(token):
161+
print('My new token is {}'.format(token))
162+
163+
:param new_token: :class:`str` The new token
164+
"""
165+
pass
166+
167+
def event(self, fctn):
168+
"""A decorator that registers an event.
169+
170+
The only event at present is :func:`on_token_reset`.
171+
172+
This could be a coro or regular function.
173+
174+
Example
175+
--------
176+
177+
.. code-block:: python3
178+
179+
@client.event()
180+
async def on_token_reset(token):
181+
print('My new token is {}'.format(token))
182+
"""
183+
setattr(self, fctn.__name__, fctn)
184+
log.info('Successfully registered %s event', fctn.__name__)
185+
return fctn
186+
187+
def dispatch(self, event_name, *args, **kwargs):
188+
log.debug('Dispatching %s event', event_name)
189+
event = 'on_' + event_name
190+
191+
try:
192+
fctn = getattr(self, event)
193+
except AttributeError:
194+
return
195+
else:
196+
if asyncio.iscoroutinefunction(fctn):
197+
asyncio.ensure_future(event(*args, **kwargs), loop=self.loop)
198+
else:
199+
event(*args, **kwargs)
200+
133201
def _add_cache(self):
134202
self._search_clans = {}
135203
self._war_clans = {}

coc/http.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ def __init__(self, method, path, kwargs: dict=None, api_page=False):
6666

6767

6868
class HTTPClient:
69-
def __init__(self, token, loop=None, *, email, password, update_tokens=False):
69+
def __init__(self, client, token, loop=None, *, email, password, update_tokens=False):
70+
self.client = client
7071
self.token = token
7172
self.loop = asyncio.get_event_loop() if loop is None else loop
7273
self.__session = None
@@ -176,6 +177,7 @@ async def reset_token(self):
176177
clean_token = response['key']['key']
177178

178179
self.token = clean_token
180+
self.client.dispatch('token_reset', clean_token)
179181
return clean_token
180182

181183
# clans

0 commit comments

Comments
 (0)