Add signed media URLs to live WebSocket replies and teach the WebUI to classify and render video attachments, so bot-sent videos can play inline in both live chats and session history. Made-with: Cursor
60 lines
1.2 KiB
TypeScript
60 lines
1.2 KiB
TypeScript
import type { UIMediaAttachment, UIMediaKind } from "@/lib/types";
|
|
|
|
const IMAGE_EXTENSIONS = new Set([
|
|
".png",
|
|
".jpg",
|
|
".jpeg",
|
|
".gif",
|
|
".webp",
|
|
".bmp",
|
|
".ico",
|
|
".tif",
|
|
".tiff",
|
|
]);
|
|
|
|
const VIDEO_EXTENSIONS = new Set([
|
|
".mp4",
|
|
".webm",
|
|
".mov",
|
|
".m4v",
|
|
".avi",
|
|
".mkv",
|
|
".3gp",
|
|
]);
|
|
|
|
function cleanPath(value: string): string {
|
|
return value.split(/[?#]/, 1)[0]?.toLowerCase() ?? "";
|
|
}
|
|
|
|
function extensionOf(value?: string): string {
|
|
if (!value) return "";
|
|
const path = cleanPath(value);
|
|
const dot = path.lastIndexOf(".");
|
|
if (dot < 0) return "";
|
|
return path.slice(dot);
|
|
}
|
|
|
|
export function inferMediaKind(media: { url?: string; name?: string }): UIMediaKind {
|
|
const url = media.url ?? "";
|
|
if (url.startsWith("data:image/")) return "image";
|
|
if (url.startsWith("data:video/")) return "video";
|
|
|
|
const ext = extensionOf(media.name) || extensionOf(url);
|
|
if (IMAGE_EXTENSIONS.has(ext)) return "image";
|
|
if (VIDEO_EXTENSIONS.has(ext)) return "video";
|
|
return "file";
|
|
}
|
|
|
|
export function toMediaAttachment(media: {
|
|
url?: string;
|
|
name?: string;
|
|
kind?: UIMediaKind;
|
|
}): UIMediaAttachment {
|
|
return {
|
|
kind: media.kind ?? inferMediaKind(media),
|
|
url: media.url,
|
|
name: media.name,
|
|
};
|
|
}
|
|
|