mc5-api-client 1.0.17__py3-none-any.whl → 1.0.18__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/__init__.py +191 -7
- mc5_api_client/client.py +24 -1
- mc5_api_client/easy_mc5.py +682 -0
- mc5_api_client/pc_storage_client.py +229 -0
- mc5_api_client/pc_storage_quick.py +234 -0
- mc5_api_client/platform.py +3 -4
- mc5_api_client/storage_admin.py +285 -0
- {mc5_api_client-1.0.17.dist-info → mc5_api_client-1.0.18.dist-info}/METADATA +165 -20
- {mc5_api_client-1.0.17.dist-info → mc5_api_client-1.0.18.dist-info}/RECORD +13 -9
- {mc5_api_client-1.0.17.dist-info → mc5_api_client-1.0.18.dist-info}/WHEEL +0 -0
- {mc5_api_client-1.0.17.dist-info → mc5_api_client-1.0.18.dist-info}/entry_points.txt +0 -0
- {mc5_api_client-1.0.17.dist-info → mc5_api_client-1.0.18.dist-info}/licenses/LICENSE +0 -0
- {mc5_api_client-1.0.17.dist-info → mc5_api_client-1.0.18.dist-info}/top_level.txt +0 -0
mc5_api_client/__init__.py
CHANGED
|
@@ -15,7 +15,7 @@ messaging, and more.
|
|
|
15
15
|
|
|
16
16
|
from typing import Optional, Dict, Any
|
|
17
17
|
|
|
18
|
-
__version__ = "1.0.
|
|
18
|
+
__version__ = "1.0.18"
|
|
19
19
|
__author__ = "Chizoba"
|
|
20
20
|
__email__ = "chizoba2026@hotmail.com"
|
|
21
21
|
__license__ = "MIT"
|
|
@@ -94,11 +94,185 @@ from .admin_client import (
|
|
|
94
94
|
quick_add_squad_rating,
|
|
95
95
|
quick_update_player_score
|
|
96
96
|
)
|
|
97
|
+
from .pc_storage_client import PCStorageClient
|
|
98
|
+
from .storage_admin import StorageAdminMixin
|
|
99
|
+
from .easy_mc5 import MC5Easy
|
|
97
100
|
|
|
98
101
|
# Encrypted token convenience functions
|
|
99
102
|
from .auth import TokenGenerator
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
# Convenience functions for global ID operations
|
|
105
|
+
def get_global_id(device_id: str = None, device_type: str = "w10", hdidfv: str = None) -> str:
|
|
106
|
+
"""
|
|
107
|
+
Get a global device ID from Gameloft's global ID service.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
device_id: Your device ID (optional, will generate one if not provided)
|
|
111
|
+
device_type: Device type (w10, android, ios, etc.)
|
|
112
|
+
hdidfv: Hardware ID fingerprint (optional)
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Global device ID string
|
|
116
|
+
"""
|
|
117
|
+
import requests
|
|
118
|
+
|
|
119
|
+
# Build request parameters
|
|
120
|
+
params = {
|
|
121
|
+
"source": "Identifiers_6.0.0",
|
|
122
|
+
"client_id": "1875:55979:6.0.0a:windows:windows",
|
|
123
|
+
"device_type": device_type,
|
|
124
|
+
"global_device_id": device_id or "1364509832654538259",
|
|
125
|
+
"hdidfv": hdidfv or "76dfc72e-7850-4d9e-b79c-9861c7e3ea20"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
headers = {
|
|
129
|
+
"Accept": "*/*",
|
|
130
|
+
"Accept-Encoding": "gzip;q=1.0, deflate;q=1.0, identity;q=0.5, *;q=0"
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
response = requests.get(
|
|
135
|
+
"https://gdid.datalake.gameloft.com/assign_global_id/",
|
|
136
|
+
params=params,
|
|
137
|
+
headers=headers,
|
|
138
|
+
timeout=30
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if response.status_code == 200:
|
|
142
|
+
return response.text.strip()
|
|
143
|
+
else:
|
|
144
|
+
return ""
|
|
145
|
+
except Exception:
|
|
146
|
+
return ""
|
|
147
|
+
|
|
148
|
+
def generate_device_id() -> str:
|
|
149
|
+
"""
|
|
150
|
+
Generate a unique device ID for the current device.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Generated device ID string
|
|
154
|
+
"""
|
|
155
|
+
import uuid
|
|
156
|
+
|
|
157
|
+
# Generate a unique device ID
|
|
158
|
+
device_id = f"mc5_{uuid.uuid4().hex[:16]}"
|
|
159
|
+
return device_id
|
|
160
|
+
|
|
161
|
+
def create_federation_session(username: str = None, password: str = None, device_id: str = None) -> Dict[str, Any]:
|
|
162
|
+
"""
|
|
163
|
+
Create a federation session for MC5 game launch.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
username: MC5 username (can use MC5_USERNAME env var)
|
|
167
|
+
password: MC5 password (can use MC5_PASSWORD env var)
|
|
168
|
+
device_id: Device ID for the session (optional)
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Dictionary with session information
|
|
172
|
+
"""
|
|
173
|
+
import os
|
|
174
|
+
import requests
|
|
175
|
+
|
|
176
|
+
# Use environment variables if not provided
|
|
177
|
+
username = username or os.getenv('MC5_USERNAME')
|
|
178
|
+
password = password or os.getenv('MC5_PASSWORD')
|
|
179
|
+
|
|
180
|
+
if not username or not password:
|
|
181
|
+
return {"error": "Username and password are required"}
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
# Build request parameters
|
|
185
|
+
params = {
|
|
186
|
+
"password": password,
|
|
187
|
+
"device_id": device_id or "1364509832654538259"
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
headers = {
|
|
191
|
+
"Accept": "*/*",
|
|
192
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
# Build URL with encoded credential
|
|
196
|
+
encoded_credential = username.replace(":", "%3A")
|
|
197
|
+
url = f"https://federation-eur.gameloft.com/sessions/1875%3A55979%3A6.0.0a%3Awindows%3Awindows/{encoded_credential}"
|
|
198
|
+
|
|
199
|
+
# Make request
|
|
200
|
+
response = requests.post(
|
|
201
|
+
url,
|
|
202
|
+
data=params,
|
|
203
|
+
headers=headers,
|
|
204
|
+
timeout=30
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
if response.status_code == 200:
|
|
208
|
+
return response.json()
|
|
209
|
+
else:
|
|
210
|
+
return {"error": f"HTTP {response.status_code}", "response": response.text}
|
|
211
|
+
|
|
212
|
+
except Exception as e:
|
|
213
|
+
return {"error": str(e)}
|
|
214
|
+
|
|
215
|
+
def locate_service(service: str) -> str:
|
|
216
|
+
"""
|
|
217
|
+
Locate a service endpoint for MC5.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
service: Service name (leaderboard, matchmaker, auth, social, alert, message, lobby, gs, sp)
|
|
221
|
+
|
|
222
|
+
Returns:
|
|
223
|
+
Service endpoint URL or empty string if not found
|
|
224
|
+
"""
|
|
225
|
+
import requests
|
|
226
|
+
|
|
227
|
+
try:
|
|
228
|
+
# Build request parameters
|
|
229
|
+
params = {
|
|
230
|
+
"service": service,
|
|
231
|
+
"client_id": "1875:55979:6.0.0a:windows:windows"
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
headers = {
|
|
235
|
+
"Accept": "*/*"
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
# Make request
|
|
239
|
+
response = requests.get(
|
|
240
|
+
"https://vgold-eur.gameloft.com/1875:55979:6.0.0a:windows:windows/locate",
|
|
241
|
+
params=params,
|
|
242
|
+
headers=headers,
|
|
243
|
+
timeout=30
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if response.status_code == 200:
|
|
247
|
+
return response.text.strip()
|
|
248
|
+
else:
|
|
249
|
+
return ""
|
|
250
|
+
|
|
251
|
+
except Exception:
|
|
252
|
+
return ""
|
|
253
|
+
|
|
254
|
+
def get_all_services() -> Dict[str, str]:
|
|
255
|
+
"""
|
|
256
|
+
Get all available service endpoints.
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
Dictionary mapping service names to endpoints
|
|
260
|
+
"""
|
|
261
|
+
services = [
|
|
262
|
+
"leaderboard", "matchmaker", "auth", "social",
|
|
263
|
+
"alert", "message", "lobby", "gs", "sp"
|
|
264
|
+
]
|
|
265
|
+
|
|
266
|
+
service_endpoints = {}
|
|
267
|
+
|
|
268
|
+
for service in services:
|
|
269
|
+
endpoint = locate_service(service)
|
|
270
|
+
if endpoint:
|
|
271
|
+
service_endpoints[service] = endpoint
|
|
272
|
+
|
|
273
|
+
return service_endpoints
|
|
274
|
+
|
|
275
|
+
def generate_encrypted_token(
|
|
102
276
|
username: str,
|
|
103
277
|
password: str,
|
|
104
278
|
device_id: Optional[str] = None,
|
|
@@ -106,7 +280,7 @@ def quick_generate_encrypted_token(
|
|
|
106
280
|
nonce: str = "*"
|
|
107
281
|
) -> Dict[str, Any]:
|
|
108
282
|
"""
|
|
109
|
-
|
|
283
|
+
Generate and encrypt an access token.
|
|
110
284
|
|
|
111
285
|
Args:
|
|
112
286
|
username: MC5 username
|
|
@@ -125,12 +299,12 @@ def quick_generate_encrypted_token(
|
|
|
125
299
|
finally:
|
|
126
300
|
token_gen.close()
|
|
127
301
|
|
|
128
|
-
def
|
|
302
|
+
def encrypt_token(
|
|
129
303
|
access_token: str,
|
|
130
304
|
nonce: str = "*"
|
|
131
305
|
) -> str:
|
|
132
306
|
"""
|
|
133
|
-
|
|
307
|
+
Encrypt an existing access token.
|
|
134
308
|
|
|
135
309
|
Args:
|
|
136
310
|
access_token: Raw access token string
|
|
@@ -216,6 +390,16 @@ __all__ = [
|
|
|
216
390
|
"help",
|
|
217
391
|
"examples",
|
|
218
392
|
"quick_reference",
|
|
219
|
-
"
|
|
220
|
-
"
|
|
393
|
+
"generate_encrypted_token",
|
|
394
|
+
"encrypt_token",
|
|
395
|
+
"MC5Easy",
|
|
396
|
+
"quick_connect",
|
|
397
|
+
"check_my_daily_tasks",
|
|
398
|
+
"get_my_mc5_profile",
|
|
399
|
+
"find_mc5_player",
|
|
400
|
+
"get_global_id",
|
|
401
|
+
"generate_device_id",
|
|
402
|
+
"create_federation_session",
|
|
403
|
+
"locate_service",
|
|
404
|
+
"get_all_services"
|
|
221
405
|
]
|
mc5_api_client/client.py
CHANGED
|
@@ -27,6 +27,7 @@ from .alerts import AlertsMixin
|
|
|
27
27
|
from .account import AccountMixin
|
|
28
28
|
from .transfer import TransferMixin
|
|
29
29
|
from .platform import Platform, get_platform_config, detect_platform_from_client_id
|
|
30
|
+
from .storage_admin import StorageAdminMixin
|
|
30
31
|
from .exceptions import (
|
|
31
32
|
MC5APIError,
|
|
32
33
|
AuthenticationError,
|
|
@@ -37,7 +38,7 @@ from .exceptions import (
|
|
|
37
38
|
)
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
class MC5Client(SquadBattleMixin, FederationMixin, AlertsMixin, AccountMixin, TransferMixin):
|
|
41
|
+
class MC5Client(SquadBattleMixin, FederationMixin, AlertsMixin, AccountMixin, TransferMixin, StorageAdminMixin):
|
|
41
42
|
"""
|
|
42
43
|
Comprehensive MC5 API client with support for all major endpoints.
|
|
43
44
|
"""
|
|
@@ -2271,6 +2272,28 @@ class MC5Client(SquadBattleMixin, FederationMixin, AlertsMixin, AccountMixin, Tr
|
|
|
2271
2272
|
response = self._make_request("GET", url, params=params)
|
|
2272
2273
|
return response if isinstance(response, list) else []
|
|
2273
2274
|
|
|
2275
|
+
def get_squad_members(self, squad_id: str, offset: int = 0, limit: int = 100) -> Dict[str, Any]:
|
|
2276
|
+
"""
|
|
2277
|
+
Get squad members list.
|
|
2278
|
+
|
|
2279
|
+
Args:
|
|
2280
|
+
squad_id: Squad ID
|
|
2281
|
+
offset: Offset for pagination
|
|
2282
|
+
limit: Number of members to retrieve
|
|
2283
|
+
|
|
2284
|
+
Returns:
|
|
2285
|
+
Squad members list
|
|
2286
|
+
"""
|
|
2287
|
+
url = f"{self.BASE_URLS['osiris']}/groups/{squad_id}/members"
|
|
2288
|
+
params = {
|
|
2289
|
+
"access_token": self._token_data['access_token'],
|
|
2290
|
+
"group_id": squad_id,
|
|
2291
|
+
"offset": str(offset),
|
|
2292
|
+
"limit": str(limit)
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
return self._make_request("GET", url, params=params)
|
|
2296
|
+
|
|
2274
2297
|
def get_clan_info(self, clan_id: str) -> Dict[str, Any]:
|
|
2275
2298
|
"""
|
|
2276
2299
|
Get detailed information about a clan.
|