diff --git a/stream_chat/async_chat/campaign.py b/stream_chat/async_chat/campaign.py index 4dfd8e90..5380ed1e 100644 --- a/stream_chat/async_chat/campaign.py +++ b/stream_chat/async_chat/campaign.py @@ -2,7 +2,7 @@ from typing import Any, Optional, Union from stream_chat.base.campaign import CampaignInterface -from stream_chat.types.campaign import CampaignData +from stream_chat.types.campaign import CampaignData, GetCampaignOptions from stream_chat.types.stream_response import StreamResponse @@ -22,9 +22,9 @@ async def create( self.campaign_id = state["campaign"]["id"] return state - async def get(self) -> StreamResponse: + async def get(self, options: Optional[GetCampaignOptions] = None) -> StreamResponse: return await self.client.get_campaign( # type: ignore - campaign_id=self.campaign_id + campaign_id=self.campaign_id, options=options ) async def update(self, data: CampaignData) -> StreamResponse: diff --git a/stream_chat/async_chat/client.py b/stream_chat/async_chat/client.py index b7a10997..bb8865c6 100644 --- a/stream_chat/async_chat/client.py +++ b/stream_chat/async_chat/client.py @@ -20,7 +20,11 @@ from stream_chat.async_chat.campaign import Campaign from stream_chat.async_chat.segment import Segment from stream_chat.types.base import SortParam -from stream_chat.types.campaign import CampaignData, QueryCampaignsOptions +from stream_chat.types.campaign import ( + CampaignData, + QueryCampaignsOptions, + GetCampaignOptions, +) from stream_chat.types.segment import ( QuerySegmentsOptions, QuerySegmentTargetsOptions, @@ -664,8 +668,13 @@ async def create_campaign( payload.update(cast(dict, data)) return await self.post("campaigns", data=payload) - async def get_campaign(self, campaign_id: str) -> StreamResponse: - return await self.get(f"campaigns/{campaign_id}") + async def get_campaign( + self, campaign_id: str, options: Optional[GetCampaignOptions] = None + ) -> StreamResponse: + params = {} + if options and "users" in options: + params.update(options["users"]) + return await self.get(f"campaigns/{campaign_id}", params) async def query_campaigns( self, diff --git a/stream_chat/base/campaign.py b/stream_chat/base/campaign.py index 70aba770..a91eb21f 100644 --- a/stream_chat/base/campaign.py +++ b/stream_chat/base/campaign.py @@ -3,7 +3,7 @@ from typing import Awaitable, Optional, Union from stream_chat.base.client import StreamChatInterface -from stream_chat.types.campaign import CampaignData +from stream_chat.types.campaign import CampaignData, GetCampaignOptions from stream_chat.types.stream_response import StreamResponse @@ -25,7 +25,9 @@ def create( pass @abc.abstractmethod - def get(self) -> Union[StreamResponse, Awaitable[StreamResponse]]: + def get( + self, options: Optional[GetCampaignOptions] = None + ) -> Union[StreamResponse, Awaitable[StreamResponse]]: pass @abc.abstractmethod diff --git a/stream_chat/base/client.py b/stream_chat/base/client.py index a8b624b4..37c46201 100644 --- a/stream_chat/base/client.py +++ b/stream_chat/base/client.py @@ -8,7 +8,11 @@ from typing import Any, Awaitable, Dict, Iterable, List, Optional, TypeVar, Union from stream_chat.types.base import SortParam -from stream_chat.types.campaign import CampaignData, QueryCampaignsOptions +from stream_chat.types.campaign import ( + CampaignData, + QueryCampaignsOptions, + GetCampaignOptions, +) from stream_chat.types.segment import ( QuerySegmentsOptions, QuerySegmentTargetsOptions, @@ -1084,10 +1088,14 @@ def create_campaign( @abc.abstractmethod def get_campaign( - self, campaign_id: str + self, campaign_id: str, options: Optional[GetCampaignOptions] = None ) -> Union[StreamResponse, Awaitable[StreamResponse]]: """ - Create a campaign + Get a campaign + + :param campaign_id: ID of the campaign to get + :param options: Optional parameters for the request + :return: Campaign data """ pass diff --git a/stream_chat/campaign.py b/stream_chat/campaign.py index b9eafea0..20869358 100644 --- a/stream_chat/campaign.py +++ b/stream_chat/campaign.py @@ -2,7 +2,7 @@ from typing import Any, Optional, Union from stream_chat.base.campaign import CampaignInterface -from stream_chat.types.campaign import CampaignData +from stream_chat.types.campaign import CampaignData, GetCampaignOptions from stream_chat.types.stream_response import StreamResponse @@ -22,8 +22,8 @@ def create( self.campaign_id = state["campaign"]["id"] # type: ignore return state # type: ignore - def get(self) -> StreamResponse: - return self.client.get_campaign(campaign_id=self.campaign_id) # type: ignore + def get(self, options: Optional[GetCampaignOptions] = None) -> StreamResponse: + return self.client.get_campaign(campaign_id=self.campaign_id, options=options) # type: ignore def update(self, data: CampaignData) -> StreamResponse: return self.client.update_campaign( # type: ignore diff --git a/stream_chat/client.py b/stream_chat/client.py index 85c1e8b9..72f681f1 100644 --- a/stream_chat/client.py +++ b/stream_chat/client.py @@ -9,7 +9,11 @@ from stream_chat.campaign import Campaign from stream_chat.segment import Segment from stream_chat.types.base import SortParam -from stream_chat.types.campaign import CampaignData, QueryCampaignsOptions +from stream_chat.types.campaign import ( + CampaignData, + QueryCampaignsOptions, + GetCampaignOptions, +) from stream_chat.types.segment import ( QuerySegmentsOptions, QuerySegmentTargetsOptions, @@ -636,8 +640,13 @@ def create_campaign( payload.update(cast(dict, data)) return self.post("campaigns", data=payload) - def get_campaign(self, campaign_id: str) -> StreamResponse: - return self.get(f"campaigns/{campaign_id}") + def get_campaign( + self, campaign_id: str, options: Optional[GetCampaignOptions] = None + ) -> StreamResponse: + params = {} + if options and "users" in options: + params.update(options["users"]) + return self.get(f"campaigns/{campaign_id}", params) def query_campaigns( self, diff --git a/stream_chat/tests/async_chat/test_campaign.py b/stream_chat/tests/async_chat/test_campaign.py index 24be9dcc..21f055e3 100644 --- a/stream_chat/tests/async_chat/test_campaign.py +++ b/stream_chat/tests/async_chat/test_campaign.py @@ -1,5 +1,5 @@ import datetime -from typing import Dict +from typing import Dict, List import pytest @@ -61,6 +61,37 @@ async def test_campaign_crud(self, client: StreamChatAsync, random_user: Dict): await client.delete_segment(segment_id=segment_id) + async def test_get_campaign_with_user_pagination( + self, client: StreamChatAsync, random_users: List[Dict] + ): + # Create a campaign with user_ids + campaign = client.campaign( + data={ + "message_template": { + "text": "Test message", + }, + "user_ids": [user["id"] for user in random_users], + "sender_id": random_users[0]["id"], + "name": "test campaign with users", + } + ) + created = await campaign.create() + assert created.is_ok() + campaign_id = created["campaign"]["id"] + + # Test get_campaign with user pagination options + response = await campaign.get( + options={"users": {"limit": 2}} # Limit to 2 users per page + ) + assert response.is_ok() + assert "campaign" in response + assert response["campaign"]["id"] == campaign_id + assert "users" in response["campaign"] + assert len(response["campaign"]["users"]) <= 2 # Verify pagination limit worked + + # Cleanup + await campaign.delete() + async def test_campaign_start_stop( self, client: StreamChatAsync, random_user: Dict ): diff --git a/stream_chat/tests/test_campaign.py b/stream_chat/tests/test_campaign.py index 30835009..7e8ae132 100644 --- a/stream_chat/tests/test_campaign.py +++ b/stream_chat/tests/test_campaign.py @@ -1,5 +1,5 @@ import datetime -from typing import Dict +from typing import Dict, List import pytest @@ -67,6 +67,37 @@ def test_campaign_crud(self, client: StreamChat, random_user: Dict): segment_deleted = client.delete_segment(segment_id=segment_id) assert segment_deleted.is_ok() + def test_get_campaign_with_user_pagination( + self, client: StreamChat, random_users: List[Dict] + ): + # Create a campaign with user_ids + campaign = client.campaign( + data={ + "message_template": { + "text": "Test message", + }, + "user_ids": [user["id"] for user in random_users], + "sender_id": random_users[0]["id"], + "name": "test campaign with users", + } + ) + created = campaign.create() + assert created.is_ok() + campaign_id = created["campaign"]["id"] + + # Test get_campaign with user pagination options + response = campaign.get( + options={"users": {"limit": 2}} # Limit to 2 users per page + ) + assert response.is_ok() + assert "campaign" in response + assert response["campaign"]["id"] == campaign_id + assert "users" in response["campaign"] + assert len(response["campaign"]["users"]) <= 2 # Verify pagination limit worked + + # Cleanup + campaign.delete() + def test_campaign_start_stop(self, client: StreamChat, random_user: Dict): segment = client.create_segment(segment_type=SegmentType.USER) segment_id = segment["segment"]["id"] diff --git a/stream_chat/types/campaign.py b/stream_chat/types/campaign.py index bc1b7306..05f4da92 100644 --- a/stream_chat/types/campaign.py +++ b/stream_chat/types/campaign.py @@ -1,5 +1,5 @@ import sys -from typing import Dict, List, Optional +from typing import Dict, List, Optional, Union if sys.version_info >= (3, 8): from typing import TypedDict @@ -76,3 +76,14 @@ class CampaignData(TypedDict, total=False): class QueryCampaignsOptions(Pager, total=False): pass + + +class GetCampaignOptions(TypedDict, total=False): + """ + Options for getting a campaign. + + Parameters: + users: Optional Pager containing pagination options for users + """ + + users: Optional[Pager]