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