webhooks #1

Merged
GKaszewski merged 6 commits from feature/webhooks into master 2026-03-15 23:51:42 +00:00
4 changed files with 122 additions and 19 deletions
Showing only changes of commit dfebcc11ef - Show all commits

View File

@@ -756,6 +756,8 @@ interface EditChannelSheetProps {
logo?: string | null;
logo_position?: LogoPosition;
logo_opacity?: number;
webhook_url?: string | null;
webhook_poll_interval_secs?: number;
},
) => void;
isPending: boolean;
@@ -787,6 +789,8 @@ export function EditChannelSheet({
const [logo, setLogo] = useState<string | null>(null);
const [logoPosition, setLogoPosition] = useState<LogoPosition>("top_right");
const [logoOpacity, setLogoOpacity] = useState(100);
const [webhookUrl, setWebhookUrl] = useState("");
const [webhookPollInterval, setWebhookPollInterval] = useState<number | "">(5);
const [selectedBlockId, setSelectedBlockId] = useState<string | null>(null);
const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
const fileInputRef = useRef<HTMLInputElement>(null);
@@ -804,6 +808,8 @@ export function EditChannelSheet({
setLogo(channel.logo ?? null);
setLogoPosition(channel.logo_position ?? "top_right");
setLogoOpacity(Math.round((channel.logo_opacity ?? 1) * 100));
setWebhookUrl(channel.webhook_url ?? "");
setWebhookPollInterval(channel.webhook_poll_interval_secs ?? 5);
setSelectedBlockId(null);
setFieldErrors({});
}
@@ -836,6 +842,10 @@ export function EditChannelSheet({
logo: logo,
logo_position: logoPosition,
logo_opacity: logoOpacity / 100,
webhook_url: webhookUrl || null,
...(webhookUrl
? { webhook_poll_interval_secs: webhookPollInterval === "" ? 5 : webhookPollInterval }
: {}),
});
};
@@ -1085,6 +1095,28 @@ export function EditChannelSheet({
onChange={setRecyclePolicy}
/>
</section>
{/* Webhook */}
<section className="space-y-3">
<h3 className="text-xs font-semibold uppercase tracking-wider text-zinc-500">Webhook</h3>
<Field label="Webhook URL" hint="POST events to this URL on broadcast changes">
<TextInput
value={webhookUrl}
onChange={setWebhookUrl}
placeholder="https://example.com/webhook"
/>
</Field>
{webhookUrl && (
<Field label="Poll interval (seconds)" hint="How often to check for broadcast changes">
<NumberInput
value={webhookPollInterval}
onChange={setWebhookPollInterval}
min={1}
placeholder="5"
/>
</Field>
)}
</section>
</div>
{/* Footer */}

View File

@@ -147,6 +147,8 @@ export interface ChannelResponse {
logo?: string | null;
logo_position: LogoPosition;
logo_opacity: number;
webhook_url?: string | null;
webhook_poll_interval_secs?: number;
created_at: string;
updated_at: string;
}
@@ -157,6 +159,8 @@ export interface CreateChannelRequest {
description?: string;
access_mode?: AccessMode;
access_password?: string;
webhook_url?: string;
webhook_poll_interval_secs?: number;
}
export interface UpdateChannelRequest {
@@ -173,6 +177,9 @@ export interface UpdateChannelRequest {
logo?: string | null;
logo_position?: LogoPosition;
logo_opacity?: number;
/** null = clear webhook */
webhook_url?: string | null;
webhook_poll_interval_secs?: number;
}
// Media & Schedule

View File

@@ -16,6 +16,7 @@
"cmdk": "^1.1.1",
"date-fns": "^4.1.0",
"embla-carousel-react": "^8.6.0",
"hls.js": "^1.6.15",
"input-otp": "^1.4.2",
"lucide-react": "^0.577.0",
"next": "16.1.6",
@@ -30,17 +31,20 @@
"sonner": "^2.0.7",
"tailwind-merge": "^3.5.0",
"tw-animate-css": "^1.4.0",
"vaul": "^1.1.2"
"vaul": "^1.1.2",
"zod": "^4.3.6"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/chromecast-caf-sender": "^1.0.11",
"@types/hls.js": "^1.0.0",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.1.6",
"tailwindcss": "^4",
"typescript": "^5"
"typescript": "5.9.3"
}
},
"node_modules/@alloc/quick-lru": {
@@ -1493,13 +1497,6 @@
"version": "1.0.0",
"license": "MIT"
},
"node_modules/@modelcontextprotocol/sdk/node_modules/zod": {
"version": "4.3.6",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/@mswjs/interceptors": {
"version": "0.41.3",
"license": "MIT",
@@ -3551,6 +3548,27 @@
"tslib": "^2.4.0"
}
},
"node_modules/@types/chrome": {
"version": "0.1.37",
"resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.1.37.tgz",
"integrity": "sha512-IJE4ceuDO7lrEuua7Pow47zwNcI8E6qqkowRP7aFPaZ0lrjxh6y836OPqqkIZeTX64FTogbw+4RNH0+QrweCTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/filesystem": "*",
"@types/har-format": "*"
}
},
"node_modules/@types/chromecast-caf-sender": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@types/chromecast-caf-sender/-/chromecast-caf-sender-1.0.11.tgz",
"integrity": "sha512-Pv3xvNYtxD/cTM/tKfuZRlLasvpxAm+CFni0GJd6Cp8XgiZS9g9tMZkR1uymsi5fIFv057SZKKAWVFFgy7fJtw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/chrome": "*"
}
},
"node_modules/@types/d3-array": {
"version": "3.2.2",
"license": "MIT"
@@ -3601,6 +3619,41 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/filesystem": {
"version": "0.0.36",
"resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz",
"integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/filewriter": "*"
}
},
"node_modules/@types/filewriter": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz",
"integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/har-format": {
"version": "1.2.16",
"resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz",
"integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/hls.js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/hls.js/-/hls.js-1.0.0.tgz",
"integrity": "sha512-EGY2QJefX+Z9XH4PAxI7RFoNqBlQEk16UpYR3kbr82CIgMX5SlMe0PjFdFV0JytRhyVPQCiwSyONuI6S1KdSag==",
"deprecated": "This is a stub types definition. hls.js provides its own type definitions, so you do not need this installed.",
"dev": true,
"license": "MIT",
"dependencies": {
"hls.js": "*"
}
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"dev": true,
@@ -5862,14 +5915,6 @@
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-react-hooks/node_modules/zod": {
"version": "4.3.6",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/eslint-plugin-react/node_modules/resolve": {
"version": "2.0.0-next.6",
"dev": true,
@@ -6654,6 +6699,12 @@
"hermes-estree": "0.25.1"
}
},
"node_modules/hls.js": {
"version": "1.6.15",
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.15.tgz",
"integrity": "sha512-E3a5VwgXimGHwpRGV+WxRTKeSp2DW5DI5MWv34ulL3t5UNmyJWCQ1KmLEHbYzcfThfXG8amBL+fCYPneGHC4VA==",
"license": "Apache-2.0"
},
"node_modules/hono": {
"version": "4.12.7",
"license": "MIT",
@@ -9321,6 +9372,15 @@
"shadcn": "dist/index.js"
}
},
"node_modules/shadcn/node_modules/zod": {
"version": "3.25.76",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/sharp": {
"version": "0.34.5",
"hasInstallScript": true,
@@ -10005,6 +10065,8 @@
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"bin": {
@@ -10525,7 +10587,9 @@
}
},
"node_modules/zod": {
"version": "3.25.76",
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"

View File

@@ -45,7 +45,7 @@
"eslint": "^9",
"eslint-config-next": "16.1.6",
"tailwindcss": "^4",
"typescript": "^5"
"typescript": "5.9.3"
},
"ignoreScripts": [
"sharp",