/**
* StreamRoller Copyright 2023 "SilenusTA https://www.twitch.tv/olddepressedgamer"
*
* StreamRoller is an all in one streaming solution designed to give a single
* 'second monitor' control page and allow easy integration for configuring
* content (ie. tweets linked to chat, overlays triggered by messages, hue lights
* controlled by donations etc)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* @extension DiscordChat
* Send received discord chat messages. Useful for mod messages during stream
* as these can be displayed below chat on the liveportal
* This is useful when you want mod messages not seen by chat.
*/
// ============================================================================
// IMPORTS/VARIABLES
// ============================================================================
import * as fs from "fs";
import { dirname } from "path";
import { fileURLToPath } from "url";
import * as logger from "../../backend/data_center/modules/logger.js";
import sr_api from "../../backend/data_center/public/streamroller-message-api.cjs";
const __dirname = dirname(fileURLToPath(import.meta.url));
// declare our stream references
// use localConfig for stuff that doesn't change or is temporary and not needed to
// be saved over restarts
const localConfig = {
OUR_CHANNEL: "DISCORD_CHAT",
EXTENSION_NAME: "discordchat",
SYSTEM_LOGGING_TAG: "[EXTENSION]",
discordClient: null,
heartBeatTimeout: 5000,
heartBeatHandle: null,
status: {
connected: false
},
DataCenterSocket: null
};
//this object will be overwritten from the sever data if it exists
const default_serverConfig = {
__version__: 0.2,
extensionname: localConfig.EXTENSION_NAME,
channel: localConfig.OUR_CHANNEL, // backend socket channel.
monitoring_channel: "stream-mod-messages", // discord channel
discordenabled: "off",
discordMessageBufferMaxSize: "300",
discordMessageBackupTimer: "60",
discordchat_restore_defaults: "off",
//credentials variable names to use (in credentials modal)
credentialscount: "1",
cred1name: "DISCORD_TOKEN",
cred1value: ""
};
// need to make sure we have a proper clone of this object and not a reference
// otherwise changes to server also change defaults
let serverConfig = structuredClone(default_serverConfig)
const serverData =
{
discordMessageBuffer: [{ name: "system", message: "Start of buffer" }]
};
const triggersandactions =
{
extensionname: serverConfig.extensionname,
description: "Discord provides an easy way to talk over voice, video, and text. Talk, chat, hang out, and stay close with your friends and communities.",
version: "0.3",
channel: serverConfig.channel,
// these are messages we can sendout that other extensions might want to use to trigger an action
triggers:
[
{
name: "DiscordMessageRecieved",
displaytitle: "Discord Message Posted",
description: "A message was posted to a discord chat room",
messagetype: "trigger_DiscordMessageReceived",
parameters:
{
channel: "",
name: "",
message: ""
}
}
],
// these are messages we can receive to perform an action
actions:
[
{
name: "DiscordPostMessage",
displaytitle: "Post Message",
description: "Post a message to a discord channel",
messagetype: "action_DiscordPostMessage",
parameters:
{
channel: "",
message: "",
file: ""
}
}
],
}
// ============================================================================
// FUNCTION: initialise
// ============================================================================
/**
* Starts the extension using the given data.
* @param {Express} app
* @param {String} host
* @param {Number} port
* @param {Number} heartbeat
*/
function initialise (app, host, port, heartbeat)
{
logger.extra(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".initialise", "host", host, "port", port, "heartbeat", heartbeat);
if (typeof (heartbeat) != "undefined")
localConfig.heartBeatTimeout = heartbeat;
else
logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".initialise", "DataCenterSocket no heatbeat passed:", heartbeat);
try
{
localConfig.DataCenterSocket = sr_api.setupConnection(onDataCenterMessage, onDataCenterConnect, onDataCenterDisconnect, host, port);
} catch (err)
{
logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".initialise", "DataCenterSocket connection failed:", err);
}
}
// ============================================================================
// FUNCTION: onDataCenterDisconnect
// ============================================================================
/**
* called when websocket connection to server goes down
* @param {string} reason
*/
function onDataCenterDisconnect (reason)
{
logger.log(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterDisconnect", reason);
}
// ============================================================================
// FUNCTION: onDataCenterConnect
// ============================================================================
/**
* called when a new server websocket connection is made
*/
function onDataCenterConnect ()
{
logger.log(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterConnect", "Creating our channel");
// Request our config from the server
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("RequestConfig", serverConfig.extensionname));
// Request our credentials from the server
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("RequestCredentials", serverConfig.extensionname));
// Create/Join the channels we need for this
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("CreateChannel", serverConfig.extensionname, serverConfig.channel));
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("RequestData", localConfig.EXTENSION_NAME));
// clear the previous timeout if we have one
clearTimeout(localConfig.heartBeatHandle);
// start our heartbeat timer
localConfig.heartBeatHandle = setTimeout(heartBeatCallback, localConfig.heartBeatTimeout)
}
// ============================================================================
// FUNCTION: onDataCenterMessage
// ============================================================================
/**
* Called when a message is received on the websocket
* @param {object} server_packet
*/
function onDataCenterMessage (server_packet)
{
if (server_packet.type === "ConfigFile")
{
// check if there is a server config to use. This could be empty if it is our first run or we have never saved any config data before.
// if it is empty we will use our current default and send it to the server
if (server_packet.data != "" && server_packet.to === serverConfig.extensionname)
{
if (server_packet.data.__version__ != default_serverConfig.__version__)
{
serverConfig = structuredClone(default_serverConfig);
console.log("\x1b[31m" + serverConfig.extensionname + " ConfigFile Updated", "The config file has been Updated to the latest version v" + default_serverConfig.__version__ + ". Your settings may have changed" + "\x1b[0m");
}
else
serverConfig = structuredClone(server_packet.data);
SaveConfigToServer();
}
}
else if (server_packet.type === "CredentialsFile")
{
if (server_packet.to === serverConfig.extensionname && server_packet.data != "")
connectToDiscord(server_packet.data);
else
{
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
serverConfig.extensionname + " CredentialsFile", "Credential file is empty make sure to set it on the admin page.");
}
}
else if (server_packet.type === "DataFile")
{
if (server_packet.data != "")
{
// check it is our config
if (server_packet.to === serverConfig.extensionname)
{
if (Object.keys(server_packet.data).length != 0 && typeof (server_packet.data.discordMessageBuffer) != "undefined")
serverData.discordMessageBuffer = server_packet.data.discordMessageBuffer;
}
SaveDataToServer();
}
SaveChatMessagesToServerScheduler();
} else if (server_packet.type === "UnknownChannel")
{
logger.info(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
"Channel " + server_packet.data + " doesn't exist, scheduling rejoin");
//channel might not exist yet, extension might still be starting up so lets rescehuled the join attempt
// need to add some sort of flood control here so we are only attempting to join one at a time
setTimeout(() =>
{
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("JoinChannel",
serverConfig.extensionname,
server_packet.data));
}, 5000);
}
else if (server_packet.type == "ExtensionMessage")
{
let extension_packet = server_packet.data;
// received a reqest for our admin bootstrap modal code
if (extension_packet.to === serverConfig.extensionname)
{
if (extension_packet.type === "RequestSettingsWidgetSmallCode")
SendSettingsWidgetSmall(extension_packet.from);
else if (extension_packet.type === 'RequestSettingsWidgetLargeCode')
SendSettingsWidgetLarge(extension_packet.from);
else if (extension_packet.type === "RequestCredentialsModalsCode")
SendCredentialsModal(extension_packet.from);
// received data from our settings widget small. A user has requested some settings be changedd
else if (extension_packet.type === "SettingsWidgetSmallData")
{
// set our config values to the ones in message
serverConfig.discordenabled = "off";
// NOTE: this will ignore new items in the page that we don't currently have in our config
for (const [key] of Object.entries(serverConfig))
{
if (key in extension_packet.data)
serverConfig[key] = extension_packet.data[key];
}
// save our data to the server for next time we run
SaveConfigToServer();
// broadcast our modal out so anyone showing it can update it
SendSettingsWidgetSmall("");
SendSettingsWidgetLarge("");
}
else if (extension_packet.type === "SettingsWidgetLargeData")
{
if (extension_packet.data.discordchat_restore_defaults == "on")
serverConfig = structuredClone(default_serverConfig);
else
{
// set our config values to the ones in message
serverConfig.discordenabled = "off";
// NOTE: this will ignore new items in the page that we don't currently have in our config
// and only performs a shallow copy
for (const [key] of Object.entries(serverConfig))
{
if (key in extension_packet.data)
serverConfig[key] = extension_packet.data[key];
}
}
// save our data to the server for next time we run
SaveConfigToServer();
// broadcast our modal out so anyone showing it can update it
SendSettingsWidgetSmall("");
SendSettingsWidgetLarge("");
}
else if (extension_packet.type === "action_DiscordPostMessage")
{
logger.info(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname +
".onDataCenterMessage", "Posting Message", extension_packet.data)
if (serverConfig.discordenabled === "on")
{
const channel = localConfig.discordClient.channels.cache.find(channel => channel.name === extension_packet.data.channel);
if (typeof (channel) != "undefined")
{
if (extension_packet.data.file && extension_packet.data.file != "")
{
channel.send(
{
content: extension_packet.data.message,
files: [{
attachment: extension_packet.data.file,
name: 'AI_Image_File.jpg',
description: "AI image from stream"
}]
})
}
else
{
// Send a basic text message
channel.send(extension_packet.data.message);
}
}
else
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
"Failed to find discord channel to send to", extension_packet.data.channel);
}
else
{
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
"Not posting to Discord as extension is turned off ", extension_packet.data.message);
}
}
else if (extension_packet.type === "RequestChatBuffer")
{
sendChatBuffer(server_packet.from)
}
else if (extension_packet.type === "ChangeListeningChannel")
{
serverConfig.monitoring_channel = extension_packet.data;
SaveConfigToServer();
logger.info(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage", "ChangeListeningChannel received ", extension_packet.data);
}
else if (extension_packet.type === "SendTriggerAndActions")
{
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ExtensionMessage",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"TriggerAndActions",
serverConfig.extensionname,
triggersandactions,
"",
server_packet.from
),
"",
server_packet.from
)
)
}
else
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
"Unable to process ExtensionMessage : ", server_packet);
}
else if (extension_packet.type === "SettingsWidgetSmallCode"
|| extension_packet.type === "SettingsWidgetLargeCode"
|| extension_packet.type === "TriggerAndActions")
{
// ignore these messages
}
else
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
"received Unhandled ExtensionMessage : ", server_packet);
}
else if (server_packet.type === "ChannelData")
{
if (server_packet.channel === serverConfig.channel)
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
serverConfig.channel + " message received !?!?", server_packet);
else
{
logger.info(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".onDataCenterMessage",
"received message: ", server_packet);
}
}
else if (server_packet.type === "ChannelJoined"
|| server_packet.type === "ChannelCreated"
|| server_packet.type === "ChannelLeft"
|| server_packet.type === "LoggingLevel")
{
// just a blank handler for items we are not using to avoid message from the catchall
}
// ------------------------------------------------ unknown message type received -----------------------------------------------
else
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname +
".onDataCenterMessage", "Unhandled message type", server_packet.type);
}
// ===========================================================================
// FUNCTION: sendChatBuffer
// ===========================================================================
/**
* Send our chat buffer to the extension
* @param {String} toExtension
*/
function sendChatBuffer (toExtension)
{
// send the modified modal data to the server
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket(
"ExtensionMessage",
localConfig.EXTENSION_NAME,
sr_api.ExtensionPacket(
"DiscordChatBuffer",
localConfig.EXTENSION_NAME,
serverData.discordMessageBuffer,
"",
toExtension,
localConfig.OUR_CHANNEL),
"",
toExtension
));
}
// ===========================================================================
// FUNCTION: SendSettingsWidgetSmall
// ===========================================================================
/**
* Send our SettingsWidgetSmall to whoever requested it
* @param {String} extensionname
*/
function SendSettingsWidgetSmall (extensionname)
{
fs.readFile(__dirname + "/discordsettingswidgetsmall.html", function (err, filedata)
{
if (err)
logger.err(localConfig.SYSTEM_LOGGING_TAG + localConfig.EXTENSION_NAME +
".SendSettingsWidgetSmall", "failed to load modal", err);
//throw err;
else
{
let modalstring = filedata.toString();
// first lets update our modal to the current settings
for (const [key, value] of Object.entries(serverConfig))
{
// true values represent a checkbox so replace the "[key]checked" values with checked
if (value === "on")
{
modalstring = modalstring.replaceAll(key + "checked", "checked");
} //value is a string then we need to replace the text
else if (typeof (value) == "string")
modalstring = modalstring.replaceAll(key + "text", value);
}
// send the modal data to the server
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ExtensionMessage",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"SettingsWidgetSmallCode",
serverConfig.extensionname,
modalstring,
"",
extensionname,
serverConfig.channel
),
"",
extensionname)
)
}
});
}
// ===========================================================================
// FUNCTION: SendSettingsWidgetLarge
// ===========================================================================
/**
* Send our SettingsWidgetSmall to whoever requested it
* @param {String} extensionname
*/
function SendSettingsWidgetLarge (extensionname)
{
fs.readFile(__dirname + "/discordsettingswidgetlarge.html", function (err, filedata)
{
if (err)
logger.err(localConfig.SYSTEM_LOGGING_TAG + localConfig.EXTENSION_NAME +
".SendSettingsWidgetLarge", "failed to load modal", err);
//throw err;
else
{
let modalstring = filedata.toString();
// first lets update our modal to the current settings
for (const [key, value] of Object.entries(serverConfig))
{
// true values represent a checkbox so replace the "[key]checked" values with checked
if (value === "on")
{
modalstring = modalstring.replaceAll(key + "checked", "checked");
} //value is a string then we need to replace the text
else if (typeof (value) == "string")
modalstring = modalstring.replaceAll(key + "text", value);
}
// send the modal data to the server
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ExtensionMessage",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"SettingsWidgetLargeCode",
serverConfig.extensionname,
modalstring,
"",
extensionname,
serverConfig.channel
),
"",
extensionname)
)
}
});
}
// ===========================================================================
// FUNCTION: SendCredentialsModal
// ===========================================================================
/**
* Send our CredentialsModal to whoever requested it
* @param {String} extensionname
*/
function SendCredentialsModal (extensionname)
{
fs.readFile(__dirname + "/discordcredentialsmodal.html", function (err, filedata)
{
if (err)
logger.err(localConfig.SYSTEM_LOGGING_TAG + localConfig.EXTENSION_NAME +
".SendCredentialsModal", "failed to load modal", err);
//throw err;
else
{
let modalstring = filedata.toString();
// first lets update our modal to the current settings
for (const [key, value] of Object.entries(serverConfig))
{
// true values represent a checkbox so replace the "[key]checked" values with checked
if (value === "on")
{
modalstring = modalstring.replaceAll(key + "checked", "checked");
} //value is a string then we need to replace the text
else if (typeof (value) == "string")
{
modalstring = modalstring.replaceAll(key + "text", value);
}
}
// send the modal data to the server
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ExtensionMessage",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"CredentialsModalCode",
serverConfig.extensionname,
modalstring,
"",
extensionname,
serverConfig.channel
),
"",
extensionname)
)
}
});
}
// ============================================================================
// FUNCTION: SaveConfigToServer
// ============================================================================
/**
* save our config to the server
*/
function SaveConfigToServer ()
{
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket(
"SaveConfig",
serverConfig.extensionname,
serverConfig));
}
// ============================================================================
// FUNCTION: SaveDataToServer
// ============================================================================
// Description:save data on backend data store
// Parameters: none
// ----------------------------- notes ----------------------------------------
// none
// ===========================================================================
/**
* save our data to the server
*/
function SaveDataToServer ()
{
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket(
"SaveData",
localConfig.EXTENSION_NAME,
serverData));
}
// ============================================================================
// FUNCTION: SaveChatMessagesToServerScheduler
// ============================================================================
/**
* saves the discord chat buffer to the server
*/
function SaveChatMessagesToServerScheduler ()
{
SaveDataToServer()
// clear any previous timeout
clearTimeout(localConfig.saveDataHandle)
localConfig.saveDataHandle = setTimeout(SaveChatMessagesToServerScheduler, serverConfig.discordMessageBackupTimer * 1000)
}
// ############################################################################
// Discord server code
// ############################################################################
// ============================================================================
// IMPORTS AND GLOBALS
// ============================================================================
import { Client, Intents } from "discord.js";
//import { clearTimeout } from "timers";
// ============================================================================
// FUNCTION: connectToDiscord
// ============================================================================
/**
* Connets to discord
* @param {object} credentials
*/
function connectToDiscord (credentials)
{
try
{
localConfig.discordClient = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
localConfig.discordClient.on("ready", function (e)
{
localConfig.status.connected = true;
//logger.log(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname, `Logged in as ${localConfig.discordClient.user.tag}!`);
//let messagedata = { name: message.author.username, message: message.content }
process_chat_data({ author: { username: "System" }, content: "Connected to Discord" });
//process_chat_data(localConfig.discordClient.user.tag, chatmessagetags, "Chat Connected to " + serverConfig.streamername)
});
// Authenticate the discord client to start it up
if (!credentials.DISCORD_TOKEN)
{
localConfig.status.connected = false;
logger.warn(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname, "DISORD_TOKEN not set");
}
else
{
localConfig.discordClient.login(credentials.DISCORD_TOKEN)
.then(() => { localConfig.status.connected = true; })
.catch((err) => logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname, "Discord login failed", err.message))
}
localConfig.discordClient.on("reconnection", (message) => discordReconnectHandler(message));
localConfig.discordClient.on("disconnect", (message) => discordDisconnectHandler(message));
localConfig.discordClient.on("error", (message) => discordErrorHandler(message));
localConfig.discordClient.on("messageCreate", (message) => discordMessageHandler(message));
}
catch (err)
{
localConfig.status.connected = false;
logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname, "Discord Error ", err.name, err.message);
}
}
// ============================================================================
// FUNCTION: discordDisconnectHandler
// ============================================================================
/**
* Called when discord disconnects
* @param {string} message
*/
function discordDisconnectHandler (message)
{
localConfig.status.connected = false;
logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".discordDisconnectHandler", "Discord Error ", message);
}
// ============================================================================
// FUNCTION: discordErrorHandler
// ============================================================================
/**
* Handles discord error messages
* @param {string} message
*/
function discordErrorHandler (message)
{
localConfig.status.connected = false;
logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".discordErrorHandler", "Discord Error ", message);
}
// ============================================================================
// FUNCTION: discordErrorHandler
// ============================================================================
/**
* Handles discord reconnections
* @param {string} message
*/
function discordReconnectHandler (message)
{
localConfig.status.connected = true;
logger.err(localConfig.SYSTEM_LOGGING_TAG + serverConfig.extensionname + ".discordReconnectHandler", "Discord Reconnected ");
}
// ============================================================================
// FUNCTION: discordMessageHandler
// ============================================================================
/**
* Handles discord messages
* @param {string} message
*/
function discordMessageHandler (message)
{
// stop bot responding to other bots
if (message.author.bot) return;
// Stop bot responding to itself
if (message.author.id === localConfig.discordClient.user.id)
return;
if (serverConfig.discordenabled != "on")
return
//restrict to only channel the channel we want to
if (message.channel.name === serverConfig.monitoring_channel)
{
// send this out so we can put it in our chat window
sendAlertMessageReceived(message)
//restrict to only Twitch Subscribers who have synced with discord
//if (message.member.roles.cache.some((role) => role.name === "Twitch Subscriber")) {
//if (message.content === "Test") {
//const user = interaction.options.getUser(message.user);
message.reply("Message recieved, I'll pass it on to ODG if I can be bothered!");
/*console.log(message);
logger.log(message.user);
console.log(message.member);
console.log(message.author.username);*/
//console.log("discordMessageHandler: ", message)
process_chat_data(message)
}
}
// ============================================================================
// FUNCTION: sendAlertMessageReceived
// ============================================================================
/**
* sends a discord message alert trigger.
* @param {object} message
*/
function sendAlertMessageReceived (message)
{
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ChannelData",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"trigger_DiscordMessageReceived",
serverConfig.extensionname,
{
channel: message.channel.name,
name: message.author.username,
message: message.content
},
serverConfig.channel),
serverConfig.channel
),
);
}
// ============================================================================
// FUNCTION: process_chat_data
// ============================================================================
/**
* Sends out a discord message targetted for teh liveportal chat window
*
* @deprecated this should be removed and extensions should check for the
* "trigger_DiscordMessageReceived" trigger instead
* @param {object} message
*/
function process_chat_data (message)
{
let messagedata = { name: message.author.username, message: message.content }
serverData.discordMessageBuffer.push(messagedata);
// Send the message received out on our streamroller "DISCORD_CHAT" channel for other extensions to use if needed
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ChannelData",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"DiscordModChat",
serverConfig.extensionname,
messagedata,
serverConfig.channel),
serverConfig.channel
),
);
}
// ============================================================================
// FUNCTION: heartBeat
// ============================================================================
/**
* sends heartbeat status out so other extensions can monitor our status
*/
function heartBeatCallback ()
{
let connected = localConfig.status.connected
if (serverConfig.discordenabled === "off")
connected = false;
sr_api.sendMessage(localConfig.DataCenterSocket,
sr_api.ServerPacket("ChannelData",
serverConfig.extensionname,
sr_api.ExtensionPacket(
"HeartBeat",
serverConfig.extensionname,
{ connected: connected },
serverConfig.channel),
serverConfig.channel
),
);
localConfig.heartBeatHandle = setTimeout(heartBeatCallback, localConfig.heartBeatTimeout)
}
// ============================================================================
// EXPORTS: initialise
// ============================================================================
// Description: exports from this module
// ----------------------------- notes ----------------------------------------
// will also need additional exports in future (ie reconnect, stop, start etc)
// ============================================================================
export { initialise, triggersandactions };