mirror of
https://github.com/yusufipk/YTChatHub.git
synced 2026-09-11 10:56:17 +00:00
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.
70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
export type Badge = {
|
|
type: 'moderator' | 'member' | 'verified' | 'owner' | 'custom';
|
|
label?: string;
|
|
imageUrl?: string;
|
|
};
|
|
|
|
export type SuperChatInfo = {
|
|
amount: string;
|
|
currency: string;
|
|
color: string;
|
|
stickerUrl?: string;
|
|
stickerAlt?: string;
|
|
};
|
|
|
|
export type MessageRun = {
|
|
text?: string;
|
|
/** Full destination URL when YouTube rendered this run as a link. The visible text may be truncated. */
|
|
url?: string;
|
|
emojiUrl?: string;
|
|
emojiAlt?: string;
|
|
};
|
|
|
|
export type Poll = {
|
|
id: string;
|
|
active: boolean;
|
|
};
|
|
|
|
export type ChatMessage = {
|
|
id: string;
|
|
author: string;
|
|
authorPhoto?: string;
|
|
authorChannelId?: string;
|
|
text: string;
|
|
runs?: MessageRun[];
|
|
publishedAt: string;
|
|
badges?: Badge[];
|
|
isModerator?: boolean;
|
|
isMember?: boolean;
|
|
isVerified?: boolean;
|
|
superChat?: SuperChatInfo;
|
|
membershipGift?: boolean;
|
|
membershipGiftPurchase?: boolean;
|
|
membershipLevel?: string;
|
|
giftCount?: number;
|
|
leaderboardRank?: number;
|
|
};
|
|
|
|
export type ConnectionState = 'disconnected' | 'connecting' | 'live' | 'reconnecting';
|
|
|
|
export type ConnectionStatus = {
|
|
state: ConnectionState;
|
|
liveId: string | null;
|
|
title?: string | null;
|
|
error?: string | null;
|
|
};
|
|
|
|
/**
|
|
* Events pushed on the single `/events` SSE stream.
|
|
* `init` is sent once per connection with the full current state; the rest are deltas.
|
|
*/
|
|
export type ServerEvent =
|
|
| { type: 'init'; status: ConnectionStatus; messages: ChatMessage[]; selection: ChatMessage | null; poll: Poll | null }
|
|
| { type: 'message'; message: ChatMessage }
|
|
| { type: 'selection'; message: ChatMessage | null }
|
|
| { type: 'poll'; poll: Poll | null }
|
|
| { type: 'status'; status: ConnectionStatus }
|
|
| { type: 'clear' };
|
|
|
|
export type ServerEventType = ServerEvent['type'];
|