Skip to content

Commit 55b45c9

Browse files
committed
Add a huge number of new events. Find them in :ref:EventReference in the docs.
Tidy up some linting/other minor fixes
1 parent 4827ee5 commit 55b45c9

File tree

2 files changed

+459
-119
lines changed

2 files changed

+459
-119
lines changed

coc/client.py

Lines changed: 124 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333

3434
from .cache import Cache
3535
from .clans import Clan, SearchClan
36-
from .enums import ACHIEVEMENT_ORDER
3736
from .errors import Forbidden, NotFound
3837
from .miscmodels import Location, League
3938
from .http import HTTPClient
@@ -1294,9 +1293,9 @@ def __init__(self, **options):
12941293
self._cache_lookup['cache_events'] = cache_events
12951294

12961295
def _setup(self):
1297-
self._clan_updates = None
1298-
self._player_updates = None
1299-
self._war_updates = None
1296+
self._clan_updates = []
1297+
self._player_updates = []
1298+
self._war_updates = []
13001299

13011300
self._active_state_tasks = {}
13021301

@@ -1426,7 +1425,7 @@ async def _run_event(self, event_name, coro, *args, **kwargs):
14261425
await coro(*args, **kwargs)
14271426
except asyncio.CancelledError:
14281427
pass
1429-
except Exception:
1428+
except (Exception, BaseException):
14301429
try:
14311430
await self.on_event_error(event_name, *args, **kwargs)
14321431
except asyncio.CancelledError:
@@ -1467,10 +1466,7 @@ async def add_clan_update(self, tags: Iterable, *, member_updates=False, retry_i
14671466
retry_interval : int
14681467
In seconds, how often the client 'checks' for updates. Defaults to 600 (10min)
14691468
"""
1470-
if not self._clan_updates:
1471-
self._clan_updates = [n for n in tags]
1472-
else:
1473-
self._clan_updates.extend(n for n in tags)
1469+
self._clan_updates.extend(n for n in tags)
14741470

14751471
if member_updates is True:
14761472
async for clan in self.get_clans(tags):
@@ -1491,10 +1487,7 @@ def add_war_update(self, tags: Iterable, *, retry_interval=600):
14911487
retry_interval : int
14921488
In seconds, how often the client 'checks' for updates. Defaults to 600 (10min)
14931489
"""
1494-
if not self._war_updates:
1495-
self._war_updates = [n for n in tags]
1496-
else:
1497-
self._war_updates.extend(n for n in tags)
1490+
self._war_updates.extend(n for n in tags)
14981491

14991492
if retry_interval < 0:
15001493
raise ValueError('retry_interval must be greater than 0 seconds')
@@ -1511,10 +1504,7 @@ def add_player_update(self, tags: Iterable, retry_interval=600):
15111504
retry_interval : int
15121505
In seconds, how often the client 'checks' for updates. Defaults to 600 (10min)
15131506
"""
1514-
if not self._player_updates:
1515-
self._player_updates = [n for n in tags]
1516-
else:
1517-
self._player_updates.extend(n for n in tags)
1507+
self._player_updates.extend(n for n in tags)
15181508

15191509
if retry_interval < 0:
15201510
raise ValueError('retry_interval must be greater than 0 seconds')
@@ -1647,7 +1637,7 @@ async def _war_updater(self):
16471637
await self._update_wars()
16481638
self._dispatch_batch_updates('on_war')
16491639
await asyncio.sleep(self._war_retry_interval)
1650-
except Exception:
1640+
except (Exception, BaseException):
16511641
await self.on_event_error('on_war_update')
16521642
return await self._war_updater()
16531643

@@ -1658,7 +1648,7 @@ async def _clan_updater(self):
16581648
await self._update_clans()
16591649
self._dispatch_batch_updates('on_clan')
16601650
await asyncio.sleep(self._clan_retry_interval)
1661-
except Exception:
1651+
except (Exception, BaseException):
16621652
await self.on_event_error('on_clan_update')
16631653
return await self._clan_updater()
16641654

@@ -1669,66 +1659,25 @@ async def _player_updater(self):
16691659
await self._update_players()
16701660
self._dispatch_batch_updates('on_player')
16711661
await asyncio.sleep(self._player_retry_interval)
1672-
except Exception:
1662+
except (Exception, BaseException):
16731663
await self.on_event_error('on_player_update')
16741664
return await self._player_updater()
16751665

16761666
async def _check_member_count(self, cached_clan, new_clan):
1677-
differences = [n for n in new_clan._members if n not in set(n.tag for n in cached_clan._members)]
1667+
differences = [n for n in new_clan.members if n not in set(n.tag for n in cached_clan.members)]
16781668

16791669
for tag in differences:
1680-
new_member = get(new_clan._members, tag=tag)
1670+
new_member = get(new_clan.members, tag=tag)
16811671
if new_member:
16821672
self.dispatch('on_clan_member_join', new_member, new_clan)
16831673
continue
16841674

1685-
member_left = get(cached_clan._members, tag=tag)
1675+
member_left = get(cached_clan.members, tag=tag)
16861676
if member_left:
16871677
self.dispatch('on_clan_member_leave', member_left, new_clan)
1688-
continue
16891678

16901679
return
16911680

1692-
async def _update_clans(self):
1693-
if not self._clan_updates:
1694-
return
1695-
1696-
async for clan in self.get_clans(self._clan_updates, cache=False, update_cache=False):
1697-
cached_clan = cache_search_clans.get(clan.tag)
1698-
if not cached_clan:
1699-
cache_search_clans.add(clan.tag, clan)
1700-
continue
1701-
1702-
if clan == cached_clan:
1703-
continue
1704-
1705-
self.dispatch('on_clan_update', cached_clan, clan)
1706-
1707-
if clan.member_count != cached_clan.member_count:
1708-
await self._check_member_count(cached_clan, clan)
1709-
1710-
cached_clan._data['memberCount'] = clan.member_count # hack for next line
1711-
1712-
if clan._data == cached_clan._data:
1713-
cache_search_clans.add(clan.tag, clan)
1714-
continue
1715-
1716-
if clan.members != cached_clan.members: # check for member donations and received
1717-
for m, c in cached_clan._members, clan._members:
1718-
if m.donations != c.donations:
1719-
self.dispatch('on_clan_member_donation', m.donations, c.donations, m, clan)
1720-
cached_clan._data['members'][cached_clan.members.index(c)]['donations'] = m.donations
1721-
if m.received != c.received:
1722-
self.dispatch('on_clan_member_donation_received', m.received, c.received, m, clan)
1723-
cached_clan._data['members'][cached_clan.members.index(c)]['donationsReceived'] = m.received
1724-
1725-
if clan._data == cached_clan._data:
1726-
cache_search_clans.add(clan.tag, clan)
1727-
continue
1728-
1729-
self.dispatch('on_clan_settings_update', cached_clan, clan)
1730-
cache_search_clans.add(clan.tag, clan)
1731-
17321681
async def _wait_for_state_change(self, state_to_wait_for, war):
17331682
if state_to_wait_for == 'inWar':
17341683
to_sleep = war.start_time.seconds_until
@@ -1784,12 +1733,12 @@ async def _update_wars(self):
17841733

17851734
async for war in self.get_current_wars(self._war_updates, cache=False, update_cache=False):
17861735
cached_war = cache_current_wars.get(war.clan_tag)
1736+
17871737
if not cached_war:
17881738
cache_current_wars.add(war.clan_tag, war)
17891739
continue
17901740

17911741
if war == cached_war:
1792-
cache_current_wars.add(war.clan_tag, war)
17931742
continue
17941743

17951744
self.dispatch('on_war_update', cached_war, war)
@@ -1800,8 +1749,7 @@ async def _update_wars(self):
18001749
if not war._attacks:
18011750
continue # if there are no attacks next line will raise TypeError.. we're not in war anymore anyway
18021751
if not cached_war._attacks:
1803-
new_attacks = [n for n in war._attacks] # war has just started
1804-
1752+
new_attacks = war.attacks
18051753
else:
18061754
new_attacks = [n for n in war._attacks if n not in set(cached_war._attacks)]
18071755

@@ -1826,79 +1774,146 @@ async def _update_players(self):
18261774

18271775
self.dispatch('on_player_update', cached_player, player)
18281776

1777+
# name
18291778
if player.name != cached_player.name:
18301779
self.dispatch('on_player_name_change', cached_player.name, player.name, player)
1831-
cached_player._data['name'] = player.name
18321780

1781+
# town/builder halls
18331782
if player.town_hall != cached_player.town_hall:
18341783
self.dispatch('on_player_townhall_upgrade', cached_player.town_hall, player.town_hall, player)
1835-
cached_player._data['townHallLevel'] = player.town_hall
1836-
18371784
if player.builder_hall != cached_player.builder_hall:
18381785
self.dispatch('on_player_builderhall_upgrade',
18391786
cached_player.builder_hall, player.builder_hall, player)
1840-
cached_player._data['builderHallLevel'] = player.town_hall
18411787

1842-
if player == cached_player:
1843-
cache_search_players.add(player.tag, player)
1844-
continue
1845-
1846-
achievement_updates = (n for n in player._achievements if n not in set(cached_player._achievements))
1788+
# best trophies/versus/war stars
1789+
if player.best_trophies != cached_player.best_trophies:
1790+
self.dispatch('on_player_best_trophies_change',
1791+
cached_player.best_trophies, player.best_trophies, player)
1792+
if player.best_versus_trophies != cached_player.best_versus_trophies:
1793+
self.dispatch('on_player_best_versus_trophies_change',
1794+
cached_player.best_versus_trophies, player.best_versus_trophies, player)
1795+
if player.war_stars != cached_player.war_stars:
1796+
self.dispatch('on_player_war_stars_change', cached_player.war_stars, player.war_stars, player)
1797+
1798+
# attacks win/defense/versus
1799+
if player.attack_wins != cached_player.attack_wins:
1800+
self.dispatch('on_player_attack_wins_change', cached_player.attack_wins, player.attack_wins, player)
1801+
if player.defense_wins != cached_player.defense_wins:
1802+
self.dispatch('on_player_defense_wins_change', cached_player.defense_wins, player.defense_wins, player)
1803+
if player.versus_attacks_wins != cached_player.versus_attacks_wins:
1804+
self.dispatch('on_player_versus_attacks_change',
1805+
cached_player.versus_attacks_wins, player.versus_attacks_wins, player)
1806+
1807+
# trophies + league
1808+
if player.trophies != cached_player.trophies:
1809+
self.dispatch('on_player_trophies_change', cached_player.trophies, player.trophies, player)
1810+
if player.league != cached_player.league:
1811+
self.dispatch('on_player_league_change', cached_player.league, player.league, player)
1812+
1813+
# clan stuff: role, donations, received, rank and prev. rank
1814+
if player.role != cached_player.role:
1815+
self.dispatch('on_player_role_change', cached_player.role, player.role, player)
1816+
if player.donations != cached_player.donations:
1817+
self.dispatch('on_player_donations_change', cached_player.donations, player.donations, player)
1818+
if player.received != cached_player.received:
1819+
self.dispatch('on_player_received_change', cached_player.received, player.received, player)
1820+
if player.clan_rank != cached_player.clan_rank:
1821+
self.dispatch('on_player_clan_rank_change', cached_player.clan_rank, player.clan_rank, player)
1822+
if player.previous_clan_rank != cached_player.previous_clan_rank:
1823+
self.dispatch('on_player_previous_clan_rank_change',
1824+
cached_player.clan_previous_rank, player.clan_previous_rank, player)
1825+
1826+
achievement_updates = (n for n in player.achievements if n not in set(cached_player.achievements))
18471827
troop_upgrades = (n for n in player.troops if n not in set(cached_player.troops))
18481828
spell_upgrades = (n for n in player.spells if n not in set(cached_player.spells))
18491829
hero_upgrades = (n for n in player.heroes if n not in set(cached_player.heroes))
18501830

18511831
for achievement in achievement_updates:
1852-
old_achievement = get(cached_player._achievements, name=achievement.name)
1832+
old_achievement = get(cached_player.achievements, name=achievement.name)
18531833
self.dispatch('on_player_achievement_update', old_achievement, achievement, player)
1854-
i = ACHIEVEMENT_ORDER.index(achievement.name)
1855-
cached_player._data['achievements'][i] = achievement._data
18561834

18571835
for troop in troop_upgrades:
18581836
old_troop = get(cached_player.troops, name=troop.name)
18591837
self.dispatch('on_player_troop_upgrade', old_troop, troop, player)
1860-
# this is a bit of a waste of resources, but we can't rely on order
1861-
# as locked troops won't appear in the troops list from api,
1862-
# meaning the order will change per-player.
1863-
troops = [n['name'] for n in cached_player._data['troops']]
1864-
try:
1865-
i = troops.index(troop.name)
1866-
except ValueError:
1867-
self.dispatch('on_player_troop_unlock', troop, player)
1868-
continue
1869-
cached_player._data['troops'][i] = troop._data
18701838

18711839
for spell in spell_upgrades:
18721840
old_spell = get(cached_player.spells, name=spell.name)
18731841
self.dispatch('on_player_spell_upgrade', old_spell, spell, player)
1874-
# same issue as troops
1875-
spells = [n['name'] for n in cached_player._data['spells']]
1876-
try:
1877-
i = spells.index(spell.name)
1878-
except ValueError:
1879-
self.dispatch('on_player_spell_unlock', spell, player)
1880-
continue
1881-
1882-
cached_player._data['spells'][i] = spell._data
18831842

18841843
for hero in hero_upgrades:
18851844
old_hero = get(cached_player.heroes, name=hero.name)
18861845
self.dispatch('on_player_hero_upgrade', old_hero, hero, player)
1887-
# same issue as troops
1888-
heroes = [n['name'] for n in cached_player._data['heroes']]
1889-
try:
1890-
i = heroes.index(hero.name)
1891-
except ValueError:
1892-
self.dispatch('on_player_hero_unlock', hero, player)
1893-
continue
18941846

1895-
cached_player._data['heroes'][i] = hero._data
1847+
async def _update_clans(self):
1848+
if not self._clan_updates:
1849+
return
1850+
1851+
async for clan in self.get_clans(self._clan_updates, cache=False, update_cache=False):
1852+
cached_clan = cache_search_clans.get(clan.tag)
1853+
if not cached_clan:
1854+
cache_search_clans.add(clan.tag, clan)
1855+
continue
18961856

1897-
if cached_player == player:
1898-
cache_search_players.add(player.tag, player)
1857+
if clan == cached_clan:
1858+
continue
1859+
1860+
self.dispatch('on_clan_update', cached_clan, clan)
1861+
1862+
if clan.member_count != cached_clan.member_count:
1863+
await self._check_member_count(cached_clan, clan)
1864+
if clan.members != cached_clan.members:
1865+
await self._update_clan_members(cached_clan, clan)
1866+
1867+
# settings
1868+
if clan.level != cached_clan.level:
1869+
self.dispatch('on_clan_level_change', cached_clan.level, clan.level, clan)
1870+
if clan.description != cached_clan.description:
1871+
self.dispatch('on_clan_description_change', cached_clan.description, clan.description, clan)
1872+
if clan.public_war_log != cached_clan.public_war_log:
1873+
self.dispatch('on_clan_public_war_log_change', cached_clan.public_war_log,
1874+
clan.public_war_log, clan)
1875+
if clan.type != cached_clan.type:
1876+
self.dispatch('on_clan_type_change', cached_clan.type, clan.type, clan)
1877+
if clan.badge != cached_clan.badge:
1878+
self.dispatch('on_clan_badge_change', cached_clan.badge, clan.badge, clan)
1879+
if clan.required_trophies != cached_clan.required_trophies:
1880+
self.dispatch('on_clan_required_trophies_change',
1881+
cached_clan.required_trophies, clan.required_trophies, clan)
1882+
if clan.war_frequency != cached_clan.war_frequency:
1883+
self.dispatch('on_clan_war_frequency_change', cached_clan.war_frequency, clan.war_frequency, clan)
1884+
1885+
# war win/loss/tie/streak
1886+
if clan.war_win_streak != cached_clan.war_win_streak:
1887+
self.dispatch('on_clan_war_win_streak_change', cached_clan.war_win_streak, clan.war_win_streak,
1888+
clan)
1889+
if clan.war_wins != cached_clan.war_wins:
1890+
self.dispatch('on_clan_war_win_change', cached_clan.war_wins, clan.war_wins, clan)
1891+
if clan.war_ties != cached_clan.war_ties:
1892+
self.dispatch('on_clan_war_tie_change', cached_clan.war_ties, clan.war_ties, clan)
1893+
if clan.war_losses != cached_clan.war_losses:
1894+
self.dispatch('on_clan_war_loss_change', cached_clan.war_losses, clan.war_losses, clan)
1895+
1896+
cache_search_clans.add(clan.tag, clan)
1897+
1898+
async def _update_clan_members(self, cached_clan, clan):
1899+
members = [n for n in clan.members if n != cached_clan.get_member(tag=n.tag)]
1900+
for m in members:
1901+
cached_member = cached_clan.get_member(tag=m.tag)
1902+
if not cached_member:
18991903
continue
19001904

1901-
self.dispatch('on_player_other_update', cached_player, player)
1905+
if m.name != cached_member.name:
1906+
self.dispatch('on_clan_member_name_change', cached_member.name, m.name, m, clan)
1907+
if m.donations != cached_member.donations:
1908+
self.dispatch('on_clan_member_donation', cached_member.donations, m.donations, m, clan)
1909+
if m.received != cached_member.received:
1910+
self.dispatch('on_clan_member_received', cached_member.received, m.received, m, clan)
1911+
if m.role != cached_member.role:
1912+
self.dispatch('on_clan_member_role_change', cached_member.role, m.role, m, clan)
1913+
if m.clan_rank != cached_member.clan_rank:
1914+
self.dispatch('on_clan_member_rank_change', cached_member.clan_rank, m.clan_rank, m, clan)
1915+
if m.level != cached_member.level:
1916+
self.dispatch('on_clan_member_level_change', cached_member.level, m.level, m, clan)
19021917

19031918

19041919
EventsClient.__doc__ = Client.__doc__

0 commit comments

Comments
 (0)