This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Components

Aura bridge components

Description and role of the main Aura Bridge components

Introduction

aura-bridge components are shown in the following schema and described below or in specific documents.

Bridge components

Server

The web server is implemented using express, that is the main web framework for nodeJS. It uses openapi-backend on top of Express to allow handling the OpenAPI v3 file.

It is in charge of setting up all the rest of the components that are needed during a request processing, as well as reading the before mentioned swagger file and setting up all the routes defined in it.

Access here to aura-bridge APIs definition.

Middlewares

Each route published in the API definition file is handled by a controller, but before a request lands on its controller, it goes through a series of middlewares, that provides some common steps needed by all the controllers of the server, such as: request authorization, request validation, common parameters extraction, logging, metrics initialization, etc.

Plugins

aura-bridge is composed of plugins, which provide functionality to the bridge.

Find complete information regarding this component in Aura bridge plugins.

Message syncer

One of the main features of aura-bridge is to be able to keep the order of the messages sent to the user, to assure that they are rendered in the correct order, so they are understandable by the users.

The component in charge of guaranteeing this order is call message syncer. It is an internal queue message system that lays on a two-level cache: a local one, that improves performance, and a remote one, to provide consistency.

Know the the detailed process for response messages synchronization managed by the message syncer.

Metrics

Aura metrics system is based on Prometheus that is an open-source systems monitoring and alerting toolkit originally built at SoundCloud.

Prometheus service pools every component to get the metrics generated during the last time period. Every component counts on a private endpoint (not accessible from internet) called /metrics where Prometheus requests the metrics.

For further information about metrics, read Metrics in aura-bridge.

1 - Plugins

Aura bridge plugins

Aura bridge plugins are components that provide different functionalities to the bridge

Introduction

aura-bridge is composed of plugins, which provide functionality to the bridge. Plugins work independently, the same way as a service in a microservices oriented architecture: isolated, self-contained and without affecting other existing functionalities in the system.

The aura-bridge plugins system also allows an OB to generate new plugins and create an “ad hoc” aura-bridge, with the functionalities required and removing those which are not needed for the OB.

ℹ️ The practical process for the generation of plugins is included in develop a plugin and activate in aura-bridge.

Discover in the current documents detailed information regarding aura-bridge plugins:

Types of plugins

There are different types of plugins:

  • Api. REST services that perform specific tasks not associated with the communication with a channel.

  • Client. These plugins define clients that can be used to communicate with a channel. These clients are normally used by processor plugins.

  • Processor. Plugins in charge of communicating with a channel, transforming the message received from a source channel to a destination channel.

  • Service. Utility plugins to be used by the rest of plugins.

Plugins management

As indicated in the previous section, aura-bridge uses the library@architect/architect for the management of plugins, so it is the architect library that is responsible for managing the dependencies injection in each module.

To create the architect application, aura-bridge uses the PluginManager module (located in the modules/plugin-manager folder). This module starts as the rest of modules at the aura-bridge start-up.

The PluginManager performs the following tasks:

  • It starts the architect application with the plugins defined in plugin-config.json file, located at the root of the aura-bridge component.
  • It adds the core modules to the IOC context. See the section modules added by aura-bridge.
  • It stores the information of each module defined in the plugins.

An example to define aura-bridge-example-service plugin of the previous section is shown below:

/* file: plugin-config.json */
[
    "./lib/plugins/aura-bridge-example-service",
]

Currently, the plugins are in the src/plugins folder of aura-bridge, but in the future these plugins should be independent libraries and could be charged by library name (for example: @telefonica/aura-bridge-example-service).

Apart from the aura-bridge core environment variables, each plugin can define its own specific variables. Access the document Aura bridge environment variables and find them in the section corresponding to your plugin.

Plugin basic structure

Currently, aura-bridge uses @architect/architect library for plugins management.

A basic plugin must define at least:

  • A package.json file defining the library, like any other JavaScript library, with a plugin section defining which modules it consumes and supplies.
  • A source code file that defines the modules that it supplies (index.ts for example).

The structure of this basic plugin is as follows:

aura-bridge-example-service
├── index.ts
└── package.json

A couple of examples with the content of each file are included below:

/* file: index.ts */
import { PluginType, registerPlugin } from '@telefonica/aura-bridge-common';
import { v4 as uuidv4 } from 'uuid';
import { Services } from './example-consume-services';

export = registerPlugin([
    {
        type: PluginType.Service,       // Plugin service type
        name: 'exampleService',         // Name of the plugin service
        instance: {                     // [provides] Instance that provides the module
            getUniqueId() {
                return uuidv4();
            }
        },
        services: Services              // [consumes] Needed modules are added here
    }
]);
/* file: package.json */
{
    "name": "@telefonica/aura-bridge-example-service",
    "version": "1.0.0",
    "main": "index.js",
    "private": true,
    "plugin": {
        "consumes": [
            "configurationManager"
        ],
        "provides": [
            "exampleService"
        ]
    }
}

The modules specified in the plugin.consumes field define the services that are needed by this plugin. The modules specified in the plugin.provides field define the modules that this plugin offered.

Plugins modules

aura-bridge currently adds three modules that can be used by the different plugins. To use them, it is only necessary to add the package.json dependencies on plugin.consumes (like any other module/component).

  • configurationManager: Module with the aura-bridge configuration information.
  • auraBridgeCache: Module to manage the aura-bridge cache.
  • prometheus: Service for metrics management.

A plugin can provide one or more plugin modules and each plugin module can be of a different type. Each type of module is intended to add a specific functionality to aura-bridge.

The existing types are defined in PluginType, which are described in the following sections.

export enum PluginType {
    Api = 'Api',
    Client = 'Client',
    Processor = 'Processor',
    Service = 'Service'
}

All plugins modules must follow the base Plugin interface:

export interface Plugin {
    /**
     * Plugin module name.
     */
    name: string;
    /**
     * Object where the services that plugin module consume will be injected (IOC).
     */
    services?: unknown;
    /**
     * Plugin module type.
     */
    type?: PluginType;
    /**
     * @hapi/joi schema definition with the variables used by the plugin module.
     */
    configuration?: { [key: string]: any; };
}

API plugin module

Use the aucli tool to generate the scaffolding of an API plugin: aucli bridge generate api

An API plugin module type mainly contains:

  • At least one source code file that defines the API plugin module and controllers for each of the operations specified in the swagger definition.
  • A package.json file defining the library, with a plugin section defining which modules it consumes and supplies.
  • A swagger.yaml file that contains a detailed description of the entire API defined by the plugin.

The basic structure for a API plugin module type is as follows:

aura-bridge-example-api
├── index.ts
├── package.json
└── swagger.yaml

A type API module must implement the PluginApi interface:

export interface PluginApi extends Plugin {
    /**
     * List of controllers (Express) defined by the plugin module.
     */
    controller: { [operationId: string]: PluginApiController | ((req: Request, res: Response) => Promise<void>) };
}

export interface PluginApiController {
    /**
     * Is directline processor?
     */
    isDirectlineProcessor?: boolean;
    /**
     * Channel type.
     */
    channelType?: BridgeType;
    /**
     * Express controller function.
     */
    controller: (req: Request, res: Response) => Promise<void>;
    /**
     * Custom error handler.
     */
    errorHandler?: (err: any, request: express.Request, response: express.Response, next: express.NextFunction) => void;
}

A couple of examples with the content of each file are included below:

/* file: index.ts */
import { PluginType, registerPlugin } from '@telefonica/aura-bridge-common';
import { Services } from './example-api-consume-services';

const controller = {
    hello: (req: Request, res: Response) => {
        res.send({ message: 'Hello from example api!' });
    }
}

export = registerPlugin([
    {
        type: PluginType.Api,           // Plugin module type
        name: 'exampleApi',             // Plugin module name
        controller,                     // Controllers definitions (linked to swagger operationId),
                                        // or it is possible to also use the PluginApiController interface
        services: Services,             // [consumes] Needed modules are added here
    }
]);
/* file: package.json */
{
    "name": "@telefonica/aura-bridge-example-api",
    "version": "1.0.0",
    "main": "index.js",
    "private": true,
    "plugin": {
        "consumes": [ ],
        "provides": [
            "exampleApi"
        ]
    }
}
# file: swagger.yaml
openapi: 3.0.0
info:
  title: aura bridge example api
...
paths:
  /example/hello:
   get:
     operationId: hello             # Function name defined in "controller".
     x-router-controller: plugins   # It should always be "plugins".
     responses:
       '200':
         description: OK
         headers: { }

An API module can also define its own error handling and not use the default error handling defined in the bridge core.

Example:

public errorHandler(err: any, request: express.Request, response: express.Response, next: express.NextFunction) {
    const corr = (request as any).correlator;

    let status: number = 200;
    let message: string = 'Accepted request';

    if (err.statusCode === 401) {
        status = err.statusCode;
        message = 'Unauthorized request';
    }

    // An error in swagger validation is simply logged as a warning
    if (err.failedValidation) {
        logger.warning({
            msg: `Bad request on swagger validation. The first error message was: ${err?.validationResult[0]?.message}`,
            stck: err.validationResult, corr,
            step: AuraBridgeStep.Controller
        });
    }

    response.status(status).send({ code: status, message });
}

Client module

Use the aucli tool to generate the scaffolding of a client module: aucli bridge generate client

A client module type mainly contains:

  • At least one source code file that defines the client module and the client itself.
  • A package.json file defining the library, with a plugin section defining which modules it consumes and supplies.

The basic structure for a client module type is as follows:

aura-bridge-example-client
├── index.ts
├── package.json

A type client module must implement the PluginClient interface:

export interface PluginClient extends Plugin {
    /**
     * Client instance.
     */
    instance?: any;
    /**
     * Returns a client instance if it must be initiated asynchronously.
     */
    getInstance?: () => any;
}

The instance field or the getInstance method should be used to obtain the client, but not both. If the client does not need to be initiated asynchronously, the client definition in the instance field is the preferred option. If it is necessary to asynchronously start the client, the getInstance method must be used.

A couple of examples with the content of each file are included below:

/* file: index.ts */
import { PluginType, registerPlugin } from '@telefonica/aura-bridge-common';
import { Services } from './example-consume-services';
import { ExampleClient } from './example-client';

export = registerPlugin([
    {
        type: PluginType.Client,
        name: 'ExampleClient',
        instance: new ExampleClient(),
        services: Services
    }
]);
/* file: package.json */
{
    "name": "@telefonica/aura-bridge-example-client",
    "version": "1.0.0",
    "main": "index.js",
    "private": true,
    "plugin": {
        "consumes": [
            "configurationManager"
        ],
        "provides": [
            "ExampleClient"
        ]
    }
}
/* file: example-client.ts */
import { AuraBridgeClient, AuraBridgeRequestInfo, SendMessageOptions } from '@telefonica/aura-bridge-common';
import { AuraLogger } from '@telefonica/aura-logging';
import { Services } from './example-consume-services';

const logger: AuraLogger.AuraBusEmitter = new AuraLogger.AuraBusEmitter('ExampleClient');

export class ExampleClient extends AuraBridgeClient {
    public constructor() {
        super('ExampleClient', Services.configurationManager.environmentConfiguration);
    }

    public async sendMessage(message: any, options: SendMessageOptions): Promise<void> {
        const { corr }: Partial<AuraBridgeRequestInfo> = options.requestInfo;
        // TODO: Implement the message sending logic here.
    }
}

A basic client should only extend the AuraBridgeClient class and implement the sendMessage method. The client can define any other method, but the sendMessage method will be used by the processors to send a message to a destination.

If the client uses the OAuth protocol, it is possible to add the OpenID authorization information to the client and automatically update the access token for the communication. To make use of this functionality, it is necessary that the new client extends from AuraBridgeClientOAuthTokens class instead of AuraBridgeClient class:

/* file: example-client.ts */
import { AuraBridgeClientOAuthTokens, AuraBridgeRequestInfo, SendMessageOptions } from '@telefonica/aura-bridge-common';
import { AuraLogger } from '@telefonica/aura-logging';
import { Services } from './example-consume-services';

const logger: AuraLogger.AuraBusEmitter = new AuraLogger.AuraBusEmitter('ExampleClient');

export class ExampleClient extends AuraBridgeClientOAuthTokens {
    public constructor() {
        super(
            'ExampleClient',
            Services.configurationManager.environmentConfiguration,
            [] // TODO: Add list ClientOAuthInformation here
        );
    }

    public async init(): Promise<void> {
        await this.refreshTokens();    // <-- It is responsible for updating the tokens before it expire.
    }

    public async sendMessage(message: any, options: SendMessageOptions): Promise<void> {
        const { corr }: Partial<AuraBridgeRequestInfo> = options.requestInfo;
        // TODO: Implement the message sending logic here.
    }
}

In addition to the refreshTokens method, the AuraBridgeClientOAuthTokens class defines the following methods:

  • addOpenIdClients: Add new clients to the list to update your tokens.
  • getTokenByClientId: Get token by client id.
  • stopRefreshTokens: Stop refresh client tokens.

Processor module

Use the aucli tool to generate the scaffolding of a processor module: aucli bridge generate processor.

As a general rule, a processor is responsible for converting an input message (from a “source” channel) to an output message (that will be sent to a “destination” channel).

Processor flow

To help with the task of generating a processor (in addition to the aucli tool) , the aura-bridge-common library provides the AuraBridgeFlow class that allows to define the converter and the client that will be used to convert and send the incoming message to the destination in a simple and declarative way.

const flow: BridgeFlow = {
    source: {                               // Source from where the request is initiated
        type: BridgeNodeType.Directline
    },
    destination: {                          // Destination where the request will be redirected
        type: BridgeNodeType.TestModel,
        converter: DirectlineToTestModelConverter,
        client: services.testModelClient,
        clientOptions: { queue: { bridgeFlowName: directlineToTestModelFlow.name } }
    },
    onError: {
        // ...
    }
};

In the same way, in case an exception occurs, it is possible to define the list of channels that should be informed.

const flow: BridgeFlow = {
    source: {
        // ...
    },
    destination: {
        // ...
    },
    onError: {                          // How and which channels should be informed on exception
        destinations: [
            {
                type: BridgeNodeType.TestModel,
                converter: ErrorToTestModelApiConverter,
                client: services.testModelClient,
                decode: TestModelDestinationResponseError
            },
            {
                type: BridgeNodeType.Directline,
                converter: ErrorToDirectlineEventConverter,
                client: services.directlineClient,
                decode: directlineDestinationResponseError
            }
        ]
    }
};

Declaring a destination

The destination field must follow the interface BridgeDestination.

export interface BridgeDestination extends BridgeNode {
    /**
     * Client instance that will be used to send the message to the destination
     */
    client: AuraBridgeClient;
    /**
     * Client options. System to send the message used: queue, retries, etc
     */
    clientOptions?: SendMessageClientOptions;
    /**
     * Converter to use
     */
    converter?: AuraBridgeMessageConverter;
    /**
     * Relationship between exception and response error
     */
    decode?: ExceptionResponseError[];
    /**
     * Optional condition for a destination to be executed
     */
    condition?: (error?: Error, lastError?: Error, requestInfo?: AuraBridgeRequestInfo, message?: any) => boolean;
}

The process to send a message using the previous definition is shown below:

If the indicated condition is true, the message will be converted (using converter) and sent (using client with options defined in clientOptions field). If during the process there is an error that throws an exception, all the destinations defined in onError.destinations field will be executed in order in the same way.

The following diagram shows the execution sequence:

flowchart LR
    subgraph source
        A[Message]
    end
    subgraph destination
    direction LR
        A[Message] --> Check{check condition}
        Check -->|True| Converter[Converter]
        Check -->|False| End[end]
        Converter --> |Converted message| Client[Client]
        help[Send message using clientOptions]
    end

When an exception is thrown, all the destinations defined in onError.Destinations are processed, passing both the original message and the exception occurred:

flowchart LR
    subgraph onError information
        Message[Message]
        Exception[Exception message]
    end
    subgraph onError destinations
    direction LR
        Message[Message] --> CheckOnError{check condition}
        Exception --> CheckOnError{check condition}
        CheckOnError -->|True| ConverterOnError[Converter]
        CheckOnError -->|False| EndOnError[Next destination]
        ConverterOnError --> |Converted message| ClientOnError[Client]
        helpOnError[Send message using clientOptions]
    end

Sending a specific message on exception

When an exception occurred during the execution of a flow (BridgeFlow), it is possible to decode the exception in a specific error message for each destination defined in onError.destinations field.

The list that relates the exception with each message is added in the field decode of BridgeDestination. Each of these elements must implement the following interface:

/**
 * @interface ExceptionResponseError
 */
export interface ExceptionResponseError {
    /**
     * Name error from exception
     */
    name?: string;
    /**
     * Message to user key
     */
    messageToUserKey?: string;
    /**
     * Error status from exception
     */
    status?: number;
    /**
     * Error response code
     */
    responseCode?: string;
    /**
     * Response error information
     */
    response: ResponseError;
}

In the following code, the example shows how to send a message with status 500 and message key bridge:error.transform when an error in the converter has occurred:

const exampleResponseError: ExceptionResponseError[] = [
    {
        name: AuraBridgeConverterError.name,
        response: {
            status: StatusCodes.INTERNAL_SERVER_ERROR,
            description: 'Internal bridge error converting input message to output format',
            messageToUserKey: 'bridge:error.transform'
        }
    }
];

Basic structure of the processor module

The processor module type mainly contains:

  • At least one source code file that defines the processor plugin module and controllers for each of the operations specified in the swagger definition.
  • A package.json file defining the library, with a plugin section defining which modules it consumes and supplies.
  • A swagger.yaml file that contains a detailed description of the entire API defined by the plugin.
  • A source code file that defines the BridgeFlow.
  • A source code file that defines the AuraBridgeMessageConverter.

The basic structure for a processor plugin module type is as follows:

aura-bridge-example-processor
├── index.ts            # Processor plugin module and controller
├── converter.ts        # Converter (AuraBridgeMessageConverter)
├── flow.ts             # Flow (BridgeFlow)
├── package.json
└── swagger.yaml        # Api definition

A type processor module must implement the PluginProcessor interface:

export interface PluginProcessor extends PluginApi {
    /**
     * List of defined flows.
     */
    flows: BridgeFlow[];
}

In addition to the definition of flows, the same requirements as for an API plugin type are applied.

If the processor plugin must manage the aura-groot response (using DirectLine) for a channel type, it is possible to use the PluginApiController interface to define the controller.

For example:

/* Manage aura-groot response messages for whatsapp channels */
postDirectlineConversationsActivities: {
    isDirectlineProcessor: true,                            // Indicates if it is a directline processor
    channelType: BridgeType.Whatsapp,                      // Channel type
    controller: directlineWhatsappController.controller     // Controller definition
}

In this way, all the messages sent for the WhatsApp type channel to /aura-services/{channelName}/v3/conversations/{conversationId}/activities and /aura-services/{channelName}/v3/conversations/{conversationId}/activities/{messageId} endpoints will be managed by the defined controller.

⚠️ These endpoints do not need to be defined in the plugin swagger, since they are supplied by the aura-bridge core.

A couple of examples with the content of each file are shown below:

/* file: index.ts */
/* description: Using controller function */

import ...

const controller = {
    exampleNotification: async (req: Request, res: Response) => {
        const env = Services.configurationManager.environmentConfiguration;
        res.status(200).send();
        await AuraBridgeFlow.process(exampleToDirectlineFlow(Services), getRequestInformation(req, env), req.body);
    }
};

export = registerPlugin([
    {
        type: PluginType.Processor,         // Plugin module type
        name: 'exampleProcessor',           // Plugin module name
        controller,                         // Controllers definitions (linked to swagger operationId)
        flows: [exampleToDirectlineFlow],   // Flows
        services: Services                  // [consumes] Needed modules are added here
    }
]);

/* file: index.ts */
/* description: Using PluginApiController interface */

import ...

const controller = {
    // This plugin manages all the requests from aura-groot for the testModel channel type destination
    postDirectlineConversationsActivities: {
        isDirectlineProcessor: true,
        channelType: BridgeType.TestModel,
        controller:  async (req: Request, res: Response) => {
            ...
        }
    }
};

export = registerPlugin([
    {
        type: PluginType.Processor,         // Plugin module type
        name: 'directlineTestModelProcessor',    // Plugin module name
        controller,                         // Controllers definitions (linked to swagger operationId)
        flows: [exampleToDirectlineFlow],   // Flows
        services: Services                  // [consumes] Needed modules are added here
    }
]);
/* file: converter.ts */
import ...

export class ExampleConverter extends AuraBridgeMessageConverter {
    public static async message(incomingMessage: ExampleMessage) {
        // Logic of the converter here
    }
}
/* file: flow.ts */
/**
 * Flow: example to directline.
 *
 *
 * [Example] ─────> (bridge) ───(ok)──────> [Directline]
 *
 * @returns {BridgeFlow} flow
 */
export function asyncCallbackToDirectlineFlow(services: any): BridgeFlow {
    const flow: BridgeFlow = {
        source: {
            type: BridgeNodeType.Example
        },
        destination: {
            type: BridgeNodeType.Directline,
            converter: ExampleConverter,
            client: services.directlineClient,
            clientOptions: { retries: {} }
        },
        onError: {
            destinations: [
                ...
            ]
        }
    };

    return flow;
}
/* file: package.json */
{
    "name": "@telefonica/aura-bridge-example-processor",
    "version": "1.0.0",
    "main": "index.js",
    "private": true,
    "plugin": {
        "consumes": [ ... ],
        "provides": [
            "exampleProcessor"
        ]
    }
}
# file: swagger.yaml
openapi: 3.0.0
info:
  title: aura bridge example processor
...
paths:
  /example/notification:
   get:
     operationId: exampleNotification       # Function name defined in "controller".
     x-router-controller: plugins           # It should always be "plugins".
     responses:
       '200':
         description: OK
         headers: { }

Service module

Use the aucli tool to generate the scaffolding of a service plugin: aucli bridge generate service

A service plugin module is a set of utilities that can be reused by the rest of plugins and mainly contains:

  • At least one source code file that defines the service plugin module and the service itself.
  • A package.json file defining the library, with a plugin section defining that modules consume and supplies.

The basic structure for a service plugin module type is as follows:

aura-bridge-example-service
├── index.ts
└── package.json

A type service module must implement the PluginService interface:

export interface PluginService extends Plugin {
    /**
     * Service instance.
     */
    instance?: any;
    /**
     * Returns a service instance if it must be initiated asynchronously.
     */
    getInstance?: () => any;
}

The instance field or the getInstance method should be used to obtain the service, but not both. If the service does not need to be initiated asynchronously, the service definition in the instance field is the preferred option. If it is necessary to asynchronously start the service, the getInstance method must be used.

A couple of examples with the content of each file are shown below:

/* file: index.ts */
import { PluginType, registerPlugin } from '@telefonica/aura-bridge-common';
...

const exampleService = {
    isActionMessage: (message: ExampleMesageModel) => {
        return !!message?.channelData?.customData?.action;
    }
}

export = registerPlugin([
    {
        type: PluginType.Service,       // Plugin module type
        name: 'exampleService',         // Plugin module name
        instance: exampleService,       // Service instance
        services: Services              // [consumes] Needed modules are added here
    }
]);
/* file: package.json */
{
    "name": "@telefonica/aura-bridge-example-service",
    "version": "1.0.0",
    "main": "index.js",
    "private": true,
    "plugin": {
        "consumes": [ ],
        "provides": [
            "exampleService"
        ]
    }
}

Plugins in specific channels

There is a relationship between a channel and the different plugins that give full support to the channel in aura-bridge. This is because plugins can supply: services, incoming messages management, output messages management, etc.

Therefore, to support a channel like WhatsApp, several plugins may be necessary and knowing that relationship allows to enable/disable the support to the complete channel in aura-bridge correctly.

Plugins for WhatsApp channel

Plugin Dependencies Core dependencies
whatsapp-incoming-processor whatsapp-service, directline-service configurationManager, prometheus
directline-whatsapp-processor whatsapp-service, directline-service configurationManager
directline-whatsapp-service whatsapp-service, directline-service configurationManager
whatsapp-service configurationManager, prometheus
directline-service configurationManager, auraBridgeCache

How to disable the WhatsApp channel

To disable the WhatsApp channel, it is necessary to take into account the following:

  • The whatsapp-incoming-processor and directline-whatsapp-processor plugins are not dependent on any other plugin, so they can be removed from the plugin-config.json file.

  • The directline-whatsapp-service, whatsapp-service and directline-service plugins can be used by other plugins and can only be removed if they are not needed.

Plugins for async-callback

Plugin Dependencies Core dependencies
async-callback-directline-processor directline-service configurationManager, prometheus

How to disable the async-callback functionality

The async-callback-directline-processor plugin is not dependent on any other plugin, so it can be removed from the plugin-config.json file to completely disable the async-callback functionality.

Plugins for Genesys

Plugin Dependencies Core dependencies
genesys-directline-processor directline-service configurationManager

How to disable the Genesys functionality

The genesys-directline-processor plugin is not dependent on any other plugin, so it can be removed from the plugin-config.json file to completely disable the Genesys functionality.

1.1 - Global plugins catalog

Aura bridge global plugins catalog

Current global plugins developed in Aura bridge by the Aura Platform Team

Global plugins repository

Check the Github global plugins repository to see the currently available plugins in aura-bridge.

Aura Platform Team is progressively documenting each plugin within this section. The already documented ones include the corresponding link below.

1.2 - auraline-conversation-api plugin

auraline-conversation-api plugin

Technical description of auraline-conversation-api plugin

Introduction

auraline-conversation-api plugin allows you to generate conversation identifiers together with an associated token to be able to communicate through the new Auraline service. This service works similarly to Microsoft Direct Line.

It is mandatory to load this plugin if any channel wants to communicate with aura-bot through Auraline.

Based on official Direct Line API 3.0

Open a new conversation

Before establishing a communication between a client and aura-bot through the Auraline channel, it is necessary to obtain a conversation ID and a token associated to it. This token will be used as APIKey to send messages to the user together with the conversation ID created.

HTTP
POST https://bridge-url.com/aura-services/v1/auraline/conversations
Authorization: APIKEY [Secret]

Conversation Response Model (Create or Update Token)

Property Type Description
conversationId string The identification of conversation created or updated (refresh token).
token string Token generated for conversation. It is temporary and can be refreshed. Use with “APIKEY” string in the Authorization HTTP header.
expires_in number Time in seconds for the duration of the token. If you want to refresh it, it must be done before this time has elapsed. It will be set based on the value of AURALINE_CONVERSATION_EXPIRATION_TIME

The following snippets provide an example of the start conversation request and response.

  • Request

    HTTP
    POST https://bridge-url.com/aura-services/v1/auraline/conversations
    Authorization: APIKEY iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xn
    
  • Response

    HTTP/1.1 201 Created
    [other headers]
    BODY
    {
      "conversationId": "X7CZj0LdjAPGfiCpg4Fv",
      "token": "RCurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xn",
      "expires_in": 1800,
    }
    

Refresh a Conversation Token

A conversation token can be refreshed an unlimited number of times, as long as it has not expired, as an expired token cannot be refreshed.

To refresh a conversation token, issue this request:

HTTP
POST https://bridge-url.com/aura-services/v1/auraline/conversations/{conversationid}/refresh
Authorization: APIKEY [TOKEN_TO_BE_REFRESHED]

The following snippets provide an example of the Refresh Token request and response.

  • Request

    HTTP
    POST https://bridge-url.com/aura-services/v1/auraline/conversations/X7CZj0LdjAPGfiCpg4Fv/refresh
    Authorization: APIKEY RCurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xn
    
  • Response

    If the request is successful, the response contains:

    • A new token that is valid for the same conversation as the previous token.
    • An expires_in value that indicates the number of seconds until the new token expires.

    For the new token to remain useful, you must refresh the token before it expires:

    HTTP
    HTTP/1.1 200 OK
    [other headers]
    BODY
    {
      "conversationId": "X7CZj0LdjAPGfiCpg4Fv",
      "token": "RCurR_XV9ZA.cwA.BKA.y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xniaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0",
      "expires_in": 1800
    }
    

1.3 - auraline-incoming-processor plugin

auraline-incoming-processor plugin

Technical description of auraline-incoming-processor plugin

Introduction

This plugin receives requests and transforms them to Auraline format to send them to aura-groot.

The specific environment variables for this plugin are located at auraline-incoming-processor plugin configuration.

Consumes components (IOC)

Name Type Description
auralineClient PluginType.Service Auraline client
configurationManager PluginType.Service Configuration manager
directlineClient PluginType.Service DirectLine client
directlineService PluginType.Service Services and utilities for Directline channel

Provides components (IOC)

Name Type Description
auraline-directline-processor PluginType.Processor Manage requests
auraline-status-processor PluginType.Processor Manage status

Controller

This plugin sets the endpoints it supports.

Operation id Path Description
postAuralineMessages /aura-services/v1/auraline/conversations/{conversationId}/activities Manage the messages sent
postAuralineStatus /aura-services/v1/auraline/conversations/{conversationId}/activities/{activityId}/status Manage the status

auraline-directline-processor flow definition

To process a message, the auraline-directline-processor uses AuraBridgeFlow with the following definition:

    const flow: BridgeFlow = {
        name: 'auralineToDirectlineFlow',
        source: {
            type: BridgeNodeType.Auraline
        },
        destination: {
            type: BridgeNodeType.Directline,
            converter: AuralineToDirectlineConverter,
            client: services.directlineClient,
            clientOptions: { retries: {} }
        },
        onError: {
            destinations: [
                {
                    type: BridgeNodeType.Auraline,
                    converter: AuralineToAuralineApiConverter,
                    client: services.auralineClient,
                    decode: auralineDirectlineResponseError
                },
                {
                    type: BridgeNodeType.Directline,
                    converter: AuralineToDirectlineEventConverter,
                    client: services.directlineClient
                }
            ]
        }
    };

According to the flow definition, AuraBridgeFlow tries to process, convert and send (using retries) the message to aura-groot using the DirectLine client.

If some type of error occurs during this process, an event message will be sent to aura-groot and client with the error information.

flowchart LR
    subgraph Flow
        direction LR
        B(Controller) --> C(Converter)
    end
    A(Client) -->|message| Flow
    Flow -->|ok| D(Bot Directline)
    Flow -->|error| E(Bot Directline Event)
    Flow -->|error| F(Client message)

auraline-directline-processor message conversion

The plugin uses two converters to transform messages to DirectLine format: AuralineToDirectlineConverter and AuralineToDirectlineEventConverter.

AuralineToDirectlineConverter

Main converter, in charge of transforming messages to DirectLine format messages using the directline-message-factory-v3 service of directline-service plugin.

AuralineToDirectlineEventConverter

It makes the conversion to a DirectLine event message if an error in the process has occurred.

Auraline status controller

This controller handles Auraline status requests and validate the APIKey fields. After that, it returns the status and if there is not an error, it passes the message to Auraline status processor.

Auraline status processor

This processor handles the status, deletes the message in queues and log errors if received.

1.4 - aurapush-sendfeedback-service

Aura Push send feedback service

Description of Aura Push send feedback service

Description

aurapush-sendfeedback-service plugin contains the services and utilities to send information to the aura-push service.

To send this information an event consumer is used: aurapush-sendfeedback-consumer. This consumer listens for the following events:

  • whatsapp.ackMessageReceived: Event emitted when a new ack message is received.
  • core.flow.error.directlineToWhatsappFlow: Event emitted when an error occurs during sending a message from Direct Line to WhatsApp.
sequenceDiagram  
    alt whatsapp.ackMessageReceived
        AuraPushFeedbackConsumer->>+onAckMessageReceived: ACK
    end
    alt core.flow.error.directlineToWhatsappFlow
        AuraPushFeedbackConsumer->>+onCoreErrorDirectlineToWhatsappFlow: Core flow error
    end
        onAckMessageReceived->>+auraPushFeedbackClient: ACK and path
        onCoreErrorDirectlineToWhatsappFlow->>+auraPushFeedbackClient: Core flow error and path
        auraPushFeedbackClient->>+Aura Push: Message

⚠️ For Brazil OB, the aurapush-sendfeedback-service plugin requires a specific configuration in the installer aurak8s.

Consumes components (IOC)

Name Type Description
configurationManager PluginType.Service Configuration manager
eventService PluginType.Service Bridge event management service

Provides components (IOC)

Name Type Description
auraPushSendFeedbackService PluginType.Service Services and utilities for AuraPush send message feedback
auraPushFeedbackClient PluginType.Service Aura push feedback client

1.5 - directline-auraline-processor plugin

directline-auraline-processor plugin

Technical description of directline-auraline-processor plugin

Introduction

This plugin receives requests from aura-groot and send them to Auraline callback.

Consumes components (IOC)

Name Type Description
auralineClient PluginType.Service Auraline client
configurationManager PluginType.Service Configuration manager
directlineService PluginType.Service Services and utilities for Directline channel

Provides components (IOC)

Name Type Description
directlineAuralineProcessor PluginType.Processor Manage Auraline responses

auraline-directline-processor flow definition

To process a message, the auraline-directline-processor uses AuraBridgeFlow with the following definition:

    const flow: BridgeFlow = {
        name: 'directlineToAuralineFlow',
        source: {
            type: BridgeNodeType.Directline
        },
        destination: {
            type: BridgeNodeType.Auraline,
            converter: DirectlineToAuralineConverter,
            client: services.auralineClient,
            clientOptions: { queue: { bridgeFlowName: directlineToAuralineFlow.name } }
        },
        onError: {
            destinations: [
                {
                    type: BridgeNodeType.Auraline,
                    converter: ErrorToAuralineApiConverter,
                    client: services.auralineClient,
                    decode: AuralineDestinationResponseError
                }
            ]
        }
    };

According to the flow definition, AuraBridgeFlow tries to process, convert and send (using queues) the message to the Auraline callback endpoint defined in the callbackOptions channel configuration property, within the ResponseOptions model.

If some type of error occurs during this process and is marked as recoverable, certain retries will be executed. If after all, the error continues, an error message will be sent to the endpoint.

AuralineToDirectlineConverter

Main converter, in charge of transforming DirectLine activities to Auraline format. The response messages will have the following format:

{
        "activities": [
            {
                "type": "message",
                "serviceUrl": "http://aura-bridge-outbound:8045/aura-services/auraline",
                "channelId": "c71dc728-5fe2-4735-927d-0c419b35ec59",
                "conversation": {
                    "id": "4nc3u4hn"
                },
                "recipient": {
                    "id": "user1"
                },
                "text": "Hi!",
                "inputHint": "acceptingInput",
                "channelData": {
                    "hasMoreMessages": false,
                    "correlator": "53c42d06-3be1-48c4-a6c9-afa6e76d54fc"
                },
                "replyToId": "8vvicc88",
                "id": "8vvicc88|0001"
            }
        ],
        "correlator": "53c42d06-3be1-48c4-a6c9-afa6e76d54fc",
        "timestamp": "2023-11-08T12:24:36.420Z",
        "id": "8vvicc88",
        "to": "user1",
        "conversationId": "4nc3u4hn"
    }

Inside the activities array, all activities will have a unique identifier (messageId|XXXX) that the client should store to later send the ack to Auraline.

1.6 - directline-rcs-processor plugin

directline-rcs-processor plugin

Technical description of directline-rcs-processor plugin

Introduction

This plugin receives requests from aura-groot and send them to RCS callback.

Consumes components (IOC)

Name Type Description
rcsClient PluginType.Service RCS client
directlineClient PluginType.Service Directline client
configurationManager PluginType.Service Configuration manager
directlineService PluginType.Service Services and utilities for Directline channel

Provides components (IOC)

Name Type Description
directlineRcsProcessor PluginType.Processor Manage RCS responses

rcs-directline-processor flow definition

To process a message, the directline-rcs-processor uses AuraBridgeFlow with the following definition:

    const flow: BridgeFlow = {
        name: 'directlineToRcsFlow',
        source: {
            type: BridgeNodeType.Directline
        },
        destination: {
            type: BridgeNodeType.Rcs,
            converter: DirectlineToRcsConverter,
            client: services.rcsClient,
            clientOptions: { queue: { bridgeFlowName: directlineToRcsFlow.name } }
        },
        onError: {
            destinations: [
                {
                    type: BridgeNodeType.Rcs,
                    converter: ErrorToRcsApiConverter,
                    client: services.rcsClient,
                    decode: RcsDestinationResponseError
                },
                {
                    type: BridgeNodeType.Directline,
                    converter: ErrorToDirectlineEventConverter,
                    client: services.directlineClient,
                    decode: RcsDestinationResponseError
                }
            ]
        }
    };

According to the flow definition, AuraBridgeFlow tries to process, convert and send (using queues) the message to the Google RCS messages endpoint. If some type of error occurs during this process and is marked as recoverable, certain retries will be executed. If after all, the error continues, an error message will be sent to RCS and an error event will be sent to aura-groot.

rcsToDirectlineConverter

Main converter, in charge of transforming DirectLine activities to RCS format.

This converter only handles activities with an attachment type application/vnd.telefonica.aura.rcs.message with content in RCS format.

{
  "type": "message",
  "serviceUrl": "http://localhost:8045/aura-services/javiagent",
  "channelId": "f7fd1021-41cd-588a-a461-387cc24be225",
  "from": {},
  "conversation": {
    "id": "d152aee9-1aaa-5b54-95a5-79352eee2e45"
  },
  "recipient": {
    "id": "34659949469",
    "name": "javiagent_xxxxxx_agent@rbm.goog"
  },
  "text": "Text doesn't matter",
  "inputHint": "acceptingInput",
  "attachments": [
    {
      "contentType": "application/vnd.telefonica.aura.rcs.message",
      "content": {
        "contentMessage": {
          "richCard": {
            "carouselCard": {
              "cardWidth": "MEDIUM",
              "cardContents": [
                {
                  "title": "Card #1",
                  "description": "The description for card #1",
                  "suggestions": [
                    {
                      "reply": {
                        "text": "Card #1",
                        "postbackData": "{\\"intent\\": \\"intent.factotum-test.rcs-formats\\",\\"entities\\":[{\\"type\\":\\"type\\",\\"entity\\":\\"postback\\"},{\\"type\\":\\"data\\",\\"entity\\":\\"card 1\\"}]}"
                      }
                    }
                  ],
                  "media": {
                    "height": "MEDIUM",
                    "contentInfo": {
                      "fileUrl": "https://storage.googleapis.com/kitchen-sink-sample-images/cute-dog.jpg",
                      "forceRefresh": "false"
                    }
                  }
                },
                {
                  "title": "Card #2",
                  "description": "The description for card #2",
                  "suggestions": [
                    {
                      "reply": {
                        "text": "Card #2",
                        "postbackData": "{\\"intent\\": \\"intent.factotum-test.rcs-formats\\",\\"entities\\":[{\\"type\\":\\"type\\",\\"entity\\":\\"postback\\"},{\\"type\\":\\"data\\",\\"entity\\":\\"card 2\\"}]}"
                      }
                    }
                  ],
                  "media": {
                    "height": "MEDIUM",
                    "contentInfo": {
                      "fileUrl": "https://storage.googleapis.com/kitchen-sink-sample-images/elephant.jpg",
                      "forceRefresh": "false"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  ],
  "channelData": {
    "correlator": "73b72144-7247-4876-880b-57b63efa323e",
    "version": "3",
    "status": {
      "code": "SUCCESS",
      "message": "Success"
    },
    "payload": {
      "bridge": {
        "channelId": "f7fd1021-41cd-588a-a461-387cc24be225"
      }
    }
  },
  "replyToId": "11879060267953086"
}

If an attachment of this type is not present, a simple message with the value of the activity.text field will be sent to the user.

1.7 - directline-service plugin

directline-service plugin

Technical description of directline-service plugin

Introduction

directline-service plugin contains the services and utilities related to message creation for Microsoft Directline v3. This plugin also contains the Directline client to send messages to aura-root.

The specific environment variables for this plugin are located at directline-service plugin configuration.

Consumes components (IOC)

Name Type Description
configurationManager PluginType.Service Configuration manager
auraBridgeCache PluginType.Service Cache for ack messages

Provides components (IOC)

Name Type Description
directlineClient PluginType.Client Direct Line client
directlineService PluginType.Service Services and utilities for Direct Line protocol

directlineClient plugin

The directlineClient class extends from the AuraBridgeClient and allows sending requests to aura-root.

directlineService

The directlineService class provides utilities related to the Directline client.

  • messageFactory for channelData v1 (DirectlineMessageFactory): Factory to create different types of Directline messages with channelData v1.
  • messageFactory for channelData v3 (DirectlineMessageFactoryV3): Factory to create different types of Directline messages with channelData v3.

1.8 - directline-whatsapp-service plugin

directline-whatsapp-service plugin

Technical description of directline-whatsapp-service plugin

Introduction

directline-whatsapp-service plugin contains the services and utilities for directline-whatsapp message conversion.

The specific environment variables for this plugin are located at directline-whatsapp-service configuration.

Consumes components (IOC)

Name Type Description
configurationManager PluginType.Service Configuration manager
prometheus PluginType.Service Metrics client for prometheus
whatsappService PluginType.Service Services and utilities for WhatsApp channel

Provides components (IOC)

Name Type Description
directlineWhatsappService PluginType.Service Services and utilities for Direct Line - WhatsApp message conversion

whatsappService

The DirectlineWhatsappService class provides the following utilities:

  • directlineToWhatsappConverter: It converts DirectLine messages (DirectlineMessageModel) to WhatsApp messages (WhatsappMessageResponseModel).

  • directlineWhatsappUtils: Utilities to help with message conversion: DirectLine to WhatsApp.

Converting Direct Line messages to WhatsApp models

The DirectlineToWhatsappConverter class extends from AuraBridgeMessageConverter and converts DirectLine messages to WhatsApp models.

To make this conversion, the DirectlineToWhatsappConverter differences between the following types of messages depending on the DirectLine message content:

Type Direct Line message content
text Direct Line messages that do not contain attachments
list Direct Line messages that contain more than one attachment and the attachmentLayout field value is list.
carousel Direct Line messages that contain more than one attachment and the attachmentLayout field value is carousel.
heroCard Direct Line message that contains a single attachment and the contentType field value is application/vnd.microsoft.card.hero.
file Direct Line message that contains a single attachment and the contentType field value is application/vnd.telefonica.aura.file.
template Direct Line message that contains a single attachment and the contentType field value is application/vnd.telefonica.aura.template.
videoCard Direct Line message that contains a single attachment and the contentType field value is application/vnd.microsoft.card.video.
whatsapp Direct Line message that contains a single attachment and the contentType field value is application/vnd.telefonica.aura.whatsapp.

In the case of list and carousel, in which there is more than one attachment, each attachment in list follows the same procedure to obtain type depending on the value of the contentType field.

⚠️ Currently, the file, template and videoCard types are disabled when they must be generated from list or carousel.

Type text conversion

DirectLine messages identified with the text type is transformed to WhatsApp text messages using the WhatsappMessageFactory.createTextMessage.

Find further information about sending WhatsApp text messages.

Type heroCard conversion

DirectLine messages identified with the heroCard type is transformed to WhatsApp text messages using the WhatsappMessageFactory.createTextMessage.

These messages will be transformed to WhatsApp list messages, WhatsApp reply buttons or enumerated text lists, following the defined guidelines in WhatsApp list options.

The transformation to a WhatsApp message depends on the type of list obtained:

  • button type. It will be transformed to WhatsApp interactive button message using the WhatsappMessageFactory.createInteractiveButtonMessage.

  • list type. It will be transformed to WhatsApp interactive list message using the WhatsappMessageFactory.createInteractiveListMessage.

  • enumeratedList type. It will be transformed to WhatsApp formatted text message using the WhatsappMessageFactory.createHeroCardMessage.

Type file conversion

DirectLine messages identified with the file type is transformed to WhatsApp media messages using the WhatsappMessageFactory.createFileMessage.

The currently supported file types are: image, document, audio and video.

Find here further information about sending WhatsApp media messages.

Type template conversion

DirectLine messages identified with the template type is transformed to WhatsApp media messages using the WhatsappMessageFactory.createTemplateMessage.

Find here further information about sending WhatsApp template messages.

Type videoCard conversion

DirectLine messages identified with the template type will be transformed to WhatsApp media messages using the WhatsappMessageFactory.createTemplateMessage.

Find here further information about sending WhatsApp template messages.

Type whatsapp conversion

Direct Line messages identified as type whatsapp will be sent to WhatsApp without any transformation. This kind of messages is composed of an attachment type application/vnd.telefonica.aura.whatsapp whose content will be sent directly to WhatsApp. Only the field to will be added.

Text conversion to WhatsApp markdown format

All texts obtained using LocaleManager instance are formatted in WhatsApp markdown format. This implies that all resources defined in POEditor to be used in WhatsApp messages must use the markdown standard format.

The getLocaleTextWithParsedMarkdown function from whatsapp-message-utils is responsible for converting the text to WhatsApp markdown format.

For the text sent from the DirectLine message, the DirectlineToWhatsappConverter class converts text to WhatsApp markdown format according to the following:

  • If the DirectLine message contains information in the channelData.payload.bridge.whatsapp.textConvert field, its value is used to convert to WhatsApp markdown format.
  • If the request field is not present, the channel configuration is used.
  • Finally, if it is not possible to obtain conversion information in the previous cases, the text message is converted by default.

By default, aura-bridge converts the text received from DirectLine message to specific WhatsApp markdown format.

The practical processes for modifying this behavior is explained in the following documents:

1.9 - genesys-directline-processor plugin

genesys-directline-processor plugin

Technical description of genesys-directline-processor plugin

Introduction

This plugin receives requests from handover and transforms them to DirectLine format to send them to aura-groot.

The specific environment variables for this plugin are located at genesys-directline-processor plugin configuration.

Consumes components (IOC)

Name Type Description
configurationManager PluginType.Service Configuration manager
directlineClient PluginType.Service DirectLine client
directlineService PluginType.Service Services and utilities for Directline channel

Provides components (IOC)

Name Type Description
genesysProcessor PluginType.Processor Manage requests from handover

Controller

This plugin sets the endpoints that support handover.

Operation id Path Description
postGenesysMessages /aura-services/v1/genesys/messages Manage the messages sent by handover

Flow definition

To process a message from handover, the genesys-directline-processor plugin uses AuraBridgeFlow with the following definition:

    const flow: BridgeFlow = {
        source: {
            type: BridgeNodeType.Genesys
        },
        destination: {
            type: BridgeNodeType.Directline,
            converter: GenesysToDirectlineConverter,
            client: services.directlineClient,
            clientOptions: { retries: {} }
        },
        onError: {
            destinations: [
                {
                    type: BridgeNodeType.Directline,
                    converter: GenesysToDirectlineEventConverter,
                    client: services.directlineClient
                }
            ]
        }
    };

According to the flow definition, AuraBridgeFlow tries to process, convert and send (using retries) the message to aura-groot using the DirectLine client.

If some type of error occurs during this process, an event message will be sent to aura-groot with the error information.

flowchart LR
    subgraph Flow
        direction LR
        B(Controller) --> C(Converter)
    end
    A(Handover) -->|message| Flow
    Flow -->|ok| D(Groot Directline)
    Flow -->|error| E(Groot Directline Event)

Message conversion

The plugin uses two converters to transform messages from Handover to DirectLine format: GenesysToDirectlineConverter and GenesysToDirectlineEventConverter.

GenesysToDirectlineConverter

Main converter, in charge of transforming Handover messages to DirectLine format messages using the messageFactory service of directline-whatsapp-service plugin.

The Handover data information in DirectLine message is added to the channeldata.payload.handover field. The converted message also includes an auraCommand with suggestion type and value defined in the environment variable AURA_GENESYS_AURA_COMMAND_DEFAULT_INTENT (by default: intent.common.handover).

Further information about handover payload in channelData v3

GenesysToDirectlineEventConverter

It makes the conversion to a DirectLine event message if an error in the process has occurred.

1.10 - whatsapp-client-service plugin

whatsapp-client-service plugin

Technical description of whatsapp-client-service plugin

Introduction

whatsapp-client-service plugin contains the services and utilities related to the WhatsApp channel. This plugin also contains the WhatsApp client to send messages to WhatsApp through Kernel.

The specific environment variables for this plugin are located at whatsapp-client-service plugin configuration.

Consumes components (IOC)

Name Type Description
configurationManager PluginType.Service Configuration manager
prometheus PluginType.Service Metrics client for Prometheus

Provides components (IOC)

Name Type Description
whatsappClient PluginType.Client WhatsApp client

whatsappClient plugin

The WhatsappClient class extends from the AuraBridgeClientOAuthTokens class to obtain the access tokens used in OpenId authentication necessary to perform communications with the Kernel API.

The WhatsappClient allows sending requests to WhatsApp through the Kernel API and is responsible for managing and refreshing all the access tokens of the whatsapp channel type.

Management of multiple Kernel WhatsApp APIs

WhatsappClient is able to handle multiple versions of Kernel WhatsApp APIs. Every channel could have in its configuration a version field with the Kernel WhatsApp API version, and this is the version to be used. By default, if no version is configured, WhatsappClient will use v1. Currently, v1 and v2 are supported.

Configuration by channel

The whatsApp.client field allows the configuration of WhatsappClient options. The interface for this field is defined as follows:

export interface FPClientModel {
    /** Client id */
    id: string;
    /** Client secret */
    secret: string;
    /** Client purposes */
    purposes?: string;
    /** Client scopes */
    scopes?: string;
    /** Client version */
    version?: string;
}

Example:

{
    ...
    "type": "whatsapp",
    "whatsapp": {
        "client": {
            "id": "client-id",              // Client id
            "purposes": "client-purposes",  // Client purposes
            "scopes": "client-scopes",      // Client scopes
            "secret": "client-secret"       // Client secret
            "version": "v1"
        }
    }
}

Error management policy

The WhatsappClient defines its own retry policy when an error occurs.

export const whatsappClientErrorPolicy: IndexedErrorPolicy = {
    // Client code (whatsapp)
    responseCode: {
        429: {
            description: 'The frequency limit was reached',
            recoverable: true
        },
        500: {
            description: 'Generic error-Message failed to send because of an unknown error.Try again later.',
            recoverable: true
        },
        1015: {
            description: 'Customer frequency limit reached.',
            recoverable: true
        },
        1016: {
            description: 'System overloaded.',
            recoverable: true
        },
        1017: {
            description: 'It is not the main master node.',
            recoverable: true
        },
        1018: {
            description: 'It is not a primary main app.',
            recoverable: true
        }
    },
    // Http status (4P)
    status: {
        // 404
        [StatusCodes.NOT_FOUND]: {
            description: ReasonPhrases.NOT_FOUND,
            recoverable: true
        },
        // 408
        [StatusCodes.REQUEST_TIMEOUT]: {
            description: ReasonPhrases.REQUEST_TIMEOUT,
            recoverable: true
        },
        // 409
        [StatusCodes.CONFLICT]: {
            description: ReasonPhrases.CONFLICT,
            recoverable: true
        },
        // 413
        [StatusCodes.REQUEST_TOO_LONG]: {
            description: ReasonPhrases.REQUEST_TOO_LONG,
            recoverable: true
        },
        // 500
        [StatusCodes.INTERNAL_SERVER_ERROR]: {
            description: ReasonPhrases.INTERNAL_SERVER_ERROR,
            recoverable: true
        },
        // 502
        [StatusCodes.BAD_GATEWAY]: {
            description: ReasonPhrases.BAD_GATEWAY,
            recoverable: true
        },
        // 503
        [StatusCodes.SERVICE_UNAVAILABLE]: {
            description: ReasonPhrases.SERVICE_UNAVAILABLE,
            recoverable: true
        },
        // 504
        [StatusCodes.GATEWAY_TIMEOUT]: {
            description: ReasonPhrases.GATEWAY_TIMEOUT,
            recoverable: true
        }
    }
};

The WhatsappClient retry policy differences between two types of errors:

  • Errors generated by WhatsApp API, associated with the responseCode error field.
  • Errors generated by Kernel API, associated with the status error field.

1.11 - whatsapp-service plugin

whatsapp-service plugin

Technical description of whatsapp-service plugin

Introduction

whatsapp-service plugin contains the services and utilities related to the WhatsApp channel. This plugin also contains the WhatsApp client to send messages to WhatsApp through Kernel.

The specific environment variables for this plugin are located at whatsapp-service plugin configuration.

Consumes components (IOC)

Name Type Description
configurationManager PluginType.Service Configuration manager
prometheus PluginType.Service Metrics client for Prometheus
whatsappClient PluginType.Client WhatsApp client

Provides components (IOC)

Name Type Description
whatsappService PluginType.Service Services and utilities for WhatsApp channel

whatsappService

The WhatsappService class provides utilities related to the WhatsApp client.

  • messageFactory (WhatsappMessageFactory): Factory to create different types of WhatsApp messages.
  • interactiveMessageUtils (WhatsappInteractiveMessageUtils): Utilities for interactive message management.
  • whatsappUtils (WhatsappUtils): Utilities for WhatsApp channel.

Find here further information about WhatsApp API section.

2 - Aura Bridge cache

Aura Bridge cache

Description of Aura Bridge cache

Description

The aura-bridge currently makes use of two caches:

  • ackCache: Cache that uses RedisConnector and stores information associated with ack status messages of aura-bridge.
  • commandCache: Cache using RedisConnector that allows to store the Behavior Manager information.

Configuration

ackCache

ackCache is configured with the following environment variables:

Property Type Description
BRIDGE_CACHE_MESSAGES_ACK_TTL number Time to live of the objects stored in the bridge ack cache messages in seconds. By default: 24 * 60 * 60.
BRIDGE_CACHE_MESSAGES_ACK_ACTIVE boolean Allows to enable/disable the ack messages cache. By default: false.

commandCache

commandCache is configured with the following environment variables:

Property Type Description
DEV_AURA_BEHAVIOR_CACHE_TTL number Maximum lifetime of behavior cache in aura-bridge in seconds. After this time, the system will delete the message. By default: 60 * 60 (60 min).