Skip to content

Commit a026fb8

Browse files
authored
Feature/devexp 1512 python oas synch sprint 11 (#7)
* feat(conversation): add display_mode field to ChoiceOption and ChoiceOptionDict * feat(Numbers): update numberSinchEvent with spec
1 parent d79ca69 commit a026fb8

20 files changed

Lines changed: 630 additions & 110 deletions

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ All notable changes to the **Sinch Python SDK** are documented in this file.
2525
### Numbers
2626

2727
- **[refactor]** `voice_configuration`, `sms_configuration`, and `number_pattern` request fields are now typed Pydantic models instead of raw dicts with validators. Added `VoiceConfigurationCustom`/`ScheduledVoiceProvisioningCustom` response variants for unrecognized voice configuration types.
28+
- **[feature]** `parse_event()` now returns a `NumberSinchEventPayload` resolved to one of two new concrete subclasses depending on `resourceType`: `ActiveNumberSinchEvent` (`ACTIVE_NUMBER`) and `NumberOrderSinchEvent` (`NUMBER_ORDER`), both inheriting from `NumberSinchEvent`.
29+
- **[deprecation notice]** `NumberSinchEvent` is deprecated; in 3.0 it will be removed in favour of the concrete subclasses plus `NumberBaseSinchEvent`, which will become the fallback for unrecognized resource types.
2830

2931
### Conversation
3032

3133
- **[feature]** Conversation Apps API: `create`, `get`, `list`, `update`, and `delete` operations, with full model, endpoints and unit/e2e test coverage.
34+
- **[feature]** New field `display_mode` added to `ChoiceOption` and `ChoiceOptionDict` to control whether a choice is transient or persistent in the message bubble.
3235
- **[deprecation notice]** `ConversationProcessingMode` and `ConversationRetentionPolicyType` are deprecated; they are unused by the SDK and will be removed in 3.0.
3336
- **[deprecation notice]** `ConversationMetadataReportView` is deprecated in favour of `ConversationMetadataReportViewType`; it will be removed in 3.0.
3437
- **[deprecation notice]** `ConversationChannel` is deprecated in favour of `ConversationChannelType`; it will be removed in 3.0.

sinch/domains/conversation/models/v1/messages/categories/choice/choice_options.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
from typing import Any, Optional
2+
23
from pydantic import Field
4+
5+
from sinch.domains.conversation.models.v1.messages.categories.calendar.calendar_message import (
6+
CalendarMessage,
7+
)
38
from sinch.domains.conversation.models.v1.messages.categories.call.call_message import (
49
CallMessage,
510
)
611
from sinch.domains.conversation.models.v1.messages.categories.location.location_message import (
712
LocationMessage,
813
)
9-
from sinch.domains.conversation.models.v1.messages.categories.url.url_message import (
10-
UrlMessage,
11-
)
12-
from sinch.domains.conversation.models.v1.messages.categories.calendar.calendar_message import (
13-
CalendarMessage,
14-
)
1514
from sinch.domains.conversation.models.v1.messages.categories.sharelocation.share_location_message import (
1615
ShareLocationMessage,
1716
)
17+
from sinch.domains.conversation.models.v1.messages.categories.text import (
18+
TextMessage,
19+
)
20+
from sinch.domains.conversation.models.v1.messages.categories.url.url_message import (
21+
UrlMessage,
22+
)
1823
from sinch.domains.conversation.models.v1.messages.internal.base import (
1924
BaseModelConfiguration,
2025
)
21-
from sinch.domains.conversation.models.v1.messages.categories.text import (
22-
TextMessage,
26+
from sinch.domains.conversation.models.v1.messages.types.display_mode_type import (
27+
DisplayModeType,
2328
)
2429

2530

@@ -28,6 +33,10 @@ class ChoiceMessageWithPostback(BaseModelConfiguration):
2833
default=None,
2934
description="An optional field. This data will be returned in the ChoiceResponseMessage. The default is message_id_{text, title}.",
3035
)
36+
display_mode: Optional[DisplayModeType] = Field(
37+
default=None,
38+
description="Controls the display behavior of a choice.",
39+
)
3140

3241

3342
class CallChoiceMessage(ChoiceMessageWithPostback):

sinch/domains/conversation/models/v1/messages/types/__init__.py

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,57 @@
11
from sinch.domains.conversation.models.v1.messages.types.agent_type import (
22
AgentType,
33
)
4+
from sinch.domains.conversation.models.v1.messages.types.card_height_type import (
5+
CardHeightType,
6+
)
7+
from sinch.domains.conversation.models.v1.messages.types.card_message_dict import (
8+
CardMessageDict,
9+
)
10+
from sinch.domains.conversation.models.v1.messages.types.carousel_message_dict import (
11+
CarouselMessageDict,
12+
)
413
from sinch.domains.conversation.models.v1.messages.types.channel_specific_message_type import (
514
ChannelSpecificMessageType,
615
)
16+
from sinch.domains.conversation.models.v1.messages.types.choice_message_dict import (
17+
ChoiceMessageDict,
18+
)
19+
from sinch.domains.conversation.models.v1.messages.types.contact_info_message_dict import (
20+
ContactInfoMessageDict,
21+
)
722
from sinch.domains.conversation.models.v1.messages.types.conversation_channel_type import (
823
ConversationChannelType,
924
)
25+
from sinch.domains.conversation.models.v1.messages.types.conversation_direction_type import (
26+
ConversationDirectionType,
27+
)
1028
from sinch.domains.conversation.models.v1.messages.types.conversation_messages_view_type import (
1129
ConversationMessagesViewType,
1230
)
13-
from sinch.domains.conversation.models.v1.messages.types.conversation_direction_type import (
14-
ConversationDirectionType,
31+
from sinch.domains.conversation.models.v1.messages.types.display_mode_type import (
32+
DisplayModeType,
1533
)
16-
from sinch.domains.conversation.models.v1.messages.types.processing_mode_type import (
17-
ProcessingModeType,
34+
from sinch.domains.conversation.models.v1.messages.types.list_message_dict import (
35+
ListMessageDict,
1836
)
19-
from sinch.domains.conversation.models.v1.messages.types.card_height_type import (
20-
CardHeightType,
37+
from sinch.domains.conversation.models.v1.messages.types.location_message_dict import (
38+
LocationMessageDict,
39+
)
40+
from sinch.domains.conversation.models.v1.messages.types.media_properties_dict import (
41+
MediaPropertiesDict,
42+
)
43+
from sinch.domains.conversation.models.v1.messages.types.message_content_type import (
44+
MessageContentType,
45+
)
46+
from sinch.domains.conversation.models.v1.messages.types.message_queue_type import (
47+
MessageQueueType,
2148
)
2249
from sinch.domains.conversation.models.v1.messages.types.messages_source_type import (
2350
MessageSourceType,
2451
)
52+
from sinch.domains.conversation.models.v1.messages.types.metadata_update_strategy_type import (
53+
MetadataUpdateStrategyType,
54+
)
2555
from sinch.domains.conversation.models.v1.messages.types.payment_order_goods_type import (
2656
PaymentOrderGoodsType,
2757
)
@@ -34,58 +64,31 @@
3464
from sinch.domains.conversation.models.v1.messages.types.pix_key_type import (
3565
PixKeyType,
3666
)
37-
from sinch.domains.conversation.models.v1.messages.types.reason_code_type import (
38-
ReasonCodeType,
39-
)
40-
from sinch.domains.conversation.models.v1.messages.types.reason_sub_code_type import (
41-
ReasonSubCodeType,
42-
)
43-
from sinch.domains.conversation.models.v1.messages.types.whatsapp_interactive_nfm_reply_name_type import (
44-
WhatsAppInteractiveNfmReplyNameType,
67+
from sinch.domains.conversation.models.v1.messages.types.processing_mode_type import (
68+
ProcessingModeType,
4569
)
4670
from sinch.domains.conversation.models.v1.messages.types.processing_strategy_type import (
4771
ProcessingStrategyType,
4872
)
49-
from sinch.domains.conversation.models.v1.messages.types.metadata_update_strategy_type import (
50-
MetadataUpdateStrategyType,
51-
)
52-
from sinch.domains.conversation.models.v1.messages.types.message_queue_type import (
53-
MessageQueueType,
54-
)
55-
from sinch.domains.conversation.models.v1.messages.types.message_content_type import (
56-
MessageContentType,
57-
)
58-
from sinch.domains.conversation.models.v1.messages.types.list_message_dict import (
59-
ListMessageDict,
60-
)
61-
from sinch.domains.conversation.models.v1.messages.types.media_properties_dict import (
62-
MediaPropertiesDict,
63-
)
64-
from sinch.domains.conversation.models.v1.messages.types.card_message_dict import (
65-
CardMessageDict,
66-
)
67-
from sinch.domains.conversation.models.v1.messages.types.carousel_message_dict import (
68-
CarouselMessageDict,
69-
)
70-
from sinch.domains.conversation.models.v1.messages.types.choice_message_dict import (
71-
ChoiceMessageDict,
72-
)
73-
from sinch.domains.conversation.models.v1.messages.types.contact_info_message_dict import (
74-
ContactInfoMessageDict,
75-
)
76-
from sinch.domains.conversation.models.v1.messages.types.location_message_dict import (
77-
LocationMessageDict,
73+
from sinch.domains.conversation.models.v1.messages.types.reason_code_type import (
74+
ReasonCodeType,
7875
)
79-
from sinch.domains.conversation.models.v1.messages.types.template_message_dict import (
80-
TemplateMessageDict,
76+
from sinch.domains.conversation.models.v1.messages.types.reason_sub_code_type import (
77+
ReasonSubCodeType,
8178
)
8279
from sinch.domains.conversation.models.v1.messages.types.recipient_dict import (
83-
RecipientDict,
8480
ChannelRecipientIdentityDict,
81+
RecipientDict,
8582
)
8683
from sinch.domains.conversation.models.v1.messages.types.send_message_request_body_dict import (
8784
SendMessageRequestBodyDict,
8885
)
86+
from sinch.domains.conversation.models.v1.messages.types.template_message_dict import (
87+
TemplateMessageDict,
88+
)
89+
from sinch.domains.conversation.models.v1.messages.types.whatsapp_interactive_nfm_reply_name_type import (
90+
WhatsAppInteractiveNfmReplyNameType,
91+
)
8992

9093
__all__ = [
9194
"AgentType",
@@ -94,6 +97,7 @@
9497
"ConversationDirectionType",
9598
"ProcessingModeType",
9699
"CardHeightType",
100+
"DisplayModeType",
97101
"ChannelSpecificMessageType",
98102
"ListMessageDict",
99103
"MediaPropertiesDict",

sinch/domains/conversation/models/v1/messages/types/choice_option_dict.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import Any, TypedDict
2+
23
from typing_extensions import NotRequired
34

45
from sinch.domains.conversation.models.v1.messages.types.calendar_message_dict import (
@@ -7,6 +8,9 @@
78
from sinch.domains.conversation.models.v1.messages.types.call_message_dict import (
89
CallMessageDict,
910
)
11+
from sinch.domains.conversation.models.v1.messages.types.display_mode_type import (
12+
DisplayModeType,
13+
)
1014
from sinch.domains.conversation.models.v1.messages.types.location_message_dict import (
1115
LocationMessageDict,
1216
)
@@ -25,6 +29,9 @@ class ChoiceOptionDict(TypedDict):
2529
# Optional metadata returned back to you as postback
2630
postback_data: NotRequired[Any]
2731

32+
# Controls the display behavior of a choice
33+
display_mode: NotRequired[DisplayModeType]
34+
2835
# Exactly one of the following keys is expected per choice:
2936
call_message: NotRequired[CallMessageDict]
3037
location_message: NotRequired[LocationMessageDict]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import Literal, Union
2+
3+
from pydantic import StrictStr
4+
5+
DisplayModeType = Union[
6+
Literal["DISPLAY_MODE_UNSPECIFIED", "PERSISTENT"],
7+
StrictStr,
8+
]

sinch/domains/numbers/models/v1/internal/update_event_destination_request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ class UpdateEventDestinationRequest(BaseModelConfigurationRequest):
99
hmac_secret: Optional[StrictStr] = Field(
1010
default=None,
1111
alias="hmacSecret",
12-
description="The HMAC secret to be updated for the specified project",
12+
description="The HMAC secret to be updated for the specified project. It must be between 32 and 64 characters, alphanumeric (A-Z, a-z, 0-9) and hyphens (-) only. Regex pattern: ^[a-zA-Z0-9-]{32,64}$",
1313
)
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1+
from sinch.domains.numbers.sinch_events.v1.events.active_number_sinch_event import (
2+
ActiveNumberSinchEvent,
3+
)
4+
from sinch.domains.numbers.sinch_events.v1.events.number_order_sinch_event import (
5+
NumberOrderSinchEvent,
6+
)
17
from sinch.domains.numbers.sinch_events.v1.events.number_sinch_event import (
28
NumberSinchEvent,
39
)
10+
from sinch.domains.numbers.sinch_events.v1.events.number_sinch_event_payload import (
11+
NumberSinchEventAdapter,
12+
NumberSinchEventPayload,
13+
)
414

5-
__all__ = ["NumberSinchEvent"]
15+
__all__ = [
16+
"NumberSinchEvent",
17+
"ActiveNumberSinchEvent",
18+
"NumberOrderSinchEvent",
19+
"NumberSinchEventPayload",
20+
"NumberSinchEventAdapter",
21+
]
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from typing import Literal, Optional, Union
2+
3+
from pydantic import Field, StrictStr
4+
5+
from sinch.domains.numbers.sinch_events.v1.events.number_sinch_event import (
6+
NumberSinchEvent,
7+
)
8+
9+
10+
class ActiveNumberSinchEvent(NumberSinchEvent):
11+
resource_type: Literal["ACTIVE_NUMBER"] = Field(
12+
default="ACTIVE_NUMBER", alias="resourceType"
13+
)
14+
event_type: Optional[
15+
Union[
16+
Literal[
17+
"PROVISIONING_TO_SMS_PLATFORM",
18+
"DEPROVISIONING_FROM_SMS_PLATFORM",
19+
"PROVISIONING_TO_CAMPAIGN",
20+
"DEPROVISIONING_FROM_CAMPAIGN",
21+
"PROVISIONING_TO_VOICE_PLATFORM",
22+
"DEPROVISIONING_FROM_VOICE_PLATFORM",
23+
],
24+
StrictStr,
25+
]
26+
] = Field(
27+
default=None, alias="eventType", description="The type of the event."
28+
)
29+
status: Optional[
30+
Union[
31+
Literal[
32+
"SUCCEEDED",
33+
"FAILED",
34+
],
35+
StrictStr,
36+
]
37+
] = Field(
38+
default=None,
39+
description="The status of the event or the state transition it represents.",
40+
)
41+
failure_code: Optional[
42+
Union[
43+
Literal[
44+
"CAMPAIGN_EXPIRED",
45+
"CAMPAIGN_MNO_REJECTED",
46+
"CAMPAIGN_MNO_REVIEW",
47+
"CAMPAIGN_MNO_SUSPENDED",
48+
"CAMPAIGN_NOT_AVAILABLE",
49+
"CAMPAIGN_PENDING_ACCEPTANCE",
50+
"CAMPAIGN_PROVISIONING_FAILED",
51+
"EXCEEDED_10DLC_LIMIT",
52+
"INSUFFICIENT_BALANCE",
53+
"INVALID_NNID",
54+
"MNO_SHARING_ERROR",
55+
"MOCK_CAMPAIGN_NOT_ALLOWED",
56+
"NUMBER_PROVISIONING_FAILED",
57+
"PARTNER_SERVICE_UNAVAILABLE",
58+
"TFN_NOT_ALLOWED",
59+
],
60+
StrictStr,
61+
]
62+
] = Field(
63+
default=None,
64+
alias="failureCode",
65+
description="If the status is FAILED, a failure code will be provided. For numbers provisioning to SMS platform, there won't be any extra `failureCode`, as the result is binary. For campaign provisioning-related failures, refer to the list for the possible values.",
66+
)
67+
internal_failure_code: Optional[StrictStr] = Field(
68+
default=None,
69+
alias="internalFailureCode",
70+
description="If the status is FAILED, certain processes (eg. number to campaign provisioning) will have an internalFailureCode in the payload. The details of these codes can be found in our dedicated [Provisioning errors](https://developers.sinch.com/docs/numbers/api-reference/error-codes/provisioning-errors) documentation.",
71+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from datetime import datetime
2+
from typing import Optional
3+
4+
from pydantic import Field, StrictStr
5+
6+
from sinch.domains.numbers.sinch_events.v1.events.resource_type import (
7+
ResourceType,
8+
)
9+
from sinch.domains.numbers.sinch_events.v1.internal.sinch_event import (
10+
SinchEvent,
11+
)
12+
13+
14+
class NumberBaseSinchEvent(SinchEvent):
15+
event_id: Optional[StrictStr] = Field(
16+
default=None, alias="eventId", description="The ID of the event."
17+
)
18+
timestamp: Optional[datetime] = Field(
19+
default=None,
20+
description="The date and time when the callback was created and added to the callbacks queue.",
21+
)
22+
project_id: Optional[StrictStr] = Field(
23+
default=None,
24+
alias="projectId",
25+
description="The ID of the project to which the event belongs.",
26+
)
27+
resource_type: ResourceType = Field(default=..., alias="resourceType")

0 commit comments

Comments
 (0)