Skip to content

Chat Context

Guido edited this page May 6, 2020 · 10 revisions

Node-RED has two variable context global and flow, the first is available everywhere in the app, the second just in the executed flow.

RedBot introduces the chat context where is possible to store information related to the specific user. The Receiver node store here some default information like chatId, username, authorized, firstName, lastName, etc. but it's possible to store any kind of information.

Two chat context providers are available

  • Memory (default): it's a very fast and volatile storage, means that when the server is restarted all the stored data is lost. It' the default one (good for experimenting) and all the methods are synchronous
  • Plain file: it stores data in a plain json file, all the methods are asynchronous.
  • SQLite: it stores context in a local *.sqlite file

To get the chat context in a Function node (using the Memory context provider):

const chat = msg.chat();
console.log(chat.get('authorized')); // is the user authorized
console.log(chat.get('username')); // guidone72
chat.set('my_stuff', 'remember that');

The same with Plain file on SQLitecontext provider

const chat = msg.chat();
chat.get('authorized')
  .then(authorized => {
    console.log(authorized); // is the user authorized
    node.send(msg);
  });

since it's asynchronous all methods return a Promise. It's also possibile to combine multiple calls

const chat = msg.chat();
chat.get('authorized', 'username')
  .then(variables => {
    console.log(variables.authorized); // is the user authorized
    console.log(variables.username); // guidone72
    return chat.set('my_stuff', 'remember that');
  })
  .then(() => node.send(msg) });  // pass thru when the chat.set is over

Context keys

Platform keys

Platform keys are pre-populated by RedBot: chatId (a unique identifier for a user in a specific platform), userId (a unique identifier of a user through different platforms) and transport. Values in the chat context are meant to be persisted over the time and different platforms, for this reason these keys are read-only and cannot be modified. They can be accessed by javascript msg.chat().get('chatId') or in templates {{chatId}} for retro-compatibility purposes, by they really don't belong to the chat context.

Flow keys

Some keys are pre-populated by RedBot: firstName, lastName, language, authorized, pending. These are specific to the flow and the used platform and can be modified or deleted by the msg.chat().* methods. Not all the chat platforms provide such informations and/or may be different (unless a Mission Control MC Store node is used to reconcile the data): for example a user can have the Telegram client in the Italian language and the Messenger client in English language. The {{message}} key is the current inbound message (from the user) and the {{messageId}} is the platform-dependent unique id (generally used to edit/delete already sent messages)

Global keys

It's possibile to access variables in the Node-RED's global context using the handlebars-like notation, for example {{global.my_global_variable}}

Payload

Some nodes (like MC GraphQL) return data on the msg.payload key of the inbound message. Such value can be used in the handlebars-like notation, for example a payload of an inbound messag

{
  total: 42,
  shipping: {
    address: 'Nowhere street,
    city: 'Milan'
  }
}

can be used the configuration panel of any RedBot nodes using the dot notation, for example:

Your order of {{payload.total}} will be shipped to {{payload.shipping.address}}, {{payload.shipping.city}}

User defined keys

The chat context can store any kind of data (string, numbers, objects, etc), for example

const chat = msg.chat();
Promise.resolve(chat.set({
  my_var: 'Guido',
  another_var: {
    subkey: 42
  }
)).then(() => node.send(msg));

can be used in the Message node

My name {{my_var}} and the answer to the universe and everything {{another_var.subkey}}

Chat context methods

All context providers support these methods:

Method Type Description
.get(key) any Return the value of the key
.get(key1, key2, ...keyN) object Return an hash with the values of the requested keys { key1: ..., key2: ... }
.set(key, value) context Set the value of the key
.set({key1: ..., key2: ...}) context Set multiple key values
.remove(key) context Remove value for the key
.remove(key1, key2, ...keyN) context Remove multiple keys
.clear() context Clear all the chat context
.dump() context Dump in console the chat context
.all() context Get all keys/values

Plain file and SQLite context always returns a JavaScript Promise, while the Memory context has just synchronous methods. In the examples it's used the Memory context for readability purpose, it's even easier to debug since it's cleared at every restart. In order to use both contexts in the same code, just wrap the calls in Promise.resolve(...) for example:

const chat = msg.chat();
// doesn't matter if chat context is Memory or an asynch one
Promise.resolve(chat.get('my_var'))
  .then(myVar => {
    // do something
  });

Template Variables

Some most of the nodes like Message node evaluates the specified text with a very simple template system (Handlebars-like syntax). For example to say hello to the user

Hi, {{firstName}}!

There are some predefined variables in each chat context

Method Type Read only Description
chatId string yes Unique identifier for a user and a specific transport. It's needed to initiate a conversation with a user
userId string yes Unique identifier for a user, related to a userId can be multiple chatIds for each platform.
messageId string no The message id of the last sent message, generally used to modifiy/delete a previously sent message
firstName no First name, when available (in Telegram must be specified in preferences)
lastName no Last name, when available (in Telegram must be specified in preferences)
authorized boolean no Whether the user is authorized or not
transport string yes Current message transport, could be telegram, facebook, slack, etc
message string no the current message from the user in string format
language string no the language of the chat client (i.e. en, it, etc). Not all chat platforms provides the user's language
pending boolean no Tells if the chatbot has some pending requests and cannot answer (for example Dialogflow node set this flag while requesting the external API)
Clone this wiki locally