Skip to main content
Corvus Connection

Scripting API

Interfaces

18
  • Local audio playback operations available inside a script handler, bound to the desktop's audio engine. Every method is failure-safe: a missing clip/alias, an unavailable output device, a TTS fault, or an unexpected throw is logged (only a stable message — never confidential data) and surfaced as a benign no-op. A failing call can never propagate out of a node. Triggering rate is the author's concern; the engine still enforces its own per-clip cooldown and concurrent-voice cap.
  • The long-lived local audio engine the desktop implements (a MediaPlayer pool plus offline TTS). The script-facing ctx.Audio facade (AudioApi) wraps this per invocation and is the failure-safe boundary — this surface may throw, and the wrapper logs and swallows. Registered in the in-process container so the script runtime resolves the desktop implementation. Implementations must not marshal to the WinUI UI thread.
  • Chat operations available inside a script handler. Implementations are bound to a single invocation — sending uses the broadcaster channel captured when the invocation began, and Subscribe creates a stream whose lifetime ends when the invocation ends.
  • A live, in-process stream of chat messages observed by a script. Used when a script wants to *watch* chat over time instead of being invoked once per message via OnChatMessageAttribute.
  • Read access to live connection health inside a script handler (spec 023), backed by the central connection-health monitor. Both members are failure-safe: an unexpected fault (or an unknown source name) is surfaced as a benign default (a Disconnected snapshot / false) — a read can never propagate out of a node. State is O(1); for "gateway" it is the aggregate (listening + client count), not one client. The source name is matched case-insensitively ("twitch"/"obs"/"spotify"/"gateway").
  • Posts to the streamer's Discord server from a script handler, via the saved channel-webhook destinations configured in the desktop. Failure-safe: an unknown destination, an API error, a rate limit, a timeout, or an unexpected throw is caught, logged (with confidential data stripped — only the stable error code, never a URL or token), and reported as false. It never throws, so a failing post can never crash the host or escape a node. Mentions are suppressed by default (no accidental @everyone).
  • OBS control + read operations available inside a script handler, bound to the bot's single obs-websocket connection. Every method is failure-safe: a disconnected OBS, a request error, or an unexpected throw is logged (only a stable message — never confidential data) and surfaced as a benign no-op (writes) or default (null / false for reads). A failing call can never propagate out of a node.
  • The API surface available to a script handler. Every facade is bound to the current invocation: sends target the broadcaster channel captured when the invocation began, and streams/subscriptions end when the invocation ends.
  • Implemented by a script that wants to compute its identity metadata at runtime instead of declaring it statically with ScriptMetadataAttribute. Useful when the version or name is derived (e.g., read from the assembly or a config value).
  • Optional health probe a script can implement so the host can surface its state on the desktop and export it as telemetry. Polled periodically and on demand; keep it cheap and side-effect free.
  • Optional lifecycle hooks a script class can implement to run setup before its first trigger fires and teardown when it is unloaded (deployment swap, host shutdown, or disable).
  • Lets a handler push progress events imperatively, without having to return an IAsyncEnumerable<ScriptProgress>. Available on every invocation via Progress.
  • Playback-control operations available inside a script handler, bound to the streamer's connected Spotify account. Every method is failure-safe: a Spotify API error, a missing/expired token, no active device, or a network fault is logged (with confidential data stripped) and swallowed — it never throws, so a failing call can never crash the host or escape a node. Mutating calls no-op on failure; GetNowPlayingAsync reports null.
  • Reverse commands to an Elgato Stream Deck key available inside a script handler. Every method is failure-safe: a missing bridge, a stale action context, or a transport fault is logged (with confidential data stripped) and swallowed — it never throws, so a failing call can never crash the host or escape a node. The context argument is the Elgato action instance id (from Context) identifying which key to target.
  • Message-templating operations available inside a script handler (spec 002 AC-22), bound to the current invocation's trigger context. Every method is failure-safe: an unknown template, a kind mismatch, a compile/render error, or an unexpected throw is logged and yields an empty string (or an empty list) — it never throws, so a failing call can never crash the host or escape a node. The Render Template graph node lowers to RenderAsync.
  • Read access to the streamer's tracked Tiltify charity campaign inside a script handler. Failure-safe: no campaign set, an API error, a missing/expired token, or a network fault is logged (with confidential data stripped) and reported as null — it never throws, so a failing call can never crash the host or escape a node. Lets a graph branch on goal progress without a try/catch.
  • Read-only Twitch query operations available inside a script handler, bound to the broadcaster channel captured when the invocation began. Every method is failure-safe: a Twitch API error or network fault is logged (with confidential data stripped) and surfaced as a benign default (null / false) — it never throws, so a graph can branch on the result without a try/catch and a failing call can never crash the host.

Trigger & control attributes

52
  • Enforces a minimum interval between invocations of a handler. While the handler is in cooldown, matching events are skipped (not queued). Use it to debounce spammable commands.
  • Routes a handler (or every handler in a class) through a named execution queue so that work sharing the same queue name is serialized to MaxConcurrency in-flight invocations, ordered by Priority. Use it to stop a script overlapping itself, or to fan several scripts onto one bounded lane (e.g., all OBS scene changes through a single-slot queue).
  • Marks a method as a handler fired when a user is banned or timed out. The method must accept (IScriptContext, BanContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler for a chat message that carried bits (a cheer in the message). The method must accept (IScriptContext, BitsInMessageContext); the context carries the bits amount and the message. A compiled graph bakes the authored minimum-bits threshold as a guard, so each handler responds only at or above its own threshold.
  • Marks a method as a handler fired on a finalized caption line. The method must accept (IScriptContext, CaptionContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a viewer redeems a custom channel-point reward. The method must accept (IScriptContext, ChannelPointRedeemContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler for a chat command — a message whose text begins with a prefix (e.g. !) followed by a command word. The method must accept (IScriptContext, ChatCommandContext); the context carries the parsed command word, the argument text/list, and the sender's role flags. Which specific command (and minimum role) a handler responds to is decided by the handler itself — a compiled graph bakes the authored command/prefix/min-role as a guard.
  • Marks a method as a handler for chat messages received on the broadcaster's channel. The method must accept (IScriptContext, ChatMessageContext) and may return void, Task, ValueTask, Task<Result>, ValueTask<Result>, Task<Result<ScriptOutcome>>, or ValueTask<Result<ScriptOutcome>>.
  • Marks a method as a handler fired when a viewer cheers with bits. The method must accept (IScriptContext, CheerContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a monitored connection goes down gracefully — an intentional close or user-disable of a connected source (spec 023). Fires for every applicable source; read e.Source to branch. The method must accept (IScriptContext, ConnectionHealthContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a connection attempt fails (spec 023). Fires once per outage (the first failed attempt); retries do not re-fire, though the attempt count still increments internally. Fires for every applicable source; read e.Source to branch. The method must accept (IScriptContext, ConnectionHealthContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a monitored socket connection drops abnormally and does not recover within the debounce grace (spec 023). Never fires for spotify (no socket — strict matrix). Fires for every other applicable source; read e.Source to branch. The method must accept (IScriptContext, ConnectionHealthContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a monitored connection that was Lost auto-reconnects (spec 023); e.Downtime carries how long it was interrupted. Never fires for gateway (a reconnecting client is a fresh OnConnectionUp — strict matrix). Fires for every other applicable source; read e.Source to branch. The method must accept (IScriptContext, ConnectionHealthContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a monitored connection comes up — a source transitions to Connected after boot (spec 023). Fires for every applicable source (twitch/obs/spotify/gateway); read e.Source to branch. The method must accept (IScriptContext, ConnectionHealthContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a donation is received through Tiltify. The method must accept (IScriptContext, DonationContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when an external tool sends a trigger command carrying this Name over the integration gateway (spec 022). The method must accept (IScriptContext, ExternalCommandContext); see OnChatMessageAttribute for the supported return types. Only scripts that declare a command are remotely invocable — this attribute is the opt-in capability boundary for the gateway. The name is matched case-insensitively.
  • Marks a method as a handler for a chatter's first message of the session. The method must accept (IScriptContext, FirstTimeChatterContext). First-time status is derived in-process (there is no reliable wire flag) from the shared first-seen tracker — the same one the Welcome Message feature uses — and is reset when the stream goes online, so it fires at most once per chatter per session.
  • Marks a method as a handler fired when a viewer follows the channel. The method must accept (IScriptContext, FollowContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a viewer gifts a community subscription bundle (the parent summary that announces how many gifts follow). The method must accept (IScriptContext, GiftSubContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a hype train begins. The method must accept (IScriptContext, HypeTrainContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a hype train ends. The method must accept (IScriptContext, HypeTrainContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a hype train advances. The method must accept (IScriptContext, HypeTrainContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler for a chat message that matches a keyword or regular expression. The method must accept (IScriptContext, KeywordMatchContext); the context carries the matched text and the originating message. A compiled graph bakes the authored pattern + match mode (keyword/regex) as the guard, so each handler responds only to its own pattern. Keyword matching runs on the chat firehose, so graphs of this trigger are dispatched on the high-volume (drop-oldest) lane.
  • Marks a method as a handler fired when a Tiltify fundraising milestone is reached. The method must accept (IScriptContext, MilestoneContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when an OBS source filter is enabled or disabled. The method must accept (IScriptContext, ObsFilterContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when OBS recording starts or stops. The method must accept (IScriptContext, ObsRecordStateContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when OBS switches its active program scene. The method must accept (IScriptContext, ObsSceneChangedContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a source's visibility toggles in an OBS scene. The method must accept (IScriptContext, ObsSourceVisibilityContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a poll begins. The method must accept (IScriptContext, PollContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a poll ends. The method must accept (IScriptContext, PollContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a prediction begins. The method must accept (IScriptContext, PredictionContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a prediction ends. The method must accept (IScriptContext, PredictionContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a prediction locks. The method must accept (IScriptContext, PredictionContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when another channel raids in. The method must accept (IScriptContext, RaidContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when this channel starts an outgoing raid. The method must accept (IScriptContext, RaidStartedContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired on a cron schedule. The method must accept (IScriptContext, ScheduleContext); the context carries the fire instant. A compiled graph carries its authored cron expression as graph metadata — the host registers a durable scheduled job that fires the handler at each occurrence. Missed occurrences (host offline) are skipped, not caught up.
  • Marks a method as a handler fired when this channel sends a shoutout. The method must accept (IScriptContext, ShoutoutCreatedContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when this channel receives a shoutout. The method must accept (IScriptContext, ShoutoutReceivedContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when Spotify playback starts or pauses. The method must accept (IScriptContext, SpotifyPlaybackChangedContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when the now-playing Spotify track changes. The method must accept (IScriptContext, SpotifyTrackChangedContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when an Elgato Stream Deck keypad button assigned to the Corvus action is pressed. The method must accept (IScriptContext, StreamDeckButtonContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when the broadcaster goes offline. The method must accept (IScriptContext, StreamLifecycleContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when the broadcaster goes live. The method must accept (IScriptContext, StreamLifecycleContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when OBS starts the streaming output. The method must accept (IScriptContext, ObsStreamContext). See OnChatMessageAttribute for the supported return types.
  • Marks a method as a handler fired when a viewer subscribes (standalone or gifted). The method must accept (IScriptContext, SubscribeContext). See OnChatMessageAttribute for the supported return types.
  • Carries a scheduled handler's cron expression onto the compiled method (spec 020 P4). Emitted onto an [OnSchedule] handler from the trigger node's authored cronExpression; the host reads it to register a durable scheduled job that fires the handler at each occurrence. Standard 5-field cron, already validated at graph-save time.
  • Sets the default dispatch concurrency for every trigger handler in a script class, so authors don't repeat the same knobs on each ScriptTriggerAttribute. A value set on an individual trigger attribute overrides the class default; the class default overrides the host's.
  • Declares a script's identity metadata: a display name plus optional description, version, author, and tags. Surfaced in the desktop and used as telemetry tags. The runtime-computed equivalent is IScriptDescriptor; when a script provides both, the interface wins.
  • Base class for all script trigger attributes (OnChatMessageAttribute, OnStreamOnlineAttribute, OnStreamOfflineAttribute, etc.). Exposes the parallelism and timeout knobs that every trigger supports.
  • Marks a trigger handler that returns IAsyncEnumerable<ScriptProgress> (or IAsyncEnumerable<ScriptOutcome>) and bounds how long it may stream. The host already detects a streaming handler from its return type; this attribute is how you cap a long-running generator so a runaway stream can't pin a dispatch worker.
  • Opts a handler (or every handler in a class) into a dedicated tracing span around each invocation, with additional telemetry tags. Use it on the handful of handlers you want to follow end-to-end in the Aspire dashboard without turning on verbose tracing globally.
  • Declares per-trigger firing controls on a handler: a cooldown (global and/or per-user), a debounce window, a dedupe key, and a max-concurrency cap. The host enforces them around the invocation — a suppressed fire (cooldown active, duplicate key) simply never runs; a debounced burst is coalesced to its latest payload. All properties default to "off", so an attribute with no values is inert.

Context records

34
  • Context bound to an OnBanAttribute handler. Covers both bans and timeouts: IsPermanent is true for a ban, and EndsAt is the timeout expiry (MinValue for a permanent ban).
  • Context bound to an OnBitsInMessageAttribute handler. Bits is the amount cheered in the message and Message is the message text. A compiled graph's emitted guard fires only at or above the authored minimum-bits threshold.
  • Context bound to an OnCaptionAttribute handler: a finalized caption line. Only final lines reach here; an authored keyword filter (if any) is applied by the compiled handler's guard.
  • Context bound to an OnChannelPointRedeemAttribute handler. Carries the redeeming viewer, the reward they redeemed (RewardTitle/RewardCost), and any text they typed into the reward (UserInput).
  • Context bound to an OnChatCommandAttribute handler. Command is the command word as typed (without the prefix); ArgumentText is everything after it (trimmed) and Arguments is that text split on whitespace. The role flags reflect the sender's chat badges so a handler (or a compiled graph's emitted guard) can apply a minimum-role gate.
  • Context bound to an OnCheerAttribute handler. User is null when the cheer is anonymous. Bits is the amount cheered and Message is the accompanying chat message.
  • The one event context bound for every connection-health handler (spec 023) — [OnConnectionUp], [OnConnectionDown], [OnConnectionLost], [OnConnectionRestored], [OnConnectionFailed]. A trigger fires for every applicable source; a hand-written handler reads Source and branches, while a graph node bakes the chosen source as a compiled guard (if (!string.Equals(e.Source, "obs", …)) return;). Per-trigger-optional fields are populated only where meaningful: each node surfaces only its relevant output ports. Source is the source name ("Twitch"/"Obs"/"Spotify"/"Gateway") as a string — the scripting SDK deliberately does not expose the server-side ConnectionSource enum, so the script surface stays free of internal Domain types.
  • Context bound to an OnDonationAttribute handler. Carries a Tiltify donation: the donor's display name (or "Anonymous"), the amount + currency, and the optional message.
  • The event context bound for an [OnExternalCommand] handler (spec 022). Command is the invoked command name; Args is the flat string→string argument bag the external gateway client sent (empty when none).
  • Context bound to an OnFirstTimeChatterAttribute handler. Carries the chatter and the message that was their first of the session. Fires at most once per chatter per session (the first-seen set resets when the stream goes online).
  • Context bound to an OnFollowAttribute handler. Carries only the public follow fields a graph/script needs — the follower's identity, the channel id, and when it happened.
  • Context bound to an OnGiftSubAttribute handler — the parent summary of a community gift bundle. Gifter is null when the gift is anonymous. Total is how many subscriptions were gifted; Tier is the normalized sub tier (1, 2, or 3).
  • Context bound to an OnHypeTrainBeginAttribute / OnHypeTrainProgressAttribute / OnHypeTrainEndAttribute handler. Progress and Goal are 0 on the end event (it reports only the final Level and Total).
  • Context bound to an OnKeywordMatchAttribute handler. Match is the matched text — the keyword itself in keyword mode, or the regex's overall match in regex mode — and Message is the full originating message. The role flags reflect the sender's chat badges.
  • Context bound to an OnMilestoneReachedAttribute handler. Carries a reached Tiltify fundraising milestone: its name, threshold amount + currency, and when it was reached.
  • Context bound to an OnObsFilterChangedAttribute handler: a source filter was enabled or disabled.
  • Context bound to an OnObsRecordStateChangedAttribute handler: OBS recording started or stopped. State is the raw OBS output state string.
  • The event context bound for an OnObsSceneChanged handler.
  • Context bound to an OnObsSourceVisibilityChangedAttribute handler: a source's visibility toggled in a scene. OBS reports the numeric SceneItemId, not the source name.
  • The event context bound for an OnStreamStarted handler. StateName is the raw OBS output-state string (e.g. OBS_WEBSOCKET_OUTPUT_STARTED).
  • Context bound to an OnPollBeginAttribute / OnPollEndAttribute handler. WinningChoice / WinningVotes are only meaningful on the end event (empty / 0 at begin).
  • Context bound to an OnPredictionBeginAttribute / OnPredictionLockAttribute / OnPredictionEndAttribute handler. WinningOutcome is only set on the end event (empty at begin/lock).
  • Context bound to an OnRaidAttribute handler. Describes an incoming raid: the raiding channel and how many Viewers it brought.
  • Context bound to an OnRaidStartedAttribute handler. Describes an outgoing raid this channel started: the TargetId channel it raided and how many Viewers it took.
  • Context bound to an OnScheduleAttribute handler. FiredAt is the instant the scheduled occurrence fired (UTC). A scheduled graph runs for the broadcaster the host is signed in as; there is no triggering user.
  • Context bound to an OnShoutoutCreatedAttribute handler: a shoutout this channel sent to ToBroadcasterId.
  • Context bound to an OnShoutoutReceivedAttribute handler: a shoutout this channel received from FromBroadcasterId.
  • Context bound to an OnSpotifyPlaybackChangedAttribute handler: playback started or paused.
  • Context bound to an OnSpotifyTrackChangedAttribute handler: the now-playing track changed. Derived from the poller, which has no stable track id — a track is identified by title + artist.
  • The event context bound for an OnStreamDeckButtonPress handler. Context is the Elgato action instance id — pass it to IStreamDeckApi reverse commands (e.g. set the pressed key's title) to target the same key the press came from.
  • Context bound to an OnSubscribeAttribute handler. Tier is the normalized sub tier (1, 2, or 3). IsGift is true when this subscription was gifted rather than purchased by the subscriber.