import type { ChannelMap } from "./channels.js"; import type { Nullable } from "./shared.js"; /** * Available channel selection strategies. Each strategy implements a different approach to finding and selecting channels in a multi-channel player UI. * * - "directvGrid": Tune via webpack injection — captures __webpack_require__, extracts the Redux store from the React fiber tree, matches by channel name, and * dispatches playConsumable. Falls back to logo aria-label click when the interceptor fails. Used by DirecTV Stream. * - "foxGrid": Find channel by station code in a non-virtualized guide grid, click the channel logo button via DOM .click(). Used by Fox.com. * - "guideGrid": Find channel by exact-matching image alt text, click nearest clickable ancestor. Optionally clicks a tab to reveal the list first. Used by Hulu * Live TV. * - "hboGrid": Discover the HBO tab page URL from the homepage menu bar, scrape the live channel tile rail for a matching channel name, and navigate to the watch * URL. Caches the tab URL across tunes with stale-cache fallback. Used by HBO Max. * - "none": No channel selection needed (single-channel sites). This is the default. * - "slingGrid": Find channel by data-testid in a virtualized A-Z guide grid, scroll via binary search on .guide-cell scrollTop, click the on-now program * cell. Used by Sling TV. * - "spectrumGrid": Find channel by callsign or display name in a non-virtualized AngularJS guide grid, extract the Gracenote tmsid from channel logo URLs, * and navigate directly to the watch URL. Caches all ~442 streamable channels on first tune. Used by Spectrum TV. * - "thumbnailRow": Find channel element using the profile's matchSelector (defaults to image URL matching), click adjacent element on the same row. Used by * USA Network. * - "tileClick": Find channel element using the profile's matchSelector (defaults to image URL matching), click tile, then optionally click play button if * playSelector is configured. Used by Disney+. * - "youtubeGrid": Find channel by aria-label in a non-virtualized EPG grid, extract the watch URL, and navigate directly. Used by YouTube TV. */ export type ChannelSelectionStrategy = "directvGrid" | "foxGrid" | "guideGrid" | "hboGrid" | "none" | "slingGrid" | "spectrumGrid" | "thumbnailRow" | "tileClick" | "youtubeGrid"; /** * Configuration for channel selection behavior within a site profile. */ export interface ChannelSelectionConfig { listSelector?: string; matchSelector?: string; playSelector?: string; scrollSelector?: string; scrollTarget?: string; scrollToBottom?: boolean; strategy: ChannelSelectionStrategy; } /** * UI category for profile grouping in dropdowns and reference documentation. Profiles are grouped by their fullscreen mechanism and special characteristics. * - "api": Profiles using the JavaScript fullscreen API (including embedded iframe and click-to-play variants). * - "custom": User-defined profiles created via the profile builder wizard or imported from provider packs. * - "keyboard": Profiles using keyboard shortcuts (typically the 'f' key) for fullscreen. * - "multiChannel": Multi-channel profiles requiring a channel selector for tile or thumbnail-based channel selection. * - "special": Special-purpose profiles like static page capture. */ export type ProfileCategory = "api" | "custom" | "keyboard" | "multiChannel" | "special"; /** * Site profile definition with optional flags. All flags are optional because profiles can inherit from other profiles, and only the flags that differ from the * parent need to be specified. The DEFAULT_SITE_PROFILE provides baseline values for any flags not set through inheritance. */ export interface SiteProfile { category?: ProfileCategory; channelSelection?: ChannelSelectionConfig; channelSelector?: Nullable; clickSelector?: Nullable; clickToPlay?: boolean; description?: string; extends?: string; summary?: string; fullscreenKey?: Nullable; fullscreenSelector?: Nullable; hideSelector?: Nullable; lockVolumeProperties?: boolean; needsIframeHandling?: boolean; noVideo?: boolean; selectReadyVideo?: boolean; useRequestFullscreen?: boolean; waitForNetworkIdle?: boolean; } /** * Fully-resolved site profile with all flags having concrete values. After resolving inheritance chains and applying defaults, every flag has a definite boolean * or string value. This interface is used by stream handling code that needs to check profile flags without worrying about undefined values. */ export interface ResolvedSiteProfile { channelSelection: ChannelSelectionConfig; channelSelector: Nullable; clickSelector: Nullable; clickToPlay: boolean; fullscreenKey: Nullable; fullscreenSelector: Nullable; hideSelector: Nullable; lockVolumeProperties: boolean; maxContinuousPlayback: Nullable; needsIframeHandling: boolean; noVideo: boolean; selectReadyVideo: boolean; useRequestFullscreen: boolean; waitForNetworkIdle: boolean; } /** * Result of resolving a site profile. Includes both the resolved profile configuration and the name of the profile that was matched. The name indicates whether the * profile came from a channel hint, domain-based autodetection, or the default fallback. */ export interface ProfileResolutionResult { profile: ResolvedSiteProfile; profileName: string; } /** * Domain-level configuration associating domain patterns with site profiles and provider display names. Each entry can specify a site profile for behavior * configuration and/or a provider display name for friendly UI labels. Used by both built-in domain mappings in sites.ts and user-defined mappings in profiles.json. */ export interface DomainConfig { loginUrl?: string; maxContinuousPlayback?: number; profile?: string; provider?: string; providerTag?: string; } /** * Storage format for profiles.json. Contains user-defined site profiles and domain mappings that extend or override the built-in configurations. */ export interface UserProfilesFile { domains?: Record; profiles?: Record; } /** * Result of loading user profiles from the profiles.json file. */ export interface UserProfilesLoadResult { domains: Record; parseError: boolean; parseErrorMessage?: string; profiles: Record; } /** * Provider pack distribution format. Bundles a profile, domain mapping(s), and optionally channels for a streaming provider into a single JSON file. On import, * its contents are split and written to profiles.json and channels.json. */ export interface ProviderPack { channels?: ChannelMap; domains?: Record; name: string; profiles: Record; version: number; } /** * Validation result for profile and domain imports. */ export interface ProfilesValidationResult { domains: Record; errors: string[]; profiles: Record; valid: boolean; }