Skip to main content

Adapters

An adapter, such as described previously, is defined using the Adapter class exposed by the JavaScript file present at the following address:

https://obs.multistream.tools/v1/adapters.js
tip

This file/module also exports a number of handy constants and utilities for modeling adapters for platforms of your choice.

The API described below allows you to develop your own adapters to add support for any platform to our generic system. You are free to implement these, for example, directly using the Twitch API or any other available online. Your adapters will simply need to be executed in HTML pages served over HTTPS and respect at least the expected data types.

API

The TypeScript signature of the Adapter class is as follows:

type Id = string;

type Event = string;

type Alerts = Event[];

type Filters = {
alerts?: false;
chat?: false;
session?: true;
other?: true;
[key: Event]: false;
};

declare class Platform {
constructor(filters?: Filters, extraAlerts?: Alerts);
get id(): Id;
has(event: Event): boolean;
}

type AlertData = {
name: string;
sender?: string;
message?: string;
tier?: string;
amount?: number;
};

type SessionData = {
[key: string]: object | object[];
};

type LoadData = {
session: SessionData;
};

type ChatData = object;

type MessageData = {
renderedText: string;
data: {
userId:Id;
msgId:Id;
nick:string;
displayName: string;
};
};

type DeleteMessageData = {
msgId: Id;
};

type DeleteMessagesData = {
userId: Id;
};

type OtherData = object;

declare class Adapter {
constructor(PlatformClass: typeof Platform, filters?: Filters, extraAlerts?: Alerts);
has(event: Event): boolean;
load(data: LoadData): void;
session(data: SessionData): void;
alerts(event: Event, data: AlertData, group?: Id, root?: true): void;
chat(event: Event, data: ChatData): void;
message(data: MessageData): void;
'delete-message'(data: DeleteMessageData): void;
'delete-messages'(data: DeleteMessagesData): void;
other(event: Event, data: OtherData): void;
$load?(data: LoadData): void | LoadData;
$session?(data: SessionData): void | SessionData;
$alerts?(data: AlertData, event: Event, group?: Id, root?: true): void | AlertData;
$chat?(data: ChatData, event: Event): void | ChatData;
$other?(data: OtherData, event: Event): void | OtherData;
}
tip

The data structures (type) listed above describe all the mandatory and optional properties that must be present, you can obviously add new ones!

Parameters

warning

Each parameter listed below can no longer be modified once the adapter has been instantiated (read-only).

An adapter needs to be linked to a platform so that the system can identify the source of the emitted events; this is the role of the first parameter named PlatformClass referring to a platform constructor that the adapter will be responsible for instantiating.

import {
Platform,
Adapter
} from 'https://obs.multistream.tools/v1/adapters.js';

class CustomPlatform extends Platform {
constructor(...args) {
super('custom', ['alert'], ...args);
}
}

class CustomPlatformAdapter extends Adapter {
constructor(...args) {
super(CustomPlatform, ...args);

// Implement custom integration logic here.
}
}

The optional filters and extraAlerts parameters will be directly passed to the PlatformClass constructor for which they are intended.

import {
Platform,
Adapter
} from 'https://obs.multistream.tools/v1/adapters.js';

const customAlert = 'alert';

class CustomPlatform extends Platform {
constructor(...args) {
super('custom', [customAlert], ...args);
}
}

class CustomAdapter extends Adapter {
constructor(PlatformClass, filters) {
super(PlatformClass, filters, ['commonAlert']);

// Implement custom integration logic here.
}
}

const customPlatformAdapter = new CustomAdapter(CustomPlatform, {
[customAlert]: false
});

Methods

The method named has is a simple proxy to that of the instance of the Platform class associated with the adapter.

Events emitted by a platform must be sorted according to categories in order to be processed correctly by our system. This sorting is carried out at the adapter level in its custom integration logic. The system categories are as follows:

  • 'load'; the load event must be emitted only once to indicate that the platform has been loaded correctly
  • 'session'; the session event should be emitted each time that the platform-related session data has been modified, generally after each alert
  • 'alerts'; the alerts event must be emitted for each alert triggered on the platform by the action of a spectator
  • 'chat'; the chat event must be emitted for each message posted or deleted in the platform's chat
  • 'other'; the other event can be emitted to cover possible other cases

The methods present on an instance of the Adapter class correspond to the categories listed above and are therefore intended to be called at the right time and with the right data so that the associated events can pass correctly through our system.

import {
subscriber,
message,
botCounter,
Twitch,
Adapter
} from 'https://obs.multistream.tools/v1/adapters.js';

class CustomAdapter extends Adapter {
constructor(PlatformClass, ...args) {
super(PlatformClass, ...args);

// Implement custom integration logic here.
this.load({ session: { /* ... */ } });
}
}

const customTwitchAdapter = new CustomAdapter(Twitch);

const name = 'TheFrenchBiff';

const subscriberData = { name };

customTwitchAdapter.alerts(subscriber, subscriberData);

customTwitchAdapter.session({ [`${subscriber}-latest`]: subscriberData });

customTwitchAdapter.chat(botCounter, { counter: 'power', value: 9001 });

const userId = crypto.randomUUID();
const msgId = crypto.randomUUID();

customTwitchAdapter.message({
renderedText: `test ${message}`,
data: {
userId,
msgId,
nick: name.toLowerCase(),
displayName: name
}
});

customTwitchAdapter['delete-message']({ msgId });

customTwitchAdapter['delete-messages']({ userId });

customTwitchAdapter.other('notCategorized', { /* ... */ });

The optional parameters, named group and root, of the alerts method allow linking several events together, in particular for display in our dock. A root event - indicated by the root parameter - must always be emitted first, followed by all those to be grouped; the value of the group parameter must therefore be a unique identifier shared by all these events. This can be used for example in the case of gifted subscriptions:

const group = crypto.randomUUID();

customTwitchAdapter.alerts(subscriber, { name, amount: 2 }, group, true);
customTwitchAdapter.alerts(subscriber, { name: 'userA', sender: name }, group);
customTwitchAdapter.alerts(subscriber, { name: 'userB', sender: name }, group);

The message, delete-message and delete-messages methods internally call the chat method by passing respectively 'message', 'delete-message' and 'delete- messages' to it as its first parameter for greater convenience. These are therefore preferred shortcuts.

The optional $load, $session, $alerts, $chat and $other methods allow transforming the received data before it is sent to our system. This can be useful to fix possible consistency issues, either by directly mutating the data object passed as the first parameter, or by returning a new object. These methods are never called for alerts/categories disabled through filters.

For a practical example, go to our page dedicated to adapter development.

Pre-configured adapters

We provide the following adapters exposed by the same JavaScript file cited throughout this page. To view their respective installation instructions, go to the dedicated page.

classplatformintegration
FacebookStreamElementsAdapterFacebookStreamElements
TrovoStreamElementsAdapterTrovoStreamElements
TwitchStreamElementsAdapterTwitchStreamElements
YouTubeStreamElementsAdapterYouTubeStreamElements

Their TypeScript signatures are as follows:

type WidgetLoadData = {
session: {
data: SessionData;
};
};

type SessionUpdateData = {
session: SessionData;
};

type EventReceivedData = {
listener: Event;
event: AlertsData | ChatData | OtherData;
};

declare class StreamElementsAdapter extends Adapter {
constructor(PlatformClass: typeof Platform, filters?: Filters);
$load(data: LoadData): void | LoadData;
$alerts(data: AlertData, event: Event, group?: Id, root?: true): void | AlertData;
onWidgetLoad(data: WidgetLoadData): void;
onEventReceived(data: EventReceivedData): void;
onSessionUpdate(data: SessionUpdateData): void;
}

declare class FacebookStreamElementsAdapter extends StreamElementsAdapter {
constructor(filters?: Filters);
}

declare class TrovoStreamElementsAdapter extends StreamElementsAdapter {
constructor(filters?: Filters);
}

declare class TwitchStreamElementsAdapter extends StreamElementsAdapter {
constructor(filters?: Filters);
}

declare class YouTubeStreamElementsAdapter extends StreamElementsAdapter {
constructor(filters?: Filters);
}
info

The onWidgetLoad, onEventReceived and onSessionUpdate methods of the StreamElementsAdapter class correspond to events of custom widgets, functionality offered by the StreamElements third-party service.