prismcast 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +18 -1
- package/dist/app.js.map +1 -1
- package/dist/browser/cdp.d.ts +2 -1
- package/dist/browser/cdp.js +44 -23
- package/dist/browser/cdp.js.map +1 -1
- package/dist/browser/channelSelection.d.ts +45 -1
- package/dist/browser/channelSelection.js +164 -27
- package/dist/browser/channelSelection.js.map +1 -1
- package/dist/browser/display.d.ts +0 -4
- package/dist/browser/display.js +0 -7
- package/dist/browser/display.js.map +1 -1
- package/dist/browser/index.d.ts +5 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/precaching.d.ts +5 -0
- package/dist/browser/precaching.js +112 -0
- package/dist/browser/precaching.js.map +1 -0
- package/dist/browser/tuning/directv.d.ts +2 -0
- package/dist/browser/tuning/directv.js +723 -0
- package/dist/browser/tuning/directv.js.map +1 -0
- package/dist/browser/tuning/fox.d.ts +2 -2
- package/dist/browser/tuning/fox.js +141 -22
- package/dist/browser/tuning/fox.js.map +1 -1
- package/dist/browser/tuning/hbo.d.ts +2 -2
- package/dist/browser/tuning/hbo.js +110 -41
- package/dist/browser/tuning/hbo.js.map +1 -1
- package/dist/browser/tuning/hulu.d.ts +2 -2
- package/dist/browser/tuning/hulu.js +537 -211
- package/dist/browser/tuning/hulu.js.map +1 -1
- package/dist/browser/tuning/sling.d.ts +2 -2
- package/dist/browser/tuning/sling.js +200 -56
- package/dist/browser/tuning/sling.js.map +1 -1
- package/dist/browser/tuning/youtubeTv.d.ts +2 -2
- package/dist/browser/tuning/youtubeTv.js +243 -57
- package/dist/browser/tuning/youtubeTv.js.map +1 -1
- package/dist/browser/video.d.ts +1 -1
- package/dist/browser/video.js +4 -2
- package/dist/browser/video.js.map +1 -1
- package/dist/channels/index.js +280 -34
- package/dist/channels/index.js.map +1 -1
- package/dist/config/health.d.ts +78 -0
- package/dist/config/health.js +202 -0
- package/dist/config/health.js.map +1 -0
- package/dist/config/paths.d.ts +10 -0
- package/dist/config/paths.js +14 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/config/profiles.d.ts +6 -4
- package/dist/config/profiles.js +65 -14
- package/dist/config/profiles.js.map +1 -1
- package/dist/config/providerPacks.d.ts +46 -0
- package/dist/config/providerPacks.js +200 -0
- package/dist/config/providerPacks.js.map +1 -0
- package/dist/config/providers.d.ts +47 -6
- package/dist/config/providers.js +211 -17
- package/dist/config/providers.js.map +1 -1
- package/dist/config/sites.d.ts +1 -12
- package/dist/config/sites.js +40 -7
- package/dist/config/sites.js.map +1 -1
- package/dist/config/userChannels.d.ts +41 -19
- package/dist/config/userChannels.js +152 -35
- package/dist/config/userChannels.js.map +1 -1
- package/dist/config/userConfig.d.ts +5 -1
- package/dist/config/userConfig.js +58 -6
- package/dist/config/userConfig.js.map +1 -1
- package/dist/config/userProfiles.d.ts +81 -0
- package/dist/config/userProfiles.js +424 -0
- package/dist/config/userProfiles.js.map +1 -0
- package/dist/routes/config/channels/index.d.ts +3 -0
- package/dist/routes/config/channels/index.js +3 -0
- package/dist/routes/config/channels/index.js.map +1 -0
- package/dist/routes/config/channels/routes.d.ts +6 -0
- package/dist/routes/config/channels/routes.js +797 -0
- package/dist/routes/config/channels/routes.js.map +1 -0
- package/dist/routes/config/channels/table.d.ts +46 -0
- package/dist/routes/config/channels/table.js +811 -0
- package/dist/routes/config/channels/table.js.map +1 -0
- package/dist/routes/config/index.d.ts +37 -0
- package/dist/routes/config/index.js +81 -0
- package/dist/routes/config/index.js.map +1 -0
- package/dist/routes/config/providers.d.ts +18 -0
- package/dist/routes/config/providers.js +573 -0
- package/dist/routes/config/providers.js.map +1 -0
- package/dist/routes/config/settings.d.ts +39 -0
- package/dist/routes/config/settings.js +820 -0
- package/dist/routes/config/settings.js.map +1 -0
- package/dist/routes/index.d.ts +3 -2
- package/dist/routes/index.js +7 -4
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/playlist.d.ts +5 -1
- package/dist/routes/playlist.js +32 -7
- package/dist/routes/playlist.js.map +1 -1
- package/dist/routes/providers.d.ts +6 -0
- package/dist/routes/providers.js +166 -0
- package/dist/routes/providers.js.map +1 -0
- package/dist/routes/root/content.d.ts +32 -0
- package/dist/routes/root/content.js +857 -0
- package/dist/routes/root/content.js.map +1 -0
- package/dist/routes/root/index.js +197 -0
- package/dist/routes/root/index.js.map +1 -0
- package/dist/routes/root/scripts/channels.d.ts +1 -0
- package/dist/routes/root/scripts/channels.js +745 -0
- package/dist/routes/root/scripts/channels.js.map +1 -0
- package/dist/routes/root/scripts/config.d.ts +1 -0
- package/dist/routes/root/scripts/config.js +1662 -0
- package/dist/routes/root/scripts/config.js.map +1 -0
- package/dist/routes/root/scripts/index.d.ts +3 -0
- package/dist/routes/root/scripts/index.js +8 -0
- package/dist/routes/root/scripts/index.js.map +1 -0
- package/dist/routes/root/scripts/status.d.ts +1 -0
- package/dist/routes/root/scripts/status.js +436 -0
- package/dist/routes/root/scripts/status.js.map +1 -0
- package/dist/routes/root/styles.d.ts +5 -0
- package/dist/routes/root/styles.js +447 -0
- package/dist/routes/root/styles.js.map +1 -0
- package/dist/routes/theme.js +7 -1
- package/dist/routes/theme.js.map +1 -1
- package/dist/routes/ui.js +8 -3
- package/dist/routes/ui.js.map +1 -1
- package/dist/service/commands.d.ts +5 -3
- package/dist/service/commands.js +117 -33
- package/dist/service/commands.js.map +1 -1
- package/dist/service/generators.d.ts +27 -0
- package/dist/service/generators.js +97 -6
- package/dist/service/generators.js.map +1 -1
- package/dist/streaming/hls.js +18 -1
- package/dist/streaming/hls.js.map +1 -1
- package/dist/streaming/lifecycle.js +1 -1
- package/dist/streaming/lifecycle.js.map +1 -1
- package/dist/streaming/monitor.d.ts +1 -38
- package/dist/streaming/monitor.js +2 -289
- package/dist/streaming/monitor.js.map +1 -1
- package/dist/streaming/recovery.d.ts +143 -0
- package/dist/streaming/recovery.js +286 -0
- package/dist/streaming/recovery.js.map +1 -0
- package/dist/streaming/registry.d.ts +1 -1
- package/dist/streaming/setup.d.ts +1 -1
- package/dist/streaming/setup.js +3 -1
- package/dist/streaming/setup.js.map +1 -1
- package/dist/streaming/showInfo.js +12 -14
- package/dist/streaming/showInfo.js.map +1 -1
- package/dist/streaming/statusEmitter.d.ts +4 -2
- package/dist/streaming/statusEmitter.js +5 -0
- package/dist/streaming/statusEmitter.js.map +1 -1
- package/dist/types/channels.d.ts +68 -0
- package/dist/types/channels.js +2 -0
- package/dist/types/channels.js.map +1 -0
- package/dist/types/config.d.ts +127 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +7 -406
- package/dist/types/index.js +1 -5
- package/dist/types/index.js.map +1 -1
- package/dist/types/profiles.d.ts +141 -0
- package/dist/types/profiles.js +2 -0
- package/dist/types/profiles.js.map +1 -0
- package/dist/types/selection.d.ts +101 -0
- package/dist/types/selection.js +6 -0
- package/dist/types/selection.js.map +1 -0
- package/dist/types/shared.d.ts +7 -0
- package/dist/types/shared.js +6 -0
- package/dist/types/shared.js.map +1 -0
- package/dist/types/streaming.d.ts +96 -0
- package/dist/types/streaming.js +2 -0
- package/dist/types/streaming.js.map +1 -0
- package/dist/utils/debugFilter.js +3 -1
- package/dist/utils/debugFilter.js.map +1 -1
- package/dist/utils/format.d.ts +7 -0
- package/dist/utils/format.js +22 -0
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/sanitize.d.ts +14 -0
- package/dist/utils/sanitize.js +37 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/package.json +6 -4
- package/dist/routes/config.d.ts +0 -72
- package/dist/routes/config.js +0 -1987
- package/dist/routes/config.js.map +0 -1
- package/dist/routes/root.js +0 -2959
- package/dist/routes/root.js.map +0 -1
- /package/dist/routes/{root.d.ts → root/index.d.ts} +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Type guard that proves channelSelector is a non-empty string. Matches the original !channelSelector truthiness check, which rejects both null and empty string.
|
|
2
|
+
// Used by the coordinator before dispatching to strategy functions.
|
|
3
|
+
export function isChannelSelectionProfile(profile) {
|
|
4
|
+
return (profile.channelSelector !== null) && (profile.channelSelector.length > 0);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/types/selection.ts"],"names":[],"mappings":"AAeA,kKAAkK;AAClK,oEAAoE;AACpE,MAAM,UAAU,yBAAyB,CAAC,OAA4B;IAEpE,OAAO,CAAC,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A utility type that represents a value that can be null.
|
|
3
|
+
* @typeParam T - The type that can be nullable.
|
|
4
|
+
*/
|
|
5
|
+
export type Nullable<T> = T | null;
|
|
6
|
+
export type ChannelSortField = "channelNumber" | "channelSelector" | "key" | "name" | "profile" | "provider" | "stationId";
|
|
7
|
+
export type SortDirection = "asc" | "desc";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/types/shared.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Nullable } from "./shared.js";
|
|
2
|
+
import type { Page } from "puppeteer-core";
|
|
3
|
+
import type { RecoveryMetrics } from "../streaming/recovery.js";
|
|
4
|
+
/**
|
|
5
|
+
* Information about an active streaming session. Created when a stream request is received and deleted when the stream ends.
|
|
6
|
+
*/
|
|
7
|
+
export interface StreamInfo {
|
|
8
|
+
channelName: Nullable<string>;
|
|
9
|
+
id: number;
|
|
10
|
+
page: Page;
|
|
11
|
+
startTime: Date;
|
|
12
|
+
stopMonitor: Nullable<() => RecoveryMetrics>;
|
|
13
|
+
url: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Snapshot of a video element's playback state. Collected by the playback health monitor to detect stalls, errors, and other problems.
|
|
17
|
+
*/
|
|
18
|
+
export interface VideoState {
|
|
19
|
+
currentTime: number;
|
|
20
|
+
ended: boolean;
|
|
21
|
+
error: boolean;
|
|
22
|
+
muted: boolean;
|
|
23
|
+
networkState: number;
|
|
24
|
+
paused: boolean;
|
|
25
|
+
readyState: number;
|
|
26
|
+
time: number;
|
|
27
|
+
volume: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Strategy for selecting a video element when multiple are present. "selectFirstVideo" takes the first video in DOM order; "selectReadyVideo" finds the video
|
|
31
|
+
* with readyState >= 3, which typically identifies the actively playing main content rather than preloaded ads.
|
|
32
|
+
*/
|
|
33
|
+
export type VideoSelectorType = "selectFirstVideo" | "selectReadyVideo";
|
|
34
|
+
/**
|
|
35
|
+
* Result of URL validation indicating whether the URL is safe to navigate to.
|
|
36
|
+
*/
|
|
37
|
+
export interface UrlValidationResult {
|
|
38
|
+
reason?: string;
|
|
39
|
+
valid: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Alias for UrlValidationResult maintained for backward compatibility with existing code.
|
|
43
|
+
*/
|
|
44
|
+
export type UrlValidation = UrlValidationResult;
|
|
45
|
+
/**
|
|
46
|
+
* Health check response structure returned by the /health endpoint.
|
|
47
|
+
*/
|
|
48
|
+
export interface HealthStatus {
|
|
49
|
+
browser: {
|
|
50
|
+
connected: boolean;
|
|
51
|
+
pageCount: number;
|
|
52
|
+
};
|
|
53
|
+
captureMode: string;
|
|
54
|
+
chrome: Nullable<string>;
|
|
55
|
+
clients: {
|
|
56
|
+
byType: {
|
|
57
|
+
count: number;
|
|
58
|
+
type: string;
|
|
59
|
+
}[];
|
|
60
|
+
total: number;
|
|
61
|
+
};
|
|
62
|
+
ffmpegAvailable: boolean;
|
|
63
|
+
memory: {
|
|
64
|
+
heapTotal: number;
|
|
65
|
+
heapUsed: number;
|
|
66
|
+
rss: number;
|
|
67
|
+
segmentBuffers: number;
|
|
68
|
+
};
|
|
69
|
+
message?: string;
|
|
70
|
+
status: "degraded" | "healthy" | "unhealthy";
|
|
71
|
+
streams: {
|
|
72
|
+
active: number;
|
|
73
|
+
limit: number;
|
|
74
|
+
};
|
|
75
|
+
timestamp: string;
|
|
76
|
+
uptime: number;
|
|
77
|
+
version: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Information about a single active stream as returned by the /streams endpoint.
|
|
81
|
+
*/
|
|
82
|
+
export interface StreamListItem {
|
|
83
|
+
channel: Nullable<string>;
|
|
84
|
+
duration: number;
|
|
85
|
+
id: number;
|
|
86
|
+
startTime: string;
|
|
87
|
+
url: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Response structure for the /streams endpoint.
|
|
91
|
+
*/
|
|
92
|
+
export interface StreamListResponse {
|
|
93
|
+
count: number;
|
|
94
|
+
limit: number;
|
|
95
|
+
streams: StreamListItem[];
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/types/streaming.ts"],"names":[],"mappings":""}
|
|
@@ -123,6 +123,7 @@ export const DEBUG_CATEGORIES = [
|
|
|
123
123
|
{ category: "browser", description: "Browser lifecycle: launch, close, stale page cleanup, restart." },
|
|
124
124
|
{ category: "browser:video", description: "Video context, fullscreen, volume locking, playback." },
|
|
125
125
|
{ category: "config", description: "Provider groups, version checking." },
|
|
126
|
+
{ category: "precache", description: "Channel lineup precaching: deferred runs, provider filter skips." },
|
|
126
127
|
{ category: "recovery", description: "General recovery: browser re-minimize, monitor abort." },
|
|
127
128
|
{ category: "recovery:context", description: "Video context: frame detachment, re-search." },
|
|
128
129
|
{ category: "recovery:nav", description: "Page navigation recovery: new tab detection, URL validation." },
|
|
@@ -131,7 +132,6 @@ export const DEBUG_CATEGORIES = [
|
|
|
131
132
|
{ category: "retry", description: "Retry attempts, page-closed aborts." },
|
|
132
133
|
{ category: "streaming:ffmpeg", description: "FFmpeg stderr output, pipe errors." },
|
|
133
134
|
{ category: "streaming:hls", description: "HLS segment storage, page close errors." },
|
|
134
|
-
{ category: "streaming:mpegts", description: "MPEG-TS remuxer errors, client connect/disconnect." },
|
|
135
135
|
{ category: "streaming:segmenter", description: "fMP4 parsing: keyframes, init segments, duration clamping." },
|
|
136
136
|
{ category: "streaming:setup", description: "Stream setup: redirect resolution, profile override, capture init." },
|
|
137
137
|
{ category: "streaming:showinfo", description: "Channels DVR show name lookups, device mapping." },
|
|
@@ -141,9 +141,11 @@ export const DEBUG_CATEGORIES = [
|
|
|
141
141
|
{ category: "timing:startup", description: "Stream startup: init segment, first playlist, capture ready." },
|
|
142
142
|
{ category: "timing:tab", description: "Tab replacement: old tab cleanup, new page creation." },
|
|
143
143
|
{ category: "timing:tune", description: "Tune waterfall: navigation, channel selection, video ready." },
|
|
144
|
+
{ category: "tuning:directv", description: "DirecTV Stream: interceptor tuning, cache, logo click fallback." },
|
|
144
145
|
{ category: "tuning:hbo", description: "HBO Max: tab URL discovery, channel rail, navigation." },
|
|
145
146
|
{ category: "tuning:hulu", description: "Hulu Live guide grid: binary search, cache, click retries." },
|
|
146
147
|
{ category: "tuning:sling", description: "Sling TV guide grid: binary search, cache, click retries." },
|
|
148
|
+
{ category: "tuning:tileClick", description: "Tile click strategy: scroll phase, matchSelector poll, play button retries, modal dismiss." },
|
|
147
149
|
{ category: "tuning:yttv", description: "YouTube TV EPG grid navigation." }
|
|
148
150
|
];
|
|
149
151
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debugFilter.js","sourceRoot":"","sources":["../../src/utils/debugFilter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"debugFilter.js","sourceRoot":"","sources":["../../src/utils/debugFilter.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/format.d.ts
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
* @returns Formatted duration string.
|
|
8
8
|
*/
|
|
9
9
|
export declare function formatDuration(ms: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Formats a Unix millisecond timestamp as a human-readable relative time string (e.g., "2 minutes ago", "3 hours ago", "5 days ago"). Used for health indicator
|
|
12
|
+
* tooltips where absolute timestamps would be harder to interpret at a glance.
|
|
13
|
+
* @param timestamp - Unix millisecond timestamp.
|
|
14
|
+
* @returns Relative time string.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatTimeAgo(timestamp: number): string;
|
|
10
17
|
/**
|
|
11
18
|
* Extracts a concise domain from a URL by keeping only the last two portions of the hostname (e.g., "watch.foodnetwork.com" becomes "foodnetwork.com",
|
|
12
19
|
* "www.hulu.com" becomes "hulu.com"). Used as a standard domain key for DOMAIN_CONFIG lookups and as a display fallback when no provider name is configured.
|
package/dist/utils/format.js
CHANGED
|
@@ -23,6 +23,28 @@ export function formatDuration(ms) {
|
|
|
23
23
|
}
|
|
24
24
|
return [String(seconds), "s"].join("");
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Formats a Unix millisecond timestamp as a human-readable relative time string (e.g., "2 minutes ago", "3 hours ago", "5 days ago"). Used for health indicator
|
|
28
|
+
* tooltips where absolute timestamps would be harder to interpret at a glance.
|
|
29
|
+
* @param timestamp - Unix millisecond timestamp.
|
|
30
|
+
* @returns Relative time string.
|
|
31
|
+
*/
|
|
32
|
+
export function formatTimeAgo(timestamp) {
|
|
33
|
+
const seconds = Math.floor((Date.now() - timestamp) / 1000);
|
|
34
|
+
if (seconds < 60) {
|
|
35
|
+
return "just now";
|
|
36
|
+
}
|
|
37
|
+
const minutes = Math.floor(seconds / 60);
|
|
38
|
+
if (minutes < 60) {
|
|
39
|
+
return String(minutes) + (minutes === 1 ? " minute ago" : " minutes ago");
|
|
40
|
+
}
|
|
41
|
+
const hours = Math.floor(minutes / 60);
|
|
42
|
+
if (hours < 24) {
|
|
43
|
+
return String(hours) + (hours === 1 ? " hour ago" : " hours ago");
|
|
44
|
+
}
|
|
45
|
+
const days = Math.floor(hours / 24);
|
|
46
|
+
return String(days) + (days === 1 ? " day ago" : " days ago");
|
|
47
|
+
}
|
|
26
48
|
/**
|
|
27
49
|
* Extracts a concise domain from a URL by keeping only the last two portions of the hostname (e.g., "watch.foodnetwork.com" becomes "foodnetwork.com",
|
|
28
50
|
* "www.hulu.com" becomes "hulu.com"). Used as a standard domain key for DOMAIN_CONFIG lookups and as a display fallback when no provider name is configured.
|
package/dist/utils/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IAEvC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAElC,IAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QAEb,OAAO,CAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,IAAG,OAAO,GAAG,CAAC,EAAE,CAAC;QAEf,OAAO,CAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,CAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IAEvC,IAAI,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAElC,uHAAuH;QACvH,IAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAEpB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QAEP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IAEvC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAElC,IAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QAEb,OAAO,CAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,IAAG,OAAO,GAAG,CAAC,EAAE,CAAC;QAEf,OAAO,CAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,CAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAE7C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAE5D,IAAG,OAAO,GAAG,EAAE,EAAE,CAAC;QAEhB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IAEzC,IAAG,OAAO,GAAG,EAAE,EAAE,CAAC;QAEhB,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IAEvC,IAAG,KAAK,GAAG,EAAE,EAAE,CAAC;QAEd,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IAEpC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IAEvC,IAAI,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAElC,uHAAuH;QACvH,IAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAEpB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QAEP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export * from "./m3u.js";
|
|
|
15
15
|
export * from "./morganStream.js";
|
|
16
16
|
export * from "./platform.js";
|
|
17
17
|
export * from "./retry.js";
|
|
18
|
+
export * from "./sanitize.js";
|
|
18
19
|
export * from "./streamContext.js";
|
|
19
20
|
export * from "./version.js";
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strips non-printable characters from a string and trims whitespace. Replaces `.trim()` at data-collection points to ensure string values contain only visible
|
|
3
|
+
* content. Safe to call on already-clean strings — the regex replacement is a no-op when no non-printable characters are present.
|
|
4
|
+
* @param value - The string to sanitize.
|
|
5
|
+
* @returns The sanitized string with non-printable characters removed and whitespace trimmed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function sanitizeString(value: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Tests whether a string contains any non-printable characters. Used for startup warnings when loading persisted data — the warning alerts users to corruption
|
|
10
|
+
* without modifying the loaded values.
|
|
11
|
+
* @param value - The string to test.
|
|
12
|
+
* @returns True if the string contains at least one non-printable character.
|
|
13
|
+
*/
|
|
14
|
+
export declare function containsNonPrintable(value: string): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* sanitize.ts: Input sanitization utilities for PrismCast.
|
|
4
|
+
*/
|
|
5
|
+
/* Non-printable characters can silently corrupt string values when introduced via copy-paste operations or hand-edited JSON files. The most common case is null bytes
|
|
6
|
+
* (\x00) interleaved between every visible character, which breaks CSS selector matching, URL parsing, and channel identification without any visible indication in
|
|
7
|
+
* the UI. These utilities strip non-printable characters at data-collection boundaries so downstream code can trust that string values contain only visible content.
|
|
8
|
+
*
|
|
9
|
+
* The regex targets control characters and Unicode special characters that have no visible representation: C0 controls (except TAB, LF, CR), DEL, BOM, zero-width
|
|
10
|
+
* spaces, and Unicode line/paragraph separators. TAB (\x09), LF (\x0A), and CR (\x0D) are preserved because they appear legitimately in multi-line text fields.
|
|
11
|
+
*/
|
|
12
|
+
// Pattern matching non-printable characters. Covers: C0 controls except TAB/LF/CR, DEL, BOM, zero-width spaces, directional markers, and line/paragraph separators.
|
|
13
|
+
// The no-control-regex rule is suppressed because this regex genuinely needs to match control characters — that is its entire purpose.
|
|
14
|
+
// eslint-disable-next-line no-control-regex
|
|
15
|
+
const NON_PRINTABLE_PATTERN = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\uFEFF\u200B-\u200F\u2028-\u2029]/g;
|
|
16
|
+
/**
|
|
17
|
+
* Strips non-printable characters from a string and trims whitespace. Replaces `.trim()` at data-collection points to ensure string values contain only visible
|
|
18
|
+
* content. Safe to call on already-clean strings — the regex replacement is a no-op when no non-printable characters are present.
|
|
19
|
+
* @param value - The string to sanitize.
|
|
20
|
+
* @returns The sanitized string with non-printable characters removed and whitespace trimmed.
|
|
21
|
+
*/
|
|
22
|
+
export function sanitizeString(value) {
|
|
23
|
+
return value.replace(NON_PRINTABLE_PATTERN, "").trim();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Tests whether a string contains any non-printable characters. Used for startup warnings when loading persisted data — the warning alerts users to corruption
|
|
27
|
+
* without modifying the loaded values.
|
|
28
|
+
* @param value - The string to test.
|
|
29
|
+
* @returns True if the string contains at least one non-printable character.
|
|
30
|
+
*/
|
|
31
|
+
export function containsNonPrintable(value) {
|
|
32
|
+
// Reset lastIndex before testing — the global flag on NON_PRINTABLE_PATTERN causes .test() to advance lastIndex on each call, which would produce alternating
|
|
33
|
+
// true/false results without this reset.
|
|
34
|
+
NON_PRINTABLE_PATTERN.lastIndex = 0;
|
|
35
|
+
return NON_PRINTABLE_PATTERN.test(value);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AAEH,oKAAoK;AACpK,uIAAuI;AACvI,4CAA4C;AAC5C,MAAM,qBAAqB,GAAG,mEAAmE,CAAC;AAElG;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAE1C,OAAO,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAEhD,8JAA8J;IAC9J,yCAAyC;IACzC,qBAAqB,CAAC,SAAS,GAAG,CAAC,CAAC;IAEpC,OAAO,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prismcast",
|
|
3
3
|
"displayName": "PrismCast",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"description": "Browser-based live TV capture server for Channels DVR, Plex, and other streaming clients.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "HJD",
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
"watch": "npm run build && nodemon"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
+
"compression": "^1.8.1",
|
|
66
67
|
"console-stamp": "3.1.2",
|
|
67
68
|
"express": "5.2.1",
|
|
68
69
|
"ffmpeg-for-homebridge": "2.2.1",
|
|
@@ -72,15 +73,16 @@
|
|
|
72
73
|
},
|
|
73
74
|
"devDependencies": {
|
|
74
75
|
"@stylistic/eslint-plugin": "5.9.0",
|
|
76
|
+
"@types/compression": "^1.8.1",
|
|
75
77
|
"@types/dateformat": "5.0.3",
|
|
76
78
|
"@types/express": "5.0.6",
|
|
77
79
|
"@types/morgan": "1.9.10",
|
|
78
|
-
"@types/node": "25.3.
|
|
80
|
+
"@types/node": "25.3.3",
|
|
79
81
|
"eslint": "9.39.2",
|
|
80
82
|
"homebridge-plugin-utils": "1.32.0",
|
|
81
|
-
"nodemon": "3.1.
|
|
83
|
+
"nodemon": "3.1.14",
|
|
82
84
|
"shx": "0.4.0",
|
|
83
85
|
"typescript": "5.9.3",
|
|
84
|
-
"typescript-eslint": "8.56.
|
|
86
|
+
"typescript-eslint": "8.56.1"
|
|
85
87
|
}
|
|
86
88
|
}
|
package/dist/routes/config.d.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { AdvancedSection } from "../config/userConfig.js";
|
|
2
|
-
import type { Express } from "express";
|
|
3
|
-
import type { Nullable } from "../types/index.js";
|
|
4
|
-
import type { ProfileInfo } from "../config/profiles.js";
|
|
5
|
-
/**
|
|
6
|
-
* Result from generating channel row HTML.
|
|
7
|
-
*/
|
|
8
|
-
export interface ChannelRowHtml {
|
|
9
|
-
displayRow: string;
|
|
10
|
-
editRow: Nullable<string>;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Generates the HTML for a single channel's table rows (display row and optional edit form row).
|
|
14
|
-
* @param key - The channel key.
|
|
15
|
-
* @param profiles - List of available profiles with descriptions for the dropdown.
|
|
16
|
-
* @returns Object with displayRow and editRow HTML strings.
|
|
17
|
-
*/
|
|
18
|
-
export declare function generateChannelRowHtml(key: string, profiles: ProfileInfo[]): ChannelRowHtml;
|
|
19
|
-
/**
|
|
20
|
-
* Generates the provider filter toolbar HTML with a multi-select dropdown, dismissable chips, and a bulk-assign dropdown.
|
|
21
|
-
* @returns HTML string for the provider filter toolbar.
|
|
22
|
-
*/
|
|
23
|
-
export declare function generateProviderFilterToolbar(): string;
|
|
24
|
-
/**
|
|
25
|
-
* Generates the Channels panel HTML content.
|
|
26
|
-
* @param channelMessage - Optional message to display (success or error).
|
|
27
|
-
* @param channelError - If true, display as error; otherwise as success.
|
|
28
|
-
* @param editingChannelKey - If set, show the edit form for this channel.
|
|
29
|
-
* @param showAddForm - If true, show the add channel form.
|
|
30
|
-
* @param formErrors - Validation errors for the channel form.
|
|
31
|
-
* @param formValues - Form values to re-populate after validation error.
|
|
32
|
-
* @returns HTML string for the Channels panel content.
|
|
33
|
-
*/
|
|
34
|
-
export declare function generateChannelsPanel(channelMessage?: string, channelError?: boolean, editingChannelKey?: string, showAddForm?: boolean, formErrors?: Map<string, string>, formValues?: Map<string, string>): string;
|
|
35
|
-
/**
|
|
36
|
-
* Generates the content for the Settings tab with non-collapsible section headers.
|
|
37
|
-
* @param validationErrors - Map of setting path to validation error message.
|
|
38
|
-
* @param formValues - Map of setting path to submitted form value.
|
|
39
|
-
* @returns HTML string for the Settings tab content.
|
|
40
|
-
*/
|
|
41
|
-
export declare function generateSettingsTabContent(validationErrors?: Map<string, string>, formValues?: Map<string, string>): string;
|
|
42
|
-
/**
|
|
43
|
-
* Generates the content for a collapsible section within the Advanced tab.
|
|
44
|
-
* @param section - The section definition.
|
|
45
|
-
* @param validationErrors - Map of setting path to validation error message.
|
|
46
|
-
* @param formValues - Map of setting path to submitted form value.
|
|
47
|
-
* @returns HTML string for the section.
|
|
48
|
-
*/
|
|
49
|
-
export declare function generateCollapsibleSection(section: AdvancedSection, validationErrors?: Map<string, string>, formValues?: Map<string, string>): string;
|
|
50
|
-
/**
|
|
51
|
-
* Generates the content for the Advanced tab with collapsible sections.
|
|
52
|
-
* @param validationErrors - Map of setting path to validation error message.
|
|
53
|
-
* @param formValues - Map of setting path to submitted form value.
|
|
54
|
-
* @returns HTML string for the Advanced tab content.
|
|
55
|
-
*/
|
|
56
|
-
export declare function generateAdvancedTabContent(validationErrors?: Map<string, string>, formValues?: Map<string, string>): string;
|
|
57
|
-
/**
|
|
58
|
-
* Generates the config path display for settings.
|
|
59
|
-
* @returns HTML string with config path.
|
|
60
|
-
*/
|
|
61
|
-
export declare function generateSettingsFormFooter(): string;
|
|
62
|
-
/**
|
|
63
|
-
* Checks if there are any environment variable overrides for configuration settings.
|
|
64
|
-
* @returns True if any settings are overridden by environment variables.
|
|
65
|
-
*/
|
|
66
|
-
export declare function hasEnvOverrides(): boolean;
|
|
67
|
-
/**
|
|
68
|
-
* Configures the configuration endpoints. The GET /config endpoint has been removed - configuration is now accessed via hash navigation on the main page
|
|
69
|
-
* (e.g., /#config/server). Channels are accessed via /#channels. POST endpoints remain for form submission handling.
|
|
70
|
-
* @param app - The Express application.
|
|
71
|
-
*/
|
|
72
|
-
export declare function setupConfigEndpoint(app: Express): void;
|