God API
The God API allows services to listen to real-time activity taking place on a Webstrates server through a websocket connection.
To enable the God API, define a God API key in the Server Config and then restart the
Webstrates server. Afterwards, the God API will be available at ws://localhost:7007/ws?noop
. (The ?noop
is added to
prevent the server from handling this connection as a regular Webstrates websocket connection. )
All commands sent to the server must include the ga
(God Action) key and a command for the server.
To authenticate with the server, send a JSON object key
command along with the key defined in the server config.
{ "ga": "key", "key": "<key>" }
Afterwards, you may subscribe to subjects. A subject is either a webstrateId, a userId, or a list of either. For each subject, you may subscribe to one (or all) of three types of events:
dom
– DOM changes. If subscribing to a user, this is all DOM changes caused by the user. If subscribing to a webstrate, this is all DOM changes happening in the webstrate.user
– User actions. If subscribing to a user, this is any joins and parts the user performs. If subscribing to a webstrate, this is joins and parts occuring in the seecific webstrate.signal
– Signals. If subscribing to a user, this is any signals sent by the user. If subscribing to a webstrate, this is signals sent within a webstrate. (Keep in mind that – as an optimization – if a signal is sent in a webstrate with no receivers, it will not be transmitted to the server, and thus not be registered by the God API either.)
A few examples
To subscribe to webstrates, the subscribeWebstrate
command must be used, along with a webstrateId (or array of
webstrateIds). Additionally, a filter
must be provided, containing any of the three events (dom
, user
, signal
).
As with the webstrates, this can be a single string value or an array.
Additionally, all subscriptions must include a subscriptionId
, which can be any string. A randomly generated string is
suitable.
A subscription to all DOM changes in the webstrate honest-kangaroo-9
may therefore look something like:
{
"ga": "subscribeWebstrate",
"subscriptionId": "45czu6mbbqo",
"webstrates": "honest-kangaroo-9",
"filter": "dom"
}
And to subscribe to multiple webstrates (e.g. frontpage
and other
) and events (e.g. user
and signal
) at once:
{
"ga": "subscribeWebstrate",
"subscriptionId": "45czu6mbbqo",
"webstrates": ["frontpage", "other"],
"filter": ["user", "signal"]
}
To subscribe to a user (or multiple), the users
value must be defined as either a single userId (or an array of
userIds). A subscription to all signals from userId kbadk:github
could look like this:
{
"ga": "subscribeUser",
"subscriptionId": "45czu6mbbqo",
"users": "kbadk:github",
"filter": "signal"
}
A real-life NodeJS example
For a real-life example, check out Webstrates Monitor. This service is built on NodeJS and uses the data received from the God API to create an activity database which applications may then query for historical data.
And another NodeJS example
To use the below example NodeJS must be installed on the machine. To get started, create a new folder with a file
index.js
containing the code below. Modify the file with correct server host (line 80) and key (line 35), then run:
npm install --prefix . websocket
To install the websocket package in the current folder, followed by running:
node index.js
The script will create the three subscriptions used in the above examples, i.e. subscriptions to:
- All DOM changes to webstrate
honest-kangaroo-9
. - All user joins/parts as well as signals in the webstrates
frontpage
andother
. - All signals sent by userId
kbadk:github
.
The events matching any of the three subscriptions will be logged to the console when the script is running.
const WebSocketClient = require('websocket').client;
const client = new WebSocketClient();
const timestamp = () => (new Date()).toLocaleTimeString();
const log = (...args) => console.log(`[${timestamp()}]`, ...args);
const error = (...args) => console.error(`[${timestamp()}]`, ...args);
client.on('connectFailed', error => {
log(error.toString());
});
client.on('connect', conn => {
log('Connected.');
conn.on('error', error => {
error(error.toString());
});
conn.on('message', message => {
if (message.type === 'utf8') {
log('↓', message.utf8Data);
}
});
const send = (msg, silent) => {
msg = JSON.stringify(msg);
!silent && log( '↑', msg);
conn.sendUTF(msg);
};
// Authenticate ourselves with the God API key defined in config.json.
send({ ga: 'key', key: '<key goes here>' });
// Each connection requires a unique subscrptionId. We just generate a pseudo-random string.
const subscriptionId = Math.random().toString(36).substr(2)
// You can subscribe to DOM changes, signals or user actions (join/part) for either a specific
// user or a specific webstrate.
// Subscribe all all DOM changes in the webstrate honest-kangaroo-9 by any user.
send({
ga: 'subscribeWebstrate',
subscriptionId,
webstrates: 'honest-kangaroo-9',
filter: 'dom'
});
// Subscribe to any join/part or signals by any user in two webstrates: frontpage and other.
send({
ga: 'subscribeWebstrate',
subscriptionId,
webstrates: ['frontpage', 'other'],
filter: ['user', 'signal']
});
// Subscribe to any signals sent by user kbadk:github regardless of webstrate.
send({
ga: 'subscribeUser',
subscriptionId,
users: 'kbadk:github',
filter: 'signal'
});
// Websocket will automatically close after 30 seconds of inactivity. Send keep alive message
// every 25 seconds.
setInterval(() => {
send({ type: 'alive' }, true);
}, 25 * 1000)
conn.on('close', (code, reason) => {
log(`Closed: ${reason} (code ${code})`);
});
});
// `?noop` to establishing a connection with ShareDB.
client.connect('wss://<host of server>/ws/?noop');