From 2f2735e4fe19bdf5c9be51dcd852d236100760c0 Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 15:13:40 -0400 Subject: [PATCH 01/11] Update response_codes.py --- webexteamssdk/response_codes.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/webexteamssdk/response_codes.py b/webexteamssdk/response_codes.py index 7897882..b996d7f 100644 --- a/webexteamssdk/response_codes.py +++ b/webexteamssdk/response_codes.py @@ -46,10 +46,14 @@ 409: "The request could not be processed because it conflicts with some " "established rule of the system. For example, a person may not be " "added to a room more than once.", + 410: "The requested resource is no longer available.", 415: "The request was made to a resource without specifying a media type " "or used a media type that is not supported.", + 423: "The requested resource is temporarily unavailable. A `Retry-After` " + "header may be present that specifies how many seconds you need to " + "wait before attempting the request again.", 429: "Too many requests have been sent in a given amount of time and the " - "request has been rate limited. A Retry-After header should be " + "request has been rate limited. A `Retry-After` header should be " "present that specifies how many seconds you need to wait before a " "successful request can be made.", 500: "Something went wrong on the server. If the issue persists, feel " @@ -63,8 +67,8 @@ RATE_LIMIT_RESPONSE_CODE = 429 EXPECTED_RESPONSE_CODE = { - 'GET': 200, - 'POST': 200, - 'PUT': 200, - 'DELETE': 204 + "GET": 200, + "POST": 200, + "PUT": 200, + "DELETE": 204 } From 9d51961880599babb3f51f76a5dc6af9fe60f954 Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 15:29:59 -0400 Subject: [PATCH 02/11] Update attachment_actions.py Rename the paramater ID parameter in the get() method from `attachmentId` to `id` to be consistent with the documentation. --- webexteamssdk/api/attachment_actions.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/webexteamssdk/api/attachment_actions.py b/webexteamssdk/api/attachment_actions.py index 8e4325c..c6f7ae4 100644 --- a/webexteamssdk/api/attachment_actions.py +++ b/webexteamssdk/api/attachment_actions.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Webex Teams Messages API wrapper. +"""Webex Teams Attachment Actions API wrapper. Copyright (c) 2016-2019 Cisco and/or its affiliates. @@ -106,12 +106,11 @@ def create(self, type, messageId, inputs, **request_parameters): # Return a attachment action object created from the response JSON data return self._object_factory(OBJECT_TYPE, json_data) - def get(self, attachmentId): - """Get the details of a attachment action, by ID. + def get(self, id): + """Get the details for a attachment action, by ID. Args: - attachmentId(basestring): The ID of the attachment action to be - retrieved. + id(basestring): A unique identifier for the attachment action. Returns: AttachmentAction: A Attachment Action object with the details of @@ -122,10 +121,10 @@ def get(self, attachmentId): ApiError: If the Webex Teams cloud returns an error. """ - check_type(attachmentId, basestring) + check_type(id, basestring) # API request - json_data = self._session.get(API_ENDPOINT + '/' + attachmentId) + json_data = self._session.get(API_ENDPOINT + '/' + id) # Return a message object created from the response JSON data return self._object_factory(OBJECT_TYPE, json_data) From e9f0d70eadce4fc238fd42b7246c38dfee95f47e Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 16:29:08 -0400 Subject: [PATCH 03/11] Update Guest Issuer API wrapper and token data model - Align the parameter names with those used in the documentation. - Update the docstrings. - The paramaters are mandatory (may not be `None`). - Use the library restsession to submit the request. The supplied headers will me merged-in with the session's default headers; the Authentication header will replace the default Authentication header. --- webexteamssdk/api/guest_issuer.py | 59 +++++++++++-------- .../models/mixins/guest_issuer_token.py | 8 +-- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/webexteamssdk/api/guest_issuer.py b/webexteamssdk/api/guest_issuer.py index b53b3e1..07db8a9 100644 --- a/webexteamssdk/api/guest_issuer.py +++ b/webexteamssdk/api/guest_issuer.py @@ -47,8 +47,8 @@ import base64 import requests -API_ENDPOINT = 'jwt' -OBJECT_TYPE = 'guest_issuer_token' +API_ENDPOINT = "jwt" +OBJECT_TYPE = "guest_issuer_token" class GuestIssuerAPI(object): @@ -76,46 +76,57 @@ def __init__(self, session, object_factory): self._session = session self._object_factory = object_factory - def create(self, subject, displayName, issuerToken, expiration, secret): + def create(self, sub, name, iss, exp, secret): """Create a new guest issuer using the provided issuer token. This function returns a guest issuer with an api access token. Args: - subject(basestring): Unique and public identifier - displayName(basestring): Display Name of the guest user - issuerToken(basestring): Issuer token from developer hub - expiration(basestring): Expiration time as a unix timestamp - secret(basestring): The secret used to sign your guest issuers + sub(basestring): The subject of the token. This is your unique + and public identifier for the guest user. This claim may + contain only letters, numbers, and hyphens. + name(basestring): The display name of the guest user. This will be + the name shown in Webex Teams clients. + iss(basestring): The issuer of the token. Use the Guest + Issuer ID provided in My Webex Teams Apps. + exp(basestring): The exp time of the token, as a UNIX + timestamp in seconds. Use the lowest practical value for the + use of the token. This is not the exp time for the guest + user's session. + secret(basestring): Use the secret Webex provided you when you + created your Guest Issuer App. The secret will be used to sign + the token request. Returns: - GuestIssuerToken: A Guest Issuer with a valid access token. + GuestIssuerToken: A Guest Issuer token with a valid access token. Raises: TypeError: If the parameter types are incorrect ApiError: If the webex teams cloud returns an error. """ - check_type(subject, basestring, optional=True) - check_type(displayName, basestring, optional=True) - check_type(issuerToken, basestring, optional=True) - check_type(expiration, basestring, optional=True) - check_type(secret, basestring, optional=True) + check_type(sub, basestring) + check_type(name, basestring) + check_type(iss, basestring) + check_type(exp, basestring) + check_type(secret, basestring) payload = { - "sub": subject, - "name": displayName, - "iss": issuerToken, - "exp": expiration + "sub": sub, + "name": name, + "iss": iss, + "exp": exp } key = base64.b64decode(secret) - jwt_token = jwt.encode(payload, key, algorithm='HS256') + jwt_token = jwt.encode(payload, key, algorithm="HS256") - url = self._session.base_url + API_ENDPOINT + "/" + "login" headers = { - 'Authorization': "Bearer " + jwt_token.decode('utf-8') + "Authorization": "Bearer " + jwt_token.decode("utf-8") } - response = requests.post(url, headers=headers) - check_response_code(response, EXPECTED_RESPONSE_CODE['GET']) - return self._object_factory(OBJECT_TYPE, response.json()) + json_data = self._session.post( + API_ENDPOINT + "/" + "login", + headers=headers + ) + + return self._object_factory(OBJECT_TYPE, json_data) diff --git a/webexteamssdk/models/mixins/guest_issuer_token.py b/webexteamssdk/models/mixins/guest_issuer_token.py index f35567b..dd97963 100644 --- a/webexteamssdk/models/mixins/guest_issuer_token.py +++ b/webexteamssdk/models/mixins/guest_issuer_token.py @@ -36,9 +36,9 @@ class GuestIssuerTokenBasicPropertiesMixin(object): """Guest issuer token basic properties""" @property - def access_token(self): - return self._json_data.get('token') + def token(self): + return self._json_data.get("token") @property - def expires_in(self): - return self._json_data.get('expiresIn') + def expiresIn(self): + return self._json_data.get("expiresIn") From 21f1afc2dbd5a69038ee9703283ab61de7f0f298 Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 16:40:57 -0400 Subject: [PATCH 04/11] Update the license data model --- webexteamssdk/models/mixins/license.py | 33 ++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/webexteamssdk/models/mixins/license.py b/webexteamssdk/models/mixins/license.py index 6047552..e1c7bfe 100644 --- a/webexteamssdk/models/mixins/license.py +++ b/webexteamssdk/models/mixins/license.py @@ -39,19 +39,44 @@ class LicenseBasicPropertiesMixin(object): @property def id(self): """A unique identifier for the license.""" - return self._json_data.get('id') + return self._json_data.get("id") @property def name(self): """Name of the licensed feature.""" - return self._json_data.get('name') + return self._json_data.get("name") @property def totalUnits(self): """Total number of license units allocated.""" - return self._json_data.get('totalUnits') + return self._json_data.get("totalUnits") @property def consumedUnits(self): """Total number of license units consumed.""" - return self._json_data.get('consumedUnits') + return self._json_data.get("consumedUnits") + + @property + def subscriptionId(self): + """The subscription ID associated with this license. + + This ID is used in other systems, such as Webex Control Hub. + """ + return self._json_data.get("subscriptionId") + + @property + def siteUrl(self): + """The Webex Meetings site associated with this license.""" + return self._json_data.get("siteUrl") + + @property + def siteType(self): + """The type of site associated with this license. + + `Control Hub managed site` the site is managed by Webex Control Hub. + + `Linked site` the site is a linked site + + `Site Admin managed site` the site is managed by Site Administration + """ + return self._json_data.get("siteType") From ede0acd484b119420c8a99bb6dc39d8c8eb747cc Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 17:12:27 -0400 Subject: [PATCH 05/11] Update Messages API - Add the parentId parameter to the messages.list() method. - Add the messages.list_direct() API endpoint. - Update the message data model attributes. --- webexteamssdk/api/messages.py | 71 ++++++++++++++++++++++++-- webexteamssdk/models/mixins/message.py | 59 +++++++++++++++------ 2 files changed, 109 insertions(+), 21 deletions(-) diff --git a/webexteamssdk/api/messages.py b/webexteamssdk/api/messages.py index b0a9916..12b2db8 100644 --- a/webexteamssdk/api/messages.py +++ b/webexteamssdk/api/messages.py @@ -73,8 +73,8 @@ def __init__(self, session, object_factory): self._object_factory = object_factory @generator_container - def list(self, roomId, mentionedPeople=None, before=None, - beforeMessage=None, max=None, **request_parameters): + def list(self, roomId, parentId=None, mentionedPeople=None, before=None, + beforeMessage=None, max=50, **request_parameters): """Lists messages in a room. Each message will include content attachments if present. @@ -93,6 +93,7 @@ def list(self, roomId, mentionedPeople=None, before=None, Args: roomId(basestring): List messages for a room, by ID. + parentId(basestring): List messages with a parent, by ID. mentionedPeople(basestring): List messages where the caller is mentioned by specifying "me" or the caller `personId`. before(basestring): List messages sent before a date and time, in @@ -114,6 +115,7 @@ def list(self, roomId, mentionedPeople=None, before=None, """ check_type(roomId, basestring) + check_type(parentId, basestring, optional=True) check_type(mentionedPeople, basestring, optional=True) check_type(before, basestring, optional=True) check_type(beforeMessage, basestring, optional=True) @@ -122,6 +124,7 @@ def list(self, roomId, mentionedPeople=None, before=None, params = dict_from_items_with_values( request_parameters, roomId=roomId, + parentId=parentId, mentionedPeople=mentionedPeople, before=before, beforeMessage=beforeMessage, @@ -135,9 +138,67 @@ def list(self, roomId, mentionedPeople=None, before=None, for item in items: yield self._object_factory(OBJECT_TYPE, item) - def create(self, roomId=None, toPersonId=None, toPersonEmail=None, - text=None, markdown=None, files=None, attachments=None, - parentId=None, **request_parameters): + @generator_container + def list_direct(self, personId=None, personEmail=None, parentId=None, + **request_parameters): + """List all messages in a 1:1 (direct) room. + + Use the `personId` or `personEmail` query parameter to specify the + room. + + The list API sorts the messages in descending order by creation date. + + This method supports Webex Teams's implementation of RFC5988 Web + Linking to provide pagination support. It returns a generator + container that incrementally yields all messages returned by the + query. The generator will automatically request additional 'pages' of + responses from Webex as needed until all responses have been returned. + The container makes the generator safe for reuse. A new API call will + be made, using the same parameters that were specified when the + generator was created, every time a new iterator is requested from the + container. + + Args: + personId(basestring): List messages in a 1:1 room, by person ID. + personEmail(basestring): List messages in a 1:1 room, by person + email. + parentId(basestring): List messages with a parent, by ID. + **request_parameters: Additional request parameters (provides + support for parameters that may be added in the future). + + Returns: + GeneratorContainer: A GeneratorContainer which, when iterated, + yields the messages returned by the Webex Teams query. + + Raises: + TypeError: If the parameter types are incorrect. + ApiError: If the Webex Teams cloud returns an error. + + """ + check_type(personId, basestring, optional=True) + check_type(personEmail, basestring, optional=True) + check_type(parentId, basestring, optional=True) + + params = dict_from_items_with_values( + request_parameters, + personId=personId, + personEmail=personEmail, + parentId=parentId, + ) + + # API request - get items + items = self._session.get_items( + API_ENDPOINT + "/direct", + params=params, + ) + + # Yield message objects created from the returned items JSON objects + for item in items: + yield self._object_factory(OBJECT_TYPE, item) + + def create(self, roomId=None, parentId=None, toPersonId=None, + toPersonEmail=None, text=None, markdown=None, files=None, + attachments=None, **request_parameters): """Post a message to a room. The files parameter is a list, which accepts multiple values to allow diff --git a/webexteamssdk/models/mixins/message.py b/webexteamssdk/models/mixins/message.py index d4aacd8..c46ae51 100644 --- a/webexteamssdk/models/mixins/message.py +++ b/webexteamssdk/models/mixins/message.py @@ -41,12 +41,17 @@ class MessageBasicPropertiesMixin(object): @property def id(self): """The unique identifier for the message.""" - return self._json_data.get('id') + return self._json_data.get("id") + + @property + def parentId(self): + """The unique identifier for the parent message.""" + return self._json_data.get("parentId") @property def roomId(self): """The room ID of the message.""" - return self._json_data.get('roomId') + return self._json_data.get("roomId") @property def roomType(self): @@ -56,57 +61,79 @@ def roomType(self): `direct`: 1:1 room `group`: Group room """ - return self._json_data.get('roomType') + return self._json_data.get("roomType") + + @property + def toPersonId(self): + """The person ID of the recipient when sending a 1:1 message.""" + return self._json_data.get("toPersonId") + + @property + def toPersonEmail(self): + """The email address of the recipient when sending a 1:1 message.""" + return self._json_data.get("toPersonEmail") @property def text(self): """The message, in plain text.""" - return self._json_data.get('text') + return self._json_data.get("text") @property def markdown(self): """The message, in Markdown format.""" - return self._json_data.get('markdown') + return self._json_data.get("markdown") @property def html(self): - """The message, in HTML format.""" - return self._json_data.get('html') + """The text content of the message, in HTML format. + + This read-only property is used by the Webex Teams clients. + """ + return self._json_data.get("html") @property def files(self): """Public URLs for files attached to the message.""" - return self._json_data.get('files') + return self._json_data.get("files") @property def personId(self): """The person ID of the message author.""" - return self._json_data.get('personId') + return self._json_data.get("personId") @property def personEmail(self): """The email address of the message author.""" - return self._json_data.get('personEmail') + return self._json_data.get("personEmail") @property def mentionedPeople(self): """People IDs for anyone mentioned in the message.""" - return self._json_data.get('mentionedPeople') + return self._json_data.get("mentionedPeople") @property def mentionedGroups(self): """Group names for the groups mentioned in the message.""" - return self._json_data.get('mentionedGroups') + return self._json_data.get("mentionedGroups") @property - def parentId(self): - """The unique identifier for the parent message.""" - return self._json_data.get('parentId') + def attachments(self): + """Message content attachments attached to the message.""" + return self._json_data.get("attachments") @property def created(self): """The date and time the message was created.""" - created = self._json_data.get('created') + created = self._json_data.get("created") + if created: + return WebexTeamsDateTime.strptime(created) + else: + return None + + @property + def updated(self): + """The date and time the message was created.""" + created = self._json_data.get("updated") if created: return WebexTeamsDateTime.strptime(created) else: From b3c1213f98f4fb4b85e7589accbca6fa8328d16a Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 17:21:37 -0400 Subject: [PATCH 06/11] Update People API Docstring updates. --- webexteamssdk/api/people.py | 12 ++++++- webexteamssdk/models/mixins/person.py | 45 ++++++++++++++------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/webexteamssdk/api/people.py b/webexteamssdk/api/people.py index 41f7b8b..ef9cd96 100644 --- a/webexteamssdk/api/people.py +++ b/webexteamssdk/api/people.py @@ -75,7 +75,17 @@ def __init__(self, session, object_factory): @generator_container def list(self, email=None, displayName=None, id=None, orgId=None, max=None, **request_parameters): - """List people + """List people in your organization. + + For most users, either the `email` or `displayName` parameter is + required. Admin users can omit these fields and list all users in their + organization. + + Response properties associated with a user's presence status, such as + `status` or `lastActivity`, will only be displayed for people within + your organization or an organization you manage. Presence information + will not be shown if the authenticated user has disabled status + sharing. This method supports Webex Teams's implementation of RFC5988 Web Linking to provide pagination support. It returns a generator diff --git a/webexteamssdk/models/mixins/person.py b/webexteamssdk/models/mixins/person.py index 6dd50fa..3e013b9 100644 --- a/webexteamssdk/models/mixins/person.py +++ b/webexteamssdk/models/mixins/person.py @@ -41,21 +41,21 @@ class PersonBasicPropertiesMixin(object): @property def id(self): """A unique identifier for the person.""" - return self._json_data.get('id') + return self._json_data.get("id") @property def emails(self): """The email addresses of the person.""" - return self._json_data.get('emails') + return self._json_data.get("emails") def phoneNumbers(self): """Phone numbers for the person.""" - return self._json_data.get('phoneNumbers') + return self._json_data.get("phoneNumbers") @property def displayName(self): """The full name of the person.""" - return self._json_data.get('displayName') + return self._json_data.get("displayName") @property def nickName(self): @@ -64,43 +64,43 @@ def nickName(self): If no nickname is configured for the person, this field will not be present. """ - return self._json_data.get('nickName') + return self._json_data.get("nickName") @property def firstName(self): """The first name of the person.""" - return self._json_data.get('firstName') + return self._json_data.get("firstName") @property def lastName(self): """The last name of the person.""" - return self._json_data.get('lastName') + return self._json_data.get("lastName") @property def avatar(self): - """The URL to the person's avatar in PNG format.""" - return self._json_data.get('avatar') + """The URL to the person"s avatar in PNG format.""" + return self._json_data.get("avatar") @property def orgId(self): """The ID of the organization to which this person belongs.""" - return self._json_data.get('orgId') + return self._json_data.get("orgId") @property def roles(self): """An array of role strings representing the roles to which this person belongs. """ - return self._json_data.get('roles') + return self._json_data.get("roles") @property def licenses(self): """An array of license strings allocated to this person.""" - return self._json_data.get('licenses') + return self._json_data.get("licenses") @property def created(self): """The date and time the person was created.""" - created = self._json_data.get('created') + created = self._json_data.get("created") if created: return WebexTeamsDateTime.strptime(created) else: @@ -109,7 +109,7 @@ def created(self): @property def lastModified(self): """The date and time the person was last changed.""" - last_modified = self._json_data.get('lastModified') + last_modified = self._json_data.get("lastModified") if last_modified: return WebexTeamsDateTime.strptime(last_modified) else: @@ -122,13 +122,13 @@ def timezone(self): If no timezone is configured on the account, this field will not be present. """ - return self._json.get('timezone') + return self._json.get("timezone") @property def lastActivity(self): - """The date and time of the person's last activity within Webex + """The date and time of the person"s last activity within Webex Teams. """ - last_activity = self._json_data.get('lastActivity') + last_activity = self._json_data.get("lastActivity") if last_activity: return WebexTeamsDateTime.strptime(last_activity) else: @@ -160,7 +160,7 @@ def status(self): `unknown`: The user’s status could not be determined """ - return self._json_data.get('status') + return self._json_data.get("status") @property def invitePending(self): @@ -173,7 +173,7 @@ def invitePending(self): `false`: An invite is not pending for this person """ - return self._json_data.get('invitePending') + return self._json_data.get("invitePending") @property def loginEnabled(self): @@ -182,9 +182,9 @@ def loginEnabled(self): Person Login Enabled Enum: `true`: The person can log into Webex Teams - 'false': The person cannot log into Webex Teams + "false": The person cannot log into Webex Teams """ - return self._json_data.get('loginEnabled') + return self._json_data.get("loginEnabled") @property def type(self): @@ -193,5 +193,6 @@ def type(self): Person Type Enum: `person`: Account belongs to a person `bot`: Account is a bot user + `appuser`: Account is a guest user """ - return self._json_data.get('type') + return self._json_data.get("type") From a1c6b78648a40f041d2fc82019aefb52793c14bd Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 17:31:18 -0400 Subject: [PATCH 07/11] Update teams.py - Update default value for `max=` in the teams.list() method. - Make `name` a required parameter for the teams.update() method. --- webexteamssdk/api/teams.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webexteamssdk/api/teams.py b/webexteamssdk/api/teams.py index 784049e..a637d47 100644 --- a/webexteamssdk/api/teams.py +++ b/webexteamssdk/api/teams.py @@ -73,7 +73,7 @@ def __init__(self, session, object_factory): self._object_factory = object_factory @generator_container - def list(self, max=None, **request_parameters): + def list(self, max=100, **request_parameters): """List teams to which the authenticated user belongs. This method supports Webex Teams's implementation of RFC5988 Web @@ -168,7 +168,7 @@ def get(self, teamId): # Return a team object created from the response JSON data return self._object_factory(OBJECT_TYPE, json_data) - def update(self, teamId, name=None, **request_parameters): + def update(self, teamId, name, **request_parameters): """Update details for a team, by ID. Args: @@ -186,7 +186,7 @@ def update(self, teamId, name=None, **request_parameters): """ check_type(teamId, basestring) - check_type(name, basestring, optional=True) + check_type(name, basestring) put_data = dict_from_items_with_values( request_parameters, From d976876ee6a956c263926de5ad3fbd064b09e084 Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 17:52:07 -0400 Subject: [PATCH 08/11] Update Team Memberships API Update the default value for the `max=` parameter of the team_memberships.list() method. --- webexteamssdk/api/team_memberships.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webexteamssdk/api/team_memberships.py b/webexteamssdk/api/team_memberships.py index 2b14901..d8d83f2 100644 --- a/webexteamssdk/api/team_memberships.py +++ b/webexteamssdk/api/team_memberships.py @@ -73,7 +73,7 @@ def __init__(self, session, object_factory): self._object_factory = object_factory @generator_container - def list(self, teamId, max=None, **request_parameters): + def list(self, teamId, max=100, **request_parameters): """List team memberships for a team, by ID. This method supports Webex Teams's implementation of RFC5988 Web From 659f3519fbbf809c1d08275aee9f2a5eafc5a5f8 Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 18:00:27 -0400 Subject: [PATCH 09/11] Update the Webhooks API Add the default value for the `max=` parameter of the webhooks.list() method. --- webexteamssdk/api/webhooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webexteamssdk/api/webhooks.py b/webexteamssdk/api/webhooks.py index 99ef8b5..b3c3fee 100644 --- a/webexteamssdk/api/webhooks.py +++ b/webexteamssdk/api/webhooks.py @@ -73,7 +73,7 @@ def __init__(self, session, object_factory): self._object_factory = object_factory @generator_container - def list(self, max=None, **request_parameters): + def list(self, max=100, **request_parameters): """List all of the authenticated user's webhooks. This method supports Webex Teams's implementation of RFC5988 Web From ecb48446d833e1f54d48796e99611cd54e6e1b8a Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 18:37:35 -0400 Subject: [PATCH 10/11] Update Messages API tests - Test new messages.list_direct() method - Test replying to messages (threading with parentId) --- tests/api/test_messages.py | 81 +++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/tests/api/test_messages.py b/tests/api/test_messages.py index 69f2155..27f1785 100644 --- a/tests/api/test_messages.py +++ b/tests/api/test_messages.py @@ -57,7 +57,7 @@ def adaptive_card(): @pytest.fixture(scope="session") -def direct_message_by_email(api, test_people): +def direct_message_by_person_email(api, test_people): person = test_people["member_added_by_email"] message = api.messages.create( toPersonEmail=person.emails[0], @@ -69,6 +69,16 @@ def direct_message_by_email(api, test_people): api.messages.delete(message.id) +@pytest.fixture(scope="session") +def direct_message_reply_by_person_email(api, direct_message_by_person_email): + text = create_string("Reply Message") + return api.messages.create( + toPersonEmail=direct_message_by_person_email.toPersonEmail, + parentId=direct_message_by_person_email.id, + text=text, + ) + + @pytest.fixture(scope="session") def direct_message_by_email_with_card(api, test_people, adaptive_card): person = test_people["member_added_by_email"] @@ -89,7 +99,7 @@ def direct_message_by_email_with_card(api, test_people, adaptive_card): @pytest.fixture(scope="session") -def direct_message_by_id(api, test_people): +def direct_message_by_person_id(api, test_people): person = test_people["member_added_by_id"] message = api.messages.create( toPersonId=person.id, @@ -101,6 +111,16 @@ def direct_message_by_id(api, test_people): api.messages.delete(message.id) +@pytest.fixture(scope="session") +def direct_message_reply_by_person_id(api, direct_message_by_person_id): + text = create_string("Reply Message") + return api.messages.create( + toPersonId=direct_message_by_person_id.toPersonId, + parentId=direct_message_by_person_id.id, + text=text, + ) + + @pytest.fixture(scope="session") def send_group_room_message(api): messages = [] @@ -125,6 +145,16 @@ def group_room_text_message(group_room, send_group_room_message): return send_group_room_message(group_room.id, text=text) +@pytest.fixture(scope="session") +def group_room_message_reply_by_id(api, group_room, group_room_text_message): + text = create_string("Reply Message") + return api.messages.create( + # roomId=group_room.id, + parentId=group_room_text_message.id, + text=text, + ) + + @pytest.fixture(scope="session") def group_room_markdown_message( me, @@ -201,13 +231,13 @@ def group_room_messages( @pytest.fixture(scope="session") def direct_messages( - direct_message_by_email, - direct_message_by_id, + direct_message_by_person_email, + direct_message_by_person_id, direct_message_by_email_with_card, ): return [ - direct_message_by_email, - direct_message_by_id, + direct_message_by_person_email, + direct_message_by_person_id, direct_message_by_email_with_card, ] @@ -258,8 +288,14 @@ def test_list_messages_mentioning_me(api, group_room, assert are_valid_messages(messages_list) -def test_create_direct_messages_by_email(direct_message_by_email): - assert is_valid_message(direct_message_by_email) +def test_create_direct_messages_by_email(direct_message_by_person_email): + assert is_valid_message(direct_message_by_person_email) + + +def test_reply_to_direct_message_by_person_email( + direct_message_reply_by_person_email +): + assert is_valid_message(direct_message_reply_by_person_email) def test_create_direct_messages_by_email_with_card( @@ -268,14 +304,39 @@ def test_create_direct_messages_by_email_with_card( assert is_valid_message(direct_message_by_email_with_card) -def test_create_direct_messages_by_id(direct_message_by_id): - assert is_valid_message(direct_message_by_id) +def test_create_direct_messages_by_id(direct_message_by_person_id): + assert is_valid_message(direct_message_by_person_id) + + +def test_reply_to_direct_message_by_person_id( + direct_message_reply_by_person_id +): + assert is_valid_message(direct_message_reply_by_person_id) + + +def test_list_direct_messages_by_person_id(api, direct_message_by_person_id): + messages = api.messages.list_direct( + personId=direct_message_by_person_id.toPersonId, + ) + assert are_valid_messages(messages) + + +def test_list_direct_messages_by_person_email(api, + direct_message_by_person_email): + messages = api.messages.list_direct( + personEmail=direct_message_by_person_email.toPersonEmail, + ) + assert are_valid_messages(messages) def test_create_text_message(group_room_text_message): assert is_valid_message(group_room_text_message) +def test_create_reply_message(group_room_text_message): + assert is_valid_message(group_room_text_message) + + def test_create_markdown_message(group_room_markdown_message): assert is_valid_message(group_room_markdown_message) From 80056c563842fbf5e61b11c22ccbd42082a9fec3 Mon Sep 17 00:00:00 2001 From: Chris Lunsford Date: Fri, 10 Jul 2020 18:41:12 -0400 Subject: [PATCH 11/11] Update docs for messages.list_direct() --- docs/user/api_structure_table.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/user/api_structure_table.rst b/docs/user/api_structure_table.rst index 83ae447..cd53440 100644 --- a/docs/user/api_structure_table.rst +++ b/docs/user/api_structure_table.rst @@ -22,6 +22,7 @@ | | | :meth:`delete() ` | +------------------------+---------------------------+---------------------------------------------------------------------------------+ | | :ref:`messages` | :meth:`list() ` | +| | | :meth:`list_direct() ` | | | | :meth:`create() ` | | | | :meth:`get() ` | | | | :meth:`delete() ` |