Files
chat_grid/client/src/audio/mediaUrl.ts
2026-03-09 04:06:46 -04:00

68 lines
2.5 KiB
TypeScript

const APP_BASE_PATH = import.meta.env.BASE_URL ?? '/';
/** Returns whether a hostname belongs to Dropbox domains that often need proxy support. */
function isDropboxHost(hostname: string): boolean {
const host = hostname.toLowerCase();
return host.endsWith('dropbox.com') || host.endsWith('dropboxusercontent.com');
}
/** Returns whether the URL already points at the local media proxy. */
function isLocalMediaProxyUrl(parsed: URL): boolean {
return parsed.origin === window.location.origin && parsed.pathname.toLowerCase().endsWith('/media_proxy.php');
}
/** Returns whether a direct radio stream URL should use the same-origin media proxy. */
export function shouldProxyRadioStreamUrl(streamUrl: string): boolean {
try {
const parsed = new URL(streamUrl);
if (isLocalMediaProxyUrl(parsed)) {
return false;
}
if (parsed.protocol === 'http:') return true;
if (parsed.protocol === 'https:' && isDropboxHost(parsed.hostname)) return true;
} catch {
return false;
}
return false;
}
/** Returns whether an arbitrary external media URL should be proxied before Web Audio playback. */
export function shouldProxyExternalMediaUrl(streamUrl: string): boolean {
try {
const parsed = new URL(streamUrl);
if (isLocalMediaProxyUrl(parsed)) {
return false;
}
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
return false;
}
return parsed.origin !== window.location.origin;
} catch {
return false;
}
}
/** Builds the same-origin proxy URL for one remote media URL. */
export function getProxyUrlForMedia(streamUrl: string): string {
const normalizedBase = APP_BASE_PATH.endsWith('/') ? APP_BASE_PATH : `${APP_BASE_PATH}/`;
const proxy = new URL(`${normalizedBase}media_proxy.php`, window.location.origin);
proxy.searchParams.set('url', streamUrl);
return proxy.toString();
}
/** Appends a cache-buster to a radio playback URL to avoid stale stream sessions. */
export function freshRadioPlaybackUrl(streamUrl: string): string {
const playbackSource = shouldProxyRadioStreamUrl(streamUrl) ? getProxyUrlForMedia(streamUrl) : streamUrl;
try {
const parsed = new URL(playbackSource);
const hostname = parsed.hostname.toLowerCase();
if (hostname.endsWith('dropbox.com') || hostname.endsWith('dropboxusercontent.com')) {
return playbackSource;
}
} catch {
// Leave non-URL strings to the generic cache-buster behavior below.
}
const separator = playbackSource.includes('?') ? '&' : '?';
return `${playbackSource}${separator}chgrid_start=${Date.now()}`;
}