stormcloud-video-player 0.8.18 → 0.8.20

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.
Files changed (48) hide show
  1. package/README.md +67 -83
  2. package/dist/stormcloud-vp.min.js +1 -1
  3. package/lib/index.cjs +686 -353
  4. package/lib/index.cjs.map +1 -1
  5. package/lib/index.d.cts +1 -1
  6. package/lib/index.d.ts +1 -1
  7. package/lib/index.js +686 -353
  8. package/lib/index.js.map +1 -1
  9. package/lib/player/AdBreakOrchestrator.cjs +11 -11
  10. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  11. package/lib/player/AdBreakOrchestrator.d.cts +4 -4
  12. package/lib/player/{VmapManager.cjs → AdConfigManager.cjs} +561 -217
  13. package/lib/player/AdConfigManager.cjs.map +1 -0
  14. package/lib/player/{VmapManager.d.cts → AdConfigManager.d.cts} +3 -3
  15. package/lib/player/AdPreloadPool.d.cts +1 -1
  16. package/lib/player/AdTimingService.d.cts +1 -1
  17. package/lib/player/HlsEngine.d.cts +1 -1
  18. package/lib/player/PlayerControls.d.cts +1 -1
  19. package/lib/player/Scte35CueManager.d.cts +1 -1
  20. package/lib/player/Scte35Parser.d.cts +1 -1
  21. package/lib/player/StormcloudVideoPlayer.cjs +686 -353
  22. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  23. package/lib/player/StormcloudVideoPlayer.d.cts +2 -2
  24. package/lib/player/playerTypes.d.cts +1 -1
  25. package/lib/players/HlsPlayer.cjs +686 -353
  26. package/lib/players/HlsPlayer.cjs.map +1 -1
  27. package/lib/players/HlsPlayer.d.cts +1 -1
  28. package/lib/players/index.cjs +686 -353
  29. package/lib/players/index.cjs.map +1 -1
  30. package/lib/sdk/hlsAdPlayer.cjs +5 -4
  31. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  32. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  33. package/lib/types-BAP8n5mE.d.cts +126 -0
  34. package/lib/ui/StormcloudVideoPlayer.cjs +686 -353
  35. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  36. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  37. package/lib/utils/ctvVastSignals.cjs +103 -33
  38. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  39. package/lib/utils/ctvVastSignals.d.cts +1 -13
  40. package/lib/utils/tracking.d.cts +1 -1
  41. package/lib/utils/vastEnvironmentSignals.cjs +450 -0
  42. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -0
  43. package/lib/utils/vastEnvironmentSignals.d.cts +16 -0
  44. package/lib/utils/vastMacros.cjs +347 -25
  45. package/lib/utils/vastMacros.cjs.map +1 -1
  46. package/lib/utils/vastMacros.d.cts +3 -1
  47. package/package.json +1 -1
  48. package/lib/player/VmapManager.cjs.map +0 -1
@@ -863,6 +863,7 @@ function createHlsAdPlayer(contentVideo, options) {
863
863
  handleAdComplete();
864
864
  });
865
865
  adVideoElement.addEventListener("error", function(e) {
866
+ if (!adPlaying) return;
866
867
  console.error("[HlsAdPlayer] Ad video error:", e);
867
868
  if (currentAd) {
868
869
  fireTrackingPixels(currentAd.trackingUrls.error);
@@ -1064,15 +1065,15 @@ function createHlsAdPlayer(contentVideo, options) {
1064
1065
  adVideoElement.muted = originalMutedState;
1065
1066
  console.log("[HlsAdPlayer] Set ad video volume to ".concat(adVideoElement.volume, ", muted: ").concat(adVideoElement.muted, ", originalMutedState: ").concat(originalMutedState, ", contentVolume: ").concat(contentVolume));
1066
1067
  }
1068
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1069
+ if (!mediaFile) {
1070
+ throw new Error("No media file available for ad");
1071
+ }
1067
1072
  if (adContainerEl) {
1068
1073
  adContainerEl.style.display = "flex";
1069
1074
  adContainerEl.style.pointerEvents = "auto";
1070
1075
  }
1071
1076
  emit("content_pause");
1072
- mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1073
- if (!mediaFile) {
1074
- throw new Error("No media file available for ad");
1075
- }
1076
1077
  isHlsAd = isHlsMediaFile(mediaFile);
1077
1078
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
1078
1079
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -2358,22 +2359,337 @@ function initializePolyfills() {
2358
2359
  polyfillTextEncoder();
2359
2360
  polyfillPromiseFinally();
2360
2361
  }
2361
- // src/utils/vastMacros.ts
2362
- function generateCorrelator() {
2363
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2362
+ // src/utils/vastEnvironmentSignals.ts
2363
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2364
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2365
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2366
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2367
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
2368
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2369
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2370
+ function getDefaultAppId() {
2371
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2372
+ var ua = navigator.userAgent;
2373
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2374
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2375
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2376
+ return AIRY_ANDROID_APP_ID;
2377
+ }
2378
+ var DEVICE_ID_STORAGE_KEYS = [
2379
+ "rdid",
2380
+ "ifa",
2381
+ "advertisingId",
2382
+ "advertising_id",
2383
+ "deviceAdvertisingId",
2384
+ "aaid",
2385
+ "adid",
2386
+ "rida",
2387
+ "tifa",
2388
+ "lgudid"
2389
+ ];
2390
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2391
+ "aaid",
2392
+ "adid"
2393
+ ]);
2394
+ function resolveVastEnvironmentSignals(isCtv) {
2395
+ var _ref, _bridgeSignals_limitAdTracking;
2396
+ var bridgeSignals = readNativeBridgeSignals();
2397
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
2398
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType();
2399
+ var limitAdTracking = deviceId != null ? (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
2400
+ if (isCtv) {
2401
+ return _object_spread_props(_object_spread({
2402
+ isCtv: true,
2403
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL,
2404
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || getDefaultAppId(),
2405
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || AIRY_APP_NAME,
2406
+ sessionId: getOrCreateCtvSessionId()
2407
+ }, deviceId ? {
2408
+ deviceId: deviceId
2409
+ } : {}, deviceIdType ? {
2410
+ deviceIdType: deviceIdType
2411
+ } : {}, limitAdTracking != null ? {
2412
+ limitAdTracking: limitAdTracking
2413
+ } : {}), {
2414
+ deviceTypeHint: 5
2415
+ });
2416
+ }
2417
+ return _object_spread({
2418
+ isCtv: false
2419
+ }, deviceId ? {
2420
+ deviceId: deviceId
2421
+ } : {}, deviceIdType ? {
2422
+ deviceIdType: deviceIdType
2423
+ } : {}, limitAdTracking != null ? {
2424
+ limitAdTracking: limitAdTracking
2425
+ } : {});
2426
+ }
2427
+ function inferDeviceIdType() {
2428
+ if (typeof navigator === "undefined") {
2429
+ return void 0;
2430
+ }
2431
+ var ua = navigator.userAgent;
2432
+ if (/Roku/i.test(ua)) return "rida";
2433
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
2434
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2435
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2436
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2437
+ if (/Android|Google TV/i.test(ua)) return "aaid";
2438
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2439
+ return void 0;
2440
+ }
2441
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
2442
+ if (!tagType || !runtimeType) return false;
2443
+ var tag = tagType.toLowerCase();
2444
+ var runtime = runtimeType.toLowerCase();
2445
+ if (tag === runtime) return true;
2446
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2447
+ }
2448
+ function getOrCreateCtvSessionId() {
2449
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2450
+ if (existing) {
2451
+ return existing;
2452
+ }
2453
+ var sessionId = createUuid();
2454
+ try {
2455
+ var _window_localStorage;
2456
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2457
+ } catch (unused) {}
2458
+ return sessionId;
2459
+ }
2460
+ function createUuid() {
2461
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2462
+ return crypto.randomUUID();
2463
+ }
2464
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2465
+ var value = Math.floor(Math.random() * 16);
2466
+ var nibble = char === "x" ? value : value & 3 | 8;
2467
+ return nibble.toString(16);
2468
+ });
2469
+ }
2470
+ function readNativeBridgeSignals() {
2471
+ if (typeof window === "undefined") {
2472
+ return {};
2473
+ }
2474
+ var candidates = [
2475
+ window.__STORMCLOUD_CTV_AD_INFO__,
2476
+ window.__STORMCLOUD_CTV__,
2477
+ window.stormcloudCtv,
2478
+ window.AiryTV,
2479
+ window.Android,
2480
+ window.webOS,
2481
+ window.tizen,
2482
+ window.amazon
2483
+ ].filter(Boolean);
2484
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2485
+ try {
2486
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2487
+ var source = _step.value;
2488
+ var contentUrl = readBridgeValue(source, [
2489
+ "contentUrl",
2490
+ "url",
2491
+ "videoUrl",
2492
+ "canonicalUrl"
2493
+ ]) || void 0;
2494
+ var appId = readBridgeValue(source, [
2495
+ "appId",
2496
+ "msid",
2497
+ "applicationId",
2498
+ "packageName"
2499
+ ]) || void 0;
2500
+ var appName = readBridgeValue(source, [
2501
+ "appName",
2502
+ "an",
2503
+ "applicationName"
2504
+ ]) || void 0;
2505
+ var deviceId = readBridgeValue(source, [
2506
+ "rdid",
2507
+ "ifa",
2508
+ "advertisingId",
2509
+ "adId",
2510
+ "deviceId",
2511
+ "lgudid",
2512
+ "LGUDID",
2513
+ "tifa",
2514
+ "rida",
2515
+ "afai",
2516
+ "aaid"
2517
+ ]) || void 0;
2518
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
2519
+ var deviceIdType = readBridgeValue(source, [
2520
+ "idtype",
2521
+ "deviceIdType",
2522
+ "advertisingIdType",
2523
+ "idType"
2524
+ ]) || inferDeviceIdType();
2525
+ var limitAdTracking = readBridgeBoolean(source, [
2526
+ "is_lat",
2527
+ "limitAdTracking",
2528
+ "limitedAdTracking",
2529
+ "lat"
2530
+ ]);
2531
+ return _object_spread({}, contentUrl ? {
2532
+ contentUrl: contentUrl
2533
+ } : {}, appId ? {
2534
+ appId: appId
2535
+ } : {}, appName ? {
2536
+ appName: appName
2537
+ } : {}, deviceId ? {
2538
+ deviceId: deviceId
2539
+ } : {}, deviceId && deviceIdType ? {
2540
+ deviceIdType: deviceIdType
2541
+ } : {}, deviceId && limitAdTracking != null ? {
2542
+ limitAdTracking: limitAdTracking
2543
+ } : {});
2544
+ }
2545
+ } catch (err) {
2546
+ _didIteratorError = true;
2547
+ _iteratorError = err;
2548
+ } finally{
2364
2549
  try {
2365
- var _buf_, _buf_1;
2366
- var buf = new Uint32Array(2);
2367
- crypto.getRandomValues(buf);
2368
- var value = ((_buf_ = buf[0]) !== null && _buf_ !== void 0 ? _buf_ : 0) * 2097152 + (((_buf_1 = buf[1]) !== null && _buf_1 !== void 0 ? _buf_1 : 0) & 2097151);
2369
- if (value > 0) {
2370
- return String(value);
2550
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2551
+ _iterator.return();
2371
2552
  }
2372
- } catch (unused) {}
2553
+ } finally{
2554
+ if (_didIteratorError) {
2555
+ throw _iteratorError;
2556
+ }
2557
+ }
2373
2558
  }
2374
- return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2559
+ return {};
2560
+ }
2561
+ function readBridgeValue(source, keys) {
2562
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2563
+ try {
2564
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2565
+ var key = _step.value;
2566
+ var value = source === null || source === void 0 ? void 0 : source[key];
2567
+ if (typeof value === "string" && value) {
2568
+ return value;
2569
+ }
2570
+ if (typeof value === "function") {
2571
+ try {
2572
+ var result = value.call(source);
2573
+ if (typeof result === "string" && result) {
2574
+ return result;
2575
+ }
2576
+ } catch (unused) {}
2577
+ }
2578
+ }
2579
+ } catch (err) {
2580
+ _didIteratorError = true;
2581
+ _iteratorError = err;
2582
+ } finally{
2583
+ try {
2584
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2585
+ _iterator.return();
2586
+ }
2587
+ } finally{
2588
+ if (_didIteratorError) {
2589
+ throw _iteratorError;
2590
+ }
2591
+ }
2592
+ }
2593
+ return void 0;
2375
2594
  }
2595
+ function readBridgeBoolean(source, keys) {
2596
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2597
+ try {
2598
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2599
+ var key = _step.value;
2600
+ var value = source === null || source === void 0 ? void 0 : source[key];
2601
+ var normalized = normalizeBoolean(value);
2602
+ if (normalized != null) {
2603
+ return normalized;
2604
+ }
2605
+ if (typeof value === "function") {
2606
+ try {
2607
+ var result = normalizeBoolean(value.call(source));
2608
+ if (result != null) {
2609
+ return result;
2610
+ }
2611
+ } catch (unused) {}
2612
+ }
2613
+ }
2614
+ } catch (err) {
2615
+ _didIteratorError = true;
2616
+ _iteratorError = err;
2617
+ } finally{
2618
+ try {
2619
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2620
+ _iterator.return();
2621
+ }
2622
+ } finally{
2623
+ if (_didIteratorError) {
2624
+ throw _iteratorError;
2625
+ }
2626
+ }
2627
+ }
2628
+ return void 0;
2629
+ }
2630
+ function readStoredDeviceId() {
2631
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2632
+ try {
2633
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2634
+ var key = _step.value;
2635
+ var value = readStoredString(key);
2636
+ if (value) {
2637
+ return value;
2638
+ }
2639
+ }
2640
+ } catch (err) {
2641
+ _didIteratorError = true;
2642
+ _iteratorError = err;
2643
+ } finally{
2644
+ try {
2645
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2646
+ _iterator.return();
2647
+ }
2648
+ } finally{
2649
+ if (_didIteratorError) {
2650
+ throw _iteratorError;
2651
+ }
2652
+ }
2653
+ }
2654
+ return void 0;
2655
+ }
2656
+ function readStoredString(key) {
2657
+ if (typeof window === "undefined") {
2658
+ return void 0;
2659
+ }
2660
+ try {
2661
+ var _window_localStorage;
2662
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2663
+ return value || void 0;
2664
+ } catch (unused) {
2665
+ return void 0;
2666
+ }
2667
+ }
2668
+ function readStoredLimitAdTracking() {
2669
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2670
+ }
2671
+ function normalizeBoolean(value) {
2672
+ if (typeof value === "boolean") {
2673
+ return value;
2674
+ }
2675
+ if (typeof value === "number") {
2676
+ return value === 1;
2677
+ }
2678
+ if (typeof value === "string") {
2679
+ var normalized = value.toLowerCase();
2680
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
2681
+ return true;
2682
+ }
2683
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
2684
+ return false;
2685
+ }
2686
+ }
2687
+ return void 0;
2688
+ }
2689
+ // src/utils/vastMacros.ts
2376
2690
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
2691
+ var INVALID_VAST_PARAM_KEY = /^\s|\s$/;
2692
+ var EXAMPLE_COM_URL = /example\.com/i;
2377
2693
  var CTV_UNSUPPORTED_PARAMS = [
2378
2694
  "description_url",
2379
2695
  "tfcd",
@@ -2388,14 +2704,288 @@ var CTV_UNSUPPORTED_PARAMS = [
2388
2704
  "gdpr_consent",
2389
2705
  "us_privacy"
2390
2706
  ];
2707
+ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2708
+ {
2709
+ pattern: /\[RDID\]/gi,
2710
+ getValue: function getValue(ctx) {
2711
+ return ctx.deviceId;
2712
+ }
2713
+ },
2714
+ {
2715
+ pattern: /\[IFA\]/gi,
2716
+ getValue: function getValue(ctx) {
2717
+ return ctx.deviceId;
2718
+ }
2719
+ },
2720
+ {
2721
+ pattern: /\[ADVERTISING[_-]?ID(?:ENTIFIER)?\]/gi,
2722
+ getValue: function getValue(ctx) {
2723
+ return ctx.deviceId;
2724
+ }
2725
+ },
2726
+ {
2727
+ pattern: /\[DEVICE[_-]?ID\]/gi,
2728
+ getValue: function getValue(ctx) {
2729
+ return ctx.deviceId;
2730
+ }
2731
+ },
2732
+ {
2733
+ pattern: /\[IDTYPE\]/gi,
2734
+ getValue: function getValue(ctx) {
2735
+ return ctx.deviceIdType;
2736
+ }
2737
+ },
2738
+ {
2739
+ pattern: /\{rdid\}/gi,
2740
+ getValue: function getValue(ctx) {
2741
+ return ctx.deviceId;
2742
+ }
2743
+ },
2744
+ {
2745
+ pattern: /\{device[_-]?id\}/gi,
2746
+ getValue: function getValue(ctx) {
2747
+ return ctx.deviceId;
2748
+ }
2749
+ },
2750
+ {
2751
+ pattern: /\{idtype\}/gi,
2752
+ getValue: function getValue(ctx) {
2753
+ return ctx.deviceIdType;
2754
+ }
2755
+ },
2756
+ {
2757
+ pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi,
2758
+ getValue: function getValue(ctx) {
2759
+ return ctx.deviceId;
2760
+ }
2761
+ },
2762
+ {
2763
+ pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi,
2764
+ getValue: function getValue(ctx) {
2765
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2766
+ }
2767
+ },
2768
+ {
2769
+ pattern: /%%ADVERTISING_ID_TYPE%%/gi,
2770
+ getValue: function getValue(ctx) {
2771
+ return ctx.deviceIdType;
2772
+ }
2773
+ },
2774
+ {
2775
+ pattern: /%%ADVERTISING_ID%%/gi,
2776
+ getValue: function getValue(ctx) {
2777
+ return ctx.deviceId;
2778
+ }
2779
+ },
2780
+ {
2781
+ pattern: /%%LIMIT_AD_TRACKING%%/gi,
2782
+ getValue: function getValue(ctx) {
2783
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2784
+ }
2785
+ },
2786
+ {
2787
+ pattern: /%%MSID%%/gi,
2788
+ getValue: function getValue(ctx) {
2789
+ return ctx.appId;
2790
+ }
2791
+ },
2792
+ {
2793
+ pattern: /%%APP_NAME%%/gi,
2794
+ getValue: function getValue(ctx) {
2795
+ return ctx.appName;
2796
+ }
2797
+ },
2798
+ {
2799
+ pattern: /%%SESSION_ID%%/gi,
2800
+ getValue: function getValue(ctx) {
2801
+ return ctx.sessionId;
2802
+ }
2803
+ },
2804
+ {
2805
+ pattern: /%%CORRELATOR%%/gi,
2806
+ getValue: function getValue(ctx) {
2807
+ return ctx.correlator;
2808
+ }
2809
+ }
2810
+ ];
2811
+ function isMacroPlaceholder(value) {
2812
+ if (value == null) return true;
2813
+ var trimmed = value.trim();
2814
+ if (!trimmed) return true;
2815
+ if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;
2816
+ return /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(trimmed);
2817
+ }
2818
+ function generateCorrelator() {
2819
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2820
+ try {
2821
+ var _buf_, _buf_1;
2822
+ var buf = new Uint32Array(2);
2823
+ crypto.getRandomValues(buf);
2824
+ var value = ((_buf_ = buf[0]) !== null && _buf_ !== void 0 ? _buf_ : 0) * 2097152 + (((_buf_1 = buf[1]) !== null && _buf_1 !== void 0 ? _buf_1 : 0) & 2097151);
2825
+ if (value > 0) {
2826
+ return String(value);
2827
+ }
2828
+ } catch (unused) {}
2829
+ }
2830
+ return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2831
+ }
2832
+ function expandInlineMacroPlaceholders(baseUrl, ctx) {
2833
+ var url = baseUrl;
2834
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2835
+ try {
2836
+ for(var _iterator = INLINE_DEVICE_MACRO_REPLACEMENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2837
+ var _step_value = _step.value, pattern = _step_value.pattern, getValue = _step_value.getValue;
2838
+ var value = getValue(ctx);
2839
+ if (value != null && value !== "") {
2840
+ url = url.replace(pattern, encodeURIComponent(value));
2841
+ }
2842
+ }
2843
+ } catch (err) {
2844
+ _didIteratorError = true;
2845
+ _iteratorError = err;
2846
+ } finally{
2847
+ try {
2848
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2849
+ _iterator.return();
2850
+ }
2851
+ } finally{
2852
+ if (_didIteratorError) {
2853
+ throw _iteratorError;
2854
+ }
2855
+ }
2856
+ }
2857
+ return url;
2858
+ }
2859
+ function applyDeviceIdentityParams(params, ctx) {
2860
+ var _ctx_deviceId, _ctx_deviceIdType;
2861
+ var runtimeId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
2862
+ var runtimeType = ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType();
2863
+ var tagRdid = params.get("rdid");
2864
+ var tagType = params.get("idtype");
2865
+ var tagLat = params.get("is_lat");
2866
+ var latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2867
+ if (runtimeId) {
2868
+ params.set("rdid", runtimeId);
2869
+ params.set("idtype", runtimeType || tagType || "aaid");
2870
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2871
+ return;
2872
+ }
2873
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2874
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2875
+ if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2876
+ params.delete("rdid");
2877
+ params.delete("idtype");
2878
+ params.delete("is_lat");
2879
+ return;
2880
+ }
2881
+ if (tagRdidValid) {
2882
+ if (isMacroPlaceholder(tagType) && runtimeType) {
2883
+ params.set("idtype", runtimeType);
2884
+ }
2885
+ if (isMacroPlaceholder(tagLat)) {
2886
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2887
+ }
2888
+ return;
2889
+ }
2890
+ params.delete("rdid");
2891
+ params.delete("idtype");
2892
+ params.delete("is_lat");
2893
+ }
2894
+ function removeBrokenAppNameOrphans(params, appName) {
2895
+ var toDelete = [];
2896
+ params.forEach(function(_value, key) {
2897
+ if (!key || INVALID_VAST_PARAM_KEY.test(key)) {
2898
+ toDelete.push(key);
2899
+ }
2900
+ });
2901
+ if (appName && appName.includes("&")) {
2902
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2903
+ try {
2904
+ for(var _iterator = appName.split("&").slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2905
+ var suffix = _step.value;
2906
+ var trimmed = suffix.trimStart();
2907
+ if (!trimmed) continue;
2908
+ toDelete.push(suffix, " ".concat(trimmed), trimmed);
2909
+ }
2910
+ } catch (err) {
2911
+ _didIteratorError = true;
2912
+ _iteratorError = err;
2913
+ } finally{
2914
+ try {
2915
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2916
+ _iterator.return();
2917
+ }
2918
+ } finally{
2919
+ if (_didIteratorError) {
2920
+ throw _iteratorError;
2921
+ }
2922
+ }
2923
+ }
2924
+ }
2925
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2926
+ try {
2927
+ for(var _iterator1 = new Set(toDelete)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2928
+ var key = _step1.value;
2929
+ if (key) params.delete(key);
2930
+ }
2931
+ } catch (err) {
2932
+ _didIteratorError1 = true;
2933
+ _iteratorError1 = err;
2934
+ } finally{
2935
+ try {
2936
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2937
+ _iterator1.return();
2938
+ }
2939
+ } finally{
2940
+ if (_didIteratorError1) {
2941
+ throw _iteratorError1;
2942
+ }
2943
+ }
2944
+ }
2945
+ }
2946
+ function normalizeVastTagUrl(raw) {
2947
+ if (!raw) return raw;
2948
+ try {
2949
+ var url = new URL(raw);
2950
+ var anValue = url.searchParams.get("an");
2951
+ if (anValue !== null) {
2952
+ var orphanFragments = [];
2953
+ url.searchParams.forEach(function(_value, key) {
2954
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2955
+ orphanFragments.push(key.trim());
2956
+ }
2957
+ });
2958
+ if (orphanFragments.length > 0) {
2959
+ var reconstructed = [
2960
+ anValue.trimEnd()
2961
+ ].concat(_to_consumable_array(orphanFragments)).filter(Boolean).join(" & ");
2962
+ url.searchParams.forEach(function(_value, key) {
2963
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2964
+ url.searchParams.delete(key);
2965
+ }
2966
+ });
2967
+ url.searchParams.set("an", reconstructed);
2968
+ return url.toString().replace(/([?&]an=)([^&]*)/, function(_match, prefix, val) {
2969
+ return prefix + val.replace(/\+/g, "%20");
2970
+ });
2971
+ }
2972
+ }
2973
+ removeBrokenAppNameOrphans(url.searchParams);
2974
+ return url.toString();
2975
+ } catch (unused) {
2976
+ return raw;
2977
+ }
2978
+ }
2391
2979
  function applyVastMacros(baseUrl, ctx) {
2980
+ var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
2392
2981
  var url;
2393
2982
  try {
2394
- url = new URL(baseUrl);
2983
+ url = new URL(normalizeVastTagUrl(expandedUrl));
2395
2984
  } catch (unused) {
2396
- return replaceCorrelatorFallback(baseUrl, ctx.correlator);
2985
+ return replaceCorrelatorFallback(expandedUrl, ctx.correlator);
2397
2986
  }
2398
2987
  var params = url.searchParams;
2988
+ removeBrokenAppNameOrphans(params, ctx.appName);
2399
2989
  params.set("correlator", ctx.correlator);
2400
2990
  if (ctx.isCtv) {
2401
2991
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2433,6 +3023,12 @@ function applyVastMacros(baseUrl, ctx) {
2433
3023
  if (!ctx.isCtv) {
2434
3024
  params.set("description_url", requestUrl);
2435
3025
  }
3026
+ } else {
3027
+ var existingUrl = params.get("url") || "";
3028
+ if (EXAMPLE_COM_URL.test(existingUrl)) {
3029
+ params.delete("url");
3030
+ params.delete("description_url");
3031
+ }
2436
3032
  }
2437
3033
  if (ctx.adWillPlayMuted != null) {
2438
3034
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
@@ -2444,6 +3040,7 @@ function applyVastMacros(baseUrl, ctx) {
2444
3040
  params.set("msid", ctx.appId);
2445
3041
  }
2446
3042
  if (ctx.appName) {
3043
+ removeBrokenAppNameOrphans(params, ctx.appName);
2447
3044
  params.set("an", ctx.appName);
2448
3045
  }
2449
3046
  if (ctx.sessionId) {
@@ -2454,15 +3051,7 @@ function applyVastMacros(baseUrl, ctx) {
2454
3051
  } else if (ctx.isCtv) {
2455
3052
  params.set("dth", "5");
2456
3053
  }
2457
- if (ctx.deviceId && ctx.deviceIdType) {
2458
- params.set("rdid", ctx.deviceId);
2459
- params.set("idtype", ctx.deviceIdType);
2460
- params.set("is_lat", ctx.limitAdTracking ? "1" : "0");
2461
- } else {
2462
- params.delete("rdid");
2463
- params.delete("idtype");
2464
- params.delete("is_lat");
2465
- }
3054
+ applyDeviceIdentityParams(params, ctx);
2466
3055
  if (!ctx.isCtv) {
2467
3056
  var consent = ctx.consent;
2468
3057
  if ((consent === null || consent === void 0 ? void 0 : consent.gdpr) != null) {
@@ -2480,7 +3069,7 @@ function applyVastMacros(baseUrl, ctx) {
2480
3069
  }
2481
3070
  var staleKeys = [];
2482
3071
  params.forEach(function(value, key) {
2483
- if (UNEXPANDED_MACRO_PATTERN.test(value)) {
3072
+ if (isMacroPlaceholder(value)) {
2484
3073
  staleKeys.push(key);
2485
3074
  }
2486
3075
  });
@@ -2504,6 +3093,7 @@ function applyVastMacros(baseUrl, ctx) {
2504
3093
  }
2505
3094
  }
2506
3095
  }
3096
+ removeBrokenAppNameOrphans(params, ctx.appName);
2507
3097
  return url.toString();
2508
3098
  }
2509
3099
  function replaceCorrelatorFallback(baseUrl, correlator) {
@@ -3754,276 +4344,10 @@ var Scte35CueManager = /*#__PURE__*/ function() {
3754
4344
  ]);
3755
4345
  return Scte35CueManager;
3756
4346
  }();
3757
- // src/utils/ctvVastSignals.ts
3758
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
3759
- var AIRY_APP_NAME = "AiryTV Movies & TV";
3760
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
3761
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3762
- var DEVICE_ID_STORAGE_KEYS = [
3763
- "rdid",
3764
- "ifa",
3765
- "advertisingId",
3766
- "advertising_id",
3767
- "deviceAdvertisingId",
3768
- "aaid",
3769
- "adid",
3770
- "rida",
3771
- "tifa"
3772
- ];
3773
- function resolveCtvVastSignals() {
3774
- var _ref, _bridgeSignals_limitAdTracking;
3775
- var bridgeSignals = readNativeBridgeSignals();
3776
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
3777
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || inferDeviceIdType();
3778
- var contentUrl = bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL;
3779
- return _object_spread_props(_object_spread({
3780
- contentUrl: contentUrl,
3781
- appId: AIRY_ANDROID_APP_ID,
3782
- appName: AIRY_APP_NAME,
3783
- sessionId: getOrCreateCtvSessionId()
3784
- }, deviceId ? {
3785
- deviceId: deviceId
3786
- } : {}, deviceId && deviceIdType ? {
3787
- deviceIdType: deviceIdType
3788
- } : {}, deviceId ? {
3789
- limitAdTracking: (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false
3790
- } : {}), {
3791
- deviceTypeHint: 5
3792
- });
3793
- }
3794
- function getOrCreateCtvSessionId() {
3795
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
3796
- if (existing) {
3797
- return existing;
3798
- }
3799
- var sessionId = createUuid();
3800
- try {
3801
- var _window_localStorage;
3802
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
3803
- } catch (unused) {}
3804
- return sessionId;
3805
- }
3806
- function createUuid() {
3807
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3808
- return crypto.randomUUID();
3809
- }
3810
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
3811
- var value = Math.floor(Math.random() * 16);
3812
- var nibble = char === "x" ? value : value & 3 | 8;
3813
- return nibble.toString(16);
3814
- });
3815
- }
3816
- function readNativeBridgeSignals() {
3817
- if (typeof window === "undefined") {
3818
- return {};
3819
- }
3820
- var candidates = [
3821
- window.__STORMCLOUD_CTV_AD_INFO__,
3822
- window.__STORMCLOUD_CTV__,
3823
- window.stormcloudCtv,
3824
- window.AiryTV,
3825
- window.Android
3826
- ].filter(Boolean);
3827
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3828
- try {
3829
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3830
- var source = _step.value;
3831
- var contentUrl = readBridgeValue(source, [
3832
- "contentUrl",
3833
- "url",
3834
- "videoUrl",
3835
- "canonicalUrl"
3836
- ]) || void 0;
3837
- var deviceId = readBridgeValue(source, [
3838
- "rdid",
3839
- "ifa",
3840
- "advertisingId",
3841
- "adId",
3842
- "deviceId"
3843
- ]) || void 0;
3844
- if (!contentUrl && !deviceId) continue;
3845
- var deviceIdType = readBridgeValue(source, [
3846
- "idtype",
3847
- "deviceIdType",
3848
- "advertisingIdType"
3849
- ]) || inferDeviceIdType();
3850
- var limitAdTracking = readBridgeBoolean(source, [
3851
- "is_lat",
3852
- "limitAdTracking",
3853
- "limitedAdTracking",
3854
- "lat"
3855
- ]);
3856
- return _object_spread({}, contentUrl ? {
3857
- contentUrl: contentUrl
3858
- } : {}, deviceId ? {
3859
- deviceId: deviceId
3860
- } : {}, deviceId && deviceIdType ? {
3861
- deviceIdType: deviceIdType
3862
- } : {}, deviceId && limitAdTracking != null ? {
3863
- limitAdTracking: limitAdTracking
3864
- } : {});
3865
- }
3866
- } catch (err) {
3867
- _didIteratorError = true;
3868
- _iteratorError = err;
3869
- } finally{
3870
- try {
3871
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3872
- _iterator.return();
3873
- }
3874
- } finally{
3875
- if (_didIteratorError) {
3876
- throw _iteratorError;
3877
- }
3878
- }
3879
- }
3880
- return {};
3881
- }
3882
- function readBridgeValue(source, keys) {
3883
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3884
- try {
3885
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3886
- var key = _step.value;
3887
- var value = source === null || source === void 0 ? void 0 : source[key];
3888
- if (typeof value === "string" && value) {
3889
- return value;
3890
- }
3891
- if (typeof value === "function") {
3892
- try {
3893
- var result = value.call(source);
3894
- if (typeof result === "string" && result) {
3895
- return result;
3896
- }
3897
- } catch (unused) {}
3898
- }
3899
- }
3900
- } catch (err) {
3901
- _didIteratorError = true;
3902
- _iteratorError = err;
3903
- } finally{
3904
- try {
3905
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3906
- _iterator.return();
3907
- }
3908
- } finally{
3909
- if (_didIteratorError) {
3910
- throw _iteratorError;
3911
- }
3912
- }
3913
- }
3914
- return void 0;
3915
- }
3916
- function readBridgeBoolean(source, keys) {
3917
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3918
- try {
3919
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3920
- var key = _step.value;
3921
- var value = source === null || source === void 0 ? void 0 : source[key];
3922
- var normalized = normalizeBoolean(value);
3923
- if (normalized != null) {
3924
- return normalized;
3925
- }
3926
- if (typeof value === "function") {
3927
- try {
3928
- var result = normalizeBoolean(value.call(source));
3929
- if (result != null) {
3930
- return result;
3931
- }
3932
- } catch (unused) {}
3933
- }
3934
- }
3935
- } catch (err) {
3936
- _didIteratorError = true;
3937
- _iteratorError = err;
3938
- } finally{
3939
- try {
3940
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3941
- _iterator.return();
3942
- }
3943
- } finally{
3944
- if (_didIteratorError) {
3945
- throw _iteratorError;
3946
- }
3947
- }
3948
- }
3949
- return void 0;
3950
- }
3951
- function readStoredDeviceId() {
3952
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3953
- try {
3954
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3955
- var key = _step.value;
3956
- var value = readStoredString(key);
3957
- if (value) {
3958
- return value;
3959
- }
3960
- }
3961
- } catch (err) {
3962
- _didIteratorError = true;
3963
- _iteratorError = err;
3964
- } finally{
3965
- try {
3966
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3967
- _iterator.return();
3968
- }
3969
- } finally{
3970
- if (_didIteratorError) {
3971
- throw _iteratorError;
3972
- }
3973
- }
3974
- }
3975
- return void 0;
3976
- }
3977
- function readStoredString(key) {
3978
- if (typeof window === "undefined") {
3979
- return void 0;
3980
- }
3981
- try {
3982
- var _window_localStorage;
3983
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
3984
- return value || void 0;
3985
- } catch (unused) {
3986
- return void 0;
3987
- }
3988
- }
3989
- function readStoredLimitAdTracking() {
3990
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
3991
- }
3992
- function normalizeBoolean(value) {
3993
- if (typeof value === "boolean") {
3994
- return value;
3995
- }
3996
- if (typeof value === "number") {
3997
- return value === 1;
3998
- }
3999
- if (typeof value === "string") {
4000
- var normalized = value.toLowerCase();
4001
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
4002
- return true;
4003
- }
4004
- if (normalized === "0" || normalized === "false" || normalized === "no") {
4005
- return false;
4006
- }
4007
- }
4008
- return void 0;
4009
- }
4010
- function inferDeviceIdType() {
4011
- if (typeof navigator === "undefined") {
4012
- return void 0;
4013
- }
4014
- var ua = navigator.userAgent;
4015
- if (/Roku/i.test(ua)) return "rida";
4016
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
4017
- if (/AppleTV/i.test(ua)) return "tvOS";
4018
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
4019
- if (/Web0S|webOS|LG/i.test(ua)) return "lgudid";
4020
- if (/Android|Google TV/i.test(ua)) return "aaid";
4021
- return void 0;
4022
- }
4023
- // src/player/VmapManager.ts
4024
- var VmapManager = /*#__PURE__*/ function() {
4025
- function VmapManager(config, video) {
4026
- _class_call_check(this, VmapManager);
4347
+ // src/player/AdConfigManager.ts
4348
+ var AdConfigManager = /*#__PURE__*/ function() {
4349
+ function AdConfigManager(config, video) {
4350
+ _class_call_check(this, AdConfigManager);
4027
4351
  this.vmapBreaks = [];
4028
4352
  this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
4029
4353
  this.streamCorrelator = generateCorrelator();
@@ -4035,7 +4359,7 @@ var VmapManager = /*#__PURE__*/ function() {
4035
4359
  this.config = config;
4036
4360
  this.video = video;
4037
4361
  }
4038
- _create_class(VmapManager, [
4362
+ _create_class(AdConfigManager, [
4039
4363
  {
4040
4364
  key: "debug",
4041
4365
  get: function get() {
@@ -4053,7 +4377,7 @@ var VmapManager = /*#__PURE__*/ function() {
4053
4377
  key: "fetchAdConfiguration",
4054
4378
  value: function fetchAdConfiguration() {
4055
4379
  return _async_to_generator(function() {
4056
- var _data_response_ima_publisherdeskima, _data_response_ima, _data_response, _data_response_options_vast_cue_tones, _data_response_options_vast, _data_response_options, _data_response1, vastMode, vastEndpoint, apiUrl, headers, response, data, imaPayload, numberAds;
4380
+ var _data_response_ima_publisherdeskima, _data_response_ima, _data_response, _data_response_options_vast_cue_tones, _data_response_options_vast, _data_response_options, _data_response1, vastMode, vastEndpoint, apiUrl, headers, response, data, imaPayload, decodedPayload, numberAds;
4057
4381
  return _ts_generator(this, function(_state) {
4058
4382
  switch(_state.label){
4059
4383
  case 0:
@@ -4097,7 +4421,7 @@ var VmapManager = /*#__PURE__*/ function() {
4097
4421
  ];
4098
4422
  }
4099
4423
  if (this.config.vastTagUrl) {
4100
- this.apiVastTagUrl = this.config.vastTagUrl;
4424
+ this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
4101
4425
  if (this.debug) {
4102
4426
  console.log("[StormcloudVideoPlayer] Using custom VAST tag URL:", this.apiVastTagUrl);
4103
4427
  }
@@ -4137,9 +4461,16 @@ var VmapManager = /*#__PURE__*/ function() {
4137
4461
  data = _state.sent();
4138
4462
  imaPayload = (_data_response = data.response) === null || _data_response === void 0 ? void 0 : (_data_response_ima = _data_response.ima) === null || _data_response_ima === void 0 ? void 0 : (_data_response_ima_publisherdeskima = _data_response_ima["publisherdesk.ima"]) === null || _data_response_ima_publisherdeskima === void 0 ? void 0 : _data_response_ima_publisherdeskima.payload;
4139
4463
  if (imaPayload) {
4140
- this.apiVastTagUrl = decodeURIComponent(imaPayload);
4464
+ decodedPayload = imaPayload;
4465
+ try {
4466
+ decodedPayload = decodeURIComponent(imaPayload);
4467
+ } catch (unused) {
4468
+ console.warn("[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:", imaPayload);
4469
+ }
4470
+ console.log("[StormcloudVideoPlayer] Raw VAST tag URL (from API):", decodedPayload);
4471
+ this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);
4141
4472
  if (this.debug) {
4142
- console.log("[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:", this.apiVastTagUrl);
4473
+ console.log("[StormcloudVideoPlayer] Normalized VAST tag URL:", this.apiVastTagUrl);
4143
4474
  }
4144
4475
  } else {
4145
4476
  if (this.debug) {
@@ -4452,28 +4783,30 @@ var VmapManager = /*#__PURE__*/ function() {
4452
4783
  for(var i = 0; i < count; i++){
4453
4784
  this.adRequestPositionInBreak++;
4454
4785
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
4455
- var ctvSignals = this.config.ctvAdRequest ? resolveCtvVastSignals() : void 0;
4786
+ var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
4456
4787
  var urlWithMacros = applyVastMacros(baseUrl, {
4457
4788
  correlator: generateCorrelator(),
4458
4789
  streamCorrelator: this.streamCorrelator,
4459
4790
  pod: this.podCounter > 0 ? this.podCounter : void 0,
4460
4791
  adPosition: this.adRequestPositionInBreak,
4461
- isCtv: this.config.ctvAdRequest,
4462
- contentUrl: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.contentUrl,
4463
- pageUrl: !this.config.ctvAdRequest && typeof window !== "undefined" ? window.location.href : void 0,
4792
+ isCtv: envSignals.isCtv,
4793
+ contentUrl: envSignals.contentUrl,
4794
+ pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? window.location.href : void 0,
4464
4795
  adWillPlayMuted: adWillPlayMuted,
4465
4796
  adWillAutoPlay: !!this.config.autoplay,
4466
- appId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appId,
4467
- appName: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appName,
4468
- sessionId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.sessionId,
4469
- deviceId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceId,
4470
- deviceIdType: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceIdType,
4471
- limitAdTracking: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.limitAdTracking,
4472
- deviceTypeHint: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceTypeHint,
4797
+ appId: envSignals.appId,
4798
+ appName: envSignals.appName,
4799
+ sessionId: envSignals.sessionId,
4800
+ deviceId: envSignals.deviceId,
4801
+ deviceIdType: envSignals.deviceIdType,
4802
+ limitAdTracking: envSignals.limitAdTracking,
4803
+ deviceTypeHint: envSignals.deviceTypeHint,
4473
4804
  adTest: this.config.adTest,
4474
4805
  consent: this.consentSignals
4475
4806
  });
4476
- urls.push(palNonce.injectNonce(urlWithMacros));
4807
+ var finalUrl = palNonce.injectNonce(urlWithMacros);
4808
+ console.log("[StormcloudVideoPlayer] Resolved ad request URL (pod=".concat(this.podCounter, ", pos=").concat(this.adRequestPositionInBreak, "):"), finalUrl);
4809
+ urls.push(finalUrl);
4477
4810
  }
4478
4811
  return urls;
4479
4812
  }
@@ -4522,7 +4855,7 @@ var VmapManager = /*#__PURE__*/ function() {
4522
4855
  }
4523
4856
  }
4524
4857
  ]);
4525
- return VmapManager;
4858
+ return AdConfigManager;
4526
4859
  }();
4527
4860
  // src/player/AdTimingService.ts
4528
4861
  var AdTimingService = /*#__PURE__*/ function() {
@@ -6249,7 +6582,7 @@ function resizePlayer(video, adPlayer, debug) {
6249
6582
  }
6250
6583
  // src/player/AdBreakOrchestrator.ts
6251
6584
  var AdBreakOrchestrator = /*#__PURE__*/ function() {
6252
- function AdBreakOrchestrator(host, timing, preloadPool, vmap, cueManager, placeholder) {
6585
+ function AdBreakOrchestrator(host, timing, preloadPool, adConfig, cueManager, placeholder) {
6253
6586
  _class_call_check(this, AdBreakOrchestrator);
6254
6587
  this.inAdBreak = false;
6255
6588
  this.showAds = false;
@@ -6264,7 +6597,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6264
6597
  this.host = host;
6265
6598
  this.timing = timing;
6266
6599
  this.preloadPool = preloadPool;
6267
- this.vmap = vmap;
6600
+ this.adConfig = adConfig;
6268
6601
  this.cueManager = cueManager;
6269
6602
  this.placeholder = placeholder;
6270
6603
  }
@@ -6430,7 +6763,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6430
6763
  }
6431
6764
  this.pendingAdBreak = null;
6432
6765
  this.cueManager.pendingScte35CueKey = void 0;
6433
- this.vmap.podAssignedByPrefetch = false;
6766
+ this.adConfig.podAssignedByPrefetch = false;
6434
6767
  }
6435
6768
  },
6436
6769
  {
@@ -6444,15 +6777,15 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6444
6777
  return _ts_generator(this, function(_state) {
6445
6778
  switch(_state.label){
6446
6779
  case 0:
6447
- scheduled = this.vmap.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6780
+ scheduled = this.adConfig.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6448
6781
  if (scheduled) {
6449
- this.vmap.consumedVmapBreakIds.add(this.vmap.getAdBreakKey(scheduled));
6782
+ this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));
6450
6783
  }
6451
- tags = this.vmap.selectVastTagsForBreak(scheduled);
6784
+ tags = this.adConfig.selectVastTagsForBreak(scheduled);
6452
6785
  if (tags && tags.length > 0 && tags[0]) {
6453
6786
  baseVastUrl = tags[0];
6454
- } else if (this.vmap.apiVastTagUrl) {
6455
- baseVastUrl = this.vmap.apiVastTagUrl;
6787
+ } else if (this.adConfig.apiVastTagUrl) {
6788
+ baseVastUrl = this.adConfig.apiVastTagUrl;
6456
6789
  } else {
6457
6790
  this.clearPendingAdBreak();
6458
6791
  return [
@@ -6470,10 +6803,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6470
6803
  this.continuousFetchingActive = true;
6471
6804
  this.isShowingPlaceholder = false;
6472
6805
  this.timing.totalAdRequestsInBreak = 0;
6473
- if (this.vmap.podAssignedByPrefetch) {
6474
- this.vmap.podAssignedByPrefetch = false;
6806
+ if (this.adConfig.podAssignedByPrefetch) {
6807
+ this.adConfig.podAssignedByPrefetch = false;
6475
6808
  } else {
6476
- this.vmap.beginNewAdPod();
6809
+ this.adConfig.beginNewAdPod();
6477
6810
  }
6478
6811
  currentMuted = this.host.video.muted;
6479
6812
  currentVolume = this.host.video.volume;
@@ -7745,7 +8078,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7745
8078
  return _this.adBreak.inAdBreak;
7746
8079
  }
7747
8080
  });
7748
- this.vmap = new VmapManager(this.config, this.video);
8081
+ this.adConfig = new AdConfigManager(this.config, this.video);
7749
8082
  this.timing = new AdTimingService(this.config, this.video, {
7750
8083
  onAdStopTimerFired: function onAdStopTimerFired() {
7751
8084
  return _this.onAdStopTimerFired();
@@ -7825,7 +8158,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7825
8158
  generateVastUrls: function generateVastUrls(base, count) {
7826
8159
  return _this.generateVastUrls(base, count);
7827
8160
  }
7828
- }, this.timing, this.preloadPool, this.vmap, this.cueManager, this.placeholder);
8161
+ }, this.timing, this.preloadPool, this.adConfig, this.cueManager, this.placeholder);
7829
8162
  }
7830
8163
  _create_class(StormcloudVideoPlayer, [
7831
8164
  {
@@ -7853,7 +8186,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7853
8186
  {
7854
8187
  key: "generateVastUrls",
7855
8188
  value: function generateVastUrls(baseUrl, count) {
7856
- return this.vmap.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
8189
+ return this.adConfig.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
7857
8190
  }
7858
8191
  },
7859
8192
  {
@@ -7881,7 +8214,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7881
8214
  ]);
7882
8215
  return [
7883
8216
  4,
7884
- this.vmap.fetchAdConfiguration()
8217
+ this.adConfig.fetchAdConfiguration()
7885
8218
  ];
7886
8219
  case 2:
7887
8220
  _state.sent();
@@ -7908,9 +8241,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7908
8241
  continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
7909
8242
  }).catch(function() {});
7910
8243
  fetchConsentSignals().then(function(signals) {
7911
- _this.vmap.consentSignals = signals;
8244
+ _this.adConfig.consentSignals = signals;
7912
8245
  }).catch(function() {});
7913
- this.vmap.initializeTracking();
8246
+ this.adConfig.initializeTracking();
7914
8247
  if (!this.hlsEngine.shouldUseNativeHls(function() {
7915
8248
  return _this.getStreamType();
7916
8249
  })) return [
@@ -7945,14 +8278,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7945
8278
  return _async_to_generator(function() {
7946
8279
  var prerollKey, adBehavior;
7947
8280
  return _ts_generator(this, function(_state) {
7948
- if (!this.vmap.isVmapEnabled() && !isLive && this.vmap.vmapBreaks.length === 0 && this.vmap.apiVastTagUrl) {
8281
+ if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {
7949
8282
  prerollKey = "synthetic-vod-preroll";
7950
- if (!this.vmap.consumedVmapBreakIds.has(prerollKey)) {
7951
- this.vmap.vmapBreaks = [
8283
+ if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {
8284
+ this.adConfig.vmapBreaks = [
7952
8285
  {
7953
8286
  id: prerollKey,
7954
8287
  startTimeMs: 0,
7955
- vastTagUrl: this.vmap.apiVastTagUrl
8288
+ vastTagUrl: this.adConfig.apiVastTagUrl
7956
8289
  }
7957
8290
  ];
7958
8291
  if (this.debug) {
@@ -8219,19 +8552,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8219
8552
  key: "startAdPrefetch",
8220
8553
  value: function startAdPrefetch(marker, fragmentSn, cueKey) {
8221
8554
  if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;
8222
- var scheduled = this.vmap.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8223
- var tags = this.vmap.selectVastTagsForBreak(scheduled);
8555
+ var scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8556
+ var tags = this.adConfig.selectVastTagsForBreak(scheduled);
8224
8557
  var baseVastUrl;
8225
8558
  if (tags && tags.length > 0 && tags[0]) {
8226
8559
  baseVastUrl = tags[0];
8227
- } else if (this.vmap.apiVastTagUrl) {
8228
- baseVastUrl = this.vmap.apiVastTagUrl;
8560
+ } else if (this.adConfig.apiVastTagUrl) {
8561
+ baseVastUrl = this.adConfig.apiVastTagUrl;
8229
8562
  } else {
8230
8563
  if (this.debug) console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
8231
8564
  return;
8232
8565
  }
8233
- this.vmap.beginNewAdPod();
8234
- this.vmap.podAssignedByPrefetch = true;
8566
+ this.adConfig.beginNewAdPod();
8567
+ this.adConfig.podAssignedByPrefetch = true;
8235
8568
  var generatedUrls = this.generateVastUrls(baseVastUrl, 1);
8236
8569
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
8237
8570
  marker: marker
@@ -8266,10 +8599,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8266
8599
  key: "onTimeUpdate",
8267
8600
  value: function onTimeUpdate(currentTimeSec) {
8268
8601
  var _this = this;
8269
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8602
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8270
8603
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8271
8604
  var nowMs = currentTimeSec * 1e3;
8272
- var breakToPlay = this.vmap.findBreakForTime(nowMs);
8605
+ var breakToPlay = this.adConfig.findBreakForTime(nowMs);
8273
8606
  if (breakToPlay) {
8274
8607
  void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
8275
8608
  if (_this.debug) {
@@ -8283,11 +8616,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8283
8616
  key: "onVideoEnded",
8284
8617
  value: function onVideoEnded() {
8285
8618
  var _this = this;
8286
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8619
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8287
8620
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8288
8621
  var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
8289
- var postroll = this.vmap.vmapBreaks.find(function(b) {
8290
- return b.startTimeMs === -1 && !_this.vmap.consumedVmapBreakIds.has(_this.vmap.getAdBreakKey(b));
8622
+ var postroll = this.adConfig.vmapBreaks.find(function(b) {
8623
+ return b.startTimeMs === -1 && !_this.adConfig.consumedVmapBreakIds.has(_this.adConfig.getAdBreakKey(b));
8291
8624
  });
8292
8625
  if (postroll) {
8293
8626
  void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
@@ -8306,11 +8639,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8306
8639
  return _ts_generator(this, function(_state) {
8307
8640
  switch(_state.label){
8308
8641
  case 0:
8309
- key = this.vmap.getAdBreakKey(adBreak);
8310
- if (this.vmap.consumedVmapBreakIds.has(key)) return [
8642
+ key = this.adConfig.getAdBreakKey(adBreak);
8643
+ if (this.adConfig.consumedVmapBreakIds.has(key)) return [
8311
8644
  2
8312
8645
  ];
8313
- breakStartMs = this.vmap.resolveBreakStartMs(adBreak);
8646
+ breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);
8314
8647
  if (breakStartMs == null) return [
8315
8648
  2
8316
8649
  ];
@@ -8321,8 +8654,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8321
8654
  3,
8322
8655
  4
8323
8656
  ];
8324
- this.vmap.consumedVmapBreakIds.add(key);
8325
- tags = this.vmap.selectVastTagsForBreak(adBreak);
8657
+ this.adConfig.consumedVmapBreakIds.add(key);
8658
+ tags = this.adConfig.selectVastTagsForBreak(adBreak);
8326
8659
  if (!tags || tags.length === 0) return [
8327
8660
  2
8328
8661
  ];
@@ -8514,7 +8847,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8514
8847
  this.video.removeEventListener("emptied", this.emptiedHandler);
8515
8848
  delete this.emptiedHandler;
8516
8849
  }
8517
- this.vmap.destroyTracking();
8850
+ this.adConfig.destroyTracking();
8518
8851
  this.hlsEngine.destroy();
8519
8852
  (_this_adPlayer = this.adPlayer) === null || _this_adPlayer === void 0 ? void 0 : _this_adPlayer.destroy();
8520
8853
  if (this.palPlaybackStarted) {