Skip to content

Commit

Permalink
finish ncco testing, start with voice endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkahan committed Apr 18, 2024
1 parent ff25ff3 commit 5819ed3
Show file tree
Hide file tree
Showing 20 changed files with 380 additions and 536 deletions.
1 change: 1 addition & 0 deletions pants.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ filter = [
'testutils',
'verify/src',
'verify_v2/src',
'voice/src',
'vonage_utils/src',
]

Expand Down
8 changes: 4 additions & 4 deletions users/src/vonage_users/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class UserSummary(BaseModel):

@model_validator(mode='after')
@classmethod
def get_link(cls, data):
if data.links is not None:
data.link = data.links.self.href
return data
def get_link(self):
if self.links is not None:
self.link = self.links.self.href
return self


class Embedded(BaseModel):
Expand Down
4 changes: 2 additions & 2 deletions voice/src/vonage_voice/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
from .enums import Channel, ConnectEndpointType, NccoActionType
from .input_types import Dtmf, Speech
from .ncco import Connect, Conversation, Input, NccoAction, Notify, Record, Stream, Talk
from .requests import Call, NccoAction, Phone, Sip, ToPhone, Vbc, Websocket
from .requests import CreateCallRequest, Phone, Sip, ToPhone, Vbc, Websocket
from .responses import CallStatus, CreateCallResponse

__all__ = [
'AdvancedMachineDetection',
'Call',
'CreateCallRequest',
'ToPhone',
'Sip',
'Websocket',
Expand Down
14 changes: 14 additions & 0 deletions voice/src/vonage_voice/models/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,17 @@ class ConnectEndpointType(str, Enum):
WEBSOCKET = 'websocket'
SIP = 'sip'
VBC = 'vbc'


class CallStatus(str, Enum):
STARTED = 'started'
RINGING = 'ringing'
ANSWERED = 'answered'
MACHINE = 'machine'
COMPLETED = 'completed'
BUSY = 'busy'
CANCELLED = 'cancelled'
FAILED = 'failed'
REJECTED = 'rejected'
TIMEOUT = 'timeout'
UNANSWERED = 'unanswered'
13 changes: 1 addition & 12 deletions voice/src/vonage_voice/models/ncco.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional, Union
from typing import Annotated, List, Optional, Union

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

@model_validator(mode='after')
def validate_objects_provided(self):
if 'dtmf' in self.type and self.dtmf is None:
raise NccoActionError(
'`dtmf` object must be provided if `dtmf` is in the `type` array.'
)
if 'speech' in self.type and self.speech is None:
raise NccoActionError(
'`speech` object must be provided if `speech` is in the `type` array.'
)


class Notify(NccoAction):
"""Use the notify action to send a custom payload to your event URL."""
Expand Down
25 changes: 15 additions & 10 deletions voice/src/vonage_voice/models/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

from ..errors import VoiceError
from .common import AdvancedMachineDetection
from .enums import Channel
from .ncco import NccoAction
from .enums import CallStatus, Channel
from .ncco import Record, Conversation, Connect, Input, Talk, Stream, Notify


class Phone(BaseModel):
Expand Down Expand Up @@ -37,11 +37,12 @@ class Vbc(BaseModel):
type: Channel = Channel.VBC


class Call(BaseModel):
ncco: List[NccoAction] = None
class CreateCallRequest(BaseModel):
ncco: List[Union[Record, Conversation, Connect, Input, Talk, Stream, Notify]] = None
answer_url: List[str] = None
answer_method: Optional[Literal['POST', 'GET']] = None
to: List[Union[ToPhone, Sip, Websocket, Vbc]]

from_: Optional[Phone] = Field(None, serialization_alias='from')
random_from_number: Optional[bool] = None
event_url: Optional[List[str]] = None
Expand All @@ -57,12 +58,6 @@ def validate_ncco_and_answer_url(self):
raise VoiceError('Either `ncco` or `answer_url` must be set')
if self.ncco is not None and self.answer_url is not None:
raise VoiceError('`ncco` and `answer_url` cannot be used together')
if (
self.ncco is not None
and self.answer_url is None
and self.answer_method is not None
):
self.answer_method = None
return self

@model_validator(mode='after')
Expand All @@ -72,3 +67,13 @@ def validate_from_and_random_from_number(self):
if self.random_from_number == True and self.from_ is not None:
raise VoiceError('`from_` and `random_from_number` cannot be used together')
return self


class ListCallsFilter(BaseModel):
status: Optional[CallStatus] = None
date_start: Optional[str] = None
date_end: Optional[str] = None
page_size: Optional[int] = Field(None, ge=1, le=100)
record_index: Optional[int] = None
order: Optional[Literal['asc', 'desc']] = None
conversation_uuid: Optional[str] = None
54 changes: 53 additions & 1 deletion voice/src/vonage_voice/models/responses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pydantic import BaseModel
from typing import List, Optional
from pydantic import BaseModel, Field, model_validator


class CreateCallResponse(BaseModel):
Expand All @@ -11,3 +12,54 @@ class CreateCallResponse(BaseModel):
class CallStatus(BaseModel):
message: str
uuid: str


class Link(BaseModel):
href: str


class Links(BaseModel):
self: Link
first: Optional[Link] = None
next: Optional[Link] = None
prev: Optional[Link] = None


class Endpoint(BaseModel):
type: str
number: str


class CallInfo(BaseModel):
uuid: str
conversation_uuid: str
to: Endpoint
from_: Endpoint = Field(..., alias='from')
status: str
direction: str
rate: Optional[str] = None
price: Optional[str] = None
duration: Optional[str] = None
start_time: Optional[str] = None
end_time: Optional[str] = None
network: Optional[str] = None
links: Links = Field(..., validation_alias='_links', exclude=True)
link: Optional[str] = None

@model_validator(mode='after')
@classmethod
def get_link(self):
self.link = self.links.self.href
return self


class Embedded(BaseModel):
calls: List[CallInfo]


class CallList(BaseModel):
count: int
page_size: int
record_index: int
embedded: Embedded = Field(..., validation_alias='_embedded')
links: Links = Field(..., validation_alias='_links')
42 changes: 38 additions & 4 deletions voice/src/vonage_voice/voice.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from pydantic import validate_call
from vonage_http_client.http_client import HttpClient

from .models.requests import Call
from .models.responses import CreateCallResponse
from .models.requests import CreateCallRequest, ListCallsFilter
from .models.responses import CallInfo, CallList, CreateCallResponse


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

@validate_call
def create_call(self, params: Call) -> CreateCallResponse:
def create_call(self, params: CreateCallRequest) -> CreateCallResponse:
"""Creates a new call using the Vonage Voice API.
Args:
params (Call): The parameters for the call.
params (CreateCallRequest): The parameters for the call.
Returns:
CreateCallResponse: The response object containing information about the created call.
Expand All @@ -28,3 +28,37 @@ def create_call(self, params: Call) -> CreateCallResponse:
)

return CreateCallResponse(**response)

@validate_call
def list_calls(self, params: ListCallsFilter = None) -> CallList:
"""Lists calls made with the Vonage Voice API.
Args:
params (ListCallsFilter): The parameters to filter the list of calls.
Returns:
CallList: The response object containing information about the calls.
"""
response = self._http_client.get(
self._http_client.api_host,
'/v1/calls',
params.model_dump(by_alias=True, exclude_none=True) if params else None,
)

return CallList(**response)

@validate_call
def get_call(self, call_id: str) -> CallInfo:
"""Gets a call by ID.
Args:
call_id (str): The ID of the call to retrieve.
Returns:
CallInfo: Object with information about the call.
"""
response = self._http_client.get(
self._http_client.api_host, f'/v1/calls/{call_id}'
)

return CallInfo(**response)
138 changes: 0 additions & 138 deletions voice/tests/_test_models.py

This file was deleted.

Loading

0 comments on commit 5819ed3

Please sign in to comment.