Status allows to register chat commands via it's API. Due to a number of recent low-level changes and low visibility of this feature part of it have been broken.
This document provides a high-level view of the current state of the API and associated limitations. Features that used to work are also detailed.
TLDR
Status bots features:
- small JS programs that can be triggered by users in a chat
- interact via messages, can have complex UI (suggestions and messages)
- isolated (so secure)
- optional webview (eventually fullscreen) for complex JS/HTML UI
- hability to suggest command execution to chatting partner
- react and manipulate chat input
Current limitations:
- can only be added when status account is in debug mode (enable dev mode, then start debug mode via console)
- must be manually added from dev env, no external distribution model (like a catalog or store)
- chatbot create a new contact with associated local command
- global commands can be added, and associated contact hidden
- chatbot JS must be hosted on an HTTP server, JS file loaded remotely every time the account is opened
- very manual UI model, limited by options offered
- no inline interactions (purely message based)
This tool is a nodejs based utility allowing to register DApps or bots on a running device identified by its IP. It mostly serves 3 purposes:
- discovery of devices and associated running bots / DApps
- registration of bots / DApps
- light dev facility to refresh those apps
What this tool offer:
- scan network to detect devices running in debug mode
- add / remove
contact
(either DApps or bots) to an identified device - switch geth network used for Dapps of an identified device
- list
contacts
currently installed in an identified device - watch a directory and refresh (eventually manually) a Dapp
- access log messages for a
contact
When debug
mode is enabled in the console chat, an embedded HTTP server (using react-native-http-bridge)
is started and listens to incoming HTTP POST request to manipulate status internal states.
This embedded server also handles the mDNS advertisment logic.
This tool suffer from endemic installation issues. It's pretty hard to setup notably due to it's usage of mDNS protocol (used to discover devices) and difficulty to install watchman.
Since its inception status significantly evolved, most specifically around DApps which are now first class citizen. The dev facility (watch, reload, switch-node) might be a little week compared to regular web tools. One might wonder what is status added value here compared to a regular web dev env. (Note that status offer DApps remote debugging capacities allowing dev to easily debug their DApps running on status).
Local installation of bots is a subset of the complete extensions publication and hosting story. Current solution is not practical for end users.
switch-node
is definitively a feature we need to keep. This allows DApps / extensions developer to target a local chain that can be more easily manipulated (e.g. using ganache). This must modify newtork for both DApps and bots.
This feature could be provided by allowing users to provide their own node URL in Profile / Advanced settings.
Note It has to be clarified how this plays with current network switching capacities.
API (as documented by https://docs.status.im/)
Documentation first details how to use status-dev-cli
and related issues, including how to workaround genymotion configuration.
Then creation of a DApps is detailed using Embark, Truffle and manually.
It would make sense to separate our docs between extensions, DApps and smart-contract creation.
Bots are added as a separate contact. Comands are then available when chatting with this contact.
3rd party developers can leverage a set of JavaScript APIs available via the status
global object.
A bot can perform logic when installed. A common pattern is to send messages to great users.
status.addListener("init", function (params, context) {
status.sendMessage("Hello user!");
});
status.addListener("on-message-send", function (params, context) {
var result = {
err: null,
data: null,
messages: []
};
result["text-message"] = "You're amazing, master!";
return result;
});
Hook on every message received. Can answer back a string
message.
Register a command that will be accessible in the command bar. How the command is displayed (as a message) can be customized via the preview
property (using an hiccup based syntax).
status.command({
name: "hello",
title: "HelloBot",
description: "Helps you say hello",
color: "#CCCCCC",
preview: function (params) {
var text = status.components.text(
{
style: {
marginTop: 5,
marginHorizontal: 0,
fontSize: 14,
fontFamily: "font",
color: "black"
}
}, "Hello from the other side!");
return {markup: status.components.view({}, [text])};
}
});
Custom logic can be triggered when executing (sending) the command.
status.command({
name: "hello",
title: "HelloBot",
description: "Helps you say hello",
color: "#CCCCCC",
handler: function (params) {
return {
event: "request",
params: [params.amount],
request: {
command: "send",
params: {
amount: params.amount
}
}
};
}
});
A command can accept typed parameters
with an optional suggestions
. When filling a command, each parameter with a suggestion will trigger the opening of a panel that usually contains predefined values. A common pattern is to fill this parameter when the suggestion is pressed.
status.command({
name: "greet",
title: "Greeter",
description: "Helps you choose greetings",
color: "#0000ff",
params: [{
name: "greet",
type: status.types.TEXT,
suggestions: helloSuggestions
}]
})
function helloSuggestions() {
var suggestions = ["Hello", "Goodbye"].map(function(entry) {
return status.components.touchable(
{onPress: status.components.dispatch([status.events.SET_VALUE, entry])},
status.components.view(
suggestionsContainerStyle,
[status.components.view(
suggestionSubContainerStyle,
[
status.components.text(
{style: valueStyle},
entry
)
]
)]
)
);
});
// Let's wrap those two touchable buttons in a scrollView
var view = status.components.scrollView(
suggestions
);
// Give back the whole thing inside an object.
return {markup: view};
}
For more complex scenario data can be stored / retrieved from an internal reactive database.
function doubledValueLabel(params) {
return "sliderValue = " + params.value +
"; (2 * sliderValue) = " + (2 * value);
}
status.defineSubscription(
// the name of subscription and the name of the value in bot-db
// associated with this subscription
"doubledValue",
// the map of values on which subscription depends: keys are arbitrary names
// and values are db paths to another value
{value: ["sliderValue"]},
// the function which will be called as reaction on changes of values above,
// should be pure. Returned result will be associated with subscription in bot-db
doubledValueLabel
);
status.setDefaultDb({
doubledValue: doubledValueLabel({value: defaultSliderValue})
});
// Some view that depends on 'doubledValue' and modifies it
// Note 'subscribe' and 'dispatch' calls
var view = ["view", {},
["text", {}, "Balance " + balance + " ETH"],
["text", {}, ["subscribe", ["doubledValue"]]],
["slider", {
maximumValue: ["subscribe", ["balance"]],
value: defaultSliderValue,
minimumValue: 0,
onSlidingComplete: ["dispatch", ["set", "sliderValue"]],
step: 0.05
}],
['touchable',
{onPress: ['dispatch', ["set-value-from-db", "roundedValue"]]},
["view", {}, ["text", {}, "Set value"]]
],
["text", {style: {color: "red"}}, ["subscribe", ["validationText"]]]
];
Allows to send a message that encapsulates a command call. Useful when you want to suggest an action to your chatting partner.
status.response({
name: "confirmation-code",
color: "#7099e6",
description: I18n.t('confirm_description'),
sequentialParams: true,
params: [{
name: "code",
type: status.types.NUMBER
}],
validator: function (params) {
if (!/^[\d]{4}$/.test(params.code)) {
var error = status.components.validationMessage(
I18n.t('confirm_validation_title'),
I18n.t('confirm_validation_description')
);
return {markup: error};
}
}
});
Change the text input:
status.components.dispatch([status.events.SET_VALUE, "@browse url"])
React on text input changes:
status.addListener("on-message-input-change", function (params, context) {
});
Some global Javascript objects are accessible to bots: web3
and localStorage
.
Status relies on the bots API for its internal commands. Note that those commands also rely on features not available to external bots.
Used to provide debug
and faucet
commands.
Use the following features:
- command (params, preview, suggestions, shortPreview, validator)
- status.response
- "on-message-input-change"
- "on-message-change"
Used to provide send
and request
commands.
Use the following features:
- command (scope, parmas, validator, async handler, preview, shortPreview)
- status.defineSubscription
- status.response
- jail implementation on top of JSC
- JS API
- status bots