/**
* Copyright (C) 2023 "SilenusTA https://www.twitch.tv/olddepressedgamer"
*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
These appear to be all the subs that can be made through this interface.
listed here as I can never seem to find my way back to the webpage at
https://twurple.js.org/reference/eventsub-ws/classes/EventSubWsListener.html
onChannelBan
onChannelCharityCampaignProgress
onChannelCharityCampaignStart
onChannelCharityCampaignStop
onChannelCharityDonation
onChannelCheer
onChannelFollow
onChannelGoalBegin
onChannelGoalEnd
onChannelGoalProgress
onChannelHypeTrainBegin
onChannelHypeTrainEnd
onChannelHypeTrainProgress
onChannelModeratorAdd
onChannelModeratorRemove
onChannelPollBegin
onChannelPollEnd
onChannelPollProgress
onChannelPredictionBegin
onChannelPredictionEnd
onChannelPredictionLock
onChannelPredictionProgress
onChannelRaidFrom
onChannelRaidTo
onChannelRedemptionAdd
onChannelRedemptionUpdate
***onChannelRedemptionAddForReward
***onChannelRedemptionUpdateForReward
onChannelRewardAdd
onChannelRewardRemove
***onChannelRewardRemoveForReward
onChannelRewardUpdate
***onChannelRewardUpdateForReward
onChannelShieldModeBegin
onChannelShieldModeEnd
onChannelShoutoutCreate
onChannelShoutoutReceive
onChannelSubscription
onChannelSubscriptionEnd
onChannelSubscriptionGift
onChannelSubscriptionMessage
onChannelUnban
onChannelUpdate
***onDropEntitlementGrant
***onExtensionBitsTransactionCreate
onStreamOffline
onStreamOnline
***onUserAuthorizationGrant
***onUserAuthorizationRevoke
*/
import { EventSubWsListener } from '@twurple/eventsub-ws';
import * as logger from "../../../backend/data_center/modules/logger.js";
import sr_api from "../../../backend/data_center/public/streamroller-message-api.cjs";
const localConf = {
apiClient: null,
apiEventSub: null,
eventSubs: [],
tAndAs: null,
channelData: null,
streamerId: null,
triggerCAllback: null
}
// get functions from https://twurple.js.org/reference/api/classes/HelixChannel.html
// get return values from https://twurple.js.org/reference/eventsub-base/classes/
const pubSubHandles = []
pubSubHandles["onChannelBan"] = { "name": "onChannelBan", "func": onChannelBan, "handle": null }
pubSubHandles["onChannelCharityCampaignProgress"] = { "name": "onChannelCharityCampaignProgress", "func": onChannelCharityCampaignProgress, "handle": null }
pubSubHandles["onChannelCharityCampaignStart"] = { "name": "onChannelCharityCampaignStart", "func": onChannelCharityCampaignStart, "handle": null }
pubSubHandles["onChannelCharityCampaignStop"] = { "name": "onChannelCharityCampaignStop", "func": onChannelCharityCampaignStop, "handle": null }
pubSubHandles["onChannelCharityDonation"] = { "name": "onChannelCharityDonation", "func": onChannelCharityDonation, "handle": null }
pubSubHandles["onChannelCheer"] = { "name": "onChannelCheer", "func": onChannelCheer, "handle": null }
pubSubHandles["onChannelFollow"] = { "name": "onChannelFollow", "func": onChannelFollow, "handle": null, "secondId": "true" }
pubSubHandles["onChannelGoalBegin"] = { "name": "onChannelGoalBegin", "func": onChannelGoalBegin, "handle": null }
pubSubHandles["onChannelGoalEnd"] = { "name": "onChannelGoalEnd", "func": onChannelGoalEnd, "handle": null }
pubSubHandles["onChannelGoalProgress"] = { "name": "onChannelGoalProgress", "func": onChannelGoalProgress, "handle": null }
pubSubHandles["onChannelHypeTrainBegin"] = { "name": "onChannelHypeTrainBegin", "func": onChannelHypeTrainBegin, "handle": null }
pubSubHandles["onChannelHypeTrainEnd"] = { "name": "onChannelHypeTrainEnd", "func": onChannelHypeTrainEnd, "handle": null }
pubSubHandles["onChannelHypeTrainProgress"] = { "name": "onChannelHypeTrainProgress", "func": onChannelHypeTrainProgress, "handle": null }
pubSubHandles["onChannelModeratorAdd"] = { "name": "onChannelModeratorAdd", "func": onChannelModeratorAdd, "handle": null }
pubSubHandles["onChannelModeratorRemove"] = { "name": "onChannelModeratorRemove", "func": onChannelModeratorRemove, "handle": null }
pubSubHandles["onChannelPollBegin"] = { "name": "onChannelPollBegin", "func": onChannelPollBegin, "handle": null }
pubSubHandles["onChannelPollEnd"] = { "name": "onChannelPollEnd", "func": onChannelPollEnd, "handle": null }
pubSubHandles["onChannelPollProgress"] = { "onChannelPollProgress": "onChannelPollProgress", "func": onChannelPollProgress, "handle": null }
pubSubHandles["onChannelPredictionBegin"] = { "name": "onChannelPredictionBegin", "func": onChannelPredictionBegin, "handle": null }
pubSubHandles["onChannelPredictionEnd"] = { "name": "onChannelPredictionEnd", "func": onChannelPredictionEnd, "handle": null }
pubSubHandles["onChannelPredictionProgress"] = { "onChannelPredictionProgress": "onChannelPredictionProgress", "func": onChannelPredictionProgress, "handle": null }
pubSubHandles["onChannelPredictionLock"] = { "onChannelPredictionLock": "onChannelPredictionLock", "func": onChannelPredictionLock, "handle": null }
pubSubHandles["onChannelRaidFrom"] = { "name": "onChannelRaidFrom", "func": onChannelRaidFrom, "handle": null }
pubSubHandles["onChannelRaidTo"] = { "name": "onChannelRaidTo", "func": onChannelRaidTo, "handle": null }
pubSubHandles["onChannelRedemptionAdd"] = { "name": "onChannelRedemptionAdd", "func": onChannelRedemptionAdd, "handle": null }
pubSubHandles["onChannelRedemptionUpdate"] = { "name": "onChannelRedemptionUpdate", "func": onChannelRedemptionUpdate, "handle": null }
pubSubHandles["onChannelRewardAdd"] = { "name": "onChannelRewardAdd", "func": onChannelRewardAdd, "handle": null }
pubSubHandles["onChannelRewardRemove"] = { "name": "onChannelRewardRemove", "func": onChannelRewardRemove, "handle": null }
pubSubHandles["onChannelRewardUpdate"] = { "name": "onChannelRewardUpdate", "func": onChannelRewardUpdate, "handle": null }
pubSubHandles["onChannelShieldModeBegin"] = { "name": "onChannelShieldModeBegin", "func": onChannelShieldModeBegin, "handle": null, "secondId": "true" }
pubSubHandles["onChannelShieldModeEnd"] = { "name": "onChannelShieldModeEnd", "func": onChannelShieldModeEnd, "handle": null, "secondId": "true" }
pubSubHandles["onChannelShoutoutCreate"] = { "name": "onChannelShoutoutCreate", "func": onChannelShoutoutCreate, "handle": null, "secondId": "true" }
pubSubHandles["onChannelShoutoutReceive"] = { "name": "onChannelShoutoutReceive", "func": onChannelShoutoutReceive, "handle": null, "secondId": "true" }
pubSubHandles["onChannelSubscription"] = { "name": "onChannelSubscription", "func": onChannelSubscription, "handle": null }
pubSubHandles["onChannelSubscriptionEnd"] = { "name": "onChannelSubscriptionEnd", "func": onChannelSubscriptionEnd, "handle": null }
pubSubHandles["onChannelSubscriptionGift"] = { "name": "onChannelSubscriptionGift", "func": onChannelSubscriptionGift, "handle": null }
pubSubHandles["onChannelSubscriptionMessage"] = { "name": "onChannelSubscriptionMessage", "func": onChannelSubscriptionMessage, "handle": null }
pubSubHandles["onChannelUnban"] = { "name": "onChannelUnban", "func": onChannelUnban, "handle": null }
pubSubHandles["onChannelUpdate"] = { "name": "onChannelUpdate", "func": onChannelUpdate, "handle": null }
pubSubHandles["onStreamOnline"] = { "name": "onStreamOnline", "func": onStreamOnline, "handle": null }
pubSubHandles["onStreamOffline"] = { "name": "onStreamOffline", "func": onStreamOffline, "handle": null }
let parentLocalConfig = null
let parentServerConfig = null
// ============================================================================
// FUNCTION: Init
// ============================================================================
/**
* Initialises the pub sub module with the given data
* @param {object} LocalConfig
* @param {object} ServerConfig
* @param {object} tAndAs
* @param {function} triggerCAllback
*/
function init (LocalConfig, ServerConfig, tAndAs, triggerCAllback)
{
parentLocalConfig = LocalConfig;
parentServerConfig = ServerConfig;
localConf.tAndAs = tAndAs
localConf.triggerCAllback = triggerCAllback
}
// ============================================================================
// FUNCTION: startEventSub
// ============================================================================
/**
* Starts event pub subs registration
* @param {string} streamerId
* @param {object} apiClient
* @param {object} channelData
*/
async function startEventSub (streamerId, apiClient, channelData)
{
try
{
localConf.channelData = channelData;
localConf.streamerId = streamerId
localConf.apiClient = apiClient
//connect to the event sub listener and start it
localConf.apiEventSub = new EventSubWsListener({ apiClient: apiClient });
await localConf.apiEventSub.start();
registerSubs(streamerId);
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.connectEventSubWs", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: registerSubs
// ============================================================================
/**
* register all subs for the given streamerId stream
* @param {string} streamerId
*/
function registerSubs (streamerId)
{
try
{
// loop object
let keys = Object.keys(pubSubHandles)
keys.forEach(element =>
{
if (pubSubHandles[element].secondId != "true")
pubSubHandles[element].handle = localConf.apiEventSub[element](streamerId, pubSubHandles[element].func)
else // some events need a second moderatorId so just use the streamers for this
pubSubHandles[element].handle = localConf.apiEventSub[element](streamerId, streamerId, pubSubHandles[element].func)
});
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.registerSubs", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: removeSubs
// ============================================================================
/**
* remove all sub events
*/
function removeSubs ()
{
try
{
// loop object
let keys = Object.keys(pubSubHandles)
keys.forEach(element =>
{
if (pubSubHandles[element].handle != null)
{
pubSubHandles[element].handle.stop()
pubSubHandles[element].handle = null
}
});
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.removeSubs", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelBan
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelBan (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchUserBanned");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.endDate = data.endDate;
trigger.parameters.isPermanent = data.isPermanent;
trigger.parameters.moderator = data.moderatorDisplayName;
trigger.parameters.reason = data.reason;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelBan", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelCharityCampaignProgress
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelCharityCampaignProgress (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_CharityCampaignProgress");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.charityName = data.charityName;
trigger.parameters.charityDescription = data.charityDescription;
trigger.parameters.charityWebsite = data.charityWebsite;
trigger.parameters.charityLogo = data.charityLogo;
trigger.parameters.currentAmount = data.currentAmount;
trigger.parameters.targetAmount = data.targetAmount;
trigger.parameters.id = data.id;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelCharityCampaignProgress", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelCharityCampaignStart
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelCharityCampaignStart (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchCharityCampaignStart");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.charityName = data.charityName;
trigger.parameters.charityDescription = data.charityDescription;
trigger.parameters.charityWebsite = data.charityWebsite;
trigger.parameters.charityLogo = data.charityLogo;
trigger.parameters.currentAmount = data.currentAmount;
trigger.parameters.targetAmount = data.targetAmount;
trigger.parameters.id = data.id;
trigger.parameters.startDate = data.startDate;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelCharityCampaignStart", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelCharityCampaignStop
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelCharityCampaignStop (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchCharityCampaignStop");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.charityName = data.charityName;
trigger.parameters.charityDescription = data.charityDescription;
trigger.parameters.charityWebsite = data.charityWebsite;
trigger.parameters.charityLogo = data.charityLogo;
trigger.parameters.currentAmount = data.currentAmount;
trigger.parameters.targetAmount = data.targetAmount;
trigger.parameters.id = data.id;
trigger.parameters.endDate = data.endDate;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelCharityCampaignStop", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelCharityDonation
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelCharityDonation (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchCharityDonation");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.amount = data.amount;
trigger.parameters.campaignId = data.campaignId;
trigger.parameters.charityName = data.charityName;
trigger.parameters.charityDescription = data.charityDescription;
trigger.parameters.charityWebsite = data.charityWebsite;
trigger.parameters.charityLogo = data.charityLogo;
trigger.parameters.donor = data.donorDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelCharityDonation", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelCheer
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelCheer (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchCheer");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.bits = data.bits;
trigger.parameters.isAnonymous = data.isAnonymous;
trigger.parameters.message = data.message;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelCheer", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelFollow
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelFollow (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchFollow");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelFollow", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelGoalBegin
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelGoalBegin (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchGoalBegin");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.currentAmount = data.currentAmount;
trigger.parameters.description = data.description;
trigger.parameters.startDate = data.startDate;
trigger.parameters.targetAmount = data.targetAmount;
trigger.parameters.type = data.type;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelGoalBegin", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelGoalEnd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelGoalEnd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchGoalEnd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.currentAmount = data.currentAmount;
trigger.parameters.description = data.description;
trigger.parameters.startDate = data.startDate;
trigger.parameters.endDate = data.endDate;
trigger.parameters.targetAmount = data.targetAmount;
trigger.parameters.type = data.type;
trigger.parameters.isAchieved = data.isAchieved;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelGoalEnd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelGoalProgress
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelGoalProgress (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchGoalProgress");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.currentAmount = data.currentAmount;
trigger.parameters.description = data.description;
trigger.parameters.startDate = data.startDate;
trigger.parameters.targetAmount = data.targetAmount;
trigger.parameters.type = data.type;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelGoalProgress", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelHypeTrainBegin
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelHypeTrainBegin (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchHypeTrainBegin");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.expiryDate = data.expiryDate;
trigger.parameters.goal = data.goal;
trigger.parameters.id = data.id;
trigger.parameters.lastContribution = data.lastContribution;
trigger.parameters.level = data.level;
trigger.parameters.progress = data.progress;
trigger.parameters.startDate = data.startDate;
trigger.parameters.topContributors = data.topContributors;
trigger.parameters.total = data.total;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelHypeTrainBegin", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelHypeTrainEnd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelHypeTrainEnd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchHypeTrainEnd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.cooldownEndDate = data.cooldownEndDate;
trigger.parameters.endDate = data.endDate;
trigger.parameters.id = data.id;
trigger.parameters.level = data.level;
trigger.parameters.startDate = data.startDate;
trigger.parameters.topContributors = data.topContributors;
trigger.parameters.total = data.total;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelHypeTrainEnd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelHypeTrainProgress
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelHypeTrainProgress (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchHypeTrainProgress");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.expiryDate = data.expiryDate;
trigger.parameters.goal = data.goal;
trigger.parameters.id = data.id;
trigger.parameters.lastContribution = data.lastContribution;
trigger.parameters.level = data.level;
trigger.parameters.progress = data.progress;
trigger.parameters.startDate = data.startDate;
trigger.parameters.topContributors = data.topContributors;
trigger.parameters.total = data.total;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelHypeTrainProgress", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelModeratorAdd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelModeratorAdd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchModAdded");
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelModeratorAdd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelModeratorRemove
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelModeratorRemove (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchModRemoved");
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelModeratorRemove", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelPollBegin
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPollBegin (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPollBegin");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.bitsPerVote = data.bitsPerVote;
trigger.parameters.channelPointsPerVote = data.channelPointsPerVote;
trigger.parameters.choices = data.choices;
trigger.parameters.endDate = data.endDate;
trigger.parameters.id = data.id;
trigger.parameters.isBitsVotingEnabled = data.isBitsVotingEnabled;
trigger.parameters.isChannelPointsVotingEnabled = data.isChannelPointsVotingEnabled;
trigger.parameters.startDate = data.startDate;
trigger.parameters.title = data.title;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPollBegin", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelPollEnd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPollEnd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPollEnd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.bitsPerVote = data.bitsPerVote;
trigger.parameters.channelPointsPerVote = data.channelPointsPerVote;
trigger.parameters.choices = data.choices;
trigger.parameters.endDate = data.endDate;
trigger.parameters.id = data.id;
trigger.parameters.isBitsVotingEnabled = data.isBitsVotingEnabled;
trigger.parameters.isChannelPointsVotingEnabled = data.isChannelPointsVotingEnabled;
trigger.parameters.startDate = data.startDate;
trigger.parameters.startDate = data.status;
trigger.parameters.title = data.title;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPollEnd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelPollProgress
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPollProgress (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPollProgress");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.bitsPerVote = data.bitsPerVote;
trigger.parameters.channelPointsPerVote = data.channelPointsPerVote;
trigger.parameters.choices = ""
data.choices.forEach(function (choice, index)
{
if (index > 0)
trigger.parameters.choices += " - "
trigger.parameters.choices += choice.title + " " + choice.totalVotes
})
trigger.parameters.endDate = data.endDate;
trigger.parameters.id = data.id;
trigger.parameters.isBitsVotingEnabled = data.isBitsVotingEnabled;
trigger.parameters.isChannelPointsVotingEnabled = data.isChannelPointsVotingEnabled;
trigger.parameters.startDate = data.startDate;
trigger.parameters.title = data.title;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPollProgress", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: createPredictionString
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function createPredictionString (data)
{
let outcomeString = ""
let topPredictionString = ""
let userCount = "0"
let chPoints = "0"
data.outcomes.forEach(function (outcome, index)
{
if (index > 0)
outcomeString += " - "
if (outcome.users != undefined)
userCount = outcome.users
if (outcome.totalChannelPoints != undefined)
chPoints = outcome.totalChannelPoints
outcomeString += "id:" + outcome.id + " "
outcomeString += "title:" + outcome.title + " "
outcomeString += "userCount:" + userCount + " "
outcomeString += "chPoints:" + chPoints + " "
outcomeString += "color:" + outcome.color
if (outcome.topPredictors == [])
{
outcome.topPredictors.forEach(function (name, i)
{
if (i > 0)
topPredictionString += " "
topPredictionString += name
})
}
})
return { outcome: outcomeString, preds: topPredictionString }
}
// ============================================================================
// FUNCTION: onChannelPredictionBegin
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPredictionBegin (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPredictionBegin");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.id = data.id;
trigger.parameters.lockDate = data.lockDate;
let results = createPredictionString(data)
trigger.parameters.outcomes = results.outcome
trigger.parameters.predictions = results.preds
trigger.parameters.startDate = data.startDate;
trigger.parameters.title = data.title;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPredictionBegin", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelPredictionEnd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPredictionEnd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPredictionEnd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.id = data.id;
trigger.parameters.endDate = data.endDate;
let results = createPredictionString(data)
trigger.parameters.outcomes = results.outcome
trigger.parameters.predictions = results.preds
trigger.parameters.startDate = data.startDate;
trigger.parameters.title = data.title;
trigger.parameters.winningOutcome = data.winningOutcome;
trigger.parameters.winningOutcomeId = data.winningOutcomeId;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPredictionEnd", "ERROR", err.message);
}
}// ============================================================================
// FUNCTION: onChannelPollProgress
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPredictionLock (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPredictionLock");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.id = data.id;
trigger.parameters.lockDate = data.lockDate;
let results = createPredictionString(data)
trigger.parameters.outcomes = results.outcome
trigger.parameters.predictions = results.preds
trigger.parameters.startDate = data.startDate;
trigger.parameters.title = data.title;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPredictionLock", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelPredictionProgress
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelPredictionProgress (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchPredictionProgress");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.id = data.id;
trigger.parameters.lockDate = data.lockDate;
let results = createPredictionString(data)
trigger.parameters.outcomes = results.outcome
trigger.parameters.predictions = results.preds
trigger.parameters.startDate = data.startDate;
trigger.parameters.title = data.title;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelPredictionProgress", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRaidFrom
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRaidFrom (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRaidFrom");
trigger.parameters.streamer = data.raidedBroadcasterDisplayName;
trigger.parameters.raider = data.raidingBroadcasterDisplayName;
trigger.parameters.viewers = data.viewers;
console.log("twitch.raidfrom received", data)
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRaidFrom", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRaidTo
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRaidTo (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRaidTo");
trigger.parameters.streamer = data.raidingBroadcasterDisplayName;
trigger.parameters.raiding = data.raidedBroadcasterDisplayName;
trigger.parameters.viewers = data.viewers;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRaidTo", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRedemptionAdd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRedemptionAdd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRedemptionAdd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.id = data.rewardId;
trigger.parameters.message = data.input;
trigger.parameters.cost = data.rewardCost;
trigger.parameters.rewardId = data.rewardId;
trigger.parameters.prompt = data.rewardPrompt;
trigger.parameters.title = data.rewardTitle;
trigger.parameters.status = data.status;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRedemptionAdd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRedemptionUpdate
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRedemptionUpdate (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRedemptionUpdate");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.message = data.input;
trigger.parameters.cost = data.rewardCost;
trigger.parameters.id = data.rewardId;
trigger.parameters.prompt = data.rewardPrompt;
trigger.parameters.title = data.rewardTitle;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRedemptionUpdate", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRewardAdd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRewardAdd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRewardAdd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.autoApproved = data.autoApproved;
trigger.parameters.bgColor = data.backgroundColor;
trigger.parameters.expiryDate = data.cooldownExpiryDate;
trigger.parameters.cost = data.cost;
trigger.parameters.cooldown = data.globalCooldown;
trigger.parameters.id = data.id;
trigger.parameters.enabled = data.isEnabled;
trigger.parameters.inStock = data.isInStock;
trigger.parameters.paused = data.isPaused;
trigger.parameters.maxPerStream = data.maxRedemptionsPerStream;
trigger.parameters.maxPerUserPerStream = data.maxRedemptionsPerUserPerStream;
trigger.parameters.prompt = data.prompt;
trigger.parameters.redemptionsThisStream = data.redemptionsThisStream;
trigger.parameters.title = data.title;
trigger.parameters.inputRequired = data.userInputRequired;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRewardAdd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRewardRemove
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRewardRemove (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRewardRemove");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.autoApproved = data.autoApproved;
trigger.parameters.bgColor = data.backgroundColor;
trigger.parameters.expiryDate = data.cooldownExpiryDate;
trigger.parameters.cost = data.cost;
trigger.parameters.cooldown = data.globalCooldown;
trigger.parameters.id = data.id;
trigger.parameters.enabled = data.isEnabled;
trigger.parameters.inStock = data.isInStock;
trigger.parameters.paused = data.isPaused;
trigger.parameters.maxPerStream = data.maxRedemptionsPerStream;
trigger.parameters.maxPerUserPerStream = data.maxRedemptionsPerUserPerStream;
trigger.parameters.prompt = data.prompt;
trigger.parameters.redemptionsThisStream = data.redemptionsThisStream;
trigger.parameters.title = data.title;
trigger.parameters.inputRequired = data.userInputRequired;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRewardRemove", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelRewardUpdate
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelRewardUpdate (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchRewardUpdate");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.autoApproved = data.autoApproved;
trigger.parameters.bgColor = data.backgroundColor;
trigger.parameters.expiryDate = data.cooldownExpiryDate;
trigger.parameters.cost = data.cost;
trigger.parameters.cooldown = data.globalCooldown;
trigger.parameters.id = data.id;
trigger.parameters.enabled = data.isEnabled;
trigger.parameters.inStock = data.isInStock;
trigger.parameters.paused = data.isPaused;
trigger.parameters.maxPerStream = data.maxRedemptionsPerStream;
trigger.parameters.maxPerUserPerStream = data.maxRedemptionsPerUserPerStream;
trigger.parameters.prompt = data.prompt;
trigger.parameters.redemptionsThisStream = data.redemptionsThisStream;
trigger.parameters.title = data.title;
trigger.parameters.inputRequired = data.userInputRequired;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelRewardUpdate", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelShieldModeBegin
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelShieldModeBegin (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchShieldModeBegin");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.moderator = data.moderatorDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelShieldModeBegin", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelShieldModeEnd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelShieldModeEnd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchShieldModeEnd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.moderator = data.moderatorDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelShieldModeEnd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelShoutoutCreate
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelShoutoutCreate (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchShoutoutCreate");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.cooldownDate = data.cooldownEndDate;
trigger.parameters.moderator = data.moderatorDisplayName;
trigger.parameters.targetName = data.shoutedOutBroadcasterDisplayName;
trigger.parameters.targetCooldown = data.targetCooldownEndDate;
trigger.parameters.viewerCount = data.viewerCount;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelShoutoutCreate", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelShoutoutReceive
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelShoutoutReceive (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchShoutoutReceive");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.shouterName = data.shoutingOutBroadcasterDisplayName;
trigger.parameters.viewerCount = data.viewerCount;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelShoutoutReceive", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelSubscription
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelSubscription (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchSubscription");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.isGift = data.isGift;
trigger.parameters.tier = data.tier;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelSubscription", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelSubscriptionEnd
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelSubscriptionEnd (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchSubscriptionEnd");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.isGift = data.isGift;
trigger.parameters.tier = data.tier;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelSubscriptionEnd", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelSubscriptionGift
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelSubscriptionGift (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchSubscriptionGift");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.amount = data.amount;
trigger.parameters.cumulativeAmount = data.cumulativeAmount;
trigger.parameters.isGift = data.isGift;
trigger.parameters.gifter = data.gifterDisplayName;
trigger.parameters.anon = data.isAnonymous;
trigger.parameters.tier = data.tier;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelSubscriptionGift", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelSubscriptionMessage
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelSubscriptionMessage (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchSubscriptionMessage");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.cumulativeMonths = data.cumulativeMonths;
trigger.parameters.durationMonths = data.durationMonths;
trigger.parameters.emoteOffsets = data.emoteOffsets;
trigger.parameters.message = data.messageText;
trigger.parameters.streakMonths = data.streakMonths;
trigger.parameters.tier = data.tier;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelSubscriptionMessage", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelUnban
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onChannelUnban (data)
{
try
{
let trigger = findTriggerByMessageType("trigger_TwitchUserUnBanned");
trigger.parameters.streamer = data.broadcasterDisplayName;
trigger.parameters.moderator = data.moderatorDisplayName;
trigger.parameters.user = data.userDisplayName;
sendTrigger(trigger)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelUnban", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onChannelUpdate
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
async function onChannelUpdate (data)
{
try
{
if (localConf.channelData.title != data.streamTitle)
{
let trigger = findTriggerByMessageType("trigger_TwitchTitleChanged");
trigger.parameters.title = data.streamTitle;
sendTrigger(trigger)
}
if (localConf.channelData.gameId != data.categoryId)
{
let trigger = findTriggerByMessageType("trigger_TwitchGamedChanged");
data.getGame().then((game) =>
{
let trigger = findTriggerByMessageType("trigger_TwitchGamedChanged");
trigger.parameters = {
triggerId: "twitchUpdate",
gameId: game.id,
name: game.name,
imageURL: game.boxArtUrl
}
sendTrigger(trigger)
})
}
if (localConf.channelData.id != data.broadcasterId)
{
let trigger = findTriggerByMessageType("trigger_TwitchStreamIdChanged");
trigger.parameters.id = data.broadcasterId;
sendTrigger(trigger)
}
if (localConf.channelData.language != data.streamLanguage)
{
let trigger = findTriggerByMessageType("trigger_TwitchStreamLanguageChanged");
trigger.parameters.language = data.streamLanguage;
sendTrigger(trigger)
}
if (localConf.channelData.name != data.broadcasterName)
{
let trigger = findTriggerByMessageType("trigger_TwitchStreamerNameChanged");
trigger.parameters.name = data.broadcasterName;
localConf.streamerId = data.getBroadcaster().id
sendTrigger(trigger)
}
// update our local data to the new config. Note that this callback has a different structure to
// this function call so can't just assign it.
localConf.channelData = await localConf.apiClient.channels.getChannelInfoById(localConf.streamerId)
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onChannelUpdate", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onStreamStarted
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onStreamOnline (data)
{
try
{
sendTrigger(findTriggerByMessageType("trigger_TwitchStreamStarted"))
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onStreamStarted", "ERROR", err.message);
}
}
// ============================================================================
// FUNCTION: onStreamStopped
// ============================================================================
/**
* Fires on a twitch pubsub event
* @param {object} data
*/
function onStreamOffline (data)
{
try
{
sendTrigger(findTriggerByMessageType("trigger_TwitchStreamEnded"))
}
catch (err)
{
logger.err("[EXTENSIONS]twitch.eventsub.onStreamOffline", "ERROR", err.message);
}
}
// ===========================================================================
// FUNCTION: sendTrigger
// ===========================================================================
/**
* sends out the given trigger
* @param {object} trigger
*/
function sendTrigger (trigger)
{
sr_api.sendMessage(parentLocalConfig.DataCenterSocket,
sr_api.ServerPacket(
'ChannelData',
parentServerConfig.extensionname,
sr_api.ExtensionPacket(
trigger.messagetype,
parentServerConfig.extensionname,
trigger,
parentServerConfig.channel,
''),
parentServerConfig.channel,
''
)
);
if (localConf.triggerCAllback)
localConf.triggerCAllback(trigger)
}
// ============================================================================
// FUNCTION: findTriggerByMessageType
// ============================================================================
/**
* Find a trigger by message type
* @param {string} messagetype
* @returns trigger
*/
function findTriggerByMessageType (messagetype)
{
for (let i = 0; i < localConf.tAndAs.triggers.length; i++)
{
if (localConf.tAndAs.triggers[i].messagetype.toLowerCase() == messagetype.toLowerCase())
return localConf.tAndAs.triggers[i];
}
logger.err(parentLocalConfig.SYSTEM_LOGGING_TAG + parentServerConfig.extensionname +
".findTriggerByMessageType", "failed to find action", messagetype);
}
export { startEventSub, removeSubs, init }