From a77516d672cdcf8e8b08918b381782c8c6a3e907 Mon Sep 17 00:00:00 2001 From: Lee Date: Wed, 27 Nov 2024 20:49:39 -0600 Subject: [PATCH 01/54] feat: Add Some Arg-Less Examples for $user... Variables (#2904) * feat: Add Some Arg-Less Examples for $user... - Per feature request #2903 - Add argument-less examples to both of the $userId and $userDisplayName variables. * fix: Pull user... vars from eventData - We were mandating it from the outer-most metadata, but Dennis said I had to make it look at eventData first. - That nullish coalesce in user-display-name L24 got a smile, thank you! - Dennis's fault if this breaks anything for anyone. * chore: arg-less first --------- Co-authored-by: Erik Bigler --- .../variables/builtin/user/user-display-name.ts | 16 +++++++++++----- src/backend/variables/builtin/user/user-id.ts | 16 +++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/backend/variables/builtin/user/user-display-name.ts b/src/backend/variables/builtin/user/user-display-name.ts index a96637262..21637da1d 100644 --- a/src/backend/variables/builtin/user/user-display-name.ts +++ b/src/backend/variables/builtin/user/user-display-name.ts @@ -8,18 +8,24 @@ import twitchApi from "../../../twitch-api/api"; const model : ReplaceVariable = { definition: { handle: "userDisplayName", - usage: "userDisplayName[username]", - description: "Gets the formatted display name for the given username. Searches local viewer DB first, then Twitch API.", + usage: "userDisplayName", + description: "Gets the formatted display name of the associated user (if there is one) for the given trigger.", categories: [VariableCategory.USER], - possibleDataOutput: [OutputDataType.TEXT] + possibleDataOutput: [OutputDataType.TEXT], + examples: [ + { + usage: "userDisplayName[username]", + description: "The formatted display name for the given username. Searches local viewer DB first, then Twitch API." + } + ] }, evaluator: async (trigger, username: string) => { if (username == null) { - const userDisplayName = trigger.metadata.userDisplayName ?? trigger.metadata.userDisplayName; + const userDisplayName = trigger.metadata?.eventData?.userDisplayName ?? trigger.metadata?.userDisplayName; if (userDisplayName != null) { return userDisplayName; } - username = trigger.metadata.username; + username = trigger.metadata?.eventData?.username ?? trigger.metadata?.username; if (username == null) { return "[No username available]"; } diff --git a/src/backend/variables/builtin/user/user-id.ts b/src/backend/variables/builtin/user/user-id.ts index bd8532a68..27ac80027 100644 --- a/src/backend/variables/builtin/user/user-id.ts +++ b/src/backend/variables/builtin/user/user-id.ts @@ -8,18 +8,24 @@ import twitchApi from "../../../twitch-api/api"; const model : ReplaceVariable = { definition: { handle: "userId", - usage: "userId[username]", - description: "Gets the user ID for the given username. Searches local viewer DB first, then Twitch API.", + usage: "userId", + description: "Gets the user ID of the associated user (if there is one) for the given trigger.", categories: [VariableCategory.USER], - possibleDataOutput: [OutputDataType.TEXT] + possibleDataOutput: [OutputDataType.TEXT], + examples: [ + { + usage: "userId[username]", + description: "The user ID for the given username. Searches local viewer DB first, then Twitch API." + } + ] }, evaluator: async (trigger, username: string) => { if (username == null) { - const userId = trigger.metadata.userid ?? trigger.metadata.userId; + const userId = trigger.metadata?.eventData?.userid ?? trigger.metadata?.userId; if (userId != null) { return userId; } - username = trigger.metadata.username; + username = trigger.metadata?.eventData?.username ?? trigger.metadata?.username; if (username == null) { return "[No username available]"; } From 1b28f24cab050df8e6d496e3a14bed9c50652d50 Mon Sep 17 00:00:00 2001 From: Erik Bigler Date: Wed, 27 Nov 2024 21:35:41 -0600 Subject: [PATCH 02/54] fix: add names to raw ui extension functions if they don't have one (#2906) * add names to raw ui extension functions if they dont have one * fix cant reassign const --- .../ui-extensions/ui-extension-manager.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/backend/ui-extensions/ui-extension-manager.ts b/src/backend/ui-extensions/ui-extension-manager.ts index b85eea304..665f4e8b4 100644 --- a/src/backend/ui-extensions/ui-extension-manager.ts +++ b/src/backend/ui-extensions/ui-extension-manager.ts @@ -37,33 +37,42 @@ class UIExtensionManager { template: page.template, fullPage: page.fullPage, disableScroll: page.disableScroll, - controllerRaw: page.controller?.toString() + controllerRaw: this.prepareFunc(page.controller, "pageCtrl") })), providers: extension.providers ? { factories: extension.providers.factories?.map(factory => ({ name: factory.name, - functionRaw: factory.function?.toString() + functionRaw: this.prepareFunc(factory.function, "factoryFunc") })), components: extension.providers.components?.map(component => ({ name: component.name, bindings: component.bindings, template: component.template, transclude: component.transclude, - controllerRaw: component.controller?.toString() + controllerRaw: this.prepareFunc(component.controller, "componentCtrl") })), directives: extension.providers.directives?.map(directive => ({ name: directive.name, - functionRaw: directive.function?.toString() + functionRaw: this.prepareFunc(directive.function, "directiveCtrl") })), filters: extension.providers.filters?.map(filter => ({ name: filter.name, - functionRaw: filter.function?.toString() + functionRaw: this.prepareFunc(filter.function, "filterFunc") })) } : undefined }; } + + // eslint-disable-next-line @typescript-eslint/ban-types + private prepareFunc(func: Function | undefined, name: string) { + let rawFunc = func?.toString() ?? "() => {}"; + if (rawFunc.startsWith("function(")) { + rawFunc = rawFunc.replace("function(", `function ${name}(`); + } + return rawFunc; + } } const manager = new UIExtensionManager(); From 1d516f50ccb6f29db678a762bd99b3f69c4aa046 Mon Sep 17 00:00:00 2001 From: CKY Date: Thu, 28 Nov 2024 08:04:10 -0700 Subject: [PATCH 03/54] feat: built in variable api (#2899) * feat: built in variable api * requested changes --------- Co-authored-by: Erik Bigler --- src/server/api/v1/controllers/variableApiController.js | 10 ++++++++++ src/server/api/v1/v1Router.js | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 src/server/api/v1/controllers/variableApiController.js diff --git a/src/server/api/v1/controllers/variableApiController.js b/src/server/api/v1/controllers/variableApiController.js new file mode 100644 index 000000000..102e4926b --- /dev/null +++ b/src/server/api/v1/controllers/variableApiController.js @@ -0,0 +1,10 @@ +"use strict"; + +const manager = require("../../../../backend//variables/replace-variable-manager"); + +exports.getReplaceVariables = function(req, res) { + const sortedVariables = [...manager.getReplaceVariables()] + .sort((a, b) => a.definition.handle.localeCompare(b.definition.handle)); + + res.json(sortedVariables); +}; \ No newline at end of file diff --git a/src/server/api/v1/v1Router.js b/src/server/api/v1/v1Router.js index 2cb8b8236..465162430 100644 --- a/src/server/api/v1/v1Router.js +++ b/src/server/api/v1/v1Router.js @@ -72,6 +72,11 @@ router .get(customVariables.getCustomVariable) .post(customVariables.setCustomVariable); +// builtin variables +const variableManager = require("./controllers/variableApiController"); + +router.route("/variables").get(variableManager.getReplaceVariables); + // viewers const viewers = require("./controllers/viewersApiController"); From a003614b6c0cac9d2680c3bf58731ff61c3ba039 Mon Sep 17 00:00:00 2001 From: Erik Bigler Date: Thu, 28 Nov 2024 11:17:13 -0600 Subject: [PATCH 04/54] feat: ability for eval js variable/effect to send strings through expressionish #2910 --- .../handlers/js-sandbox/sandbox-eval.ts | 20 +++++++++++++++---- src/backend/effects/builtin/eval-js.ts | 2 +- .../variables/builtin/utility/eval-js.ts | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/backend/common/handlers/js-sandbox/sandbox-eval.ts b/src/backend/common/handlers/js-sandbox/sandbox-eval.ts index 4dec7d393..5a8d5c733 100644 --- a/src/backend/common/handlers/js-sandbox/sandbox-eval.ts +++ b/src/backend/common/handlers/js-sandbox/sandbox-eval.ts @@ -9,16 +9,26 @@ const htmlPath = join(__dirname, './sandbox.html'); const { getCustomVariable } = require('../../custom-variable-manager'); +import replaceVariableManager from '../../../variables/replace-variable-manager'; + const charList = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; -const handlers = new Map unknown>(); +const handlers = new Map unknown>(); -handlers.set('getCustomVariable', (name) => { +handlers.set('getCustomVariable', (_trigger, name) => { if (name == null || typeof name !== 'string') { throw new Error('variable name must be a string'); } return getCustomVariable(name); }); +handlers.set('evaluateVariableExpression', (trigger, expressionString) => { + if (expressionString == null || typeof expressionString !== 'string') { + throw new Error('variable expression must be a string'); + } + + return replaceVariableManager.evaluateText(expressionString, trigger?.metadata, trigger); +}); + interface Sandbox { finished: boolean, tunnel: Electron.MessagePortMain, @@ -29,7 +39,9 @@ interface Sandbox { reject?: (...args: unknown[]) => void } -export const evalSandboxedJs = async (code: string, args: unknown[], metadata: Trigger["metadata"]) => { +export const evalSandboxedJs = async (code: string, args: unknown[], trigger: Trigger) => { + const metadata = trigger.metadata; + if (code instanceof String) { code = `${code}`; } @@ -119,7 +131,7 @@ export const evalSandboxedJs = async (code: string, args: unknown[], metadata: T } else if (handlers.has(method)) { try { - const result = await handlers.get(method)(...parameters); + const result = await handlers.get(method)(trigger, ...parameters); if (sandbox.finished) { return; } diff --git a/src/backend/effects/builtin/eval-js.ts b/src/backend/effects/builtin/eval-js.ts index 5cd987166..8954e7f50 100644 --- a/src/backend/effects/builtin/eval-js.ts +++ b/src/backend/effects/builtin/eval-js.ts @@ -87,7 +87,7 @@ const model: EffectType<{ }, onTriggerEvent: async ({ effect, trigger }) => { try { - const result = await evalSandboxedJs(effect.code, effect.parameters ?? [], trigger.metadata); + const result = await evalSandboxedJs(effect.code, effect.parameters ?? [], trigger); return { success: true, outputs: { diff --git a/src/backend/variables/builtin/utility/eval-js.ts b/src/backend/variables/builtin/utility/eval-js.ts index 4df28674f..3393b590b 100644 --- a/src/backend/variables/builtin/utility/eval-js.ts +++ b/src/backend/variables/builtin/utility/eval-js.ts @@ -27,7 +27,7 @@ const model : ReplaceVariable = { }, evaluator: async (trigger: Trigger, code: string, ...args: unknown[]) => { try { - return await evalSandboxedJs(code, args, trigger.metadata); + return await evalSandboxedJs(code, args, trigger); } catch (err) { err.javascript = code; From c5e93aea2658ca0a032132911d6a8af5ae0291e0 Mon Sep 17 00:00:00 2001 From: CKY Date: Thu, 28 Nov 2024 10:22:30 -0700 Subject: [PATCH 05/54] feat: variable examples and description changes (#2908) Co-authored-by: Erik Bigler --- .../variables/extralife-donations.ts | 2 +- .../variables/extralife-incentives.ts | 2 +- .../extralife/variables/extralife-info.ts | 2 +- .../variables/extralife-milestones.ts | 2 +- .../builtin/obs/variables/group-item-id.ts | 2 ++ .../builtin/obs/variables/group-name.ts | 2 ++ .../builtin/obs/variables/input-active.ts | 4 +++- .../obs/variables/input-audio-balance.ts | 5 +++-- .../obs/variables/input-audio-monitor-type.ts | 4 +++- .../obs/variables/input-audio-sync-offset.ts | 4 +++- .../obs/variables/input-audio-tracks.ts | 5 +++-- .../builtin/obs/variables/input-kind.ts | 4 +++- .../builtin/obs/variables/input-muted.ts | 5 +++-- .../builtin/obs/variables/input-name.ts | 4 +++- .../builtin/obs/variables/input-settings.ts | 4 +++- .../builtin/obs/variables/input-showing.ts | 4 +++- .../builtin/obs/variables/input-uuid.ts | 4 +++- .../builtin/obs/variables/input-volume-db.ts | 4 +++- .../obs/variables/input-volume-multiplier.ts | 4 +++- .../builtin/obs/variables/is-connected.ts | 4 +++- .../builtin/obs/variables/is-recording.ts | 4 +++- .../builtin/obs/variables/is-streaming.ts | 4 +++- .../builtin/obs/variables/obs-color-value.ts | 2 +- .../builtin/obs/variables/old-input-name.ts | 2 ++ .../builtin/obs/variables/profile-name.ts | 2 ++ .../obs/variables/replay-buffer-path.ts | 2 ++ .../obs/variables/scene-collection-name.ts | 4 +++- .../obs/variables/scene-item-enabled.ts | 2 ++ .../builtin/obs/variables/scene-item-id.ts | 2 ++ .../builtin/obs/variables/scene-item-name.ts | 2 ++ .../obs/variables/scene-name-variable.ts | 4 +++- .../obs/variables/transition-duration.ts | 2 ++ .../builtin/obs/variables/transition-name.ts | 2 ++ .../obs/variables/vendor-event-data.ts | 2 ++ .../obs/variables/vendor-event-type.ts | 2 ++ .../builtin/obs/variables/vendor-name.ts | 2 ++ .../variables/sloots-alert-message.js | 2 +- .../streamloots/variables/sloots-card-name.js | 2 +- .../variables/sloots-card-rarity.js | 2 +- .../streamloots/variables/sloots-giftee.js | 2 +- .../streamloots/variables/sloots-image-url.js | 2 +- .../streamloots/variables/sloots-message.js | 2 +- .../streamloots/variables/sloots-quantity.js | 2 +- .../streamloots/variables/sloots-sound-url.js | 2 +- .../variables/builtin/array/array-find.ts | 3 +-- .../variables/builtin/array/array-from.ts | 10 ++++++++++ .../variables/builtin/array/array-join.ts | 10 ++++++++++ .../variables/builtin/array/array-length.ts | 10 ++++++++++ .../builtin/array/array-random-item.ts | 10 ++++++++++ .../variables/builtin/array/array-reverse.ts | 10 ++++++++++ .../variables/builtin/array/array-shuffle.ts | 10 ++++++++++ .../variables/builtin/counter/counter.ts | 6 ++++++ .../builtin/currency/currency-rank.ts | 8 +++++++- .../variables/builtin/currency/currency.ts | 10 ++++++++-- .../builtin/currency/top-currency.ts | 6 ++++++ .../builtin/metadata/arg-array-raw.ts | 2 +- .../effect-queue-length.ts} | 2 +- .../builtin/metadata/top-metadata.ts | 6 ++++++ .../variables/builtin/misc/view-time.ts | 14 ++++++++++++-- src/backend/variables/builtin/number/math.ts | 12 +++++++++++- .../variables/builtin/number/number-ceil.ts | 6 ++++++ .../builtin/number/number-commafy.ts | 6 ++++++ .../variables/builtin/number/number-floor.ts | 10 ++++++++++ .../variables/builtin/number/number-max.ts | 6 ++++++ .../variables/builtin/number/number-min.ts | 6 ++++++ .../builtin/object/object-set-property.ts | 14 ++++++++++++++ .../variables/builtin/text/text-capitalize.ts | 6 ++++++ .../variables/builtin/text/text-concat.ts | 6 ++++++ .../builtin/text/text-decode-from-html.ts | 6 ++++++ .../builtin/text/text-decode-from-url.ts | 6 ++++++ .../builtin/text/text-encode-for-html.ts | 6 ++++++ .../builtin/text/text-encode-for-url.ts | 6 ++++++ .../{user => twitch}/account-creation-date.ts | 0 .../builtin/twitch/twitch-channel-url.ts | 19 +++++++++++++++++-- .../variables/builtin/user/chat-messages.ts | 12 +++++++++++- src/backend/variables/builtin/user/index.ts | 2 +- .../variables/builtin/user/user-exists.ts | 2 +- .../variables/builtin/user/user-is-banned.ts | 2 +- .../builtin/user/user-is-timed-out.ts | 2 +- .../builtin/utility/audio-duration.ts | 12 +++++++++++- .../builtin/utility/convert-from-json.ts | 6 ++++++ .../variables/builtin/utility/index.ts | 2 +- .../builtin/utility/video-duration.ts | 12 +++++++++++- .../directives/misc/replaceVariableMenu.js | 10 ++++++++-- .../modals/effects/add-new-effect-modal.js | 2 +- src/gui/scss/core/_effects.scss | 2 +- src/shared/variable-constants.js | 4 +++- src/types/variables.d.ts | 4 +++- 88 files changed, 373 insertions(+), 60 deletions(-) rename src/backend/variables/builtin/{utility/get-effect-queue-length.ts => metadata/effect-queue-length.ts} (95%) rename src/backend/variables/builtin/{user => twitch}/account-creation-date.ts (100%) diff --git a/src/backend/integrations/builtin/extralife/variables/extralife-donations.ts b/src/backend/integrations/builtin/extralife/variables/extralife-donations.ts index c588dc03e..c4c663329 100644 --- a/src/backend/integrations/builtin/extralife/variables/extralife-donations.ts +++ b/src/backend/integrations/builtin/extralife/variables/extralife-donations.ts @@ -33,7 +33,7 @@ const ExtraLifeDonations: ReplaceVariable = { description: "Returns top 3 donations for current signed in extra life account in JSON format." } ], - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (_, sortName: string, numResults: number, participantID: number, returnJson: boolean) => { diff --git a/src/backend/integrations/builtin/extralife/variables/extralife-incentives.ts b/src/backend/integrations/builtin/extralife/variables/extralife-incentives.ts index 20f586340..785e72fb4 100644 --- a/src/backend/integrations/builtin/extralife/variables/extralife-incentives.ts +++ b/src/backend/integrations/builtin/extralife/variables/extralife-incentives.ts @@ -29,7 +29,7 @@ const ExtraLifeIncentives: ReplaceVariable = { description: "Returns ten incentives for current logged in extra life account in JSON format." } ], - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: async (_, rewardDesc: string, numResults: number, participantID: number, returnJson: boolean) => { diff --git a/src/backend/integrations/builtin/extralife/variables/extralife-info.ts b/src/backend/integrations/builtin/extralife/variables/extralife-info.ts index 704a3995d..4db6b6108 100644 --- a/src/backend/integrations/builtin/extralife/variables/extralife-info.ts +++ b/src/backend/integrations/builtin/extralife/variables/extralife-info.ts @@ -57,7 +57,7 @@ const ExtraLifeInfo: ReplaceVariable = { description: "Get all profile data for the current logged in extra life account in JSON format." } ], - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (_, infoPath: string, participantID: number, returnJson: boolean) => { diff --git a/src/backend/integrations/builtin/extralife/variables/extralife-milestones.ts b/src/backend/integrations/builtin/extralife/variables/extralife-milestones.ts index 5df3dc066..02315434c 100644 --- a/src/backend/integrations/builtin/extralife/variables/extralife-milestones.ts +++ b/src/backend/integrations/builtin/extralife/variables/extralife-milestones.ts @@ -29,7 +29,7 @@ const ExtraLifeMilestones: ReplaceVariable = { description: "Returns three milestones in JSON format." } ], - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: async (_, milestoneGoal: string, numResults: number, participantID: number, returnJson: boolean) => { diff --git a/src/backend/integrations/builtin/obs/variables/group-item-id.ts b/src/backend/integrations/builtin/obs/variables/group-item-id.ts index 5b4075ab9..6903fd491 100644 --- a/src/backend/integrations/builtin/obs/variables/group-item-id.ts +++ b/src/backend/integrations/builtin/obs/variables/group-item-id.ts @@ -1,6 +1,7 @@ import { TriggerType } from "../../../../common/EffectType"; import { ReplaceVariable } from "../../../../../types/variables"; import { OBS_EVENT_SOURCE_ID, OBS_SCENE_ITEM_ENABLE_STATE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -14,6 +15,7 @@ export const GroupItemIdVariable: ReplaceVariable = { description: "The group-unique numeric ID of the item in OBS that triggered the event, or -1 when the item is not grouped.", possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/group-name.ts b/src/backend/integrations/builtin/obs/variables/group-name.ts index 40d8ba025..3758b3da2 100644 --- a/src/backend/integrations/builtin/obs/variables/group-name.ts +++ b/src/backend/integrations/builtin/obs/variables/group-name.ts @@ -1,6 +1,7 @@ import { TriggerType } from "../../../../common/EffectType"; import { ReplaceVariable } from "../../../../../types/variables"; import { OBS_EVENT_SOURCE_ID, OBS_SCENE_ITEM_ENABLE_STATE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -14,6 +15,7 @@ export const GroupNameVariable: ReplaceVariable = { description: "The name of the OBS group containing the item that triggered the event, or 'Unknown' if the element isn't grouped.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/input-active.ts b/src/backend/integrations/builtin/obs/variables/input-active.ts index 36471fac5..0cbde6ba7 100644 --- a/src/backend/integrations/builtin/obs/variables/input-active.ts +++ b/src/backend/integrations/builtin/obs/variables/input-active.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_ACTIVE_STATE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputActiveVariable: ReplaceVariable = { definition: { handle: "obsInputActive", description: "Returns `true` if the OBS input is active or `false` if it is not.", - possibleDataOutput: ["bool"] + possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputActive = trigger.metadata?.eventData?.inputActive; diff --git a/src/backend/integrations/builtin/obs/variables/input-audio-balance.ts b/src/backend/integrations/builtin/obs/variables/input-audio-balance.ts index dce56b82a..74f84bdc6 100644 --- a/src/backend/integrations/builtin/obs/variables/input-audio-balance.ts +++ b/src/backend/integrations/builtin/obs/variables/input-audio-balance.ts @@ -4,7 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_AUDIO_BALANCE_CHANGED_EVENT_ID } from "../constants"; - +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ `${OBS_EVENT_SOURCE_ID}:${OBS_INPUT_AUDIO_BALANCE_CHANGED_EVENT_ID}` @@ -15,7 +15,8 @@ export const InputAudioBalanceVariable: ReplaceVariable = { definition: { handle: "obsInputAudioBalance", description: "Returns the audio balance value of the OBS input.", - possibleDataOutput: ["number"] + possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputAudioBalance = trigger.metadata?.eventData?.inputAudioBalance; diff --git a/src/backend/integrations/builtin/obs/variables/input-audio-monitor-type.ts b/src/backend/integrations/builtin/obs/variables/input-audio-monitor-type.ts index 1d940ed73..2e7397328 100644 --- a/src/backend/integrations/builtin/obs/variables/input-audio-monitor-type.ts +++ b/src/backend/integrations/builtin/obs/variables/input-audio-monitor-type.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_AUDIO_MONITOR_TYPE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputAudioMonitorTypeVariable: ReplaceVariable = { definition: { handle: "obsInputMonitorType", description: "Returns the audio monitor type of the OBS input. Values are `None`, `Monitor Only`, or `Monitor and Output`.", - possibleDataOutput: ["text"] + possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const monitorType = trigger.metadata?.eventData?.monitorType; diff --git a/src/backend/integrations/builtin/obs/variables/input-audio-sync-offset.ts b/src/backend/integrations/builtin/obs/variables/input-audio-sync-offset.ts index b672cc274..7831fd373 100644 --- a/src/backend/integrations/builtin/obs/variables/input-audio-sync-offset.ts +++ b/src/backend/integrations/builtin/obs/variables/input-audio-sync-offset.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_AUDIO_BALANCE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputAudioSyncOffsetVariable: ReplaceVariable = { definition: { handle: "obsInputAudioSyncOffset", description: "Returns the audio sync offset (in milliseconds) of the OBS input.", - possibleDataOutput: ["number"] + possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputAudioSyncOffset = trigger.metadata?.eventData?.inputAudioSyncOffset; diff --git a/src/backend/integrations/builtin/obs/variables/input-audio-tracks.ts b/src/backend/integrations/builtin/obs/variables/input-audio-tracks.ts index d68685774..510736861 100644 --- a/src/backend/integrations/builtin/obs/variables/input-audio-tracks.ts +++ b/src/backend/integrations/builtin/obs/variables/input-audio-tracks.ts @@ -4,7 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_AUDIO_TRACKS_CHANGED_EVENT_ID } from "../constants"; - +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ `${OBS_EVENT_SOURCE_ID}:${OBS_INPUT_AUDIO_TRACKS_CHANGED_EVENT_ID}` @@ -15,7 +15,8 @@ export const InputAudioTracksVariable: ReplaceVariable = { definition: { handle: "obsInputAudioTracks", description: "Returns the raw OBS audio tracks object of the OBS input.", - possibleDataOutput: ["object"] + possibleDataOutput: ["object"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputAudioTracks = trigger.metadata?.eventData?.inputAudioTracks; diff --git a/src/backend/integrations/builtin/obs/variables/input-kind.ts b/src/backend/integrations/builtin/obs/variables/input-kind.ts index 75a447cfa..ed2d09e3b 100644 --- a/src/backend/integrations/builtin/obs/variables/input-kind.ts +++ b/src/backend/integrations/builtin/obs/variables/input-kind.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_CREATED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputKindVariable: ReplaceVariable = { definition: { handle: "obsInputKind", description: "Returns the OBS internal name of the kind of OBS input.", - possibleDataOutput: ["text"] + possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputKind = trigger.metadata?.eventData?.inputKind; diff --git a/src/backend/integrations/builtin/obs/variables/input-muted.ts b/src/backend/integrations/builtin/obs/variables/input-muted.ts index 9916ad382..25ad80494 100644 --- a/src/backend/integrations/builtin/obs/variables/input-muted.ts +++ b/src/backend/integrations/builtin/obs/variables/input-muted.ts @@ -4,7 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_MUTE_STATE_CHANGED_EVENT_ID } from "../constants"; - +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ `${OBS_EVENT_SOURCE_ID}:${OBS_INPUT_MUTE_STATE_CHANGED_EVENT_ID}` @@ -15,7 +15,8 @@ export const InputMutedVariable: ReplaceVariable = { definition: { handle: "obsInputMuted", description: "Returns `true` if the OBS input is muted or `false` if it is not.", - possibleDataOutput: ["bool"] + possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputMuted = trigger.metadata?.eventData?.inputMuted; diff --git a/src/backend/integrations/builtin/obs/variables/input-name.ts b/src/backend/integrations/builtin/obs/variables/input-name.ts index d1fc71046..2a5c70412 100644 --- a/src/backend/integrations/builtin/obs/variables/input-name.ts +++ b/src/backend/integrations/builtin/obs/variables/input-name.ts @@ -15,6 +15,7 @@ import { OBS_INPUT_AUDIO_MONITOR_TYPE_CHANGED_EVENT_ID, OBS_INPUT_AUDIO_TRACKS_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -37,7 +38,8 @@ export const InputNameVariable: ReplaceVariable = { definition: { handle: "obsInputName", description: "Returns the name of the OBS input.", - possibleDataOutput: ["text"] + possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputName = trigger.metadata?.eventData?.inputName; diff --git a/src/backend/integrations/builtin/obs/variables/input-settings.ts b/src/backend/integrations/builtin/obs/variables/input-settings.ts index 735ec45ec..c1b9452c1 100644 --- a/src/backend/integrations/builtin/obs/variables/input-settings.ts +++ b/src/backend/integrations/builtin/obs/variables/input-settings.ts @@ -5,6 +5,7 @@ import { OBS_INPUT_CREATED_EVENT_ID, OBS_INPUT_SETTINGS_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -17,7 +18,8 @@ export const InputSettingsVariable: ReplaceVariable = { definition: { handle: "obsInputSettings", description: "Returns the raw OBS settings object of the OBS input.", - possibleDataOutput: ["object"] + possibleDataOutput: ["object"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputSettings = trigger.metadata?.eventData?.inputSettings; diff --git a/src/backend/integrations/builtin/obs/variables/input-showing.ts b/src/backend/integrations/builtin/obs/variables/input-showing.ts index 49ed32691..900d10f40 100644 --- a/src/backend/integrations/builtin/obs/variables/input-showing.ts +++ b/src/backend/integrations/builtin/obs/variables/input-showing.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_SHOW_STATE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputShowingVariable: ReplaceVariable = { definition: { handle: "obsInputShowing", description: "Returns `true` if the OBS input is currently showing or `false` if it is not.", - possibleDataOutput: ["bool"] + possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputShowing = trigger.metadata?.eventData?.inputShowing; diff --git a/src/backend/integrations/builtin/obs/variables/input-uuid.ts b/src/backend/integrations/builtin/obs/variables/input-uuid.ts index 6459df4a0..de6b234e5 100644 --- a/src/backend/integrations/builtin/obs/variables/input-uuid.ts +++ b/src/backend/integrations/builtin/obs/variables/input-uuid.ts @@ -15,6 +15,7 @@ import { OBS_INPUT_AUDIO_MONITOR_TYPE_CHANGED_EVENT_ID, OBS_INPUT_AUDIO_TRACKS_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -37,7 +38,8 @@ export const InputUuidVariable: ReplaceVariable = { definition: { handle: "obsInputUuid", description: "Returns the UUID of the OBS input.", - possibleDataOutput: ["text"] + possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputUuid = trigger.metadata?.eventData?.inputUuid; diff --git a/src/backend/integrations/builtin/obs/variables/input-volume-db.ts b/src/backend/integrations/builtin/obs/variables/input-volume-db.ts index dd5661e4d..c8d249701 100644 --- a/src/backend/integrations/builtin/obs/variables/input-volume-db.ts +++ b/src/backend/integrations/builtin/obs/variables/input-volume-db.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_VOLUME_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputVolumeDbVariable: ReplaceVariable = { definition: { handle: "obsInputVolumeDb", description: "Returns the volume level in dB of the OBS input.", - possibleDataOutput: ["number"] + possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputVolumeDb = trigger.metadata?.eventData?.inputVolumeDb; diff --git a/src/backend/integrations/builtin/obs/variables/input-volume-multiplier.ts b/src/backend/integrations/builtin/obs/variables/input-volume-multiplier.ts index 3de5ce1dd..9a9828edf 100644 --- a/src/backend/integrations/builtin/obs/variables/input-volume-multiplier.ts +++ b/src/backend/integrations/builtin/obs/variables/input-volume-multiplier.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_VOLUME_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,7 +16,8 @@ export const InputVolumeMultiplierVariable: ReplaceVariable = { definition: { handle: "obsInputVolumeMultiplier", description: "Returns the volume level multiplier of the OBS input.", - possibleDataOutput: ["number"] + possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const inputVolumeMultiplier = trigger.metadata?.eventData?.inputVolumeMultiplier; diff --git a/src/backend/integrations/builtin/obs/variables/is-connected.ts b/src/backend/integrations/builtin/obs/variables/is-connected.ts index 571ce8d59..bd08451a6 100644 --- a/src/backend/integrations/builtin/obs/variables/is-connected.ts +++ b/src/backend/integrations/builtin/obs/variables/is-connected.ts @@ -1,11 +1,13 @@ import { ReplaceVariable } from "../../../../../types/variables"; import { isConnected } from "../obs-remote"; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const IsConnectedVariable: ReplaceVariable = { definition: { handle: "obsIsConnected", description: "Returns 'true' if OBS is currently connected or 'false' if it is not.", - possibleDataOutput: ["bool"] + possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async () => { return isConnected() ?? false; diff --git a/src/backend/integrations/builtin/obs/variables/is-recording.ts b/src/backend/integrations/builtin/obs/variables/is-recording.ts index 476cd5208..478b4fca7 100644 --- a/src/backend/integrations/builtin/obs/variables/is-recording.ts +++ b/src/backend/integrations/builtin/obs/variables/is-recording.ts @@ -1,12 +1,14 @@ import { ReplaceVariable } from "../../../../../types/variables"; import { isRecording } from "../obs-remote"; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const IsRecordingVariable: ReplaceVariable = { definition: { handle: "obsIsRecording", description: "Returns 'true' if OBS is currently recording or 'false' if it is not.", - possibleDataOutput: ["bool"] + possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async () => { const recordState = await isRecording(); diff --git a/src/backend/integrations/builtin/obs/variables/is-streaming.ts b/src/backend/integrations/builtin/obs/variables/is-streaming.ts index 7c67a625b..9b1455567 100644 --- a/src/backend/integrations/builtin/obs/variables/is-streaming.ts +++ b/src/backend/integrations/builtin/obs/variables/is-streaming.ts @@ -1,12 +1,14 @@ import { ReplaceVariable } from "../../../../../types/variables"; import { isStreaming } from "../obs-remote"; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const IsStreamingVariable: ReplaceVariable = { definition: { handle: "obsIsStreaming", description: "Returns 'true' if OBS is currently streaming or 'false' if it is not.", - possibleDataOutput: ["bool"] + possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async () => { const streamState = await isStreaming(); diff --git a/src/backend/integrations/builtin/obs/variables/obs-color-value.ts b/src/backend/integrations/builtin/obs/variables/obs-color-value.ts index 4680fa49c..669f10ba0 100644 --- a/src/backend/integrations/builtin/obs/variables/obs-color-value.ts +++ b/src/backend/integrations/builtin/obs/variables/obs-color-value.ts @@ -6,7 +6,7 @@ export const ColorValueVariable: ReplaceVariable = { definition: { handle: "obsColorValue", description: "Returns an OBS color value based on either a hex color code (e.g. #0066FF) or an HTML color name.", - categories: [VariableCategory.ADVANCED], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], possibleDataOutput: ["number"] }, evaluator: (_, ...args: string[]) => { diff --git a/src/backend/integrations/builtin/obs/variables/old-input-name.ts b/src/backend/integrations/builtin/obs/variables/old-input-name.ts index 32bc93571..4c724a4da 100644 --- a/src/backend/integrations/builtin/obs/variables/old-input-name.ts +++ b/src/backend/integrations/builtin/obs/variables/old-input-name.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_INPUT_NAME_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,6 +16,7 @@ export const OldInputNameVariable: ReplaceVariable = { definition: { handle: "obsOldInputName", description: "Returns the previous name of the OBS input.", + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], possibleDataOutput: ["text"] }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/profile-name.ts b/src/backend/integrations/builtin/obs/variables/profile-name.ts index b2ffc7b2b..406dfb076 100644 --- a/src/backend/integrations/builtin/obs/variables/profile-name.ts +++ b/src/backend/integrations/builtin/obs/variables/profile-name.ts @@ -4,6 +4,7 @@ import { OBS_CURRENT_PROFILE_CHANGED_EVENT_ID, OBS_EVENT_SOURCE_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -16,6 +17,7 @@ export const ProfileNameVariable: ReplaceVariable = { description: "The name of the OBS profile that triggered the event.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/replay-buffer-path.ts b/src/backend/integrations/builtin/obs/variables/replay-buffer-path.ts index 6a22e4495..0bfc06080 100644 --- a/src/backend/integrations/builtin/obs/variables/replay-buffer-path.ts +++ b/src/backend/integrations/builtin/obs/variables/replay-buffer-path.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_REPLAY_BUFFER_SAVED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -16,6 +17,7 @@ export const ReplayBufferPathVariable: ReplaceVariable = { description: "The path of the replay buffer file that OBS saved.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/scene-collection-name.ts b/src/backend/integrations/builtin/obs/variables/scene-collection-name.ts index 0d740f2ed..774ffa705 100644 --- a/src/backend/integrations/builtin/obs/variables/scene-collection-name.ts +++ b/src/backend/integrations/builtin/obs/variables/scene-collection-name.ts @@ -1,12 +1,14 @@ import { ReplaceVariable } from "../../../../../types/variables"; import { getCurrentSceneCollectionName } from "../obs-remote"; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const SceneCollectionNameVariable: ReplaceVariable = { definition: { handle: "obsSceneCollectionName", description: "The name of the OBS scene collection that triggered the event, or the name of the current OBS scene collection if there is no event. If OBS isn't running, it returns 'Unknown'.", - possibleDataOutput: ["text"] + possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: async (trigger) => { const currentSceneCollectionName = trigger.metadata?.eventData?.sceneCollectionName ?? await getCurrentSceneCollectionName(); diff --git a/src/backend/integrations/builtin/obs/variables/scene-item-enabled.ts b/src/backend/integrations/builtin/obs/variables/scene-item-enabled.ts index 8efc4fdf4..560a7499d 100644 --- a/src/backend/integrations/builtin/obs/variables/scene-item-enabled.ts +++ b/src/backend/integrations/builtin/obs/variables/scene-item-enabled.ts @@ -1,6 +1,7 @@ import { TriggerType } from "../../../../common/EffectType"; import { ReplaceVariable } from "../../../../../types/variables"; import { OBS_EVENT_SOURCE_ID, OBS_SCENE_ITEM_ENABLE_STATE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -13,6 +14,7 @@ export const SceneItemEnabledVariable: ReplaceVariable = { description: "Returns `true` if the OBS scene item that triggered the event is enabled, or `false` otherwise.", possibleDataOutput: ["bool"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/scene-item-id.ts b/src/backend/integrations/builtin/obs/variables/scene-item-id.ts index f2594f4ef..c5fdfe8a1 100644 --- a/src/backend/integrations/builtin/obs/variables/scene-item-id.ts +++ b/src/backend/integrations/builtin/obs/variables/scene-item-id.ts @@ -1,6 +1,7 @@ import { TriggerType } from "../../../../common/EffectType"; import { ReplaceVariable } from "../../../../../types/variables"; import { OBS_EVENT_SOURCE_ID, OBS_SCENE_ITEM_ENABLE_STATE_CHANGED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -13,6 +14,7 @@ export const SceneItemIdVariable: ReplaceVariable = { description: "The numeric ID of the OBS scene item that triggered the event.", possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/scene-item-name.ts b/src/backend/integrations/builtin/obs/variables/scene-item-name.ts index 1e23e6658..4aa682f52 100644 --- a/src/backend/integrations/builtin/obs/variables/scene-item-name.ts +++ b/src/backend/integrations/builtin/obs/variables/scene-item-name.ts @@ -2,6 +2,7 @@ import { TriggerType } from "../../../../common/EffectType"; import { ReplaceVariable } from "../../../../../types/variables"; import { OBS_EVENT_SOURCE_ID, OBS_SCENE_ITEM_ENABLE_STATE_CHANGED_EVENT_ID } from "../constants"; import { getGroupItem, getSceneItem } from "../obs-remote"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -15,6 +16,7 @@ export const SceneItemNameVariable: ReplaceVariable = { description: "The name of the OBS scene item that triggered the event.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/scene-name-variable.ts b/src/backend/integrations/builtin/obs/variables/scene-name-variable.ts index 03a992382..94fbc97e3 100644 --- a/src/backend/integrations/builtin/obs/variables/scene-name-variable.ts +++ b/src/backend/integrations/builtin/obs/variables/scene-name-variable.ts @@ -1,12 +1,14 @@ import { ReplaceVariable } from "../../../../../types/variables"; import { getCurrentSceneName } from "../obs-remote"; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const SceneNameVariable: ReplaceVariable = { definition: { handle: "obsSceneName", description: "The name of the OBS scene that triggered the event, or the current OBS Scene if there is no event. If OBS isn't running, it returns 'Unknown'.", - possibleDataOutput: ["text"] + possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS] }, evaluator: (trigger) => { const currentSceneName = trigger.metadata?.eventData?.sceneName ?? getCurrentSceneName(); diff --git a/src/backend/integrations/builtin/obs/variables/transition-duration.ts b/src/backend/integrations/builtin/obs/variables/transition-duration.ts index 540ec8084..18d86d4cf 100644 --- a/src/backend/integrations/builtin/obs/variables/transition-duration.ts +++ b/src/backend/integrations/builtin/obs/variables/transition-duration.ts @@ -4,6 +4,7 @@ import { OBS_CURRENT_SCENE_TRANSITION_DURATION_CHANGED_EVENT_ID, OBS_EVENT_SOURCE_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -16,6 +17,7 @@ export const TransitionDurationVariable: ReplaceVariable = { description: "The new duration (in milliseconds) of the OBS transition that was updated.", possibleDataOutput: ["number"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/transition-name.ts b/src/backend/integrations/builtin/obs/variables/transition-name.ts index 31c7cd325..fdd2f39c2 100644 --- a/src/backend/integrations/builtin/obs/variables/transition-name.ts +++ b/src/backend/integrations/builtin/obs/variables/transition-name.ts @@ -6,6 +6,7 @@ import { OBS_SCENE_TRANSITION_ENDED_EVENT_ID, OBS_SCENE_TRANSITION_STARTED_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -20,6 +21,7 @@ export const TransitionNameVariable: ReplaceVariable = { description: "The name of the OBS transition that triggered the event.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/vendor-event-data.ts b/src/backend/integrations/builtin/obs/variables/vendor-event-data.ts index ae85cf6ad..c331c1740 100644 --- a/src/backend/integrations/builtin/obs/variables/vendor-event-data.ts +++ b/src/backend/integrations/builtin/obs/variables/vendor-event-data.ts @@ -9,6 +9,7 @@ const triggers = {}; triggers[TriggerType.EVENT] = [ `${OBS_EVENT_SOURCE_ID}:${OBS_VENDOR_EVENT_EVENT_ID}` ]; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const VendorEventDataVariable: ReplaceVariable = { definition: { @@ -16,6 +17,7 @@ export const VendorEventDataVariable: ReplaceVariable = { description: "The vendor-specified raw JSON data from the OBS vendor event.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/vendor-event-type.ts b/src/backend/integrations/builtin/obs/variables/vendor-event-type.ts index f4b136906..249c37985 100644 --- a/src/backend/integrations/builtin/obs/variables/vendor-event-type.ts +++ b/src/backend/integrations/builtin/obs/variables/vendor-event-type.ts @@ -9,6 +9,7 @@ const triggers = {}; triggers[TriggerType.EVENT] = [ `${OBS_EVENT_SOURCE_ID}:${OBS_VENDOR_EVENT_EVENT_ID}` ]; +import { VariableCategory } from "../../../../../shared/variable-constants"; export const VendorEventTypeVariable: ReplaceVariable = { definition: { @@ -16,6 +17,7 @@ export const VendorEventTypeVariable: ReplaceVariable = { description: "The vendor-specified type of event that triggered the OBS vendor event.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/obs/variables/vendor-name.ts b/src/backend/integrations/builtin/obs/variables/vendor-name.ts index 5bdbf95c4..220e51bc4 100644 --- a/src/backend/integrations/builtin/obs/variables/vendor-name.ts +++ b/src/backend/integrations/builtin/obs/variables/vendor-name.ts @@ -4,6 +4,7 @@ import { OBS_EVENT_SOURCE_ID, OBS_VENDOR_EVENT_EVENT_ID } from "../constants"; +import { VariableCategory } from "../../../../../shared/variable-constants"; const triggers = {}; triggers[TriggerType.EVENT] = [ @@ -16,6 +17,7 @@ export const VendorNameVariable: ReplaceVariable = { description: "The name of the vendor that triggered the OBS vendor event.", possibleDataOutput: ["text"], + categories: [VariableCategory.ADVANCED, VariableCategory.INTEGRATION, VariableCategory.OBS], triggers: triggers }, evaluator: async (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-alert-message.js b/src/backend/integrations/builtin/streamloots/variables/sloots-alert-message.js index dd96f048e..c793e737f 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-alert-message.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-alert-message.js @@ -12,7 +12,7 @@ const model = { handle: "slootsAlertMessage", description: "The alert message included with a StreamLoots Chest/Card.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-card-name.js b/src/backend/integrations/builtin/streamloots/variables/sloots-card-name.js index 0638dc875..346b07676 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-card-name.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-card-name.js @@ -12,7 +12,7 @@ const model = { handle: "slootsCardName", description: "The name of a StreamLoots Card.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-card-rarity.js b/src/backend/integrations/builtin/streamloots/variables/sloots-card-rarity.js index 933b8c8c8..657cbfef4 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-card-rarity.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-card-rarity.js @@ -12,7 +12,7 @@ const model = { handle: "slootsCardRarity", description: "The rarity of a StreamLoots Card.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-giftee.js b/src/backend/integrations/builtin/streamloots/variables/sloots-giftee.js index 5fe5f6bb1..02c8b3096 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-giftee.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-giftee.js @@ -12,7 +12,7 @@ const model = { handle: "slootsGiftee", description: "The person who was gifted StreamLoots Chests.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-image-url.js b/src/backend/integrations/builtin/streamloots/variables/sloots-image-url.js index 345520ebc..69cf8a5e6 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-image-url.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-image-url.js @@ -12,7 +12,7 @@ const model = { handle: "slootsImageUrl", description: "The image url for the StreamLoots Chest/Card", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-message.js b/src/backend/integrations/builtin/streamloots/variables/sloots-message.js index 5bad8cddc..9652314df 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-message.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-message.js @@ -12,7 +12,7 @@ const model = { handle: "slootsMessage", description: "The users message included with a StreamLoots Chest/Card.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-quantity.js b/src/backend/integrations/builtin/streamloots/variables/sloots-quantity.js index ae26a577b..780f8927f 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-quantity.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-quantity.js @@ -12,7 +12,7 @@ const model = { handle: "slootsChestQuantity", description: "The number of purchased StreamLoots Chests.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.NUMBER] }, evaluator: (trigger) => { diff --git a/src/backend/integrations/builtin/streamloots/variables/sloots-sound-url.js b/src/backend/integrations/builtin/streamloots/variables/sloots-sound-url.js index 14962e414..4c6e03af7 100644 --- a/src/backend/integrations/builtin/streamloots/variables/sloots-sound-url.js +++ b/src/backend/integrations/builtin/streamloots/variables/sloots-sound-url.js @@ -12,7 +12,7 @@ const model = { handle: "slootsSoundUrl", description: "The sound url for the StreamLoots Chest/Card.", triggers: triggers, - categories: [VariableCategory.COMMON, VariableCategory.TRIGGER], + categories: [VariableCategory.COMMON, VariableCategory.INTEGRATION], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger) => { diff --git a/src/backend/variables/builtin/array/array-find.ts b/src/backend/variables/builtin/array/array-find.ts index 9d6933924..911f86242 100644 --- a/src/backend/variables/builtin/array/array-find.ts +++ b/src/backend/variables/builtin/array/array-find.ts @@ -31,8 +31,7 @@ const model : ReplaceVariable = { } ], categories: [VariableCategory.ADVANCED], - possibleDataOutput: [OutputDataType.TEXT, OutputDataType.NUMBER], - hidden: true + possibleDataOutput: [OutputDataType.TEXT, OutputDataType.NUMBER] }, evaluator: ( diff --git a/src/backend/variables/builtin/array/array-from.ts b/src/backend/variables/builtin/array/array-from.ts index 2348eba82..7dfa8157b 100644 --- a/src/backend/variables/builtin/array/array-from.ts +++ b/src/backend/variables/builtin/array/array-from.ts @@ -6,6 +6,16 @@ const model : ReplaceVariable = { handle: "arrayFrom", usage: "arrayFrom[value, value, ...]", description: "Returns a raw array containing the listed values", + examples: [ + { + usage: "arrayFrom[1, 2, 3]", + description: "Returns [1, 2, 3]." + }, + { + usage: `arrayFrom["a", "b", "c"]`, + description: `Returns ["a", "b", "c"].` + } + ], categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/array/array-join.ts b/src/backend/variables/builtin/array/array-join.ts index e2ef3da60..ef1cfff95 100644 --- a/src/backend/variables/builtin/array/array-join.ts +++ b/src/backend/variables/builtin/array/array-join.ts @@ -6,6 +6,16 @@ const model : ReplaceVariable = { handle: "arrayJoin", description: "Returns a string with each array item joined together with the given separator", usage: "arrayJoin[array, separator]", + examples: [ + { + usage: `arrayJoin["[1,2,3]", ", "]`, + description: `Returns "1, 2, 3".` + }, + { + usage: `arrayJoin["["apple","banana","cherry"]", " - "]`, + description: `Returns "apple - banana - cherry".` + } + ], categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/array/array-length.ts b/src/backend/variables/builtin/array/array-length.ts index d4ba57208..e2ae3cd6a 100644 --- a/src/backend/variables/builtin/array/array-length.ts +++ b/src/backend/variables/builtin/array/array-length.ts @@ -6,6 +6,16 @@ const model : ReplaceVariable = { handle: "arrayLength", usage: "arrayLength[array]", description: "Returns the length of the input array.", + examples: [ + { + usage: `arrayLength["[1,2,3]"]`, + description: "Returns 3." + }, + { + usage: "arrayLength[rawArray]", + description: "Returns the length of the raw array." + } + ], categories: [VariableCategory.ADVANCED, VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/array/array-random-item.ts b/src/backend/variables/builtin/array/array-random-item.ts index 8c20bc95c..df8bf7f74 100644 --- a/src/backend/variables/builtin/array/array-random-item.ts +++ b/src/backend/variables/builtin/array/array-random-item.ts @@ -6,6 +6,16 @@ const model : ReplaceVariable = { handle: "arrayRandomItem", usage: "arrayRandomItem[array]", description: "Returns a random item from the given array", + examples: [ + { + usage: `arrayRandomItem["[1,2,3]"]`, + description: "Returns a random item from the array [1,2,3]." + }, + { + usage: "arrayRandomItem[rawArray]", + description: "Returns a random item from the raw array." + } + ], categories: [VariableCategory.ADVANCED, VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/array/array-reverse.ts b/src/backend/variables/builtin/array/array-reverse.ts index c2e8f1fa6..db98258c1 100644 --- a/src/backend/variables/builtin/array/array-reverse.ts +++ b/src/backend/variables/builtin/array/array-reverse.ts @@ -6,6 +6,16 @@ const model : ReplaceVariable = { handle: "arrayReverse", description: "Returns a new reversed array", usage: "arrayReverse[array]", + examples: [ + { + usage: `arrayReverse["[1,2,3]"]`, + description: "Returns [3,2,1]." + }, + { + usage: "arrayReverse[rawArray]", + description: "Returns the reversed raw array." + } + ], categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/array/array-shuffle.ts b/src/backend/variables/builtin/array/array-shuffle.ts index 45a8d0b52..dc59264ee 100644 --- a/src/backend/variables/builtin/array/array-shuffle.ts +++ b/src/backend/variables/builtin/array/array-shuffle.ts @@ -17,6 +17,16 @@ const model : ReplaceVariable = { handle: "arrayShuffle", description: "Returns a new shuffled array", usage: "arrayShuffle[array]", + examples: [ + { + usage: `arrayShuffle["[1,2,3]"]`, + description: "Returns a shuffled version of [1,2,3], e.g., [2,1,3]." + }, + { + usage: "arrayShuffle[rawArray]", + description: "Returns a shuffled version of the raw array." + } + ], categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/counter/counter.ts b/src/backend/variables/builtin/counter/counter.ts index 7f0125b71..fbdafa103 100644 --- a/src/backend/variables/builtin/counter/counter.ts +++ b/src/backend/variables/builtin/counter/counter.ts @@ -7,6 +7,12 @@ const model: ReplaceVariable = { handle: "counter", usage: "counter[name]", description: "Displays the value of the given counter.", + examples: [ + { + usage: "counter[name]", + description: "Returns the value of the specified counter" + } + ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/currency/currency-rank.ts b/src/backend/variables/builtin/currency/currency-rank.ts index 9833bca40..e60f4dbe8 100644 --- a/src/backend/variables/builtin/currency/currency-rank.ts +++ b/src/backend/variables/builtin/currency/currency-rank.ts @@ -7,8 +7,14 @@ import currencyManager from "../../../currency/currency-manager"; const model : ReplaceVariable = { definition: { handle: "currencyRank", - description: "Returns the rank of the given user based on how much of the given currency they have.", + description: "Returns the rank of the current user based on how much of the given currency they have.", usage: "currencyRank[currencyName, username]", + examples: [ + { + usage: "currencyRank[currencyName, username]", + description: "Returns the rank for the specified user in the specified currency" + } + ], categories: [VariableCategory.USER, VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/currency/currency.ts b/src/backend/variables/builtin/currency/currency.ts index 9fbf6325d..802d3a2f9 100644 --- a/src/backend/variables/builtin/currency/currency.ts +++ b/src/backend/variables/builtin/currency/currency.ts @@ -7,8 +7,14 @@ import currencyManager from "../../../currency/currency-manager"; const model : ReplaceVariable = { definition: { handle: "currency", - description: "How much of the given currency the given user has.", - usage: "currency[currencyName, username]", + description: "How much of the given currency the current user has.", + usage: "currency[currencyName]", + examples: [ + { + usage: "currency[currencyName, username]", + description: "Returns the amount of specified currency the given user fas" + } + ], categories: [VariableCategory.USER, VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/currency/top-currency.ts b/src/backend/variables/builtin/currency/top-currency.ts index d3d3aec9c..dacb1becb 100644 --- a/src/backend/variables/builtin/currency/top-currency.ts +++ b/src/backend/variables/builtin/currency/top-currency.ts @@ -10,6 +10,12 @@ const model : ReplaceVariable = { handle: "topCurrency", description: "Comma separated list of users with the most of the given currency. Defaults to top 10, you can provide a custom number as a second argument.", usage: "topCurrency[currencyName]", + examples: [ + { + usage: "topCurrency[Points, 5]", + description: "Returns comma-separated list of top 5 users with their Points amounts" + } + ], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/metadata/arg-array-raw.ts b/src/backend/variables/builtin/metadata/arg-array-raw.ts index 6e042dd6a..404b9a3a3 100644 --- a/src/backend/variables/builtin/metadata/arg-array-raw.ts +++ b/src/backend/variables/builtin/metadata/arg-array-raw.ts @@ -10,7 +10,7 @@ triggers[EffectTrigger.MANUAL] = true; const model : ReplaceVariable = { definition: { handle: "rawArgArray", - description: "(Deprecated; use $argArray) Returns the raw array of command arguments", + description: "(Deprecated: use $argArray) Returns the raw array of command arguments", triggers: triggers, categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.ARRAY] diff --git a/src/backend/variables/builtin/utility/get-effect-queue-length.ts b/src/backend/variables/builtin/metadata/effect-queue-length.ts similarity index 95% rename from src/backend/variables/builtin/utility/get-effect-queue-length.ts rename to src/backend/variables/builtin/metadata/effect-queue-length.ts index 432c8e383..68133c5e1 100644 --- a/src/backend/variables/builtin/utility/get-effect-queue-length.ts +++ b/src/backend/variables/builtin/metadata/effect-queue-length.ts @@ -12,7 +12,7 @@ const model : ReplaceVariable = { possibleDataOutput: [OutputDataType.TEXT] }, evaluator: async (_trigger, text = "") => { - const selectedQueue = effectQueueManager.getAllItems().find((queue) => queue.name === text); + const selectedQueue = effectQueueManager.getAllItems().find(queue => queue.name === text); if (selectedQueue) { return selectedQueue.length.toString(); } diff --git a/src/backend/variables/builtin/metadata/top-metadata.ts b/src/backend/variables/builtin/metadata/top-metadata.ts index 9a4f4ef7b..79dbdfca8 100644 --- a/src/backend/variables/builtin/metadata/top-metadata.ts +++ b/src/backend/variables/builtin/metadata/top-metadata.ts @@ -9,6 +9,12 @@ const model : ReplaceVariable = { handle: "topMetadata", description: "Comma separated list of users with the most of the given metadata key. Defaults to top 10, you can provide a custom number as a second argument.", usage: "topMetadata[metadataKey]", + examples: [ + { + usage: "topMetadata[deaths, 5]", + description: "Returns comma-separated list of top 5 users with their death counts" + } + ], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/misc/view-time.ts b/src/backend/variables/builtin/misc/view-time.ts index 1d8c040f0..f1213a561 100644 --- a/src/backend/variables/builtin/misc/view-time.ts +++ b/src/backend/variables/builtin/misc/view-time.ts @@ -6,10 +6,20 @@ import viewerDatabase from "../../../viewers/viewer-database"; const model : ReplaceVariable = { definition: { handle: "viewTime", - usage: "viewTime[username]", + usage: "viewTime", description: "Displays the view time (in hours) of a given viewer (leave blank to use current viewer)", + examples: [ + { + usage: "viewTime", + description: "Returns view time for current viewer" + }, + { + usage: "viewTime[username]", + description: "Returns view time for specified viewer" + } + ], categories: [VariableCategory.USER], - possibleDataOutput: [OutputDataType.NUMBER] + possibleDataOutput: [OutputDataType.NUMBER, OutputDataType.TEXT] }, evaluator: async (trigger, username: string) => { if (username == null) { diff --git a/src/backend/variables/builtin/number/math.ts b/src/backend/variables/builtin/number/math.ts index 3956853a2..b810af262 100644 --- a/src/backend/variables/builtin/number/math.ts +++ b/src/backend/variables/builtin/number/math.ts @@ -7,8 +7,18 @@ const logger = require("../../../logwrapper"); const model : ReplaceVariable = { definition: { handle: "math", - usage: "math[expression]", + usage: "math[expression]", description: 'Evaluate a math equation using math.js', + examples: [ + { + usage: "math[2 + 2]", + description: "Simple addition calculation returns 4" + }, + { + usage: "math[5 * (3 + 2)]", + description: "Complex calculation returns 25" + } + ], categories: [VariableCategory.COMMON, VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/number/number-ceil.ts b/src/backend/variables/builtin/number/number-ceil.ts index 1ce8a2ab2..47ef56513 100644 --- a/src/backend/variables/builtin/number/number-ceil.ts +++ b/src/backend/variables/builtin/number/number-ceil.ts @@ -6,6 +6,12 @@ const model : ReplaceVariable = { handle: "ceil", description: "Rounds up the given number to the nearest whole number.", usage: "ceil[num]", + examples: [ + { + usage: "ceil[3.2]", + description: "Returns 4" + } + ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/number/number-commafy.ts b/src/backend/variables/builtin/number/number-commafy.ts index ed1ba668f..82313520d 100644 --- a/src/backend/variables/builtin/number/number-commafy.ts +++ b/src/backend/variables/builtin/number/number-commafy.ts @@ -6,6 +6,12 @@ const model : ReplaceVariable = { handle: "commafy", description: "Adds the appropriate commas to a number.", usage: "commafy[number]", + examples: [ + { + usage: "commafy[1000000]", + description: "Returns \"1,000,000\"" + } + ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/number/number-floor.ts b/src/backend/variables/builtin/number/number-floor.ts index 9629e1b15..4985ccccc 100644 --- a/src/backend/variables/builtin/number/number-floor.ts +++ b/src/backend/variables/builtin/number/number-floor.ts @@ -6,6 +6,16 @@ const model : ReplaceVariable = { handle: "floor", description: "Rounds down the given number to the nearest whole number.", usage: "floor[num]", + examples: [ + { + usage: "floor[3.7]", + description: "Returns 3" + }, + { + usage: "floor[$presetListArg[Number]]", + description: "Rounds down the preset list argument value" + } + ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/number/number-max.ts b/src/backend/variables/builtin/number/number-max.ts index 1f35b1f31..cc84bedfe 100644 --- a/src/backend/variables/builtin/number/number-max.ts +++ b/src/backend/variables/builtin/number/number-max.ts @@ -6,6 +6,12 @@ const model : ReplaceVariable = { handle: "max", description: "Returns the highest-value numbered passed", usage: "max[num1, num2, ...]", + examples: [ + { + usage: "max[1, 5, 3, 10]", + description: "Returns 10, the highest value from the input numbers" + } + ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/number/number-min.ts b/src/backend/variables/builtin/number/number-min.ts index 1a8654785..0cd31a402 100644 --- a/src/backend/variables/builtin/number/number-min.ts +++ b/src/backend/variables/builtin/number/number-min.ts @@ -6,6 +6,12 @@ const model : ReplaceVariable = { handle: "min", description: "Returns the lowest-value numbered passed", usage: "min[num1, num2, ...]", + examples: [ + { + usage: "min[1, 5, 3, 10]", + description: "Returns 1, the lowest value from the input numbers" + } + ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NULL, OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/object/object-set-property.ts b/src/backend/variables/builtin/object/object-set-property.ts index 531dcd54b..6af1c419f 100644 --- a/src/backend/variables/builtin/object/object-set-property.ts +++ b/src/backend/variables/builtin/object/object-set-property.ts @@ -8,6 +8,20 @@ const model : ReplaceVariable = { handle: "setObjectProperty", description: "Adds or updates a property's value in the given JSON object. For nested properties, you can use dot notation (e.g. some.property). Set value to null to remove property.", usage: "setObjectProperty[object, propertyPath, value]", + examples: [ + { + usage: `setObjectProperty[{"name": "John"}, age, 25]`, + description: `Adds/updates the age property to 25. Result: {"name": "John", "age": 25}` + }, + { + usage: `setObjectProperty[{"user": {"name": "John"}}, user.age, 25]`, + description: `Adds/updates a nested property using dot notation. Result: {"user": {"name": "John", "age": 25}}` + }, + { + usage: `setObjectProperty[{"name": "John", "age": 25}, age, null]`, + description: `Removes the age property. Result: {"name": "John"}` + } + ], categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/text/text-capitalize.ts b/src/backend/variables/builtin/text/text-capitalize.ts index 74b10adf1..3689fb634 100644 --- a/src/backend/variables/builtin/text/text-capitalize.ts +++ b/src/backend/variables/builtin/text/text-capitalize.ts @@ -6,6 +6,12 @@ const model : ReplaceVariable = { handle: "capitalize", description: "Capitalizes the given text.", usage: "capitalize[text]", + examples: [ + { + usage: `capitalize["hello world"]`, + description: `Returns "Hello world".` + } + ], categories: [VariableCategory.TEXT], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/text/text-concat.ts b/src/backend/variables/builtin/text/text-concat.ts index 148d0b7f6..de00ab72c 100644 --- a/src/backend/variables/builtin/text/text-concat.ts +++ b/src/backend/variables/builtin/text/text-concat.ts @@ -7,6 +7,12 @@ const model : ReplaceVariable = { handle: "concat", description: "Appends text together", usage: "concat[text, text, ...]", + examples: [ + { + usage: `concat[Hello, " ", World]`, + description: `Returns "Hello World"` + } + ], categories: [VariableCategory.TEXT], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/text/text-decode-from-html.ts b/src/backend/variables/builtin/text/text-decode-from-html.ts index bd772f3e9..e7e802560 100644 --- a/src/backend/variables/builtin/text/text-decode-from-html.ts +++ b/src/backend/variables/builtin/text/text-decode-from-html.ts @@ -9,6 +9,12 @@ const model : ReplaceVariable = { handle: "decodeFromHtml", description: "Decodes input text from an HTML-encoded string", usage: "decodeFromHtml[text]", + examples: [ + { + usage: `decodeFromHtml[<p>Hello & Welcome!</p>]`, + description: `Returns "

Hello & Welcome!

"` + } + ], categories: [VariableCategory.TEXT], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/text/text-decode-from-url.ts b/src/backend/variables/builtin/text/text-decode-from-url.ts index 3e17cff34..cb99d0a4c 100644 --- a/src/backend/variables/builtin/text/text-decode-from-url.ts +++ b/src/backend/variables/builtin/text/text-decode-from-url.ts @@ -7,6 +7,12 @@ const model : ReplaceVariable = { handle: "decodeFromUrl", description: "Decodes input text from a URL-encoded string", usage: "decodeFromUrl[text]", + examples: [ + { + usage: `decodeFromUrl["Hello%20World%21"]`, + description: "Returns Hello World!" + } + ], categories: [VariableCategory.TEXT], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/text/text-encode-for-html.ts b/src/backend/variables/builtin/text/text-encode-for-html.ts index d19196c02..cf7dc8fa0 100644 --- a/src/backend/variables/builtin/text/text-encode-for-html.ts +++ b/src/backend/variables/builtin/text/text-encode-for-html.ts @@ -9,6 +9,12 @@ const model : ReplaceVariable = { handle: "encodeForHtml", description: "Encodes input text for safe use within HTML templates", usage: "encodeForHtml[text]", + examples: [ + { + usage: "encodeForHtml[

Hello & Welcome!

]", + description: `Returns "<p>Hello & Welcome!</p>"` + } + ], categories: [VariableCategory.TEXT], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/text/text-encode-for-url.ts b/src/backend/variables/builtin/text/text-encode-for-url.ts index efc4b73d3..8fdf0a440 100644 --- a/src/backend/variables/builtin/text/text-encode-for-url.ts +++ b/src/backend/variables/builtin/text/text-encode-for-url.ts @@ -7,6 +7,12 @@ const model : ReplaceVariable = { handle: "encodeForUrl", description: "Encodes input text for use in a URL", usage: "encodeForUrl[text]", + examples: [ + { + usage: "encodeForUrl[Hello World!]", + description: `Returns "Hello%20World%21"` + } + ], categories: [VariableCategory.TEXT], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/user/account-creation-date.ts b/src/backend/variables/builtin/twitch/account-creation-date.ts similarity index 100% rename from src/backend/variables/builtin/user/account-creation-date.ts rename to src/backend/variables/builtin/twitch/account-creation-date.ts diff --git a/src/backend/variables/builtin/twitch/twitch-channel-url.ts b/src/backend/variables/builtin/twitch/twitch-channel-url.ts index 5f6247e71..0c0c73945 100644 --- a/src/backend/variables/builtin/twitch/twitch-channel-url.ts +++ b/src/backend/variables/builtin/twitch/twitch-channel-url.ts @@ -4,12 +4,27 @@ import { OutputDataType, VariableCategory } from "../../../../shared/variable-co const model: ReplaceVariable = { definition: { handle: "twitchChannelUrl", - usage: "twitchChannelUrl[channel]", - description: "Returns the Twitch URL for the given channel name (e.g. https://www.twitch.tv/ReallyCoolFirebotUser).", + usage: "twitchChannelUrl[channelName]", + description: "Returns the Twitch URL for the given channel name (e.g. https://www.twitch.tv/reallycoolfirebotuser).", + examples: [ + { + usage: "twitchChannelUrl[$streamer]", + description: "Returns the Twitch URL for the given channel name (e.g. https://www.twitch.tv/reallycoolfirebotuser)." + }, + { + usage: "twitchChannelUrl[$username]", + description: "Returns the Twitch URL for the given channel name (e.g. https://www.twitch.tv/reallycoolfirebotuser)." + }, + { + usage: "twitchChannelUrl[$target]", + description: "Returns the Twitch URL for the given channel name (e.g. https://www.twitch.tv/reallycoolfirebotuser).(Not all Display Names will work)" + } + ], categories: [VariableCategory.TEXT, VariableCategory.COMMON], possibleDataOutput: [OutputDataType.TEXT] }, evaluator: (trigger, channelName: string) => { + return `https://www.twitch.tv/${channelName}`; } }; diff --git a/src/backend/variables/builtin/user/chat-messages.ts b/src/backend/variables/builtin/user/chat-messages.ts index 22309855d..936cebe0b 100644 --- a/src/backend/variables/builtin/user/chat-messages.ts +++ b/src/backend/variables/builtin/user/chat-messages.ts @@ -6,8 +6,18 @@ import viewerDatabase from "../../../viewers/viewer-database"; const model : ReplaceVariable = { definition: { handle: "chatMessages", - usage: "chatMessages[username]", + usage: "chatMessages", description: "Displays the number of chat messages for a viewer (leave blank to use current viewer)", + examples: [ + { + usage: "chatMessages", + description: "Returns the number of chat messages for the current viewer" + }, + { + usage: "chatMessages[username]", + description: "Returns the number of chat messages for the specified user" + } + ], categories: [VariableCategory.USER], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/user/index.ts b/src/backend/variables/builtin/user/index.ts index d6eb30a12..dbb812614 100644 --- a/src/backend/variables/builtin/user/index.ts +++ b/src/backend/variables/builtin/user/index.ts @@ -1,4 +1,4 @@ -import accountCreationDate from './account-creation-date'; +import accountCreationDate from '../twitch/account-creation-date'; import chatMessages from './chat-messages'; import isUserInChat from './is-user-in-chat'; import metadataKey from './metadata-key'; diff --git a/src/backend/variables/builtin/user/user-exists.ts b/src/backend/variables/builtin/user/user-exists.ts index d62f0f6d5..62c8eef19 100644 --- a/src/backend/variables/builtin/user/user-exists.ts +++ b/src/backend/variables/builtin/user/user-exists.ts @@ -9,7 +9,7 @@ const model : ReplaceVariable = { usage: "userExists[username]", description: "Outputs 'true' if a user exists in Firebot's database, 'false' if not", categories: [VariableCategory.ADVANCED], - possibleDataOutput: [OutputDataType.TEXT] + possibleDataOutput: [OutputDataType.TEXT, OutputDataType.BOOLEAN] }, evaluator: async (_, username: string) => { const user = await viewerDatabase.getViewerByUsername(username); diff --git a/src/backend/variables/builtin/user/user-is-banned.ts b/src/backend/variables/builtin/user/user-is-banned.ts index b105a144f..89c3ae091 100644 --- a/src/backend/variables/builtin/user/user-is-banned.ts +++ b/src/backend/variables/builtin/user/user-is-banned.ts @@ -8,7 +8,7 @@ const UserIsBannedVariable: ReplaceVariable = { usage: "userIsBanned[username]", description: "Returns `true` if the specified user is currently banned (not just timed out), otherwise returns `false`.", categories: [VariableCategory.COMMON, VariableCategory.TRIGGER, VariableCategory.USER], - possibleDataOutput: [OutputDataType.TEXT] + possibleDataOutput: [OutputDataType.TEXT, OutputDataType.BOOLEAN] }, evaluator: async (trigger, username: string) => { if (username == null || username === "") { diff --git a/src/backend/variables/builtin/user/user-is-timed-out.ts b/src/backend/variables/builtin/user/user-is-timed-out.ts index 6bb63b841..2bde9eb90 100644 --- a/src/backend/variables/builtin/user/user-is-timed-out.ts +++ b/src/backend/variables/builtin/user/user-is-timed-out.ts @@ -8,7 +8,7 @@ const UserIsTimedOutVariable: ReplaceVariable = { usage: "userIsTimedOut[username]", description: "Returns `true` if the specified user is currently timed out, otherwise returns `false`.", categories: [VariableCategory.COMMON, VariableCategory.TRIGGER, VariableCategory.USER], - possibleDataOutput: [OutputDataType.TEXT] + possibleDataOutput: [OutputDataType.TEXT, OutputDataType.BOOLEAN] }, evaluator: async (trigger, username: string) => { if (username == null || username === "") { diff --git a/src/backend/variables/builtin/utility/audio-duration.ts b/src/backend/variables/builtin/utility/audio-duration.ts index 9a26aecef..6659f2c85 100644 --- a/src/backend/variables/builtin/utility/audio-duration.ts +++ b/src/backend/variables/builtin/utility/audio-duration.ts @@ -8,8 +8,18 @@ const model : ReplaceVariable = { handle: "audioDuration", usage: "audioDuration[filePathOrUrl]", description: "Attempts to retrieve audio duration.", + examples: [ + { + usage: `audioDuration["path/to/audio.mp3"]`, + description: "Returns the duration of the audio file in seconds." + }, + { + usage: `audioDuration["https://example.com/audio.mp3"]`, + description: "Returns the duration of the audio file from a URL in seconds." + } + ], categories: [VariableCategory.ADVANCED], - possibleDataOutput: [OutputDataType.NUMBER] + possibleDataOutput: [OutputDataType.NUMBER, OutputDataType.TEXT] }, evaluator: async (trigger, url) => { if (url == null) { diff --git a/src/backend/variables/builtin/utility/convert-from-json.ts b/src/backend/variables/builtin/utility/convert-from-json.ts index 7c1e5d44f..c848395d5 100644 --- a/src/backend/variables/builtin/utility/convert-from-json.ts +++ b/src/backend/variables/builtin/utility/convert-from-json.ts @@ -6,6 +6,12 @@ const model : ReplaceVariable = { handle: "convertFromJSON", description: "Converts JSON text into a raw object instance", usage: "convertFromJSON[json text]", + examples: [ + { + usage: `convertFromJSON['{"name": "John", "age": 30}']`, + description: "Returns a raw object from JSON string" + } + ], categories: [VariableCategory.ADVANCED], possibleDataOutput: [OutputDataType.TEXT] }, diff --git a/src/backend/variables/builtin/utility/index.ts b/src/backend/variables/builtin/utility/index.ts index 82c5e0dfe..27835a407 100644 --- a/src/backend/variables/builtin/utility/index.ts +++ b/src/backend/variables/builtin/utility/index.ts @@ -10,7 +10,7 @@ import fileLineCount from './file-line-count'; import fileName from './file-name'; import fileRead from './file-read'; import filesInDirectory from './files-in-directory'; -import getEffectQueueLength from "./get-effect-queue-length"; +import getEffectQueueLength from "../metadata/effect-queue-length"; import loopCount from './loop-count'; import loopItem from './loop-item'; import quickstore from './quick-store'; diff --git a/src/backend/variables/builtin/utility/video-duration.ts b/src/backend/variables/builtin/utility/video-duration.ts index 70af1f679..26228c150 100644 --- a/src/backend/variables/builtin/utility/video-duration.ts +++ b/src/backend/variables/builtin/utility/video-duration.ts @@ -9,8 +9,18 @@ const model : ReplaceVariable = { handle: "videoDuration", usage: "videoDuration[filePathOrUrl]", description: "Attempts to retrieve video duration.", + examples: [ + { + usage: "videoDuration[\"path/to/video.mp4\"]", + description: "Returns the duration of the video file in seconds." + }, + { + usage: "videoDuration[\"https://example.com/video.mp4\"]", + description: "Returns the duration of the video file from a URL in seconds." + } + ], categories: [VariableCategory.ADVANCED], - possibleDataOutput: [OutputDataType.TEXT] + possibleDataOutput: [OutputDataType.TEXT, OutputDataType.NUMBER] }, evaluator: async (trigger, url) => { if (url == null) { diff --git a/src/gui/app/directives/misc/replaceVariableMenu.js b/src/gui/app/directives/misc/replaceVariableMenu.js index 87be6eb8a..7bff323d0 100644 --- a/src/gui/app/directives/misc/replaceVariableMenu.js +++ b/src/gui/app/directives/misc/replaceVariableMenu.js @@ -223,10 +223,16 @@
All
-
{{category}}
+
{{category}} + +
-
+
\${{variable.usage ? variable.usage : variable.handle}}
diff --git a/src/gui/app/directives/modals/effects/add-new-effect-modal.js b/src/gui/app/directives/modals/effects/add-new-effect-modal.js index dacc3320e..c79749af0 100644 --- a/src/gui/app/directives/modals/effects/add-new-effect-modal.js +++ b/src/gui/app/directives/modals/effects/add-new-effect-modal.js @@ -25,7 +25,7 @@ const { EffectCategory } = require("../../shared/effect-constants");
diff --git a/src/gui/scss/core/_effects.scss b/src/gui/scss/core/_effects.scss index fa00a48b4..a21465603 100644 --- a/src/gui/scss/core/_effects.scss +++ b/src/gui/scss/core/_effects.scss @@ -35,7 +35,7 @@ &.dark { background: $variable-category-bg; padding-top: 5px; - width: 125px; + width: 135px; } } diff --git a/src/shared/variable-constants.js b/src/shared/variable-constants.js index dfcb7c863..ef7ee773e 100644 --- a/src/shared/variable-constants.js +++ b/src/shared/variable-constants.js @@ -26,7 +26,9 @@ const VariableCategory = Object.freeze({ USER: "user based", TEXT: "text", NUMBERS: "numbers", - ADVANCED: "advanced" + ADVANCED: "advanced", + INTEGRATION: "integrations", + OBS: "obs" }); exports.OutputDataType = OutputDataType; diff --git a/src/types/variables.d.ts b/src/types/variables.d.ts index 372197777..1b03ee81d 100644 --- a/src/types/variables.d.ts +++ b/src/types/variables.d.ts @@ -6,7 +6,9 @@ export type VariableCategory = | "user based" | "text" | "numbers" - | "advanced"; + | "advanced" + | "obs" + | "integrations"; interface VariableDefinition { handle: string; From ea0e6ec46a167827c0aa78a6546101304b73474d Mon Sep 17 00:00:00 2001 From: CKY Date: Thu, 28 Nov 2024 10:28:56 -0700 Subject: [PATCH 06/54] fix: command cooldown (#2909) Co-authored-by: Erik Bigler --- .../chat/commands/command-cooldown-manager.ts | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/backend/chat/commands/command-cooldown-manager.ts b/src/backend/chat/commands/command-cooldown-manager.ts index 1ba82d247..ce87369ad 100644 --- a/src/backend/chat/commands/command-cooldown-manager.ts +++ b/src/backend/chat/commands/command-cooldown-manager.ts @@ -112,13 +112,11 @@ class CommandCooldownManager { ); if (cooldown.global > 0) { - if (this._cooldownCache.get(globalCacheKey) == null) { - this._cooldownCache.set( - globalCacheKey, - DateTime.utc().plus({ seconds: cooldown.global }), - cooldown.global - ); - } + this._cooldownCache.set( + globalCacheKey, + DateTime.utc().plus({ seconds: cooldown.global }), + cooldown.global + ); } if (cooldown.user > 0) { this._cooldownCache.set( @@ -147,13 +145,11 @@ class CommandCooldownManager { ); if (config.cooldown.global > 0) { - if (this._cooldownCache.get(globalCacheKey) == null) { - this._cooldownCache.set( - globalCacheKey, - DateTime.utc().plus({ seconds: config.cooldown.global }), - config.cooldown.global - ); - } + this._cooldownCache.set( + globalCacheKey, + DateTime.utc().plus({ seconds: config.cooldown.global }), + config.cooldown.global + ); } if (config.cooldown.user > 0 && config.username != null) { this._cooldownCache.set( From c3ec9dc35249f6793f321851c1830196cea0bd47 Mon Sep 17 00:00:00 2001 From: Dennis Rijsdijk <70665154+dennisrijsdijk@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:30:27 +0100 Subject: [PATCH 07/54] chore: replace variable examples (#2913) * chore: move imports * chore: remove redundant usages * chore: semantics * chore: quotes * chore: typo * chore: fix currencyRank usage --- src/backend/variables/builtin/counter/counter.ts | 6 ------ src/backend/variables/builtin/currency/currency-rank.ts | 2 +- src/backend/variables/builtin/currency/currency.ts | 2 +- src/backend/variables/builtin/metadata/index.ts | 2 ++ src/backend/variables/builtin/number/math.ts | 6 +++--- src/backend/variables/builtin/number/number-commafy.ts | 2 +- src/backend/variables/builtin/number/number-floor.ts | 4 ---- src/backend/variables/builtin/number/number-max.ts | 2 +- src/backend/variables/builtin/number/number-min.ts | 2 +- src/backend/variables/builtin/text/text-capitalize.ts | 6 +++++- src/backend/variables/builtin/text/text-decode-from-url.ts | 2 +- src/backend/variables/builtin/twitch/index.ts | 2 ++ src/backend/variables/builtin/user/index.ts | 2 -- src/backend/variables/builtin/utility/index.ts | 2 -- src/backend/variables/builtin/utility/video-duration.ts | 4 ++-- 15 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/backend/variables/builtin/counter/counter.ts b/src/backend/variables/builtin/counter/counter.ts index fbdafa103..7f0125b71 100644 --- a/src/backend/variables/builtin/counter/counter.ts +++ b/src/backend/variables/builtin/counter/counter.ts @@ -7,12 +7,6 @@ const model: ReplaceVariable = { handle: "counter", usage: "counter[name]", description: "Displays the value of the given counter.", - examples: [ - { - usage: "counter[name]", - description: "Returns the value of the specified counter" - } - ], categories: [VariableCategory.NUMBERS], possibleDataOutput: [OutputDataType.NUMBER] }, diff --git a/src/backend/variables/builtin/currency/currency-rank.ts b/src/backend/variables/builtin/currency/currency-rank.ts index e60f4dbe8..519936345 100644 --- a/src/backend/variables/builtin/currency/currency-rank.ts +++ b/src/backend/variables/builtin/currency/currency-rank.ts @@ -8,7 +8,7 @@ const model : ReplaceVariable = { definition: { handle: "currencyRank", description: "Returns the rank of the current user based on how much of the given currency they have.", - usage: "currencyRank[currencyName, username]", + usage: "currencyRank[currencyName]", examples: [ { usage: "currencyRank[currencyName, username]", diff --git a/src/backend/variables/builtin/currency/currency.ts b/src/backend/variables/builtin/currency/currency.ts index 802d3a2f9..6519f22cc 100644 --- a/src/backend/variables/builtin/currency/currency.ts +++ b/src/backend/variables/builtin/currency/currency.ts @@ -12,7 +12,7 @@ const model : ReplaceVariable = { examples: [ { usage: "currency[currencyName, username]", - description: "Returns the amount of specified currency the given user fas" + description: "Returns the amount of specified currency the given user has" } ], categories: [VariableCategory.USER, VariableCategory.NUMBERS], diff --git a/src/backend/variables/builtin/metadata/index.ts b/src/backend/variables/builtin/metadata/index.ts index c04face94..d3e3312f8 100644 --- a/src/backend/variables/builtin/metadata/index.ts +++ b/src/backend/variables/builtin/metadata/index.ts @@ -6,6 +6,7 @@ import commandTrigger from './command-trigger'; import count from './count'; import effectOutput from './effect-output'; import effectQueueId from './effect-queue-id'; +import effectQueueLength from './effect-queue-length'; import effectQueueName from './effect-queue-name'; import effectQueueStatus from './effect-queue-status'; import overlayInstance from './overlay-instance'; @@ -26,6 +27,7 @@ export default [ count, effectOutput, effectQueueId, + effectQueueLength, effectQueueName, effectQueueStatus, overlayInstance, diff --git a/src/backend/variables/builtin/number/math.ts b/src/backend/variables/builtin/number/math.ts index b810af262..38147e899 100644 --- a/src/backend/variables/builtin/number/math.ts +++ b/src/backend/variables/builtin/number/math.ts @@ -7,16 +7,16 @@ const logger = require("../../../logwrapper"); const model : ReplaceVariable = { definition: { handle: "math", - usage: "math[expression]", + usage: "math[expression]", description: 'Evaluate a math equation using math.js', examples: [ { usage: "math[2 + 2]", - description: "Simple addition calculation returns 4" + description: `Returns 4` }, { usage: "math[5 * (3 + 2)]", - description: "Complex calculation returns 25" + description: `Returns 25` } ], categories: [VariableCategory.COMMON, VariableCategory.NUMBERS], diff --git a/src/backend/variables/builtin/number/number-commafy.ts b/src/backend/variables/builtin/number/number-commafy.ts index 82313520d..0a8eb3fa6 100644 --- a/src/backend/variables/builtin/number/number-commafy.ts +++ b/src/backend/variables/builtin/number/number-commafy.ts @@ -9,7 +9,7 @@ const model : ReplaceVariable = { examples: [ { usage: "commafy[1000000]", - description: "Returns \"1,000,000\"" + description: `Returns "1,000,000"` } ], categories: [VariableCategory.NUMBERS], diff --git a/src/backend/variables/builtin/number/number-floor.ts b/src/backend/variables/builtin/number/number-floor.ts index 4985ccccc..e6a6aa246 100644 --- a/src/backend/variables/builtin/number/number-floor.ts +++ b/src/backend/variables/builtin/number/number-floor.ts @@ -10,10 +10,6 @@ const model : ReplaceVariable = { { usage: "floor[3.7]", description: "Returns 3" - }, - { - usage: "floor[$presetListArg[Number]]", - description: "Rounds down the preset list argument value" } ], categories: [VariableCategory.NUMBERS], diff --git a/src/backend/variables/builtin/number/number-max.ts b/src/backend/variables/builtin/number/number-max.ts index cc84bedfe..cc2677c54 100644 --- a/src/backend/variables/builtin/number/number-max.ts +++ b/src/backend/variables/builtin/number/number-max.ts @@ -4,7 +4,7 @@ import { OutputDataType, VariableCategory } from "../../../../shared/variable-co const model : ReplaceVariable = { definition: { handle: "max", - description: "Returns the highest-value numbered passed", + description: "Returns the highest-value number", usage: "max[num1, num2, ...]", examples: [ { diff --git a/src/backend/variables/builtin/number/number-min.ts b/src/backend/variables/builtin/number/number-min.ts index 0cd31a402..336d2b05f 100644 --- a/src/backend/variables/builtin/number/number-min.ts +++ b/src/backend/variables/builtin/number/number-min.ts @@ -4,7 +4,7 @@ import { OutputDataType, VariableCategory } from "../../../../shared/variable-co const model : ReplaceVariable = { definition: { handle: "min", - description: "Returns the lowest-value numbered passed", + description: "Returns the lowest-value number", usage: "min[num1, num2, ...]", examples: [ { diff --git a/src/backend/variables/builtin/text/text-capitalize.ts b/src/backend/variables/builtin/text/text-capitalize.ts index 3689fb634..2e56cba6c 100644 --- a/src/backend/variables/builtin/text/text-capitalize.ts +++ b/src/backend/variables/builtin/text/text-capitalize.ts @@ -4,12 +4,16 @@ import { OutputDataType, VariableCategory } from "../../../../shared/variable-co const model : ReplaceVariable = { definition: { handle: "capitalize", - description: "Capitalizes the given text.", + description: "Capitalizes the first letter of the given text, converting the rest into lowercase", usage: "capitalize[text]", examples: [ { usage: `capitalize["hello world"]`, description: `Returns "Hello world".` + }, + { + usage: `capitalize["HELLO WORLD"]`, + description: `Returns "Hello world".` } ], categories: [VariableCategory.TEXT], diff --git a/src/backend/variables/builtin/text/text-decode-from-url.ts b/src/backend/variables/builtin/text/text-decode-from-url.ts index cb99d0a4c..36ec4c7c6 100644 --- a/src/backend/variables/builtin/text/text-decode-from-url.ts +++ b/src/backend/variables/builtin/text/text-decode-from-url.ts @@ -10,7 +10,7 @@ const model : ReplaceVariable = { examples: [ { usage: `decodeFromUrl["Hello%20World%21"]`, - description: "Returns Hello World!" + description: `Returns "Hello World!"` } ], categories: [VariableCategory.TEXT], diff --git a/src/backend/variables/builtin/twitch/index.ts b/src/backend/variables/builtin/twitch/index.ts index 540a4ce3b..77cacd925 100644 --- a/src/backend/variables/builtin/twitch/index.ts +++ b/src/backend/variables/builtin/twitch/index.ts @@ -11,6 +11,7 @@ import rewardVariables from './reward'; import streamVariables from './stream'; import subVariables from './subs'; +import accountCreationDate from './account-creation-date'; import followAge from './follow-age'; import followCount from './follow-count'; import predictionWinningOutcomeName from './prediction-winning-outcome-name'; @@ -32,6 +33,7 @@ export default [ ...streamVariables, ...subVariables, + accountCreationDate, followAge, followCount, predictionWinningOutcomeName, diff --git a/src/backend/variables/builtin/user/index.ts b/src/backend/variables/builtin/user/index.ts index dbb812614..fde667945 100644 --- a/src/backend/variables/builtin/user/index.ts +++ b/src/backend/variables/builtin/user/index.ts @@ -1,4 +1,3 @@ -import accountCreationDate from '../twitch/account-creation-date'; import chatMessages from './chat-messages'; import isUserInChat from './is-user-in-chat'; import metadataKey from './metadata-key'; @@ -25,7 +24,6 @@ import roleVariables from './roles'; import rankVariables from './ranks'; export default [ - accountCreationDate, chatMessages, isUserInChat, metadataKey, diff --git a/src/backend/variables/builtin/utility/index.ts b/src/backend/variables/builtin/utility/index.ts index 27835a407..2f46d0bab 100644 --- a/src/backend/variables/builtin/utility/index.ts +++ b/src/backend/variables/builtin/utility/index.ts @@ -10,7 +10,6 @@ import fileLineCount from './file-line-count'; import fileName from './file-name'; import fileRead from './file-read'; import filesInDirectory from './files-in-directory'; -import getEffectQueueLength from "../metadata/effect-queue-length"; import loopCount from './loop-count'; import loopItem from './loop-item'; import quickstore from './quick-store'; @@ -31,7 +30,6 @@ export default [ fileName, fileRead, filesInDirectory, - getEffectQueueLength, loopCount, loopItem, quickstore, diff --git a/src/backend/variables/builtin/utility/video-duration.ts b/src/backend/variables/builtin/utility/video-duration.ts index 26228c150..a02944482 100644 --- a/src/backend/variables/builtin/utility/video-duration.ts +++ b/src/backend/variables/builtin/utility/video-duration.ts @@ -11,11 +11,11 @@ const model : ReplaceVariable = { description: "Attempts to retrieve video duration.", examples: [ { - usage: "videoDuration[\"path/to/video.mp4\"]", + usage: `videoDuration["path/to/video.mp4"]`, description: "Returns the duration of the video file in seconds." }, { - usage: "videoDuration[\"https://example.com/video.mp4\"]", + usage: `videoDuration["https://example.com/video.mp4"]`, description: "Returns the duration of the video file from a URL in seconds." } ], From 65eb69803b9177f27ca5f2d8f2f566f3f157430c Mon Sep 17 00:00:00 2001 From: Erik Bigler Date: Fri, 29 Nov 2024 17:17:32 -0600 Subject: [PATCH 08/54] feat(ui): implement selectable-input-editors component, use in metadata and websocket effects --- .../builtin/send-custom-websocket-event.ts | 38 ++++++-- .../effects/builtin/set-user-metadata.js | 31 +++++- src/gui/app/app-main.js | 4 + .../app/directives/controls/firebot-input.js | 58 ++++++++--- .../controls/selectable-input-editors.js | 63 ++++++++++++ .../modals/misc/add-or-edit-metadata-modal.js | 95 ++++++++----------- src/gui/scss/core/_bootstrap-overrides.scss | 5 + src/gui/scss/core/_live-events.scss | 15 ++- 8 files changed, 231 insertions(+), 78 deletions(-) create mode 100644 src/gui/app/directives/controls/selectable-input-editors.js diff --git a/src/backend/effects/builtin/send-custom-websocket-event.ts b/src/backend/effects/builtin/send-custom-websocket-event.ts index a25087ec7..6db975505 100644 --- a/src/backend/effects/builtin/send-custom-websocket-event.ts +++ b/src/backend/effects/builtin/send-custom-websocket-event.ts @@ -17,27 +17,49 @@ const model: EffectType<{ }, optionsTemplate: ` -

Enter the name of the event you'd like to send. It will be sent as:
custom-event:eventname

+

Enter the name of the event you'd like to send.

+

It will be sent as: custom-event:{{effect.eventName || 'eventname'}}

Enter any event data that you'd like to include with the event.

-
`, - optionsController: () => { }, + optionsController: ($scope) => { + $scope.editors = [ + { + label: "Basic", + inputType: "text", + useTextArea: true, + placeholderText: "Enter event data", + menuPosition: "under" + }, + { + label: "JSON", + inputType: "codemirror", + menuPosition: "under", + codeMirrorOptions: { + mode: {name: "javascript", json: true}, + theme: 'blackboard', + lineNumbers: true, + autoRefresh: true, + showGutter: true + } + } + ]; + + $scope.initialEditorLabel = $scope.effect?.eventData?.startsWith("{") || $scope.effect?.eventData?.startsWith("[") ? "JSON" : "Basic"; + }, optionsValidator: (effect) => { const errors = []; if (!(effect.eventName?.length > 0)) { diff --git a/src/backend/effects/builtin/set-user-metadata.js b/src/backend/effects/builtin/set-user-metadata.js index cd7c1e8fd..2eaa76b49 100644 --- a/src/backend/effects/builtin/set-user-metadata.js +++ b/src/backend/effects/builtin/set-user-metadata.js @@ -24,7 +24,11 @@ const effect = {

This is the data that will be saved under the above key in the user's data. Can be text or another replace phrase.

- +

Note: If data is a valid JSON string, it will be parsed into an object or array.

@@ -44,7 +48,30 @@ const effect = {
`, - optionsController: () => {}, + optionsController: ($scope) => { + $scope.editors = [ + { + label: "Basic", + inputType: "text", + useTextArea: true, + placeholderText: "Enter text/data" + }, + { + label: "JSON", + inputType: "codemirror", + placeholderText: "Enter text/data", + codeMirrorOptions: { + mode: {name: "javascript", json: true}, + theme: 'blackboard', + lineNumbers: true, + autoRefresh: true, + showGutter: true + } + } + ]; + + $scope.initialEditorLabel = $scope.effect?.data?.startsWith("{") || $scope.effect?.data?.startsWith("[") ? "JSON" : "Basic"; + }, optionsValidator: (effect) => { const errors = []; if (effect.username == null || effect.username === "") { diff --git a/src/gui/app/app-main.js b/src/gui/app/app-main.js index 16cf2a9b3..5c32fb97c 100644 --- a/src/gui/app/app-main.js +++ b/src/gui/app/app-main.js @@ -87,6 +87,10 @@ ]); }); + app.config(function($animateProvider) { + $animateProvider.classNameFilter(/^(?:(?!ng-animate-disabled).)*$/); + }); + app.config([ "ngToastProvider", function(ngToast) { diff --git a/src/gui/app/directives/controls/firebot-input.js b/src/gui/app/directives/controls/firebot-input.js index 98e128bf0..5d4970c1c 100644 --- a/src/gui/app/directives/controls/firebot-input.js +++ b/src/gui/app/directives/controls/firebot-input.js @@ -14,6 +14,7 @@ disableVariables: "<", forceInput: " -
+
{{$ctrl.inputTitle}}
-
+
+
+
+
+
`, controller: function ($timeout) { @@ -104,27 +118,38 @@ $ctrl.forceInputInternal = false; + $ctrl.cmEditor = null; + $ctrl.onChange = (model) => { if (!$ctrl.allowNewLines) { model = model.replace(/\n/gm, ""); } $ctrl.model = model; $timeout(() => { - $ctrl.onInputUpdate(); + $ctrl.onInputUpdate?.(); }, 25); }; - $ctrl.$onInit = () => { - $ctrl.forceInputInternal = !$ctrl.useTextArea && ($ctrl.forceInput || $ctrl.disableVariables && $ctrl.inputType !== 'text'); + const init = () => { + $ctrl.allowNewLines = $ctrl.useTextArea === true; $ctrl.wrapMode = $ctrl.useTextArea ? "soft" : "off"; $ctrl.useInputGroup = $ctrl.inputTitle != null && $ctrl.inputTitle !== ""; + $ctrl.forceInputInternal = !$ctrl.useTextArea && ($ctrl.forceInput || ($ctrl.disableVariables && $ctrl.inputType !== 'text')); + + if ($ctrl.inputType === 'codemirror') { + $ctrl.cmEditor?.refresh(); + } + $timeout(() => { - $ctrl.onInputUpdate(); + $ctrl.onInputUpdate?.(); }, 25); }; + $ctrl.$onInit = init; + $ctrl.$onChanges = init; + $ctrl.onResize = () => { $ctrl.wrapMode = "soft"; }; @@ -132,7 +157,7 @@ // This is a hack to make the input field resize properly when it has a scrollbar $ctrl.$postLink = () => { $timeout(() => { - if ($ctrl.useTextArea || $ctrl.forceInputInternal) { + if ($ctrl.inputType === "codemirror" || $ctrl.useTextArea || $ctrl.forceInputInternal) { return; } @@ -153,6 +178,17 @@ }, 25); }, 25); }; + + $ctrl.codemirrorLoaded = function(_editor) { + $ctrl.cmEditor = _editor; + $ctrl.cmEditor.refresh(); + const cmResize = require("cm-resize"); + cmResize(_editor, { + minHeight: 200, + resizableWidth: false, + resizableHeight: true + }); + }; } }); })(); diff --git a/src/gui/app/directives/controls/selectable-input-editors.js b/src/gui/app/directives/controls/selectable-input-editors.js new file mode 100644 index 000000000..48b88d424 --- /dev/null +++ b/src/gui/app/directives/controls/selectable-input-editors.js @@ -0,0 +1,63 @@ +"use strict"; + +(function () { + angular.module("firebotApp").component("selectableInputEditors", { + bindings: { + editors: "<", + initialEditorLabel: " 1 }"> + +
+ +
+
`, + controller: function () { + const $ctrl = this; + + $ctrl.selectedEditor = null; + + $ctrl.$onInit = () => { + $ctrl.selectedEditor = $ctrl.initialEditorLabel + ? $ctrl.editors.find(o => o.label === $ctrl.initialEditorLabel) ?? $ctrl.editors[0] + : $ctrl.editors[0]; + }; + } + }); +})(); \ No newline at end of file diff --git a/src/gui/app/directives/modals/misc/add-or-edit-metadata-modal.js b/src/gui/app/directives/modals/misc/add-or-edit-metadata-modal.js index 38eda5cde..c42873730 100644 --- a/src/gui/app/directives/modals/misc/add-or-edit-metadata-modal.js +++ b/src/gui/app/directives/modals/misc/add-or-edit-metadata-modal.js @@ -14,15 +14,15 @@
- @@ -31,34 +31,11 @@
- -
-
- -
-
Data Editor Type
- - -
-
-
+

The overlay is what allows Firebot to display images, videos, and more on your stream.

@@ -217,7 +116,7 @@
-
+

We love spotlighting the amazing interactive experiences
crafted by our community using Firebot.

Would you like to be featured on our website during your live streams?

@@ -231,7 +130,7 @@
-
+
@@ -292,9 +191,8 @@ $ctrl.stepTitles = [ "", - "Import V4 Data", "Get Signed In", - "Lets Setup The Overlay", + "Let's Setup the Overlay", "Feature Your Stream", "" ]; @@ -326,29 +224,17 @@ }; $ctrl.getNextLabel = function() { - switch ($ctrl.step) { - default: - return "Next"; - } + return "Next"; }; $ctrl.handlePrevious = function() { - switch ($ctrl.step) { - case 2: - $ctrl.step = 0; - break; - default: - $ctrl.step -= $ctrl.isFirstStep() ? 0 : 1; - } + $ctrl.step -= $ctrl.isFirstStep() ? 0 : 1; }; $ctrl.showNextButton = function() { if ($ctrl.isFirstStep() || $ctrl.isLastStep()) { return false; } - if ($ctrl.step === 1) { - return false; - } return true; }; @@ -361,87 +247,21 @@ $ctrl.canGoToNext = function() { switch ($ctrl.step) { - case 2: + case 1: return connectionService.accounts.streamer.loggedIn; - case 3: { + case 2: { const overlayStatus = connectionManager.getOverlayStatus(); return !overlayStatus.serverStarted || overlayStatus.clientsConnected; } } return true; }; - - $ctrl.v4DataDetected = false; - backendCommunicator.fireEventAsync("v4-data-check") - .then((detected) => { - $ctrl.v4DataDetected = detected; - }); - - $ctrl.importSettings = {}; - - $ctrl.canStartImport = () => { - return $ctrl.importSettings.commands || - $ctrl.importSettings.events || - $ctrl.importSettings.viewerGroups || - $ctrl.importSettings.hotkeys || - $ctrl.importSettings.misc; - }; - - $ctrl.startImport = () => { - if (!$ctrl.canStartImport()) { - return; - } - - backendCommunicator.fireEvent("start-v4-import", $ctrl.importSettings); - }; - - $ctrl.importStarted = false; - $ctrl.currentlyImporting = null; - $ctrl.importCompleted = false; - $ctrl.importSuccess = false; - $ctrl.importIncompatibilityMessages = []; - $ctrl.importIncompatibilityMessageText = ""; - - backendCommunicator.on("v4-import-started", () => { - $ctrl.importStarted = true; - }); - - backendCommunicator.on("v4-import-update", (data) => { - $ctrl.currentlyImporting = data.importing; - }); - - backendCommunicator.on("v4-import-complete", (data) => { - $ctrl.importCompleted = true; - $ctrl.importStarted = false; - $ctrl.importSuccess = data.success; - $ctrl.importIncompatibilityMessages = data.incompatibilityWarnings; - }); - $ctrl.handleNext = async function(forceNext) { if ($ctrl.isLastStep()) { $ctrl.close(); } else { - switch ($ctrl.step) { - case 0: - if ($ctrl.v4DataDetected) { - $ctrl.step = 1; - } else { - $ctrl.step = 2; - } - return; - case 1: - $ctrl.step = 2; - $ctrl.importCompleted = false; - return; - case 2: - case 3: - case 4: { - if (!$ctrl.canGoToNext() && !forceNext) { - return; - } - - break; - } + if (!$ctrl.canGoToNext() && !forceNext) { + return; } $ctrl.step += 1; } @@ -449,10 +269,10 @@ $ctrl.getTooltipText = function() { switch ($ctrl.step) { - case 2: + case 1: return "Please sign into your Streamer account."; - case 3: - return "Please add the overlay url to your broadcasting software."; + case 2: + return "Please add the overlay URL to your broadcasting software."; } return ""; }; @@ -498,12 +318,6 @@ } }); }; - - $ctrl.$onInit = function() { - // When the component is initialized - // This is where you can start to access bindings, such as variables stored in 'resolve' - // IE $ctrl.resolve.shouldDelete or whatever - }; } }); -}()); +}()); \ No newline at end of file From d24d9c9384603483d5b8473f8b11eacd6ecaf0f1 Mon Sep 17 00:00:00 2001 From: CKY Date: Wed, 25 Dec 2024 01:26:24 -0700 Subject: [PATCH 54/54] feat: add set currency command (#2925) * feat: add set currency command * fix capitalization --------- Co-authored-by: CaveMobster --- .../currency/currency-command-manager.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/backend/currency/currency-command-manager.ts b/src/backend/currency/currency-command-manager.ts index 97dd385e4..fd1e2bee3 100644 --- a/src/backend/currency/currency-command-manager.ts +++ b/src/backend/currency/currency-command-manager.ts @@ -34,6 +34,7 @@ class CurrencyCommandManager { currencyBalanceMessageTemplate: string; whisperCurrencyBalanceMessage: boolean; addMessageTemplate: string; + setMessageTemplate: string; removeMessageTemplate: string; addAllMessageTemplate: string; removeAllMessageTemplate: string; @@ -47,6 +48,7 @@ class CurrencyCommandManager { currencyBalanceMessageTemplate: string; whisperCurrencyBalanceMessage: boolean; addMessageTemplate: string; + setMessageTemplate: string; removeMessageTemplate: string; addAllMessageTemplate: string; removeAllMessageTemplate: string; @@ -113,6 +115,14 @@ class CurrencyCommandManager { tip: "Variables: {currency}, {amount}", default: `Removed {amount} {currency} from everyone!`, useTextArea: true + }, + setMessageTemplate: { + type: "string", + title: "Set Currency Message Template", + description: "How the !currency set message appears in chat.", + tip: "Variables: {user}, {currency}, {amount}", + default: `Set {user}'s {currency} to {amount} !`, + useTextArea: true } }, subCommands: [ @@ -157,6 +167,24 @@ class CurrencyCommandManager { usage: "give [@user] [amount]", description: "Gives currency from one user to another user." }, + { + arg: "set", + usage: "set [@user] [amount]", + description: "Sets currency to the amount.", + restrictionData: { + restrictions: [ + { + id: "sys-cmd-mods-only-perms", + type: "firebot:permissions", + mode: "roles", + roleIds: [ + "mod", + "broadcaster" + ] + } + ] + } + }, { arg: "addall", usage: "addall [amount]", @@ -269,6 +297,28 @@ class CurrencyCommandManager { break; } + case "set": { + // Get username and make sure our currency amount is a positive integer. + const username = args[1].replace(/^@/, ''), + currencyAdjust = Math.abs(parseInt(args[2])); + + // Adjust currency, it will return true on success and false on failure. + const status = await currencyManager.adjustCurrencyForViewer(username, currencyId, currencyAdjust, "set"); + + if (status) { + const setMessageTemplate = commandOptions.setMessageTemplate + .replace("{user}", username) + .replace("{currency}", currencyName) + .replace("{amount}", util.commafy(currencyAdjust)); + await twitchChat.sendChatMessage(setMessageTemplate); + } else { + // Error removing currency. + await twitchChat.sendChatMessage(`Error: Could not set currency for user.`); + logger.error(`Error setting currency for user (${username}) via chat command. Currency: ${currencyId}. Value: ${currencyAdjust}`); + } + + break; + } case "give": { // Get username and make sure our currency amount is a positive integer. const username = args[1].replace(/^@/, ''),