From 601a93ec31b8a2cc2d005ac334dfa7d7cd831579 Mon Sep 17 00:00:00 2001 From: DevRuby <60344644+dev-ruby@users.noreply.github.com> Date: Wed, 29 Mar 2023 09:06:00 +0900 Subject: [PATCH 1/4] Change major API sets - LICENSE: Update copyright year - TrackerGG/__init__.py: Update __init__.py - TrackerGG/client.py: Add `CSGOClient` class - TrackerGG/httpclient.py: Add `RequestMethod` Enum, `Route` Class, `ResponseData` Class, `HTTPClient` class - TrackerGG/Models Create Models package - TrackerGG/Models/csgo.py: Add `CSGOProfile` class - TrackerGG/Models/platform.py: Add `Platform` Enum, `PlatformInfo` Class - TrackerGG/Models/segment.py: Add `Stat` Class, `Segment` Class - TrackerGG/Models/user.py: Add `SocialAccount` Class, `UserInfo` class - TrackerGG/exceptions.py: Delete TrackerGG/exceptions.py - TrackerGG/info.py: Delete TrackerGG/info.py - TrackerGG/models.py: Delete TrackerGG/models.py --- LICENSE | 2 +- TrackerGG/{info.py => Models/__init__.py} | 9 +- TrackerGG/Models/csgo.py | 33 ++++ TrackerGG/Models/platform.py | 46 +++++ TrackerGG/Models/segment.py | 49 +++++ TrackerGG/Models/user.py | 49 +++++ TrackerGG/__init__.py | 19 +- TrackerGG/client.py | 49 +++++ TrackerGG/exceptions.py | 24 --- TrackerGG/httpclient.py | 122 ++++++++++++ TrackerGG/models.py | 230 ---------------------- 11 files changed, 357 insertions(+), 275 deletions(-) rename TrackerGG/{info.py => Models/__init__.py} (69%) create mode 100644 TrackerGG/Models/csgo.py create mode 100644 TrackerGG/Models/platform.py create mode 100644 TrackerGG/Models/segment.py create mode 100644 TrackerGG/Models/user.py create mode 100644 TrackerGG/client.py delete mode 100644 TrackerGG/exceptions.py create mode 100644 TrackerGG/httpclient.py delete mode 100644 TrackerGG/models.py diff --git a/LICENSE b/LICENSE index d050e56..6a5068d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 DevRuby +Copyright (c) 2023 DevRuby 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/TrackerGG/info.py b/TrackerGG/Models/__init__.py similarity index 69% rename from TrackerGG/info.py rename to TrackerGG/Models/__init__.py index 5b55b93..afd9573 100644 --- a/TrackerGG/info.py +++ b/TrackerGG/Models/__init__.py @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- """ -Copyright (c) 2021 DevRuby +Copyright (c) 2023 DevRuby MIT License THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR @@ -16,7 +16,4 @@ """ -__version__ = "1.0" -__author__ = "DevRuby" -__license__ = "MIT License" -__copyright__ = "(c) 2021 DevRuby" +from .csgo import CSGOProfile diff --git a/TrackerGG/Models/csgo.py b/TrackerGG/Models/csgo.py new file mode 100644 index 0000000..af75d93 --- /dev/null +++ b/TrackerGG/Models/csgo.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- + +""" +Copyright (c) 2023 DevRuby + +MIT License + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +""" +from typing import Dict, Any, List +from .platform import PlatformInfo +from .user import UserInfo +from .segment import Segment + + +class CSGOProfile: + def __init__(self, data: Dict[str, Any]): + segments = [] + for seg in data["segments"]: + segments.append(Segment(seg)) + + self.platform_info: PlatformInfo = PlatformInfo(data["platformInfo"]) + self.user_info: UserInfo = UserInfo(data["userInfo"]) + self.segments: List[Segment] = segments + self.expiry_date: str = data["expiryDate"] diff --git a/TrackerGG/Models/platform.py b/TrackerGG/Models/platform.py new file mode 100644 index 0000000..a4fb36e --- /dev/null +++ b/TrackerGG/Models/platform.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +""" +Copyright (c) 2023 DevRuby + +MIT License + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +""" + +from enum import Enum +from typing import Dict, Union, Any + + +class Platform(Enum): + steam = "steam" + origin = "origin" + xbl = "xbl" + psn = "psn" + uplay = "uplay" + + +class PlatformInfo: + def __init__(self, data: Dict[str, Union[str, int, None]]): + platforms = { + "steam": Platform.steam, + "origin": Platform.origin, + "xbl": Platform.xbl, + "psn": Platform.psn, + "uplay": Platform.uplay, + } + + self.platform_slug: Platform = platforms[data["platformSlug"]] + self.platform_user_id: Union[str, int] = data["platformUserId"] + self.platform_user_handle: str = data["platformUserHandle"] + self.platform_user_identifier: Union[str, int] = data["platformUserIdentifier"] + self.avatar_url: str = data["avatarUrl"] + self.additional_parameters: Any = data["additionalParameters"] diff --git a/TrackerGG/Models/segment.py b/TrackerGG/Models/segment.py new file mode 100644 index 0000000..c53e8e1 --- /dev/null +++ b/TrackerGG/Models/segment.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +""" +Copyright (c) 2023 DevRuby + +MIT License + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +""" + +from typing import List, Dict, Union, Any + + +class Stat: + def __init__(self, data: Dict[str, Union[int, float, str, None, dict]]): + self.rank: int = data["rank"] + self.percentile: float = data["percentile"] + self.display_name: str = data["displayName"] + self.display_category: str = data["displayCategory"] + self.category: Union[None, str] = data["category"] + self.description: str = data["description"] + self.metadata: Union[None, dict[str, Any]] = data["metadata"] + self.value: int = data["value"] + self.display_value: str = data["displayValue"] + self.display_type: str = data["displayType"] + + def __str__(self): + return f"Name : {self.display_name}\nValue : {self.display_value}\nPercentile : {self.percentile}" + + +class Segment: + def __init__(self, data: Dict[str, Union[str, int, dict]]): + stats = [] + for stat in data["stats"].keys(): + stats.append(Stat(data["stats"][stat])) + + self.type: str = data["type"] + self.attributes: dict = data["attributes"] + self.metadata: dict = data["metadata"] + self.expiry_date: str = data["expiryDate"] + self.stats: List[Stat] = stats diff --git a/TrackerGG/Models/user.py b/TrackerGG/Models/user.py new file mode 100644 index 0000000..a966b99 --- /dev/null +++ b/TrackerGG/Models/user.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +""" +Copyright (c) 2023 DevRuby + +MIT License + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +""" + +from typing import Dict, Union, Optional, Any, List + + +class SocialAccount: + def __init__(self, data: Dict[str, Union[str, int, None]]): + self.platform_slug: str = data["platformSlug"] + self.platform_user_id: Union[str, int] = data["platformUserId"] + self.platform_user_handle: str = data["platformUserHandle"] + self.platform_user_identifier: Union[str, int] = data["platformUserIdentifier"] + self.avatar_url: str = data["avatarUrl"] + self.additional_parameters: Any = data["additionalParameters"] + + +class UserInfo: + def __init__(self, data: Dict[str, Union[str, int, bool, list, None]]): + social_accounts = [] + if data["socialAccounts"]: + for social_account in data["socialAccounts"]: + social_accounts.append(SocialAccount(social_account)) + + self.user_id: Optional[int] = data["userId"] + self.is_premium: bool = data["isPremium"] + self.is_verified: bool = data["isVerified"] + self.is_influencer: bool = data["isInfluencer"] + self.is_partner: bool = data["isPartner"] + self.country_code: Union[str, None] = data["countryCode"] + self.custom_avatar_url: Optional[str] = data["customAvatarUrl"] + self.custom_hero_url: Optional[str] = data["customHeroUrl"] + self.social_accounts: List[SocialAccount] = social_accounts + self.page_views: int = data["pageviews"] + self.custom_avatar_url: Any = data["isSuspicious"] diff --git a/TrackerGG/__init__.py b/TrackerGG/__init__.py index 4261609..12500a6 100644 --- a/TrackerGG/__init__.py +++ b/TrackerGG/__init__.py @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- """ -Copyright (c) 2021 DevRuby +Copyright (c) 2023 DevRuby MIT License THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR @@ -16,15 +16,6 @@ """ -from .exceptions import ApiError -from .exceptions import UserError -from .models import Client -from .models import CsgoStatData -from .models import CsgoProfileData -from .models import CsgoStats -from .models import PlatformInfo -from .models import Platform -from .info import __version__ -from .info import __author__ -from .info import __license__ -from .info import __copyright__ +from .client import CSGOClient + +from .Models import CSGOProfile diff --git a/TrackerGG/client.py b/TrackerGG/client.py new file mode 100644 index 0000000..e562d1f --- /dev/null +++ b/TrackerGG/client.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +""" +Copyright (c) 2023 DevRuby + +MIT License + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +""" + +import asyncio +from .httpclient import HTTPClient +from .httpclient import RequestMethod +from .httpclient import Route +from .httpclient import ResponseData +from .Models import CSGOProfile + +import json + + +class CSGOClient: + api_key: str + loop: asyncio.AbstractEventLoop + http_client: HTTPClient + + def __init__(self, api_key: str) -> None: + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + self.loop = asyncio.get_event_loop() + self.api_key = api_key + self.http_client = HTTPClient(self.loop, self.api_key) + + async def get_profile(self, identifier: str): + response: ResponseData = await self.http_client.request( + Route(RequestMethod.GET, f"/csgo/standard/profile/steam/{identifier}") + ) + + assert response.status == 200, "HTTP Response Status Code is not 200" + + json_data: dict = json.loads(response.response_data) + + return CSGOProfile(json_data["data"]) diff --git a/TrackerGG/exceptions.py b/TrackerGG/exceptions.py deleted file mode 100644 index b603959..0000000 --- a/TrackerGG/exceptions.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -Copyright (c) 2021 DevRuby - -MIT License - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -""" - -class ApiError(Exception): - def __init__(self): - super().__init__("Incorrect API key") -class UserError(Exception): - def __init__(self): - super().__init__("Can't find the user") diff --git a/TrackerGG/httpclient.py b/TrackerGG/httpclient.py new file mode 100644 index 0000000..cda7966 --- /dev/null +++ b/TrackerGG/httpclient.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +""" +Copyright (c) 2023 DevRuby + +MIT License + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +""" + +import asyncio +import aiohttp +import atexit + +from typing import ClassVar, Optional, Dict, Any +from enum import Enum + + +class Missing: + pass + + +MISSING: Any = Missing() + + +class RequestMethod(Enum): + GET = 0 + POST = 1 + PUT = 2 + HEAD = 3 + DELETE = 4 + PATCH = 5 + OPTIONS = 6 + + +class Route: + BASE_URL: ClassVar[str] = "https://public-api.tracker.gg/v2" + + @staticmethod + def __make_url(url: str, params: dict) -> str: + first: bool = True + for key, val in params.items(): + url += "%s%s=%s" % ("?" if first else "&", key, val) + first = False + return url + + def __init__( + self, method: RequestMethod, url: str, params: Optional[Dict[str, str]] = None + ) -> None: + if params: + url = self.__make_url(url, params) + self.url: str = self.BASE_URL + url + self.method: RequestMethod = method + + +class ResponseData: + def __init__(self, text: str, status: int) -> None: + self.response_data: str = text + self.status: int = status + + def __str__(self) -> str: + return f"status_code : {self.status}\nresponse_data : {self.response_data}" + + +class HTTPClient: + USER_AGENT: ClassVar[str] = "Mozilla/5.0" + + def __init__(self, loop: asyncio.AbstractEventLoop, api_key: str) -> None: + self.loop: asyncio.AbstractEventLoop = loop + self.session: aiohttp.ClientSession = MISSING + self.api_key: str = api_key + + atexit.register(self.close) + + async def request( + self, route: Route, headers: Optional[Dict[str, str]] = None + ) -> ResponseData: + if headers: + headers["User-Agent"] = self.USER_AGENT + headers["Accept"] = "application/json" + headers["Accept-Encoding"] = "gzip" + headers["TRN-Api-Key"] = self.api_key + headers["Host"] = "public-api.tracker.gg" + headers["Connection"] = "keep-alive" + headers["TE"] = "trailers" + headers["Upgrade-Insecure-Requests"] = "1" + else: + headers = { + "User-Agent": self.USER_AGENT, + "Accept": "application/json", + "Accept-Encoding": "gzip", + "TRN-Api-Key": self.api_key, + "Host": "public-api.tracker.gg", + "Connection": "keep-alive", + "TE": "trailers", + "Upgrade-Insecure-Requests": "1", + } + + if self.session == MISSING: + self.session = aiohttp.ClientSession() + + async with self.session.request( + method=route.method.name, url=route.url, headers=headers + ) as response: + status: int = response.status + text: str = await response.text(encoding="utf-8") + return ResponseData(text, status) + + def close(self) -> None: + try: + if not self.session.closed: + asyncio.run(self.session.close()) + except TypeError: + pass diff --git a/TrackerGG/models.py b/TrackerGG/models.py deleted file mode 100644 index 7562b26..0000000 --- a/TrackerGG/models.py +++ /dev/null @@ -1,230 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -Copyright (c) 2021 DevRuby - -MIT License - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -""" - -import requests -from .exceptions import ApiError, UserError -from enum import Enum -import re -import aiohttp - - -class Platform(Enum): - steam = "steam" - uplay = "uplay" - ps = "playstation" - xbox = "xbox" - battlenet = "battlenet" - origin = "origin" - - -def get_platform(platform: str) -> Platform: - return { - "steam": Platform.steam, - "uplay": Platform.uplay, - "psn": Platform.ps, - "xbl": Platform.xbox, - "battlenet": Platform.battlenet, - "origin": Platform.origin, - }.get(platform) - - -class CsgoProfileData: - """ - Attributes - ----------- - platform class:`PlatformInfo` - user's playform data - stats class:`CsgoStats` - user's stats - """ - def __init__(self, data: dict): - self.platform: PlatformInfo = PlatformInfo(data["platformInfo"]) - self.stats: CsgoStats = CsgoStats(data["segments"][0]["stats"]) - - -class CsgoStatData: - """ - Attributes - ----------- - rank class:`str` - Could be `None` - percentile class:`str` - percentage of your data - displayName class:`str` - The name of the stat on the TrackerGG website. - displayCategory class:`str` - - category class:`str` - - metadata class:`str` - - value class:`float` or `int` - stat's value - displayValue class:`str` - The value of the stat on the TrackerGG website - displayType class:`str` - The type of the stat on the TrackerGG website - """ - def __init__(self, data: dict): - self.rank = data["rank"] - self.percentile = data["percentile"] - self.displayName = data["displayName"] - self.displayCategory = data["displayCategory"] - self.category = data["category"] - self.metadata = data["metadata"] - self.value = data["value"] - self.displayValue = data["displayValue"] - self.displayType = data["displayType"] - - -class CsgoStats: - def __init__(self, data: dict): - self.timePlayed: CsgoStatData = CsgoStatData(data["timePlayed"]) - self.score: CsgoStatData = CsgoStatData(data["score"]) - self.kills: CsgoStatData = CsgoStatData(data["kills"]) - self.deaths: CsgoStatData = CsgoStatData(data["deaths"]) - self.kdr: CsgoStatData = CsgoStatData(data["kd"]) - self.damage: CsgoStatData = CsgoStatData(data["damage"]) - self.headshots: CsgoStatData = CsgoStatData(data["headshots"]) - self.dominations: CsgoStatData = CsgoStatData(data["dominations"]) - self.shotsFired: CsgoStatData = CsgoStatData(data["shotsFired"]) - self.shotsHit: CsgoStatData = CsgoStatData(data["shotsHit"]) - self.shotsAccuracy: CsgoStatData = CsgoStatData(data["shotsAccuracy"]) - self.snipersKilled: CsgoStatData = CsgoStatData(data["snipersKilled"]) - self.dominationOverkills: CsgoStatData = CsgoStatData( - data["dominationOverkills"] - ) - self.dominationRevenges: CsgoStatData = CsgoStatData(data["dominationRevenges"]) - self.bombsPlanted: CsgoStatData = CsgoStatData(data["bombsPlanted"]) - self.bombsDefused: CsgoStatData = CsgoStatData(data["bombsDefused"]) - self.moneyEarned: CsgoStatData = CsgoStatData(data["moneyEarned"]) - self.hostagesRescued: CsgoStatData = CsgoStatData(data["hostagesRescued"]) - self.mvp: CsgoStatData = CsgoStatData(data["mvp"]) - self.wins: CsgoStatData = CsgoStatData(data["wins"]) - self.ties: CsgoStatData = CsgoStatData(data["ties"]) - self.matchesPlayed: CsgoStatData = CsgoStatData(data["matchesPlayed"]) - self.losses: CsgoStatData = CsgoStatData(data["losses"]) - self.roundsPlayed: CsgoStatData = CsgoStatData(data["roundsPlayed"]) - self.roundsWon: CsgoStatData = CsgoStatData(data["roundsWon"]) - self.winLosePct: CsgoStatData = CsgoStatData(data["wlPercentage"]) - self.headshotPct: CsgoStatData = CsgoStatData(data["headshotPct"]) - - -class PlatformInfo: - """ - Attributes - ----------- - platform class:`Platform` - user's platform - userID class:`str` or `int` - user's ID in the platform - userHandle class:`str` - user's name - userIdentifier class:`str` or `int` - user's identifier - avatarUrl class:`str` - user's avatar - additionalParameters - Parameters. Could be None - """ - def __init__(self, data: dict): - self.platform = get_platform(data["platformSlug"]) - self.userID = data["platformUserId"] - self.userHandle = data["platformUserHandle"] - self.userIdentifier = data["platformUserIdentifier"] - self.avatarUrl = data["avatarUrl"] - self.additionalParameters = data["additionalParameters"] - - -class Client: - def __init__(self, api_key: str) -> None: - if ( - re.compile( - "[A-Za-z0-9+]{8}-[A-Za-z0-9+]{4}-[A-Za-z0-9+]{4}-[A-Za-z0-9+]{4}-[A-Za-z0-9+]{12}" - ).match(api_key) - == None - or not len(api_key) == 36 - ): - raise ApiError - - self.__api_key = api_key - - @property - def api_key(self) -> str: - return self.__api_key - - @api_key.setter - def api_key(self, api_key: str) -> None: - if ( - re.compile( - "[A-Za-z0-9+]{8}-[A-Za-z0-9+]{4}-[A-Za-z0-9+]{4}-[A-Za-z0-9+]{4}-[A-Za-z0-9+]{12}" - ).match(api_key) - == None - or not len(api_key) == 36 - ): - raise ApiError - - self.__api_key = api_key - - def get_csgo_profile(self, identifier: str) -> CsgoProfileData: - response = requests.get( - url="https://public-api.tracker.gg/v2/csgo/standard/profile/steam/{0}".format( - identifier - ), - params={ - "TRN-Api-Key": self.__api_key, - "Accept": "application/json", - "Accept-Encoding": "gzip", - }, - ) - if response.json().get("message") == "Invalid authentication credentials": - raise ApiError - if ( - "errors" in response.json() - and response.json().get("errors")[0].get("message") - == "The stat collector returned the following status code: NotFound" - ): - raise UserError - - return CsgoProfileData(response.json()["data"]) - - async def async_get_csgo_profile(self, identifier:str) -> CsgoProfileData: - async with aiohttp.ClientSession() as session: - async with session.get( - "https://public-api.tracker.gg/v2/csgo/standard/profile/steam/{0}".format( - identifier - ), - params={ - "TRN-Api-Key": self.__api_key, - "Accept": "application/json", - "Accept-Encoding": "gzip", - }, - ) as response: - res = await response.json() - if ( - res.get("message") - == "Invalid authentication credentials" - ): - raise ApiError - if ( - "errors" in res - and res.get("errors")[0].get("message") - == "The stat collector returned the following status code: NotFound" - ): - raise UserError - return CsgoProfileData(res["data"]) From 7095a066a5eab6ef27164acc3f3197e8e7b3d4be Mon Sep 17 00:00:00 2001 From: DevRuby <60344644+dev-ruby@users.noreply.github.com> Date: Wed, 29 Mar 2023 16:54:31 +0900 Subject: [PATCH 2/4] Update README.md --- README.md | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 533be1d..159ec52 100644 --- a/README.md +++ b/README.md @@ -11,37 +11,35 @@ ![Tracker](https://static1-fr.millenium.gg/articles/9/34/23/09/@/1117224-111-article_m-1.jpg) -**TrackerGG is a Tracker API Client** +**An API Wrapper for [TrackerGG API](https://tracker.gg)** ## Install ```pip install TrackerGG``` -## Use -[Sign in tracker.gg and get token](https://tracker.gg/developers) +Get API Key -**Example of getting csgo profile** +[TrackerGG Developers](https://tracker.gg/developers) + + +## **Quick Example** ```py -import TrackerGG # import this library -import asyncio # asyncio library for calling async function +import TrackerGG +import asyncio -client = TrackerGG.Client('TOKEN') # replace 'TOKEN' with your token value. -def GetSync(profile): - return client.get_csgo_profile(profile) +client = TrackerGG.CSGOClient("YOUR_API_KEY") -async def GetAsync(profile): - return await client.async_get_csgo_profile(profile) +profile = asyncio.run(client.get_profile("PLAYER_NAME OR ID")) -print(GetSync("DevRuby").stats.kills.value) -print(asyncio.run(GetAsync("DevRuby")).stats.kills.value) +print(profile.segments[0].stats[0]) ``` - -## Exceptions -### ApiError -Incorrect Api Key -### UserError -Can't find the user +**Output** +``` +Name : Time Played +Value : 1,236h +Percentile : 84.0 +``` From f816a24009645ec4adcc8cf97caff1ce2872bab6 Mon Sep 17 00:00:00 2001 From: DevRuby <60344644+dev-ruby@users.noreply.github.com> Date: Wed, 29 Mar 2023 21:37:47 +0900 Subject: [PATCH 3/4] Sort imports - TrackerGG/__init__.py: Sort imports - TrackerGG/client.py: Sort imports - TrackerGG/httpclient.py: Sort imports - TrackerGG/csgo.py: Sort imports --- TrackerGG/Models/csgo.py | 3 ++- TrackerGG/__init__.py | 3 +-- TrackerGG/client.py | 8 ++++---- TrackerGG/httpclient.py | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/TrackerGG/Models/csgo.py b/TrackerGG/Models/csgo.py index af75d93..c7c0e7c 100644 --- a/TrackerGG/Models/csgo.py +++ b/TrackerGG/Models/csgo.py @@ -16,9 +16,10 @@ """ from typing import Dict, Any, List + from .platform import PlatformInfo -from .user import UserInfo from .segment import Segment +from .user import UserInfo class CSGOProfile: diff --git a/TrackerGG/__init__.py b/TrackerGG/__init__.py index 12500a6..594201a 100644 --- a/TrackerGG/__init__.py +++ b/TrackerGG/__init__.py @@ -16,6 +16,5 @@ """ -from .client import CSGOClient - from .Models import CSGOProfile +from .client import CSGOClient diff --git a/TrackerGG/client.py b/TrackerGG/client.py index e562d1f..b5ee224 100644 --- a/TrackerGG/client.py +++ b/TrackerGG/client.py @@ -17,13 +17,13 @@ """ import asyncio +import json + +from .Models import CSGOProfile from .httpclient import HTTPClient from .httpclient import RequestMethod -from .httpclient import Route from .httpclient import ResponseData -from .Models import CSGOProfile - -import json +from .httpclient import Route class CSGOClient: diff --git a/TrackerGG/httpclient.py b/TrackerGG/httpclient.py index cda7966..0a89e94 100644 --- a/TrackerGG/httpclient.py +++ b/TrackerGG/httpclient.py @@ -17,11 +17,11 @@ """ import asyncio -import aiohttp import atexit - -from typing import ClassVar, Optional, Dict, Any from enum import Enum +from typing import ClassVar, Optional, Dict, Any + +import aiohttp class Missing: From cfcde135490c1dcd618b451c84f0b5972ed9231a Mon Sep 17 00:00:00 2001 From: DevRuby <60344644+dev-ruby@users.noreply.github.com> Date: Wed, 29 Mar 2023 21:38:16 +0900 Subject: [PATCH 4/4] Edit setup.py - setup.py: Update version, email, description --- setup.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index e00fe7f..103f6e0 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,14 @@ import setuptools -with open("README.md", "r") as fh: - long_description = fh.read() +with open("README.md", "r") as fs: + long_description = fs.read() setuptools.setup( name="TrackerGG", - version="1.0.1", + version="2.0.0", author="DevRuby", - author_email="devruby7777@gmail.com", - description="Game Stat Library with Tracker API", + author_email="hiveruby@gmail.com", + description="TrackerGG API Wrapper Library", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/dev-ruby/TrackerGG", @@ -17,9 +17,6 @@ "Programming Language :: Python", "License :: OSI Approved :: MIT License", ], - install_requires=[ - "requests", - "aiohttp" - ], + install_requires=["requests", "aiohttp"], python_requires=">=3.3", )