python-xbox 0.1.0__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.
Files changed (64) hide show
  1. python_xbox-0.1.0.dist-info/METADATA +217 -0
  2. python_xbox-0.1.0.dist-info/RECORD +64 -0
  3. python_xbox-0.1.0.dist-info/WHEEL +4 -0
  4. python_xbox-0.1.0.dist-info/entry_points.txt +6 -0
  5. python_xbox-0.1.0.dist-info/licenses/LICENSE +20 -0
  6. pythonxbox/__init__.py +4 -0
  7. pythonxbox/api/__init__.py +0 -0
  8. pythonxbox/api/client.py +166 -0
  9. pythonxbox/api/language.py +76 -0
  10. pythonxbox/api/provider/__init__.py +0 -0
  11. pythonxbox/api/provider/account/__init__.py +73 -0
  12. pythonxbox/api/provider/account/models.py +11 -0
  13. pythonxbox/api/provider/achievements/__init__.py +164 -0
  14. pythonxbox/api/provider/achievements/models.py +133 -0
  15. pythonxbox/api/provider/baseprovider.py +22 -0
  16. pythonxbox/api/provider/catalog/__init__.py +86 -0
  17. pythonxbox/api/provider/catalog/const.py +15 -0
  18. pythonxbox/api/provider/catalog/models.py +428 -0
  19. pythonxbox/api/provider/cqs/__init__.py +85 -0
  20. pythonxbox/api/provider/cqs/models.py +59 -0
  21. pythonxbox/api/provider/gameclips/__init__.py +167 -0
  22. pythonxbox/api/provider/gameclips/models.py +58 -0
  23. pythonxbox/api/provider/lists/__init__.py +71 -0
  24. pythonxbox/api/provider/lists/models.py +33 -0
  25. pythonxbox/api/provider/mediahub/__init__.py +64 -0
  26. pythonxbox/api/provider/mediahub/models.py +82 -0
  27. pythonxbox/api/provider/message/__init__.py +135 -0
  28. pythonxbox/api/provider/message/models.py +96 -0
  29. pythonxbox/api/provider/people/__init__.py +193 -0
  30. pythonxbox/api/provider/people/models.py +252 -0
  31. pythonxbox/api/provider/presence/__init__.py +110 -0
  32. pythonxbox/api/provider/presence/models.py +53 -0
  33. pythonxbox/api/provider/profile/__init__.py +140 -0
  34. pythonxbox/api/provider/profile/models.py +47 -0
  35. pythonxbox/api/provider/ratelimitedprovider.py +79 -0
  36. pythonxbox/api/provider/screenshots/__init__.py +167 -0
  37. pythonxbox/api/provider/screenshots/models.py +56 -0
  38. pythonxbox/api/provider/smartglass/__init__.py +402 -0
  39. pythonxbox/api/provider/smartglass/models.py +186 -0
  40. pythonxbox/api/provider/titlehub/__init__.py +143 -0
  41. pythonxbox/api/provider/titlehub/models.py +106 -0
  42. pythonxbox/api/provider/usersearch/__init__.py +29 -0
  43. pythonxbox/api/provider/usersearch/models.py +17 -0
  44. pythonxbox/api/provider/userstats/__init__.py +164 -0
  45. pythonxbox/api/provider/userstats/models.py +44 -0
  46. pythonxbox/authentication/__init__.py +0 -0
  47. pythonxbox/authentication/manager.py +161 -0
  48. pythonxbox/authentication/models.py +162 -0
  49. pythonxbox/authentication/xal.py +348 -0
  50. pythonxbox/common/__init__.py +0 -0
  51. pythonxbox/common/exceptions.py +59 -0
  52. pythonxbox/common/filetimes.py +81 -0
  53. pythonxbox/common/models.py +34 -0
  54. pythonxbox/common/ratelimits/__init__.py +268 -0
  55. pythonxbox/common/ratelimits/models.py +23 -0
  56. pythonxbox/common/request_signer.py +190 -0
  57. pythonxbox/common/signed_session.py +60 -0
  58. pythonxbox/py.typed +0 -0
  59. pythonxbox/scripts/__init__.py +15 -0
  60. pythonxbox/scripts/authenticate.py +159 -0
  61. pythonxbox/scripts/change_gamertag.py +111 -0
  62. pythonxbox/scripts/friends.py +80 -0
  63. pythonxbox/scripts/search.py +43 -0
  64. pythonxbox/scripts/xal.py +113 -0
@@ -0,0 +1,164 @@
1
+ """
2
+ Achievements
3
+
4
+ Get Xbox 360 and Xbox One Achievement data
5
+ """
6
+
7
+ from pythonxbox.api.provider.achievements.models import (
8
+ Achievement360ProgressResponse,
9
+ Achievement360Response,
10
+ AchievementResponse,
11
+ RecentProgressResponse,
12
+ )
13
+ from pythonxbox.api.provider.ratelimitedprovider import RateLimitedProvider
14
+
15
+
16
+ class AchievementsProvider(RateLimitedProvider):
17
+ ACHIEVEMENTS_URL = "https://achievements.xboxlive.com"
18
+ HEADERS_GAME_360_PROGRESS = {"x-xbl-contract-version": "1"}
19
+ HEADERS_GAME_PROGRESS = {"x-xbl-contract-version": "2"}
20
+
21
+ RATE_LIMITS = {"burst": 100, "sustain": 300}
22
+
23
+ async def get_achievements_detail_item(
24
+ self, xuid: str, service_config_id: str, achievement_id: str, **kwargs
25
+ ) -> AchievementResponse:
26
+ """
27
+ Get achievement detail for specific item
28
+
29
+ Args:
30
+ xuid (str): Xbox User Id
31
+ service_config_id (str): Service Config Id
32
+ achievement_id (str): Achievement Id
33
+
34
+ Returns:
35
+ :class:`AchievementResponse`: Achievement Response
36
+ """
37
+ url = f"{self.ACHIEVEMENTS_URL}/users/xuid({xuid})/achievements/{service_config_id}/{achievement_id}"
38
+ resp = await self.client.session.get(
39
+ url,
40
+ headers=self.HEADERS_GAME_PROGRESS,
41
+ rate_limits=self.rate_limit_read,
42
+ **kwargs,
43
+ )
44
+ resp.raise_for_status()
45
+ return AchievementResponse(**resp.json())
46
+
47
+ async def get_achievements_xbox360_all(
48
+ self, xuid: str, title_id: str, **kwargs
49
+ ) -> Achievement360Response:
50
+ """
51
+ Get all achievements for specific X360 title Id
52
+
53
+ Args:
54
+ xuid (str): Xbox User Id
55
+ title_id (str): Xbox 360 Title Id
56
+
57
+ Returns:
58
+ :class:`Achievement360Response`: Achievement 360 Response
59
+ """
60
+ url = f"{self.ACHIEVEMENTS_URL}/users/xuid({xuid})/titleachievements?"
61
+ params = {"titleId": title_id}
62
+ resp = await self.client.session.get(
63
+ url,
64
+ params=params,
65
+ headers=self.HEADERS_GAME_360_PROGRESS,
66
+ rate_limits=self.rate_limit_read,
67
+ **kwargs,
68
+ )
69
+ resp.raise_for_status()
70
+ return Achievement360Response(**resp.json())
71
+
72
+ async def get_achievements_xbox360_earned(
73
+ self, xuid: str, title_id: str, **kwargs
74
+ ) -> Achievement360Response:
75
+ """
76
+ Get earned achievements for specific X360 title id
77
+
78
+ Args:
79
+ xuid (str): Xbox User Id
80
+ title_id (str): Xbox 360 Title Id
81
+
82
+ Returns:
83
+ :class:`Achievement360Response`: Achievement 360 Response
84
+ """
85
+ url = f"{self.ACHIEVEMENTS_URL}/users/xuid({xuid})/achievements?"
86
+ params = {"titleId": title_id}
87
+ resp = await self.client.session.get(
88
+ url,
89
+ params=params,
90
+ headers=self.HEADERS_GAME_360_PROGRESS,
91
+ rate_limits=self.rate_limit_read,
92
+ **kwargs,
93
+ )
94
+ resp.raise_for_status()
95
+ return Achievement360Response(**resp.json())
96
+
97
+ async def get_achievements_xbox360_recent_progress_and_info(
98
+ self, xuid: str, **kwargs
99
+ ) -> Achievement360ProgressResponse:
100
+ """
101
+ Get recent achievement progress and information
102
+
103
+ Args:
104
+ xuid (str): Xbox User Id
105
+
106
+ Returns:
107
+ :class:`Achievement360Response`: Achievement 360 Response
108
+ """
109
+ url = f"{self.ACHIEVEMENTS_URL}/users/xuid({xuid})/history/titles"
110
+ resp = await self.client.session.get(
111
+ url,
112
+ headers=self.HEADERS_GAME_360_PROGRESS,
113
+ rate_limits=self.rate_limit_read,
114
+ **kwargs,
115
+ )
116
+ resp.raise_for_status()
117
+ return Achievement360ProgressResponse(**resp.json())
118
+
119
+ async def get_achievements_xboxone_gameprogress(
120
+ self, xuid: str, title_id: str, **kwargs
121
+ ) -> AchievementResponse:
122
+ """
123
+ Get gameprogress for Xbox One title
124
+
125
+ Args:
126
+ xuid (str): Xbox User Id
127
+ title_id (str): Xbox One Title Id
128
+
129
+ Returns:
130
+ :class:`AchievementResponse`: Achievement Response
131
+ """
132
+ url = f"{self.ACHIEVEMENTS_URL}/users/xuid({xuid})/achievements?"
133
+ params = {"titleId": title_id}
134
+ resp = await self.client.session.get(
135
+ url,
136
+ params=params,
137
+ headers=self.HEADERS_GAME_PROGRESS,
138
+ rate_limits=self.rate_limit_read,
139
+ **kwargs,
140
+ )
141
+ resp.raise_for_status()
142
+ return AchievementResponse(**resp.json())
143
+
144
+ async def get_achievements_xboxone_recent_progress_and_info(
145
+ self, xuid: str, **kwargs
146
+ ) -> RecentProgressResponse:
147
+ """
148
+ Get recent achievement progress and information
149
+
150
+ Args:
151
+ xuid (str): Xbox User Id
152
+
153
+ Returns:
154
+ :class:`RecentProgressResponse`: Recent Progress Response
155
+ """
156
+ url = f"{self.ACHIEVEMENTS_URL}/users/xuid({xuid})/history/titles"
157
+ resp = await self.client.session.get(
158
+ url,
159
+ headers=self.HEADERS_GAME_PROGRESS,
160
+ rate_limits=self.rate_limit_read,
161
+ **kwargs,
162
+ )
163
+ resp.raise_for_status()
164
+ return RecentProgressResponse(**resp.json())
@@ -0,0 +1,133 @@
1
+ from datetime import datetime, time
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from pythonxbox.common.models import CamelCaseModel
7
+
8
+
9
+ class PagingInfo(CamelCaseModel):
10
+ continuation_token: str | None = None
11
+ total_records: int
12
+
13
+
14
+ class Achievement360(CamelCaseModel):
15
+ id: int
16
+ title_id: int
17
+ name: str
18
+ sequence: int
19
+ flags: int
20
+ unlocked_online: bool
21
+ unlocked: bool
22
+ is_secret: bool
23
+ platform: int
24
+ gamerscore: int
25
+ image_id: int
26
+ description: str
27
+ locked_description: str
28
+ type: int
29
+ is_revoked: bool
30
+ time_unlocked: datetime
31
+
32
+
33
+ class Title360(CamelCaseModel):
34
+ last_played: datetime
35
+ current_achievements: int
36
+ current_gamerscore: int
37
+ sequence: int
38
+ title_id: int
39
+ title_type: int
40
+ platforms: list[int]
41
+ name: str
42
+ total_achievements: int
43
+ total_gamerscore: int
44
+
45
+
46
+ class Achievement360Response(CamelCaseModel):
47
+ achievements: list[Achievement360]
48
+ paging_info: PagingInfo
49
+ version: datetime
50
+
51
+
52
+ class Achievement360ProgressResponse(CamelCaseModel):
53
+ titles: list[Title360]
54
+ paging_info: PagingInfo
55
+ version: datetime
56
+
57
+
58
+ class TitleAssociation(BaseModel):
59
+ name: str
60
+ id: int
61
+
62
+
63
+ class Requirement(CamelCaseModel):
64
+ id: str
65
+ current: str | None = None
66
+ target: str
67
+ operation_type: str
68
+ value_type: str
69
+ rule_participation_type: str
70
+
71
+
72
+ class Progression(CamelCaseModel):
73
+ requirements: list[Requirement]
74
+ time_unlocked: datetime
75
+
76
+
77
+ class MediaAsset(BaseModel):
78
+ name: str
79
+ type: str
80
+ url: str
81
+
82
+
83
+ class Reward(CamelCaseModel):
84
+ name: Any = None
85
+ description: Any = None
86
+ value: str
87
+ type: str
88
+ media_asset: Any = None
89
+ value_type: str
90
+
91
+
92
+ class Achievement(CamelCaseModel):
93
+ id: str
94
+ service_config_id: str
95
+ name: str
96
+ title_associations: list[TitleAssociation]
97
+ progress_state: str
98
+ progression: Progression
99
+ media_assets: list[MediaAsset]
100
+ platforms: list[str]
101
+ is_secret: bool
102
+ description: str
103
+ locked_description: str
104
+ product_id: str
105
+ achievement_type: str
106
+ participation_type: str
107
+ time_window: Any = None
108
+ rewards: list[Reward]
109
+ estimated_time: time
110
+ deeplink: Any = None
111
+ is_revoked: bool
112
+
113
+
114
+ class AchievementResponse(CamelCaseModel):
115
+ achievements: list[Achievement]
116
+ paging_info: PagingInfo
117
+
118
+
119
+ class Title(CamelCaseModel):
120
+ last_unlock: datetime
121
+ title_id: int
122
+ service_config_id: str
123
+ title_type: str
124
+ platform: str
125
+ name: str
126
+ earned_achievements: int
127
+ current_gamerscore: int
128
+ max_gamerscore: int
129
+
130
+
131
+ class RecentProgressResponse(CamelCaseModel):
132
+ titles: list[Title]
133
+ paging_info: PagingInfo
@@ -0,0 +1,22 @@
1
+ """
2
+ BaseProvider
3
+
4
+ Subclassed by every *real* provider
5
+ """
6
+
7
+ from typing import TYPE_CHECKING
8
+
9
+
10
+ if TYPE_CHECKING:
11
+ from pythonxbox.api.client import XboxLiveClient
12
+
13
+
14
+ class BaseProvider:
15
+ def __init__(self, client: "XboxLiveClient") -> None:
16
+ """
17
+ Initialize an the BaseProvider
18
+
19
+ Args:
20
+ client (:class:`XboxLiveClient`): Instance of XboxLiveClient
21
+ """
22
+ self.client = client
@@ -0,0 +1,86 @@
1
+ """
2
+ Store Catalog - Lookup Product Information
3
+ """
4
+
5
+ from pythonxbox.api.provider.baseprovider import BaseProvider
6
+ from pythonxbox.api.provider.catalog.models import (
7
+ AlternateIdType,
8
+ CatalogResponse,
9
+ CatalogSearchResponse,
10
+ FieldsTemplate,
11
+ PlatformType,
12
+ )
13
+
14
+
15
+ class CatalogProvider(BaseProvider):
16
+ CATALOG_URL = "https://displaycatalog.mp.microsoft.com"
17
+ SEPERATOR = ","
18
+
19
+ async def get_products(
20
+ self,
21
+ big_ids: list[str],
22
+ fields: FieldsTemplate = FieldsTemplate.DETAILS,
23
+ **kwargs,
24
+ ) -> CatalogResponse:
25
+ """Lookup product by Big IDs."""
26
+ ids = self.SEPERATOR.join(big_ids)
27
+ params = {
28
+ "actionFilter": "Browse",
29
+ "bigIds": ids,
30
+ "fieldsTemplate": fields.value,
31
+ "languages": self.client.language.locale,
32
+ "market": self.client.language.short_id,
33
+ }
34
+ url = f"{self.CATALOG_URL}/v7.0/products"
35
+ resp = await self.client.session.get(
36
+ url, params=params, include_auth=False, **kwargs
37
+ )
38
+ resp.raise_for_status()
39
+ return CatalogResponse(**resp.json())
40
+
41
+ async def get_product_from_alternate_id(
42
+ self,
43
+ id: str,
44
+ id_type: AlternateIdType,
45
+ fields: FieldsTemplate = FieldsTemplate.DETAILS,
46
+ top: int = 25,
47
+ **kwargs,
48
+ ) -> CatalogResponse:
49
+ """Lookup product by Alternate ID."""
50
+ params = {
51
+ "top": top,
52
+ "alternateId": id_type.value,
53
+ "fieldsTemplate": fields.value,
54
+ "languages": self.client.language.locale,
55
+ "market": self.client.language.short_id,
56
+ "value": id,
57
+ }
58
+ url = f"{self.CATALOG_URL}/v7.0/products/lookup"
59
+ resp = await self.client.session.get(
60
+ url, params=params, include_auth=False, **kwargs
61
+ )
62
+ resp.raise_for_status()
63
+ return CatalogResponse(**resp.json())
64
+
65
+ async def product_search(
66
+ self,
67
+ query: str,
68
+ platform: PlatformType = PlatformType.XBOX,
69
+ top: int = 5,
70
+ **kwargs,
71
+ ) -> CatalogSearchResponse:
72
+ """Search for products by name."""
73
+ params = {
74
+ "languages": self.client.language.locale,
75
+ "market": self.client.language.short_id,
76
+ "platformdependencyname": platform.value,
77
+ "productFamilyNames": "Games,Apps",
78
+ "query": query,
79
+ "topProducts": top,
80
+ }
81
+ url = f"{self.CATALOG_URL}/v7.0/productFamilies/autosuggest"
82
+ resp = await self.client.session.get(
83
+ url, params=params, include_auth=False, **kwargs
84
+ )
85
+ resp.raise_for_status()
86
+ return CatalogSearchResponse(**resp.json())
@@ -0,0 +1,15 @@
1
+ """Web API Constants."""
2
+
3
+ from pythonxbox.api.provider.catalog.models import AlternateIdType
4
+
5
+ HOME_APP_IDS = {
6
+ AlternateIdType.LEGACY_XBOX_PRODUCT_ID: "7b3ca835-5ef5-4d96-bc84-c1d8b5084236",
7
+ AlternateIdType.XBOX_TITLE_ID: "750323071",
8
+ }
9
+
10
+ SYSTEM_PFN_ID_MAP = {
11
+ "Microsoft.Xbox.LiveTV_8wekyb3d8bbwe": {
12
+ AlternateIdType.LEGACY_XBOX_PRODUCT_ID: "71e7df12-89e0-4dc7-a5ff-a182fc2df94f",
13
+ AlternateIdType.XBOX_TITLE_ID: "371594669",
14
+ },
15
+ }