mc5-api-client 1.0.3__py3-none-any.whl → 1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mc5_api_client/client.py +177 -0
- {mc5_api_client-1.0.3.dist-info → mc5_api_client-1.0.4.dist-info}/METADATA +40 -9
- {mc5_api_client-1.0.3.dist-info → mc5_api_client-1.0.4.dist-info}/RECORD +7 -7
- {mc5_api_client-1.0.3.dist-info → mc5_api_client-1.0.4.dist-info}/LICENSE +0 -0
- {mc5_api_client-1.0.3.dist-info → mc5_api_client-1.0.4.dist-info}/WHEEL +0 -0
- {mc5_api_client-1.0.3.dist-info → mc5_api_client-1.0.4.dist-info}/entry_points.txt +0 -0
- {mc5_api_client-1.0.3.dist-info → mc5_api_client-1.0.4.dist-info}/top_level.txt +0 -0
mc5_api_client/client.py
CHANGED
|
@@ -1724,6 +1724,183 @@ class MC5Client:
|
|
|
1724
1724
|
|
|
1725
1725
|
return config_data
|
|
1726
1726
|
|
|
1727
|
+
# Batch Operations
|
|
1728
|
+
|
|
1729
|
+
def get_batch_profiles(self, credentials: List[str], include_fields: List[str] = None) -> Dict[str, Any]:
|
|
1730
|
+
"""
|
|
1731
|
+
Get batch player profiles with detailed statistics and game save data.
|
|
1732
|
+
|
|
1733
|
+
Args:
|
|
1734
|
+
credentials: List of player credentials to fetch
|
|
1735
|
+
include_fields: List of fields to include (default: ['_game_save', 'inventory'])
|
|
1736
|
+
|
|
1737
|
+
Returns:
|
|
1738
|
+
Dictionary with player profiles containing detailed statistics
|
|
1739
|
+
"""
|
|
1740
|
+
if include_fields is None:
|
|
1741
|
+
include_fields = ['_game_save', 'inventory']
|
|
1742
|
+
|
|
1743
|
+
url = "https://app-468561b3-9ecd-4d21-8241-30ed288f4d8b.gold0009.gameloft.com/1875/windows/09/public/OfficialScripts/mc5Portal.wsgi"
|
|
1744
|
+
|
|
1745
|
+
data = {
|
|
1746
|
+
'op_code': 'get_batch_profiles',
|
|
1747
|
+
'client_id': self.client_id,
|
|
1748
|
+
'credentials': ','.join(credentials),
|
|
1749
|
+
'pandora': f"https://vgold-eur.gameloft.com/{self.client_id}",
|
|
1750
|
+
'include_fields': ','.join(include_fields)
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
headers = {
|
|
1754
|
+
'Accept': '*/*',
|
|
1755
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
1756
|
+
'accept-encoding': 'identity'
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
return self._make_request("POST", url, data=data, headers=headers)
|
|
1760
|
+
|
|
1761
|
+
def get_player_stats_by_dogtag(self, dogtag: str) -> Dict[str, Any]:
|
|
1762
|
+
"""
|
|
1763
|
+
Get detailed player statistics using their dogtag (in-game ID).
|
|
1764
|
+
|
|
1765
|
+
Args:
|
|
1766
|
+
dogtag: Player's dogtag in XXXX format (hexadecimal)
|
|
1767
|
+
|
|
1768
|
+
Returns:
|
|
1769
|
+
Player statistics and profile information
|
|
1770
|
+
"""
|
|
1771
|
+
# Convert dogtag to alias for API lookup
|
|
1772
|
+
alias = self.convert_dogtag_to_alias(dogtag)
|
|
1773
|
+
|
|
1774
|
+
# Get player info using alias
|
|
1775
|
+
player_info = self.get_alias_info(alias)
|
|
1776
|
+
if not player_info.get('credential'):
|
|
1777
|
+
return {'error': f'Player not found for dogtag: {dogtag}', 'alias': alias}
|
|
1778
|
+
|
|
1779
|
+
# Get detailed stats using the credential
|
|
1780
|
+
try:
|
|
1781
|
+
stats = self.get_batch_profiles([player_info['credential']])
|
|
1782
|
+
|
|
1783
|
+
# Add dogtag and alias info to the response
|
|
1784
|
+
if player_info['credential'] in stats:
|
|
1785
|
+
stats[player_info['credential']]['dogtag'] = dogtag
|
|
1786
|
+
stats[player_info['credential']]['alias'] = alias
|
|
1787
|
+
stats[player_info['credential']]['player_info'] = player_info
|
|
1788
|
+
|
|
1789
|
+
return stats
|
|
1790
|
+
|
|
1791
|
+
except Exception as e:
|
|
1792
|
+
return {
|
|
1793
|
+
'error': f'Failed to get stats for dogtag {dogtag}: {e}',
|
|
1794
|
+
'dogtag': dogtag,
|
|
1795
|
+
'alias': alias,
|
|
1796
|
+
'player_info': player_info
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
def search_player_by_dogtag(self, dogtag: str) -> Dict[str, Any]:
|
|
1800
|
+
"""
|
|
1801
|
+
Search for a player using their dogtag and return their profile information.
|
|
1802
|
+
|
|
1803
|
+
Args:
|
|
1804
|
+
dogtag: Player's dogtag in XXXX format (hexadecimal)
|
|
1805
|
+
|
|
1806
|
+
Returns:
|
|
1807
|
+
Complete player information including stats if found
|
|
1808
|
+
"""
|
|
1809
|
+
return self.get_player_stats_by_dogtag(dogtag)
|
|
1810
|
+
|
|
1811
|
+
def get_player_detailed_stats(self, credential: str) -> Dict[str, Any]:
|
|
1812
|
+
"""
|
|
1813
|
+
Get detailed player statistics including game save and inventory.
|
|
1814
|
+
|
|
1815
|
+
Args:
|
|
1816
|
+
credential: Player's credential
|
|
1817
|
+
|
|
1818
|
+
Returns:
|
|
1819
|
+
Detailed player statistics and game data
|
|
1820
|
+
"""
|
|
1821
|
+
return self.get_batch_profiles([credential])
|
|
1822
|
+
|
|
1823
|
+
def parse_player_stats(self, stats_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
1824
|
+
"""
|
|
1825
|
+
Parse and structure player statistics for easier consumption.
|
|
1826
|
+
|
|
1827
|
+
Args:
|
|
1828
|
+
stats_data: Raw stats data from get_batch_profiles
|
|
1829
|
+
|
|
1830
|
+
Returns:
|
|
1831
|
+
Structured player statistics
|
|
1832
|
+
"""
|
|
1833
|
+
if not stats_data or not isinstance(stats_data, dict):
|
|
1834
|
+
return {'error': 'Invalid stats data'}
|
|
1835
|
+
|
|
1836
|
+
# Get the first (and likely only) player's data
|
|
1837
|
+
player_credential = list(stats_data.keys())[0] if stats_data else None
|
|
1838
|
+
if not player_credential or player_credential not in stats_data:
|
|
1839
|
+
return {'error': 'No player data found'}
|
|
1840
|
+
|
|
1841
|
+
player_data = stats_data[player_credential]
|
|
1842
|
+
|
|
1843
|
+
# Extract game save data
|
|
1844
|
+
game_save = player_data.get('_game_save', {})
|
|
1845
|
+
inventory = player_data.get('inventory', {})
|
|
1846
|
+
|
|
1847
|
+
# Parse statistics
|
|
1848
|
+
parsed_stats = {
|
|
1849
|
+
'credential': player_credential,
|
|
1850
|
+
'rating': game_save.get('rating', 0),
|
|
1851
|
+
'rating_duel': game_save.get('rating_duel', 0),
|
|
1852
|
+
'rating_last': game_save.get('rating_last', 0),
|
|
1853
|
+
'current_skill': game_save.get('current_skill', 'unknown'),
|
|
1854
|
+
'current_weapon': game_save.get('current_weapon', 'unknown'),
|
|
1855
|
+
'current_loadout': game_save.get('current_loadout', 0),
|
|
1856
|
+
'kill_signature': game_save.get('killsig', {}),
|
|
1857
|
+
'progress': game_save.get('progress', []),
|
|
1858
|
+
'loadouts': game_save.get('loadouts', []),
|
|
1859
|
+
'statistics': game_save.get('statistics', {}),
|
|
1860
|
+
'inventory': inventory,
|
|
1861
|
+
'xp': inventory.get('xp', 0),
|
|
1862
|
+
'vip_points': inventory.get('vip_points', 0)
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
# Parse weapon statistics
|
|
1866
|
+
weapons = inventory.get('weapons', {})
|
|
1867
|
+
weapon_stats = []
|
|
1868
|
+
|
|
1869
|
+
for weapon_id, weapon_data in weapons.items():
|
|
1870
|
+
if isinstance(weapon_data, dict):
|
|
1871
|
+
weapon_stats.append({
|
|
1872
|
+
'id': weapon_id,
|
|
1873
|
+
'kills': weapon_data.get('kills', 0),
|
|
1874
|
+
'shots': weapon_data.get('shots', 0),
|
|
1875
|
+
'hits': weapon_data.get('hits', 0),
|
|
1876
|
+
'score': weapon_data.get('score', 0),
|
|
1877
|
+
'time_used': weapon_data.get('time_used', 0)
|
|
1878
|
+
})
|
|
1879
|
+
|
|
1880
|
+
# Sort by kills
|
|
1881
|
+
weapon_stats.sort(key=lambda x: x['kills'], reverse=True)
|
|
1882
|
+
parsed_stats['weapon_stats'] = weapon_stats
|
|
1883
|
+
|
|
1884
|
+
# Parse overall statistics
|
|
1885
|
+
stats = game_save.get('statistics', {})
|
|
1886
|
+
if stats:
|
|
1887
|
+
sp_stats = stats.get('sp', {})
|
|
1888
|
+
mp_stats = stats.get('mp', {})
|
|
1889
|
+
|
|
1890
|
+
parsed_stats['overall_stats'] = {
|
|
1891
|
+
'total_kills': sp_stats.get('kill.total', 0) + mp_stats.get('kill.total', 0),
|
|
1892
|
+
'total_deaths': sp_stats.get('death.total', 0) + mp_stats.get('death.total', 0),
|
|
1893
|
+
'total_headshots': sp_stats.get('kill.headshots', 0) + mp_stats.get('kill.headshots', 0),
|
|
1894
|
+
'total_assists': sp_stats.get('kill.assists', 0) + mp_stats.get('kill.assists', 0),
|
|
1895
|
+
'total_time_played': sp_stats.get('time.played', 0) + mp_stats.get('time.played', 0),
|
|
1896
|
+
'sp_kills': sp_stats.get('kill.total', 0),
|
|
1897
|
+
'mp_kills': mp_stats.get('kill.total', 0),
|
|
1898
|
+
'sp_headshots': sp_stats.get('kill.headshots', 0),
|
|
1899
|
+
'mp_headshots': mp_stats.get('kill.headshots', 0)
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
return parsed_stats
|
|
1903
|
+
|
|
1727
1904
|
def __enter__(self):
|
|
1728
1905
|
"""Context manager entry."""
|
|
1729
1906
|
return self
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mc5-api-client
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: A comprehensive Python library for interacting with the Modern Combat 5 API
|
|
5
5
|
Home-page: https://pypi.org/project/mc5-api-client/
|
|
6
6
|
Author: Chizoba
|
|
@@ -960,6 +960,7 @@ The library comes with comprehensive examples to get you started:
|
|
|
960
960
|
- `examples/private_messaging.py` - Private messaging and inbox management
|
|
961
961
|
- `examples/message_management.py` - Advanced message management and bulk deletion
|
|
962
962
|
- `examples/advanced_features.py` - Events, account management, alias system, game config
|
|
963
|
+
- `examples/player_stats.py` - Player statistics, batch profiles, dogtag search
|
|
963
964
|
|
|
964
965
|
### 🚀 Advanced Examples
|
|
965
966
|
- Squad management bot with automated updates
|
|
@@ -1028,14 +1029,44 @@ The library comes with comprehensive examples to get you started:
|
|
|
1028
1029
|
- ✅ Support for cross-platform data transfer
|
|
1029
1030
|
- ✅ Account verification and validation
|
|
1030
1031
|
|
|
1031
|
-
###
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1032
|
+
### 📊 Player Statistics & Batch Profiles
|
|
1033
|
+
|
|
1034
|
+
Get detailed player statistics using dogtags (in-game IDs) or credentials:
|
|
1035
|
+
|
|
1036
|
+
```python
|
|
1037
|
+
# Search player by their in-game dogtag
|
|
1038
|
+
player_stats = client.get_player_stats_by_dogtag("f55f")
|
|
1039
|
+
print(f"Player found: {player_stats.get('player_info', {}).get('account', 'Unknown')}")
|
|
1040
|
+
|
|
1041
|
+
# Parse and analyze statistics
|
|
1042
|
+
parsed = client.parse_player_stats(player_stats)
|
|
1043
|
+
print(f"Rating: {parsed.get('rating', 0)}")
|
|
1044
|
+
print(f"K/D Ratio: {parsed.get('overall_stats', {}).get('total_kills', 0) / max(parsed.get('overall_stats', {}).get('total_deaths', 1), 1):.2f}")
|
|
1045
|
+
|
|
1046
|
+
# Get detailed stats for multiple players
|
|
1047
|
+
credentials = ["player1_cred", "player2_cred", "player3_cred"]
|
|
1048
|
+
batch_stats = client.get_batch_profiles(credentials)
|
|
1049
|
+
|
|
1050
|
+
# Search players using dogtags
|
|
1051
|
+
for dogtag in ["f55f", "ff11", "g6765"]:
|
|
1052
|
+
player = client.search_player_by_dogtag(dogtag)
|
|
1053
|
+
if 'error' not in player:
|
|
1054
|
+
print(f"Found: {player.get('player_info', {}).get('account')}")
|
|
1055
|
+
```
|
|
1056
|
+
|
|
1057
|
+
### 📊 Player Statistics & Batch Profiles (6+ Methods)
|
|
1058
|
+
- ✅ Get batch player profiles with detailed statistics
|
|
1059
|
+
- ✅ Search players by dogtag (in-game ID)
|
|
1060
|
+
- ✅ Get detailed player statistics using credentials
|
|
1061
|
+
- ✅ Parse and structure player statistics
|
|
1062
|
+
- ✅ Convert dogtags to aliases for API lookup
|
|
1063
|
+
- ✅ Combine alias lookup with stats retrieval
|
|
1064
|
+
- ✅ Support for multiple player batch operations
|
|
1065
|
+
- ✅ Detailed game save and inventory data access
|
|
1066
|
+
- ✅ Weapon statistics and performance analysis
|
|
1067
|
+
- ✅ Campaign progress tracking
|
|
1068
|
+
- ✅ Overall statistics calculation (K/D, accuracy, etc.)
|
|
1069
|
+
- ✅ Player performance analysis tools
|
|
1039
1070
|
|
|
1040
1071
|
### ⚙️ Game Configuration (4+ Methods)
|
|
1041
1072
|
- ✅ Get asset hash metadata
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
mc5_api_client/__init__.py,sha256=VtZ8P-CwnjHSq6VmSuBwVttNXIK3qoOrFuNxXMVeaMc,1021
|
|
2
2
|
mc5_api_client/auth.py,sha256=Yj_6s8KmtbswWbR6q816d8soIirUF2aD_KWxg-jNqR0,9978
|
|
3
3
|
mc5_api_client/cli.py,sha256=KegNTxwq28gu_vrffc_cXcALrHzUBDHd-5DqKyYp4p0,17284
|
|
4
|
-
mc5_api_client/client.py,sha256=
|
|
4
|
+
mc5_api_client/client.py,sha256=dHngiS2KgLBJ_WF2Xb0kMAOkWsLggH9jkM2Hz1W0m-w,65469
|
|
5
5
|
mc5_api_client/exceptions.py,sha256=o7od4GrEIlgq6xSNUjZdh74xoDTytF3PLcMq5ewRiJw,2683
|
|
6
6
|
mc5_api_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
mc5_api_client-1.0.
|
|
8
|
-
mc5_api_client-1.0.
|
|
9
|
-
mc5_api_client-1.0.
|
|
10
|
-
mc5_api_client-1.0.
|
|
11
|
-
mc5_api_client-1.0.
|
|
12
|
-
mc5_api_client-1.0.
|
|
7
|
+
mc5_api_client-1.0.4.dist-info/LICENSE,sha256=M0UBQ4B3pB9XcV54_jhVP681xyauF8GB6YK_rKmuXzk,1064
|
|
8
|
+
mc5_api_client-1.0.4.dist-info/METADATA,sha256=oyW9LIWxY9Ov5aAkzRD6JcxUHgEOu0DpcYtIPvNo3vE,37125
|
|
9
|
+
mc5_api_client-1.0.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
10
|
+
mc5_api_client-1.0.4.dist-info/entry_points.txt,sha256=2kruOpleFYK3Jl1MoQwGyqCd-Pj4kQWngXmIjnXx_gE,48
|
|
11
|
+
mc5_api_client-1.0.4.dist-info/top_level.txt,sha256=eYJe4ue9j1ig_jFY5Z05mDqpizUEV7TYpk5lBXVd4kA,15
|
|
12
|
+
mc5_api_client-1.0.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|