Additional¶
These are additional functions which can be used inside the bot processes. They cover more specific tasks that are related to the DialoX platform, like token management, process management and communication.
_(msgid)
¶
Mark a given string as translatable.
For example:
say _("Hello world")
For more information, see the translation guide.
__testing_name_lookup(identifier)
¶
Look up a bot by testing name
__testing_phone_number_lookup(identifier)
¶
Look up a bot by testing phone number
assign_conversation(user)
¶
Assign the current conversation to the given user.
The user can either be an exact UUID, or a user as returned by the
get_assignable_users
or get_operator_by_uuid
functions.
Returns true
when the operation succeeded, or false
when the
user was not found or does not have access to the inbox. It crashes
when trying to assign from a process conversation (master or group),
or when an invalid user UUID is passed in.
Examples:
_result = assign_conversation("cb190dcb-a428-4420-9dfc-c4b1ce15c6fb")
get_assignable_users()
|> first()
|> assign_conversation()
bml_escape(string)
¶
Escape a BML string as a normal string.
iex> bml_escape(1) "\"1\""
iex> bml_escape("aa") "\"aa\""
iex> bml_escape("a\"a") "\"a\\"a\""
iex> bml_escape("a\na") "\"a\na\""
iex> bml_escape("#{bla}") "\"#{bla}\""
iex> bml_escape("[time] | do not want | private") "\"[time] | do not want | private\""
iex> bml_escape("is a [0] [0] /^reg/[=val]") "\"is a [0] [0] /^reg/[=val]\""
cancel_emit(schedule_id)
¶
Will cancel the given scheduled emit
. The identifier can be obtained
from the emit
statement; a scheduled emit (with in:
or at:
option) sets the variable with the name schedule_id
in the bot
script. You can use this variable to cancel it:
emit "status_update", [], in: 10
cancel_emit schedule_id
When you give the scheduled event a name
, it can also be cancelled
using that name:
emit "status_update", [], in: 10, name: "update"
cancel_emit "update"
chat_link(frontend, params \\ nil)
¶
Generates a link to this bot for sharing purposes.
say "Reach me on the web on this link:"
say chat_link("web_pwa")
If you want a link to the same channel that the current user is
chatting through, you can pass in the user.frontend
variable:
say chat_link(user.frontend)
The second argument, params
is used to add extra parameters to the
chat link, for instance the g
parameter to join a group.
say chat_link("web_pwa", g: group)
To create a link which leads into a users's session, use the
user_id
parameter:
say chat_link("web_pwa", user_id: some_user_id)
Account linking:
To create a link which leads into a user's session and then aliases
your current user ID to the new user ID, use user_id
combined with
alias_user_id
(which is the "old" user id):
say chat_link("web_pwa", user_id: some_user_id, alias_user_id: user.user_id)
create_chargeable_event(event_type, opts \\ [])
¶
Add a charge for a billable event.
create_todo(opts)
¶
Create a new todo item.
Options:
:title
: String with the title of the todo.:description
: The main body describing the work that needs to be done.:tags
: A list of tags to assign to the todo.:start_at
: When the todo should start.:due_at
: Deadline for when the todo needs to be a done.
delete_token(token_id)
¶
Delete a given token ID
See API integrations
detect_language(text)
¶
Detect the language of the given text, using the Google Natural Language processing API.
Only works when your account has Dialogflow support enabled.
end_session()
¶
Stop the interaction.
Note: deprecated: use
stop
instead
escalate(reason \\ "Assistance required", opts \\ [])
¶
Send an escalation message to the operators of this bot.
The operators which are on call are notified, either in the studio,
by web push notification, or with email. The return value is true
when an operator could be reached, or false
if there were no
operators on call.
The reason that can be passed in is supposed to be a human-readable message, describing why the bot needed to hand over the conversation. It is sent as the subject of the email and push notification.
Options can include:
-
:to
- the audience of the escalation. This is either a role tag (to: "tag:finance"
), which will send the escalation to all roles with thefinance
tag; an array of tags:to: ["tag:finance", "tag:frontdesk"]
; or a user id of a user in the studio:to: "studio:68eafe876f8a6e87a6e"
-
:tag
- the tag of the audience of the escalation.tag: "foo"
is a shorthand notation forto: "tag:foo"
.
flow_condition?(expression, opts \\ [])
¶
Check a given flow expression against the list of tags.
The expression
argument is the internal data structure that is the
output of the ui:widget: flow_condition
CMS input control,
consisting of a list of clauses which are evaluated in an OR'ed
fashion.
Options:
:tags
- the tags to check against; when not given, the currentconversation.tags
are used.
get_access_token(token_id)
¶
Return the plain access token for the given token identifer. This access token is used in HTTP calls to perform requests to the integrated service.
See API integrations
get_assignable_operators(opts \\ [])
¶
Get the list of agents and operators for this bot.
This list only includes people that have a direct operator or agent role on
the organisation to which this bot belongs, and are currently set to
available
.
Options:
:within_office_hours
: Filter the list to only users for whom it's currently within office hours.:presence
: Filter the list to users that match the given presence. Valid values include:"online"
,"offline"
, and"away"
.:emails
: Filter the list to only users with the given list of emails.
Examples:
_users = get_assignable_users(presence: "online", within_office_hours: true)
assign_conversation(random(_users))
_users =
get_assignable_users(
emails: [
"agent1@example.com",
"agent2@example.com"
],
within_office_hours: true,
)
get_attachments()
¶
Get the list of all attachments that the user uploaded in this conversation.
get_available_operators()
¶
List all operators which are on call, e.g. which have indicated to be available and are within their indicated office hours.
Returns a list of maps with the fields id
, name
,
profile_picture
, timezone
and status
. Status can be online
when they are logged in into the studio, or offline
when they are
not logged in.
get_conversation_transcript()
¶
Get a transcript of the current conversation as a text string.
It's possible for messages that have arrived right before calling this function to be missing from the transcript. This happens because the messages are fetched from Elasticsearch, which takes a bit of time to make the messages searchable after insertion. On most channels this won't be noticable, because we can wait a bit longer until they've been made searchable. However, on voice channels (such as phone calls), waiting is not an option, so you may encounter this issue there.
get_dialog_locale()
¶
Return the locale in which the bot is currently talking to the user.
get_full_token(token_id)
¶
Retrieves the full token information structure, mainly for inspection purposes.
See API integrations
get_next_office_hours_timeslot(office_hours, opts \\ [])
¶
Get the next pair of opening and closing times from a given date. Returns a list containing two items: the opening datetime and the closing datetime.
The office_hours
variable must be a 7-item array in which each
item represents an opening/closing hour. The first (0th) element in
the array is sunday, the last is saturday.
Options:
:timezone
- The timezone to consider (defaults touser.timezone
orbot.timezone
):date
- The reference date to consider (defaults todate_now()
)
get_operator_by_uuid(uuid)
¶
Retrieve a studio user's details by its UUID
get_phone_number_type(phone, default_country \\ nil)
¶
Try to determine for the given phone number what type of number it is.
If the given string cannot be parsed as a valid phone number (or something
other than a string was passed in), then this function will return :error
.
Otherwise, it will return one of the following:
:fixed_line
:mobile
:fixed_line_or_mobile
:toll_fee
:premium_rate
:shared_cost
:voip
:personal_number
:pager
:uan
:voicemail
:unknown
get_token_info(token_id)
¶
Return some basic information about the user that is connected to the specific token:
log get_token_info(user.tokens.google)
See API integrations
get_users_by_email(email)
¶
Retrieve user details for all users that are registered with the given email address. Used for account linking.
glob_scripts(pattern, opts \\ [])
¶
Return the titles of all scripts that match the given pattern.
Examples:
glob_scripts("flows/*")
glob_scripts("*.test")
Options:
:type
- restrict by valid script MIME type (text/bubblescript
,text/yaml+data
,application/json+data
, etc)
group_name(parts)
¶
Generates a deterministic group name for a list of identifiers based on a hash.
The identifiers can appear in any order, they are sorted before they are hashed. No ~ is prepended to the group name - you need to do this yourself.
inbox_link()
¶
Returns a link to this conversation in the DialoX Inbox.
json_build(data)
¶
Convert a given value to a string encoded as JSON.
json_parse(data)
¶
Convert the given JSON-encoded string to a data structure. Returns nil
when decoding fails.
jwt_build(payload, opts \\ [])
¶
Builds a JSON Web Token (JWT).
Returns a token string on success, or nil
on failure.
Note that the payload of the JWT is not encrypted, and is therefore readable to everyone that has access the token.
Options:
:signature_secret
: The secret key to use to validate the token. Defaults to the REST-API channel token. If a signature was not given and the REST-API channel is not configured, an error is raised.:expires_at
: An optional datetime string that indicates when the token should be expired. Raises an error if an invalid datetime was passed in. Translates to the JWTexp
claim.:not_before
: An optional datetime string that indicates when the token should become valid. Raises an error if an invalid datetime was passed in. Translates to the JWTnbf
claim.:issuer
: String containing theiss
field of the JWT. Defaults tonil
. Translates to the JWTiss
claim.:issued_at
: Whenfalse
, do not fill theiat
claim with the current time.
Examples:
token = jwt_build(%{my_data: "here"},
signature_secret: "hunter2",
expires_at: date_shift(date_now(), days: 1),
not_before: date_now(),
issuer: "Me"
)
jwt_parse(token, opts \\ [])
¶
Parses a JSON Web Token (JWT).
Returns a parsed map containing the payload on success, or nil
on failure.
Options:
:signature_secret
: The secret key to use to validate the token. Defaults to the REST-API channel token. If a signature was not given and the REST-API channel is not configured, an error is raised.:verify_signature
: Boolean to indicate if the token should be validated. Defaults totrue
.
Examples:
token = jwt_build(%{my_data: "here"}, signature_secret: "hunter2")
result = jwt_parse(token, signature_secret: "hunter2")
result.my_data == "here"
result = jwt_parse(token, verify_signature: false)
result.my_data == "here"
link_user(arg)
¶
Link the given user address to the current user.
If there is no conversation (or actually, a user_frontend) yet for the given addr, a user_frontend entry will be created and linked to the given user.
In case the given address already belongs to the current user, nothing happens.
In case the given address belongs to another user, the target user is merged into the current user.
Returns true
if linking was successful, or false
when an error happened.
liquid(template, context)
¶
Render a liquid template with the given variables.
log(value)
¶
Logs a debugging statement in the chat session's stream.
mail(to, subject, message, opts \\ [])
¶
Sends a notification e-mail to the given user.
mail("user@example.com", "Subject", "Hi there! This is your bot talking to you.")
This will send a pre-formatted HTML email, with the bot's name, profile picture and the message details.
HTML can not be used inside e-mail. The mail function is meant for basic notification and reminder messages.
The fourth argument can be given as options:
:cc
- a list of email addresses to put in the CC field:bcc
- a list of email addresses to put in the BCC field:link_url
- can be used to render a button below the text, which will link to the given URL.:link_caption
- The optional caption of the button, defaults to "Open link":image_url
- The URL of an image to show below the text (and below the button). Whenlink_url
is also set, the image links to the link URL as well.:unsubscribe_url
- The URL where the recipient can go to unsubscribe theirselves from messages like this. When set, an 'unsubscribe' option will be added to the mail message's footer.:attachments
- List of attachments to send with the email. Each entry must be a user-uploaded attachment or an object withtype
(one of image, audio, video, file) andurl
fields. It's also possible to send a string as attachment usingtype: :memory
and the:content
,:content_type
and:filename
fields.:locale
- The locale to localize the unsubscribe link in. Defaults toen
.
mail("user@example.com", "Subject", "Body", link_url: "http://example.com", image_url: "http://example.com/test.jpg")
See e-mail handling for more information on the mail capabilities of the platform.
mustache(template, context)
¶
Render a mustache template with the given variables.
oauth_link(alias)
¶
This function generates a link for the requested integration which starts the OAuth authorization flow.
The one required argument is the name of the provider or alias of which integration to start:
say oauth_link("google")
See API integrations
phone_format(phone, format \\ :national, default_country \\ nil)
¶
Format a number to a specific format.
Returns :error
if the given string cannot be parsed as a valid phone number.
The allowed formats are:
:e164
:international
:national
:rfc3966
Examples:
iex> phone_format("0612345678", :national)
"06 12345678"
iex> phone_format("+31612345678", :national)
"06 12345678"
iex> phone_format("0612345678", :e164)
"+31612345678"
iex> phone_format("0612345678", :rfc3966)
"tel:+31-6-12345678"
phone_parse(phone, default_country \\ nil)
¶
Parse a phone number and return it in normalized, international format.
phone_parse("0612345678")
→ "+31612345678"
When no country code is given in the input, the number is assumed to be local to the bot's region.
pre_escalate(reason \\ "Assistance required", opts \\ [])
¶
Use pre-escalate to indicate to external inbox channels that a chat is being qualified and will soon be waiting for a chat operator.
query(recipient, name, payload \\ [])
¶
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.
read_script(title)
¶
Read a script file by name, returning its text.
resolve_dialogflow_intent(text, lang \\ nil)
¶
Check if the given text resolves to a dialogflow intent
If an intent matches it returns the intent structure, otherwise nil
.
Like the global intent matcher, this function looks first in a
locally defined Dialogflow agent (if the dialogflow
Google Service
account JSON file was found); otherwise it uses the
globally-available Botsquad-Defaults Dialogflow agent.
resolve_gpt_local_intent(text, intents, opts \\ [])
¶
Deprecated, please use resolve_llm_intent() instead
resolve_llm_intent(text, opts \\ [])
¶
Check if the given text resolves to any of the given intents using GPT
Options: - question: The question that the bot asks - prompt: Override the GPT prompt used (default: classify_llm_intents) - locale: Override the locale to use - intents: the list of intents to restrict to (defaults to all LLM intents)
resolve_qna_intents(text, opts \\ [])
¶
Check if the given text resolves to one or more QnA intents
Returns the list of matched intents, in order of confidence.
Options:
-
provider_agent
- Name of an alternative qnaprovider_agent
, when not given the default agent is used. -
:locale
- a locale string to override the locale that is selected for selecting the QnA model.
shorten_url(url, opts \\ [])
¶
Create a shortened URL, for use in SMS messages and such.
The shortened URLs are scoped to the current bot and, as such, are removed when the bot is removed. Shortening the same URL again returns the same short URL.
Only HTTP and HTTPS URLs can be shortened. Giving invalid input to
the function returns nil
instead of a short URL.
Expiration date:
It's possible to give a date at which point the URL stops working (and
will return HTTP 404). The date given with :expires_at
must be in the
future. When using :ttl
, it will add the given number of seconds to the
current date.
Example:
shorten_url(url, ttl: 86400)
# The above :ttl is the same as:
shorten_url(url, expires_at: date_shift(date_now(), seconds: 86400))
sms(phone, message, opts \\ [])
¶
Send a notification SMS message to the given phone number.
The phone number must be specified in full international format, e.g. +31641345678. The sender of the SMS is the alphanumeric sender "DialoX".
In order for this function to work, you need to have setup a Twilio connection to your existing SMS service. Read more about SMS handling
Options:
sender
- Override the SMS sender using the given alfanumeric sender string or phone number. Only works with Enreach SMS and when the sender is part of the SMS sender allowlist of the organisation.
sms_notify(phone, message)
¶
Deprecated, please use sms() instead
spawn_function(function, args)
¶
Run a function asynchronously
Runs the given function asynchronously. When the function finishes, its return value is sent to the calling process as an event.
The name of the event is returned as the return value of spawn_function()
.
dialog main do
# spawn the function in the background
_eventname = spawn_function(:worker, ["some_arg"])
say "We are processing your request, one moment"
_result = await(event(_eventname))
say("HTTP worker result = #{_result.payload}")
end
function worker(_arg) do
log "Going to post in the background.."
_result = http_post @url
log "done"
return _result.body
end
As the name of the event is dynamic, the event should be awaited on
in the main conversation using await
or with the wait control.
@constants
are available in the spawned function, as well as the
global variables. However, the global variables CANNOT be changed:
they are set to a snapshot of the globals at time the function was
spawned. Any changes to the globals not carried over to the main
conversation, these are lost when the spawned function is done.
The lifecycle of a spawned function is limited to the lifecycle of
the conversation: as soon as the conversation finishes (via close
or similar), all still running spawned functions will exit.
Side effects like tag
and logging is supported in spawned
functions. However, the remember
and forget
statements are
forbidden, as these could cause race conditions.
spawn_group(group \\ nil, context \\ %{})
¶
Spawn a group process.
strip_emoji(string)
¶
Remove any emoji from a given string.
strip_html(string)
¶
Remove HTML tags from a given string.
strip_markdown(string)
¶
Remove Markdown formatting from a given string.
strip_speechmarkdown(string)
¶
Remove any Speech Markdown formatting from a given string.
tag?(tag)
¶
Retrieve the value of a prefixed tag, or true
/ false
for a
normal tag, for the tags that are set on the current conversation.
tag "workflow::assigned"
say tag?("workflow")
Will say assigned
.
tag "hello"
if tag?("hello"), do: say "Hello is set"
testing?()
¶
Helper function for checking whether the bot is running as part of a test case
Returns true
if that is the case, or false
otherwise.
Using this function can help you switching parts of your bot (mocking data, HTTP calls etc.) when the bot tests are being run.
text_to_speech(smd, opts \\ [])
¶
Perform text-to-speech on the given speech markdown string.
Returns the URL to the stored MP3 audio recording. Results are cached so that performing the same text-to-speech twice will return the same URL.
text to speech can fail because the requested locale does not have a
corresponding voice configuration, or the Google TTS backend returns
an error. In both cases, nil
is returned to the caller.
Options:
:locale
— The locale to speak in. Must have a voice configured in the corresponding connected channel. (if the conversation is not on a voice channel, it is assumed the REST API channel is enabled which also has a voices configuration).
transcribe(input, request_params \\ [])
¶
Transcribe the given audio attachment or URL into a %Bubble.Message{}
struct.
Options:
locale
- use recognition in given locale (defaults to locale of conversation)provider
- Eithergoogle
,microsoft_openai
,google_ai
ordeepgram
.model
- the name of the speech model (default:latest_long
for Google,whisper-1
for Microsoft OpenAI,nova-2
for Deepgram, gemini-1.5-flash for GoogleAI)
See the transcribe REST API docs for more information on all available transcribe parameters.
unidecode(text)
¶
Transliterate a string with accented characters to a plain ASCII version without any accents or special symbols.
whatsapp(phone, template_id, opts \\ [])
¶
Send the given Whatsapp template message to the given phone number.
The current bot must have a valid 360dialog Whatsapp connection setup up in order for this function to work. Furthermore, the given
The given whatsapp template identifier (template_id
) must exist in
the conversation's locale (or with the overridden locale:
option).
Options:
-
:parameters
- a map of numbered body parameters, e.g.%{"1" => "Pete", "2" => "example"}
; can only used for basic text-only templates. Will be ignored if:components
option is given. -
:components
- A full list of template component parameters (https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#template-object) -
:locale
- a locale string to override the locale that is selected for sending the template message.
within_office_hours(office_hours, opts \\ [])
¶
Calculate whether the given date is within the given week day office hours.
The office_hours
variable must be a 7-item array in which each
item represents an opening/closing hour. The first (0th) element in
the array is sunday, the last is saturday.
Options:
timezone
- The timezone to consider (defaults touser.timezone
orbot.timezone
)date
- The reference date to consider (defaults todate_now()
)
write_script(title, contents, opts \\ [])
¶
Write a script file by name.
This function is primarily meant for writing migrations that work on content scripts. It only works given the following conditions:
- The script (by title) must already exist, or the
type:
option must be given - The function is called within the DialoX studio, in preview mode (debugging)
- The user that calls the script must be allowed to change the script
The function only works for existing scripts. The content type of the script is unchanged, and the content must be formatted in the right format; e.g. the caller must know that the file is JSON, bubblescript, YAML, etc. The draft version of the script is written; e.g. a manual publish is still required to put the change 'live'.
Options:
:type
- a valid script MIME type (text/bubblescript
,text/yaml+data
,application/json+data
, etc)
yaml_build(data)
¶
Convert a given value to a string encoded as YAML.
yaml_parse(string)
¶
Convert the given JSON-encoded string to a data structure. Returns nil
when decoding fails.