mirror of
https://github.com/yusufipk/YTChatHub.git
synced 2026-09-12 03:16:10 +00:00
Rewrite dashboard and overlay, single /events stream, static client served by the backend
Backend: one SSE stream for messages, selection, poll and connection status; reconnect with backoff; no on-disk Innertube session cache; mock only with MOCK_CHAT=1; binds to 127.0.0.1; serves client/out so production runs on one port. Full URLs for links YouTube truncates in chat. Client: components split out, Lucide icons, stream title and status, on-air strip, search, pause, keyboard shortcuts, overlay settings dialog. Overlay themes, position, size, animation and auto-hide via URL, sized for 1080p and scaled with the source. New blueprint theme for the brand background. Removed Tailwind, better-sqlite3, zod, the timezone helpers, Cline memory bank and AGENTS.md. Added ESLint, node:test tests and CI.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
const VIDEO_ID = /^[A-Za-z0-9_-]{11}$/;
|
||||
const YOUTUBE_HOST = /(^|\.)(youtube\.com|youtube-nocookie\.com|youtu\.be)$/;
|
||||
|
||||
/**
|
||||
* Extracts the 11-character video id from a bare id or any YouTube URL
|
||||
* (watch?v=, youtu.be/, /live/, /embed/, with or without scheme). Returns '' for anything else.
|
||||
*/
|
||||
export function extractLiveId(input: string | undefined): string {
|
||||
const trimmed = (input ?? '').trim();
|
||||
if (!trimmed) return '';
|
||||
if (VIDEO_ID.test(trimmed)) return trimmed;
|
||||
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(/^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`);
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
if (!YOUTUBE_HOST.test(url.hostname)) return '';
|
||||
|
||||
const candidate = url.searchParams.get('v') ?? url.pathname.split('/').filter(Boolean).pop() ?? '';
|
||||
return VIDEO_ID.test(candidate) ? candidate : '';
|
||||
}
|
||||
Reference in New Issue
Block a user