Skip to content

Commit b6a13ea

Browse files
authored
Merge pull request #56 from CiscoDevNet/feature-55-events-api
Feature 55 - Add Events API Support
2 parents 41ba14f + 8f599ec commit b6a13ea

File tree

9 files changed

+334
-30
lines changed

9 files changed

+334
-30
lines changed

ciscosparkapi/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from past.builtins import basestring
1717

1818
from .api.access_tokens import AccessTokensAPI as _AccessTokensAPI
19+
from .api.events import EventsAPI as _EventsAPI
1920
from .api.licenses import LicensesAPI as _LicensesAPI
2021
from .api.memberships import MembershipsAPI as _MembershipsAPI
2122
from .api.messages import MessagesAPI as _MessagesAPI
@@ -31,8 +32,8 @@
3132
ciscosparkapiException,
3233
)
3334
from .models import (
34-
AccessToken, License, Membership, Message, Organization, Person, Role,
35-
Room, Team, TeamMembership, Webhook, WebhookEvent, sparkdata_factory,
35+
AccessToken, Event, License, Membership, Message, Organization, Person,
36+
Role, Room, Team, TeamMembership, Webhook, WebhookEvent, sparkdata_factory,
3637
)
3738
from .restsession import (
3839
DEFAULT_SINGLE_REQUEST_TIMEOUT,
@@ -95,6 +96,8 @@ class CiscoSparkAPI(object):
9596
9697
:class:`roles <_RolesAPI>`
9798
99+
:class:`events <_EventsAPI>`
100+
98101
:class:`access_tokens <_AccessTokensAPI>`
99102
100103
"""
@@ -187,6 +190,7 @@ def __init__(self, access_token=None, base_url=DEFAULT_BASE_URL,
187190
self.access_tokens = _AccessTokensAPI(
188191
self.base_url, object_factory, timeout=single_request_timeout
189192
)
193+
self.events = _EventsAPI(self._session, object_factory)
190194

191195
@property
192196
def access_token(self):

ciscosparkapi/api/events.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# -*- coding: utf-8 -*-
2+
"""Cisco Spark Events API."""
3+
4+
5+
from __future__ import (
6+
absolute_import,
7+
division,
8+
print_function,
9+
unicode_literals,
10+
)
11+
12+
from builtins import *
13+
14+
from past.builtins import basestring
15+
16+
from ..generator_containers import generator_container
17+
from ..restsession import RestSession
18+
from ..utils import (
19+
check_type,
20+
dict_from_items_with_values,
21+
)
22+
23+
24+
__author__ = "Chris Lunsford"
25+
__author_email__ = "[email protected]"
26+
__copyright__ = "Copyright (c) 2016-2018 Cisco and/or its affiliates."
27+
__license__ = "MIT"
28+
29+
30+
API_ENDPOINT = 'events'
31+
OBJECT_TYPE = 'event'
32+
33+
34+
class EventsAPI(object):
35+
"""Cisco Spark Events API.
36+
37+
Wraps the Cisco Spark Events API and exposes the API as native Python
38+
methods that return native Python objects.
39+
40+
"""
41+
42+
def __init__(self, session, object_factory):
43+
"""Initialize a new EventsAPI object with the provided RestSession.
44+
45+
Args:
46+
session(RestSession): The RESTful session object to be used for
47+
API calls to the Cisco Spark service.
48+
49+
Raises:
50+
TypeError: If the parameter types are incorrect.
51+
52+
"""
53+
check_type(session, RestSession, may_be_none=False)
54+
55+
super(EventsAPI, self).__init__()
56+
57+
self._session = session
58+
self._object_factory = object_factory
59+
60+
@generator_container
61+
def list(self, resource=None, type=None, actorId=None, _from=None, to=None,
62+
max=None, **request_parameters):
63+
"""List events.
64+
65+
List events in your organization. Several query parameters are
66+
available to filter the response.
67+
68+
Note: `from` is a keyword in Python and may not be used as a variable
69+
name, so we had to use `_from` instead.
70+
71+
This method supports Cisco Spark's implementation of RFC5988 Web
72+
Linking to provide pagination support. It returns a generator
73+
container that incrementally yields all events returned by the
74+
query. The generator will automatically request additional 'pages' of
75+
responses from Spark as needed until all responses have been returned.
76+
The container makes the generator safe for reuse. A new API call will
77+
be made, using the same parameters that were specified when the
78+
generator was created, every time a new iterator is requested from the
79+
container.
80+
81+
Args:
82+
resource(basestring): Limit results to a specific resource type.
83+
Possible values: "messages", "memberships".
84+
type(basestring): Limit results to a specific event type. Possible
85+
values: "created", "updated", "deleted".
86+
actorId(basestring): Limit results to events performed by this
87+
person, by ID.
88+
_from(basestring): Limit results to events which occurred after a
89+
date and time, in ISO8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ).
90+
to(basestring): Limit results to events which occurred before a
91+
date and time, in ISO8601 format (yyyy-MM-dd'T'HH:mm:ss.SSSZ).
92+
max(int): Limit the maximum number of items returned from the Spark
93+
service per request.
94+
**request_parameters: Additional request parameters (provides
95+
support for parameters that may be added in the future).
96+
97+
Returns:
98+
GeneratorContainer: A GeneratorContainer which, when iterated,
99+
yields the events returned by the Cisco Spark query.
100+
101+
Raises:
102+
TypeError: If the parameter types are incorrect.
103+
SparkApiError: If the Cisco Spark cloud returns an error.
104+
105+
"""
106+
check_type(resource, basestring)
107+
check_type(type, basestring)
108+
check_type(actorId, basestring)
109+
check_type(_from, basestring)
110+
check_type(to, basestring)
111+
check_type(max, int)
112+
113+
params = dict_from_items_with_values(
114+
request_parameters,
115+
resource=resource,
116+
type=type,
117+
actorId=actorId,
118+
_from=_from,
119+
to=to,
120+
max=max,
121+
)
122+
123+
if _from:
124+
params["from"] = params.pop("_from")
125+
126+
# API request - get items
127+
items = self._session.get_items(API_ENDPOINT, params=params)
128+
129+
# Yield event objects created from the returned items JSON objects
130+
for item in items:
131+
yield self._object_factory(OBJECT_TYPE, item)
132+
133+
def get(self, eventId):
134+
"""Get the details for an event, by event ID.
135+
136+
Args:
137+
eventId(basestring): The ID of the event to be retrieved.
138+
139+
Returns:
140+
Event: A event object with the details of the requested room.
141+
142+
Raises:
143+
TypeError: If the parameter types are incorrect.
144+
SparkApiError: If the Cisco Spark cloud returns an error.
145+
146+
"""
147+
check_type(eventId, basestring, may_be_none=False)
148+
149+
# API request
150+
json_data = self._session.get(API_ENDPOINT + '/' + eventId)
151+
152+
# Return a room object created from the response JSON data
153+
return self._object_factory(OBJECT_TYPE, json_data)

ciscosparkapi/models/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from collections import defaultdict
1313

1414
from .access_token import AccessTokenBasicPropertiesMixin
15+
from .event import EventBasicPropertiesMixin
1516
from .license import LicenseBasicPropertiesMixin
1617
from .membership import MembershipBasicPropertiesMixin
1718
from .message import MessageBasicPropertiesMixin
@@ -36,6 +37,10 @@ class AccessToken(SparkData, AccessTokenBasicPropertiesMixin):
3637
"""Cisco Spark Access-Token data model."""
3738

3839

40+
class Event(SparkData, EventBasicPropertiesMixin):
41+
"""Cisco Spark Event data model."""
42+
43+
3944
class License(SparkData, LicenseBasicPropertiesMixin):
4045
"""Cisco Spark License data model."""
4146

@@ -82,6 +87,7 @@ class WebhookEvent(SparkData, WebhookEventBasicPropertiesMixin):
8287
sparkdata_models = defaultdict(
8388
lambda: SparkData,
8489
access_token=AccessToken,
90+
event=Event,
8591
license=License,
8692
membership=Membership,
8793
message=Message,

ciscosparkapi/models/event.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# -*- coding: utf-8 -*-
2+
"""Cisco Spark Event data model."""
3+
4+
5+
from __future__ import (
6+
absolute_import,
7+
division,
8+
print_function,
9+
unicode_literals,
10+
)
11+
12+
from builtins import *
13+
14+
from .sparkdata import SparkData
15+
16+
17+
__author__ = "Chris Lunsford"
18+
__author_email__ = "[email protected]"
19+
__copyright__ = "Copyright (c) 2016-2018 Cisco and/or its affiliates."
20+
__license__ = "MIT"
21+
22+
23+
class EventBasicPropertiesMixin(object):
24+
"""A mixin for :class:`SparkData` classes."""
25+
26+
@property
27+
def id(self):
28+
"""Event ID."""
29+
return self._json_data.get('id')
30+
31+
@property
32+
def resource(self):
33+
"""The event resource type (`messagess`, `memberships`)."""
34+
return self._json_data.get('resource')
35+
36+
@property
37+
def type(self):
38+
"""The event type (`created`, `updated`, `deleted`)."""
39+
return self._json_data.get('type')
40+
41+
@property
42+
def actorId(self):
43+
"""The ID of the person that performed this event."""
44+
return self._json_data.get('actorId')
45+
46+
@property
47+
def created(self):
48+
"""The date and time the event was performed."""
49+
return self._json_data.get('created')
50+
51+
@property
52+
def data(self):
53+
"""The event resource data."""
54+
return SparkData(self._json_data.get('data'))

ciscosparkapi/models/webhook_event.py

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
"""Cisco Spark Access-Token data model."""
2+
"""Cisco Spark Webhook-Event data model."""
33

44

55
from __future__ import (
@@ -91,30 +91,5 @@ def actorId(self):
9191

9292
@property
9393
def data(self):
94-
"""The data for the resource that triggered the webhook.
95-
96-
For example, if you registered a webhook that triggers when messages
97-
are created (i.e. posted into a room) then the data property will
98-
contain the JSON representation for a message resource.
99-
100-
Note: That not all of the details of the resource are included in the
101-
data object. For example, the contents of a message are not included.
102-
You would need to request the details for the message using the message
103-
'id' (which is in the data object) and the
104-
`CiscoSparkAPI.messages.get()` method.
105-
106-
"""
107-
if self._data is None and self._json_data.get('data'):
108-
if self.resource == "memberships":
109-
self._data = Membership(self._json_data.get('data'))
110-
111-
elif self.resource == "messages":
112-
self._data = Message(self._json_data.get('data'))
113-
114-
elif self.resource == "rooms":
115-
self._data = Room(self._json_data.get('data'))
116-
117-
else:
118-
self._data = SparkData(self._json_data.get('data'))
119-
120-
return self._data
94+
"""The data for the resource that triggered the webhook."""
95+
return SparkData(self._json_data.get('data'))

docs/user/api.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ roles
101101
.. autoclass:: ciscosparkapi.api.roles.RolesAPI()
102102

103103

104+
.. _events:
105+
106+
events
107+
-----
108+
109+
.. autoclass:: ciscosparkapi.api.events.EventsAPI()
110+
111+
104112
.. _access_tokens:
105113

106114
access_tokens
@@ -232,6 +240,15 @@ Role
232240
:inherited-members:
233241

234242

243+
.. _Event:
244+
245+
Event
246+
-----
247+
248+
.. autoclass:: Event()
249+
:inherited-members:
250+
251+
235252
.. _Access Token:
236253

237254
Access Token

docs/user/quickstart.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ structure is provided here.
239239
| | +-------------------------------------+
240240
| | | :meth:`~RolesAPI.create` |
241241
+-----------------------+-------------------------+-------------------------------------+
242+
| | :ref:`events` | :meth:`~EventsAPI.list` |
243+
| | +-------------------------------------+
244+
| | | :meth:`~EventsAPI.get` |
245+
+-----------------------+-------------------------+-------------------------------------+
242246
| | :ref:`access_tokens` | :meth:`~AccessTokensAPI.get` |
243247
| | +-------------------------------------+
244248
| | | :meth:`~AccessTokensAPI.refresh` |

0 commit comments

Comments
 (0)