Botsquad documentation logo

Background coordinator processes

The DSL provides a few constructions to allow the users of a bot to do things together.

Sending internal messages

Using emit with to: syntax, you can send an event (with optional payload) to another user. This way, you can create a chatbot which relays messages between two users.

However, in order to do this, you need to know the other user’s user_id, which is not exposed in every chat session.

There are two types of scripts which are special and run as separate “threads” in the bot runtime. These are called master and group. These background processes can be used to relay information between different users, perform tasks in the background, and do several other things.

The master coordinator

The master script is a special process which runs as a separate process. There is at most one master process per bot:

multiprocess

emit

From a user script, you can emit something to :master. It receives the event and can then relay the information to another user, or send (emit) something back to the sender.

emit "hello", to: :master

The master process can catch this "hello" event and then perform something, update some administration or emit something back:

task event: "hello" do
  users = users + [event.sender]
  # let the user know we have registered it
  emit "ok", to: event.sender
end

query

Sends an event to the given user, and waits for the reply.

reply = query :master, "ping"
say reply

In the other script, define a task or dialog that catches the ping event, and use the reply construct to send a payload back:

task event: "ping" do
  reply "pong"
end

Make sure that the handling task / dialog in the other process finishes quickly. If there is no reply received within 1 second, the value :timeout is returned in the calling process.

The ChatterBot in the botsquad examples is a good example of how a master script is used to create a group chat in which all chat members relay all text messages and images they send to each other.

The group coordinators

A group script is also a background process which can be used to group several members of a chat together.

Group coordinators work similarly to the master process, but there can be multiple groups active at the same time:

multiprocess

By default, a chat session is not part of any group. A new group process can be started by using the spawn_group() function:

group = spawn_group()

The group variable now contains the identifier of the newly created group. To have other people join this group, you need to share the link to the group chat. This can be done with the chat_link() function:

say "Group created! Have people join using the following link:"
say chat_link("web", g: group)

When someone clicks that link, he will be joined in the group. When a chat is part of a group, it will have a group variable automatically filled in the DSL context. This group variable can be used to emit messages to the group coordinator:

emit "hello", to: group

named groups

group = spawn_group("~mygroup")

Group names always start with a ~.

passing initial variables to group

group = spawn_group("~mygroup", [foo: "bar"])

The variable foo is now available in the group process.

You can also spawn a new group with a randomized name and predefined variables, by giving nil as the group name:

group = spawn_group(nil, [foo: "bar"])

group names based on user ids

Sometimes you want to give the group a deterministic identifier, based on the identifiers of the participants, for instance when creating a one-on-one chat. The group_name() function providers exactly that. Given the input identifiers, it returns a unique identifier that is usable as group name. The identifier is based on the given identifiers, but they are sorted and hashed together into a short new identifier.