Skip to content

Commit

Permalink
add more voice methods
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkahan committed Apr 22, 2024
1 parent 016e34c commit c8e2f69
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 24 deletions.
14 changes: 13 additions & 1 deletion http_client/src/vonage_http_client/http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ def patch(
'PATCH', host, request_path, params, auth_type, sent_data_type
)

def put(
self,
host: str,
request_path: str = '',
params: dict = None,
auth_type: Literal['jwt', 'basic', 'body', 'signature'] = 'jwt',
sent_data_type: Literal['json', 'form', 'query_params'] = 'json',
) -> Union[dict, None]:
return self.make_request(
'PUT', host, request_path, params, auth_type, sent_data_type
)

def delete(
self,
host: str,
Expand All @@ -176,7 +188,7 @@ def delete(
@validate_call
def make_request(
self,
request_type: Literal['GET', 'POST', 'PATCH', 'DELETE'],
request_type: Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE'],
host: str,
request_path: str = '',
params: Optional[dict] = None,
Expand Down
2 changes: 1 addition & 1 deletion testutils/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def _filter_none_values(data: dict) -> dict:
@validate_call
def build_response(
file_path: str,
method: Literal['GET', 'POST', 'PATCH', 'DELETE'],
method: Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE'],
url: str,
mock_path: str = None,
status_code: int = 200,
Expand Down
6 changes: 1 addition & 5 deletions voice/src/vonage_voice/models/common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Literal, Optional

from pydantic import BaseModel, Field
from vonage_utils.types import Dtmf, PhoneNumber, SipUri
from vonage_utils.types import PhoneNumber, SipUri
from vonage_voice.models.enums import Channel


Expand All @@ -10,10 +10,6 @@ class Phone(BaseModel):
type: Channel = Channel.PHONE


class ToPhone(Phone):
dtmf_answer: Optional[Dtmf] = Field(None, serialization_alias='dtmfAnswer')


class Sip(BaseModel):
uri: SipUri
type: Channel = Channel.SIP
Expand Down
2 changes: 1 addition & 1 deletion voice/src/vonage_voice/models/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ConnectEndpointType(str, Enum):
VBC = 'vbc'


class CallStatus(str, Enum):
class CallState(str, Enum):
STARTED = 'started'
RINGING = 'ringing'
ANSWERED = 'answered'
Expand Down
12 changes: 9 additions & 3 deletions voice/src/vonage_voice/models/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

from pydantic import BaseModel, Field, model_validator

from vonage_utils.types import Dtmf

from ..errors import VoiceError
from .common import AdvancedMachineDetection, Phone, Sip, ToPhone, Vbc, Websocket
from .enums import CallStatus
from .common import AdvancedMachineDetection, Phone, Sip, Vbc, Websocket
from .enums import CallState
from .ncco import Connect, Conversation, Input, Notify, Record, Stream, Talk


class ToPhone(Phone):
dtmf_answer: Optional[Dtmf] = Field(None, serialization_alias='dtmfAnswer')


class CreateCallRequest(BaseModel):
ncco: List[Union[Record, Conversation, Connect, Input, Talk, Stream, Notify]] = None
answer_url: List[str] = None
Expand Down Expand Up @@ -41,7 +47,7 @@ def validate_from_and_random_from_number(self):


class ListCallsFilter(BaseModel):
status: Optional[CallStatus] = None
status: Optional[CallState] = None
date_start: Optional[str] = None
date_end: Optional[str] = None
page_size: Optional[int] = Field(100, ge=1, le=100)
Expand Down
6 changes: 3 additions & 3 deletions voice/src/vonage_voice/models/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from pydantic import BaseModel, Field, model_validator
from vonage_utils.models import Link

from .common import Phone, Sip, ToPhone, Vbc, Websocket
from .common import Phone, Sip, Vbc, Websocket


class CreateCallResponse(BaseModel):
Expand All @@ -13,7 +13,7 @@ class CreateCallResponse(BaseModel):
conversation_uuid: str


class CallStatus(BaseModel):
class CallMessage(BaseModel):
message: str
uuid: str

Expand All @@ -29,7 +29,7 @@ class Links(BaseModel):
class CallInfo(BaseModel):
uuid: str
conversation_uuid: str
to: ToPhone
to: Phone
from_: Union[Phone, Sip, Websocket, Vbc] = Field(..., validation_alias='from')
status: str
direction: str
Expand Down
87 changes: 86 additions & 1 deletion voice/src/vonage_voice/voice.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

from pydantic import validate_call
from vonage_http_client.http_client import HttpClient
from vonage_voice.models.ncco import NccoAction

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


class Voice:
Expand Down Expand Up @@ -72,3 +73,87 @@ def get_call(self, call_id: str) -> CallInfo:
)

return CallInfo(**response)

@validate_call
def transfer_call_ncco(self, uuid: str, ncco: List[NccoAction]) -> None:
"""Transfers a call to a new NCCO.
Args:
uuid (str): The UUID of the call to transfer.
ncco (List[NccoAction]): The new NCCO to transfer the call to.
"""
serializable_ncco = [
action.model_dump(by_alias=True, exclude_none=True) for action in ncco
]
self._http_client.put(
self._http_client.api_host,
f'/v1/calls/{uuid}',
{
'action': 'transfer',
'destination': {'type': 'ncco', 'ncco': serializable_ncco},
},
)

@validate_call
def transfer_call_answer_url(self, uuid: str, answer_url: str) -> None:
"""Transfers a call to a new answer URL.
Args:
uuid (str): The UUID of the call to transfer.
answer_url (str): The new answer URL to transfer the call to.
"""
self._http_client.put(
self._http_client.api_host,
f'/v1/calls/{uuid}',
{'action': 'transfer', 'destination': {'type': 'ncco', 'url': [answer_url]}},
)

def hangup(self, uuid: str) -> None:
"""Ends the call for the specified UUID, removing them from it.
Args:
uuid (str): The UUID to end the call for.
"""
self._http_client.put(
self._http_client.api_host, f'/v1/calls/{uuid}', {'action': 'hangup'}
)

def mute(self, uuid: str) -> None:
"""Mutes a call for the specified UUID.
Args:
uuid (str): The UUID to mute the call for.
"""
self._http_client.put(
self._http_client.api_host, f'/v1/calls/{uuid}', {'action': 'mute'}
)

def unmute(self, uuid: str) -> None:
"""Unmutes a call for the specified UUID.
Args:
uuid (str): The UUID to unmute the call for.
"""
self._http_client.put(
self._http_client.api_host, f'/v1/calls/{uuid}', {'action': 'unmute'}
)

def earmuff(self, uuid: str) -> None:
"""Earmuffs a call for the specified UUID (prevents them from hearing audio).
Args:
uuid (str): The UUID you want to prevent from hearing audio.
"""
self._http_client.put(
self._http_client.api_host, f'/v1/calls/{uuid}', {'action': 'earmuff'}
)

def unearmuff(self, uuid: str) -> None:
"""Allows the specified UUID to hear audio.
Args:
uuid (str): The UUID you want to to allow to hear audio.
"""
self._http_client.put(
self._http_client.api_host, f'/v1/calls/{uuid}', {'action': 'unearmuff'}
)
25 changes: 25 additions & 0 deletions voice/tests/data/get_call.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"_links": {
"self": {
"href": "/v1/calls/e154eb57-2962-41e7-baf4-90f63e25e439"
}
},
"conversation_uuid": "CON-d4e1389a-b2c8-4621-97eb-c6f3a2b51c72",
"direction": "outbound",
"duration": "2",
"end_time": "2024-04-19T01:34:20.000Z",
"from": {
"number": "9876543210",
"type": "phone"
},
"network": "23420",
"price": "0.00333333",
"rate": "0.10000000",
"start_time": "2024-04-19T01:34:18.000Z",
"status": "completed",
"to": {
"number": "1234567890",
"type": "phone"
},
"uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
}
File renamed without changes.
Loading

0 comments on commit c8e2f69

Please sign in to comment.