stormcloud-video-player 0.8.22 → 0.8.24

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.
@@ -1510,300 +1510,759 @@ function publishMQTT(topic, payload) {
1510
1510
  return false;
1511
1511
  }
1512
1512
  }
1513
- // src/utils/tracking.ts
1514
- var cachedBrowserId = null;
1515
- function getClientInfo() {
1516
- var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
1513
+ // src/utils/vastEnvironmentSignals.ts
1514
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
1515
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
1516
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
1517
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
1518
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
1519
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
1520
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
1521
+ var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
1522
+ var LG_TEST_APP_ID = "com.hulu.plus";
1523
+ var LG_TEST_APP_NAME = "Hulu";
1524
+ var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
1525
+ var _lgTestDeviceId;
1526
+ function getLgTestDeviceId() {
1527
+ if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
1528
+ return _lgTestDeviceId;
1529
+ }
1530
+ function isLgWebOS() {
1531
+ if (typeof navigator === "undefined") return false;
1532
+ return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
1533
+ }
1534
+ function getDefaultAppId() {
1535
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
1517
1536
  var ua = navigator.userAgent;
1518
- var platform = navigator.platform;
1519
- var vendor = navigator.vendor || "";
1520
- var maxTouchPoints = navigator.maxTouchPoints || 0;
1521
- var memory = navigator.deviceMemory || null;
1522
- var hardwareConcurrency = navigator.hardwareConcurrency || 1;
1523
- var screenInfo = {
1524
- width: (_screen = screen) === null || _screen === void 0 ? void 0 : _screen.width,
1525
- height: (_screen1 = screen) === null || _screen1 === void 0 ? void 0 : _screen1.height,
1526
- availWidth: (_screen2 = screen) === null || _screen2 === void 0 ? void 0 : _screen2.availWidth,
1527
- availHeight: (_screen3 = screen) === null || _screen3 === void 0 ? void 0 : _screen3.availHeight,
1528
- orientation: ((_screen4 = screen) === null || _screen4 === void 0 ? void 0 : (_screen_orientation = _screen4.orientation) === null || _screen_orientation === void 0 ? void 0 : _screen_orientation.type) || "",
1529
- pixelDepth: (_screen5 = screen) === null || _screen5 === void 0 ? void 0 : _screen5.pixelDepth
1530
- };
1531
- var deviceType = "desktop";
1532
- var brand = "Unknown";
1533
- var os = "Unknown";
1534
- var model = "";
1535
- var isSmartTV = false;
1536
- var isAndroid = false;
1537
- var isWebView = false;
1538
- var isWebApp = false;
1539
- if (ua.includes("Web0S")) {
1540
- brand = "LG";
1541
- os = "webOS";
1542
- isSmartTV = true;
1543
- deviceType = "tv";
1544
- var webosMatch = ua.match(/Web0S\/([^\s]+)/);
1545
- model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
1546
- } else if (ua.includes("Tizen")) {
1547
- brand = "Samsung";
1548
- os = "Tizen";
1549
- isSmartTV = true;
1550
- deviceType = "tv";
1551
- var tizenMatch = ua.match(/Tizen\/([^\s]+)/);
1552
- var tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
1553
- model = tizenMatch ? "Tizen ".concat(tizenMatch[1], " ").concat(tvMatch).trim() : "Tizen TV";
1554
- } else if (ua.includes("Philips")) {
1555
- brand = "Philips";
1556
- os = "Saphi";
1557
- isSmartTV = true;
1558
- deviceType = "tv";
1559
- } else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
1560
- brand = "Sharp";
1561
- os = "Android TV";
1562
- isSmartTV = true;
1563
- deviceType = "tv";
1564
- } else if (ua.includes("Android") && (ua.includes("Sony") || vendor.includes("Sony"))) {
1565
- brand = "Sony";
1566
- os = "Android TV";
1567
- isSmartTV = true;
1568
- deviceType = "tv";
1569
- } else if (ua.includes("Android") && (ua.includes("NetCast") || ua.includes("LG"))) {
1570
- brand = "LG";
1571
- os = "Android TV";
1572
- isSmartTV = true;
1573
- deviceType = "tv";
1574
- } else if (ua.includes(" Roku") || ua.includes("Roku/")) {
1575
- brand = "Roku";
1576
- os = "Roku OS";
1577
- isSmartTV = true;
1578
- deviceType = "tv";
1579
- } else if (ua.includes("AppleTV")) {
1580
- brand = "Apple";
1581
- os = "tvOS";
1582
- isSmartTV = true;
1583
- deviceType = "tv";
1537
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
1538
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
1539
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
1540
+ return AIRY_ANDROID_APP_ID;
1541
+ }
1542
+ var DEVICE_ID_STORAGE_KEYS = [
1543
+ "rdid",
1544
+ "ifa",
1545
+ "advertisingId",
1546
+ "advertising_id",
1547
+ "deviceAdvertisingId",
1548
+ "aaid",
1549
+ "adid",
1550
+ "rida",
1551
+ "tifa",
1552
+ "lgudid"
1553
+ ];
1554
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
1555
+ "aaid",
1556
+ "adid"
1557
+ ]);
1558
+ function resolveVastEnvironmentSignals(isCtv) {
1559
+ var _ref;
1560
+ var bridgeSignals = readNativeBridgeSignals();
1561
+ var platformDevice = readPlatformNativeDeviceId();
1562
+ var lg = isCtv && isLgWebOS();
1563
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId || (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : void 0);
1564
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType() || (lg ? "lgudid" : void 0);
1565
+ var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
1566
+ var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
1567
+ if (isCtv) {
1568
+ return _object_spread_props(_object_spread({
1569
+ isCtv: true,
1570
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
1571
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
1572
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
1573
+ sessionId: getOrCreateCtvSessionId()
1574
+ }, deviceId ? {
1575
+ deviceId: deviceId
1576
+ } : {}, deviceIdType ? {
1577
+ deviceIdType: deviceIdType
1578
+ } : {}, limitAdTracking != null ? {
1579
+ limitAdTracking: limitAdTracking
1580
+ } : {}), {
1581
+ deviceTypeHint: 5
1582
+ });
1584
1583
  }
1585
- if (ua.includes("Android")) {
1586
- isAndroid = true;
1587
- os = "Android";
1588
- deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
1589
- if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
1590
- deviceType = "tv";
1591
- isSmartTV = true;
1592
- brand = brand === "Unknown" ? "Android TV" : brand;
1593
- }
1594
- var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
1595
- if (androidModelMatch && androidModelMatch[1]) {
1596
- model = androidModelMatch[1];
1597
- }
1584
+ return _object_spread({
1585
+ isCtv: false
1586
+ }, deviceId ? {
1587
+ deviceId: deviceId
1588
+ } : {}, deviceIdType ? {
1589
+ deviceIdType: deviceIdType
1590
+ } : {}, limitAdTracking != null ? {
1591
+ limitAdTracking: limitAdTracking
1592
+ } : {});
1593
+ }
1594
+ function inferDeviceIdType() {
1595
+ if (typeof navigator === "undefined") {
1596
+ return void 0;
1598
1597
  }
1599
- if (/iPad|iPhone|iPod/.test(ua)) {
1600
- os = "iOS";
1601
- deviceType = "mobile";
1602
- brand = "Apple";
1603
- if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
1604
- deviceType = "tablet";
1605
- }
1598
+ var ua = navigator.userAgent;
1599
+ if (/Roku/i.test(ua)) return "rida";
1600
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
1601
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
1602
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
1603
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
1604
+ if (/Android|Google TV/i.test(ua)) return "aaid";
1605
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
1606
+ return void 0;
1607
+ }
1608
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
1609
+ if (!tagType || !runtimeType) return false;
1610
+ var tag = tagType.toLowerCase();
1611
+ var runtime = runtimeType.toLowerCase();
1612
+ if (tag === runtime) return true;
1613
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
1614
+ }
1615
+ function resolveNativeDeviceId() {
1616
+ var bridgeSignals = readNativeBridgeSignals();
1617
+ var platformDevice = readPlatformNativeDeviceId();
1618
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
1619
+ if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {
1620
+ return void 0;
1606
1621
  }
1607
- if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
1608
- if (ua.includes("Windows")) {
1609
- os = "Windows";
1610
- deviceType = "desktop";
1611
- } else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
1612
- os = "macOS";
1613
- deviceType = "desktop";
1614
- if (maxTouchPoints > 1) deviceType = "tablet";
1615
- } else if (ua.includes("Linux")) {
1616
- os = "Linux";
1617
- deviceType = "desktop";
1618
- }
1622
+ return deviceId;
1623
+ }
1624
+ function getOrCreateStoredUuid(storageKey) {
1625
+ if (typeof window === "undefined") {
1626
+ return void 0;
1619
1627
  }
1620
- if (brand === "Unknown") {
1621
- if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
1622
- if (vendor.includes("Apple")) brand = "Apple";
1623
- if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
1628
+ var existing = readStoredString(storageKey);
1629
+ if (existing) {
1630
+ return existing;
1624
1631
  }
1625
- isWebView = /wv|WebView|Linux; U;/.test(ua);
1626
- if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
1627
- isWebView = true;
1632
+ var id = createUuid();
1633
+ try {
1634
+ var _window_localStorage;
1635
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(storageKey, id);
1636
+ } catch (unused) {}
1637
+ return id;
1638
+ }
1639
+ function getOrCreateCtvSessionId() {
1640
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
1641
+ if (existing) {
1642
+ return existing;
1628
1643
  }
1629
- isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_window_screen = window.screen) === null || _window_screen === void 0 ? void 0 : (_window_screen_orientation = _window_screen.orientation) === null || _window_screen_orientation === void 0 ? void 0 : _window_screen_orientation.angle) !== void 0;
1630
- return {
1631
- brand: brand,
1632
- os: os,
1633
- model: model || ua.substring(0, 50) + "...",
1634
- deviceType: deviceType,
1635
- isSmartTV: isSmartTV,
1636
- isAndroid: isAndroid,
1637
- isWebView: isWebView,
1638
- isWebApp: isWebApp,
1639
- domain: window.location.hostname,
1640
- origin: window.location.origin,
1641
- path: window.location.pathname,
1642
- userAgent: ua,
1643
- vendor: vendor,
1644
- platform: platform,
1645
- screen: screenInfo,
1646
- hardwareConcurrency: hardwareConcurrency,
1647
- deviceMemory: memory,
1648
- maxTouchPoints: maxTouchPoints,
1649
- language: navigator.language,
1650
- languages: ((_navigator_languages = navigator.languages) === null || _navigator_languages === void 0 ? void 0 : _navigator_languages.join(",")) || "",
1651
- cookieEnabled: navigator.cookieEnabled,
1652
- doNotTrack: navigator.doNotTrack || "",
1653
- referrer: document.referrer,
1654
- visibilityState: document.visibilityState
1655
- };
1644
+ var sessionId = createUuid();
1645
+ try {
1646
+ var _window_localStorage;
1647
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
1648
+ } catch (unused) {}
1649
+ return sessionId;
1656
1650
  }
1657
- function getBrowserID(clientInfo) {
1658
- return _async_to_generator(function() {
1659
- var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
1660
- return _ts_generator(this, function(_state) {
1661
- switch(_state.label){
1662
- case 0:
1663
- if (cachedBrowserId) {
1664
- return [
1665
- 2,
1666
- cachedBrowserId
1667
- ];
1668
- }
1669
- fingerprintString = JSON.stringify(clientInfo);
1670
- if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
1671
- 3,
1672
- 5
1673
- ];
1674
- _state.label = 1;
1675
- case 1:
1676
- _state.trys.push([
1677
- 1,
1678
- 4,
1679
- ,
1680
- 5
1681
- ]);
1682
- return [
1683
- 4,
1684
- crypto.subtle.digest("SHA-256", new Uint8Array([
1685
- 1,
1686
- 2,
1687
- 3
1688
- ]))
1689
- ];
1690
- case 2:
1691
- _state.sent();
1692
- if (typeof TextEncoder !== "undefined") {
1693
- encodedData = new TextEncoder().encode(fingerprintString);
1694
- } else {
1695
- utf8 = unescape(encodeURIComponent(fingerprintString));
1696
- buffer = new Uint8Array(utf8.length);
1697
- for(i = 0; i < utf8.length; i++){
1698
- buffer[i] = utf8.charCodeAt(i);
1699
- }
1700
- encodedData = buffer;
1701
- }
1702
- return [
1703
- 4,
1704
- crypto.subtle.digest("SHA-256", encodedData)
1705
- ];
1706
- case 3:
1707
- hashBuffer = _state.sent();
1708
- hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
1709
- return b.toString(16).padStart(2, "0");
1710
- }).join("");
1711
- cachedBrowserId = hashHex;
1712
- return [
1713
- 2,
1714
- hashHex
1715
- ];
1716
- case 4:
1717
- unused = _state.sent();
1718
- console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
1719
- return [
1720
- 3,
1721
- 5
1722
- ];
1723
- case 5:
1724
- hash = 0;
1725
- for(i1 = 0; i1 < fingerprintString.length; i1++){
1726
- char = fingerprintString.charCodeAt(i1);
1727
- hash = (hash << 5) - hash + char;
1728
- hash = hash & hash;
1729
- }
1730
- fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
1731
- timestamp = Date.now().toString(16).padStart(12, "0");
1732
- random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
1733
- cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, "0");
1734
- return [
1735
- 2,
1736
- cachedBrowserId
1737
- ];
1651
+ function createUuid() {
1652
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1653
+ return crypto.randomUUID();
1654
+ }
1655
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
1656
+ var value = Math.floor(Math.random() * 16);
1657
+ var nibble = char === "x" ? value : value & 3 | 8;
1658
+ return nibble.toString(16);
1659
+ });
1660
+ }
1661
+ function readPlatformNativeDeviceId() {
1662
+ if (typeof window === "undefined") return {};
1663
+ try {
1664
+ var _window_webapis;
1665
+ var adinfo = (_window_webapis = window.webapis) === null || _window_webapis === void 0 ? void 0 : _window_webapis.adinfo;
1666
+ if (adinfo) {
1667
+ var tifa = typeof adinfo.getTIFA === "function" ? adinfo.getTIFA() : adinfo.tifa;
1668
+ if (typeof tifa === "string" && tifa && !isMacroPlaceholder(tifa)) {
1669
+ var lat = typeof adinfo.isLATEnabled === "function" ? adinfo.isLATEnabled() : void 0;
1670
+ return _object_spread({
1671
+ deviceId: tifa,
1672
+ deviceIdType: "tifa"
1673
+ }, typeof lat === "boolean" ? {
1674
+ limitAdTracking: lat
1675
+ } : {});
1738
1676
  }
1739
- });
1740
- })();
1677
+ }
1678
+ } catch (unused) {}
1679
+ try {
1680
+ var webOSDev = window.webOSDev;
1681
+ if (webOSDev) {
1682
+ var _webOSDev_lgudid;
1683
+ var lgudid = typeof webOSDev.LGUDID === "function" ? webOSDev.LGUDID() : (_webOSDev_lgudid = webOSDev.lgudid) !== null && _webOSDev_lgudid !== void 0 ? _webOSDev_lgudid : webOSDev.LGUDID;
1684
+ if (typeof lgudid === "string" && lgudid) {
1685
+ if (isZeroedAdId(lgudid)) {
1686
+ return {
1687
+ deviceIdType: "lgudid",
1688
+ limitAdTracking: true
1689
+ };
1690
+ }
1691
+ if (!isMacroPlaceholder(lgudid)) {
1692
+ return {
1693
+ deviceId: lgudid,
1694
+ deviceIdType: "lgudid",
1695
+ limitAdTracking: false
1696
+ };
1697
+ }
1698
+ }
1699
+ }
1700
+ } catch (unused) {}
1701
+ try {
1702
+ var roku = window.Roku;
1703
+ if (roku) {
1704
+ var rida = typeof roku.getPublisherUniqueId === "function" ? roku.getPublisherUniqueId() : roku.rida;
1705
+ if (typeof rida === "string" && rida && !isMacroPlaceholder(rida)) {
1706
+ return {
1707
+ deviceId: rida,
1708
+ deviceIdType: "rida",
1709
+ limitAdTracking: false
1710
+ };
1711
+ }
1712
+ }
1713
+ } catch (unused) {}
1714
+ return {};
1741
1715
  }
1742
- function canPublish(licenseKey) {
1743
- return Boolean(isMQTTEnabled() && licenseKey);
1716
+ var ZEROED_AD_ID_PATTERNS = /* @__PURE__ */ new Set([
1717
+ "38400000-8cf0-11bd-b23e-10b96e40000d",
1718
+ "00000000-0000-0000-0000-000000000000"
1719
+ ]);
1720
+ function isMacroPlaceholder(value) {
1721
+ var t = value.trim();
1722
+ return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
1744
1723
  }
1745
- function buildPlayerMetricEvent() {
1746
- return _async_to_generator(function() {
1747
- var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
1748
- var _arguments = arguments;
1749
- return _ts_generator(this, function(_state) {
1750
- switch(_state.label){
1751
- case 0:
1752
- context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1753
- clientInfo = getClientInfo();
1754
- return [
1755
- 4,
1756
- getBrowserID(clientInfo)
1757
- ];
1758
- case 1:
1759
- playerId = _state.sent();
1760
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
1761
- return [
1762
- 2,
1763
- _object_spread({
1764
- player_id: playerId,
1765
- device_type: clientInfo.deviceType,
1766
- os: clientInfo.os.toLowerCase(),
1767
- ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
1768
- ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
1769
- capture_at: captureAt
1770
- }, context.inputStreamType ? {
1771
- input_stream_type: context.inputStreamType
1772
- } : {})
1773
- ];
1724
+ function isZeroedAdId(value) {
1725
+ return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
1726
+ }
1727
+ function readNativeBridgeSignals() {
1728
+ if (typeof window === "undefined") {
1729
+ return {};
1730
+ }
1731
+ var candidates = [
1732
+ window.__STORMCLOUD_CTV_AD_INFO__,
1733
+ window.__STORMCLOUD_CTV__,
1734
+ window.stormcloudCtv,
1735
+ window.AiryTV,
1736
+ window.Android,
1737
+ window.webOS,
1738
+ window.tizen,
1739
+ window.amazon
1740
+ ].filter(Boolean);
1741
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1742
+ try {
1743
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1744
+ var source = _step.value;
1745
+ var contentUrl = readBridgeValue(source, [
1746
+ "contentUrl",
1747
+ "url",
1748
+ "videoUrl",
1749
+ "canonicalUrl"
1750
+ ]) || void 0;
1751
+ var appId = readBridgeValue(source, [
1752
+ "appId",
1753
+ "msid",
1754
+ "applicationId",
1755
+ "packageName"
1756
+ ]) || void 0;
1757
+ var appName = readBridgeValue(source, [
1758
+ "appName",
1759
+ "an",
1760
+ "applicationName"
1761
+ ]) || void 0;
1762
+ var deviceId = readBridgeValue(source, [
1763
+ "rdid",
1764
+ "ifa",
1765
+ "advertisingId",
1766
+ "adId",
1767
+ "deviceId",
1768
+ "lgudid",
1769
+ "LGUDID",
1770
+ "tifa",
1771
+ "rida",
1772
+ "afai",
1773
+ "aaid"
1774
+ ]) || void 0;
1775
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
1776
+ var deviceIdType = readBridgeValue(source, [
1777
+ "idtype",
1778
+ "deviceIdType",
1779
+ "advertisingIdType",
1780
+ "idType"
1781
+ ]) || inferDeviceIdType();
1782
+ var limitAdTracking = readBridgeBoolean(source, [
1783
+ "is_lat",
1784
+ "limitAdTracking",
1785
+ "limitedAdTracking",
1786
+ "lat"
1787
+ ]);
1788
+ return _object_spread({}, contentUrl ? {
1789
+ contentUrl: contentUrl
1790
+ } : {}, appId ? {
1791
+ appId: appId
1792
+ } : {}, appName ? {
1793
+ appName: appName
1794
+ } : {}, deviceId ? {
1795
+ deviceId: deviceId
1796
+ } : {}, deviceId && deviceIdType ? {
1797
+ deviceIdType: deviceIdType
1798
+ } : {}, deviceId && limitAdTracking != null ? {
1799
+ limitAdTracking: limitAdTracking
1800
+ } : {});
1801
+ }
1802
+ } catch (err) {
1803
+ _didIteratorError = true;
1804
+ _iteratorError = err;
1805
+ } finally{
1806
+ try {
1807
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1808
+ _iterator.return();
1774
1809
  }
1775
- });
1776
- }).apply(this, arguments);
1810
+ } finally{
1811
+ if (_didIteratorError) {
1812
+ throw _iteratorError;
1813
+ }
1814
+ }
1815
+ }
1816
+ return {};
1777
1817
  }
1778
- function publishTracking(licenseKey, channel, body) {
1779
- ensureMQTTClient();
1780
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
1818
+ function readBridgeValue(source, keys) {
1819
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1820
+ try {
1821
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1822
+ var key = _step.value;
1823
+ var value = source === null || source === void 0 ? void 0 : source[key];
1824
+ if (typeof value === "string" && value) {
1825
+ return value;
1826
+ }
1827
+ if (typeof value === "function") {
1828
+ try {
1829
+ var result = value.call(source);
1830
+ if (typeof result === "string" && result) {
1831
+ return result;
1832
+ }
1833
+ } catch (unused) {}
1834
+ }
1835
+ }
1836
+ } catch (err) {
1837
+ _didIteratorError = true;
1838
+ _iteratorError = err;
1839
+ } finally{
1840
+ try {
1841
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1842
+ _iterator.return();
1843
+ }
1844
+ } finally{
1845
+ if (_didIteratorError) {
1846
+ throw _iteratorError;
1847
+ }
1848
+ }
1849
+ }
1850
+ return void 0;
1781
1851
  }
1782
- function sendInitialTracking(_0) {
1783
- return _async_to_generator(function(licenseKey) {
1784
- var context, metricEvent, error;
1785
- var _arguments = arguments;
1852
+ function readBridgeBoolean(source, keys) {
1853
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1854
+ try {
1855
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1856
+ var key = _step.value;
1857
+ var value = source === null || source === void 0 ? void 0 : source[key];
1858
+ var normalized = normalizeBoolean(value);
1859
+ if (normalized != null) {
1860
+ return normalized;
1861
+ }
1862
+ if (typeof value === "function") {
1863
+ try {
1864
+ var result = normalizeBoolean(value.call(source));
1865
+ if (result != null) {
1866
+ return result;
1867
+ }
1868
+ } catch (unused) {}
1869
+ }
1870
+ }
1871
+ } catch (err) {
1872
+ _didIteratorError = true;
1873
+ _iteratorError = err;
1874
+ } finally{
1875
+ try {
1876
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1877
+ _iterator.return();
1878
+ }
1879
+ } finally{
1880
+ if (_didIteratorError) {
1881
+ throw _iteratorError;
1882
+ }
1883
+ }
1884
+ }
1885
+ return void 0;
1886
+ }
1887
+ function readStoredDeviceId() {
1888
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1889
+ try {
1890
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1891
+ var key = _step.value;
1892
+ var value = readStoredString(key);
1893
+ if (value) {
1894
+ return value;
1895
+ }
1896
+ }
1897
+ } catch (err) {
1898
+ _didIteratorError = true;
1899
+ _iteratorError = err;
1900
+ } finally{
1901
+ try {
1902
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1903
+ _iterator.return();
1904
+ }
1905
+ } finally{
1906
+ if (_didIteratorError) {
1907
+ throw _iteratorError;
1908
+ }
1909
+ }
1910
+ }
1911
+ return void 0;
1912
+ }
1913
+ function readStoredString(key) {
1914
+ if (typeof window === "undefined") {
1915
+ return void 0;
1916
+ }
1917
+ try {
1918
+ var _window_localStorage;
1919
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
1920
+ return value || void 0;
1921
+ } catch (unused) {
1922
+ return void 0;
1923
+ }
1924
+ }
1925
+ function readStoredLimitAdTracking() {
1926
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
1927
+ }
1928
+ function normalizeBoolean(value) {
1929
+ if (typeof value === "boolean") {
1930
+ return value;
1931
+ }
1932
+ if (typeof value === "number") {
1933
+ return value === 1;
1934
+ }
1935
+ if (typeof value === "string") {
1936
+ var normalized = value.toLowerCase();
1937
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
1938
+ return true;
1939
+ }
1940
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
1941
+ return false;
1942
+ }
1943
+ }
1944
+ return void 0;
1945
+ }
1946
+ // src/utils/tracking.ts
1947
+ var cachedBrowserId = null;
1948
+ function getClientInfo() {
1949
+ var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
1950
+ var ua = navigator.userAgent;
1951
+ var platform = navigator.platform;
1952
+ var vendor = navigator.vendor || "";
1953
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
1954
+ var memory = navigator.deviceMemory || null;
1955
+ var hardwareConcurrency = navigator.hardwareConcurrency || 1;
1956
+ var screenInfo = {
1957
+ width: (_screen = screen) === null || _screen === void 0 ? void 0 : _screen.width,
1958
+ height: (_screen1 = screen) === null || _screen1 === void 0 ? void 0 : _screen1.height,
1959
+ availWidth: (_screen2 = screen) === null || _screen2 === void 0 ? void 0 : _screen2.availWidth,
1960
+ availHeight: (_screen3 = screen) === null || _screen3 === void 0 ? void 0 : _screen3.availHeight,
1961
+ orientation: ((_screen4 = screen) === null || _screen4 === void 0 ? void 0 : (_screen_orientation = _screen4.orientation) === null || _screen_orientation === void 0 ? void 0 : _screen_orientation.type) || "",
1962
+ pixelDepth: (_screen5 = screen) === null || _screen5 === void 0 ? void 0 : _screen5.pixelDepth
1963
+ };
1964
+ var deviceType = "desktop";
1965
+ var brand = "Unknown";
1966
+ var os = "Unknown";
1967
+ var model = "";
1968
+ var isSmartTV = false;
1969
+ var isAndroid = false;
1970
+ var isWebView = false;
1971
+ var isWebApp = false;
1972
+ if (ua.includes("Web0S")) {
1973
+ brand = "LG";
1974
+ os = "webOS";
1975
+ isSmartTV = true;
1976
+ deviceType = "tv";
1977
+ var webosMatch = ua.match(/Web0S\/([^\s]+)/);
1978
+ model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
1979
+ } else if (ua.includes("Tizen")) {
1980
+ brand = "Samsung";
1981
+ os = "Tizen";
1982
+ isSmartTV = true;
1983
+ deviceType = "tv";
1984
+ var tizenMatch = ua.match(/Tizen\/([^\s]+)/);
1985
+ var tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
1986
+ model = tizenMatch ? "Tizen ".concat(tizenMatch[1], " ").concat(tvMatch).trim() : "Tizen TV";
1987
+ } else if (ua.includes("Philips")) {
1988
+ brand = "Philips";
1989
+ os = "Saphi";
1990
+ isSmartTV = true;
1991
+ deviceType = "tv";
1992
+ } else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
1993
+ brand = "Sharp";
1994
+ os = "Android TV";
1995
+ isSmartTV = true;
1996
+ deviceType = "tv";
1997
+ } else if (ua.includes("Android") && (ua.includes("Sony") || vendor.includes("Sony"))) {
1998
+ brand = "Sony";
1999
+ os = "Android TV";
2000
+ isSmartTV = true;
2001
+ deviceType = "tv";
2002
+ } else if (ua.includes("Android") && (ua.includes("NetCast") || ua.includes("LG"))) {
2003
+ brand = "LG";
2004
+ os = "Android TV";
2005
+ isSmartTV = true;
2006
+ deviceType = "tv";
2007
+ } else if (ua.includes(" Roku") || ua.includes("Roku/")) {
2008
+ brand = "Roku";
2009
+ os = "Roku OS";
2010
+ isSmartTV = true;
2011
+ deviceType = "tv";
2012
+ } else if (ua.includes("AppleTV")) {
2013
+ brand = "Apple";
2014
+ os = "tvOS";
2015
+ isSmartTV = true;
2016
+ deviceType = "tv";
2017
+ }
2018
+ if (ua.includes("Android")) {
2019
+ isAndroid = true;
2020
+ os = "Android";
2021
+ deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
2022
+ if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
2023
+ deviceType = "tv";
2024
+ isSmartTV = true;
2025
+ brand = brand === "Unknown" ? "Android TV" : brand;
2026
+ }
2027
+ var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
2028
+ if (androidModelMatch && androidModelMatch[1]) {
2029
+ model = androidModelMatch[1];
2030
+ }
2031
+ }
2032
+ if (/iPad|iPhone|iPod/.test(ua)) {
2033
+ os = "iOS";
2034
+ deviceType = "mobile";
2035
+ brand = "Apple";
2036
+ if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
2037
+ deviceType = "tablet";
2038
+ }
2039
+ }
2040
+ if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
2041
+ if (ua.includes("Windows")) {
2042
+ os = "Windows";
2043
+ deviceType = "desktop";
2044
+ } else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
2045
+ os = "macOS";
2046
+ deviceType = "desktop";
2047
+ if (maxTouchPoints > 1) deviceType = "tablet";
2048
+ } else if (ua.includes("Linux")) {
2049
+ os = "Linux";
2050
+ deviceType = "desktop";
2051
+ }
2052
+ }
2053
+ if (brand === "Unknown") {
2054
+ if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
2055
+ if (vendor.includes("Apple")) brand = "Apple";
2056
+ if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
2057
+ }
2058
+ isWebView = /wv|WebView|Linux; U;/.test(ua);
2059
+ if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
2060
+ isWebView = true;
2061
+ }
2062
+ isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_window_screen = window.screen) === null || _window_screen === void 0 ? void 0 : (_window_screen_orientation = _window_screen.orientation) === null || _window_screen_orientation === void 0 ? void 0 : _window_screen_orientation.angle) !== void 0;
2063
+ return {
2064
+ brand: brand,
2065
+ os: os,
2066
+ model: model || ua.substring(0, 50) + "...",
2067
+ deviceType: deviceType,
2068
+ isSmartTV: isSmartTV,
2069
+ isAndroid: isAndroid,
2070
+ isWebView: isWebView,
2071
+ isWebApp: isWebApp,
2072
+ domain: window.location.hostname,
2073
+ origin: window.location.origin,
2074
+ path: window.location.pathname,
2075
+ userAgent: ua,
2076
+ vendor: vendor,
2077
+ platform: platform,
2078
+ screen: screenInfo,
2079
+ hardwareConcurrency: hardwareConcurrency,
2080
+ deviceMemory: memory,
2081
+ maxTouchPoints: maxTouchPoints,
2082
+ language: navigator.language,
2083
+ languages: ((_navigator_languages = navigator.languages) === null || _navigator_languages === void 0 ? void 0 : _navigator_languages.join(",")) || "",
2084
+ cookieEnabled: navigator.cookieEnabled,
2085
+ doNotTrack: navigator.doNotTrack || "",
2086
+ referrer: document.referrer,
2087
+ visibilityState: document.visibilityState
2088
+ };
2089
+ }
2090
+ function sha256Hex(input) {
2091
+ return _async_to_generator(function() {
2092
+ var _crypto_subtle, encodedData, utf8, buffer, i, hashBuffer, unused, hash, i1, char, fallbackHash, timestamp, random;
1786
2093
  return _ts_generator(this, function(_state) {
1787
2094
  switch(_state.label){
1788
2095
  case 0:
1789
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1790
- if (!canPublish(licenseKey)) return [
1791
- 2
2096
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
2097
+ 3,
2098
+ 5
1792
2099
  ];
1793
2100
  _state.label = 1;
1794
2101
  case 1:
1795
2102
  _state.trys.push([
1796
2103
  1,
1797
- 3,
2104
+ 4,
1798
2105
  ,
1799
- 4
2106
+ 5
1800
2107
  ]);
1801
2108
  return [
1802
2109
  4,
1803
- buildPlayerMetricEvent(context, {
1804
- adLoaded: false,
1805
- adDetect: false
1806
- })
2110
+ crypto.subtle.digest("SHA-256", new Uint8Array([
2111
+ 1,
2112
+ 2,
2113
+ 3
2114
+ ]))
2115
+ ];
2116
+ case 2:
2117
+ _state.sent();
2118
+ if (typeof TextEncoder !== "undefined") {
2119
+ encodedData = new TextEncoder().encode(input);
2120
+ } else {
2121
+ utf8 = unescape(encodeURIComponent(input));
2122
+ buffer = new Uint8Array(utf8.length);
2123
+ for(i = 0; i < utf8.length; i++){
2124
+ buffer[i] = utf8.charCodeAt(i);
2125
+ }
2126
+ encodedData = buffer;
2127
+ }
2128
+ return [
2129
+ 4,
2130
+ crypto.subtle.digest("SHA-256", encodedData)
2131
+ ];
2132
+ case 3:
2133
+ hashBuffer = _state.sent();
2134
+ return [
2135
+ 2,
2136
+ Array.from(new Uint8Array(hashBuffer)).map(function(b) {
2137
+ return b.toString(16).padStart(2, "0");
2138
+ }).join("")
2139
+ ];
2140
+ case 4:
2141
+ unused = _state.sent();
2142
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
2143
+ return [
2144
+ 3,
2145
+ 5
2146
+ ];
2147
+ case 5:
2148
+ hash = 0;
2149
+ for(i1 = 0; i1 < input.length; i1++){
2150
+ char = input.charCodeAt(i1);
2151
+ hash = (hash << 5) - hash + char;
2152
+ hash = hash & hash;
2153
+ }
2154
+ fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
2155
+ timestamp = Date.now().toString(16).padStart(12, "0");
2156
+ random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
2157
+ return [
2158
+ 2,
2159
+ (fallbackHash + timestamp + random).padEnd(64, "0")
2160
+ ];
2161
+ }
2162
+ });
2163
+ })();
2164
+ }
2165
+ function resolvePlayerIdentitySeed(clientInfo) {
2166
+ var nativeDeviceId = resolveNativeDeviceId();
2167
+ if (nativeDeviceId) {
2168
+ return "device:".concat(nativeDeviceId);
2169
+ }
2170
+ var persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);
2171
+ if (persistedId) {
2172
+ return "persisted:".concat(persistedId);
2173
+ }
2174
+ return "fingerprint:".concat(JSON.stringify(clientInfo));
2175
+ }
2176
+ function getBrowserID(clientInfo) {
2177
+ return _async_to_generator(function() {
2178
+ return _ts_generator(this, function(_state) {
2179
+ switch(_state.label){
2180
+ case 0:
2181
+ if (cachedBrowserId) {
2182
+ return [
2183
+ 2,
2184
+ cachedBrowserId
2185
+ ];
2186
+ }
2187
+ return [
2188
+ 4,
2189
+ sha256Hex(resolvePlayerIdentitySeed(clientInfo))
2190
+ ];
2191
+ case 1:
2192
+ cachedBrowserId = _state.sent();
2193
+ return [
2194
+ 2,
2195
+ cachedBrowserId
2196
+ ];
2197
+ }
2198
+ });
2199
+ })();
2200
+ }
2201
+ function canPublish(licenseKey) {
2202
+ return Boolean(isMQTTEnabled() && licenseKey);
2203
+ }
2204
+ function buildPlayerMetricEvent() {
2205
+ return _async_to_generator(function() {
2206
+ var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
2207
+ var _arguments = arguments;
2208
+ return _ts_generator(this, function(_state) {
2209
+ switch(_state.label){
2210
+ case 0:
2211
+ context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
2212
+ clientInfo = getClientInfo();
2213
+ return [
2214
+ 4,
2215
+ getBrowserID(clientInfo)
2216
+ ];
2217
+ case 1:
2218
+ playerId = _state.sent();
2219
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
2220
+ return [
2221
+ 2,
2222
+ _object_spread({
2223
+ player_id: playerId,
2224
+ device_type: clientInfo.deviceType,
2225
+ os: clientInfo.os.toLowerCase(),
2226
+ ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
2227
+ ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
2228
+ capture_at: captureAt
2229
+ }, context.inputStreamType ? {
2230
+ input_stream_type: context.inputStreamType
2231
+ } : {})
2232
+ ];
2233
+ }
2234
+ });
2235
+ }).apply(this, arguments);
2236
+ }
2237
+ function publishTracking(licenseKey, channel, body) {
2238
+ ensureMQTTClient();
2239
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
2240
+ }
2241
+ function sendInitialTracking(_0) {
2242
+ return _async_to_generator(function(licenseKey) {
2243
+ var context, metricEvent, error;
2244
+ var _arguments = arguments;
2245
+ return _ts_generator(this, function(_state) {
2246
+ switch(_state.label){
2247
+ case 0:
2248
+ context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
2249
+ if (!canPublish(licenseKey)) return [
2250
+ 2
2251
+ ];
2252
+ _state.label = 1;
2253
+ case 1:
2254
+ _state.trys.push([
2255
+ 1,
2256
+ 3,
2257
+ ,
2258
+ 4
2259
+ ]);
2260
+ return [
2261
+ 4,
2262
+ buildPlayerMetricEvent(context, {
2263
+ adLoaded: false,
2264
+ adDetect: false
2265
+ })
1807
2266
  ];
1808
2267
  case 2:
1809
2268
  metricEvent = _state.sent();
@@ -1963,654 +2422,314 @@ function sendAdImpressionTracking(_0, _1) {
1963
2422
  ];
1964
2423
  case 3:
1965
2424
  error = _state.sent();
1966
- console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
1967
- return [
1968
- 3,
1969
- 4
1970
- ];
1971
- case 4:
1972
- return [
1973
- 2
1974
- ];
1975
- }
1976
- });
1977
- }).apply(this, arguments);
1978
- }
1979
- function sendHeartbeat(_0) {
1980
- return _async_to_generator(function(licenseKey) {
1981
- var context, flags, heartbeatData, error;
1982
- var _arguments = arguments;
1983
- return _ts_generator(this, function(_state) {
1984
- switch(_state.label){
1985
- case 0:
1986
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
1987
- if (!canPublish(licenseKey)) return [
1988
- 2
1989
- ];
1990
- _state.label = 1;
1991
- case 1:
1992
- _state.trys.push([
1993
- 1,
1994
- 3,
1995
- ,
1996
- 4
1997
- ]);
1998
- return [
1999
- 4,
2000
- buildPlayerMetricEvent(context, flags)
2001
- ];
2002
- case 2:
2003
- heartbeatData = _state.sent();
2004
- publishTracking(licenseKey, "heartbeat", heartbeatData);
2005
- return [
2006
- 3,
2007
- 4
2008
- ];
2009
- case 3:
2010
- error = _state.sent();
2011
- console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
2012
- return [
2013
- 3,
2014
- 4
2015
- ];
2016
- case 4:
2017
- return [
2018
- 2
2019
- ];
2020
- }
2021
- });
2022
- }).apply(this, arguments);
2023
- }
2024
- // src/utils/polyfills.ts
2025
- function polyfillURLSearchParams() {
2026
- if (typeof URLSearchParams !== "undefined") {
2027
- return;
2028
- }
2029
- var URLSearchParamsPolyfill = /*#__PURE__*/ function() {
2030
- function URLSearchParamsPolyfill(init) {
2031
- var _this = this;
2032
- _class_call_check(this, URLSearchParamsPolyfill);
2033
- this.params = /* @__PURE__ */ new Map();
2034
- if (typeof init === "string") {
2035
- this.parseQueryString(init);
2036
- } else if (_instanceof(init, URLSearchParamsPolyfill)) {
2037
- init.forEach(function(value, key) {
2038
- _this.append(key, value);
2039
- });
2040
- }
2041
- }
2042
- _create_class(URLSearchParamsPolyfill, [
2043
- {
2044
- key: "parseQueryString",
2045
- value: function parseQueryString(query) {
2046
- var _this = this;
2047
- var cleanQuery = query.startsWith("?") ? query.slice(1) : query;
2048
- if (!cleanQuery) return;
2049
- cleanQuery.split("&").forEach(function(param) {
2050
- var _param_split = _sliced_to_array(param.split("="), 2), key = _param_split[0], value = _param_split[1];
2051
- if (key) {
2052
- var decodedKey = _this.safeDecodeURIComponent(key);
2053
- var decodedValue = value ? _this.safeDecodeURIComponent(value) : "";
2054
- _this.append(decodedKey, decodedValue);
2055
- }
2056
- });
2057
- }
2058
- },
2059
- {
2060
- key: "safeDecodeURIComponent",
2061
- value: function safeDecodeURIComponent(str) {
2062
- try {
2063
- return decodeURIComponent(str.replace(/\+/g, " "));
2064
- } catch (e) {
2065
- return str;
2066
- }
2067
- }
2068
- },
2069
- {
2070
- key: "append",
2071
- value: function append(name, value) {
2072
- var values = this.params.get(name) || [];
2073
- values.push(String(value));
2074
- this.params.set(name, values);
2075
- }
2076
- },
2077
- {
2078
- key: "delete",
2079
- value: function _delete(name) {
2080
- this.params.delete(name);
2081
- }
2082
- },
2083
- {
2084
- key: "get",
2085
- value: function get(name) {
2086
- var values = this.params.get(name);
2087
- return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
2088
- }
2089
- },
2090
- {
2091
- key: "getAll",
2092
- value: function getAll(name) {
2093
- return this.params.get(name) || [];
2094
- }
2095
- },
2096
- {
2097
- key: "has",
2098
- value: function has(name) {
2099
- return this.params.has(name);
2100
- }
2101
- },
2102
- {
2103
- key: "set",
2104
- value: function set(name, value) {
2105
- this.params.set(name, [
2106
- String(value)
2107
- ]);
2108
- }
2109
- },
2110
- {
2111
- key: "forEach",
2112
- value: function forEach(callback) {
2113
- var _this = this;
2114
- this.params.forEach(function(values, key) {
2115
- values.forEach(function(value) {
2116
- callback(value, key, _this);
2117
- });
2118
- });
2119
- }
2120
- },
2121
- {
2122
- key: "toString",
2123
- value: function toString() {
2124
- var parts = [];
2125
- this.params.forEach(function(values, key) {
2126
- values.forEach(function(value) {
2127
- parts.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)));
2128
- });
2129
- });
2130
- return parts.join("&");
2131
- }
2132
- }
2133
- ]);
2134
- return URLSearchParamsPolyfill;
2135
- }();
2136
- window.URLSearchParams = URLSearchParamsPolyfill;
2137
- }
2138
- function polyfillTextEncoder() {
2139
- if (typeof TextEncoder !== "undefined") {
2140
- return;
2141
- }
2142
- var TextEncoderPolyfill = /*#__PURE__*/ function() {
2143
- function TextEncoderPolyfill() {
2144
- _class_call_check(this, TextEncoderPolyfill);
2145
- this.encoding = "utf-8";
2146
- }
2147
- _create_class(TextEncoderPolyfill, [
2148
- {
2149
- key: "encode",
2150
- value: function encode(str) {
2151
- var utf8 = [];
2152
- for(var i = 0; i < str.length; i++){
2153
- var charcode = str.charCodeAt(i);
2154
- if (charcode < 128) {
2155
- utf8.push(charcode);
2156
- } else if (charcode < 2048) {
2157
- utf8.push(192 | charcode >> 6, 128 | charcode & 63);
2158
- } else if (charcode < 55296 || charcode >= 57344) {
2159
- utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2160
- } else {
2161
- i++;
2162
- charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
2163
- utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2164
- }
2165
- }
2166
- return new Uint8Array(utf8);
2167
- }
2168
- }
2169
- ]);
2170
- return TextEncoderPolyfill;
2171
- }();
2172
- window.TextEncoder = TextEncoderPolyfill;
2173
- }
2174
- function polyfillPromiseFinally() {
2175
- if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
2176
- Promise.prototype.finally = function(callback) {
2177
- var constructor = this.constructor;
2178
- return this.then(function(value) {
2179
- return constructor.resolve(callback()).then(function() {
2180
- return value;
2181
- });
2182
- }, function(reason) {
2183
- return constructor.resolve(callback()).then(function() {
2184
- throw reason;
2185
- });
2186
- });
2187
- };
2188
- }
2189
- }
2190
- function polyfillObjectAssign() {
2191
- if (typeof Object.assign !== "function") {
2192
- Object.assign = function(target) {
2193
- for(var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
2194
- sources[_key - 1] = arguments[_key];
2195
- }
2196
- if (target == null) {
2197
- throw new TypeError("Cannot convert undefined or null to object");
2198
- }
2199
- var to = Object(target);
2200
- for(var i = 0; i < sources.length; i++){
2201
- var nextSource = sources[i];
2202
- if (nextSource != null) {
2203
- for(var nextKey in nextSource){
2204
- if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
2205
- to[nextKey] = nextSource[nextKey];
2206
- }
2207
- }
2208
- }
2209
- }
2210
- return to;
2211
- };
2212
- }
2213
- }
2214
- function polyfillArrayFrom() {
2215
- if (!Array.from) {
2216
- Array.from = function(arrayLike, mapFn, thisArg) {
2217
- var items = Object(arrayLike);
2218
- if (arrayLike == null) {
2219
- throw new TypeError("Array.from requires an array-like object");
2220
- }
2221
- var len = items.length >>> 0;
2222
- var result = new Array(len);
2223
- for(var i = 0; i < len; i++){
2224
- if (mapFn) {
2225
- result[i] = mapFn.call(thisArg, items[i], i);
2226
- } else {
2227
- result[i] = items[i];
2228
- }
2229
- }
2230
- return result;
2231
- };
2232
- }
2233
- }
2234
- function polyfillStringStartsWith() {
2235
- if (!String.prototype.startsWith) {
2236
- String.prototype.startsWith = function(search, pos) {
2237
- pos = !pos || pos < 0 ? 0 : +pos;
2238
- return this.substring(pos, pos + search.length) === search;
2239
- };
2240
- }
2241
- }
2242
- function polyfillStringEndsWith() {
2243
- if (!String.prototype.endsWith) {
2244
- String.prototype.endsWith = function(search, length) {
2245
- if (length === void 0 || length > this.length) {
2246
- length = this.length;
2247
- }
2248
- return this.substring(length - search.length, length) === search;
2249
- };
2250
- }
2251
- }
2252
- function polyfillStringIncludes() {
2253
- if (!String.prototype.includes) {
2254
- String.prototype.includes = function(search, start) {
2255
- if (typeof start !== "number") {
2256
- start = 0;
2257
- }
2258
- if (start + search.length > this.length) {
2259
- return false;
2260
- }
2261
- return this.indexOf(search, start) !== -1;
2262
- };
2263
- }
2264
- }
2265
- function initializePolyfills() {
2266
- polyfillObjectAssign();
2267
- polyfillArrayFrom();
2268
- polyfillStringStartsWith();
2269
- polyfillStringEndsWith();
2270
- polyfillStringIncludes();
2271
- polyfillURLSearchParams();
2272
- polyfillTextEncoder();
2273
- polyfillPromiseFinally();
2274
- }
2275
- // src/utils/vastEnvironmentSignals.ts
2276
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2277
- var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2278
- var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2279
- var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2280
- var AIRY_APP_NAME = "AiryTV Movies & TV";
2281
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2282
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2283
- var LG_TEST_APP_ID = "com.hulu.plus";
2284
- var LG_TEST_APP_NAME = "Hulu";
2285
- var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
2286
- var _lgTestDeviceId;
2287
- function getLgTestDeviceId() {
2288
- if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
2289
- return _lgTestDeviceId;
2290
- }
2291
- function isLgWebOS() {
2292
- if (typeof navigator === "undefined") return false;
2293
- return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
2294
- }
2295
- function getDefaultAppId() {
2296
- if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2297
- var ua = navigator.userAgent;
2298
- if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2299
- if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2300
- if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2301
- return AIRY_ANDROID_APP_ID;
2302
- }
2303
- var DEVICE_ID_STORAGE_KEYS = [
2304
- "rdid",
2305
- "ifa",
2306
- "advertisingId",
2307
- "advertising_id",
2308
- "deviceAdvertisingId",
2309
- "aaid",
2310
- "adid",
2311
- "rida",
2312
- "tifa",
2313
- "lgudid"
2314
- ];
2315
- var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2316
- "aaid",
2317
- "adid"
2318
- ]);
2319
- function resolveVastEnvironmentSignals(isCtv) {
2320
- var _ref, _bridgeSignals_limitAdTracking;
2321
- var bridgeSignals = readNativeBridgeSignals();
2322
- var lg = isCtv && isLgWebOS();
2323
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || (lg ? getLgTestDeviceId() : void 0);
2324
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType() || (lg ? "lgudid" : void 0);
2325
- 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;
2326
- if (isCtv) {
2327
- return _object_spread_props(_object_spread({
2328
- isCtv: true,
2329
- contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
2330
- appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
2331
- appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
2332
- sessionId: getOrCreateCtvSessionId()
2333
- }, deviceId ? {
2334
- deviceId: deviceId
2335
- } : {}, deviceIdType ? {
2336
- deviceIdType: deviceIdType
2337
- } : {}, limitAdTracking != null ? {
2338
- limitAdTracking: limitAdTracking
2339
- } : {}), {
2340
- deviceTypeHint: 5
2341
- });
2342
- }
2343
- return _object_spread({
2344
- isCtv: false
2345
- }, deviceId ? {
2346
- deviceId: deviceId
2347
- } : {}, deviceIdType ? {
2348
- deviceIdType: deviceIdType
2349
- } : {}, limitAdTracking != null ? {
2350
- limitAdTracking: limitAdTracking
2351
- } : {});
2352
- }
2353
- function inferDeviceIdType() {
2354
- if (typeof navigator === "undefined") {
2355
- return void 0;
2356
- }
2357
- var ua = navigator.userAgent;
2358
- if (/Roku/i.test(ua)) return "rida";
2359
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
2360
- if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2361
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2362
- if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2363
- if (/Android|Google TV/i.test(ua)) return "aaid";
2364
- if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2365
- return void 0;
2366
- }
2367
- function isEquivalentDeviceIdType(tagType, runtimeType) {
2368
- if (!tagType || !runtimeType) return false;
2369
- var tag = tagType.toLowerCase();
2370
- var runtime = runtimeType.toLowerCase();
2371
- if (tag === runtime) return true;
2372
- return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2373
- }
2374
- function getOrCreateCtvSessionId() {
2375
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2376
- if (existing) {
2377
- return existing;
2378
- }
2379
- var sessionId = createUuid();
2380
- try {
2381
- var _window_localStorage;
2382
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2383
- } catch (unused) {}
2384
- return sessionId;
2425
+ console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
2426
+ return [
2427
+ 3,
2428
+ 4
2429
+ ];
2430
+ case 4:
2431
+ return [
2432
+ 2
2433
+ ];
2434
+ }
2435
+ });
2436
+ }).apply(this, arguments);
2385
2437
  }
2386
- function createUuid() {
2387
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2388
- return crypto.randomUUID();
2389
- }
2390
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2391
- var value = Math.floor(Math.random() * 16);
2392
- var nibble = char === "x" ? value : value & 3 | 8;
2393
- return nibble.toString(16);
2394
- });
2438
+ function sendHeartbeat(_0) {
2439
+ return _async_to_generator(function(licenseKey) {
2440
+ var context, flags, heartbeatData, error;
2441
+ var _arguments = arguments;
2442
+ return _ts_generator(this, function(_state) {
2443
+ switch(_state.label){
2444
+ case 0:
2445
+ context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
2446
+ if (!canPublish(licenseKey)) return [
2447
+ 2
2448
+ ];
2449
+ _state.label = 1;
2450
+ case 1:
2451
+ _state.trys.push([
2452
+ 1,
2453
+ 3,
2454
+ ,
2455
+ 4
2456
+ ]);
2457
+ return [
2458
+ 4,
2459
+ buildPlayerMetricEvent(context, flags)
2460
+ ];
2461
+ case 2:
2462
+ heartbeatData = _state.sent();
2463
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
2464
+ return [
2465
+ 3,
2466
+ 4
2467
+ ];
2468
+ case 3:
2469
+ error = _state.sent();
2470
+ console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
2471
+ return [
2472
+ 3,
2473
+ 4
2474
+ ];
2475
+ case 4:
2476
+ return [
2477
+ 2
2478
+ ];
2479
+ }
2480
+ });
2481
+ }).apply(this, arguments);
2395
2482
  }
2396
- function readNativeBridgeSignals() {
2397
- if (typeof window === "undefined") {
2398
- return {};
2483
+ // src/utils/polyfills.ts
2484
+ function polyfillURLSearchParams() {
2485
+ if (typeof URLSearchParams !== "undefined") {
2486
+ return;
2399
2487
  }
2400
- var candidates = [
2401
- window.__STORMCLOUD_CTV_AD_INFO__,
2402
- window.__STORMCLOUD_CTV__,
2403
- window.stormcloudCtv,
2404
- window.AiryTV,
2405
- window.Android,
2406
- window.webOS,
2407
- window.tizen,
2408
- window.amazon
2409
- ].filter(Boolean);
2410
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2411
- try {
2412
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2413
- var source = _step.value;
2414
- var contentUrl = readBridgeValue(source, [
2415
- "contentUrl",
2416
- "url",
2417
- "videoUrl",
2418
- "canonicalUrl"
2419
- ]) || void 0;
2420
- var appId = readBridgeValue(source, [
2421
- "appId",
2422
- "msid",
2423
- "applicationId",
2424
- "packageName"
2425
- ]) || void 0;
2426
- var appName = readBridgeValue(source, [
2427
- "appName",
2428
- "an",
2429
- "applicationName"
2430
- ]) || void 0;
2431
- var deviceId = readBridgeValue(source, [
2432
- "rdid",
2433
- "ifa",
2434
- "advertisingId",
2435
- "adId",
2436
- "deviceId",
2437
- "lgudid",
2438
- "LGUDID",
2439
- "tifa",
2440
- "rida",
2441
- "afai",
2442
- "aaid"
2443
- ]) || void 0;
2444
- if (!contentUrl && !deviceId && !appId && !appName) continue;
2445
- var deviceIdType = readBridgeValue(source, [
2446
- "idtype",
2447
- "deviceIdType",
2448
- "advertisingIdType",
2449
- "idType"
2450
- ]) || inferDeviceIdType();
2451
- var limitAdTracking = readBridgeBoolean(source, [
2452
- "is_lat",
2453
- "limitAdTracking",
2454
- "limitedAdTracking",
2455
- "lat"
2456
- ]);
2457
- return _object_spread({}, contentUrl ? {
2458
- contentUrl: contentUrl
2459
- } : {}, appId ? {
2460
- appId: appId
2461
- } : {}, appName ? {
2462
- appName: appName
2463
- } : {}, deviceId ? {
2464
- deviceId: deviceId
2465
- } : {}, deviceId && deviceIdType ? {
2466
- deviceIdType: deviceIdType
2467
- } : {}, deviceId && limitAdTracking != null ? {
2468
- limitAdTracking: limitAdTracking
2469
- } : {});
2470
- }
2471
- } catch (err) {
2472
- _didIteratorError = true;
2473
- _iteratorError = err;
2474
- } finally{
2475
- try {
2476
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2477
- _iterator.return();
2478
- }
2479
- } finally{
2480
- if (_didIteratorError) {
2481
- throw _iteratorError;
2488
+ var URLSearchParamsPolyfill = /*#__PURE__*/ function() {
2489
+ function URLSearchParamsPolyfill(init) {
2490
+ var _this = this;
2491
+ _class_call_check(this, URLSearchParamsPolyfill);
2492
+ this.params = /* @__PURE__ */ new Map();
2493
+ if (typeof init === "string") {
2494
+ this.parseQueryString(init);
2495
+ } else if (_instanceof(init, URLSearchParamsPolyfill)) {
2496
+ init.forEach(function(value, key) {
2497
+ _this.append(key, value);
2498
+ });
2482
2499
  }
2483
2500
  }
2484
- }
2485
- return {};
2486
- }
2487
- function readBridgeValue(source, keys) {
2488
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2489
- try {
2490
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2491
- var key = _step.value;
2492
- var value = source === null || source === void 0 ? void 0 : source[key];
2493
- if (typeof value === "string" && value) {
2494
- return value;
2495
- }
2496
- if (typeof value === "function") {
2497
- try {
2498
- var result = value.call(source);
2499
- if (typeof result === "string" && result) {
2500
- return result;
2501
+ _create_class(URLSearchParamsPolyfill, [
2502
+ {
2503
+ key: "parseQueryString",
2504
+ value: function parseQueryString(query) {
2505
+ var _this = this;
2506
+ var cleanQuery = query.startsWith("?") ? query.slice(1) : query;
2507
+ if (!cleanQuery) return;
2508
+ cleanQuery.split("&").forEach(function(param) {
2509
+ var _param_split = _sliced_to_array(param.split("="), 2), key = _param_split[0], value = _param_split[1];
2510
+ if (key) {
2511
+ var decodedKey = _this.safeDecodeURIComponent(key);
2512
+ var decodedValue = value ? _this.safeDecodeURIComponent(value) : "";
2513
+ _this.append(decodedKey, decodedValue);
2514
+ }
2515
+ });
2516
+ }
2517
+ },
2518
+ {
2519
+ key: "safeDecodeURIComponent",
2520
+ value: function safeDecodeURIComponent(str) {
2521
+ try {
2522
+ return decodeURIComponent(str.replace(/\+/g, " "));
2523
+ } catch (e) {
2524
+ return str;
2501
2525
  }
2502
- } catch (unused) {}
2526
+ }
2527
+ },
2528
+ {
2529
+ key: "append",
2530
+ value: function append(name, value) {
2531
+ var values = this.params.get(name) || [];
2532
+ values.push(String(value));
2533
+ this.params.set(name, values);
2534
+ }
2535
+ },
2536
+ {
2537
+ key: "delete",
2538
+ value: function _delete(name) {
2539
+ this.params.delete(name);
2540
+ }
2541
+ },
2542
+ {
2543
+ key: "get",
2544
+ value: function get(name) {
2545
+ var values = this.params.get(name);
2546
+ return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
2547
+ }
2548
+ },
2549
+ {
2550
+ key: "getAll",
2551
+ value: function getAll(name) {
2552
+ return this.params.get(name) || [];
2553
+ }
2554
+ },
2555
+ {
2556
+ key: "has",
2557
+ value: function has(name) {
2558
+ return this.params.has(name);
2559
+ }
2560
+ },
2561
+ {
2562
+ key: "set",
2563
+ value: function set(name, value) {
2564
+ this.params.set(name, [
2565
+ String(value)
2566
+ ]);
2567
+ }
2568
+ },
2569
+ {
2570
+ key: "forEach",
2571
+ value: function forEach(callback) {
2572
+ var _this = this;
2573
+ this.params.forEach(function(values, key) {
2574
+ values.forEach(function(value) {
2575
+ callback(value, key, _this);
2576
+ });
2577
+ });
2578
+ }
2579
+ },
2580
+ {
2581
+ key: "toString",
2582
+ value: function toString() {
2583
+ var parts = [];
2584
+ this.params.forEach(function(values, key) {
2585
+ values.forEach(function(value) {
2586
+ parts.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)));
2587
+ });
2588
+ });
2589
+ return parts.join("&");
2590
+ }
2503
2591
  }
2592
+ ]);
2593
+ return URLSearchParamsPolyfill;
2594
+ }();
2595
+ window.URLSearchParams = URLSearchParamsPolyfill;
2596
+ }
2597
+ function polyfillTextEncoder() {
2598
+ if (typeof TextEncoder !== "undefined") {
2599
+ return;
2600
+ }
2601
+ var TextEncoderPolyfill = /*#__PURE__*/ function() {
2602
+ function TextEncoderPolyfill() {
2603
+ _class_call_check(this, TextEncoderPolyfill);
2604
+ this.encoding = "utf-8";
2504
2605
  }
2505
- } catch (err) {
2506
- _didIteratorError = true;
2507
- _iteratorError = err;
2508
- } finally{
2509
- try {
2510
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2511
- _iterator.return();
2512
- }
2513
- } finally{
2514
- if (_didIteratorError) {
2515
- throw _iteratorError;
2606
+ _create_class(TextEncoderPolyfill, [
2607
+ {
2608
+ key: "encode",
2609
+ value: function encode(str) {
2610
+ var utf8 = [];
2611
+ for(var i = 0; i < str.length; i++){
2612
+ var charcode = str.charCodeAt(i);
2613
+ if (charcode < 128) {
2614
+ utf8.push(charcode);
2615
+ } else if (charcode < 2048) {
2616
+ utf8.push(192 | charcode >> 6, 128 | charcode & 63);
2617
+ } else if (charcode < 55296 || charcode >= 57344) {
2618
+ utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2619
+ } else {
2620
+ i++;
2621
+ charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
2622
+ utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2623
+ }
2624
+ }
2625
+ return new Uint8Array(utf8);
2626
+ }
2516
2627
  }
2517
- }
2628
+ ]);
2629
+ return TextEncoderPolyfill;
2630
+ }();
2631
+ window.TextEncoder = TextEncoderPolyfill;
2632
+ }
2633
+ function polyfillPromiseFinally() {
2634
+ if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
2635
+ Promise.prototype.finally = function(callback) {
2636
+ var constructor = this.constructor;
2637
+ return this.then(function(value) {
2638
+ return constructor.resolve(callback()).then(function() {
2639
+ return value;
2640
+ });
2641
+ }, function(reason) {
2642
+ return constructor.resolve(callback()).then(function() {
2643
+ throw reason;
2644
+ });
2645
+ });
2646
+ };
2518
2647
  }
2519
- return void 0;
2520
2648
  }
2521
- function readBridgeBoolean(source, keys) {
2522
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2523
- try {
2524
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2525
- var key = _step.value;
2526
- var value = source === null || source === void 0 ? void 0 : source[key];
2527
- var normalized = normalizeBoolean(value);
2528
- if (normalized != null) {
2529
- return normalized;
2530
- }
2531
- if (typeof value === "function") {
2532
- try {
2533
- var result = normalizeBoolean(value.call(source));
2534
- if (result != null) {
2535
- return result;
2536
- }
2537
- } catch (unused) {}
2649
+ function polyfillObjectAssign() {
2650
+ if (typeof Object.assign !== "function") {
2651
+ Object.assign = function(target) {
2652
+ for(var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
2653
+ sources[_key - 1] = arguments[_key];
2538
2654
  }
2539
- }
2540
- } catch (err) {
2541
- _didIteratorError = true;
2542
- _iteratorError = err;
2543
- } finally{
2544
- try {
2545
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2546
- _iterator.return();
2655
+ if (target == null) {
2656
+ throw new TypeError("Cannot convert undefined or null to object");
2547
2657
  }
2548
- } finally{
2549
- if (_didIteratorError) {
2550
- throw _iteratorError;
2658
+ var to = Object(target);
2659
+ for(var i = 0; i < sources.length; i++){
2660
+ var nextSource = sources[i];
2661
+ if (nextSource != null) {
2662
+ for(var nextKey in nextSource){
2663
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
2664
+ to[nextKey] = nextSource[nextKey];
2665
+ }
2666
+ }
2667
+ }
2551
2668
  }
2552
- }
2669
+ return to;
2670
+ };
2553
2671
  }
2554
- return void 0;
2555
2672
  }
2556
- function readStoredDeviceId() {
2557
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2558
- try {
2559
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2560
- var key = _step.value;
2561
- var value = readStoredString(key);
2562
- if (value) {
2563
- return value;
2564
- }
2565
- }
2566
- } catch (err) {
2567
- _didIteratorError = true;
2568
- _iteratorError = err;
2569
- } finally{
2570
- try {
2571
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2572
- _iterator.return();
2673
+ function polyfillArrayFrom() {
2674
+ if (!Array.from) {
2675
+ Array.from = function(arrayLike, mapFn, thisArg) {
2676
+ var items = Object(arrayLike);
2677
+ if (arrayLike == null) {
2678
+ throw new TypeError("Array.from requires an array-like object");
2573
2679
  }
2574
- } finally{
2575
- if (_didIteratorError) {
2576
- throw _iteratorError;
2680
+ var len = items.length >>> 0;
2681
+ var result = new Array(len);
2682
+ for(var i = 0; i < len; i++){
2683
+ if (mapFn) {
2684
+ result[i] = mapFn.call(thisArg, items[i], i);
2685
+ } else {
2686
+ result[i] = items[i];
2687
+ }
2577
2688
  }
2578
- }
2689
+ return result;
2690
+ };
2579
2691
  }
2580
- return void 0;
2581
2692
  }
2582
- function readStoredString(key) {
2583
- if (typeof window === "undefined") {
2584
- return void 0;
2585
- }
2586
- try {
2587
- var _window_localStorage;
2588
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2589
- return value || void 0;
2590
- } catch (unused) {
2591
- return void 0;
2693
+ function polyfillStringStartsWith() {
2694
+ if (!String.prototype.startsWith) {
2695
+ String.prototype.startsWith = function(search, pos) {
2696
+ pos = !pos || pos < 0 ? 0 : +pos;
2697
+ return this.substring(pos, pos + search.length) === search;
2698
+ };
2592
2699
  }
2593
2700
  }
2594
- function readStoredLimitAdTracking() {
2595
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2596
- }
2597
- function normalizeBoolean(value) {
2598
- if (typeof value === "boolean") {
2599
- return value;
2600
- }
2601
- if (typeof value === "number") {
2602
- return value === 1;
2701
+ function polyfillStringEndsWith() {
2702
+ if (!String.prototype.endsWith) {
2703
+ String.prototype.endsWith = function(search, length) {
2704
+ if (length === void 0 || length > this.length) {
2705
+ length = this.length;
2706
+ }
2707
+ return this.substring(length - search.length, length) === search;
2708
+ };
2603
2709
  }
2604
- if (typeof value === "string") {
2605
- var normalized = value.toLowerCase();
2606
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
2607
- return true;
2608
- }
2609
- if (normalized === "0" || normalized === "false" || normalized === "no") {
2610
- return false;
2611
- }
2710
+ }
2711
+ function polyfillStringIncludes() {
2712
+ if (!String.prototype.includes) {
2713
+ String.prototype.includes = function(search, start) {
2714
+ if (typeof start !== "number") {
2715
+ start = 0;
2716
+ }
2717
+ if (start + search.length > this.length) {
2718
+ return false;
2719
+ }
2720
+ return this.indexOf(search, start) !== -1;
2721
+ };
2612
2722
  }
2613
- return void 0;
2723
+ }
2724
+ function initializePolyfills() {
2725
+ polyfillObjectAssign();
2726
+ polyfillArrayFrom();
2727
+ polyfillStringStartsWith();
2728
+ polyfillStringEndsWith();
2729
+ polyfillStringIncludes();
2730
+ polyfillURLSearchParams();
2731
+ polyfillTextEncoder();
2732
+ polyfillPromiseFinally();
2614
2733
  }
2615
2734
  // src/utils/vastMacros.ts
2616
2735
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
@@ -2733,7 +2852,7 @@ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2733
2852
  }
2734
2853
  }
2735
2854
  ];
2736
- function isMacroPlaceholder(value) {
2855
+ function isMacroPlaceholder2(value) {
2737
2856
  if (value == null) return true;
2738
2857
  var trimmed = value.trim();
2739
2858
  if (!trimmed) return true;
@@ -2792,11 +2911,11 @@ function applyDeviceIdentityParams(params, ctx) {
2792
2911
  if (runtimeId) {
2793
2912
  params.set("rdid", runtimeId);
2794
2913
  params.set("idtype", runtimeType || tagType || "aaid");
2795
- params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2914
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
2796
2915
  return;
2797
2916
  }
2798
- var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2799
- var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2917
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
2918
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
2800
2919
  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2801
2920
  params.delete("rdid");
2802
2921
  params.delete("idtype");
@@ -2804,10 +2923,10 @@ function applyDeviceIdentityParams(params, ctx) {
2804
2923
  return;
2805
2924
  }
2806
2925
  if (tagRdidValid) {
2807
- if (isMacroPlaceholder(tagType) && runtimeType) {
2926
+ if (isMacroPlaceholder2(tagType) && runtimeType) {
2808
2927
  params.set("idtype", runtimeType);
2809
2928
  }
2810
- if (isMacroPlaceholder(tagLat)) {
2929
+ if (isMacroPlaceholder2(tagLat)) {
2811
2930
  params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2812
2931
  }
2813
2932
  return;
@@ -2993,7 +3112,7 @@ function applyVastMacros(baseUrl, ctx) {
2993
3112
  }
2994
3113
  var staleKeys = [];
2995
3114
  params.forEach(function(value, key) {
2996
- if (isMacroPlaceholder(value)) {
3115
+ if (isMacroPlaceholder2(value)) {
2997
3116
  staleKeys.push(key);
2998
3117
  }
2999
3118
  });
@@ -5942,7 +6061,7 @@ var HlsEngine = /*#__PURE__*/ function() {
5942
6061
  key: "setupNativeHls",
5943
6062
  value: function setupNativeHls() {
5944
6063
  return _async_to_generator(function() {
5945
- var _this_config_isLiveStream, _this_config_lowLatencyMode, _this_video_play;
6064
+ var _this_config_isLiveStream, _this_config_lowLatencyMode, adBehavior, _this_video_play;
5946
6065
  return _ts_generator(this, function(_state) {
5947
6066
  switch(_state.label){
5948
6067
  case 0:
@@ -5951,10 +6070,11 @@ var HlsEngine = /*#__PURE__*/ function() {
5951
6070
  this.video.src = this.config.src;
5952
6071
  this.isLiveStream = (_this_config_isLiveStream = this.config.isLiveStream) !== null && _this_config_isLiveStream !== void 0 ? _this_config_isLiveStream : (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false;
5953
6072
  if (this.debug) {
5954
- console.log("[StormcloudVideoPlayer] Using native HLS playback - VOD mode:", {
6073
+ adBehavior = this.isLiveStream ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
6074
+ console.log("[StormcloudVideoPlayer] Using native HLS playback:", {
5955
6075
  isLive: this.isLiveStream,
5956
6076
  allowNativeHls: this.config.allowNativeHls,
5957
- adBehavior: "vod (main video pauses during ads)"
6077
+ adBehavior: adBehavior
5958
6078
  });
5959
6079
  }
5960
6080
  if (!this.config.autoplay) return [
@@ -6363,6 +6483,14 @@ var HlsEngine = /*#__PURE__*/ function() {
6363
6483
  });
6364
6484
  }
6365
6485
  },
6486
+ {
6487
+ key: "getLiveSyncPosition",
6488
+ value: function getLiveSyncPosition() {
6489
+ var _this_hls;
6490
+ var pos = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.liveSyncPosition;
6491
+ return typeof pos === "number" && Number.isFinite(pos) ? pos : void 0;
6492
+ }
6493
+ },
6366
6494
  {
6367
6495
  key: "destroy",
6368
6496
  value: function destroy() {
@@ -7937,6 +8065,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7937
8065
  this.host.video.volume = restoredVolume;
7938
8066
  }
7939
8067
  if (this.host.shouldContinueLiveStreamDuringAds()) {
8068
+ var liveSyncPos = this.host.getLiveSyncPosition();
8069
+ if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8070
+ if (this.debug) {
8071
+ console.log("[StormcloudVideoPlayer] Live break end — snapping to live edge: ".concat(this.host.video.currentTime.toFixed(2), "s → ").concat(liveSyncPos.toFixed(2), "s"));
8072
+ }
8073
+ this.host.video.currentTime = liveSyncPos;
8074
+ }
7940
8075
  if (this.host.video.paused) {
7941
8076
  var _this_host_video_play;
7942
8077
  if (this.debug) console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
@@ -8079,6 +8214,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8079
8214
  shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
8080
8215
  return _this.shouldContinueLiveStreamDuringAds();
8081
8216
  },
8217
+ getLiveSyncPosition: function getLiveSyncPosition() {
8218
+ return _this.hlsEngine.getLiveSyncPosition();
8219
+ },
8082
8220
  generateVastUrls: function generateVastUrls(base, count) {
8083
8221
  return _this.generateVastUrls(base, count);
8084
8222
  }
@@ -8120,7 +8258,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8120
8258
  // ───────────────────────────────────────────────────────────────
8121
8259
  function load() {
8122
8260
  return _async_to_generator(function() {
8123
- var _this, _this_config_lowLatencyMode, error;
8261
+ var _this, _this_config_lowLatencyMode, error, continueLiveStreamDuringAds;
8124
8262
  return _ts_generator(this, function(_state) {
8125
8263
  switch(_state.label){
8126
8264
  case 0:
@@ -8174,15 +8312,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8174
8312
  3,
8175
8313
  6
8176
8314
  ];
8177
- this.adPlayer.destroy();
8178
- this.adPlayer = this.createAdPlayer(false);
8179
- this.adPlayer.initialize();
8180
8315
  return [
8181
8316
  4,
8182
8317
  this.hlsEngine.setupNativeHls()
8183
8318
  ];
8184
8319
  case 5:
8185
8320
  _state.sent();
8321
+ continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
8322
+ if (this.debug) {
8323
+ console.log("[StormcloudVideoPlayer] Native HLS ad behavior:", {
8324
+ isLive: this.hlsEngine.isLiveStream,
8325
+ continueLiveStreamDuringAds: continueLiveStreamDuringAds
8326
+ });
8327
+ }
8328
+ this.adPlayer.destroy();
8329
+ this.adPlayer = this.createAdPlayer(continueLiveStreamDuringAds);
8330
+ this.adPlayer.initialize();
8186
8331
  return [
8187
8332
  2
8188
8333
  ];
@@ -8290,9 +8435,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8290
8435
  {
8291
8436
  key: "shouldContinueLiveStreamDuringAds",
8292
8437
  value: function shouldContinueLiveStreamDuringAds() {
8293
- if (this.config.allowNativeHls) return false;
8294
- if (!this.hlsEngine.isLiveStream) return false;
8295
- return true;
8438
+ if (this.hlsEngine.isLiveStream) {
8439
+ return true;
8440
+ }
8441
+ var duration = this.video.duration;
8442
+ if (!Number.isFinite(duration) || duration === Infinity) {
8443
+ return true;
8444
+ }
8445
+ return false;
8296
8446
  }
8297
8447
  },
8298
8448
  {
@@ -8590,9 +8740,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8590
8740
  this.adBreak.showAds = true;
8591
8741
  this.adBreak.inAdBreak = true;
8592
8742
  this.timing.currentAdBreakStartWallClockMs = Date.now();
8593
- if (!this.video.paused) {
8594
- this.video.pause();
8595
- }
8596
8743
  _state.label = 1;
8597
8744
  case 1:
8598
8745
  _state.trys.push([