shellbot.spaces.ciscospark module¶
-
class
shellbot.spaces.ciscospark.
SparkSpace
(context=None, ears=None, fan=None, **kwargs)[source]¶ Bases:
shellbot.spaces.base.Space
Handles a Cisco Spark room
This is a representation of a chat space hosted at Cisco Spark.
-
DEFAULT_SETTINGS
= {'server': {'url': '$SERVER_URL', 'hook': '/hook', 'binding': '0.0.0.0', 'port': 8080}, 'space': {'room': '$CHAT_ROOM_TITLE'}}¶
-
check
()[source]¶ Checks settings of the space
This function reads key
space
and below, and update the context accordingly:space.configure({'space': { 'type': 'spark', 'room': 'My preferred room', 'participants': ['alan.droit@azerty.org', 'bob.nard@support.tv'], 'team': 'Anchor team', 'token': '$MY_BOT_TOKEN', }})
This can also be written in a more compact form:
space.configure({'space.room': 'My preferred room', 'space.token': '$MY_BOT_TOKEN', })
This function handles following parameters:
space.room
- title of the associated Cisco Spark room. This can refer to an environment variable if it starts with$
, e.g.,$ROOM_TITLE
.space.participants
- list of initial participants. This can be taken from$CHANNEL_DEFAULT_PARTICIPANTS
from the environment.space.team
- title of a team associated with this roomspace.token
- private token of the bot, given by Cisco Spark. Instead of putting the real value of the token you are encouraged to use an environment variable instead, e.g.,$MY_BOT_TOKEN
. Ifspace.token
is not provided, then the function looks for an environment variableCISCO_SPARK_BOT_TOKEN
.space.audit_token
- token to be used for the audit of chat events. It is recommended that a token of a person is used, so that the visibility is maximised for the proper audit of events. Instead of putting the real value of the token you are encouraged to use an environment variable instead, e.g.,$MY_AUDIT_TOKEN
. Ifspace.audit_token
is not provided, then the function looks for an environment variableCISCO_SPARK_AUDIT_TOKEN
.
If a single value is provided for
participants
then it is turned automatically to a list.Example:
>>>space.configure({'space.participants': 'bobby@jah.com'}) >>>space.context.get('space.participants') ['bobby@jah.com']
-
configured_title
()[source]¶ Returns the title of the space as set in configuration
Returns: the configured title, or Collaboration space
Return type: str This function should be rewritten in sub-classes if space title does not come from
space.room
parameter.
-
connect
(factory=None, **kwargs)[source]¶ Connects to the back-end API
Parameters: factory – an API factory, for test purpose Type: object If a factory is provided, it is used to get API instances. Else the regular CiscoSparkAPI is invoked instead.
This function loads two instances of Cisco Spark API, one using the bot token, and one using the audit token, if this is available.
-
create
(title, ex_team=None, **kwargs)[source]¶ Creates a room
Parameters: - title (str) – title of a new channel
- ex_team (str or object) – the team attached to this room (optional)
If the parameter
ex_team
is provided, then it can be either a simple name, or a team object featuring an id.Returns: Channel or None This function returns a representation of the local channel.
-
delete
(id, **kwargs)[source]¶ Deletes a room
Parameters: id (str) – the unique id of an existing room
-
deregister
()[source]¶ Stops inbound flow from Cisco Spark
This function deregisters hooks that it may have created.
Previous webhooks registered with the bot token are all removed before registration. This means that only the most recent instance of the bot will be notified of new invitations.
This function also removes webhooks created with the audit token, if any. So after deregister the audit of individual rooms just stops.
-
get_attachment
(url, token=None, response=None)[source]¶ Retrieves a document attached to a room
Returns: a stream of BytesIO Return type: BytesIO #TODO: stream from requests response = requests.get(url, stream=True) response.decode_content = True shutil.copyfileobj(response.raw, target)
-
get_by_id
(id, **kwargs)[source]¶ Looks for an existing room by id
Parameters: id (str) – identifier of the target room Returns: Channel instance or None
-
get_by_person
(label, **kwargs)[source]¶ Looks for an existing private room with a person
Parameters: label (str) – the display name of the person’s account Returns: Channel instance or None If a channel already exists for this person, a representation of it is returned. Else the value ``None``is returned.
-
get_by_title
(title, **kwargs)[source]¶ Looks for an existing room by name
Parameters: title (str) – title of the target room Returns: Channel instance or None Note: This function looks only into group rooms. To get a direct room use
get_by_person()
instead.
-
get_team
(name)[source]¶ Gets a team by name
Parameters: name (str) – name of the target team Returns: attributes of the team Return type: Team or None >>>print(space.get_team(“Hello World”)) Team({
“id” : “Y2lzY29zcGFyazovL3VzL1RFQU0Yy0xMWU2LWE5ZDgtMjExYTBkYzc5NzY5”, “name” : “Hello World”, “created” : “2015-10-18T14:26:16+00:00”})
-
list_group_channels
(quantity=10, **kwargs)[source]¶ Lists available channels
Parameters: quantity (positive integer) – maximum quantity of channels to return Returns: list of Channel
-
list_participants
(id)[source]¶ Lists participants to a channel
Parameters: id (str) – the unique id of an existing channel Returns: a list of persons Return type: list of str Note: this function returns all participants, except the bot itself.
-
on_connect
()[source]¶ Retrieves attributes of this bot
This function queries the Cisco Spark API to remember the id of this bot. This is used afterwards to filter inbound messages to the shell.
-
on_init
(token=None, **kwargs)[source]¶ Handles extended initialisation parameters
Parameters: token (str) – bot authentication token for the Cisco Spark API Example:
space = SparkSpace(context=context)
-
on_join
(item, queue=None)[source]¶ Normalizes message for the listener
Parameters: - item (dict) – attributes of the inbound message
- queue (Queue) – the processing queue (optional)
Example item received on memberships:create:
{ 'isMonitor': False, 'created': '2017-05-31T21:25:30.424Z', 'personId': 'Y2lzY29zcGFyazovL3VRiMTAtODZkYy02YzU0Yjg5ODA5N2U', 'isModerator': False, 'personOrgId': 'Y2lzY29zcGFyazovL3V0FOSVpBVElPTi9jb25zdW1lcg', 'personDisplayName': 'foo.bar@acme.com', 'personEmail': 'foo.bar@acme.com', 'roomId': 'Y2lzY29zcGFyazovL3VzL1JP3LTk5MDAtMDU5MDI2YjBiNDUz', 'id': 'Y2lzY29zcGFyazovL3VzDctMTFlNy05OTAwLTA1OTAyNmIwYjQ1Mw' }
This function prepares a Join and push it to the provided queue.
type
is set tojoin
actor_id
is a copy ofpersonId
actor_address
is a copy ofpersonEmail
actor_label
is a copy ofpersonDisplayName
stamp
is a copy ofcreated
-
on_leave
(item, queue=None)[source]¶ Normalizes message for the listener
Parameters: - item (dict) – attributes of the inbound message
- queue (Queue) – the processing queue (optional)
Example item received on memberships:delete:
{ 'isMonitor': False, 'created': '2017-05-31T21:25:30.424Z', 'personId': 'Y2lzY29zcGFyazovL3VRiMTAtODZkYy02YzU0Yjg5ODA5N2U', 'isModerator': False, 'personOrgId': 'Y2lzY29zcGFyazovL3V0FOSVpBVElPTi9jb25zdW1lcg', 'personDisplayName': 'foo.bar@acme.com', 'personEmail': 'foo.bar@acme.com', 'roomId': 'Y2lzY29zcGFyazovL3VzL1JP3LTk5MDAtMDU5MDI2YjBiNDUz', 'id': 'Y2lzY29zcGFyazovL3VzDctMTFlNy05OTAwLTA1OTAyNmIwYjQ1Mw' }
This function prepares a Leave and push it to the provided queue.
type
is set toleave
actor_id
is a copy ofpersonId
actor_address
is a copy ofpersonEmail
actor_label
is a copy ofpersonDisplayName
stamp
is a copy ofcreated
-
on_message
(item, queue=None)[source]¶ Normalizes message for the listener
Parameters: - item (dict) – attributes of the inbound message
- queue (Queue) – the processing queue (optional)
Returns: a Message
This function prepares a Message and push it to the provided queue.
This function adds following keys to messages so that a neutral format can be used with the listener:
type
is set tomessage
content
is a copy ofhtml
from_id
is a copy ofpersonId
from_label
is a copy ofpersonEmail
is_direct
if the message is coming from 1:1 roommentioned_ids
is a copy ofmentionedPeople
channel_id
is a copy ofroomId
stamp
is a copy ofcreated
-
post_message
(id=None, text=None, content=None, file=None, person=None, **kwargs)[source]¶ Posts a message to a Cisco Spark room
Parameters: - id (str) – the unique id of an existing room
- person (str) – address for a direct message
- text (str) – message in plain text
- content (str) – rich format, such as Markdown or HTML
- file (str) – URL or local path for an attachment
Example message out of plain text:
space.post_message(id=id, text='hello world')
Example message with Markdown:
space.post_message(id, content='this is a **bold** statement')
Example file upload:
space.post_message(id, file='./my_file.pdf')
Of course, you can combine text with the upload of a file:
text = 'This is the presentation that was used for our meeting' space.post_message(id=id, text=text, file='./my_file.pdf')
For direct messages, provide who you want to reach instead of a channel id, like this:
space.post_message(person='foo.bar@acme.com', text='hello guy')
-
pull
()[source]¶ Fetches events from Cisco Spark
This function senses most recent items, and pushes them to a processing queue.
-
register
(hook_url)[source]¶ Connects in the background to Cisco Spark inbound events
Parameters: webhook (str) – web address to be used by Cisco Spark service This function registers the provided hook multiple times, so as to receive mutiple kind of updates:
- The bot is invited to a room, or kicked out of it. People are joining or leaving: webhook name = shellbot-memberships resource = memberships, event = all, registered with bot token
- Messages are sent, maybe with some files: webhook name = shellbot-messages resource = messages, event = created, registered with bot token
- Messages sent, maybe with some files, for audit purpose: webhook name = shellbot-audit resource = messages, event = created, registered with audit token
Previous webhooks registered with the bot token are all removed before registration. This means that only the most recent instance of the bot will be notified of new invitations.
-
update
(channel, **kwargs)[source]¶ Updates an existing room
Parameters: channel (Channel) – a representation of the updated room This function can change the title of a room.
For example, change the title from a bot instance:
bot.channel.title = "A new title" bot.space.update(bot.channel)
-
walk_messages
(id=None, **kwargs)[source]¶ Walk messages from a Cisco Spark room
Parameters: id (str) – the unique id of an existing room Returns: an iterator of Message objects
-
webhook
(item=None)[source]¶ Processes the flow of events from Cisco Spark
Parameters: item (dict) – if provided, do not invoke the request
objectThis function is called from far far away, over the Internet, most of the time. Or it is called locally, from test environment, when an item is provided.
The structure of the provided item should be identical to those of updates sent by Cisco Spark.
Example event on message creation:
{ "resource": "messages", "event": "created", "data": { "id": "...." }, "name": "shellbot-audit" }
-
-
shellbot.spaces.ciscospark.
no_exception
(function, return_value=None)[source]¶ Stops the propagation of exceptions
Parameters: return_value – Returned by the decorated function on exception This decorator is a convenient approach for silently discarding exceptions.
#wip – this should be moved in a general-purpose module of shellbot
Example:
@no_exception(return_value=[]) def list_items(): ... # if an exception is raised here, an empty list is returned
-
shellbot.spaces.ciscospark.
retry
(give_up='Unable to request Cisco Spark API', silent=False, delays=(0.1, 1, 5), skipped=(401, 403, 404, 409))[source]¶ Improves a call to Cisco Spark API
Parameters: - give_up (str) – message to log on final failure
- silent (bool) – if exceptions should be masked as much as possible
- delays (a list of positive numbers) – time to wait between repetitions
- skipped (a list of web status codes) – do not retry for these status codes
This decorator compensates for common transient communication issues with the Cisco Spark platform in the cloud.
Example:
@retry(give_up="Unable to get information on this bot") def api_call(): return self.api.people.me() me = api_call()
credit: http://code.activestate.com/recipes/580745-retry-decorator-in-python/