7. Bot-related events
7.1. Rooms
There are two types of events indicating that a new room was created.
Both events are received by all connected users.
The first of the two new_room
is the more general one.
It can be triggered for every created room independently of its purpose and layout.
@self.sio.event
def new_room(data):
do_something(data)
data
in new_room
has this structure:
room(int)
: theid
of the room that was created
The second event can be triggered only if a task room was created.
A task room is a room that has a task_id
assigned.
@self.sio.event
def new_task_room(data):
do_something(data)
data
in new_task_room
has this structure:
room(int)
: theid
of the room that was createdtask(int)
: theid
of the task that was assigned to the roomusers(list)
: a list of users that are linked to this task room. Eachuser(dict)
is represented by anid(int)
and aname(str)
It is important to remember that those events are not sent automatically on room creation but have to be emitted by a bot after it has created a room:
self.sio.emit("room_created", data)
data
is a dictionary with the following keys:
room(int)
: theid
of the room that was createdtask(int, optional)
: theid
of the task that will be performed in this room
7.1.1. Example: Echo Bot
When the Concierge Bot creates a new room, it will move the assigned users to
this room and send a room_created
event to the server. In order to join
those task rooms, bots may listen to the new_task_room
event just like the Echo Bot:
@self.sio.event
def new_task_room(data):
room_id = data["room"]
task_id = data["task"]
if self.task_id is None or task_id == self.task_id:
response = requests.post(
f"{self.uri}/users/{self.user}/rooms/{room_id}",
headers={"Authorization": f"Bearer {self.token}"}
)
If a task room has been opened, it compares the task id of the task room with its own task id. It joins the room only if the two task ids match or it is not assigned any task id. We interpret the latter as the Echo Bot being relevant to all tasks.
7.2. Movement
7.2.1. Monitoring own movement
Bots can monitor their own movement between rooms. This includes them joining
or leaving a room. For this purpose, they have to listen to the joined_room
and left_room
events, respectively. Both events are only sent to the user
(e.g. bot) that caused them.
@self.sio.event
def joined_room(data):
do_something(data)
data
in joined_room
has this structure:
user(int)
: theid
of the user who caused this eventroom(int)
: theid
of the room that was entered by this user
Task bots are generally sent to rooms to instruct users and provide resources
necessary to the task fulfillment. The joined_room
event handler can be
used to introduce the bot to the users and set an initial task description.
@self.sio.event
def left_room(data):
do_something(data)
data
in left_room
has this structure:
user(int)
: theid
of the user who caused this eventroom(int)
: theid
of the room that was left by this user
7.2.2. Monitoring overall movement
Bots are also notified once a user joins or leaves one of the rooms the bot is placed in. The term user here includes the bot itself, as well as other bots and human users.
@self.sio.event
def status(data):
do_something(data)
data
in status
has this structure:
type(str)
: the status type, either join or leaveuser(dict)
: dictionary ofid(int)
andname(str)
of the user who caused this eventroom(int)
: theid
of the room that was entered or left, respectivelytimestamp(str)
: as ISO 8601:YYYY-MM-DD hh:mm:ss.ssssss
in UTC Time
7.3. Chat
All of the events mentioned below can be either private
or not. If an event
is private
it is only sent to a designated receiver. If this receiver is
the bot, it receives the event. Otherwise it does not receive it. If an event
is not private
it can be seen by all users in the specified room.
Only bots should send private content, but for debugging purposes, you can use
the chat interface and the following syntax to send private messages
@<user_id> <text>
or private images @<user_id> image: <url>
. Make sure
that whoever is supposed to send private content is assigned the send_privately
permission.
7.3.1. Messages
Every data collection experiment evolves around users exchanging messages.
Those can be sent by any user that is assigned the send_message
or
send_html_message
permission. A bot may wish to verify message content,
count messages until a certain milestone is reached or otherwise process user messages.
Messages can also be sent by bots:
self.sio.emit(
"text",
data
)
data
is a dictionary with the following keys:
message(str)
: the content of the text messageroom(int)
: theid
of the room where the text message will be sent toreceiver_id(int, optional)
: theid
of the user that this message is directed atbroadcast(bool, optional)
:True
if the message should be transmitted to all connected users.False
otherwisehtml(bool, optional)
:True
if special html formatting should be applied to a message. This requiressend_html_message
permissions.False
otherwise.
Messages cause an event on the server side that can be handled by bots:
@self.sio.event
def text_message(data):
do_something(data)
message(str)
: the content of the text messageuser(dict)
: dictionary ofid(int)
andname(str)
of the user who sent the messageroom(int)
: theid
of the room where the message was sentprivate(bool)
:True
if this was a private message meant for a single user.False
otherwisebroadcast(bool)
:True
if the message should be transmitted to all connected users.False
otherwisetimestamp(str)
: as ISO 8601:YYYY-MM-DD hh:mm:ss.ssssss
in UTC Time
7.3.2. Images
If given the permission send_image
, a user may send image data. Normally,
only bots are supposed to do so. But for debugging purposes, it is possible to
send images via the chat interface using the syntax image: <url>
.
Bots can send images like this:
self.sio.emit(
"image",
data
)
data
is a dictionary with the following keys:
url(str)
: URL of the image to displaywidth(int, optional)
: the recommended width of the image. Defaults to 200height(int, optional)
: the recommended height of the image. Defaults to 200room(int)
: theid
of the room where the image is sentreceiver_id(int, optional)
: theid
of the user that this image is directed atbroadcast(bool, optional)
:True
if the image should be transmitted to all connected users.False
otherwise
Images cause an event on the server side that can be handled by bots:
@self.sio.event
def image_message(data):
do_something(data)
data
in image_message
has this structure:
url(str)
: URL of the displayed imagewidth(int)
: the recommended width of the image orNone
height(int)
: the recommended height of the image orNone
user(dict)
: dictionary ofid(int)
andname(str)
of the user who submitted the imageroom(int)
: theid
of the room where the image was sentprivate(bool)
:True
if this was a private image meant for a single user.False
otherwisebroadcast(bool)
:True
if the image was transmitted to all connected users.False
otherwisetimestamp(str)
: as ISO 8601:YYYY-MM-DD hh:mm:ss.ssssss
in UTC Time
7.3.3. Commands
Commands are very similar to text messages, but they are only visible to bots. In order for a user to be able to send commands, they need the permission send_command
. Commands are normally sent by human users. For a chat message to be understood as a command, it needs to be prefixed by a slash /
.
It is, however, also possible for bots to send commands:
self.sio.emit(
"message_command",
data
)
data
is a dictionary with the following keys:
command(str)
: the command contentroom(int)
: theid
of the room where the command is sentreceiver_id(int, optional)
: theid
of the user that this command is directed atbroadcast(bool, optional)
:True
if the message should be transmitted to all connected users.False
otherwise
Commands cause an event on the server side that can be handled by bots:
@self.sio.event
def command(data):
do_something(data)
data
in command
has this structure:
command(str)
: the command contentuser(dict)
: dictionary ofid(int)
andname(str)
of the user who sent the commandroom(int)
: theid
of the room where the command was sentprivate(bool)
:True
if this was a private command meant for a single user.False
otherwisebroadcast(bool)
:True
if the command was transmitted to all connected users.False
otherwisetimestamp(str)
: as ISO 8601:YYYY-MM-DD hh:mm:ss.ssssss
in UTC Time
7.4. Others
For both events below coordinates
are given in percentage. For example an x-value of 0.4 for an image of width 100px should be interpreted as the mouse being 40px to the right of the left corner of the html element.
7.4.1. Mouse Tracking
If one specifies the plain script mouse-tracking
in a room layout bots will receive an additional mouse
event.
@self.sio.event
def mouse(data):
do_something(data)
data
in mouse
has this structure:
type(str)
:click
if the user clicked on the html element,move
for every few miliseconds of mouse movementcoordinates(dict)
: contains the keysx
andy
, the position{"x": 0, "y": 0}
would be the top left corner of the html elementelement_id(str)
: theid
of the html element in which movement is trackeduser(dict)
: dictionary ofid(int)
andname(str)
of the user who caused this eventroom(int)
: theid
of the room where the event was triggeredtimestamp(str)
: as ISO 8601:YYYY-MM-DD hh:mm:ss.ssssss
in UTC Time
7.4.2. Bounding Boxes
If one specifies the plain script bounding-boxes
in a room layout and assigns a bot the permission receive_bounding_box
it will receive an additional bounding_box
event.
@self.sio.event
def bounding_box(data):
do_something(data)
data
in bounding_box
has this structure:
type(str)
:add
if a bounding box was added,remove
if the canvas was resetted and all bounding boxes removed in the processcoordinates(dict, optional)
: only passed for theadd
event, contains the keysleft
,top
,bottom
andright
specifying all four corners of the rectangleuser(dict)
: dictionary ofid(int)
andname(str)
of the user who caused this eventroom(int)
: theid
of the room where the event was triggered