Skip to content

Commit 5819ed3

Browse files
committed
finish ncco testing, start with voice endpoints
1 parent ff25ff3 commit 5819ed3

File tree

20 files changed

+380
-536
lines changed

20 files changed

+380
-536
lines changed

pants.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ filter = [
4040
'testutils',
4141
'verify/src',
4242
'verify_v2/src',
43+
'voice/src',
4344
'vonage_utils/src',
4445
]
4546

users/src/vonage_users/responses.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ class UserSummary(BaseModel):
2020

2121
@model_validator(mode='after')
2222
@classmethod
23-
def get_link(cls, data):
24-
if data.links is not None:
25-
data.link = data.links.self.href
26-
return data
23+
def get_link(self):
24+
if self.links is not None:
25+
self.link = self.links.self.href
26+
return self
2727

2828

2929
class Embedded(BaseModel):

voice/src/vonage_voice/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
from .enums import Channel, ConnectEndpointType, NccoActionType
1111
from .input_types import Dtmf, Speech
1212
from .ncco import Connect, Conversation, Input, NccoAction, Notify, Record, Stream, Talk
13-
from .requests import Call, NccoAction, Phone, Sip, ToPhone, Vbc, Websocket
13+
from .requests import CreateCallRequest, Phone, Sip, ToPhone, Vbc, Websocket
1414
from .responses import CallStatus, CreateCallResponse
1515

1616
__all__ = [
1717
'AdvancedMachineDetection',
18-
'Call',
18+
'CreateCallRequest',
1919
'ToPhone',
2020
'Sip',
2121
'Websocket',

voice/src/vonage_voice/models/enums.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,17 @@ class ConnectEndpointType(str, Enum):
2424
WEBSOCKET = 'websocket'
2525
SIP = 'sip'
2626
VBC = 'vbc'
27+
28+
29+
class CallStatus(str, Enum):
30+
STARTED = 'started'
31+
RINGING = 'ringing'
32+
ANSWERED = 'answered'
33+
MACHINE = 'machine'
34+
COMPLETED = 'completed'
35+
BUSY = 'busy'
36+
CANCELLED = 'cancelled'
37+
FAILED = 'failed'
38+
REJECTED = 'rejected'
39+
TIMEOUT = 'timeout'
40+
UNANSWERED = 'unanswered'

voice/src/vonage_voice/models/ncco.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List, Optional, Union
1+
from typing import Annotated, List, Optional, Union
22

33
from pydantic import BaseModel, Field, model_validator
44
from typing_extensions import Literal
@@ -138,17 +138,6 @@ class Input(NccoAction):
138138
eventMethod: Optional[str] = None
139139
action: NccoActionType = NccoActionType.INPUT
140140

141-
@model_validator(mode='after')
142-
def validate_objects_provided(self):
143-
if 'dtmf' in self.type and self.dtmf is None:
144-
raise NccoActionError(
145-
'`dtmf` object must be provided if `dtmf` is in the `type` array.'
146-
)
147-
if 'speech' in self.type and self.speech is None:
148-
raise NccoActionError(
149-
'`speech` object must be provided if `speech` is in the `type` array.'
150-
)
151-
152141

153142
class Notify(NccoAction):
154143
"""Use the notify action to send a custom payload to your event URL."""

voice/src/vonage_voice/models/requests.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
from ..errors import VoiceError
77
from .common import AdvancedMachineDetection
8-
from .enums import Channel
9-
from .ncco import NccoAction
8+
from .enums import CallStatus, Channel
9+
from .ncco import Record, Conversation, Connect, Input, Talk, Stream, Notify
1010

1111

1212
class Phone(BaseModel):
@@ -37,11 +37,12 @@ class Vbc(BaseModel):
3737
type: Channel = Channel.VBC
3838

3939

40-
class Call(BaseModel):
41-
ncco: List[NccoAction] = None
40+
class CreateCallRequest(BaseModel):
41+
ncco: List[Union[Record, Conversation, Connect, Input, Talk, Stream, Notify]] = None
4242
answer_url: List[str] = None
4343
answer_method: Optional[Literal['POST', 'GET']] = None
4444
to: List[Union[ToPhone, Sip, Websocket, Vbc]]
45+
4546
from_: Optional[Phone] = Field(None, serialization_alias='from')
4647
random_from_number: Optional[bool] = None
4748
event_url: Optional[List[str]] = None
@@ -57,12 +58,6 @@ def validate_ncco_and_answer_url(self):
5758
raise VoiceError('Either `ncco` or `answer_url` must be set')
5859
if self.ncco is not None and self.answer_url is not None:
5960
raise VoiceError('`ncco` and `answer_url` cannot be used together')
60-
if (
61-
self.ncco is not None
62-
and self.answer_url is None
63-
and self.answer_method is not None
64-
):
65-
self.answer_method = None
6661
return self
6762

6863
@model_validator(mode='after')
@@ -72,3 +67,13 @@ def validate_from_and_random_from_number(self):
7267
if self.random_from_number == True and self.from_ is not None:
7368
raise VoiceError('`from_` and `random_from_number` cannot be used together')
7469
return self
70+
71+
72+
class ListCallsFilter(BaseModel):
73+
status: Optional[CallStatus] = None
74+
date_start: Optional[str] = None
75+
date_end: Optional[str] = None
76+
page_size: Optional[int] = Field(None, ge=1, le=100)
77+
record_index: Optional[int] = None
78+
order: Optional[Literal['asc', 'desc']] = None
79+
conversation_uuid: Optional[str] = None

voice/src/vonage_voice/models/responses.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from pydantic import BaseModel
1+
from typing import List, Optional
2+
from pydantic import BaseModel, Field, model_validator
23

34

45
class CreateCallResponse(BaseModel):
@@ -11,3 +12,54 @@ class CreateCallResponse(BaseModel):
1112
class CallStatus(BaseModel):
1213
message: str
1314
uuid: str
15+
16+
17+
class Link(BaseModel):
18+
href: str
19+
20+
21+
class Links(BaseModel):
22+
self: Link
23+
first: Optional[Link] = None
24+
next: Optional[Link] = None
25+
prev: Optional[Link] = None
26+
27+
28+
class Endpoint(BaseModel):
29+
type: str
30+
number: str
31+
32+
33+
class CallInfo(BaseModel):
34+
uuid: str
35+
conversation_uuid: str
36+
to: Endpoint
37+
from_: Endpoint = Field(..., alias='from')
38+
status: str
39+
direction: str
40+
rate: Optional[str] = None
41+
price: Optional[str] = None
42+
duration: Optional[str] = None
43+
start_time: Optional[str] = None
44+
end_time: Optional[str] = None
45+
network: Optional[str] = None
46+
links: Links = Field(..., validation_alias='_links', exclude=True)
47+
link: Optional[str] = None
48+
49+
@model_validator(mode='after')
50+
@classmethod
51+
def get_link(self):
52+
self.link = self.links.self.href
53+
return self
54+
55+
56+
class Embedded(BaseModel):
57+
calls: List[CallInfo]
58+
59+
60+
class CallList(BaseModel):
61+
count: int
62+
page_size: int
63+
record_index: int
64+
embedded: Embedded = Field(..., validation_alias='_embedded')
65+
links: Links = Field(..., validation_alias='_links')

voice/src/vonage_voice/voice.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from pydantic import validate_call
22
from vonage_http_client.http_client import HttpClient
33

4-
from .models.requests import Call
5-
from .models.responses import CreateCallResponse
4+
from .models.requests import CreateCallRequest, ListCallsFilter
5+
from .models.responses import CallInfo, CallList, CreateCallResponse
66

77

88
class Voice:
@@ -12,11 +12,11 @@ def __init__(self, http_client: HttpClient) -> None:
1212
self._http_client = http_client
1313

1414
@validate_call
15-
def create_call(self, params: Call) -> CreateCallResponse:
15+
def create_call(self, params: CreateCallRequest) -> CreateCallResponse:
1616
"""Creates a new call using the Vonage Voice API.
1717
1818
Args:
19-
params (Call): The parameters for the call.
19+
params (CreateCallRequest): The parameters for the call.
2020
2121
Returns:
2222
CreateCallResponse: The response object containing information about the created call.
@@ -28,3 +28,37 @@ def create_call(self, params: Call) -> CreateCallResponse:
2828
)
2929

3030
return CreateCallResponse(**response)
31+
32+
@validate_call
33+
def list_calls(self, params: ListCallsFilter = None) -> CallList:
34+
"""Lists calls made with the Vonage Voice API.
35+
36+
Args:
37+
params (ListCallsFilter): The parameters to filter the list of calls.
38+
39+
Returns:
40+
CallList: The response object containing information about the calls.
41+
"""
42+
response = self._http_client.get(
43+
self._http_client.api_host,
44+
'/v1/calls',
45+
params.model_dump(by_alias=True, exclude_none=True) if params else None,
46+
)
47+
48+
return CallList(**response)
49+
50+
@validate_call
51+
def get_call(self, call_id: str) -> CallInfo:
52+
"""Gets a call by ID.
53+
54+
Args:
55+
call_id (str): The ID of the call to retrieve.
56+
57+
Returns:
58+
CallInfo: Object with information about the call.
59+
"""
60+
response = self._http_client.get(
61+
self._http_client.api_host, f'/v1/calls/{call_id}'
62+
)
63+
64+
return CallInfo(**response)

voice/tests/_test_models.py

Lines changed: 0 additions & 138 deletions
This file was deleted.

0 commit comments

Comments
 (0)