|
1 | | -from typing import List, Optional |
| 1 | +from typing import Literal, Optional, Union |
2 | 2 |
|
3 | | -from pydantic import BaseModel, Field, model_validator |
4 | | -from vonage_utils.models import Link |
5 | | -from vonage_utils.types import PhoneNumber |
| 3 | +from pydantic import BaseModel, Field, field_validator |
6 | 4 |
|
| 5 | +from .enums import Region |
| 6 | +from .errors import ApplicationError |
7 | 7 |
|
8 | | -class ResourceLink(BaseModel): |
9 | | - self: Link |
10 | 8 |
|
| 9 | +class Url(BaseModel): |
| 10 | + address: str |
| 11 | + http_method: Optional[Literal['GET', 'POST']] = None |
11 | 12 |
|
12 | | -class PstnChannel(BaseModel): |
13 | | - number: int |
14 | 13 |
|
| 14 | +class VoiceUrl(Url): |
| 15 | + connection_timeout: Optional[int] = Field(None, ge=300, le=1000) |
| 16 | + socket_timeout: Optional[int] = Field(None, ge=1000, le=5000) |
15 | 17 |
|
16 | | -class SipChannel(BaseModel): |
17 | | - uri: str = Field(..., pattern=r'^(sip|sips):\+?([\w|:.\-@;,=%&]+)') |
18 | | - username: str = None |
19 | | - password: str = None |
20 | 18 |
|
| 19 | +class VoiceWebhooks(BaseModel): |
| 20 | + answer_url: Optional[Url] = None |
| 21 | + fallback_answer_url: Optional[Url] = None |
| 22 | + event_url: Optional[Url] = None |
21 | 23 |
|
22 | | -class VbcChannel(BaseModel): |
23 | | - extension: str |
24 | 24 |
|
| 25 | +class Voice(BaseModel): |
| 26 | + webhooks: Optional[VoiceWebhooks] = None |
| 27 | + signed_callbacks: Optional[bool] = None |
| 28 | + conversations_ttl: Optional[int] = Field(None, ge=1, le=9000) |
| 29 | + leg_persistence_time: Optional[int] = Field(None, ge=1, le=31) |
| 30 | + region: Optional[Region] = None |
25 | 31 |
|
26 | | -class WebsocketChannel(BaseModel): |
27 | | - uri: str = Field(pattern=r'^(ws|wss):\/\/[a-zA-Z0-9~#%@&-_?\/.,:;)(\]\[]*$') |
28 | | - content_type: Optional[str] = Field( |
29 | | - None, alias='content-type', pattern='^audio/l16;rate=(8000|16000)$' |
30 | | - ) |
31 | | - headers: Optional[dict] = None |
32 | 32 |
|
| 33 | +class RtcWebhooks(BaseModel): |
| 34 | + event_url: Optional[Url] = None |
33 | 35 |
|
34 | | -class SmsChannel(BaseModel): |
35 | | - number: PhoneNumber |
36 | 36 |
|
| 37 | +class Rtc(BaseModel): |
| 38 | + webhooks: Optional[RtcWebhooks] = None |
| 39 | + signed_callbacks: Optional[bool] = None |
37 | 40 |
|
38 | | -class MmsChannel(BaseModel): |
39 | | - number: PhoneNumber |
40 | 41 |
|
| 42 | +class MessagesWebhooks(BaseModel): |
| 43 | + inbound_url: Optional[Url] = None |
| 44 | + status_url: Optional[Url] = None |
41 | 45 |
|
42 | | -class WhatsappChannel(BaseModel): |
43 | | - number: PhoneNumber |
44 | 46 |
|
| 47 | +class Messages(BaseModel): |
| 48 | + version: Optional[str] = None |
| 49 | + webhooks: Optional[MessagesWebhooks] = None |
45 | 50 |
|
46 | | -class ViberChannel(BaseModel): |
47 | | - number: PhoneNumber |
48 | 51 |
|
| 52 | +class Vbc(BaseModel): |
| 53 | + pass |
49 | 54 |
|
50 | | -class MessengerChannel(BaseModel): |
51 | | - id: str |
52 | 55 |
|
| 56 | +class VerifyWebhooks(BaseModel): |
| 57 | + status_url: Optional[Url] = None |
53 | 58 |
|
54 | | -class Channels(BaseModel): |
55 | | - sms: Optional[List[SmsChannel]] = None |
56 | | - mms: Optional[List[MmsChannel]] = None |
57 | | - whatsapp: Optional[List[WhatsappChannel]] = None |
58 | | - viber: Optional[List[ViberChannel]] = None |
59 | | - messenger: Optional[List[MessengerChannel]] = None |
60 | | - pstn: Optional[List[PstnChannel]] = None |
61 | | - sip: Optional[List[SipChannel]] = None |
62 | | - websocket: Optional[List[WebsocketChannel]] = None |
63 | | - vbc: Optional[List[VbcChannel]] = None |
| 59 | + @field_validator('status_url') |
| 60 | + @classmethod |
| 61 | + def check_http_method(cls, v: Url): |
| 62 | + if v.http_method is not None and v.http_method != 'POST': |
| 63 | + raise ApplicationError('HTTP method must be POST') |
| 64 | + return v |
64 | 65 |
|
65 | 66 |
|
66 | | -class Properties(BaseModel): |
67 | | - custom_data: Optional[dict] = None |
| 67 | +class Verify(BaseModel): |
| 68 | + webhooks: Optional[VerifyWebhooks] = None |
| 69 | + version: Optional[str] = None |
68 | 70 |
|
69 | 71 |
|
70 | | -class User(BaseModel): |
71 | | - name: Optional[str] = None |
72 | | - display_name: Optional[str] = None |
73 | | - image_url: Optional[str] = None |
74 | | - channels: Optional[Channels] = None |
75 | | - properties: Optional[Properties] = None |
76 | | - links: Optional[ResourceLink] = Field(None, validation_alias='_links', exclude=True) |
77 | | - link: Optional[str] = None |
78 | | - id: Optional[str] = None |
| 72 | +class Privacy(BaseModel): |
| 73 | + improve_ai: Optional[bool] = None |
79 | 74 |
|
80 | | - @model_validator(mode='after') |
81 | | - def get_link(self): |
82 | | - if self.links is not None: |
83 | | - self.link = self.links.self.href |
84 | | - return self |
| 75 | + |
| 76 | +class ApplicationBase(BaseModel): |
| 77 | + name: str |
| 78 | + capabilities: Optional[Union[Voice, Rtc, Messages, Vbc, Verify]] = None |
| 79 | + privacy: Optional[Privacy] = None |
0 commit comments