Skip to content

Commit

Permalink
finish adding NCCO actions and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkahan committed Apr 17, 2024
1 parent 5e7d13e commit ff25ff3
Show file tree
Hide file tree
Showing 12 changed files with 564 additions and 202 deletions.
4 changes: 0 additions & 4 deletions messages/tests/BUILD
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
python_tests(dependencies=['messages', 'testutils'])

python_sources(
name="tests0",
)
15 changes: 15 additions & 0 deletions voice/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,18 @@ This package contains the code to use [Vonage's Voice API](https://developer.von
It is recommended to use this as part of the main `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`.

### Create a Call


### Note on URLs

The Voice API requires most URLs to be passed in a list with only one element. When creating models, simply pass the url and the model will marshal it into the correct structure for you.

e.g.

```python
# Don't do this


# Do this

```
1 change: 1 addition & 0 deletions voice/src/vonage_voice/models/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python_sources()
45 changes: 45 additions & 0 deletions voice/src/vonage_voice/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from .common import AdvancedMachineDetection
from .connect_endpoints import (
AppEndpoint,
OnAnswer,
PhoneEndpoint,
SipEndpoint,
VbcEndpoint,
WebsocketEndpoint,
)
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 .responses import CallStatus, CreateCallResponse

__all__ = [
'AdvancedMachineDetection',
'Call',
'ToPhone',
'Sip',
'Websocket',
'Vbc',
'Phone',
'NccoAction',
'Channel',
'NccoActionType',
'ConnectEndpointType',
'OnAnswer',
'PhoneEndpoint',
'AppEndpoint',
'WebsocketEndpoint',
'SipEndpoint',
'VbcEndpoint',
'Dtmf',
'Speech',
'CreateCallResponse',
'CallStatus',
'Record',
'Conversation',
'Connect',
'Talk',
'Stream',
'Input',
'Notify',
]
2 changes: 1 addition & 1 deletion voice/src/vonage_voice/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@

class AdvancedMachineDetection(BaseModel):
behavior: Optional[Literal['continue', 'hangup']] = None
mode: Optional[Literal['default', 'detect', 'detect_beep']] = 'detect'
mode: Optional[Literal['default', 'detect', 'detect_beep']] = None
beep_timeout: Optional[int] = Field(None, ge=45, le=120)
32 changes: 14 additions & 18 deletions voice/src/vonage_voice/models/connect_endpoints.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,44 @@
from pydantic import BaseModel, AnyUrl, Field
from typing import Optional
from typing_extensions import Literal

from .enums import ConnectEndpointType

from pydantic import BaseModel, Field
from typing_extensions import Literal
from vonage_utils.types import Dtmf, PhoneNumber, SipUri


class BaseEndpoint(BaseModel):
"""Base Endpoint model for use with the NCCO Connect action."""
from .enums import ConnectEndpointType


class OnAnswer(BaseModel):
url: AnyUrl
ringbackTone: Optional[AnyUrl] = None
url: str
ringbackTone: Optional[str] = None


class PhoneEndpoint(BaseEndpoint):
class PhoneEndpoint(BaseModel):
number: PhoneNumber
dtmfAnswer: Optional[Dtmf] = None
onAnswer: Optional[OnAnswer] = None
type: ConnectEndpointType = ConnectEndpointType.PHONE


class AppEndpoint(BaseEndpoint):
class AppEndpoint(BaseModel):
user: str
type: ConnectEndpointType = ConnectEndpointType.APP


class WebsocketEndpoint(BaseEndpoint):
uri: AnyUrl
class WebsocketEndpoint(BaseModel):
uri: str
contentType: Literal['audio/l16;rate=16000', 'audio/l16;rate=8000'] = Field(
'audio/l16;rate=16000', serialization_alias='content-type'
None, serialization_alias='content-type'
)
headers: Optional[dict] = {}
headers: Optional[dict] = None
type: ConnectEndpointType = ConnectEndpointType.WEBSOCKET


class SipEndpoint(BaseEndpoint):
class SipEndpoint(BaseModel):
uri: SipUri
headers: Optional[dict] = {}
headers: Optional[dict] = None
type: ConnectEndpointType = ConnectEndpointType.SIP


class VbcEndpoint(BaseEndpoint):
class VbcEndpoint(BaseModel):
extension: str
type: ConnectEndpointType = ConnectEndpointType.VBC
6 changes: 3 additions & 3 deletions voice/src/vonage_voice/models/enums.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from enum import Enum


class Channel(Enum, str):
class Channel(str, Enum):
PHONE = 'phone'
SIP = 'sip'
WEBSOCKET = 'websocket'
VBC = 'vbc'


class NccoActionType(Enum, str):
class NccoActionType(str, Enum):
RECORD = 'record'
CONVERSATION = 'conversation'
CONNECT = 'connect'
Expand All @@ -18,7 +18,7 @@ class NccoActionType(Enum, str):
NOTIFY = 'notify'


class ConnectEndpointType(Enum, str):
class ConnectEndpointType(str, Enum):
PHONE = 'phone'
APP = 'app'
WEBSOCKET = 'websocket'
Expand Down
36 changes: 15 additions & 21 deletions voice/src/vonage_voice/models/input_types.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
from pydantic import BaseModel, confloat, conint
from typing import Optional, List
from typing import List, Optional

from pydantic import BaseModel, Field

class InputTypes:
class Dtmf(BaseModel):
timeOut: Optional[conint(ge=0, le=10)]
maxDigits: Optional[conint(ge=1, le=20)]
submitOnHash: Optional[bool]

class Speech(BaseModel):
uuid: Optional[str]
endOnSilence: Optional[confloat(ge=0.4, le=10.0)]
language: Optional[str]
context: Optional[List[str]]
startTimeout: Optional[conint(ge=1, le=60)]
maxDuration: Optional[conint(ge=1, le=60)]
saveAudio: Optional[bool]
class Dtmf(BaseModel):
timeOut: Optional[int] = Field(None, ge=0, le=10)
maxDigits: Optional[int] = Field(None, ge=1, le=20)
submitOnHash: Optional[bool] = None

@classmethod
def create_dtmf_model(cls, dict) -> Dtmf:
return cls.Dtmf.parse_obj(dict)

@classmethod
def create_speech_model(cls, dict) -> Speech:
return cls.Speech.parse_obj(dict)
class Speech(BaseModel):
uuid: Optional[List[str]] = None
endOnSilence: Optional[float] = Field(None, ge=0.4, le=10.0)
language: Optional[str] = None
context: Optional[List[str]] = None
startTimeout: Optional[int] = Field(None, ge=1, le=60)
maxDuration: Optional[int] = Field(None, ge=1, le=60)
saveAudio: Optional[bool] = False
sensitivity: Optional[int] = Field(None, ge=0, le=100)
Loading

0 comments on commit ff25ff3

Please sign in to comment.