stream-chat 4.11.0__tar.gz → 4.12.1__tar.gz

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 (37) hide show
  1. {stream-chat-4.11.0/stream_chat.egg-info → stream-chat-4.12.1}/PKG-INFO +2 -2
  2. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/__pkg__.py +1 -1
  3. stream-chat-4.12.1/stream_chat/async_chat/campaign.py +52 -0
  4. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/async_chat/client.py +141 -26
  5. stream-chat-4.12.1/stream_chat/async_chat/segment.py +65 -0
  6. stream-chat-4.12.1/stream_chat/base/campaign.py +51 -0
  7. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/base/client.py +123 -31
  8. stream-chat-4.12.1/stream_chat/base/segment.py +72 -0
  9. stream-chat-4.12.1/stream_chat/campaign.py +60 -0
  10. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/client.py +135 -28
  11. stream-chat-4.12.1/stream_chat/segment.py +63 -0
  12. stream-chat-4.12.1/stream_chat/types/base.py +45 -0
  13. stream-chat-4.12.1/stream_chat/types/campaign.py +78 -0
  14. stream-chat-4.12.1/stream_chat/types/segment.py +46 -0
  15. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/types/stream_response.py +4 -0
  16. {stream-chat-4.11.0 → stream-chat-4.12.1/stream_chat.egg-info}/PKG-INFO +2 -2
  17. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat.egg-info/SOURCES.txt +9 -0
  18. {stream-chat-4.11.0 → stream-chat-4.12.1}/LICENSE +0 -0
  19. {stream-chat-4.11.0 → stream-chat-4.12.1}/MANIFEST.in +0 -0
  20. {stream-chat-4.11.0 → stream-chat-4.12.1}/README.md +0 -0
  21. {stream-chat-4.11.0 → stream-chat-4.12.1}/pyproject.toml +0 -0
  22. {stream-chat-4.11.0 → stream-chat-4.12.1}/setup.cfg +0 -0
  23. {stream-chat-4.11.0 → stream-chat-4.12.1}/setup.py +0 -0
  24. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/__init__.py +0 -0
  25. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/async_chat/__init__.py +0 -0
  26. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/async_chat/channel.py +0 -0
  27. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/base/__init__.py +0 -0
  28. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/base/channel.py +0 -0
  29. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/base/exceptions.py +0 -0
  30. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/channel.py +0 -0
  31. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/py.typed +0 -0
  32. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/types/__init__.py +0 -0
  33. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat/types/rate_limit.py +0 -0
  34. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat.egg-info/dependency_links.txt +0 -0
  35. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat.egg-info/not-zip-safe +0 -0
  36. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat.egg-info/requires.txt +0 -0
  37. {stream-chat-4.11.0 → stream-chat-4.12.1}/stream_chat.egg-info/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: stream-chat
3
- Version: 4.11.0
3
+ Version: 4.12.1
4
4
  Summary: Client for Stream Chat.
5
5
  Home-page: https://github.com/GetStream/stream-chat-python
6
6
  Author: Tommaso Barbugli
7
7
  Author-email: support@getstream.io
8
8
  Project-URL: Bug Tracker, https://github.com/GetStream/stream-chat-python/issues
9
9
  Project-URL: Documentation, https://getstream.io/activity-feeds/docs/python/?language=python
10
- Project-URL: Release Notes, https://github.com/GetStream/stream-chat-python/releases/tag/v4.11.0
10
+ Project-URL: Release Notes, https://github.com/GetStream/stream-chat-python/releases/tag/v4.12.1
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Intended Audience :: System Administrators
13
13
  Classifier: Operating System :: OS Independent
@@ -1,6 +1,6 @@
1
1
  __author__ = "Tommaso Barbugli"
2
2
  __copyright__ = "Copyright 2019-2022, Stream.io, Inc"
3
- __version__ = "4.11.0"
3
+ __version__ = "4.12.1"
4
4
  __maintainer__ = "Tommaso Barbugli"
5
5
  __email__ = "support@getstream.io"
6
6
  __status__ = "Production"
@@ -0,0 +1,52 @@
1
+ import datetime
2
+ from typing import Any, Optional, Union
3
+
4
+ from stream_chat.base.campaign import CampaignInterface
5
+ from stream_chat.types.campaign import CampaignData
6
+ from stream_chat.types.stream_response import StreamResponse
7
+
8
+
9
+ class Campaign(CampaignInterface):
10
+ async def create(
11
+ self, campaign_id: Optional[str] = None, data: Optional[CampaignData] = None
12
+ ) -> StreamResponse:
13
+ if campaign_id is not None:
14
+ self.campaign_id = campaign_id
15
+ if data is not None:
16
+ self.data = data
17
+ state = await self.client.create_campaign( # type: ignore
18
+ campaign_id=self.campaign_id, data=self.data
19
+ )
20
+
21
+ if self.campaign_id is None and state.is_ok() and "campaign" in state:
22
+ self.campaign_id = state["campaign"]["id"]
23
+ return state
24
+
25
+ async def get(self) -> StreamResponse:
26
+ return await self.client.get_campaign( # type: ignore
27
+ campaign_id=self.campaign_id
28
+ )
29
+
30
+ async def update(self, data: CampaignData) -> StreamResponse:
31
+ return await self.client.update_campaign( # type: ignore
32
+ campaign_id=self.campaign_id, data=data
33
+ )
34
+
35
+ async def delete(self, **options: Any) -> StreamResponse:
36
+ return await self.client.delete_campaign( # type: ignore
37
+ campaign_id=self.campaign_id, **options
38
+ )
39
+
40
+ async def start(
41
+ self,
42
+ scheduled_for: Optional[Union[str, datetime.datetime]] = None,
43
+ stop_at: Optional[Union[str, datetime.datetime]] = None,
44
+ ) -> StreamResponse:
45
+ return await self.client.start_campaign( # type: ignore
46
+ campaign_id=self.campaign_id, scheduled_for=scheduled_for, stop_at=stop_at
47
+ )
48
+
49
+ async def stop(self) -> StreamResponse:
50
+ return await self.client.stop_campaign( # type: ignore
51
+ campaign_id=self.campaign_id
52
+ )
@@ -13,9 +13,21 @@ from typing import (
13
13
  Optional,
14
14
  Type,
15
15
  Union,
16
+ cast,
16
17
  )
17
18
  from urllib.parse import urlparse
18
19
 
20
+ from stream_chat.async_chat.campaign import Campaign
21
+ from stream_chat.async_chat.segment import Segment
22
+ from stream_chat.types.base import SortParam
23
+ from stream_chat.types.campaign import CampaignData, QueryCampaignsOptions
24
+ from stream_chat.types.segment import (
25
+ QuerySegmentsOptions,
26
+ QuerySegmentTargetsOptions,
27
+ SegmentData,
28
+ SegmentType,
29
+ )
30
+
19
31
  if sys.version_info >= (3, 8):
20
32
  from typing import Literal
21
33
  else:
@@ -473,7 +485,7 @@ class StreamChatAsync(StreamChatInterface, AsyncContextManager):
473
485
  return await self._parse_response(response)
474
486
 
475
487
  async def create_blocklist(
476
- self, name: str, words: Iterable[str], type: str = "regular"
488
+ self, name: str, words: Iterable[str], type: str = "word"
477
489
  ) -> StreamResponse:
478
490
  return await self.post(
479
491
  "blocklists", data={"name": name, "words": words, "type": type}
@@ -537,45 +549,148 @@ class StreamChatAsync(StreamChatInterface, AsyncContextManager):
537
549
  async def list_roles(self) -> StreamResponse:
538
550
  return await self.get("roles")
539
551
 
540
- async def create_segment(self, segment: Dict) -> StreamResponse:
541
- return await self.post("segments", data={"segment": segment})
552
+ def segment( # type: ignore
553
+ self,
554
+ segment_type: SegmentType,
555
+ segment_id: Optional[str] = None,
556
+ data: Optional[SegmentData] = None,
557
+ ) -> Segment:
558
+ return Segment(
559
+ client=self, segment_type=segment_type, segment_id=segment_id, data=data
560
+ )
561
+
562
+ async def create_segment(
563
+ self,
564
+ segment_type: SegmentType,
565
+ segment_id: Optional[str] = None,
566
+ data: Optional[SegmentData] = None,
567
+ ) -> StreamResponse:
568
+ payload = {"type": segment_type.value}
569
+ if segment_id is not None:
570
+ payload["id"] = segment_id
571
+ if data is not None:
572
+ payload.update(cast(dict, data))
573
+ return await self.post("segments", data=payload)
542
574
 
543
- async def query_segments(self, **params: Any) -> StreamResponse:
544
- return await self.get("segments", params={"payload": json.dumps(params)})
575
+ async def get_segment(self, segment_id: str) -> StreamResponse:
576
+ return await self.get(f"segments/{segment_id}")
545
577
 
546
- async def update_segment(self, segment_id: str, data: Dict) -> StreamResponse:
547
- return await self.put(f"segments/{segment_id}", data={"segment": data})
578
+ async def query_segments(
579
+ self,
580
+ filter_conditions: Optional[Dict[str, Any]] = None,
581
+ sort: Optional[List[SortParam]] = None,
582
+ options: Optional[QuerySegmentsOptions] = None,
583
+ ) -> StreamResponse:
584
+ payload = {}
585
+ if filter_conditions is not None:
586
+ payload["filter"] = filter_conditions
587
+ if sort is not None:
588
+ payload["sort"] = sort # type: ignore
589
+ if options is not None:
590
+ payload.update(cast(dict, options))
591
+ return await self.post("segments/query", data=payload)
592
+
593
+ async def update_segment(
594
+ self, segment_id: str, data: SegmentData
595
+ ) -> StreamResponse:
596
+ return await self.put(f"segments/{segment_id}", data=data)
548
597
 
549
598
  async def delete_segment(self, segment_id: str) -> StreamResponse:
550
599
  return await self.delete(f"segments/{segment_id}")
551
600
 
552
- async def create_campaign(self, campaign: Dict) -> StreamResponse:
553
- return await self.post("campaigns", data={"campaign": campaign})
601
+ async def segment_target_exists(
602
+ self, segment_id: str, target_id: str
603
+ ) -> StreamResponse:
604
+ return await self.get(f"segments/{segment_id}/target/{target_id}")
554
605
 
555
- async def query_campaigns(self, **params: Any) -> StreamResponse:
556
- return await self.get("campaigns", params={"payload": json.dumps(params)})
606
+ async def add_segment_targets(
607
+ self, segment_id: str, target_ids: List[str]
608
+ ) -> StreamResponse:
609
+ return await self.post(
610
+ f"segments/{segment_id}/addtargets", data={"target_ids": target_ids}
611
+ )
557
612
 
558
- async def update_campaign(self, campaign_id: str, data: Dict) -> StreamResponse:
559
- return await self.put(f"campaigns/{campaign_id}", data={"campaign": data})
613
+ async def query_segment_targets(
614
+ self,
615
+ segment_id: str,
616
+ filter_conditions: Optional[Dict[str, Any]] = None,
617
+ sort: Optional[List[SortParam]] = None,
618
+ options: Optional[QuerySegmentTargetsOptions] = None,
619
+ ) -> StreamResponse:
620
+ payload = {}
621
+ if filter_conditions is not None:
622
+ payload["filter"] = filter_conditions
623
+ if sort is not None:
624
+ payload["sort"] = sort # type: ignore
625
+ if options is not None:
626
+ payload.update(cast(dict, options))
627
+ return await self.post(f"segments/{segment_id}/targets/query", data=payload)
628
+
629
+ async def remove_segment_targets(
630
+ self, segment_id: str, target_ids: List[str]
631
+ ) -> StreamResponse:
632
+ return await self.post(
633
+ f"segments/{segment_id}/deletetargets", data={"target_ids": target_ids}
634
+ )
560
635
 
561
- async def delete_campaign(self, campaign_id: str, **options: Any) -> StreamResponse:
562
- return await self.delete(f"campaigns/{campaign_id}", params=options)
636
+ def campaign( # type: ignore
637
+ self, campaign_id: Optional[str] = None, data: Optional[CampaignData] = None
638
+ ) -> Campaign:
639
+ return Campaign(client=self, campaign_id=campaign_id, data=data)
563
640
 
564
- async def schedule_campaign(
565
- self, campaign_id: str, scheduled_for: int = None
641
+ async def create_campaign(
642
+ self, campaign_id: Optional[str] = None, data: Optional[CampaignData] = None
566
643
  ) -> StreamResponse:
567
- return await self.patch(
568
- f"campaigns/{campaign_id}/schedule", data={"scheduled_for": scheduled_for}
569
- )
644
+ payload = {"id": campaign_id}
645
+ if data is not None:
646
+ payload.update(cast(dict, data))
647
+ return await self.post("campaigns", data=payload)
570
648
 
571
- async def query_recipients(self, **params: Any) -> StreamResponse:
572
- return await self.get("recipients", params={"payload": json.dumps(params)})
649
+ async def get_campaign(self, campaign_id: str) -> StreamResponse:
650
+ return await self.get(f"campaigns/{campaign_id}")
573
651
 
574
- async def stop_campaign(self, campaign_id: str) -> StreamResponse:
575
- return await self.patch(f"campaigns/{campaign_id}/stop")
652
+ async def query_campaigns(
653
+ self,
654
+ filter_conditions: Optional[Dict[str, Any]] = None,
655
+ sort: Optional[List[SortParam]] = None,
656
+ options: QueryCampaignsOptions = None,
657
+ ) -> StreamResponse:
658
+ payload = {}
659
+ if filter_conditions is not None:
660
+ payload["filter"] = filter_conditions
661
+ if sort is not None:
662
+ payload["sort"] = sort # type: ignore
663
+ if options is not None:
664
+ payload.update(cast(dict, options))
665
+ return await self.post("campaigns/query", data=payload)
666
+
667
+ async def update_campaign(
668
+ self, campaign_id: str, data: CampaignData
669
+ ) -> StreamResponse:
670
+ return await self.put(f"campaigns/{campaign_id}", data=data)
671
+
672
+ async def delete_campaign(self, campaign_id: str, **options: Any) -> StreamResponse:
673
+ return await self.delete(f"campaigns/{campaign_id}", options)
576
674
 
577
- async def resume_campaign(self, campaign_id: str) -> StreamResponse:
578
- return await self.patch(f"campaigns/{campaign_id}/resume")
675
+ async def start_campaign(
676
+ self,
677
+ campaign_id: str,
678
+ scheduled_for: Optional[Union[str, datetime.datetime]] = None,
679
+ stop_at: Optional[Union[str, datetime.datetime]] = None,
680
+ ) -> StreamResponse:
681
+ payload = {}
682
+ if scheduled_for is not None:
683
+ if isinstance(scheduled_for, datetime.datetime):
684
+ scheduled_for = scheduled_for.isoformat()
685
+ payload["scheduled_for"] = scheduled_for
686
+ if stop_at is not None:
687
+ if isinstance(stop_at, datetime.datetime):
688
+ stop_at = stop_at.isoformat()
689
+ payload["stop_at"] = stop_at
690
+ return await self.post(f"campaigns/{campaign_id}/start", data=payload)
691
+
692
+ async def stop_campaign(self, campaign_id: str) -> StreamResponse:
693
+ return await self.post(f"campaigns/{campaign_id}/stop")
579
694
 
580
695
  async def test_campaign(
581
696
  self, campaign_id: str, users: Iterable[str]
@@ -0,0 +1,65 @@
1
+ from typing import Dict, List, Optional
2
+
3
+ from stream_chat.base.segment import SegmentInterface
4
+ from stream_chat.types.base import SortParam
5
+ from stream_chat.types.segment import QuerySegmentTargetsOptions, SegmentData
6
+ from stream_chat.types.stream_response import StreamResponse
7
+
8
+
9
+ class Segment(SegmentInterface):
10
+ async def create(
11
+ self, segment_id: Optional[str] = None, data: Optional[SegmentData] = None
12
+ ) -> StreamResponse:
13
+ if segment_id is not None:
14
+ self.segment_id = segment_id
15
+ if data is not None:
16
+ self.data = data
17
+
18
+ state = await self.client.create_segment( # type: ignore
19
+ segment_type=self.segment_type, segment_id=self.segment_id, data=self.data
20
+ )
21
+
22
+ if self.segment_id is None and state.is_ok() and "segment" in state:
23
+ self.segment_id = state["segment"]["id"]
24
+ return state
25
+
26
+ async def get(self) -> StreamResponse:
27
+ return await self.client.get_segment(segment_id=self.segment_id) # type: ignore
28
+
29
+ async def update(self, data: SegmentData) -> StreamResponse:
30
+ return await self.client.update_segment( # type: ignore
31
+ segment_id=self.segment_id, data=data
32
+ )
33
+
34
+ async def delete(self) -> StreamResponse:
35
+ return await self.client.delete_segment( # type: ignore
36
+ segment_id=self.segment_id
37
+ )
38
+
39
+ async def target_exists(self, target_id: str) -> StreamResponse:
40
+ return await self.client.segment_target_exists( # type: ignore
41
+ segment_id=self.segment_id, target_id=target_id
42
+ )
43
+
44
+ async def add_targets(self, target_ids: list) -> StreamResponse:
45
+ return await self.client.add_segment_targets( # type: ignore
46
+ segment_id=self.segment_id, target_ids=target_ids
47
+ )
48
+
49
+ async def query_targets(
50
+ self,
51
+ filter_conditions: Optional[Dict] = None,
52
+ sort: Optional[List[SortParam]] = None,
53
+ options: Optional[QuerySegmentTargetsOptions] = None,
54
+ ) -> StreamResponse:
55
+ return await self.client.query_segment_targets( # type: ignore
56
+ segment_id=self.segment_id,
57
+ filter_conditions=filter_conditions,
58
+ sort=sort,
59
+ options=options,
60
+ )
61
+
62
+ async def remove_targets(self, target_ids: list) -> StreamResponse:
63
+ return await self.client.remove_segment_targets( # type: ignore
64
+ segment_id=self.segment_id, target_ids=target_ids
65
+ )
@@ -0,0 +1,51 @@
1
+ import abc
2
+ import datetime
3
+ from typing import Awaitable, Optional, Union
4
+
5
+ from stream_chat.base.client import StreamChatInterface
6
+ from stream_chat.types.campaign import CampaignData
7
+ from stream_chat.types.stream_response import StreamResponse
8
+
9
+
10
+ class CampaignInterface(abc.ABC):
11
+ def __init__(
12
+ self,
13
+ client: StreamChatInterface,
14
+ campaign_id: Optional[str] = None,
15
+ data: CampaignData = None,
16
+ ):
17
+ self.client = client
18
+ self.campaign_id = campaign_id
19
+ self.data = data
20
+
21
+ @abc.abstractmethod
22
+ def create(
23
+ self, campaign_id: Optional[str], data: Optional[CampaignData]
24
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
25
+ pass
26
+
27
+ @abc.abstractmethod
28
+ def get(self) -> Union[StreamResponse, Awaitable[StreamResponse]]:
29
+ pass
30
+
31
+ @abc.abstractmethod
32
+ def update(
33
+ self, data: CampaignData
34
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
35
+ pass
36
+
37
+ @abc.abstractmethod
38
+ def delete(self) -> Union[StreamResponse, Awaitable[StreamResponse]]:
39
+ pass
40
+
41
+ @abc.abstractmethod
42
+ def start(
43
+ self,
44
+ scheduled_for: Optional[Union[str, datetime.datetime]] = None,
45
+ stop_at: Optional[Union[str, datetime.datetime]] = None,
46
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
47
+ pass
48
+
49
+ @abc.abstractmethod
50
+ def stop(self) -> Union[StreamResponse, Awaitable[StreamResponse]]:
51
+ pass
@@ -5,7 +5,16 @@ import hashlib
5
5
  import hmac
6
6
  import os
7
7
  import sys
8
- from typing import Any, Awaitable, Dict, Iterable, List, TypeVar, Union
8
+ from typing import Any, Awaitable, Dict, Iterable, List, Optional, TypeVar, Union
9
+
10
+ from stream_chat.types.base import SortParam
11
+ from stream_chat.types.campaign import CampaignData, QueryCampaignsOptions
12
+ from stream_chat.types.segment import (
13
+ QuerySegmentsOptions,
14
+ QuerySegmentTargetsOptions,
15
+ SegmentData,
16
+ SegmentType,
17
+ )
9
18
 
10
19
  if sys.version_info >= (3, 8):
11
20
  from typing import Literal
@@ -18,6 +27,10 @@ from stream_chat.types.stream_response import StreamResponse
18
27
 
19
28
  TChannel = TypeVar("TChannel")
20
29
 
30
+ TSegment = TypeVar("TSegment")
31
+
32
+ TCampaign = TypeVar("TCampaign")
33
+
21
34
 
22
35
  class StreamChatInterface(abc.ABC):
23
36
  def __init__(
@@ -585,7 +598,6 @@ class StreamChatInterface(abc.ABC):
585
598
  ) -> TChannel: # type: ignore[type-var]
586
599
  """
587
600
  Creates a channel object
588
-
589
601
  :param channel_type: the channel type
590
602
  :param channel_id: the id of the channel
591
603
  :param data: additional data, ie: {"members":[id1, id2, ...]}
@@ -753,7 +765,7 @@ class StreamChatInterface(abc.ABC):
753
765
 
754
766
  @abc.abstractmethod
755
767
  def create_blocklist(
756
- self, name: str, words: Iterable[str], type: str = "regular"
768
+ self, name: str, words: Iterable[str], type: str = "word"
757
769
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
758
770
  """
759
771
  Create a blocklist
@@ -918,18 +930,49 @@ class StreamChatInterface(abc.ABC):
918
930
  """
919
931
  pass
920
932
 
933
+ @abc.abstractmethod
934
+ def segment(
935
+ self,
936
+ segment_type: SegmentType,
937
+ segment_id: Optional[str],
938
+ data: Optional[SegmentData],
939
+ ) -> TSegment: # type: ignore[type-var]
940
+ """
941
+ Creates a channel object
942
+ :param segment_type: the segment type
943
+ :param segment_id: the id of the segment
944
+ :param data: the segment data, ie: {"members":[id1, id2, ...]}
945
+ :return: Segment
946
+ """
947
+ pass
948
+
921
949
  @abc.abstractmethod
922
950
  def create_segment(
923
- self, segment: Dict
951
+ self,
952
+ segment_type: SegmentType,
953
+ segment_id: Optional[str],
954
+ data: Optional[SegmentData] = None,
924
955
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
925
956
  """
926
957
  Create a segment
927
958
  """
928
959
  pass
929
960
 
961
+ @abc.abstractmethod
962
+ def get_segment(
963
+ self, segment_id: str
964
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
965
+ """
966
+ Query segments
967
+ """
968
+ pass
969
+
930
970
  @abc.abstractmethod
931
971
  def query_segments(
932
- self, **params: Any
972
+ self,
973
+ filter_conditions: Optional[Dict] = None,
974
+ sort: Optional[List[SortParam]] = None,
975
+ options: Optional[QuerySegmentsOptions] = None,
933
976
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
934
977
  """
935
978
  Query segments
@@ -938,7 +981,7 @@ class StreamChatInterface(abc.ABC):
938
981
 
939
982
  @abc.abstractmethod
940
983
  def update_segment(
941
- self, segment_id: str, data: Dict
984
+ self, segment_id: str, data: SegmentData
942
985
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
943
986
  """
944
987
  Update a segment by id
@@ -954,9 +997,70 @@ class StreamChatInterface(abc.ABC):
954
997
  """
955
998
  pass
956
999
 
1000
+ @abc.abstractmethod
1001
+ def segment_target_exists(
1002
+ self, segment_id: str, target_id: str
1003
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1004
+ """
1005
+ Check if a target exists in a segment
1006
+ """
1007
+ pass
1008
+
1009
+ @abc.abstractmethod
1010
+ def add_segment_targets(
1011
+ self, segment_id: str, target_ids: List[str]
1012
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1013
+ """
1014
+ Add targets to a segment
1015
+ """
1016
+ pass
1017
+
1018
+ @abc.abstractmethod
1019
+ def query_segment_targets(
1020
+ self,
1021
+ segment_id: str,
1022
+ filter_conditions: Optional[Dict] = None,
1023
+ sort: Optional[List[SortParam]] = None,
1024
+ options: Optional[QuerySegmentTargetsOptions] = None,
1025
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1026
+ """
1027
+ Query targets in a segment
1028
+ """
1029
+ pass
1030
+
1031
+ @abc.abstractmethod
1032
+ def remove_segment_targets(
1033
+ self, segment_id: str, target_ids: List[str]
1034
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1035
+ """
1036
+ Delete targets from a segment
1037
+ """
1038
+ pass
1039
+
1040
+ @abc.abstractmethod
1041
+ def campaign(
1042
+ self, campaign_id: Optional[str], data: Optional[CampaignData]
1043
+ ) -> TCampaign: # type: ignore[type-var]
1044
+ """
1045
+ Creates a campaign object
1046
+ :param campaign_id: the campaign id
1047
+ :param data: campaign_id data
1048
+ :return: Campaign
1049
+ """
1050
+ pass
1051
+
957
1052
  @abc.abstractmethod
958
1053
  def create_campaign(
959
- self, campaign: Dict
1054
+ self, campaign_id: Optional[str], data: Optional[CampaignData]
1055
+ ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1056
+ """
1057
+ Create a campaign
1058
+ """
1059
+ pass
1060
+
1061
+ @abc.abstractmethod
1062
+ def get_campaign(
1063
+ self, campaign_id: str
960
1064
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
961
1065
  """
962
1066
  Create a campaign
@@ -965,7 +1069,10 @@ class StreamChatInterface(abc.ABC):
965
1069
 
966
1070
  @abc.abstractmethod
967
1071
  def query_campaigns(
968
- self, **params: Any
1072
+ self,
1073
+ filter_conditions: Optional[Dict] = None,
1074
+ sort: Optional[List[SortParam]] = None,
1075
+ options: Optional[QueryCampaignsOptions] = None,
969
1076
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
970
1077
  """
971
1078
  Query campaigns
@@ -974,7 +1081,7 @@ class StreamChatInterface(abc.ABC):
974
1081
 
975
1082
  @abc.abstractmethod
976
1083
  def update_campaign(
977
- self, campaign_id: str, data: Dict
1084
+ self, campaign_id: str, data: CampaignData
978
1085
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
979
1086
  """
980
1087
  Update a campaign
@@ -991,11 +1098,14 @@ class StreamChatInterface(abc.ABC):
991
1098
  pass
992
1099
 
993
1100
  @abc.abstractmethod
994
- def schedule_campaign(
995
- self, campaign_id: str, scheduled_for: int = None
1101
+ def start_campaign(
1102
+ self,
1103
+ campaign_id: str,
1104
+ scheduled_for: Optional[Union[str, datetime.datetime]] = None,
1105
+ stop_at: Optional[Union[str, datetime.datetime]] = None,
996
1106
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
997
1107
  """
998
- Schedule a campaign at given time
1108
+ Start a campaign at given time or now if not specified
999
1109
  """
1000
1110
  pass
1001
1111
 
@@ -1004,16 +1114,7 @@ class StreamChatInterface(abc.ABC):
1004
1114
  self, campaign_id: str
1005
1115
  ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1006
1116
  """
1007
- Stop a in progress campaign
1008
- """
1009
- pass
1010
-
1011
- @abc.abstractmethod
1012
- def resume_campaign(
1013
- self, campaign_id: str
1014
- ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1015
- """
1016
- Resume a stopped campaign
1117
+ Stop an in progress campaign
1017
1118
  """
1018
1119
  pass
1019
1120
 
@@ -1026,15 +1127,6 @@ class StreamChatInterface(abc.ABC):
1026
1127
  """
1027
1128
  pass
1028
1129
 
1029
- @abc.abstractmethod
1030
- def query_recipients(
1031
- self, **params: Any
1032
- ) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1033
- """
1034
- Query recipients
1035
- """
1036
- pass
1037
-
1038
1130
  @abc.abstractmethod
1039
1131
  def revoke_tokens(
1040
1132
  self, since: Union[str, datetime.datetime]