diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..8ec19e4 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,24 @@ +name: doc generation +on: + push: + branches: + - master +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v3 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: pip install -r requirements-docs.txt + - run: mkdocs gh-deploy --force diff --git a/LICENSE b/LICENSE index 0645398..f3ab63b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 PyClasher +Copyright (c) 2023 - Present 201st-Luka Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc_gen.py b/doc_gen.py new file mode 100644 index 0000000..a3999b8 --- /dev/null +++ b/doc_gen.py @@ -0,0 +1,54 @@ +import os +import shutil + + +def get_project_dir() -> str: + return "/" + os.getcwd().strip("docs/doc_autogen.py") + + +def create_markdown_structure(package_path, output_path): + """ + Create a directory structure mirroring the Python package structure, with + markdown files containing '::: pyclasher.path.filename' for each module. + + Args: + package_path (str): The path to the Python package. + output_path (str): The path where the directory structure and markdown files will be generated. + """ + for dirpath, dirnames, filenames in os.walk(package_path): + relative_dir = os.path.relpath(dirpath, package_path) + output_dir = os.path.join(output_path, relative_dir) + os.makedirs(output_dir, exist_ok=True) + + for filename in filenames: + if filename.endswith('.py') and filename != "__init__.py": + module_name = os.path.splitext(filename)[0] + import_path = ( + "pyclasher." + + os.path.join(relative_dir if relative_dir != '.' + else '', + module_name) + ).replace('/', '.') + markdown_content = f"::: {import_path}\n" + + markdown_file_path = os.path.join(output_dir, + f"{module_name}.md") + + with open(markdown_file_path, 'w') as markdown_file: + print(f"Creating docs for {import_path}") + markdown_file.write(markdown_content) + + +if __name__ == '__main__': + project_dir = get_project_dir() + + doc_dir = os.path.join(project_dir, "docs") + + api_ref_dir = os.path.join(doc_dir, "docs/API Reference") + pyclasher_dir = os.path.join(project_dir, "pyclasher") + + shutil.rmtree(api_ref_dir) + + os.mkdir(api_ref_dir) + + create_markdown_structure(pyclasher_dir, api_ref_dir) diff --git a/docs/API Reference/api/bulk_requests/abc.md b/docs/API Reference/api/bulk_requests/abc.md new file mode 100644 index 0000000..ae4edf1 --- /dev/null +++ b/docs/API Reference/api/bulk_requests/abc.md @@ -0,0 +1 @@ +::: pyclasher.api.bulk_requests.abc diff --git a/docs/API Reference/api/bulk_requests/b_player.md b/docs/API Reference/api/bulk_requests/b_player.md new file mode 100644 index 0000000..c15e3c2 --- /dev/null +++ b/docs/API Reference/api/bulk_requests/b_player.md @@ -0,0 +1 @@ +::: pyclasher.api.bulk_requests.b_player diff --git a/docs/API Reference/api/models/abc.md b/docs/API Reference/api/models/abc.md new file mode 100644 index 0000000..0098378 --- /dev/null +++ b/docs/API Reference/api/models/abc.md @@ -0,0 +1 @@ +::: pyclasher.api.models.abc diff --git a/docs/API Reference/api/models/base_models.md b/docs/API Reference/api/models/base_models.md new file mode 100644 index 0000000..6e2453e --- /dev/null +++ b/docs/API Reference/api/models/base_models.md @@ -0,0 +1 @@ +::: pyclasher.api.models.base_models diff --git a/docs/API Reference/api/models/clan.md b/docs/API Reference/api/models/clan.md new file mode 100644 index 0000000..3f78cc4 --- /dev/null +++ b/docs/API Reference/api/models/clan.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan diff --git a/docs/API Reference/api/models/clan_builder_base_ranking_list.md b/docs/API Reference/api/models/clan_builder_base_ranking_list.md new file mode 100644 index 0000000..ad5a01c --- /dev/null +++ b/docs/API Reference/api/models/clan_builder_base_ranking_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_builder_base_ranking_list diff --git a/docs/API Reference/api/models/clan_capital_raid_seasons.md b/docs/API Reference/api/models/clan_capital_raid_seasons.md new file mode 100644 index 0000000..f2ea2c8 --- /dev/null +++ b/docs/API Reference/api/models/clan_capital_raid_seasons.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_capital_raid_seasons diff --git a/docs/API Reference/api/models/clan_capital_ranking_list.md b/docs/API Reference/api/models/clan_capital_ranking_list.md new file mode 100644 index 0000000..40b39a6 --- /dev/null +++ b/docs/API Reference/api/models/clan_capital_ranking_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_capital_ranking_list diff --git a/docs/API Reference/api/models/clan_list.md b/docs/API Reference/api/models/clan_list.md new file mode 100644 index 0000000..a82802e --- /dev/null +++ b/docs/API Reference/api/models/clan_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_list diff --git a/docs/API Reference/api/models/clan_member.md b/docs/API Reference/api/models/clan_member.md new file mode 100644 index 0000000..0bd35b8 --- /dev/null +++ b/docs/API Reference/api/models/clan_member.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_member diff --git a/docs/API Reference/api/models/clan_member_list.md b/docs/API Reference/api/models/clan_member_list.md new file mode 100644 index 0000000..3c13b91 --- /dev/null +++ b/docs/API Reference/api/models/clan_member_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_member_list diff --git a/docs/API Reference/api/models/clan_ranking_list.md b/docs/API Reference/api/models/clan_ranking_list.md new file mode 100644 index 0000000..a65dd23 --- /dev/null +++ b/docs/API Reference/api/models/clan_ranking_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_ranking_list diff --git a/docs/API Reference/api/models/clan_war.md b/docs/API Reference/api/models/clan_war.md new file mode 100644 index 0000000..674e246 --- /dev/null +++ b/docs/API Reference/api/models/clan_war.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_war diff --git a/docs/API Reference/api/models/clan_war_league_group.md b/docs/API Reference/api/models/clan_war_league_group.md new file mode 100644 index 0000000..8c367fc --- /dev/null +++ b/docs/API Reference/api/models/clan_war_league_group.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_war_league_group diff --git a/docs/API Reference/api/models/clan_war_log.md b/docs/API Reference/api/models/clan_war_log.md new file mode 100644 index 0000000..f71bfa6 --- /dev/null +++ b/docs/API Reference/api/models/clan_war_log.md @@ -0,0 +1 @@ +::: pyclasher.api.models.clan_war_log diff --git a/docs/API Reference/api/models/enums.md b/docs/API Reference/api/models/enums.md new file mode 100644 index 0000000..e716d50 --- /dev/null +++ b/docs/API Reference/api/models/enums.md @@ -0,0 +1 @@ +::: pyclasher.api.models.enums diff --git a/docs/API Reference/api/models/gold_pass_season.md b/docs/API Reference/api/models/gold_pass_season.md new file mode 100644 index 0000000..3fed304 --- /dev/null +++ b/docs/API Reference/api/models/gold_pass_season.md @@ -0,0 +1 @@ +::: pyclasher.api.models.gold_pass_season diff --git a/docs/API Reference/api/models/labels.md b/docs/API Reference/api/models/labels.md new file mode 100644 index 0000000..394fbd0 --- /dev/null +++ b/docs/API Reference/api/models/labels.md @@ -0,0 +1 @@ +::: pyclasher.api.models.labels diff --git a/docs/API Reference/api/models/language.md b/docs/API Reference/api/models/language.md new file mode 100644 index 0000000..ca54662 --- /dev/null +++ b/docs/API Reference/api/models/language.md @@ -0,0 +1 @@ +::: pyclasher.api.models.language diff --git a/docs/API Reference/api/models/leagues.md b/docs/API Reference/api/models/leagues.md new file mode 100644 index 0000000..63fab04 --- /dev/null +++ b/docs/API Reference/api/models/leagues.md @@ -0,0 +1 @@ +::: pyclasher.api.models.leagues diff --git a/docs/API Reference/api/models/location.md b/docs/API Reference/api/models/location.md new file mode 100644 index 0000000..28c2854 --- /dev/null +++ b/docs/API Reference/api/models/location.md @@ -0,0 +1 @@ +::: pyclasher.api.models.location diff --git a/docs/API Reference/api/models/login/login_models.md b/docs/API Reference/api/models/login/login_models.md new file mode 100644 index 0000000..bd24ccc --- /dev/null +++ b/docs/API Reference/api/models/login/login_models.md @@ -0,0 +1 @@ +::: pyclasher.api.models.login.login_models diff --git a/docs/API Reference/api/models/misc/api.md b/docs/API Reference/api/models/misc/api.md new file mode 100644 index 0000000..0989ad9 --- /dev/null +++ b/docs/API Reference/api/models/misc/api.md @@ -0,0 +1 @@ +::: pyclasher.api.models.misc.api diff --git a/docs/API Reference/api/models/misc/posts.md b/docs/API Reference/api/models/misc/posts.md new file mode 100644 index 0000000..8eba707 --- /dev/null +++ b/docs/API Reference/api/models/misc/posts.md @@ -0,0 +1 @@ +::: pyclasher.api.models.misc.posts diff --git a/docs/API Reference/api/models/misc/responses.md b/docs/API Reference/api/models/misc/responses.md new file mode 100644 index 0000000..678f196 --- /dev/null +++ b/docs/API Reference/api/models/misc/responses.md @@ -0,0 +1 @@ +::: pyclasher.api.models.misc.responses diff --git a/docs/API Reference/api/models/misc/war_status.md b/docs/API Reference/api/models/misc/war_status.md new file mode 100644 index 0000000..969afeb --- /dev/null +++ b/docs/API Reference/api/models/misc/war_status.md @@ -0,0 +1 @@ +::: pyclasher.api.models.misc.war_status diff --git a/docs/API Reference/api/models/player.md b/docs/API Reference/api/models/player.md new file mode 100644 index 0000000..0a9b3da --- /dev/null +++ b/docs/API Reference/api/models/player.md @@ -0,0 +1 @@ +::: pyclasher.api.models.player diff --git a/docs/API Reference/api/models/player_builder_base_ranking_list.md b/docs/API Reference/api/models/player_builder_base_ranking_list.md new file mode 100644 index 0000000..88a0749 --- /dev/null +++ b/docs/API Reference/api/models/player_builder_base_ranking_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.player_builder_base_ranking_list diff --git a/docs/API Reference/api/models/player_house.md b/docs/API Reference/api/models/player_house.md new file mode 100644 index 0000000..e177beb --- /dev/null +++ b/docs/API Reference/api/models/player_house.md @@ -0,0 +1 @@ +::: pyclasher.api.models.player_house diff --git a/docs/API Reference/api/models/player_ranking_clan.md b/docs/API Reference/api/models/player_ranking_clan.md new file mode 100644 index 0000000..fa160a3 --- /dev/null +++ b/docs/API Reference/api/models/player_ranking_clan.md @@ -0,0 +1 @@ +::: pyclasher.api.models.player_ranking_clan diff --git a/docs/API Reference/api/models/player_ranking_list.md b/docs/API Reference/api/models/player_ranking_list.md new file mode 100644 index 0000000..d339ef9 --- /dev/null +++ b/docs/API Reference/api/models/player_ranking_list.md @@ -0,0 +1 @@ +::: pyclasher.api.models.player_ranking_list diff --git a/docs/API Reference/api/models/season.md b/docs/API Reference/api/models/season.md new file mode 100644 index 0000000..0ddf811 --- /dev/null +++ b/docs/API Reference/api/models/season.md @@ -0,0 +1 @@ +::: pyclasher.api.models.season diff --git a/docs/API Reference/api/models/war_clan.md b/docs/API Reference/api/models/war_clan.md new file mode 100644 index 0000000..70f8e9c --- /dev/null +++ b/docs/API Reference/api/models/war_clan.md @@ -0,0 +1 @@ +::: pyclasher.api.models.war_clan diff --git a/docs/API Reference/api/requests/abc.md b/docs/API Reference/api/requests/abc.md new file mode 100644 index 0000000..414a1f2 --- /dev/null +++ b/docs/API Reference/api/requests/abc.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.abc diff --git a/docs/API Reference/api/requests/builder_base_league.md b/docs/API Reference/api/requests/builder_base_league.md new file mode 100644 index 0000000..cbbcca2 --- /dev/null +++ b/docs/API Reference/api/requests/builder_base_league.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.builder_base_league diff --git a/docs/API Reference/api/requests/builder_base_leagues.md b/docs/API Reference/api/requests/builder_base_leagues.md new file mode 100644 index 0000000..ab92cd7 --- /dev/null +++ b/docs/API Reference/api/requests/builder_base_leagues.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.builder_base_leagues diff --git a/docs/API Reference/api/requests/capital_league.md b/docs/API Reference/api/requests/capital_league.md new file mode 100644 index 0000000..1e05e4b --- /dev/null +++ b/docs/API Reference/api/requests/capital_league.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.capital_league diff --git a/docs/API Reference/api/requests/capital_league_seasons.md b/docs/API Reference/api/requests/capital_league_seasons.md new file mode 100644 index 0000000..6fdded6 --- /dev/null +++ b/docs/API Reference/api/requests/capital_league_seasons.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.capital_league_seasons diff --git a/docs/API Reference/api/requests/capital_rankings.md b/docs/API Reference/api/requests/capital_rankings.md new file mode 100644 index 0000000..09c1a30 --- /dev/null +++ b/docs/API Reference/api/requests/capital_rankings.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.capital_rankings diff --git a/docs/API Reference/api/requests/clan.md b/docs/API Reference/api/requests/clan.md new file mode 100644 index 0000000..0aa5b4f --- /dev/null +++ b/docs/API Reference/api/requests/clan.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan diff --git a/docs/API Reference/api/requests/clan_builder_base_rankings.md b/docs/API Reference/api/requests/clan_builder_base_rankings.md new file mode 100644 index 0000000..ebbc161 --- /dev/null +++ b/docs/API Reference/api/requests/clan_builder_base_rankings.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_builder_base_rankings diff --git a/docs/API Reference/api/requests/clan_capital_raid_seasons.md b/docs/API Reference/api/requests/clan_capital_raid_seasons.md new file mode 100644 index 0000000..cf303e4 --- /dev/null +++ b/docs/API Reference/api/requests/clan_capital_raid_seasons.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_capital_raid_seasons diff --git a/docs/API Reference/api/requests/clan_current_war.md b/docs/API Reference/api/requests/clan_current_war.md new file mode 100644 index 0000000..a8eacf9 --- /dev/null +++ b/docs/API Reference/api/requests/clan_current_war.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_current_war diff --git a/docs/API Reference/api/requests/clan_currentwar_leaguegroup.md b/docs/API Reference/api/requests/clan_currentwar_leaguegroup.md new file mode 100644 index 0000000..c031cc6 --- /dev/null +++ b/docs/API Reference/api/requests/clan_currentwar_leaguegroup.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_currentwar_leaguegroup diff --git a/docs/API Reference/api/requests/clan_labels.md b/docs/API Reference/api/requests/clan_labels.md new file mode 100644 index 0000000..9f7f668 --- /dev/null +++ b/docs/API Reference/api/requests/clan_labels.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_labels diff --git a/docs/API Reference/api/requests/clan_members.md b/docs/API Reference/api/requests/clan_members.md new file mode 100644 index 0000000..9fa27a7 --- /dev/null +++ b/docs/API Reference/api/requests/clan_members.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_members diff --git a/docs/API Reference/api/requests/clan_rankings.md b/docs/API Reference/api/requests/clan_rankings.md new file mode 100644 index 0000000..c4eed36 --- /dev/null +++ b/docs/API Reference/api/requests/clan_rankings.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_rankings diff --git a/docs/API Reference/api/requests/clan_search.md b/docs/API Reference/api/requests/clan_search.md new file mode 100644 index 0000000..744cede --- /dev/null +++ b/docs/API Reference/api/requests/clan_search.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_search diff --git a/docs/API Reference/api/requests/clan_war_log.md b/docs/API Reference/api/requests/clan_war_log.md new file mode 100644 index 0000000..0838aa7 --- /dev/null +++ b/docs/API Reference/api/requests/clan_war_log.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_war_log diff --git a/docs/API Reference/api/requests/clan_warleagues_wars.md b/docs/API Reference/api/requests/clan_warleagues_wars.md new file mode 100644 index 0000000..70694ee --- /dev/null +++ b/docs/API Reference/api/requests/clan_warleagues_wars.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.clan_warleagues_wars diff --git a/docs/API Reference/api/requests/gold_pass.md b/docs/API Reference/api/requests/gold_pass.md new file mode 100644 index 0000000..ce1a6a2 --- /dev/null +++ b/docs/API Reference/api/requests/gold_pass.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.gold_pass diff --git a/docs/API Reference/api/requests/league.md b/docs/API Reference/api/requests/league.md new file mode 100644 index 0000000..394f309 --- /dev/null +++ b/docs/API Reference/api/requests/league.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.league diff --git a/docs/API Reference/api/requests/league_season.md b/docs/API Reference/api/requests/league_season.md new file mode 100644 index 0000000..1951ad7 --- /dev/null +++ b/docs/API Reference/api/requests/league_season.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.league_season diff --git a/docs/API Reference/api/requests/league_seasons.md b/docs/API Reference/api/requests/league_seasons.md new file mode 100644 index 0000000..8397a2b --- /dev/null +++ b/docs/API Reference/api/requests/league_seasons.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.league_seasons diff --git a/docs/API Reference/api/requests/leagues.md b/docs/API Reference/api/requests/leagues.md new file mode 100644 index 0000000..65fba5c --- /dev/null +++ b/docs/API Reference/api/requests/leagues.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.leagues diff --git a/docs/API Reference/api/requests/location.md b/docs/API Reference/api/requests/location.md new file mode 100644 index 0000000..8f4c96f --- /dev/null +++ b/docs/API Reference/api/requests/location.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.location diff --git a/docs/API Reference/api/requests/locations.md b/docs/API Reference/api/requests/locations.md new file mode 100644 index 0000000..1cb0d0d --- /dev/null +++ b/docs/API Reference/api/requests/locations.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.locations diff --git a/docs/API Reference/api/requests/player.md b/docs/API Reference/api/requests/player.md new file mode 100644 index 0000000..575e1fa --- /dev/null +++ b/docs/API Reference/api/requests/player.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.player diff --git a/docs/API Reference/api/requests/player_builder_base_rankings.md b/docs/API Reference/api/requests/player_builder_base_rankings.md new file mode 100644 index 0000000..188a810 --- /dev/null +++ b/docs/API Reference/api/requests/player_builder_base_rankings.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.player_builder_base_rankings diff --git a/docs/API Reference/api/requests/player_labels.md b/docs/API Reference/api/requests/player_labels.md new file mode 100644 index 0000000..ecfd468 --- /dev/null +++ b/docs/API Reference/api/requests/player_labels.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.player_labels diff --git a/docs/API Reference/api/requests/player_rankings.md b/docs/API Reference/api/requests/player_rankings.md new file mode 100644 index 0000000..6a06df0 --- /dev/null +++ b/docs/API Reference/api/requests/player_rankings.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.player_rankings diff --git a/docs/API Reference/api/requests/war_league.md b/docs/API Reference/api/requests/war_league.md new file mode 100644 index 0000000..6f7ed04 --- /dev/null +++ b/docs/API Reference/api/requests/war_league.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.war_league diff --git a/docs/API Reference/api/requests/war_leagues.md b/docs/API Reference/api/requests/war_leagues.md new file mode 100644 index 0000000..75ad06b --- /dev/null +++ b/docs/API Reference/api/requests/war_leagues.md @@ -0,0 +1 @@ +::: pyclasher.api.requests.war_leagues diff --git a/docs/API Reference/client/client.md b/docs/API Reference/client/client.md new file mode 100644 index 0000000..fa3d3bb --- /dev/null +++ b/docs/API Reference/client/client.md @@ -0,0 +1 @@ +::: pyclasher.client.client diff --git a/docs/API Reference/client/request_consumer.md b/docs/API Reference/client/request_consumer.md new file mode 100644 index 0000000..0534b04 --- /dev/null +++ b/docs/API Reference/client/request_consumer.md @@ -0,0 +1 @@ +::: pyclasher.client.request_consumer diff --git a/docs/API Reference/client/request_queue.md b/docs/API Reference/client/request_queue.md new file mode 100644 index 0000000..fccacc8 --- /dev/null +++ b/docs/API Reference/client/request_queue.md @@ -0,0 +1 @@ +::: pyclasher.client.request_queue diff --git a/docs/API Reference/exceptions.md b/docs/API Reference/exceptions.md new file mode 100644 index 0000000..da88edd --- /dev/null +++ b/docs/API Reference/exceptions.md @@ -0,0 +1 @@ +::: pyclasher.exceptions diff --git a/docs/API Reference/utils/exectimer.md b/docs/API Reference/utils/exectimer.md new file mode 100644 index 0000000..1bb2129 --- /dev/null +++ b/docs/API Reference/utils/exectimer.md @@ -0,0 +1 @@ +::: pyclasher.utils.exectimer diff --git a/docs/API Reference/utils/functions.md b/docs/API Reference/utils/functions.md new file mode 100644 index 0000000..3dbb3b7 --- /dev/null +++ b/docs/API Reference/utils/functions.md @@ -0,0 +1 @@ +::: pyclasher.utils.functions diff --git a/docs/API Reference/utils/login.md b/docs/API Reference/utils/login.md new file mode 100644 index 0000000..8a3fa99 --- /dev/null +++ b/docs/API Reference/utils/login.md @@ -0,0 +1 @@ +::: pyclasher.utils.login diff --git a/docs/API Reference/utils/request_methods.md b/docs/API Reference/utils/request_methods.md new file mode 100644 index 0000000..f894ba1 --- /dev/null +++ b/docs/API Reference/utils/request_methods.md @@ -0,0 +1 @@ +::: pyclasher.utils.request_methods diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..bfee35c --- /dev/null +++ b/docs/index.md @@ -0,0 +1,42 @@ +[![Discord][discord_shield]][discord_url] ![Last commit][last_commit_shield] + +# PyClasher + +PyClasher is the name of the asynchronous ClashOfClans API. It is +an object-oriented wrapper client that provides easy access to the +requested data. + +--- +## Features +- Asynchronous and parallel requesting +- Possibility to use multiple tokens and to login via email address and + password of the ClashOfClans developer portal +- Control over the number of requests per second and the number of used tokens +- Open source +- Type hinted +- Supports Python 3.8 -> 3.11 + +--- + +## Installation + +It is possible to install the package from GitHib releases. You can use the +following command to add PyClasher to your library: +```bash +pip install git+https://github.com/201st-Luka/PyClasher.git@v1.0.0-alpha1 +``` + +--- + +## Disclaimer +This material is unofficial and is not endorsed by Supercell. For more +information see Supercell's Fan Content Policy: +www.supercell.com/fan-content-policy. + + + + +[discord_shield]: https://img.shields.io/badge/Discord-blue?logo=discord&logoColor=white +[discord_url]: https://discord.gg/j2PAF9Wru8 +[last_commit_shield]: https://img.shields.io/github/last-commit/201st-Luka/HeadhunterBot +[headhunterbot_url]: https://github.com/201st-Luka/HeadhunterBot diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..eabc871 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,71 @@ +site_name: PyClasher +site_url: https://201st-Luka.github.io/pyclasher/ +copyright: Copyright © Copyright (c) 2023 - Present 201st-Luka +repo_url: https://github.com/201st-Luka/PyClasher +repo_name: 201st-Luka/PyClasher +docs_dir: docs + +theme: + name: material + features: + - navigation.tabs + - navigation.tabs.sticky + - navigation.instant + - navigation.tracking + - navigation.path + - navigation.prune + - navigation.top + - search.suggest + - search.share + - search.highlight + - content.tabs.link + - content.code.annotation + - content.code.copy + language: en + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: indigo + accent: orange + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: indigo + accent: orange + toggle: + icon: material/brightness-3 + name: Switch to light mode + icon: fontawesome/brands/github + +plugins: + - search: + lang: en + - git-committers: + repository: 201st-Luka/PyClasher + branch: master + token: !!python/object/apply:os.getenv ["MKDOCS_GIT_COMMITTERS_APIKEY"] + - mkdocstrings: + enabled: true + custom_templates: templates + default_handler: python + handlers: + python: + options: + show_source: true + - awesome-pages + +extra: + version: + provider: mike + social: + - icon: fontawesome/brands/discord + link: https://discord.gg/j2PAF9Wru8 + name: Become part of the 201st Community + - icon: fontawesome/brands/github + link: https://github.com/201st-Luka/PyClasher + name: PyClasher on GitHub + +watch: + - pyclasher \ No newline at end of file diff --git a/pyclasher/__init__.py b/pyclasher/__init__.py index 71c6f7a..1a2f304 100644 --- a/pyclasher/__init__.py +++ b/pyclasher/__init__.py @@ -9,7 +9,7 @@ .. author:: 201st-Luka """ -__version__ = '1.0.0-alpha1' +__version__ = '1.0.0' from .api import * from .client import Client diff --git a/pyclasher/client/__init__.py b/pyclasher/client/__init__.py new file mode 100644 index 0000000..8aef758 --- /dev/null +++ b/pyclasher/client/__init__.py @@ -0,0 +1,13 @@ +""" +All client modules are in this package +""" + +from .client import Client +from .request_queue import PQueue +from .request_consumer import PConsumer + +__all__ = ( + "Client", + "PQueue", + "PConsumer" +) diff --git a/pyclasher/client.py b/pyclasher/client/client.py similarity index 62% rename from pyclasher/client.py rename to pyclasher/client/client.py index 8d72630..7832f06 100644 --- a/pyclasher/client.py +++ b/pyclasher/client/client.py @@ -3,41 +3,87 @@ from typing import Iterable from urllib.parse import urlparse -from .exceptions import (InvalidType, ClientIsRunning, ClientIsNotRunning, - NoneToken, MISSING, ClientAlreadyInitialised, - PyClasherException) -from .request_queue import PConsumer, PQueue -from .utils.login import Login +from pyclasher.exceptions import ( + InvalidType, + ClientIsRunning, + ClientIsNotRunning, + NoneToken, + MISSING, + ClientAlreadyInitialised, + PyClasherException +) +from .request_queue import PQueue +from .request_consumer import PConsumer + +from pyclasher.utils.login import Login + global_client_id = 0 +"""Global variable for counting and identifying clients""" class Client: + """ + ClashOfClans API client + + Attributes: + __instances: the instances of the client + base_url: the base URL for the requests (usually ``https://api.clashofclans.com``) + endpoint: the endpoint URL for the requests (usually ``/v1``) + requests_per_second: the number of requests done per consumer/token per second (usually 5) + logger: logger to log the requests, ... (usually MISSING) + queue: the request_queue where the requests are enqueued + __consumers: list of consumers of the request_queue and requests + __consume_tasks: list of tasks of the consumer + __temporary_session: boolean that indicates if the session is temporary or not + __tokens: list of tokens + __client_running: boolean that indicates if the client is running or not + """ + __instances = None + """List of Client instances or None""" base_url = "https://api.clashofclans.com" + """Base url for all requests""" endpoint = "/v1" + """Endpoint url for all requests""" requests_per_second = 5 + """Maximal number of requests that are executed per second""" logger = MISSING + """Logger that logs the requests""" + + def __new__(cls, *, tokens=None, **kwargs): + """ + Class method to create a new instance of the Client + + Args: + tokens (str | list[str] | None): the Bearer tokens for the authentication of the ClashOfClans API + **kwargs: other key word arguments - def __new__(cls, *args, **kwargs): + Notes: + This function checks if all initialised clients do not share a + token. If so the ecxeption ``ClientAlreadyInitialised`` is raised. + + Raises: + InvalidType + ClientAlreadyInitialised + """ if cls.__instances is None: cls.__instances = [super().__new__(cls)] return cls.__instances[0] - if 'tokens' in kwargs: - if isinstance(kwargs['tokens'], str): - tokens = [kwargs['tokens']] - elif isinstance(kwargs['tokens'], Iterable): - tokens = list(kwargs['tokens']) - else: - raise InvalidType(kwargs['tokens'], - (str, Iterable[str])) - for token in tokens: - for client in Client.__instances: - if client.__tokens is not None: - if token in client.__tokens: - raise ClientAlreadyInitialised - continue + if isinstance(tokens, str): + tokens = [tokens] + elif isinstance(tokens, Iterable): + tokens = list(tokens) + else: + raise InvalidType(tokens, + (str, Iterable[str])) + for token in tokens: + for client in Client.__instances: + if client.__tokens is not None: + if token in client.__tokens: + raise ClientAlreadyInitialised + continue cls.__instances.append(super().__new__(cls)) return cls.__instances[-1] @@ -50,6 +96,24 @@ def __init__( logger=MISSING, swagger_url=None ): + """ + initialisation method for the client + + Args: + tokens (str | list[str] | None): the Bearer tokens for the authentication of the ClashOfClans API + requests_per_second (int): This integer limits the number of requests done per second (per token). + This value is important to bypass the rate limit of the ClashOfClans API. + More tokens allow more requests per second because each token can do + as many requests per second as specified. + Defaults to 5. + logger (Logger): logger for detailed logging + Defaults to None + swagger_url (str): swagger url for requests + Defaults to None + Returns: + None + """ + global global_client_id if logger is None: @@ -101,7 +165,7 @@ async def from_login(cls, email, password, requests_per_second=5, logger.info("initialising client via login") - self = cls([login.temporary_api_token for login in logins], + self = cls(tokens=[login.temporary_api_token for login in logins], requests_per_second=requests_per_second, request_timeout=request_timeout, swagger_url=logins[0].swagger_url) diff --git a/pyclasher/client.pyi b/pyclasher/client/client.pyi similarity index 60% rename from pyclasher/client.pyi rename to pyclasher/client/client.pyi index e6a377e..d996575 100644 --- a/pyclasher/client.pyi +++ b/pyclasher/client/client.pyi @@ -1,7 +1,7 @@ from logging import Logger from typing import Iterable -from .exceptions import MISSING +from ..exceptions import MISSING from .request_queue import PQueue global_client_id: int = ... @@ -11,36 +11,31 @@ class Client: """ this is the class for the ClashOfClans API client - :cvar __instances: the private instance of the client - :type __instances: Client - :cvar base_url: the public base URL for the requests (usually https://api.clashofclans.com) - :type base_url: str - :cvar endpoint: the public endpoint URL for the requests (usually /v1) - :type endpoint: str - :cvar requests_per_second: the public number of requests done per consumer/token per second (usually 5) - :type requests_per_second: int - :cvar logger: public logger to log the requests, ... (usually MISSING) - :type logger: Logger - :ivar queue: the public request_queue where the requests are enqueued - :type queue: RequestQueue - :ivar __consumers: private list of consumers of the request_queue and requests - :type __consumers: list[Consumer] - :ivar __consume_tasks: private list of tasks of the consumer - :type __consume_tasks: list[Task] - :ivar __temporary_session: private boolean that indicates if the session is temporary or not - :type __temporary_session: bool - :ivar __tokens: private list of tokens - :type __tokens: list[str] - :ivar __client_running: private boolean that indicates if the client is running or not - :type __client_running: bool + Attributes: + __instances: the instances of the client + base_url: the base URL for the requests (usually https://api.clashofclans.com) + endpoint: the endpoint URL for the requests (usually /v1) + requests_per_second: the number of requests done per consumer/token per second (usually 5) + logger: logger to log the requests, ... (usually MISSING) + queue: the request_queue where the requests are enqueued + __consumers: list of consumers of the request_queue and requests + __consume_tasks: list of tasks of the consumer + __temporary_session: boolean that indicates if the session is temporary or not + __tokens: list of tokens + __client_running: boolean that indicates if the client is running or not """ __instances: list[Client] = None + """List of Client instances or None""" base_url: str = "https://api.clashofclans.com" + """Base url for all requests""" endpoint: str = "/v1" + """Endpoint url for all requests""" requests_per_second: int = 5 + """Maximal number of requests that are executed per second""" logger: Logger = MISSING + """Logger that logs the requests""" def __new__(cls, *args, **kwargs): ... @@ -56,22 +51,19 @@ class Client: """ initialisation method for the client - :param tokens: the Bearer tokens for the authentication of the ClashOfClans API - :type tokens: str | list[str] | None - :param requests_per_second: This integer limits the number of requests done per second (per token). - This value is important to bypass the rate limit of the ClashOfClans API. - More tokens allow more requests per second because each token can do - as many requests per second as specified. - Defaults to 5. - :type requests_per_second: int - :param logger: logger for detailed logging - Defaults to None - :type logger: Logger - :param swagger_url: swagger url for requests - Defaults to None - :type swagger_url: str - :return: None - :rtype: None + Args: + tokens (str | list[str] | None): the Bearer tokens for the authentication of the ClashOfClans API + requests_per_second (int=5): This integer limits the number of requests done per second (per token). + This value is important to bypass the rate limit of the ClashOfClans API. + More tokens allow more requests per second because each token can do + as many requests per second as specified. + Defaults to 5. + logger (Logger): logger for detailed logging + Defaults to None + swagger_url (str): swagger url for requests + Defaults to None + Returns: + None """ self.logger: Logger = ... self.__tokens: list[str] = ... diff --git a/pyclasher/request_queue/request_consumer.py b/pyclasher/client/request_consumer.py similarity index 85% rename from pyclasher/request_queue/request_consumer.py rename to pyclasher/client/request_consumer.py index 91228c0..b968444 100644 --- a/pyclasher/request_queue/request_consumer.py +++ b/pyclasher/client/request_consumer.py @@ -3,9 +3,9 @@ from aiohttp import ClientSession, ClientTimeout -from ..api.models import ClientError -from ..exceptions import ApiExceptions, MISSING, RequestTimeout -from ..utils import ExecutionTimer +from pyclasher.api.models import ClientError +from pyclasher.exceptions import ApiExceptions, MISSING, RequestTimeout +from pyclasher.utils import ExecutionTimer class PConsumer: @@ -49,6 +49,12 @@ async def _request(self, future, url, method, body, status, error): future.set_result(MISSING) status.set_result(None) error.set_result(RequestTimeout(self.timeout)) + except Exception as exception: + future.set_result(MISSING) + status.set_result(None) + error.set_result(exception) + raise exception + async def consume(self): while True: diff --git a/pyclasher/request_queue/request_consumer.pyi b/pyclasher/client/request_consumer.pyi similarity index 100% rename from pyclasher/request_queue/request_consumer.pyi rename to pyclasher/client/request_consumer.pyi diff --git a/pyclasher/request_queue/request_queue.py b/pyclasher/client/request_queue.py similarity index 100% rename from pyclasher/request_queue/request_queue.py rename to pyclasher/client/request_queue.py diff --git a/pyclasher/request_queue/request_queue.pyi b/pyclasher/client/request_queue.pyi similarity index 100% rename from pyclasher/request_queue/request_queue.pyi rename to pyclasher/client/request_queue.pyi diff --git a/pyclasher/exceptions.py b/pyclasher/exceptions.py index 0271374..d03933c 100644 --- a/pyclasher/exceptions.py +++ b/pyclasher/exceptions.py @@ -31,7 +31,7 @@ class ApiException(PyClasherException): def __init__(self, api_code, client_error=None, *args, **kwargs): self.api_code = api_code self.client_error = client_error - super.__init__(*args, **kwargs) + super().__init__(*args, **kwargs) return def __repr__(self): @@ -52,7 +52,7 @@ def __str__(self): class AccessDenied(ApiException): def __init__(self, client_error=None): - super().__init__(400, client_error) + super().__init__(403, client_error) return def __str__(self): @@ -63,7 +63,7 @@ def __str__(self): class NotFound(ApiException): def __init__(self, client_error=None): - super().__init__(400, client_error) + super().__init__(404, client_error) return def __str__(self): @@ -72,7 +72,7 @@ def __str__(self): class Throttled(ApiException): def __init__(self, client_error=None): - super().__init__(400, client_error) + super().__init__(429, client_error) return def __str__(self): @@ -82,7 +82,7 @@ def __str__(self): class UnknownApiException(ApiException): def __init__(self, client_error=None): - super().__init__(400, client_error) + super().__init__(500, client_error) return def __str__(self): @@ -91,7 +91,7 @@ def __str__(self): class Maintenance(ApiException): def __init__(self, client_error=None): - super().__init__(400, client_error) + super().__init__(503, client_error) return def __str__(self): @@ -99,21 +99,30 @@ def __str__(self): class ApiExceptions: - BadRequest = BadRequest - AccessDenied = AccessDenied - NotFound = NotFound - Throttled = Throttled - UnknownApiException = UnknownApiException - Maintenance = Maintenance + BadRequest = BadRequest() + AccessDenied = AccessDenied() + NotFound = NotFound() + Throttled = Throttled() + UnknownApiException = UnknownApiException() + Maintenance = Maintenance() @classmethod def from_api_code(cls, api_code, client_error=None): - for key, value in cls.__dict__.items(): - if value is ApiException: - if value().api_code == api_code: - return value(client_error) - raise PyClasherException(f"could not find {api_code} in the API " - f"exceptions") + if api_code == 400: + return BadRequest(client_error) + elif api_code == 403: + return AccessDenied(client_error) + elif api_code == 404: + return NotFound(client_error) + elif api_code == 429: + return Throttled(client_error) + elif api_code == 500: + return UnknownApiException(client_error) + elif api_code == 503: + return Maintenance(client_error) + else: + PyClasherException(f"could not find {api_code} in the API " + f"exceptions") class RequestNotDone(PyClasherException): diff --git a/pyclasher/request_queue/__init__.py b/pyclasher/request_queue/__init__.py deleted file mode 100644 index edebc14..0000000 --- a/pyclasher/request_queue/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .request_consumer import PConsumer -from .request_queue import PQueue diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..23d4344 --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,5 @@ +mkdocs +mkdocs-material +mkdocs-git-committers-plugin +mkdocstrings[python] +mkdocs-awesome-pages-plugin \ No newline at end of file diff --git a/tests/requests/test_clan.py b/tests/requests/test_clan.py index 5662443..a1fd621 100644 --- a/tests/requests/test_clan.py +++ b/tests/requests/test_clan.py @@ -4,8 +4,8 @@ ClanRequest, ClanMembersRequest, Missing, ClanCurrentWarRequest, ClanWarLogRequest, ClanSearchRequest, ClanCapitalRaidSeasonsRequest, ClanCurrentwarLeaguegroupRequest, - RequestNotDone, ClanWarleaguesWarsRequest, - MISSING + ClanWarleaguesWarsRequest, + MISSING, NotFound ) from pyclasher.api.models import ( ClanType, WarFrequency, BadgeUrls, WarLeague, CapitalLeague, Language, @@ -221,7 +221,7 @@ async def test_clan_currentwar_leaguegroup(event_loop, pyclasher_client): league_group = ClanCurrentwarLeaguegroupRequest(TEST_CLAN_TAG) await league_group.request("test_client") - except RequestNotDone: + except NotFound: pass else: assert isinstance(league_group.to_dict(), dict) @@ -239,7 +239,7 @@ async def test_clan_warleagues_wars(event_loop, pyclasher_client): league_group = ClanCurrentwarLeaguegroupRequest(TEST_CLAN_TAG) await league_group.request("test_client") - except RequestNotDone: + except NotFound: pass else: for league_round in league_group.rounds: