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