Skip to content

Commit

Permalink
feat: Add option to remove tags from player nicks (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
cetteup authored Aug 15, 2024
1 parent 05a5c8d commit aa5d499
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 72 deletions.
5 changes: 3 additions & 2 deletions aspxstats/bf2/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ def __init__(
self,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False,
):
super().__init__(provider, timeout, response_validation_mode)
super().__init__(provider, timeout, response_validation_mode, clean_nicks)

async def searchforplayers(
self,
Expand Down
35 changes: 21 additions & 14 deletions aspxstats/bf2/async_fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ async def async_searchforplayers(
sort: SearchSortOrder = SearchSortOrder.ASCENDING,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> PlayerSearchResponse:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.searchforplayers(nick, where, sort)


Expand All @@ -25,9 +26,10 @@ async def async_searchforplayers_dict(
sort: SearchSortOrder = SearchSortOrder.ASCENDING,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> dict:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.searchforplayers_dict(nick, where, sort)


Expand All @@ -45,9 +47,10 @@ async def async_getleaderboard(
pid: Optional[int] = None,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> LeaderboardResponse:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.getleaderboard(leaderboard_type, leaderboard_id, pos, before, after, pid)


Expand All @@ -65,9 +68,10 @@ async def async_getleaderboard_dict(
pid: Optional[int] = None,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> dict:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.getleaderboard_dict(leaderboard_type, leaderboard_id, pos, before, after, pid)


Expand All @@ -76,9 +80,10 @@ async def async_getplayerinfo(
key_set: PlayerinfoKeySet = PlayerinfoKeySet.GENERAL_STATS,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> PlayerinfoResponse:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.getplayerinfo(pid, key_set)


Expand All @@ -87,9 +92,10 @@ async def async_getplayerinfo_dict(
key_set: PlayerinfoKeySet = PlayerinfoKeySet.GENERAL_STATS,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> dict:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.getplayerinfo_dict(pid, key_set)


Expand Down Expand Up @@ -127,9 +133,10 @@ async def async_getunlocksinfo_dict(
pid: int,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False
) -> dict:
async with AsyncAspxClient(provider, timeout, response_validation_mode) as client:
async with AsyncAspxClient(provider, timeout, response_validation_mode, clean_nicks) as client:
return await client.getunlocksinfo_dict(pid)


Expand Down
87 changes: 62 additions & 25 deletions aspxstats/bf2/client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, Optional, Union
from typing import Dict, Optional, Union, Callable

from .schemas import GETLEADERBOARD_RESPONSE_SCHEMA, SEARCHFORPLAYERS_RESPONSE_SCHEMA, \
GETPLAYERINFO_GENERAL_STATS_RESPONSE_SCHEMA, GETPLAYERINFO_MAP_STATS_RESPONSE_SCHEMA, GETRANKINFO_RESPONSE_SCHEMA, \
Expand All @@ -7,25 +7,29 @@
ScoreLeaderboardId, WeaponType, VehicleType, \
KitType, LeaderboardResponse, PlayerinfoKeySet, PlayerinfoResponse, \
PlayerinfoGeneralStats, PlayerinfoMapStats, RankinfoResponse
from .utils import clean_nick
from ..client import AspxClient as BaseAspxClient
from ..exceptions import InvalidParameterError, InvalidResponseError, NotFoundError
from ..parsing import parse_dict_values
from ..types import ProviderConfig, ParseTarget, ResponseValidationMode
from ..types import ProviderConfig, ParseTarget, ResponseValidationMode, CleanerType
from ..validation import is_valid_dict, is_numeric


class AspxClient(BaseAspxClient):
provider: StatsProvider
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]]

def __init__(
self,
provider: StatsProvider = StatsProvider.BF2HUB,
timeout: float = 2.0,
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX
response_validation_mode: ResponseValidationMode = ResponseValidationMode.LAX,
clean_nicks: bool = False,
):
provider_config = AspxClient.get_provider_config(provider)
super().__init__(provider_config.base_uri, provider_config.default_headers, timeout, response_validation_mode)
self.provider = provider
self.cleaners = AspxClient.get_cleaners(clean_nicks)

def searchforplayers(
self,
Expand Down Expand Up @@ -63,15 +67,18 @@ def validate_and_parse_searchforplayers_response(self, raw_data: str) -> dict:
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid searchforplayers response data')

return self.parse_searchforplayers_response_values(parsed)
return self.parse_searchforplayers_response_values(parsed, self.cleaners)

@staticmethod
def is_valid_searchforplayers_response_data(parsed: dict) -> bool:
return is_valid_dict(parsed, SEARCHFORPLAYERS_RESPONSE_SCHEMA)

@staticmethod
def parse_searchforplayers_response_values(parsed: dict) -> dict:
return parse_dict_values(parsed, SEARCHFORPLAYERS_RESPONSE_SCHEMA)
def parse_searchforplayers_response_values(
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
return parse_dict_values(parsed, SEARCHFORPLAYERS_RESPONSE_SCHEMA, cleaners)

def getleaderboard(
self,
Expand Down Expand Up @@ -129,16 +136,19 @@ def validate_and_parse_getleaderboard_response(self, raw_data: str) -> dict:
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid getleaderboard response data')

return self.parse_getleaderboard_response_values(parsed)
return self.parse_getleaderboard_response_values(parsed, self.cleaners)

@staticmethod
def is_valid_getleaderboard_response_data(parsed: dict) -> bool:
# TODO: Add per-leaderboard validation with respective attributes
return is_valid_dict(parsed, GETLEADERBOARD_RESPONSE_SCHEMA)

@staticmethod
def parse_getleaderboard_response_values(parsed: dict) -> dict:
return parse_dict_values(parsed, GETLEADERBOARD_RESPONSE_SCHEMA)
def parse_getleaderboard_response_values(
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
return parse_dict_values(parsed, GETLEADERBOARD_RESPONSE_SCHEMA, cleaners)

def getplayerinfo(
self,
Expand Down Expand Up @@ -186,7 +196,7 @@ def validate_and_parse_getplayerinfo_response(self, key_set: PlayerinfoKeySet, r
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid getplayerinfo response data')

return self.parse_getplayerinfo_response_values(key_set, parsed)
return self.parse_getplayerinfo_response_values(key_set, parsed, self.cleaners)

@staticmethod
def fix_getplayerinfo_zero_values(parsed: dict) -> dict:
Expand Down Expand Up @@ -220,11 +230,15 @@ def is_valid_getplayerinfo_response_data(key_set: PlayerinfoKeySet, parsed: dict
return is_valid_dict(parsed, GETPLAYERINFO_MAP_STATS_RESPONSE_SCHEMA)

@staticmethod
def parse_getplayerinfo_response_values(key_set: PlayerinfoKeySet, parsed: dict) -> dict:
def parse_getplayerinfo_response_values(
key_set: PlayerinfoKeySet,
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
if key_set is PlayerinfoKeySet.GENERAL_STATS:
return parse_dict_values(parsed, GETPLAYERINFO_GENERAL_STATS_RESPONSE_SCHEMA)
return parse_dict_values(parsed, GETPLAYERINFO_GENERAL_STATS_RESPONSE_SCHEMA, cleaners)
else:
return parse_dict_values(parsed, GETPLAYERINFO_MAP_STATS_RESPONSE_SCHEMA)
return parse_dict_values(parsed, GETPLAYERINFO_MAP_STATS_RESPONSE_SCHEMA, cleaners)

def getrankinfo(
self,
Expand Down Expand Up @@ -257,15 +271,18 @@ def validate_and_parse_getrankinfo_response(self, raw_data: str) -> dict:
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid getrankinfo response data')

return self.parse_getrankinfo_response_values(parsed)
return self.parse_getrankinfo_response_values(parsed, self.cleaners)

@staticmethod
def is_valid_getrankinfo_response_data(parsed: dict) -> bool:
return is_valid_dict(parsed, GETRANKINFO_RESPONSE_SCHEMA)

@staticmethod
def parse_getrankinfo_response_values(parsed: dict) -> dict:
return parse_dict_values(parsed, GETRANKINFO_RESPONSE_SCHEMA)
def parse_getrankinfo_response_values(
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
return parse_dict_values(parsed, GETRANKINFO_RESPONSE_SCHEMA, cleaners)

def getawardsinfo_dict(
self,
Expand All @@ -292,15 +309,18 @@ def validate_and_parse_getawardsinfo_response(self, raw_data: str) -> dict:
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid getawardsinfo response data')

return self.parse_getawardsinfo_response_values(parsed)
return self.parse_getawardsinfo_response_values(parsed, self.cleaners)

@staticmethod
def is_valid_getawardsinfo_response_data(parsed: dict) -> bool:
return is_valid_dict(parsed, GETAWARDSINFO_RESPONSE_SCHEMA)

@staticmethod
def parse_getawardsinfo_response_values(parsed: dict) -> dict:
return parse_dict_values(parsed, GETAWARDSINFO_RESPONSE_SCHEMA)
def parse_getawardsinfo_response_values(
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
return parse_dict_values(parsed, GETAWARDSINFO_RESPONSE_SCHEMA, cleaners)

def getunlocksinfo_dict(
self,
Expand Down Expand Up @@ -328,15 +348,18 @@ def validate_and_parse_getunlocksinfo_response(self, raw_data: str) -> dict:
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid getunlocksinfo response data')

return self.parse_getunlocksinfo_response_values(parsed)
return self.parse_getunlocksinfo_response_values(parsed, self.cleaners)

@staticmethod
def is_valid_getunlocksinfo_response_data(parsed: dict) -> bool:
return is_valid_dict(parsed, GETUNLOCKSINFO_RESPONSE_SCHEMA)

@staticmethod
def parse_getunlocksinfo_response_values(parsed: dict) -> dict:
return parse_dict_values(parsed, GETUNLOCKSINFO_RESPONSE_SCHEMA)
def parse_getunlocksinfo_response_values(
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
return parse_dict_values(parsed, GETUNLOCKSINFO_RESPONSE_SCHEMA, cleaners)

def getbackendinfo_dict(
self,
Expand All @@ -358,15 +381,18 @@ def validate_and_parse_getbackendinfo_response(self, raw_data: str) -> dict:
if not valid_data:
raise InvalidResponseError(f'{self.provider} returned invalid getbackendinfo response data')

return self.parse_getbackendinfo_response_values(parsed)
return self.parse_getbackendinfo_response_values(parsed, self.cleaners)

@staticmethod
def is_valid_getbackendinfo_response_data(parsed: dict) -> bool:
return is_valid_dict(parsed, GETBACKENDINFO_RESPONSE_SCHEMA)

@staticmethod
def parse_getbackendinfo_response_values(parsed: dict) -> dict:
return parse_dict_values(parsed, GETBACKENDINFO_RESPONSE_SCHEMA)
def parse_getbackendinfo_response_values(
parsed: dict,
cleaners: Optional[Dict[CleanerType, Callable[[str], str]]] = None
) -> dict:
return parse_dict_values(parsed, GETBACKENDINFO_RESPONSE_SCHEMA, cleaners)

@staticmethod
def get_provider_config(provider: StatsProvider = StatsProvider.BF2HUB) -> ProviderConfig:
Expand All @@ -388,3 +414,14 @@ def get_provider_config(provider: StatsProvider = StatsProvider.BF2HUB) -> Provi
raise InvalidParameterError(f'No provider config for given provider "{provider}"')

return config

@staticmethod
def get_cleaners(clean_nicks: bool = False) -> Optional[Dict[CleanerType, Callable[[str], str]]]:
cleaners: Dict[CleanerType, Callable[[str], str]] = {}
if clean_nicks:
cleaners[CleanerType.NICK] = clean_nick

if len(cleaners) > 0:
return cleaners

return None
Loading

0 comments on commit aa5d499

Please sign in to comment.