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.
@@ -1547,300 +1547,759 @@ function publishMQTT(topic, payload) {
1547
1547
  return false;
1548
1548
  }
1549
1549
  }
1550
- // src/utils/tracking.ts
1551
- var cachedBrowserId = null;
1552
- function getClientInfo() {
1553
- var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
1550
+ // src/utils/vastEnvironmentSignals.ts
1551
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
1552
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
1553
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
1554
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
1555
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
1556
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
1557
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
1558
+ var PLAYER_ID_STORAGE_KEY = "stormcloud.player.id";
1559
+ var LG_TEST_APP_ID = "com.hulu.plus";
1560
+ var LG_TEST_APP_NAME = "Hulu";
1561
+ var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
1562
+ var _lgTestDeviceId;
1563
+ function getLgTestDeviceId() {
1564
+ if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
1565
+ return _lgTestDeviceId;
1566
+ }
1567
+ function isLgWebOS() {
1568
+ if (typeof navigator === "undefined") return false;
1569
+ return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
1570
+ }
1571
+ function getDefaultAppId() {
1572
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
1554
1573
  var ua = navigator.userAgent;
1555
- var platform = navigator.platform;
1556
- var vendor = navigator.vendor || "";
1557
- var maxTouchPoints = navigator.maxTouchPoints || 0;
1558
- var memory = navigator.deviceMemory || null;
1559
- var hardwareConcurrency = navigator.hardwareConcurrency || 1;
1560
- var screenInfo = {
1561
- width: (_screen = screen) === null || _screen === void 0 ? void 0 : _screen.width,
1562
- height: (_screen1 = screen) === null || _screen1 === void 0 ? void 0 : _screen1.height,
1563
- availWidth: (_screen2 = screen) === null || _screen2 === void 0 ? void 0 : _screen2.availWidth,
1564
- availHeight: (_screen3 = screen) === null || _screen3 === void 0 ? void 0 : _screen3.availHeight,
1565
- orientation: ((_screen4 = screen) === null || _screen4 === void 0 ? void 0 : (_screen_orientation = _screen4.orientation) === null || _screen_orientation === void 0 ? void 0 : _screen_orientation.type) || "",
1566
- pixelDepth: (_screen5 = screen) === null || _screen5 === void 0 ? void 0 : _screen5.pixelDepth
1567
- };
1568
- var deviceType = "desktop";
1569
- var brand = "Unknown";
1570
- var os = "Unknown";
1571
- var model = "";
1572
- var isSmartTV = false;
1573
- var isAndroid = false;
1574
- var isWebView = false;
1575
- var isWebApp = false;
1576
- if (ua.includes("Web0S")) {
1577
- brand = "LG";
1578
- os = "webOS";
1579
- isSmartTV = true;
1580
- deviceType = "tv";
1581
- var webosMatch = ua.match(/Web0S\/([^\s]+)/);
1582
- model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
1583
- } else if (ua.includes("Tizen")) {
1584
- brand = "Samsung";
1585
- os = "Tizen";
1586
- isSmartTV = true;
1587
- deviceType = "tv";
1588
- var tizenMatch = ua.match(/Tizen\/([^\s]+)/);
1589
- var tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
1590
- model = tizenMatch ? "Tizen ".concat(tizenMatch[1], " ").concat(tvMatch).trim() : "Tizen TV";
1591
- } else if (ua.includes("Philips")) {
1592
- brand = "Philips";
1593
- os = "Saphi";
1594
- isSmartTV = true;
1595
- deviceType = "tv";
1596
- } else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
1597
- brand = "Sharp";
1598
- os = "Android TV";
1599
- isSmartTV = true;
1600
- deviceType = "tv";
1601
- } else if (ua.includes("Android") && (ua.includes("Sony") || vendor.includes("Sony"))) {
1602
- brand = "Sony";
1603
- os = "Android TV";
1604
- isSmartTV = true;
1605
- deviceType = "tv";
1606
- } else if (ua.includes("Android") && (ua.includes("NetCast") || ua.includes("LG"))) {
1607
- brand = "LG";
1608
- os = "Android TV";
1609
- isSmartTV = true;
1610
- deviceType = "tv";
1611
- } else if (ua.includes(" Roku") || ua.includes("Roku/")) {
1612
- brand = "Roku";
1613
- os = "Roku OS";
1614
- isSmartTV = true;
1615
- deviceType = "tv";
1616
- } else if (ua.includes("AppleTV")) {
1617
- brand = "Apple";
1618
- os = "tvOS";
1619
- isSmartTV = true;
1620
- deviceType = "tv";
1574
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
1575
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
1576
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
1577
+ return AIRY_ANDROID_APP_ID;
1578
+ }
1579
+ var DEVICE_ID_STORAGE_KEYS = [
1580
+ "rdid",
1581
+ "ifa",
1582
+ "advertisingId",
1583
+ "advertising_id",
1584
+ "deviceAdvertisingId",
1585
+ "aaid",
1586
+ "adid",
1587
+ "rida",
1588
+ "tifa",
1589
+ "lgudid"
1590
+ ];
1591
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
1592
+ "aaid",
1593
+ "adid"
1594
+ ]);
1595
+ function resolveVastEnvironmentSignals(isCtv) {
1596
+ var _ref;
1597
+ var bridgeSignals = readNativeBridgeSignals();
1598
+ var platformDevice = readPlatformNativeDeviceId();
1599
+ var lg = isCtv && isLgWebOS();
1600
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId || (lg && platformDevice.limitAdTracking !== true ? getLgTestDeviceId() : void 0);
1601
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType() || (lg ? "lgudid" : void 0);
1602
+ var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
1603
+ var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
1604
+ if (isCtv) {
1605
+ return _object_spread_props(_object_spread({
1606
+ isCtv: true,
1607
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
1608
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
1609
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
1610
+ sessionId: getOrCreateCtvSessionId()
1611
+ }, deviceId ? {
1612
+ deviceId: deviceId
1613
+ } : {}, deviceIdType ? {
1614
+ deviceIdType: deviceIdType
1615
+ } : {}, limitAdTracking != null ? {
1616
+ limitAdTracking: limitAdTracking
1617
+ } : {}), {
1618
+ deviceTypeHint: 5
1619
+ });
1621
1620
  }
1622
- if (ua.includes("Android")) {
1623
- isAndroid = true;
1624
- os = "Android";
1625
- deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
1626
- if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
1627
- deviceType = "tv";
1628
- isSmartTV = true;
1629
- brand = brand === "Unknown" ? "Android TV" : brand;
1630
- }
1631
- var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
1632
- if (androidModelMatch && androidModelMatch[1]) {
1633
- model = androidModelMatch[1];
1634
- }
1621
+ return _object_spread({
1622
+ isCtv: false
1623
+ }, deviceId ? {
1624
+ deviceId: deviceId
1625
+ } : {}, deviceIdType ? {
1626
+ deviceIdType: deviceIdType
1627
+ } : {}, limitAdTracking != null ? {
1628
+ limitAdTracking: limitAdTracking
1629
+ } : {});
1630
+ }
1631
+ function inferDeviceIdType() {
1632
+ if (typeof navigator === "undefined") {
1633
+ return void 0;
1635
1634
  }
1636
- if (/iPad|iPhone|iPod/.test(ua)) {
1637
- os = "iOS";
1638
- deviceType = "mobile";
1639
- brand = "Apple";
1640
- if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
1641
- deviceType = "tablet";
1642
- }
1635
+ var ua = navigator.userAgent;
1636
+ if (/Roku/i.test(ua)) return "rida";
1637
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
1638
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
1639
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
1640
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
1641
+ if (/Android|Google TV/i.test(ua)) return "aaid";
1642
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
1643
+ return void 0;
1644
+ }
1645
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
1646
+ if (!tagType || !runtimeType) return false;
1647
+ var tag = tagType.toLowerCase();
1648
+ var runtime = runtimeType.toLowerCase();
1649
+ if (tag === runtime) return true;
1650
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
1651
+ }
1652
+ function resolveNativeDeviceId() {
1653
+ var bridgeSignals = readNativeBridgeSignals();
1654
+ var platformDevice = readPlatformNativeDeviceId();
1655
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || platformDevice.deviceId;
1656
+ if (!deviceId || isMacroPlaceholder(deviceId) || isZeroedAdId(deviceId)) {
1657
+ return void 0;
1643
1658
  }
1644
- if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
1645
- if (ua.includes("Windows")) {
1646
- os = "Windows";
1647
- deviceType = "desktop";
1648
- } else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
1649
- os = "macOS";
1650
- deviceType = "desktop";
1651
- if (maxTouchPoints > 1) deviceType = "tablet";
1652
- } else if (ua.includes("Linux")) {
1653
- os = "Linux";
1654
- deviceType = "desktop";
1655
- }
1659
+ return deviceId;
1660
+ }
1661
+ function getOrCreateStoredUuid(storageKey) {
1662
+ if (typeof window === "undefined") {
1663
+ return void 0;
1656
1664
  }
1657
- if (brand === "Unknown") {
1658
- if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
1659
- if (vendor.includes("Apple")) brand = "Apple";
1660
- if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
1665
+ var existing = readStoredString(storageKey);
1666
+ if (existing) {
1667
+ return existing;
1661
1668
  }
1662
- isWebView = /wv|WebView|Linux; U;/.test(ua);
1663
- if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
1664
- isWebView = true;
1669
+ var id = createUuid();
1670
+ try {
1671
+ var _window_localStorage;
1672
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(storageKey, id);
1673
+ } catch (unused) {}
1674
+ return id;
1675
+ }
1676
+ function getOrCreateCtvSessionId() {
1677
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
1678
+ if (existing) {
1679
+ return existing;
1665
1680
  }
1666
- 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;
1667
- return {
1668
- brand: brand,
1669
- os: os,
1670
- model: model || ua.substring(0, 50) + "...",
1671
- deviceType: deviceType,
1672
- isSmartTV: isSmartTV,
1673
- isAndroid: isAndroid,
1674
- isWebView: isWebView,
1675
- isWebApp: isWebApp,
1676
- domain: window.location.hostname,
1677
- origin: window.location.origin,
1678
- path: window.location.pathname,
1679
- userAgent: ua,
1680
- vendor: vendor,
1681
- platform: platform,
1682
- screen: screenInfo,
1683
- hardwareConcurrency: hardwareConcurrency,
1684
- deviceMemory: memory,
1685
- maxTouchPoints: maxTouchPoints,
1686
- language: navigator.language,
1687
- languages: ((_navigator_languages = navigator.languages) === null || _navigator_languages === void 0 ? void 0 : _navigator_languages.join(",")) || "",
1688
- cookieEnabled: navigator.cookieEnabled,
1689
- doNotTrack: navigator.doNotTrack || "",
1690
- referrer: document.referrer,
1691
- visibilityState: document.visibilityState
1692
- };
1681
+ var sessionId = createUuid();
1682
+ try {
1683
+ var _window_localStorage;
1684
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
1685
+ } catch (unused) {}
1686
+ return sessionId;
1693
1687
  }
1694
- function getBrowserID(clientInfo) {
1695
- return _async_to_generator(function() {
1696
- var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
1697
- return _ts_generator(this, function(_state) {
1698
- switch(_state.label){
1699
- case 0:
1700
- if (cachedBrowserId) {
1701
- return [
1702
- 2,
1703
- cachedBrowserId
1704
- ];
1705
- }
1706
- fingerprintString = JSON.stringify(clientInfo);
1707
- if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
1708
- 3,
1709
- 5
1710
- ];
1711
- _state.label = 1;
1712
- case 1:
1713
- _state.trys.push([
1714
- 1,
1715
- 4,
1716
- ,
1717
- 5
1718
- ]);
1719
- return [
1720
- 4,
1721
- crypto.subtle.digest("SHA-256", new Uint8Array([
1722
- 1,
1723
- 2,
1724
- 3
1725
- ]))
1726
- ];
1727
- case 2:
1728
- _state.sent();
1729
- if (typeof TextEncoder !== "undefined") {
1730
- encodedData = new TextEncoder().encode(fingerprintString);
1731
- } else {
1732
- utf8 = unescape(encodeURIComponent(fingerprintString));
1733
- buffer = new Uint8Array(utf8.length);
1734
- for(i = 0; i < utf8.length; i++){
1735
- buffer[i] = utf8.charCodeAt(i);
1736
- }
1737
- encodedData = buffer;
1738
- }
1739
- return [
1740
- 4,
1741
- crypto.subtle.digest("SHA-256", encodedData)
1742
- ];
1743
- case 3:
1744
- hashBuffer = _state.sent();
1745
- hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
1746
- return b.toString(16).padStart(2, "0");
1747
- }).join("");
1748
- cachedBrowserId = hashHex;
1749
- return [
1750
- 2,
1751
- hashHex
1752
- ];
1753
- case 4:
1754
- unused = _state.sent();
1755
- console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
1756
- return [
1757
- 3,
1758
- 5
1759
- ];
1760
- case 5:
1761
- hash = 0;
1762
- for(i1 = 0; i1 < fingerprintString.length; i1++){
1763
- char = fingerprintString.charCodeAt(i1);
1764
- hash = (hash << 5) - hash + char;
1765
- hash = hash & hash;
1766
- }
1767
- fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
1768
- timestamp = Date.now().toString(16).padStart(12, "0");
1769
- random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
1770
- cachedBrowserId = (fallbackHash + timestamp + random).padEnd(64, "0");
1771
- return [
1772
- 2,
1773
- cachedBrowserId
1774
- ];
1688
+ function createUuid() {
1689
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1690
+ return crypto.randomUUID();
1691
+ }
1692
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
1693
+ var value = Math.floor(Math.random() * 16);
1694
+ var nibble = char === "x" ? value : value & 3 | 8;
1695
+ return nibble.toString(16);
1696
+ });
1697
+ }
1698
+ function readPlatformNativeDeviceId() {
1699
+ if (typeof window === "undefined") return {};
1700
+ try {
1701
+ var _window_webapis;
1702
+ var adinfo = (_window_webapis = window.webapis) === null || _window_webapis === void 0 ? void 0 : _window_webapis.adinfo;
1703
+ if (adinfo) {
1704
+ var tifa = typeof adinfo.getTIFA === "function" ? adinfo.getTIFA() : adinfo.tifa;
1705
+ if (typeof tifa === "string" && tifa && !isMacroPlaceholder(tifa)) {
1706
+ var lat = typeof adinfo.isLATEnabled === "function" ? adinfo.isLATEnabled() : void 0;
1707
+ return _object_spread({
1708
+ deviceId: tifa,
1709
+ deviceIdType: "tifa"
1710
+ }, typeof lat === "boolean" ? {
1711
+ limitAdTracking: lat
1712
+ } : {});
1775
1713
  }
1776
- });
1777
- })();
1714
+ }
1715
+ } catch (unused) {}
1716
+ try {
1717
+ var webOSDev = window.webOSDev;
1718
+ if (webOSDev) {
1719
+ var _webOSDev_lgudid;
1720
+ var lgudid = typeof webOSDev.LGUDID === "function" ? webOSDev.LGUDID() : (_webOSDev_lgudid = webOSDev.lgudid) !== null && _webOSDev_lgudid !== void 0 ? _webOSDev_lgudid : webOSDev.LGUDID;
1721
+ if (typeof lgudid === "string" && lgudid) {
1722
+ if (isZeroedAdId(lgudid)) {
1723
+ return {
1724
+ deviceIdType: "lgudid",
1725
+ limitAdTracking: true
1726
+ };
1727
+ }
1728
+ if (!isMacroPlaceholder(lgudid)) {
1729
+ return {
1730
+ deviceId: lgudid,
1731
+ deviceIdType: "lgudid",
1732
+ limitAdTracking: false
1733
+ };
1734
+ }
1735
+ }
1736
+ }
1737
+ } catch (unused) {}
1738
+ try {
1739
+ var roku = window.Roku;
1740
+ if (roku) {
1741
+ var rida = typeof roku.getPublisherUniqueId === "function" ? roku.getPublisherUniqueId() : roku.rida;
1742
+ if (typeof rida === "string" && rida && !isMacroPlaceholder(rida)) {
1743
+ return {
1744
+ deviceId: rida,
1745
+ deviceIdType: "rida",
1746
+ limitAdTracking: false
1747
+ };
1748
+ }
1749
+ }
1750
+ } catch (unused) {}
1751
+ return {};
1778
1752
  }
1779
- function canPublish(licenseKey) {
1780
- return Boolean(isMQTTEnabled() && licenseKey);
1753
+ var ZEROED_AD_ID_PATTERNS = /* @__PURE__ */ new Set([
1754
+ "38400000-8cf0-11bd-b23e-10b96e40000d",
1755
+ "00000000-0000-0000-0000-000000000000"
1756
+ ]);
1757
+ function isMacroPlaceholder(value) {
1758
+ var t = value.trim();
1759
+ return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
1781
1760
  }
1782
- function buildPlayerMetricEvent() {
1783
- return _async_to_generator(function() {
1784
- var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
1785
- var _arguments = arguments;
1786
- return _ts_generator(this, function(_state) {
1787
- switch(_state.label){
1788
- case 0:
1789
- context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1790
- clientInfo = getClientInfo();
1791
- return [
1792
- 4,
1793
- getBrowserID(clientInfo)
1794
- ];
1795
- case 1:
1796
- playerId = _state.sent();
1797
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
1798
- return [
1799
- 2,
1800
- _object_spread({
1801
- player_id: playerId,
1802
- device_type: clientInfo.deviceType,
1803
- os: clientInfo.os.toLowerCase(),
1804
- ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
1805
- ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
1806
- capture_at: captureAt
1807
- }, context.inputStreamType ? {
1808
- input_stream_type: context.inputStreamType
1809
- } : {})
1810
- ];
1761
+ function isZeroedAdId(value) {
1762
+ return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
1763
+ }
1764
+ function readNativeBridgeSignals() {
1765
+ if (typeof window === "undefined") {
1766
+ return {};
1767
+ }
1768
+ var candidates = [
1769
+ window.__STORMCLOUD_CTV_AD_INFO__,
1770
+ window.__STORMCLOUD_CTV__,
1771
+ window.stormcloudCtv,
1772
+ window.AiryTV,
1773
+ window.Android,
1774
+ window.webOS,
1775
+ window.tizen,
1776
+ window.amazon
1777
+ ].filter(Boolean);
1778
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1779
+ try {
1780
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1781
+ var source = _step.value;
1782
+ var contentUrl = readBridgeValue(source, [
1783
+ "contentUrl",
1784
+ "url",
1785
+ "videoUrl",
1786
+ "canonicalUrl"
1787
+ ]) || void 0;
1788
+ var appId = readBridgeValue(source, [
1789
+ "appId",
1790
+ "msid",
1791
+ "applicationId",
1792
+ "packageName"
1793
+ ]) || void 0;
1794
+ var appName = readBridgeValue(source, [
1795
+ "appName",
1796
+ "an",
1797
+ "applicationName"
1798
+ ]) || void 0;
1799
+ var deviceId = readBridgeValue(source, [
1800
+ "rdid",
1801
+ "ifa",
1802
+ "advertisingId",
1803
+ "adId",
1804
+ "deviceId",
1805
+ "lgudid",
1806
+ "LGUDID",
1807
+ "tifa",
1808
+ "rida",
1809
+ "afai",
1810
+ "aaid"
1811
+ ]) || void 0;
1812
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
1813
+ var deviceIdType = readBridgeValue(source, [
1814
+ "idtype",
1815
+ "deviceIdType",
1816
+ "advertisingIdType",
1817
+ "idType"
1818
+ ]) || inferDeviceIdType();
1819
+ var limitAdTracking = readBridgeBoolean(source, [
1820
+ "is_lat",
1821
+ "limitAdTracking",
1822
+ "limitedAdTracking",
1823
+ "lat"
1824
+ ]);
1825
+ return _object_spread({}, contentUrl ? {
1826
+ contentUrl: contentUrl
1827
+ } : {}, appId ? {
1828
+ appId: appId
1829
+ } : {}, appName ? {
1830
+ appName: appName
1831
+ } : {}, deviceId ? {
1832
+ deviceId: deviceId
1833
+ } : {}, deviceId && deviceIdType ? {
1834
+ deviceIdType: deviceIdType
1835
+ } : {}, deviceId && limitAdTracking != null ? {
1836
+ limitAdTracking: limitAdTracking
1837
+ } : {});
1838
+ }
1839
+ } catch (err) {
1840
+ _didIteratorError = true;
1841
+ _iteratorError = err;
1842
+ } finally{
1843
+ try {
1844
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1845
+ _iterator.return();
1811
1846
  }
1812
- });
1813
- }).apply(this, arguments);
1847
+ } finally{
1848
+ if (_didIteratorError) {
1849
+ throw _iteratorError;
1850
+ }
1851
+ }
1852
+ }
1853
+ return {};
1814
1854
  }
1815
- function publishTracking(licenseKey, channel, body) {
1816
- ensureMQTTClient();
1817
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
1855
+ function readBridgeValue(source, keys) {
1856
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1857
+ try {
1858
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1859
+ var key = _step.value;
1860
+ var value = source === null || source === void 0 ? void 0 : source[key];
1861
+ if (typeof value === "string" && value) {
1862
+ return value;
1863
+ }
1864
+ if (typeof value === "function") {
1865
+ try {
1866
+ var result = value.call(source);
1867
+ if (typeof result === "string" && result) {
1868
+ return result;
1869
+ }
1870
+ } catch (unused) {}
1871
+ }
1872
+ }
1873
+ } catch (err) {
1874
+ _didIteratorError = true;
1875
+ _iteratorError = err;
1876
+ } finally{
1877
+ try {
1878
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1879
+ _iterator.return();
1880
+ }
1881
+ } finally{
1882
+ if (_didIteratorError) {
1883
+ throw _iteratorError;
1884
+ }
1885
+ }
1886
+ }
1887
+ return void 0;
1818
1888
  }
1819
- function sendInitialTracking(_0) {
1820
- return _async_to_generator(function(licenseKey) {
1821
- var context, metricEvent, error;
1822
- var _arguments = arguments;
1889
+ function readBridgeBoolean(source, keys) {
1890
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1891
+ try {
1892
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1893
+ var key = _step.value;
1894
+ var value = source === null || source === void 0 ? void 0 : source[key];
1895
+ var normalized = normalizeBoolean(value);
1896
+ if (normalized != null) {
1897
+ return normalized;
1898
+ }
1899
+ if (typeof value === "function") {
1900
+ try {
1901
+ var result = normalizeBoolean(value.call(source));
1902
+ if (result != null) {
1903
+ return result;
1904
+ }
1905
+ } catch (unused) {}
1906
+ }
1907
+ }
1908
+ } catch (err) {
1909
+ _didIteratorError = true;
1910
+ _iteratorError = err;
1911
+ } finally{
1912
+ try {
1913
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1914
+ _iterator.return();
1915
+ }
1916
+ } finally{
1917
+ if (_didIteratorError) {
1918
+ throw _iteratorError;
1919
+ }
1920
+ }
1921
+ }
1922
+ return void 0;
1923
+ }
1924
+ function readStoredDeviceId() {
1925
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1926
+ try {
1927
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1928
+ var key = _step.value;
1929
+ var value = readStoredString(key);
1930
+ if (value) {
1931
+ return value;
1932
+ }
1933
+ }
1934
+ } catch (err) {
1935
+ _didIteratorError = true;
1936
+ _iteratorError = err;
1937
+ } finally{
1938
+ try {
1939
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1940
+ _iterator.return();
1941
+ }
1942
+ } finally{
1943
+ if (_didIteratorError) {
1944
+ throw _iteratorError;
1945
+ }
1946
+ }
1947
+ }
1948
+ return void 0;
1949
+ }
1950
+ function readStoredString(key) {
1951
+ if (typeof window === "undefined") {
1952
+ return void 0;
1953
+ }
1954
+ try {
1955
+ var _window_localStorage;
1956
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
1957
+ return value || void 0;
1958
+ } catch (unused) {
1959
+ return void 0;
1960
+ }
1961
+ }
1962
+ function readStoredLimitAdTracking() {
1963
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
1964
+ }
1965
+ function normalizeBoolean(value) {
1966
+ if (typeof value === "boolean") {
1967
+ return value;
1968
+ }
1969
+ if (typeof value === "number") {
1970
+ return value === 1;
1971
+ }
1972
+ if (typeof value === "string") {
1973
+ var normalized = value.toLowerCase();
1974
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
1975
+ return true;
1976
+ }
1977
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
1978
+ return false;
1979
+ }
1980
+ }
1981
+ return void 0;
1982
+ }
1983
+ // src/utils/tracking.ts
1984
+ var cachedBrowserId = null;
1985
+ function getClientInfo() {
1986
+ var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
1987
+ var ua = navigator.userAgent;
1988
+ var platform = navigator.platform;
1989
+ var vendor = navigator.vendor || "";
1990
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
1991
+ var memory = navigator.deviceMemory || null;
1992
+ var hardwareConcurrency = navigator.hardwareConcurrency || 1;
1993
+ var screenInfo = {
1994
+ width: (_screen = screen) === null || _screen === void 0 ? void 0 : _screen.width,
1995
+ height: (_screen1 = screen) === null || _screen1 === void 0 ? void 0 : _screen1.height,
1996
+ availWidth: (_screen2 = screen) === null || _screen2 === void 0 ? void 0 : _screen2.availWidth,
1997
+ availHeight: (_screen3 = screen) === null || _screen3 === void 0 ? void 0 : _screen3.availHeight,
1998
+ orientation: ((_screen4 = screen) === null || _screen4 === void 0 ? void 0 : (_screen_orientation = _screen4.orientation) === null || _screen_orientation === void 0 ? void 0 : _screen_orientation.type) || "",
1999
+ pixelDepth: (_screen5 = screen) === null || _screen5 === void 0 ? void 0 : _screen5.pixelDepth
2000
+ };
2001
+ var deviceType = "desktop";
2002
+ var brand = "Unknown";
2003
+ var os = "Unknown";
2004
+ var model = "";
2005
+ var isSmartTV = false;
2006
+ var isAndroid = false;
2007
+ var isWebView = false;
2008
+ var isWebApp = false;
2009
+ if (ua.includes("Web0S")) {
2010
+ brand = "LG";
2011
+ os = "webOS";
2012
+ isSmartTV = true;
2013
+ deviceType = "tv";
2014
+ var webosMatch = ua.match(/Web0S\/([^\s]+)/);
2015
+ model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
2016
+ } else if (ua.includes("Tizen")) {
2017
+ brand = "Samsung";
2018
+ os = "Tizen";
2019
+ isSmartTV = true;
2020
+ deviceType = "tv";
2021
+ var tizenMatch = ua.match(/Tizen\/([^\s]+)/);
2022
+ var tvMatch = ua.match(/(?:Smart-TV|SMART-TV|TV)/i) ? "Smart TV" : "";
2023
+ model = tizenMatch ? "Tizen ".concat(tizenMatch[1], " ").concat(tvMatch).trim() : "Tizen TV";
2024
+ } else if (ua.includes("Philips")) {
2025
+ brand = "Philips";
2026
+ os = "Saphi";
2027
+ isSmartTV = true;
2028
+ deviceType = "tv";
2029
+ } else if (ua.includes("Sharp") || ua.includes("AQUOS")) {
2030
+ brand = "Sharp";
2031
+ os = "Android TV";
2032
+ isSmartTV = true;
2033
+ deviceType = "tv";
2034
+ } else if (ua.includes("Android") && (ua.includes("Sony") || vendor.includes("Sony"))) {
2035
+ brand = "Sony";
2036
+ os = "Android TV";
2037
+ isSmartTV = true;
2038
+ deviceType = "tv";
2039
+ } else if (ua.includes("Android") && (ua.includes("NetCast") || ua.includes("LG"))) {
2040
+ brand = "LG";
2041
+ os = "Android TV";
2042
+ isSmartTV = true;
2043
+ deviceType = "tv";
2044
+ } else if (ua.includes(" Roku") || ua.includes("Roku/")) {
2045
+ brand = "Roku";
2046
+ os = "Roku OS";
2047
+ isSmartTV = true;
2048
+ deviceType = "tv";
2049
+ } else if (ua.includes("AppleTV")) {
2050
+ brand = "Apple";
2051
+ os = "tvOS";
2052
+ isSmartTV = true;
2053
+ deviceType = "tv";
2054
+ }
2055
+ if (ua.includes("Android")) {
2056
+ isAndroid = true;
2057
+ os = "Android";
2058
+ deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
2059
+ if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
2060
+ deviceType = "tv";
2061
+ isSmartTV = true;
2062
+ brand = brand === "Unknown" ? "Android TV" : brand;
2063
+ }
2064
+ var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
2065
+ if (androidModelMatch && androidModelMatch[1]) {
2066
+ model = androidModelMatch[1];
2067
+ }
2068
+ }
2069
+ if (/iPad|iPhone|iPod/.test(ua)) {
2070
+ os = "iOS";
2071
+ deviceType = "mobile";
2072
+ brand = "Apple";
2073
+ if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
2074
+ deviceType = "tablet";
2075
+ }
2076
+ }
2077
+ if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
2078
+ if (ua.includes("Windows")) {
2079
+ os = "Windows";
2080
+ deviceType = "desktop";
2081
+ } else if (ua.includes("Mac") && !/iPhone/.test(ua)) {
2082
+ os = "macOS";
2083
+ deviceType = "desktop";
2084
+ if (maxTouchPoints > 1) deviceType = "tablet";
2085
+ } else if (ua.includes("Linux")) {
2086
+ os = "Linux";
2087
+ deviceType = "desktop";
2088
+ }
2089
+ }
2090
+ if (brand === "Unknown") {
2091
+ if (vendor.includes("Google") || ua.includes("Chrome")) brand = "Google";
2092
+ if (vendor.includes("Apple")) brand = "Apple";
2093
+ if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
2094
+ }
2095
+ isWebView = /wv|WebView|Linux; U;/.test(ua);
2096
+ if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
2097
+ isWebView = true;
2098
+ }
2099
+ 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;
2100
+ return {
2101
+ brand: brand,
2102
+ os: os,
2103
+ model: model || ua.substring(0, 50) + "...",
2104
+ deviceType: deviceType,
2105
+ isSmartTV: isSmartTV,
2106
+ isAndroid: isAndroid,
2107
+ isWebView: isWebView,
2108
+ isWebApp: isWebApp,
2109
+ domain: window.location.hostname,
2110
+ origin: window.location.origin,
2111
+ path: window.location.pathname,
2112
+ userAgent: ua,
2113
+ vendor: vendor,
2114
+ platform: platform,
2115
+ screen: screenInfo,
2116
+ hardwareConcurrency: hardwareConcurrency,
2117
+ deviceMemory: memory,
2118
+ maxTouchPoints: maxTouchPoints,
2119
+ language: navigator.language,
2120
+ languages: ((_navigator_languages = navigator.languages) === null || _navigator_languages === void 0 ? void 0 : _navigator_languages.join(",")) || "",
2121
+ cookieEnabled: navigator.cookieEnabled,
2122
+ doNotTrack: navigator.doNotTrack || "",
2123
+ referrer: document.referrer,
2124
+ visibilityState: document.visibilityState
2125
+ };
2126
+ }
2127
+ function sha256Hex(input) {
2128
+ return _async_to_generator(function() {
2129
+ var _crypto_subtle, encodedData, utf8, buffer, i, hashBuffer, unused, hash, i1, char, fallbackHash, timestamp, random;
1823
2130
  return _ts_generator(this, function(_state) {
1824
2131
  switch(_state.label){
1825
2132
  case 0:
1826
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
1827
- if (!canPublish(licenseKey)) return [
1828
- 2
2133
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
2134
+ 3,
2135
+ 5
1829
2136
  ];
1830
2137
  _state.label = 1;
1831
2138
  case 1:
1832
2139
  _state.trys.push([
1833
2140
  1,
1834
- 3,
2141
+ 4,
1835
2142
  ,
1836
- 4
2143
+ 5
1837
2144
  ]);
1838
2145
  return [
1839
2146
  4,
1840
- buildPlayerMetricEvent(context, {
1841
- adLoaded: false,
1842
- adDetect: false
1843
- })
2147
+ crypto.subtle.digest("SHA-256", new Uint8Array([
2148
+ 1,
2149
+ 2,
2150
+ 3
2151
+ ]))
2152
+ ];
2153
+ case 2:
2154
+ _state.sent();
2155
+ if (typeof TextEncoder !== "undefined") {
2156
+ encodedData = new TextEncoder().encode(input);
2157
+ } else {
2158
+ utf8 = unescape(encodeURIComponent(input));
2159
+ buffer = new Uint8Array(utf8.length);
2160
+ for(i = 0; i < utf8.length; i++){
2161
+ buffer[i] = utf8.charCodeAt(i);
2162
+ }
2163
+ encodedData = buffer;
2164
+ }
2165
+ return [
2166
+ 4,
2167
+ crypto.subtle.digest("SHA-256", encodedData)
2168
+ ];
2169
+ case 3:
2170
+ hashBuffer = _state.sent();
2171
+ return [
2172
+ 2,
2173
+ Array.from(new Uint8Array(hashBuffer)).map(function(b) {
2174
+ return b.toString(16).padStart(2, "0");
2175
+ }).join("")
2176
+ ];
2177
+ case 4:
2178
+ unused = _state.sent();
2179
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
2180
+ return [
2181
+ 3,
2182
+ 5
2183
+ ];
2184
+ case 5:
2185
+ hash = 0;
2186
+ for(i1 = 0; i1 < input.length; i1++){
2187
+ char = input.charCodeAt(i1);
2188
+ hash = (hash << 5) - hash + char;
2189
+ hash = hash & hash;
2190
+ }
2191
+ fallbackHash = Math.abs(hash).toString(16).padStart(8, "0");
2192
+ timestamp = Date.now().toString(16).padStart(12, "0");
2193
+ random = Math.random().toString(16).substring(2, 14).padStart(12, "0");
2194
+ return [
2195
+ 2,
2196
+ (fallbackHash + timestamp + random).padEnd(64, "0")
2197
+ ];
2198
+ }
2199
+ });
2200
+ })();
2201
+ }
2202
+ function resolvePlayerIdentitySeed(clientInfo) {
2203
+ var nativeDeviceId = resolveNativeDeviceId();
2204
+ if (nativeDeviceId) {
2205
+ return "device:".concat(nativeDeviceId);
2206
+ }
2207
+ var persistedId = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);
2208
+ if (persistedId) {
2209
+ return "persisted:".concat(persistedId);
2210
+ }
2211
+ return "fingerprint:".concat(JSON.stringify(clientInfo));
2212
+ }
2213
+ function getBrowserID(clientInfo) {
2214
+ return _async_to_generator(function() {
2215
+ return _ts_generator(this, function(_state) {
2216
+ switch(_state.label){
2217
+ case 0:
2218
+ if (cachedBrowserId) {
2219
+ return [
2220
+ 2,
2221
+ cachedBrowserId
2222
+ ];
2223
+ }
2224
+ return [
2225
+ 4,
2226
+ sha256Hex(resolvePlayerIdentitySeed(clientInfo))
2227
+ ];
2228
+ case 1:
2229
+ cachedBrowserId = _state.sent();
2230
+ return [
2231
+ 2,
2232
+ cachedBrowserId
2233
+ ];
2234
+ }
2235
+ });
2236
+ })();
2237
+ }
2238
+ function canPublish(licenseKey) {
2239
+ return Boolean(isMQTTEnabled() && licenseKey);
2240
+ }
2241
+ function buildPlayerMetricEvent() {
2242
+ return _async_to_generator(function() {
2243
+ var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
2244
+ var _arguments = arguments;
2245
+ return _ts_generator(this, function(_state) {
2246
+ switch(_state.label){
2247
+ case 0:
2248
+ context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
2249
+ clientInfo = getClientInfo();
2250
+ return [
2251
+ 4,
2252
+ getBrowserID(clientInfo)
2253
+ ];
2254
+ case 1:
2255
+ playerId = _state.sent();
2256
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
2257
+ return [
2258
+ 2,
2259
+ _object_spread({
2260
+ player_id: playerId,
2261
+ device_type: clientInfo.deviceType,
2262
+ os: clientInfo.os.toLowerCase(),
2263
+ ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
2264
+ ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
2265
+ capture_at: captureAt
2266
+ }, context.inputStreamType ? {
2267
+ input_stream_type: context.inputStreamType
2268
+ } : {})
2269
+ ];
2270
+ }
2271
+ });
2272
+ }).apply(this, arguments);
2273
+ }
2274
+ function publishTracking(licenseKey, channel, body) {
2275
+ ensureMQTTClient();
2276
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
2277
+ }
2278
+ function sendInitialTracking(_0) {
2279
+ return _async_to_generator(function(licenseKey) {
2280
+ var context, metricEvent, error;
2281
+ var _arguments = arguments;
2282
+ return _ts_generator(this, function(_state) {
2283
+ switch(_state.label){
2284
+ case 0:
2285
+ context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
2286
+ if (!canPublish(licenseKey)) return [
2287
+ 2
2288
+ ];
2289
+ _state.label = 1;
2290
+ case 1:
2291
+ _state.trys.push([
2292
+ 1,
2293
+ 3,
2294
+ ,
2295
+ 4
2296
+ ]);
2297
+ return [
2298
+ 4,
2299
+ buildPlayerMetricEvent(context, {
2300
+ adLoaded: false,
2301
+ adDetect: false
2302
+ })
1844
2303
  ];
1845
2304
  case 2:
1846
2305
  metricEvent = _state.sent();
@@ -2000,654 +2459,314 @@ function sendAdImpressionTracking(_0, _1) {
2000
2459
  ];
2001
2460
  case 3:
2002
2461
  error = _state.sent();
2003
- console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
2004
- return [
2005
- 3,
2006
- 4
2007
- ];
2008
- case 4:
2009
- return [
2010
- 2
2011
- ];
2012
- }
2013
- });
2014
- }).apply(this, arguments);
2015
- }
2016
- function sendHeartbeat(_0) {
2017
- return _async_to_generator(function(licenseKey) {
2018
- var context, flags, heartbeatData, error;
2019
- var _arguments = arguments;
2020
- return _ts_generator(this, function(_state) {
2021
- switch(_state.label){
2022
- case 0:
2023
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
2024
- if (!canPublish(licenseKey)) return [
2025
- 2
2026
- ];
2027
- _state.label = 1;
2028
- case 1:
2029
- _state.trys.push([
2030
- 1,
2031
- 3,
2032
- ,
2033
- 4
2034
- ]);
2035
- return [
2036
- 4,
2037
- buildPlayerMetricEvent(context, flags)
2038
- ];
2039
- case 2:
2040
- heartbeatData = _state.sent();
2041
- publishTracking(licenseKey, "heartbeat", heartbeatData);
2042
- return [
2043
- 3,
2044
- 4
2045
- ];
2046
- case 3:
2047
- error = _state.sent();
2048
- console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
2049
- return [
2050
- 3,
2051
- 4
2052
- ];
2053
- case 4:
2054
- return [
2055
- 2
2056
- ];
2057
- }
2058
- });
2059
- }).apply(this, arguments);
2060
- }
2061
- // src/utils/polyfills.ts
2062
- function polyfillURLSearchParams() {
2063
- if (typeof URLSearchParams !== "undefined") {
2064
- return;
2065
- }
2066
- var URLSearchParamsPolyfill = /*#__PURE__*/ function() {
2067
- function URLSearchParamsPolyfill(init) {
2068
- var _this = this;
2069
- _class_call_check(this, URLSearchParamsPolyfill);
2070
- this.params = /* @__PURE__ */ new Map();
2071
- if (typeof init === "string") {
2072
- this.parseQueryString(init);
2073
- } else if (_instanceof(init, URLSearchParamsPolyfill)) {
2074
- init.forEach(function(value, key) {
2075
- _this.append(key, value);
2076
- });
2077
- }
2078
- }
2079
- _create_class(URLSearchParamsPolyfill, [
2080
- {
2081
- key: "parseQueryString",
2082
- value: function parseQueryString(query) {
2083
- var _this = this;
2084
- var cleanQuery = query.startsWith("?") ? query.slice(1) : query;
2085
- if (!cleanQuery) return;
2086
- cleanQuery.split("&").forEach(function(param) {
2087
- var _param_split = _sliced_to_array(param.split("="), 2), key = _param_split[0], value = _param_split[1];
2088
- if (key) {
2089
- var decodedKey = _this.safeDecodeURIComponent(key);
2090
- var decodedValue = value ? _this.safeDecodeURIComponent(value) : "";
2091
- _this.append(decodedKey, decodedValue);
2092
- }
2093
- });
2094
- }
2095
- },
2096
- {
2097
- key: "safeDecodeURIComponent",
2098
- value: function safeDecodeURIComponent(str) {
2099
- try {
2100
- return decodeURIComponent(str.replace(/\+/g, " "));
2101
- } catch (e) {
2102
- return str;
2103
- }
2104
- }
2105
- },
2106
- {
2107
- key: "append",
2108
- value: function append(name, value) {
2109
- var values = this.params.get(name) || [];
2110
- values.push(String(value));
2111
- this.params.set(name, values);
2112
- }
2113
- },
2114
- {
2115
- key: "delete",
2116
- value: function _delete(name) {
2117
- this.params.delete(name);
2118
- }
2119
- },
2120
- {
2121
- key: "get",
2122
- value: function get(name) {
2123
- var values = this.params.get(name);
2124
- return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
2125
- }
2126
- },
2127
- {
2128
- key: "getAll",
2129
- value: function getAll(name) {
2130
- return this.params.get(name) || [];
2131
- }
2132
- },
2133
- {
2134
- key: "has",
2135
- value: function has(name) {
2136
- return this.params.has(name);
2137
- }
2138
- },
2139
- {
2140
- key: "set",
2141
- value: function set(name, value) {
2142
- this.params.set(name, [
2143
- String(value)
2144
- ]);
2145
- }
2146
- },
2147
- {
2148
- key: "forEach",
2149
- value: function forEach(callback) {
2150
- var _this = this;
2151
- this.params.forEach(function(values, key) {
2152
- values.forEach(function(value) {
2153
- callback(value, key, _this);
2154
- });
2155
- });
2156
- }
2157
- },
2158
- {
2159
- key: "toString",
2160
- value: function toString() {
2161
- var parts = [];
2162
- this.params.forEach(function(values, key) {
2163
- values.forEach(function(value) {
2164
- parts.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)));
2165
- });
2166
- });
2167
- return parts.join("&");
2168
- }
2169
- }
2170
- ]);
2171
- return URLSearchParamsPolyfill;
2172
- }();
2173
- window.URLSearchParams = URLSearchParamsPolyfill;
2174
- }
2175
- function polyfillTextEncoder() {
2176
- if (typeof TextEncoder !== "undefined") {
2177
- return;
2178
- }
2179
- var TextEncoderPolyfill = /*#__PURE__*/ function() {
2180
- function TextEncoderPolyfill() {
2181
- _class_call_check(this, TextEncoderPolyfill);
2182
- this.encoding = "utf-8";
2183
- }
2184
- _create_class(TextEncoderPolyfill, [
2185
- {
2186
- key: "encode",
2187
- value: function encode(str) {
2188
- var utf8 = [];
2189
- for(var i = 0; i < str.length; i++){
2190
- var charcode = str.charCodeAt(i);
2191
- if (charcode < 128) {
2192
- utf8.push(charcode);
2193
- } else if (charcode < 2048) {
2194
- utf8.push(192 | charcode >> 6, 128 | charcode & 63);
2195
- } else if (charcode < 55296 || charcode >= 57344) {
2196
- utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2197
- } else {
2198
- i++;
2199
- charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
2200
- utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2201
- }
2202
- }
2203
- return new Uint8Array(utf8);
2204
- }
2205
- }
2206
- ]);
2207
- return TextEncoderPolyfill;
2208
- }();
2209
- window.TextEncoder = TextEncoderPolyfill;
2210
- }
2211
- function polyfillPromiseFinally() {
2212
- if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
2213
- Promise.prototype.finally = function(callback) {
2214
- var constructor = this.constructor;
2215
- return this.then(function(value) {
2216
- return constructor.resolve(callback()).then(function() {
2217
- return value;
2218
- });
2219
- }, function(reason) {
2220
- return constructor.resolve(callback()).then(function() {
2221
- throw reason;
2222
- });
2223
- });
2224
- };
2225
- }
2226
- }
2227
- function polyfillObjectAssign() {
2228
- if (typeof Object.assign !== "function") {
2229
- Object.assign = function(target) {
2230
- for(var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
2231
- sources[_key - 1] = arguments[_key];
2232
- }
2233
- if (target == null) {
2234
- throw new TypeError("Cannot convert undefined or null to object");
2235
- }
2236
- var to = Object(target);
2237
- for(var i = 0; i < sources.length; i++){
2238
- var nextSource = sources[i];
2239
- if (nextSource != null) {
2240
- for(var nextKey in nextSource){
2241
- if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
2242
- to[nextKey] = nextSource[nextKey];
2243
- }
2244
- }
2245
- }
2246
- }
2247
- return to;
2248
- };
2249
- }
2250
- }
2251
- function polyfillArrayFrom() {
2252
- if (!Array.from) {
2253
- Array.from = function(arrayLike, mapFn, thisArg) {
2254
- var items = Object(arrayLike);
2255
- if (arrayLike == null) {
2256
- throw new TypeError("Array.from requires an array-like object");
2257
- }
2258
- var len = items.length >>> 0;
2259
- var result = new Array(len);
2260
- for(var i = 0; i < len; i++){
2261
- if (mapFn) {
2262
- result[i] = mapFn.call(thisArg, items[i], i);
2263
- } else {
2264
- result[i] = items[i];
2265
- }
2266
- }
2267
- return result;
2268
- };
2269
- }
2270
- }
2271
- function polyfillStringStartsWith() {
2272
- if (!String.prototype.startsWith) {
2273
- String.prototype.startsWith = function(search, pos) {
2274
- pos = !pos || pos < 0 ? 0 : +pos;
2275
- return this.substring(pos, pos + search.length) === search;
2276
- };
2277
- }
2278
- }
2279
- function polyfillStringEndsWith() {
2280
- if (!String.prototype.endsWith) {
2281
- String.prototype.endsWith = function(search, length) {
2282
- if (length === void 0 || length > this.length) {
2283
- length = this.length;
2284
- }
2285
- return this.substring(length - search.length, length) === search;
2286
- };
2287
- }
2288
- }
2289
- function polyfillStringIncludes() {
2290
- if (!String.prototype.includes) {
2291
- String.prototype.includes = function(search, start) {
2292
- if (typeof start !== "number") {
2293
- start = 0;
2294
- }
2295
- if (start + search.length > this.length) {
2296
- return false;
2297
- }
2298
- return this.indexOf(search, start) !== -1;
2299
- };
2300
- }
2301
- }
2302
- function initializePolyfills() {
2303
- polyfillObjectAssign();
2304
- polyfillArrayFrom();
2305
- polyfillStringStartsWith();
2306
- polyfillStringEndsWith();
2307
- polyfillStringIncludes();
2308
- polyfillURLSearchParams();
2309
- polyfillTextEncoder();
2310
- polyfillPromiseFinally();
2311
- }
2312
- // src/utils/vastEnvironmentSignals.ts
2313
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2314
- var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2315
- var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2316
- var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2317
- var AIRY_APP_NAME = "AiryTV Movies & TV";
2318
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2319
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2320
- var LG_TEST_APP_ID = "com.hulu.plus";
2321
- var LG_TEST_APP_NAME = "Hulu";
2322
- var LG_TEST_CONTENT_URL = "https://www.hulu.com/live-tv";
2323
- var _lgTestDeviceId;
2324
- function getLgTestDeviceId() {
2325
- if (!_lgTestDeviceId) _lgTestDeviceId = createUuid();
2326
- return _lgTestDeviceId;
2327
- }
2328
- function isLgWebOS() {
2329
- if (typeof navigator === "undefined") return false;
2330
- return /Web0S|webOS|LG Browser|LGSTB|LGE/i.test(navigator.userAgent);
2331
- }
2332
- function getDefaultAppId() {
2333
- if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2334
- var ua = navigator.userAgent;
2335
- if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2336
- if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2337
- if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2338
- return AIRY_ANDROID_APP_ID;
2339
- }
2340
- var DEVICE_ID_STORAGE_KEYS = [
2341
- "rdid",
2342
- "ifa",
2343
- "advertisingId",
2344
- "advertising_id",
2345
- "deviceAdvertisingId",
2346
- "aaid",
2347
- "adid",
2348
- "rida",
2349
- "tifa",
2350
- "lgudid"
2351
- ];
2352
- var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2353
- "aaid",
2354
- "adid"
2355
- ]);
2356
- function resolveVastEnvironmentSignals(isCtv) {
2357
- var _ref, _bridgeSignals_limitAdTracking;
2358
- var bridgeSignals = readNativeBridgeSignals();
2359
- var lg = isCtv && isLgWebOS();
2360
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId() || (lg ? getLgTestDeviceId() : void 0);
2361
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType() || (lg ? "lgudid" : void 0);
2362
- 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;
2363
- if (isCtv) {
2364
- return _object_spread_props(_object_spread({
2365
- isCtv: true,
2366
- contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || (lg ? LG_TEST_CONTENT_URL : AIRY_DEFAULT_CONTENT_URL),
2367
- appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || (lg ? LG_TEST_APP_ID : getDefaultAppId()),
2368
- appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || (lg ? LG_TEST_APP_NAME : AIRY_APP_NAME),
2369
- sessionId: getOrCreateCtvSessionId()
2370
- }, deviceId ? {
2371
- deviceId: deviceId
2372
- } : {}, deviceIdType ? {
2373
- deviceIdType: deviceIdType
2374
- } : {}, limitAdTracking != null ? {
2375
- limitAdTracking: limitAdTracking
2376
- } : {}), {
2377
- deviceTypeHint: 5
2378
- });
2379
- }
2380
- return _object_spread({
2381
- isCtv: false
2382
- }, deviceId ? {
2383
- deviceId: deviceId
2384
- } : {}, deviceIdType ? {
2385
- deviceIdType: deviceIdType
2386
- } : {}, limitAdTracking != null ? {
2387
- limitAdTracking: limitAdTracking
2388
- } : {});
2389
- }
2390
- function inferDeviceIdType() {
2391
- if (typeof navigator === "undefined") {
2392
- return void 0;
2393
- }
2394
- var ua = navigator.userAgent;
2395
- if (/Roku/i.test(ua)) return "rida";
2396
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
2397
- if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2398
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2399
- if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2400
- if (/Android|Google TV/i.test(ua)) return "aaid";
2401
- if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2402
- return void 0;
2403
- }
2404
- function isEquivalentDeviceIdType(tagType, runtimeType) {
2405
- if (!tagType || !runtimeType) return false;
2406
- var tag = tagType.toLowerCase();
2407
- var runtime = runtimeType.toLowerCase();
2408
- if (tag === runtime) return true;
2409
- return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2410
- }
2411
- function getOrCreateCtvSessionId() {
2412
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2413
- if (existing) {
2414
- return existing;
2415
- }
2416
- var sessionId = createUuid();
2417
- try {
2418
- var _window_localStorage;
2419
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2420
- } catch (unused) {}
2421
- return sessionId;
2462
+ console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
2463
+ return [
2464
+ 3,
2465
+ 4
2466
+ ];
2467
+ case 4:
2468
+ return [
2469
+ 2
2470
+ ];
2471
+ }
2472
+ });
2473
+ }).apply(this, arguments);
2422
2474
  }
2423
- function createUuid() {
2424
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2425
- return crypto.randomUUID();
2426
- }
2427
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2428
- var value = Math.floor(Math.random() * 16);
2429
- var nibble = char === "x" ? value : value & 3 | 8;
2430
- return nibble.toString(16);
2431
- });
2475
+ function sendHeartbeat(_0) {
2476
+ return _async_to_generator(function(licenseKey) {
2477
+ var context, flags, heartbeatData, error;
2478
+ var _arguments = arguments;
2479
+ return _ts_generator(this, function(_state) {
2480
+ switch(_state.label){
2481
+ case 0:
2482
+ context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
2483
+ if (!canPublish(licenseKey)) return [
2484
+ 2
2485
+ ];
2486
+ _state.label = 1;
2487
+ case 1:
2488
+ _state.trys.push([
2489
+ 1,
2490
+ 3,
2491
+ ,
2492
+ 4
2493
+ ]);
2494
+ return [
2495
+ 4,
2496
+ buildPlayerMetricEvent(context, flags)
2497
+ ];
2498
+ case 2:
2499
+ heartbeatData = _state.sent();
2500
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
2501
+ return [
2502
+ 3,
2503
+ 4
2504
+ ];
2505
+ case 3:
2506
+ error = _state.sent();
2507
+ console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
2508
+ return [
2509
+ 3,
2510
+ 4
2511
+ ];
2512
+ case 4:
2513
+ return [
2514
+ 2
2515
+ ];
2516
+ }
2517
+ });
2518
+ }).apply(this, arguments);
2432
2519
  }
2433
- function readNativeBridgeSignals() {
2434
- if (typeof window === "undefined") {
2435
- return {};
2520
+ // src/utils/polyfills.ts
2521
+ function polyfillURLSearchParams() {
2522
+ if (typeof URLSearchParams !== "undefined") {
2523
+ return;
2436
2524
  }
2437
- var candidates = [
2438
- window.__STORMCLOUD_CTV_AD_INFO__,
2439
- window.__STORMCLOUD_CTV__,
2440
- window.stormcloudCtv,
2441
- window.AiryTV,
2442
- window.Android,
2443
- window.webOS,
2444
- window.tizen,
2445
- window.amazon
2446
- ].filter(Boolean);
2447
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2448
- try {
2449
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2450
- var source = _step.value;
2451
- var contentUrl = readBridgeValue(source, [
2452
- "contentUrl",
2453
- "url",
2454
- "videoUrl",
2455
- "canonicalUrl"
2456
- ]) || void 0;
2457
- var appId = readBridgeValue(source, [
2458
- "appId",
2459
- "msid",
2460
- "applicationId",
2461
- "packageName"
2462
- ]) || void 0;
2463
- var appName = readBridgeValue(source, [
2464
- "appName",
2465
- "an",
2466
- "applicationName"
2467
- ]) || void 0;
2468
- var deviceId = readBridgeValue(source, [
2469
- "rdid",
2470
- "ifa",
2471
- "advertisingId",
2472
- "adId",
2473
- "deviceId",
2474
- "lgudid",
2475
- "LGUDID",
2476
- "tifa",
2477
- "rida",
2478
- "afai",
2479
- "aaid"
2480
- ]) || void 0;
2481
- if (!contentUrl && !deviceId && !appId && !appName) continue;
2482
- var deviceIdType = readBridgeValue(source, [
2483
- "idtype",
2484
- "deviceIdType",
2485
- "advertisingIdType",
2486
- "idType"
2487
- ]) || inferDeviceIdType();
2488
- var limitAdTracking = readBridgeBoolean(source, [
2489
- "is_lat",
2490
- "limitAdTracking",
2491
- "limitedAdTracking",
2492
- "lat"
2493
- ]);
2494
- return _object_spread({}, contentUrl ? {
2495
- contentUrl: contentUrl
2496
- } : {}, appId ? {
2497
- appId: appId
2498
- } : {}, appName ? {
2499
- appName: appName
2500
- } : {}, deviceId ? {
2501
- deviceId: deviceId
2502
- } : {}, deviceId && deviceIdType ? {
2503
- deviceIdType: deviceIdType
2504
- } : {}, deviceId && limitAdTracking != null ? {
2505
- limitAdTracking: limitAdTracking
2506
- } : {});
2507
- }
2508
- } catch (err) {
2509
- _didIteratorError = true;
2510
- _iteratorError = err;
2511
- } finally{
2512
- try {
2513
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2514
- _iterator.return();
2515
- }
2516
- } finally{
2517
- if (_didIteratorError) {
2518
- throw _iteratorError;
2525
+ var URLSearchParamsPolyfill = /*#__PURE__*/ function() {
2526
+ function URLSearchParamsPolyfill(init) {
2527
+ var _this = this;
2528
+ _class_call_check(this, URLSearchParamsPolyfill);
2529
+ this.params = /* @__PURE__ */ new Map();
2530
+ if (typeof init === "string") {
2531
+ this.parseQueryString(init);
2532
+ } else if (_instanceof(init, URLSearchParamsPolyfill)) {
2533
+ init.forEach(function(value, key) {
2534
+ _this.append(key, value);
2535
+ });
2519
2536
  }
2520
2537
  }
2521
- }
2522
- return {};
2523
- }
2524
- function readBridgeValue(source, keys) {
2525
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2526
- try {
2527
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2528
- var key = _step.value;
2529
- var value = source === null || source === void 0 ? void 0 : source[key];
2530
- if (typeof value === "string" && value) {
2531
- return value;
2532
- }
2533
- if (typeof value === "function") {
2534
- try {
2535
- var result = value.call(source);
2536
- if (typeof result === "string" && result) {
2537
- return result;
2538
+ _create_class(URLSearchParamsPolyfill, [
2539
+ {
2540
+ key: "parseQueryString",
2541
+ value: function parseQueryString(query) {
2542
+ var _this = this;
2543
+ var cleanQuery = query.startsWith("?") ? query.slice(1) : query;
2544
+ if (!cleanQuery) return;
2545
+ cleanQuery.split("&").forEach(function(param) {
2546
+ var _param_split = _sliced_to_array(param.split("="), 2), key = _param_split[0], value = _param_split[1];
2547
+ if (key) {
2548
+ var decodedKey = _this.safeDecodeURIComponent(key);
2549
+ var decodedValue = value ? _this.safeDecodeURIComponent(value) : "";
2550
+ _this.append(decodedKey, decodedValue);
2551
+ }
2552
+ });
2553
+ }
2554
+ },
2555
+ {
2556
+ key: "safeDecodeURIComponent",
2557
+ value: function safeDecodeURIComponent(str) {
2558
+ try {
2559
+ return decodeURIComponent(str.replace(/\+/g, " "));
2560
+ } catch (e) {
2561
+ return str;
2538
2562
  }
2539
- } catch (unused) {}
2563
+ }
2564
+ },
2565
+ {
2566
+ key: "append",
2567
+ value: function append(name, value) {
2568
+ var values = this.params.get(name) || [];
2569
+ values.push(String(value));
2570
+ this.params.set(name, values);
2571
+ }
2572
+ },
2573
+ {
2574
+ key: "delete",
2575
+ value: function _delete(name) {
2576
+ this.params.delete(name);
2577
+ }
2578
+ },
2579
+ {
2580
+ key: "get",
2581
+ value: function get(name) {
2582
+ var values = this.params.get(name);
2583
+ return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
2584
+ }
2585
+ },
2586
+ {
2587
+ key: "getAll",
2588
+ value: function getAll(name) {
2589
+ return this.params.get(name) || [];
2590
+ }
2591
+ },
2592
+ {
2593
+ key: "has",
2594
+ value: function has(name) {
2595
+ return this.params.has(name);
2596
+ }
2597
+ },
2598
+ {
2599
+ key: "set",
2600
+ value: function set(name, value) {
2601
+ this.params.set(name, [
2602
+ String(value)
2603
+ ]);
2604
+ }
2605
+ },
2606
+ {
2607
+ key: "forEach",
2608
+ value: function forEach(callback) {
2609
+ var _this = this;
2610
+ this.params.forEach(function(values, key) {
2611
+ values.forEach(function(value) {
2612
+ callback(value, key, _this);
2613
+ });
2614
+ });
2615
+ }
2616
+ },
2617
+ {
2618
+ key: "toString",
2619
+ value: function toString() {
2620
+ var parts = [];
2621
+ this.params.forEach(function(values, key) {
2622
+ values.forEach(function(value) {
2623
+ parts.push("".concat(encodeURIComponent(key), "=").concat(encodeURIComponent(value)));
2624
+ });
2625
+ });
2626
+ return parts.join("&");
2627
+ }
2540
2628
  }
2629
+ ]);
2630
+ return URLSearchParamsPolyfill;
2631
+ }();
2632
+ window.URLSearchParams = URLSearchParamsPolyfill;
2633
+ }
2634
+ function polyfillTextEncoder() {
2635
+ if (typeof TextEncoder !== "undefined") {
2636
+ return;
2637
+ }
2638
+ var TextEncoderPolyfill = /*#__PURE__*/ function() {
2639
+ function TextEncoderPolyfill() {
2640
+ _class_call_check(this, TextEncoderPolyfill);
2641
+ this.encoding = "utf-8";
2541
2642
  }
2542
- } catch (err) {
2543
- _didIteratorError = true;
2544
- _iteratorError = err;
2545
- } finally{
2546
- try {
2547
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2548
- _iterator.return();
2549
- }
2550
- } finally{
2551
- if (_didIteratorError) {
2552
- throw _iteratorError;
2643
+ _create_class(TextEncoderPolyfill, [
2644
+ {
2645
+ key: "encode",
2646
+ value: function encode(str) {
2647
+ var utf8 = [];
2648
+ for(var i = 0; i < str.length; i++){
2649
+ var charcode = str.charCodeAt(i);
2650
+ if (charcode < 128) {
2651
+ utf8.push(charcode);
2652
+ } else if (charcode < 2048) {
2653
+ utf8.push(192 | charcode >> 6, 128 | charcode & 63);
2654
+ } else if (charcode < 55296 || charcode >= 57344) {
2655
+ utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2656
+ } else {
2657
+ i++;
2658
+ charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
2659
+ utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63);
2660
+ }
2661
+ }
2662
+ return new Uint8Array(utf8);
2663
+ }
2553
2664
  }
2554
- }
2665
+ ]);
2666
+ return TextEncoderPolyfill;
2667
+ }();
2668
+ window.TextEncoder = TextEncoderPolyfill;
2669
+ }
2670
+ function polyfillPromiseFinally() {
2671
+ if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
2672
+ Promise.prototype.finally = function(callback) {
2673
+ var constructor = this.constructor;
2674
+ return this.then(function(value) {
2675
+ return constructor.resolve(callback()).then(function() {
2676
+ return value;
2677
+ });
2678
+ }, function(reason) {
2679
+ return constructor.resolve(callback()).then(function() {
2680
+ throw reason;
2681
+ });
2682
+ });
2683
+ };
2555
2684
  }
2556
- return void 0;
2557
2685
  }
2558
- function readBridgeBoolean(source, keys) {
2559
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2560
- try {
2561
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2562
- var key = _step.value;
2563
- var value = source === null || source === void 0 ? void 0 : source[key];
2564
- var normalized = normalizeBoolean(value);
2565
- if (normalized != null) {
2566
- return normalized;
2567
- }
2568
- if (typeof value === "function") {
2569
- try {
2570
- var result = normalizeBoolean(value.call(source));
2571
- if (result != null) {
2572
- return result;
2573
- }
2574
- } catch (unused) {}
2686
+ function polyfillObjectAssign() {
2687
+ if (typeof Object.assign !== "function") {
2688
+ Object.assign = function(target) {
2689
+ for(var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
2690
+ sources[_key - 1] = arguments[_key];
2575
2691
  }
2576
- }
2577
- } catch (err) {
2578
- _didIteratorError = true;
2579
- _iteratorError = err;
2580
- } finally{
2581
- try {
2582
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2583
- _iterator.return();
2692
+ if (target == null) {
2693
+ throw new TypeError("Cannot convert undefined or null to object");
2584
2694
  }
2585
- } finally{
2586
- if (_didIteratorError) {
2587
- throw _iteratorError;
2695
+ var to = Object(target);
2696
+ for(var i = 0; i < sources.length; i++){
2697
+ var nextSource = sources[i];
2698
+ if (nextSource != null) {
2699
+ for(var nextKey in nextSource){
2700
+ if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
2701
+ to[nextKey] = nextSource[nextKey];
2702
+ }
2703
+ }
2704
+ }
2588
2705
  }
2589
- }
2706
+ return to;
2707
+ };
2590
2708
  }
2591
- return void 0;
2592
2709
  }
2593
- function readStoredDeviceId() {
2594
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2595
- try {
2596
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2597
- var key = _step.value;
2598
- var value = readStoredString(key);
2599
- if (value) {
2600
- return value;
2601
- }
2602
- }
2603
- } catch (err) {
2604
- _didIteratorError = true;
2605
- _iteratorError = err;
2606
- } finally{
2607
- try {
2608
- if (!_iteratorNormalCompletion && _iterator.return != null) {
2609
- _iterator.return();
2710
+ function polyfillArrayFrom() {
2711
+ if (!Array.from) {
2712
+ Array.from = function(arrayLike, mapFn, thisArg) {
2713
+ var items = Object(arrayLike);
2714
+ if (arrayLike == null) {
2715
+ throw new TypeError("Array.from requires an array-like object");
2610
2716
  }
2611
- } finally{
2612
- if (_didIteratorError) {
2613
- throw _iteratorError;
2717
+ var len = items.length >>> 0;
2718
+ var result = new Array(len);
2719
+ for(var i = 0; i < len; i++){
2720
+ if (mapFn) {
2721
+ result[i] = mapFn.call(thisArg, items[i], i);
2722
+ } else {
2723
+ result[i] = items[i];
2724
+ }
2614
2725
  }
2615
- }
2726
+ return result;
2727
+ };
2616
2728
  }
2617
- return void 0;
2618
2729
  }
2619
- function readStoredString(key) {
2620
- if (typeof window === "undefined") {
2621
- return void 0;
2622
- }
2623
- try {
2624
- var _window_localStorage;
2625
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2626
- return value || void 0;
2627
- } catch (unused) {
2628
- return void 0;
2730
+ function polyfillStringStartsWith() {
2731
+ if (!String.prototype.startsWith) {
2732
+ String.prototype.startsWith = function(search, pos) {
2733
+ pos = !pos || pos < 0 ? 0 : +pos;
2734
+ return this.substring(pos, pos + search.length) === search;
2735
+ };
2629
2736
  }
2630
2737
  }
2631
- function readStoredLimitAdTracking() {
2632
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2633
- }
2634
- function normalizeBoolean(value) {
2635
- if (typeof value === "boolean") {
2636
- return value;
2637
- }
2638
- if (typeof value === "number") {
2639
- return value === 1;
2738
+ function polyfillStringEndsWith() {
2739
+ if (!String.prototype.endsWith) {
2740
+ String.prototype.endsWith = function(search, length) {
2741
+ if (length === void 0 || length > this.length) {
2742
+ length = this.length;
2743
+ }
2744
+ return this.substring(length - search.length, length) === search;
2745
+ };
2640
2746
  }
2641
- if (typeof value === "string") {
2642
- var normalized = value.toLowerCase();
2643
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
2644
- return true;
2645
- }
2646
- if (normalized === "0" || normalized === "false" || normalized === "no") {
2647
- return false;
2648
- }
2747
+ }
2748
+ function polyfillStringIncludes() {
2749
+ if (!String.prototype.includes) {
2750
+ String.prototype.includes = function(search, start) {
2751
+ if (typeof start !== "number") {
2752
+ start = 0;
2753
+ }
2754
+ if (start + search.length > this.length) {
2755
+ return false;
2756
+ }
2757
+ return this.indexOf(search, start) !== -1;
2758
+ };
2649
2759
  }
2650
- return void 0;
2760
+ }
2761
+ function initializePolyfills() {
2762
+ polyfillObjectAssign();
2763
+ polyfillArrayFrom();
2764
+ polyfillStringStartsWith();
2765
+ polyfillStringEndsWith();
2766
+ polyfillStringIncludes();
2767
+ polyfillURLSearchParams();
2768
+ polyfillTextEncoder();
2769
+ polyfillPromiseFinally();
2651
2770
  }
2652
2771
  // src/utils/vastMacros.ts
2653
2772
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
@@ -2770,7 +2889,7 @@ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2770
2889
  }
2771
2890
  }
2772
2891
  ];
2773
- function isMacroPlaceholder(value) {
2892
+ function isMacroPlaceholder2(value) {
2774
2893
  if (value == null) return true;
2775
2894
  var trimmed = value.trim();
2776
2895
  if (!trimmed) return true;
@@ -2829,11 +2948,11 @@ function applyDeviceIdentityParams(params, ctx) {
2829
2948
  if (runtimeId) {
2830
2949
  params.set("rdid", runtimeId);
2831
2950
  params.set("idtype", runtimeType || tagType || "aaid");
2832
- params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2951
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder2(tagLat) ? "0" : tagLat);
2833
2952
  return;
2834
2953
  }
2835
- var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2836
- var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2954
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder2(tagRdid));
2955
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder2(tagType));
2837
2956
  if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2838
2957
  params.delete("rdid");
2839
2958
  params.delete("idtype");
@@ -2841,10 +2960,10 @@ function applyDeviceIdentityParams(params, ctx) {
2841
2960
  return;
2842
2961
  }
2843
2962
  if (tagRdidValid) {
2844
- if (isMacroPlaceholder(tagType) && runtimeType) {
2963
+ if (isMacroPlaceholder2(tagType) && runtimeType) {
2845
2964
  params.set("idtype", runtimeType);
2846
2965
  }
2847
- if (isMacroPlaceholder(tagLat)) {
2966
+ if (isMacroPlaceholder2(tagLat)) {
2848
2967
  params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2849
2968
  }
2850
2969
  return;
@@ -3030,7 +3149,7 @@ function applyVastMacros(baseUrl, ctx) {
3030
3149
  }
3031
3150
  var staleKeys = [];
3032
3151
  params.forEach(function(value, key) {
3033
- if (isMacroPlaceholder(value)) {
3152
+ if (isMacroPlaceholder2(value)) {
3034
3153
  staleKeys.push(key);
3035
3154
  }
3036
3155
  });
@@ -5979,7 +6098,7 @@ var HlsEngine = /*#__PURE__*/ function() {
5979
6098
  key: "setupNativeHls",
5980
6099
  value: function setupNativeHls() {
5981
6100
  return _async_to_generator(function() {
5982
- var _this_config_isLiveStream, _this_config_lowLatencyMode, _this_video_play;
6101
+ var _this_config_isLiveStream, _this_config_lowLatencyMode, adBehavior, _this_video_play;
5983
6102
  return _ts_generator(this, function(_state) {
5984
6103
  switch(_state.label){
5985
6104
  case 0:
@@ -5988,10 +6107,11 @@ var HlsEngine = /*#__PURE__*/ function() {
5988
6107
  this.video.src = this.config.src;
5989
6108
  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;
5990
6109
  if (this.debug) {
5991
- console.log("[StormcloudVideoPlayer] Using native HLS playback - VOD mode:", {
6110
+ adBehavior = this.isLiveStream ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
6111
+ console.log("[StormcloudVideoPlayer] Using native HLS playback:", {
5992
6112
  isLive: this.isLiveStream,
5993
6113
  allowNativeHls: this.config.allowNativeHls,
5994
- adBehavior: "vod (main video pauses during ads)"
6114
+ adBehavior: adBehavior
5995
6115
  });
5996
6116
  }
5997
6117
  if (!this.config.autoplay) return [
@@ -6400,6 +6520,14 @@ var HlsEngine = /*#__PURE__*/ function() {
6400
6520
  });
6401
6521
  }
6402
6522
  },
6523
+ {
6524
+ key: "getLiveSyncPosition",
6525
+ value: function getLiveSyncPosition() {
6526
+ var _this_hls;
6527
+ var pos = (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.liveSyncPosition;
6528
+ return typeof pos === "number" && Number.isFinite(pos) ? pos : void 0;
6529
+ }
6530
+ },
6403
6531
  {
6404
6532
  key: "destroy",
6405
6533
  value: function destroy() {
@@ -7974,6 +8102,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7974
8102
  this.host.video.volume = restoredVolume;
7975
8103
  }
7976
8104
  if (this.host.shouldContinueLiveStreamDuringAds()) {
8105
+ var liveSyncPos = this.host.getLiveSyncPosition();
8106
+ if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8107
+ if (this.debug) {
8108
+ console.log("[StormcloudVideoPlayer] Live break end — snapping to live edge: ".concat(this.host.video.currentTime.toFixed(2), "s → ").concat(liveSyncPos.toFixed(2), "s"));
8109
+ }
8110
+ this.host.video.currentTime = liveSyncPos;
8111
+ }
7977
8112
  if (this.host.video.paused) {
7978
8113
  var _this_host_video_play;
7979
8114
  if (this.debug) console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
@@ -8116,6 +8251,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8116
8251
  shouldContinueLiveStreamDuringAds: function shouldContinueLiveStreamDuringAds() {
8117
8252
  return _this.shouldContinueLiveStreamDuringAds();
8118
8253
  },
8254
+ getLiveSyncPosition: function getLiveSyncPosition() {
8255
+ return _this.hlsEngine.getLiveSyncPosition();
8256
+ },
8119
8257
  generateVastUrls: function generateVastUrls(base, count) {
8120
8258
  return _this.generateVastUrls(base, count);
8121
8259
  }
@@ -8157,7 +8295,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8157
8295
  // ───────────────────────────────────────────────────────────────
8158
8296
  function load() {
8159
8297
  return _async_to_generator(function() {
8160
- var _this, _this_config_lowLatencyMode, error;
8298
+ var _this, _this_config_lowLatencyMode, error, continueLiveStreamDuringAds;
8161
8299
  return _ts_generator(this, function(_state) {
8162
8300
  switch(_state.label){
8163
8301
  case 0:
@@ -8211,15 +8349,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8211
8349
  3,
8212
8350
  6
8213
8351
  ];
8214
- this.adPlayer.destroy();
8215
- this.adPlayer = this.createAdPlayer(false);
8216
- this.adPlayer.initialize();
8217
8352
  return [
8218
8353
  4,
8219
8354
  this.hlsEngine.setupNativeHls()
8220
8355
  ];
8221
8356
  case 5:
8222
8357
  _state.sent();
8358
+ continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
8359
+ if (this.debug) {
8360
+ console.log("[StormcloudVideoPlayer] Native HLS ad behavior:", {
8361
+ isLive: this.hlsEngine.isLiveStream,
8362
+ continueLiveStreamDuringAds: continueLiveStreamDuringAds
8363
+ });
8364
+ }
8365
+ this.adPlayer.destroy();
8366
+ this.adPlayer = this.createAdPlayer(continueLiveStreamDuringAds);
8367
+ this.adPlayer.initialize();
8223
8368
  return [
8224
8369
  2
8225
8370
  ];
@@ -8327,9 +8472,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8327
8472
  {
8328
8473
  key: "shouldContinueLiveStreamDuringAds",
8329
8474
  value: function shouldContinueLiveStreamDuringAds() {
8330
- if (this.config.allowNativeHls) return false;
8331
- if (!this.hlsEngine.isLiveStream) return false;
8332
- return true;
8475
+ if (this.hlsEngine.isLiveStream) {
8476
+ return true;
8477
+ }
8478
+ var duration = this.video.duration;
8479
+ if (!Number.isFinite(duration) || duration === Infinity) {
8480
+ return true;
8481
+ }
8482
+ return false;
8333
8483
  }
8334
8484
  },
8335
8485
  {
@@ -8627,9 +8777,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8627
8777
  this.adBreak.showAds = true;
8628
8778
  this.adBreak.inAdBreak = true;
8629
8779
  this.timing.currentAdBreakStartWallClockMs = Date.now();
8630
- if (!this.video.paused) {
8631
- this.video.pause();
8632
- }
8633
8780
  _state.label = 1;
8634
8781
  case 1:
8635
8782
  _state.trys.push([
@@ -9003,7 +9150,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9003
9150
  setShowSpeedMenu(false);
9004
9151
  };
9005
9152
  var isHlsStream = (src === null || src === void 0 ? void 0 : src.toLowerCase().includes(".m3u8")) || (src === null || src === void 0 ? void 0 : src.toLowerCase().includes("/hls/"));
9006
- var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls || isLiveStream === false : true);
9153
+ var isLiveUiMode = isLiveStream === true;
9154
+ var shouldShowEnhancedControls = showCustomControls && (isHlsStream ? !isLiveUiMode : true);
9007
9155
  var criticalPropsKey = (0, import_react.useMemo)(function() {
9008
9156
  return CRITICAL_PROPS.map(function(prop) {
9009
9157
  return "".concat(prop, ":").concat(props[prop]);