import type { InsertPayload, PlaybackMethod, VideoSource } from './types'; /** * Contexts where the ShortCode tab is shown (no easy raw shortcode paste elsewhere). */ export function isShortcodeTabContext( context?: string ): boolean { if ( ! context ) { return false; } if ( context === 'featured' || context === 'widget' ) { return true; } return context.startsWith( 'block-' ) || context.startsWith( 'legacy-block-' ); } export function getVideoPreviewUrl( sources?: VideoSource[] ): string | null { if ( ! sources?.length ) { return null; } const mp4 = sources.find( ( source ) => { const type = ( source.type || '' ).toLowerCase(); const file = ( source.file || '' ).toLowerCase(); const label = ( source.label || '' ).toLowerCase(); return type.includes( 'mp4' ) || file.includes( '.mp4' ) || label.includes( 'mp4' ); } ); if ( mp4?.file ) { return mp4.file; } const playable = sources.find( ( source ) => source.file ); return playable?.file || null; } export function formatDuration( value?: string ): string { if ( ! value ) { return ''; } const sec = parseInt( value, 10 ); const hours = Math.floor( sec / 3600 ); const minutes = Math.floor( ( sec - hours * 3600 ) / 60 ); const seconds = sec - hours * 3600 - minutes * 60; const pad = ( n: number ) => ( n < 10 ? `0${ n }` : String( n ) ); return `${ pad( hours ) }:${ pad( minutes ) }:${ pad( seconds ) }`; } export function formatDate( timestamp?: number | null ): string { if ( ! timestamp ) { return ''; } const date = new Date( timestamp * 1000 ); return date.toLocaleDateString( undefined, { month: 'short', day: 'numeric', year: 'numeric' } ); } const ALLOWED_SHORTCODE_TAGS = new Set( [ 'voltax', 'mm-video', 'sendtonews' ] ); export function extractShortcodeTag( value: string ): string | undefined { const match = value.trim().match( /^\[\s*([a-z0-9_-]+)/i ); return match?.[ 1 ]?.toLowerCase(); } export function isAllowedShortcodeInput( value: string ): boolean { const trimmed = value.trim(); if ( ! trimmed ) { return false; } if ( ! trimmed.startsWith( '[' ) ) { return true; } const tag = extractShortcodeTag( trimmed ); return !! tag && ALLOWED_SHORTCODE_TAGS.has( tag ); } /** * STN keys are hyphenated (e.g. abcded-6273668-9994). * Voltax content IDs are contiguous alphanumerics (e.g. 01ab7f7d). */ export function isStnKey( value: string ): boolean { return /^[a-z0-9]+(?:-[a-z0-9]+)+$/i.test( value.trim() ); } /** * Normalize ShortCode-tab input into a full shortcode. * Supports: * - full [voltax], [mm-video], [sendtonews] shortcodes * - raw STN keys → [sendtonews type="float" key="…"] * - raw Voltax IDs → [voltax id="…"] */ export function resolveShortcodeInput( value: string ): string | null { const trimmed = value.trim(); if ( ! trimmed || ! isAllowedShortcodeInput( trimmed ) ) { return null; } if ( trimmed.startsWith( '[' ) ) { return trimmed; } const safeToken = trimmed.replace( /["\]]/g, '' ); if ( ! safeToken ) { return null; } if ( isStnKey( safeToken ) ) { return `[sendtonews type="float" key="${ safeToken }"]`; } return `[voltax id="${ safeToken }"]`; } export function normalizePlaybackmethod( value?: string ): PlaybackMethod { return value === 'clicktoplay' ? 'clicktoplay' : 'autoplay'; } /** * Playback UI applies to Voltax library video/playlist picks only. * ShortCode-tab and STN-key inserts carry their own shortcode attrs. */ export function supportsPlaybackmethodUi( payload: InsertPayload | null ): boolean { if ( ! payload?.id?.trim() || payload.shortcode?.trim() ) { return false; } return ! isStnKey( payload.id ); } export function buildShortcode( payload: InsertPayload ): string { if ( payload.shortcode?.trim() ) { return payload.shortcode.trim(); } if ( payload.id?.trim() ) { const id = payload.id.trim(); if ( isStnKey( id ) ) { return `[sendtonews type="float" key="${ id }"]`; } const method = normalizePlaybackmethod( payload.playbackmethod ); return `[voltax id="${ id }" playbackmethod="${ method }"]`; } return ''; } export function isInsertPayloadValid( payload: InsertPayload | null ): boolean { if ( ! payload ) { return false; } const shortcode = buildShortcode( payload ); return !! shortcode && isAllowedShortcodeInput( shortcode ); } export function extractVoltaxContentId( shortcode: string ): string | undefined { const voltaxMatch = shortcode.match( /\[voltax[^\]]*\bid=["']([^"']+)["']/i ); if ( voltaxMatch?.[ 1 ] ) { return voltaxMatch[ 1 ]; } const mmVideoMatch = shortcode.match( /\[mm-video[^\]]*\bid=["']([^"']+)["']/i ); return mmVideoMatch?.[ 1 ]; }