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): the- idof 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): the- idof the room that was created
- task(int): the- idof the task that was assigned to the room
- users(list): a list of users that are linked to this task room. Each- user(dict)is represented by an- id(int)and a- name(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): the- idof the room that was created
- task(int, optional): the- idof 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): the- idof the user who caused this event
- room(int): the- idof 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): the- idof the user who caused this event
- room(int): the- idof 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 leave
- user(dict): dictionary of- id(int)and- name(str)of the user who caused this event
- room(int): the- idof the room that was entered or left, respectively
- timestamp(str): as ISO 8601:- YYYY-MM-DD hh:mm:ss.ssssssin 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 message
- room(int): the- idof the room where the text message will be sent to
- receiver_id(int, optional): the- idof the user that this message is directed at
- broadcast(bool, optional):- Trueif the message should be transmitted to all connected users.- Falseotherwise
- html(bool, optional):- Trueif special html formatting should be applied to a message. This requires- send_html_messagepermissions.- Falseotherwise.
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 message
- user(dict): dictionary of- id(int)and- name(str)of the user who sent the message
- room(int): the- idof the room where the message was sent
- private(bool):- Trueif this was a private message meant for a single user.- Falseotherwise
- broadcast(bool):- Trueif the message should be transmitted to all connected users.- Falseotherwise
- timestamp(str): as ISO 8601:- YYYY-MM-DD hh:mm:ss.ssssssin 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 display
- width(int, optional): the recommended width of the image. Defaults to 200
- height(int, optional): the recommended height of the image. Defaults to 200
- room(int): the- idof the room where the image is sent
- receiver_id(int, optional): the- idof the user that this image is directed at
- broadcast(bool, optional):- Trueif the image should be transmitted to all connected users.- Falseotherwise
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 image
- width(int): the recommended width of the image or- None
- height(int): the recommended height of the image or- None
- user(dict): dictionary of- id(int)and- name(str)of the user who submitted the image
- room(int): the- idof the room where the image was sent
- private(bool):- Trueif this was a private image meant for a single user.- Falseotherwise
- broadcast(bool):- Trueif the image was transmitted to all connected users.- Falseotherwise
- timestamp(str): as ISO 8601:- YYYY-MM-DD hh:mm:ss.ssssssin 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 content
- room(int): the- idof the room where the command is sent
- receiver_id(int, optional): the- idof the user that this command is directed at
- broadcast(bool, optional):- Trueif the message should be transmitted to all connected users.- Falseotherwise
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 content
- user(dict): dictionary of- id(int)and- name(str)of the user who sent the command
- room(int): the- idof the room where the command was sent
- private(bool):- Trueif this was a private command meant for a single user.- Falseotherwise
- broadcast(bool):- Trueif the command was transmitted to all connected users.- Falseotherwise
- timestamp(str): as ISO 8601:- YYYY-MM-DD hh:mm:ss.ssssssin 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):- clickif the user clicked on the html element,- movefor every few miliseconds of mouse movement
- coordinates(dict): contains the keys- xand- y, the position- {"x": 0, "y": 0}would be the top left corner of the html element
- element_id(str): the- idof the html element in which movement is tracked
- user(dict): dictionary of- id(int)and- name(str)of the user who caused this event
- room(int): the- idof the room where the event was triggered
- timestamp(str): as ISO 8601:- YYYY-MM-DD hh:mm:ss.ssssssin 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):- addif a bounding box was added,- removeif the canvas was resetted and all bounding boxes removed in the process
- coordinates(dict, optional): only passed for the- addevent, contains the keys- left,- top,- bottomand- rightspecifying all four corners of the rectangle
- user(dict): dictionary of- id(int)and- name(str)of the user who caused this event
- room(int): the- idof the room where the event was triggered