Skip to content

Commit 442751e

Browse files
authored
Merge pull request #128 from CiscoDevNet/feature-127
#127 Update the existing Webex Teams API wrappers and data models
2 parents 27178df + 80056c5 commit 442751e

14 files changed

+303
-103
lines changed

docs/user/api_structure_table.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
| | | :meth:`delete() <webeteamssdk.api.memberships.MembershipsAPI.delete>` |
2323
+------------------------+---------------------------+---------------------------------------------------------------------------------+
2424
| | :ref:`messages` | :meth:`list() <webeteamssdk.api.messages.MessagesAPI.list>` |
25+
| | | :meth:`list_direct() <webeteamssdk.api.messages.MessagesAPI.list_direct>` |
2526
| | | :meth:`create() <webeteamssdk.api.messages.MessagesAPI.create>` |
2627
| | | :meth:`get() <webeteamssdk.api.messages.MessagesAPI.get>` |
2728
| | | :meth:`delete() <webeteamssdk.api.messages.MessagesAPI.delete>` |

tests/api/test_messages.py

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def adaptive_card():
5757

5858

5959
@pytest.fixture(scope="session")
60-
def direct_message_by_email(api, test_people):
60+
def direct_message_by_person_email(api, test_people):
6161
person = test_people["member_added_by_email"]
6262
message = api.messages.create(
6363
toPersonEmail=person.emails[0],
@@ -69,6 +69,16 @@ def direct_message_by_email(api, test_people):
6969
api.messages.delete(message.id)
7070

7171

72+
@pytest.fixture(scope="session")
73+
def direct_message_reply_by_person_email(api, direct_message_by_person_email):
74+
text = create_string("Reply Message")
75+
return api.messages.create(
76+
toPersonEmail=direct_message_by_person_email.toPersonEmail,
77+
parentId=direct_message_by_person_email.id,
78+
text=text,
79+
)
80+
81+
7282
@pytest.fixture(scope="session")
7383
def direct_message_by_email_with_card(api, test_people, adaptive_card):
7484
person = test_people["member_added_by_email"]
@@ -89,7 +99,7 @@ def direct_message_by_email_with_card(api, test_people, adaptive_card):
8999

90100

91101
@pytest.fixture(scope="session")
92-
def direct_message_by_id(api, test_people):
102+
def direct_message_by_person_id(api, test_people):
93103
person = test_people["member_added_by_id"]
94104
message = api.messages.create(
95105
toPersonId=person.id,
@@ -101,6 +111,16 @@ def direct_message_by_id(api, test_people):
101111
api.messages.delete(message.id)
102112

103113

114+
@pytest.fixture(scope="session")
115+
def direct_message_reply_by_person_id(api, direct_message_by_person_id):
116+
text = create_string("Reply Message")
117+
return api.messages.create(
118+
toPersonId=direct_message_by_person_id.toPersonId,
119+
parentId=direct_message_by_person_id.id,
120+
text=text,
121+
)
122+
123+
104124
@pytest.fixture(scope="session")
105125
def send_group_room_message(api):
106126
messages = []
@@ -125,6 +145,16 @@ def group_room_text_message(group_room, send_group_room_message):
125145
return send_group_room_message(group_room.id, text=text)
126146

127147

148+
@pytest.fixture(scope="session")
149+
def group_room_message_reply_by_id(api, group_room, group_room_text_message):
150+
text = create_string("Reply Message")
151+
return api.messages.create(
152+
# roomId=group_room.id,
153+
parentId=group_room_text_message.id,
154+
text=text,
155+
)
156+
157+
128158
@pytest.fixture(scope="session")
129159
def group_room_markdown_message(
130160
me,
@@ -201,13 +231,13 @@ def group_room_messages(
201231

202232
@pytest.fixture(scope="session")
203233
def direct_messages(
204-
direct_message_by_email,
205-
direct_message_by_id,
234+
direct_message_by_person_email,
235+
direct_message_by_person_id,
206236
direct_message_by_email_with_card,
207237
):
208238
return [
209-
direct_message_by_email,
210-
direct_message_by_id,
239+
direct_message_by_person_email,
240+
direct_message_by_person_id,
211241
direct_message_by_email_with_card,
212242
]
213243

@@ -258,8 +288,14 @@ def test_list_messages_mentioning_me(api, group_room,
258288
assert are_valid_messages(messages_list)
259289

260290

261-
def test_create_direct_messages_by_email(direct_message_by_email):
262-
assert is_valid_message(direct_message_by_email)
291+
def test_create_direct_messages_by_email(direct_message_by_person_email):
292+
assert is_valid_message(direct_message_by_person_email)
293+
294+
295+
def test_reply_to_direct_message_by_person_email(
296+
direct_message_reply_by_person_email
297+
):
298+
assert is_valid_message(direct_message_reply_by_person_email)
263299

264300

265301
def test_create_direct_messages_by_email_with_card(
@@ -268,14 +304,39 @@ def test_create_direct_messages_by_email_with_card(
268304
assert is_valid_message(direct_message_by_email_with_card)
269305

270306

271-
def test_create_direct_messages_by_id(direct_message_by_id):
272-
assert is_valid_message(direct_message_by_id)
307+
def test_create_direct_messages_by_id(direct_message_by_person_id):
308+
assert is_valid_message(direct_message_by_person_id)
309+
310+
311+
def test_reply_to_direct_message_by_person_id(
312+
direct_message_reply_by_person_id
313+
):
314+
assert is_valid_message(direct_message_reply_by_person_id)
315+
316+
317+
def test_list_direct_messages_by_person_id(api, direct_message_by_person_id):
318+
messages = api.messages.list_direct(
319+
personId=direct_message_by_person_id.toPersonId,
320+
)
321+
assert are_valid_messages(messages)
322+
323+
324+
def test_list_direct_messages_by_person_email(api,
325+
direct_message_by_person_email):
326+
messages = api.messages.list_direct(
327+
personEmail=direct_message_by_person_email.toPersonEmail,
328+
)
329+
assert are_valid_messages(messages)
273330

274331

275332
def test_create_text_message(group_room_text_message):
276333
assert is_valid_message(group_room_text_message)
277334

278335

336+
def test_create_reply_message(group_room_text_message):
337+
assert is_valid_message(group_room_text_message)
338+
339+
279340
def test_create_markdown_message(group_room_markdown_message):
280341
assert is_valid_message(group_room_markdown_message)
281342

webexteamssdk/api/attachment_actions.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
"""Webex Teams Messages API wrapper.
2+
"""Webex Teams Attachment Actions API wrapper.
33
44
Copyright (c) 2016-2019 Cisco and/or its affiliates.
55
@@ -106,12 +106,11 @@ def create(self, type, messageId, inputs, **request_parameters):
106106
# Return a attachment action object created from the response JSON data
107107
return self._object_factory(OBJECT_TYPE, json_data)
108108

109-
def get(self, attachmentId):
110-
"""Get the details of a attachment action, by ID.
109+
def get(self, id):
110+
"""Get the details for a attachment action, by ID.
111111
112112
Args:
113-
attachmentId(basestring): The ID of the attachment action to be
114-
retrieved.
113+
id(basestring): A unique identifier for the attachment action.
115114
116115
Returns:
117116
AttachmentAction: A Attachment Action object with the details of
@@ -122,10 +121,10 @@ def get(self, attachmentId):
122121
ApiError: If the Webex Teams cloud returns an error.
123122
124123
"""
125-
check_type(attachmentId, basestring)
124+
check_type(id, basestring)
126125

127126
# API request
128-
json_data = self._session.get(API_ENDPOINT + '/' + attachmentId)
127+
json_data = self._session.get(API_ENDPOINT + '/' + id)
129128

130129
# Return a message object created from the response JSON data
131130
return self._object_factory(OBJECT_TYPE, json_data)

webexteamssdk/api/guest_issuer.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
import base64
4848
import requests
4949

50-
API_ENDPOINT = 'jwt'
51-
OBJECT_TYPE = 'guest_issuer_token'
50+
API_ENDPOINT = "jwt"
51+
OBJECT_TYPE = "guest_issuer_token"
5252

5353

5454
class GuestIssuerAPI(object):
@@ -76,46 +76,57 @@ def __init__(self, session, object_factory):
7676
self._session = session
7777
self._object_factory = object_factory
7878

79-
def create(self, subject, displayName, issuerToken, expiration, secret):
79+
def create(self, sub, name, iss, exp, secret):
8080
"""Create a new guest issuer using the provided issuer token.
8181
8282
This function returns a guest issuer with an api access token.
8383
8484
Args:
85-
subject(basestring): Unique and public identifier
86-
displayName(basestring): Display Name of the guest user
87-
issuerToken(basestring): Issuer token from developer hub
88-
expiration(basestring): Expiration time as a unix timestamp
89-
secret(basestring): The secret used to sign your guest issuers
85+
sub(basestring): The subject of the token. This is your unique
86+
and public identifier for the guest user. This claim may
87+
contain only letters, numbers, and hyphens.
88+
name(basestring): The display name of the guest user. This will be
89+
the name shown in Webex Teams clients.
90+
iss(basestring): The issuer of the token. Use the Guest
91+
Issuer ID provided in My Webex Teams Apps.
92+
exp(basestring): The exp time of the token, as a UNIX
93+
timestamp in seconds. Use the lowest practical value for the
94+
use of the token. This is not the exp time for the guest
95+
user's session.
96+
secret(basestring): Use the secret Webex provided you when you
97+
created your Guest Issuer App. The secret will be used to sign
98+
the token request.
9099
91100
Returns:
92-
GuestIssuerToken: A Guest Issuer with a valid access token.
101+
GuestIssuerToken: A Guest Issuer token with a valid access token.
93102
94103
Raises:
95104
TypeError: If the parameter types are incorrect
96105
ApiError: If the webex teams cloud returns an error.
97106
"""
98-
check_type(subject, basestring, optional=True)
99-
check_type(displayName, basestring, optional=True)
100-
check_type(issuerToken, basestring, optional=True)
101-
check_type(expiration, basestring, optional=True)
102-
check_type(secret, basestring, optional=True)
107+
check_type(sub, basestring)
108+
check_type(name, basestring)
109+
check_type(iss, basestring)
110+
check_type(exp, basestring)
111+
check_type(secret, basestring)
103112

104113
payload = {
105-
"sub": subject,
106-
"name": displayName,
107-
"iss": issuerToken,
108-
"exp": expiration
114+
"sub": sub,
115+
"name": name,
116+
"iss": iss,
117+
"exp": exp
109118
}
110119

111120
key = base64.b64decode(secret)
112-
jwt_token = jwt.encode(payload, key, algorithm='HS256')
121+
jwt_token = jwt.encode(payload, key, algorithm="HS256")
113122

114-
url = self._session.base_url + API_ENDPOINT + "/" + "login"
115123
headers = {
116-
'Authorization': "Bearer " + jwt_token.decode('utf-8')
124+
"Authorization": "Bearer " + jwt_token.decode("utf-8")
117125
}
118-
response = requests.post(url, headers=headers)
119-
check_response_code(response, EXPECTED_RESPONSE_CODE['GET'])
120126

121-
return self._object_factory(OBJECT_TYPE, response.json())
127+
json_data = self._session.post(
128+
API_ENDPOINT + "/" + "login",
129+
headers=headers
130+
)
131+
132+
return self._object_factory(OBJECT_TYPE, json_data)

webexteamssdk/api/messages.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def __init__(self, session, object_factory):
7373
self._object_factory = object_factory
7474

7575
@generator_container
76-
def list(self, roomId, mentionedPeople=None, before=None,
77-
beforeMessage=None, max=None, **request_parameters):
76+
def list(self, roomId, parentId=None, mentionedPeople=None, before=None,
77+
beforeMessage=None, max=50, **request_parameters):
7878
"""Lists messages in a room.
7979
8080
Each message will include content attachments if present.
@@ -93,6 +93,7 @@ def list(self, roomId, mentionedPeople=None, before=None,
9393
9494
Args:
9595
roomId(basestring): List messages for a room, by ID.
96+
parentId(basestring): List messages with a parent, by ID.
9697
mentionedPeople(basestring): List messages where the caller is
9798
mentioned by specifying "me" or the caller `personId`.
9899
before(basestring): List messages sent before a date and time, in
@@ -114,6 +115,7 @@ def list(self, roomId, mentionedPeople=None, before=None,
114115
115116
"""
116117
check_type(roomId, basestring)
118+
check_type(parentId, basestring, optional=True)
117119
check_type(mentionedPeople, basestring, optional=True)
118120
check_type(before, basestring, optional=True)
119121
check_type(beforeMessage, basestring, optional=True)
@@ -122,6 +124,7 @@ def list(self, roomId, mentionedPeople=None, before=None,
122124
params = dict_from_items_with_values(
123125
request_parameters,
124126
roomId=roomId,
127+
parentId=parentId,
125128
mentionedPeople=mentionedPeople,
126129
before=before,
127130
beforeMessage=beforeMessage,
@@ -135,9 +138,67 @@ def list(self, roomId, mentionedPeople=None, before=None,
135138
for item in items:
136139
yield self._object_factory(OBJECT_TYPE, item)
137140

138-
def create(self, roomId=None, toPersonId=None, toPersonEmail=None,
139-
text=None, markdown=None, files=None, attachments=None,
140-
parentId=None, **request_parameters):
141+
@generator_container
142+
def list_direct(self, personId=None, personEmail=None, parentId=None,
143+
**request_parameters):
144+
"""List all messages in a 1:1 (direct) room.
145+
146+
Use the `personId` or `personEmail` query parameter to specify the
147+
room.
148+
149+
The list API sorts the messages in descending order by creation date.
150+
151+
This method supports Webex Teams's implementation of RFC5988 Web
152+
Linking to provide pagination support. It returns a generator
153+
container that incrementally yields all messages returned by the
154+
query. The generator will automatically request additional 'pages' of
155+
responses from Webex as needed until all responses have been returned.
156+
The container makes the generator safe for reuse. A new API call will
157+
be made, using the same parameters that were specified when the
158+
generator was created, every time a new iterator is requested from the
159+
container.
160+
161+
Args:
162+
personId(basestring): List messages in a 1:1 room, by person ID.
163+
personEmail(basestring): List messages in a 1:1 room, by person
164+
email.
165+
parentId(basestring): List messages with a parent, by ID.
166+
**request_parameters: Additional request parameters (provides
167+
support for parameters that may be added in the future).
168+
169+
Returns:
170+
GeneratorContainer: A GeneratorContainer which, when iterated,
171+
yields the messages returned by the Webex Teams query.
172+
173+
Raises:
174+
TypeError: If the parameter types are incorrect.
175+
ApiError: If the Webex Teams cloud returns an error.
176+
177+
"""
178+
check_type(personId, basestring, optional=True)
179+
check_type(personEmail, basestring, optional=True)
180+
check_type(parentId, basestring, optional=True)
181+
182+
params = dict_from_items_with_values(
183+
request_parameters,
184+
personId=personId,
185+
personEmail=personEmail,
186+
parentId=parentId,
187+
)
188+
189+
# API request - get items
190+
items = self._session.get_items(
191+
API_ENDPOINT + "/direct",
192+
params=params,
193+
)
194+
195+
# Yield message objects created from the returned items JSON objects
196+
for item in items:
197+
yield self._object_factory(OBJECT_TYPE, item)
198+
199+
def create(self, roomId=None, parentId=None, toPersonId=None,
200+
toPersonEmail=None, text=None, markdown=None, files=None,
201+
attachments=None, **request_parameters):
141202
"""Post a message to a room.
142203
143204
The files parameter is a list, which accepts multiple values to allow

0 commit comments

Comments
 (0)