Skip to content

Releases: mathsman5133/coc.py

v1.1.0

16 Feb 06:26

Choose a tag to compare

  • Adds support for the new Player API verification endpoint - see :meth:Client.verify_player_token

  • Fixes a bug where members in clan.get_detailed_members() wouldn't have the clan_rank attribute, for example::

    before

    async for member in clan.get_detailed_members():
    print(member.clan_rank) # prints "None"

    after

    async for member in clan.get_detailed_members():
    print(member.clan_rank) # prints "1" or "10" or their clan rank.

  • Fixes a bug where getting the warlog failed for clans with (>3yr) old war logs. See #72

  • Fixed docs for :attr:Player.clan_previous_rank since it was misleading before.

v1.0.4

10 Dec 09:19
6214d1a

Choose a tag to compare

v1.0.4
Support aiohttp v3.7
Add retry handling to the HTTPClient - if a request fails with a GatewayError (or TimeoutError), it will sleep and then retry for a maximum of 5 times.
Super Minion, Super Wizard, Ice Hound, Log Launcher and Invisibility Spells were added.

v1.0.3

27 Oct 01:08

Choose a tag to compare

v1.0.3

  • Fixed an issue where the HTTP cache layer was not being utilised.

  • Fixed an issue where :meth:utils.get_season_start and :meth:utils.get_season_end got the previous season information
    if the system time had not yet passed 5am UTC.

v1.0.2

20 Oct 06:36

Choose a tag to compare

v1.0.2

  • Fixed an issue where hitting Maintenance errors when using the normal Client would raise an Attribute Error.

  • Fixed an issue where using Clan.get_member without calling Clan.members would build an incorrect player lookup dict.

  • Fixed an issue where events wouldn't start because the maintenance event wasn't set properly.

v1.0.1

13 Oct 06:55

Choose a tag to compare

v1.0.1

  • Maintenance event poller logic has been reworked to enable the use of :class:EventsClient without any player/clan/war
    updates.

  • 5min preparation time has been included in the list of valid prep times for friendly wars.

  • The warlog example has been updated to properly close the client, and a typo fixed in the README example.

  • The correct_tags parameter has been changed to default to True. There is no side-effects of having this enabled.

v1.0

08 Oct 08:25

Choose a tag to compare

Migrating to coc.py v1.0

v1.0 is a complete rewrite of the library, from top to bottom, and no effort was made to maintain backwards compatibility.

Most notably, all models have been rewritten and the :class:EventsClient has undergone a significant refactor.

All exceptions and iterators remain the same, and :class:Client methods remain similar.

Clans

The naming of clan objects has been changed to align with the API naming, and to improve understand of what each model represents and where it may come from.

For example, previously, coc.BasicClan was an abstract name to describe a clan with limit information, belonging to a player, as returned in the :meth:Client.get_player method.
It has been renamed to :class:coc.PlayerClan.

+--------------------+-------------------------+
| Before | After |
+--------------------+-------------------------+
| coc.Clan | :class:coc.BaseClan |
+--------------------+-------------------------+
| coc.BasicClan | :class:coc.PlayerClan |
+--------------------+-------------------------+
| coc.SearchClan | :class:coc.Clan |
+--------------------+-------------------------+

Additionally, :class:RankedClan was added.
This is returned when the :meth:Client.get_location_clans or :meth:Client.get_location_clans_versus are called.
Also, :class:ClanWarLeagueClan was added, which represents a CWL clan retrieved in the :meth:Client.get_league_group method.

Properties and Methods


+--------------------------+----------------------------+
|        Before            |         After              |
+--------------------------+----------------------------+
| ``Clan.iterlabels``      | :attr:`Clan.labels`        |
+--------------------------+----------------------------+
| ``Clan.itermembers``     | :attr:`Clan.members`       |
+--------------------------+----------------------------+
| ``Clan.members_dict``    | Removed                    |
+--------------------------+----------------------------+
| ``Clan.get_member``      | :meth:`Clan.get_member_by` |
+--------------------------+----------------------------+
| Didn't exist             | :meth:`Clan.get_member`    |
+--------------------------+----------------------------+
| ``WarClan.itermembers``  | :attr:`Clan.members`       |
+--------------------------+----------------------------+
| ``WarClan.iterattacks``  | :attr:`WarClan.attacks`    |
+--------------------------+----------------------------+
| ``WarClan.iterdefenses`` | :attr:`WarClan.defenses`   |
+--------------------------+----------------------------+

A quick explanation and example of the uses of :meth:`Clan.get_member` and :meth:`Clan.get_member_by`:

The previous :meth:`Clan.get_member` has been *renamed* to :meth:`Clan.get_member_by`.

A *new* method, :meth:`Clan.get_member` has been introduced. It provides a way to get a member (by tag) that is
*significantly* faster than :meth:`Clan.get_member`.

The below is a slimmed down version of how each function work. This **is not** a working example, however it highlights
the use and efficiency of :meth:`Clan.get_member` vs :meth:`Clan.get_member_by`

.. code-block:: python3

    def get_member(self, tag):
        try:
            return self._members[tag]  # fast dict lookup
        except KeyError:
            return None

    def get_member_by(self, **attrs):
        for member in self.members:
            # slow because it potentially has to iterate over every member before finding the correct one
            if all(getattr(member, k) == v for k, v in attrs):
                return member


A quick example about the use of :meth:`Clan.get_member` and :meth:`Clan.get_member_by`:

.. code-block:: python3

    # before
    member = clan.get_member(name="Bob the Builder")
    member = clan.get_member(tag="#P02VLYC")

    # after
    member = clan.get_member_by(name="Bob the Builder")
    member = clan.get_member("#P02VLYC")

This change vastly improves the efficiency of :meth:`Clan.get_member`.

Clans now have a ``__eq__`` comparison that is based on their tag. For example:

.. code-block:: python3

    # before
    player = await client.get_player('#P02VLYC')
    clan = await client.get_clan(player.clan.tag)
    assert player.clan == clan  # False

    # after
    player = await client.get_player('#P02VLYC')
    clan = await client.get_clan(player.clan.tag)
    assert player.clan == clan  # True


Players
--------
As with clans, the naming of player classes have also changed to align with API naming and improve readability of what an object contains.

+----------------------+----------------------------+
|      Before          |        After               |
+----------------------+----------------------------+
| ``coc.Player``       | :class:`coc.BasePlayer`    |
+----------------------+----------------------------+
| ``coc.BasicPlayer``  | :class:`coc.ClanMember`    |
+----------------------+----------------------------+
| ``coc.WarMember``    | :class:`coc.ClanWarMember` |
+----------------------+----------------------------+
| ``coc.SearchPlayer`` | :class:`coc.Player`        |
+----------------------+----------------------------+

Additionally, :class:`RankedPlayer` was added. This is returned when the :meth:`Client.get_location_players` or :meth:`Client.get_location_players_versus` are called.

Properties and Methods

+-------------------------------------------+----------------------------------+
| Before | After |
+-------------------------------------------+----------------------------------+
| WarMember.iterattacks | :attr:ClanWarMember.attacks |
+-------------------------------------------+----------------------------------+
| WarMember.iterdefenses | :attr:ClanWarMember.defenses |
+-------------------------------------------+----------------------------------+
| SearchPlayer.iterachievements | :attr:Player.achievements |
+-------------------------------------------+----------------------------------+
| SearchPlayer.iterlabels | :attr:Player.labels |
+-------------------------------------------+----------------------------------+
| SearchPlayer.ordered_builder_troops | :attr:Player.builder_troops |
+-------------------------------------------+----------------------------------+
| SearchPlayer.ordered_heroes | :attr:Player.heroes |
+-------------------------------------------+----------------------------------+
| SearchPlayer.ordered_home_troops | :attr:Player.home_troops |
+-------------------------------------------+----------------------------------+
| SearchPlayer.ordered_siege_machines | :attr:Player.siege_machines |
+-------------------------------------------+----------------------------------+
| SearchPlayer.ordered_spells | :attr:Player.spells |
+-------------------------------------------+----------------------------------+
| SearchPlayer.achievements_dict | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.builder_troops_dict | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.get_ordered_troops() | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.heroes_dict | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.home_troops_dict | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.ordered_super_troops | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.siege_machines_dict | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.spells_dict | Removed |
+-------------------------------------------+----------------------------------+
| SearchPlayer.super_troops_dict | Removed |
+-------------------------------------------+----------------------------------+
| Didn't exist | :meth:Player.get_hero |
+-------------------------------------------+----------------------------------+
| Didn't exist | :meth:Player.get_achievement |
+-------------------------------------------+----------------------------------+
| Didn't exist | :meth:Player.legend_statistics |
+-------------------------------------------+----------------------------------+

You will notice that a number of _dict and ordered_ attributes were removed.
All properties returning troops and spells are now ordered, apart from :attr:Player.troops.
This is due to the baby dragon being in both home and builder troops, making it difficult to sort these troops,
at the expense of a less efficient property it has been decided to not order these.
Please use :attr:Player.home_troops or :attr:Player.builder_troops instead.

In addition, all properties return lists of their object (achievements, troops, spells, etc.).
This change was made to improve consistency and fluidity. Objects that are commonly used with a lookup
(achievements and heroes) are now stored internally a...

Read more

v0.3.3

03 Jan 21:54

Choose a tag to compare

v0.3.3

Breaking Changes

- ``SearchPlayer.versus_attacks_wins`` has been renamed to ``SearchPlayer.versus_attack_wins``.
- The ``on_player_versus_attacks_change`` event has been renamed to ``on_player_versus_attack_change`` to match the above change.
- There was a typo with the spelling of the ``coc.Maintenance`` exception. It has been renamed from ``coc.Maitenance`` to ``coc.Maintenance``.

New Things
~~~~~~~~~~~
- Add a default `Unranked` league to ``BasicPlayer.league``.
- Added TH13 content.

BugFixes
~~~~~~~~~
- Fixed ``client.get_members`` raising ``AttributeError`` if no clan is found in the cache.
- ``client.get_warlog`` was only returning league wars. This has been fixed.

v0.3.1

26 Nov 03:37

Choose a tag to compare

v0.3.1

New Features.

- :ref:`on_clan_member_trophy_change`, :ref:`on_clan_member_versus_trophy_change` and
  :ref:`on_clan_member_league_change` were added as new events.
- Add ability to pass async and other iterables into methods that return iterators.
- Add the `HogGlider` to list of builder base troops.
- Added support for `SearchClan.labels` and `SearchPlayer.labels`. They will return a :class:`~coc.Label` object.
- Add a special parameter to `Client` to automatically "fix" or call `utils.correct_tag` on any tags passed in to calls.
- `Client.get_clan_labels()` and `Client.get_player_labels()` are now valid client calls.

BugFixes
~~~~~~~~~~~~
- Getting clans and players for a location will now default to getting for the global leaderboard.
- `LeagueWar` will no longer throw an `AttributeError` when no clan is found.
- Never update the cache automatically when the `EventsClient` is used.
- Fixed :ref:`on_war_state_change` not firing properly when a clan entered `preparation` or `warEnded`.

v0.3.0

22 Aug 09:51

Choose a tag to compare

v0.3.0

Bug Fixes

- All iterators have been fixed in python 3.7
- :ref:`on_clan_member_join` will now fire events correctly
- Properly parse HTML errors thrown by CloudFlare
- Accessing the ``League.badge`` attribute has been fixed
- Clan events now sleep for the correct interval
- ``WarMember.town_hall`` has been fixed
- The API used to fetch IP has been changed (##19) to https://api.ipify.org/
- Ensure the clan is in war before trying to find prep time (##21)

New Things
  • Check out the Cache tab in sidebar for a how-to work with the new cache. It still works out of the box!

  • You can now call utils with coc.utils.X

  • All events now have callbacks as an extra layer of security to stop them from failing.

  • New Properties: Clan.share_link and Player.share_link.

  • Add utils.maybe_sort() as an easy tool to sort clan war attacks.

  • All attributes that were prefaced with a _ to dictate being iterables have been changed to be prefixed
    with iter, ie. _attacks becomes iterattacks.

  • Rename SearchPlayer.level to SearchPlayer.exp_level - keep in line with API naming.

  • Default value can be passed to BasicPlayer.league; defaults to None

  • Default value for SearchPlayer.builder_hall is 0.

  • New Error: PrivateWarLog:

    • Subclass of Forbidden and a special case for when a 403 is thrown from trying to access war info for a clan with a private war log.

    • Redirect all Forbidden thrown errors in get_WARS methods to throw PrivateWarLog

    • A valid operation is to do either:

.. code-block:: python3

try:
    await coc.get_current_war(...)
except coc.Forbidden:
    pass

# or:

try:
    await coc.get_current_war(...)
except coc.PrivateWarLog:
    pass
  • EventsClient.add_X_update now accepts either a string or iterable.

  • New Method: client.remove_events() which works in the same way as client.add_events()

  • Speed up utils.get

  • New Events:

    • :ref:on_player_clan_join - when a player joins a clan
    • :ref:on_player_clan_leave - when a player leaves a clan
    • :ref:on_player_clan_level_change - when a player's clan's level changes
    • :ref:on_player_clan_badge_change - when a player's clan's badges change.
    • on_client_close which is dispatched upon closing the client
  • Rename x_achievement_update --> x_achievement_change for consistency

  • Add localised_name and localised_short_name attributes to :class:League and :class:Location

    • These have no effect at present.

Documentation

- Lots of the docs have had tidy-ups, with 2 new how-to's dedicated to Cache and the Events Client.

v0.2.1

19 Jun 01:05

Choose a tag to compare

BugFix