Add kirov_reporting script asset tto marketplace

This commit is contained in:
2026-01-13 18:09:52 +01:00
parent 4f1eb2fc82
commit 8dc4cc72e8
11 changed files with 140 additions and 7 deletions

Binary file not shown.

View File

@@ -1,5 +1,4 @@
{
"name": "Chat Overlay",
"description": "Render the last two minutes of Twitch chat messages on the broadcast canvas.",
"broadcaster": "System"
"description": "Render the last two minutes of Twitch chat messages on the broadcast canvas."
}

Binary file not shown.

View File

@@ -0,0 +1,4 @@
{
"name": "Kirov Reporting!",
"description": "Plays kirov_reporting.mp3 whenever !kirov is typed in chat."
}

View File

@@ -0,0 +1,73 @@
const COMMAND = "!kirov";
const COOLDOWN_MS = 5000;
const ATTACHMENT_NAME = "kirov_reporting.mp3";
function normalizeMessage(message) {
return (message || "").trim().toLowerCase();
}
function isCommandMatch(message) {
const normalized = normalizeMessage(message);
if (!normalized.startsWith(COMMAND)) {
return false;
}
return normalized.length === COMMAND.length || normalized.startsWith(`${COMMAND} `);
}
function resolveAttachmentId(assets, state) {
if (state?.attachmentId) {
return state.attachmentId;
}
if (!Array.isArray(assets)) {
return null;
}
const match = assets.find((asset) => asset?.name?.toLowerCase() === ATTACHMENT_NAME);
if (!match?.id) {
return null;
}
state.attachmentId = match.id;
return match.id;
}
function tick(context, state) {
const { chatMessages, assets, now, playAudio } = context;
if (!Array.isArray(chatMessages) || chatMessages.length === 0) {
return;
}
if (typeof playAudio !== "function") {
return;
}
const lastSeen = state.lastChatTimestamp ?? 0;
let latestSeen = lastSeen;
const currentTime = Number.isFinite(now) ? now : 0;
const lastTriggerAt = state.lastTriggerAt ?? -Infinity;
let nextTriggerAt = lastTriggerAt;
let shouldTrigger = false;
chatMessages.forEach((message) => {
const timestamp = message?.timestamp ?? 0;
if (timestamp <= lastSeen) {
return;
}
latestSeen = Math.max(latestSeen, timestamp);
if (!shouldTrigger && isCommandMatch(message?.message)) {
if (currentTime - lastTriggerAt >= COOLDOWN_MS) {
shouldTrigger = true;
}
}
});
state.lastChatTimestamp = latestSeen;
if (!shouldTrigger) {
return;
}
const attachmentId = resolveAttachmentId(assets, state);
if (!attachmentId) {
return;
}
playAudio(attachmentId);
state.lastTriggerAt = currentTime;
}

Binary file not shown.

View File

@@ -1,5 +1,4 @@
{
"name": "Teapot 3D Viewer",
"description": "Renders the classic Utah teapot using a 3D model attachment.",
"broadcaster": "System"
"description": "Renders the classic Utah teapot using a 3D model attachment."
}