-
Notifications
You must be signed in to change notification settings - Fork 2
Sigmanuts API
This page will go over some technical parts of the app.
Sigmanuts is a .NET Core 3.1 WPF app, and uses WebView2 for the user interface. We will call the frontend simply Sigmanuts, and the backend Sigmanuts API. Let's talk about the frontend first.
In the frontend, the app is running two WebView2 instances - YouTube chat in the background, and the user interface of the app in the foreground. Switching to either Chat or Login tabs will bring up the background WebView2 instance, and switching away from those tabs bring the app user interface back. Both of these WebView2 instances are running together at all times.
The background instance hosts YouTube chat. It is required that it is always running as the YouTube chat stops scrolling when unfocused which breaks the mechanism by which this app works. When app is launched, the Sigmanuts API injects a script into the chat which listens for any DOM mutations, packs all the information into JSON objects and sends them out through a websocket to all the widgets that are connected to the websocket.
Sigmanuts API has 2 main components: the websocket, and the local server. The local server is hosted on port 6969 as long as the app is running, and the websocket port is 6970. All widgets are hosted on the local server, and so can be accessed like so
http://localhost:6969/widgets/${WIDGETNAME}/widget.html
When writing widgets for Sigmanuts, you don't need to create the websocket connection yourself, the app takes care of that for you. We tried to make the coding process as similar to Streamelements as possible, as it is the most popular coding environment for custom widgets. In the next section, you will find information about which events you can listen for, and what information is available to you.
To start, when writing the widget, you can listen for the following window
events: onWidgetLoad
and onEventReceived
.
In the onWidgetLoad
scope you can access all the fields of your widget like so
window.addEventListener('onWidgetLoad', function (obj) {
const fieldData = obj.detail.fieldData;
});
Similarly, listener
and detail
fields of an event can be accessed in the onEventReceived
scope like so
window.addEventListener('onEventReceived', function (obj) {
const listener = obj.detail.listeners;
const event = obj.detail.event;
});
Continue reading to find all listeners and their corresponding event information.
The listener for chat messages is message
.
The full JSON schema for the event is
{
"listener": "message",
"event": {
"service": "youtube",
"data": {
"time": 1676958488,
"tags": {
"badge-info": "",
"badges": "member/1,moderator/1",
"client-nonce": "",
"color": "#FFFFFF",
"display-name": "sigmacw",
"emotes": "",
"first-msg": "0",
"flags": "",
"id": "",
"mod": true,
"returning-chatter": "0",
"room-id": 1234,
"subscriber": true,
"member": true,
"tmi-sent-ts": "",
"turbo": "",
"user-id": 12345678,
"user-type": "moderator"
},
"nick": "sigmacw",
"userId": 12345678,
"displayName": "sigmacw",
"displayColor": "#FFFFFF",
"profileImage": "https://img.url",
"badges": [],
"channel": "",
"text": "Hello",
"isAction": false,
"emotes": [],
"msgId": 12345678
},
"renderedText": "Hello"
}
}
The listener for membership notifications is member-latest
.
The full JSON schema for the event is
{
"listener": "member-latest",
"event": {
"type": "member",
"name": "sigmacw",
"amount": 1,
"count": 1,
"items": [],
"tier": "1000",
"month": 1,
"message": "Hello",
"sessionTop": false,
"originalEventName": "member-latest",
"profileImage": "https://img.url",
"badge": "https://badge.url"
}
}
The listener for membership gifts is gift-latest
.
The full JSON schema for the event is
{
"listener": "gift-latest",
"event": {
"type": "gift",
"name": "sigmacw",
"items": [],
"tier": "1000",
"month": "",
"message": "Hello",
"sessionTop": false,
"originalEventName": "gift-latest",
"profileImage": "https://img.url",
"amount": 1,
"badge": "https://badge.url"
}
}
The listener for membership redemption is gift-redemption
.
The full JSON schema for the event is
{
"listener": "gift-redemption",
"event": {
"type": "gift-redemption",
"name": "sigmacw",
"items": [],
"tier": "1000",
"month": "",
"message": "Hello",
"sessionTop": false,
"originalEventName": "gift-redemption",
"profileImage": "https://img.url",
"sender": "chroneco"
}
}
The listener for superchat messages is superchat-latest
.
Superchats have a lot of interesting information in them, specifically colors
and tier
.
Tiers go from 1000
to 7000
based on the superchat color, and colors
just list primary and secondary colors used in superchat messages.
The full JSON schema for the event is
{
"listener": "superchat-latest",
"event": {
"type": "superchat",
"name": "sigmacw",
"amount": 50,
"count": 1,
"items": [],
"tier": "1000",
"colors": {
"primaryColor": "rgba(30,136,229,1)",
"secondaryColor": "rgba(21,101,192,1)"
},
"month": "",
"message": "Hello",
"sessionTop": false,
"originalEventName": "superchat-latest",
"profileImage": "https://img.url",
"badge": "https://badge.url"
}
}
The listener for sticker messages is sticker-latest
.
Stickers, just like superchats, have a lot of interesting information in them, specifically colors
and tier
.
Tiers go from 1000
to 7000
based on the sticker color, and colors
just list primary and secondary colors used in sticker messages.
The full JSON schema for the event is
{
"listener": "sticker-latest",
"event": {
"type": "sticker",
"name": "sigmacw",
"amount": 50,
"count": 1,
"items": [],
"tier": "1000",
"colors": {
"primaryColor": "rgba(30,136,229,1)",
"secondaryColor": "rgba(21,101,192,1)"
},
"month": "",
"stickerUrl": "https://sticker.url",
"message": "",
"sessionTop": false,
"originalEventName": "sticker-latest",
"profileImage": "https://img.url",
}
}
This one is a bit special. It doesn't have any special purpose, it just sends the raw HTML of the DOM Mutation. You can listen for it using youtube-basic
as a listener, but it's only really useful for the default YouTube chat preset in the app. The JSON schema for this event is as follows
{
"listener": "youtube-basic",
"event": {
"type": "message",
"html": "<yt-message-renderer-..> ..."
}
}