Skip to content

Commit 47ce0f8

Browse files
committed
start creating application package
1 parent 5f6667d commit 47ce0f8

File tree

15 files changed

+545
-0
lines changed

15 files changed

+545
-0
lines changed

application/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
resource(name='pyproject', source='pyproject.toml')
2+
file(name='readme', source='README.md')
3+
4+
files(sources=['tests/data/*'])
5+
6+
python_distribution(
7+
name='vonage-application',
8+
dependencies=[
9+
':pyproject',
10+
':readme',
11+
'application/src/vonage_application',
12+
],
13+
provides=python_artifact(),
14+
generate_setup=False,
15+
repositories=['@pypi'],
16+
)

application/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# 1.0.0
2+
- Initial upload

application/README.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Vonage Users Package
2+
3+
This package contains the code to use Vonage's Application API in Python.
4+
5+
It includes methods for managing applications.
6+
7+
## Usage
8+
9+
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`.
10+
11+
--------------
12+
--------------
13+
--------------
14+
--------------
15+
--------------
16+
--------------
17+
--------------
18+
--------------
19+
--------------
20+
--------------
21+
--------------
22+
--------------
23+
--------------
24+
--------------
25+
--------------
26+
27+
### List Users
28+
29+
With no custom options specified, this method will get the last 100 users. It returns a tuple consisting of a list of `UserSummary` objects and a string describing the cursor to the next page of results.
30+
31+
```python
32+
from vonage_users import ListUsersRequest
33+
34+
users, _ = vonage_client.users.list_users()
35+
36+
# With options
37+
params = ListUsersRequest(
38+
page_size=10,
39+
cursor=my_cursor,
40+
order='desc',
41+
)
42+
users, next_cursor = vonage_client.users.list_users(params)
43+
```
44+
45+
### Create a New User
46+
47+
```python
48+
from vonage_users import User, Channels, SmsChannel
49+
user_options = User(
50+
name='my_user_name',
51+
display_name='My User Name',
52+
properties={'custom_key': 'custom_value'},
53+
channels=Channels(sms=[SmsChannel(number='1234567890')]),
54+
)
55+
user = vonage_client.users.create_user(user_options)
56+
```
57+
58+
### Get a User
59+
60+
```python
61+
user = client.users.get_user('USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b')
62+
user_as_dict = user.model_dump(exclude_none=True)
63+
```
64+
65+
### Update a User
66+
```python
67+
from vonage_users import User, Channels, SmsChannel, WhatsappChannel
68+
user_options = User(
69+
name='my_user_name',
70+
display_name='My User Name',
71+
properties={'custom_key': 'custom_value'},
72+
channels=Channels(sms=[SmsChannel(number='1234567890')], whatsapp=[WhatsappChannel(number='9876543210')]),
73+
)
74+
user = vonage_client.users.update_user(id, user_options)
75+
```
76+
77+
### Delete a User
78+
79+
```python
80+
vonage_client.users.delete_user(id)
81+
```

application/pyproject.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[project]
2+
name = 'vonage-application'
3+
version = '1.0.0'
4+
description = 'Vonage Users package'
5+
readme = "README.md"
6+
authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7+
requires-python = ">=3.8"
8+
dependencies = [
9+
"vonage-http-client>=1.3.1",
10+
"vonage-utils>=1.1.1",
11+
"pydantic>=2.7.1",
12+
]
13+
classifiers = [
14+
"Programming Language :: Python",
15+
"Programming Language :: Python :: 3",
16+
"Programming Language :: Python :: 3.8",
17+
"Programming Language :: Python :: 3.9",
18+
"Programming Language :: Python :: 3.10",
19+
"Programming Language :: Python :: 3.11",
20+
"Programming Language :: Python :: 3.12",
21+
"License :: OSI Approved :: Apache Software License",
22+
]
23+
24+
[project.urls]
25+
homepage = "https://github.com/Vonage/vonage-python-sdk"
26+
27+
[build-system]
28+
requires = ["setuptools>=61.0", "wheel"]
29+
build-backend = "setuptools.build_meta"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python_sources()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .application import Application
2+
3+
__all__ = [
4+
'Application',
5+
]
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from typing import List, Optional, Tuple
2+
3+
from pydantic import validate_call
4+
from vonage_http_client.http_client import HttpClient
5+
6+
from .common import User
7+
from .requests import ApplicationOptions, ListApplicationsFilter
8+
from .responses import ApplicationInfo
9+
10+
11+
class Application:
12+
"""Class containing methods for Vonage Application management."""
13+
14+
def __init__(self, http_client: HttpClient) -> None:
15+
self._http_client = http_client
16+
self._auth_type = 'basic'
17+
18+
@property
19+
def http_client(self) -> HttpClient:
20+
"""The HTTP client used to make requests to the Users API.
21+
22+
Returns:
23+
HttpClient: The HTTP client used to make requests to the Users API.
24+
"""
25+
return self._http_client
26+
27+
@validate_call
28+
def list_applications(
29+
self, filter: ListApplicationsFilter = ListApplicationsFilter()
30+
) -> Tuple[List[ApplicationInfo], Optional[str]]:
31+
""""""
32+
response = self._http_client.get(
33+
self._http_client.api_host,
34+
'/v2/applications',
35+
filter.model_dump(exclude_none=True),
36+
self._auth_type,
37+
)
38+
39+
# applications_response = ListApplicationsResponse(**response)
40+
# if applications_response.links.next is None:
41+
# return applications_response.embedded.users, None
42+
43+
# parsed_url = urlparse(users_response.links.next.href)
44+
# query_params = parse_qs(parsed_url.query)
45+
# next_cursor = query_params.get('cursor', [None])[0]
46+
# return users_response.embedded.users, next_cursor
47+
48+
@validate_call
49+
def create_application(
50+
self, params: Optional[ApplicationOptions] = None
51+
) -> ApplicationData:
52+
""".
53+
.
54+
"""
55+
response = self._http_client.post(
56+
self._http_client.api_host,
57+
'/v2/applications',
58+
params.model_dump(exclude_none=True) if params is not None else None,
59+
self._auth_type,
60+
)
61+
return User(**response)
62+
63+
@validate_call
64+
def get_user(self, id: str) -> User:
65+
"""Get a user by ID.
66+
67+
Args:
68+
id (str): The ID of the user to retrieve.
69+
70+
Returns:
71+
User: The user object.
72+
"""
73+
response = self._http_client.get(
74+
self._http_client.api_host, f'/v1/users/{id}', None, self._auth_type
75+
)
76+
return User(**response)
77+
78+
@validate_call
79+
def update_user(self, id: str, params: User) -> User:
80+
"""Update a user.
81+
82+
Args:
83+
id (str): The ID of the user to update.
84+
params (User): The updated user object.
85+
86+
Returns:
87+
User: The updated user object.
88+
"""
89+
response = self._http_client.patch(
90+
self._http_client.api_host,
91+
f'/v1/users/{id}',
92+
params.model_dump(exclude_none=True),
93+
self._auth_type,
94+
)
95+
return User(**response)
96+
97+
@validate_call
98+
def delete_user(self, id: str) -> None:
99+
"""Delete a user.
100+
101+
Args:
102+
id (str): The ID of the user to delete.
103+
104+
Returns:
105+
None
106+
"""
107+
self._http_client.delete(
108+
self._http_client.api_host, f'/v1/users/{id}', None, self._auth_type
109+
)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from typing import List, Optional
2+
3+
from pydantic import BaseModel, Field, model_validator
4+
from vonage_utils.models import Link
5+
from vonage_utils.types import PhoneNumber
6+
7+
8+
class ResourceLink(BaseModel):
9+
self: Link
10+
11+
12+
class PstnChannel(BaseModel):
13+
number: int
14+
15+
16+
class SipChannel(BaseModel):
17+
uri: str = Field(..., pattern=r'^(sip|sips):\+?([\w|:.\-@;,=%&]+)')
18+
username: str = None
19+
password: str = None
20+
21+
22+
class VbcChannel(BaseModel):
23+
extension: str
24+
25+
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+
33+
34+
class SmsChannel(BaseModel):
35+
number: PhoneNumber
36+
37+
38+
class MmsChannel(BaseModel):
39+
number: PhoneNumber
40+
41+
42+
class WhatsappChannel(BaseModel):
43+
number: PhoneNumber
44+
45+
46+
class ViberChannel(BaseModel):
47+
number: PhoneNumber
48+
49+
50+
class MessengerChannel(BaseModel):
51+
id: str
52+
53+
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
64+
65+
66+
class Properties(BaseModel):
67+
custom_data: Optional[dict] = None
68+
69+
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
79+
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

0 commit comments

Comments
 (0)