diff --git a/src/pythonxbox/api/provider/titlehub/__init__.py b/src/pythonxbox/api/provider/titlehub/__init__.py index 766f859..0aeb7e4 100644 --- a/src/pythonxbox/api/provider/titlehub/__init__.py +++ b/src/pythonxbox/api/provider/titlehub/__init__.py @@ -66,7 +66,11 @@ async def get_title_history( return TitleHubResponse.model_validate_json(resp.text) async def _get_title_info( - self, moniker: str, fields: list[TitleFields] | None = None, **kwargs + self, + xuid: str, + moniker: str, + fields: list[TitleFields] | None = None, + **kwargs, ) -> TitleHubResponse: if not fields: fields = [ @@ -78,7 +82,7 @@ async def _get_title_info( ] fields = self.SEPARATOR.join(fields) - url = f"{self.TITLEHUB_URL}/users/xuid({self.client.xuid})/titles/{moniker}/decoration/{fields}" + url = f"{self.TITLEHUB_URL}/users/xuid({xuid})/titles/{moniker}/decoration/{fields}" resp = await self.client.session.get(url, headers=self._headers, **kwargs) resp.raise_for_status() return TitleHubResponse.model_validate_json(resp.text) @@ -96,7 +100,31 @@ async def get_title_info( Returns: :class:`TitleHubResponse`: Title Hub Response """ - return await self._get_title_info(f"titleid({title_id})", fields, **kwargs) + return await self._get_title_info( + self.client.xuid, f"titleid({title_id})", fields, **kwargs + ) + + async def get_title_info_by_xuid( + self, + xuid: str, + title_id: str, + fields: list[TitleFields] | None = None, + **kwargs, + ) -> TitleHubResponse: + """ + Get info for specific title by XUID + + Args: + xuid: XUID of user to get title info for + title_id: Title Id + fields: List of title fields + + Returns: + :class:`TitleHubResponse`: Title Hub Response + """ + return await self._get_title_info( + xuid, f"titleid({title_id})", fields, **kwargs + ) async def get_title_info_by_pfn( self, pfn: str, fields: list[TitleFields] | None = None, **kwargs @@ -111,7 +139,9 @@ async def get_title_info_by_pfn( Returns: :class:`TitleHubResponse`: Title Hub Response """ - return await self._get_title_info(f"pfn({pfn})", fields, **kwargs) + return await self._get_title_info( + self.client.xuid, f"pfn({pfn})", fields, **kwargs + ) async def get_titles_batch( self, pfns: list[str], fields: list[TitleFields] | None = None, **kwargs diff --git a/tests/test_titlehub.py b/tests/test_titlehub.py index 9cffc09..77ed361 100644 --- a/tests/test_titlehub.py +++ b/tests/test_titlehub.py @@ -35,6 +35,40 @@ async def test_titlehub_titleinfo( assert route.called +@pytest.mark.asyncio +async def test_titlehub_titleinfo_by_xuid( + respx_mock: MockRouter, xbl_client: XboxLiveClient +) -> None: + route = respx_mock.get("https://titlehub.xboxlive.com").mock( + return_value=Response(200, json=get_response_json("titlehub_titleinfo")) + ) + ret = await xbl_client.titlehub.get_title_info_by_xuid(987654321, 1717113201) + + assert len(ret.titles) == 1 + assert "xuid(987654321)" in str(respx_mock.calls[0].request.url) + + assert route.called + + +@pytest.mark.asyncio +async def test_titlehub_titleinfo_by_pfn( + respx_mock: MockRouter, xbl_client: XboxLiveClient +) -> None: + route = respx_mock.get("https://titlehub.xboxlive.com").mock( + return_value=Response(200, json=get_response_json("titlehub_titleinfo")) + ) + ret = await xbl_client.titlehub.get_title_info_by_pfn( + "Microsoft.SeaofThieves_8wekyb3d8bbwe" + ) + + assert len(ret.titles) == 1 + assert "pfn(Microsoft.SeaofThieves_8wekyb3d8bbwe)" in str( + respx_mock.calls[0].request.url + ) + + assert route.called + + @pytest.mark.asyncio async def test_titlehub_batch( respx_mock: MockRouter, xbl_client: XboxLiveClient