stormcloud-video-player 0.6.11 → 0.6.13

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.
@@ -159,9 +159,11 @@ function _ts_generator(thisArg, body) {
159
159
  };
160
160
  }
161
161
  }
162
+ var __create = Object.create;
162
163
  var __defProp = Object.defineProperty;
163
164
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
164
165
  var __getOwnPropNames = Object.getOwnPropertyNames;
166
+ var __getProtoOf = Object.getPrototypeOf;
165
167
  var __hasOwnProp = Object.prototype.hasOwnProperty;
166
168
  var __export = function __export(target, all) {
167
169
  for(var name in all)__defProp(target, name, {
@@ -200,6 +202,16 @@ var __copyProps = function __copyProps(to, from, except, desc) {
200
202
  }
201
203
  return to;
202
204
  };
205
+ var __toESM = function __toESM(mod, isNodeMode, target) {
206
+ return target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(// If the importer is in node compatibility mode or this is not an ESM
207
+ // file that has been converted to a CommonJS file using a Babel-
208
+ // compatible transform (i.e. "__esModule" has not been set), then set
209
+ // "default" to the CommonJS "module.exports" for node compatibility.
210
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
211
+ value: mod,
212
+ enumerable: true
213
+ }) : target, mod);
214
+ };
203
215
  var __toCommonJS = function __toCommonJS(mod) {
204
216
  return __copyProps(__defProp({}, "__esModule", {
205
217
  value: true
@@ -231,6 +243,100 @@ __export(tracking_exports, {
231
243
  }
232
244
  });
233
245
  module.exports = __toCommonJS(tracking_exports);
246
+ // src/utils/mqttConfig.ts
247
+ var DEFAULT_MQTT_CONFIG = {
248
+ enabled: true,
249
+ brokerAddress: "vecbae77.ala.us-east-1.emqxsl.com",
250
+ brokerPort: 8883,
251
+ wsPort: 8084,
252
+ username: "for-sonifi",
253
+ password: "sonifi-mqtt",
254
+ topicPrefix: "adstorm/players",
255
+ qos: 1
256
+ };
257
+ var mqttConfig = _object_spread({}, DEFAULT_MQTT_CONFIG);
258
+ function isMQTTEnabled() {
259
+ return mqttConfig.enabled;
260
+ }
261
+ function buildMQTTBrokerUrl() {
262
+ if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;
263
+ return "wss://".concat(mqttConfig.brokerAddress, ":").concat(mqttConfig.wsPort, "/mqtt");
264
+ }
265
+ function buildPlayerTopic(licenseKey, channel) {
266
+ return "".concat(mqttConfig.topicPrefix, "/").concat(licenseKey, "/").concat(channel);
267
+ }
268
+ // src/utils/mqttClient.ts
269
+ var import_mqtt = __toESM(require("mqtt"), 1);
270
+ var LOG = "[StormcloudVideoPlayer][MQTT]";
271
+ var client = null;
272
+ var status = "disconnected";
273
+ function initMQTTClient() {
274
+ if (client || !isMQTTEnabled()) return;
275
+ var url = buildMQTTBrokerUrl();
276
+ status = "connecting";
277
+ var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
278
+ try {
279
+ client = import_mqtt.default.connect(url, {
280
+ clientId: clientId,
281
+ username: mqttConfig.username,
282
+ password: mqttConfig.password,
283
+ keepalive: 60,
284
+ clean: true,
285
+ reconnectPeriod: 5e3,
286
+ connectTimeout: 1e4,
287
+ queueQoSZero: false
288
+ });
289
+ } catch (err) {
290
+ status = "error";
291
+ console.warn("".concat(LOG, " connect() threw:"), err);
292
+ return;
293
+ }
294
+ client.on("connect", function() {
295
+ status = "connected";
296
+ console.info("".concat(LOG, " connected to ").concat(url));
297
+ });
298
+ client.on("reconnect", function() {
299
+ status = "connecting";
300
+ console.info("".concat(LOG, " reconnecting…"));
301
+ });
302
+ client.on("offline", function() {
303
+ status = "disconnected";
304
+ console.warn("".concat(LOG, " offline"));
305
+ });
306
+ client.on("error", function(err) {
307
+ status = "error";
308
+ console.warn("".concat(LOG, " error:"), err.message);
309
+ });
310
+ client.on("close", function() {
311
+ if (status === "connected") {
312
+ status = "disconnected";
313
+ }
314
+ });
315
+ }
316
+ function ensureMQTTClient() {
317
+ if (isMQTTEnabled() && !client) {
318
+ initMQTTClient();
319
+ }
320
+ }
321
+ function publishMQTT(topic, payload) {
322
+ if (!isMQTTEnabled()) {
323
+ return false;
324
+ }
325
+ ensureMQTTClient();
326
+ if (!client) {
327
+ return false;
328
+ }
329
+ try {
330
+ client.publish(topic, JSON.stringify(payload), {
331
+ qos: mqttConfig.qos
332
+ });
333
+ return true;
334
+ } catch (err) {
335
+ console.warn("".concat(LOG, " publish failed on ").concat(topic, ":"), err);
336
+ return false;
337
+ }
338
+ }
339
+ // src/utils/tracking.ts
234
340
  var cachedBrowserId = null;
235
341
  function getClientInfo() {
236
342
  var _screen, _screen1, _screen2, _screen3, _screen_orientation, _screen4, _screen5, _window, _window1, _window_screen_orientation, _window_screen, _navigator_languages;
@@ -261,8 +367,8 @@ function getClientInfo() {
261
367
  os = "webOS";
262
368
  isSmartTV = true;
263
369
  deviceType = "tv";
264
- var webosMatch = ua.match(/Web0S\/([^\s]+)/);
265
- model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
370
+ var m = ua.match(/Web0S\/([^\s]+)/);
371
+ model = m ? "webOS ".concat(m[1]) : "webOS TV";
266
372
  } else if (ua.includes("Tizen")) {
267
373
  brand = "Samsung";
268
374
  os = "Tizen";
@@ -306,23 +412,19 @@ function getClientInfo() {
306
412
  isAndroid = true;
307
413
  os = "Android";
308
414
  deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
309
- if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
415
+ if (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi")) {
310
416
  deviceType = "tv";
311
417
  isSmartTV = true;
312
418
  brand = brand === "Unknown" ? "Android TV" : brand;
313
419
  }
314
420
  var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
315
- if (androidModelMatch && androidModelMatch[1]) {
316
- model = androidModelMatch[1];
317
- }
421
+ if (androidModelMatch === null || androidModelMatch === void 0 ? void 0 : androidModelMatch[1]) model = androidModelMatch[1];
318
422
  }
319
423
  if (/iPad|iPhone|iPod/.test(ua)) {
320
424
  os = "iOS";
321
425
  deviceType = "mobile";
322
426
  brand = "Apple";
323
- if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
324
- deviceType = "tablet";
325
- }
427
+ if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) deviceType = "tablet";
326
428
  }
327
429
  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
328
430
  if (ua.includes("Windows")) {
@@ -343,9 +445,7 @@ function getClientInfo() {
343
445
  if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
344
446
  }
345
447
  isWebView = /wv|WebView|Linux; U;/.test(ua);
346
- if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
347
- isWebView = true;
348
- }
448
+ if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) isWebView = true;
349
449
  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;
350
450
  return {
351
451
  brand: brand,
@@ -376,18 +476,16 @@ function getClientInfo() {
376
476
  }
377
477
  function getBrowserID(clientInfo) {
378
478
  return _async_to_generator(function() {
379
- var fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashArray, hashHex, error, hash, i1, char, fallbackHash, timestamp, random;
479
+ var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
380
480
  return _ts_generator(this, function(_state) {
381
481
  switch(_state.label){
382
482
  case 0:
383
- if (cachedBrowserId) {
384
- return [
385
- 2,
386
- cachedBrowserId
387
- ];
388
- }
483
+ if (cachedBrowserId) return [
484
+ 2,
485
+ cachedBrowserId
486
+ ];
389
487
  fingerprintString = JSON.stringify(clientInfo);
390
- if (!(typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest)) return [
488
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
391
489
  3,
392
490
  5
393
491
  ];
@@ -414,9 +512,7 @@ function getBrowserID(clientInfo) {
414
512
  } else {
415
513
  utf8 = unescape(encodeURIComponent(fingerprintString));
416
514
  buffer = new Uint8Array(utf8.length);
417
- for(i = 0; i < utf8.length; i++){
418
- buffer[i] = utf8.charCodeAt(i);
419
- }
515
+ for(i = 0; i < utf8.length; i++)buffer[i] = utf8.charCodeAt(i);
420
516
  encodedData = buffer;
421
517
  }
422
518
  return [
@@ -425,8 +521,7 @@ function getBrowserID(clientInfo) {
425
521
  ];
426
522
  case 3:
427
523
  hashBuffer = _state.sent();
428
- hashArray = Array.from(new Uint8Array(hashBuffer));
429
- hashHex = hashArray.map(function(b) {
524
+ hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
430
525
  return b.toString(16).padStart(2, "0");
431
526
  }).join("");
432
527
  cachedBrowserId = hashHex;
@@ -435,8 +530,8 @@ function getBrowserID(clientInfo) {
435
530
  hashHex
436
531
  ];
437
532
  case 4:
438
- error = _state.sent();
439
- console.warn("[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash");
533
+ unused = _state.sent();
534
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
440
535
  return [
441
536
  3,
442
537
  5
@@ -460,177 +555,91 @@ function getBrowserID(clientInfo) {
460
555
  });
461
556
  })();
462
557
  }
463
- var PLAYER_TRACKING_BASE_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking";
464
- var TRACK_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/metrics/ingest");
465
- var HEARTBEAT_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/heartbeat");
466
- var IMPRESSIONS_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/impressions/ingest");
467
- function buildHeaders(licenseKey) {
468
- var headers = {
469
- "Content-Type": "application/json"
470
- };
471
- if (licenseKey) {
472
- headers["Authorization"] = "Bearer ".concat(licenseKey);
473
- }
474
- return headers;
558
+ function canPublish(licenseKey) {
559
+ return Boolean(isMQTTEnabled() && licenseKey);
475
560
  }
476
- function sendTrackRequest(licenseKey, body) {
561
+ function buildPlayerMetricEvent() {
477
562
  return _async_to_generator(function() {
478
- var response;
479
- return _ts_generator(this, function(_state) {
480
- switch(_state.label){
481
- case 0:
482
- return [
483
- 4,
484
- fetch(TRACK_URL, {
485
- method: "POST",
486
- headers: buildHeaders(licenseKey),
487
- body: JSON.stringify(body)
488
- })
489
- ];
490
- case 1:
491
- response = _state.sent();
492
- if (!response.ok) {
493
- throw new Error("HTTP error! status: ".concat(response.status));
494
- }
495
- return [
496
- 4,
497
- response.json()
498
- ];
499
- case 2:
500
- _state.sent();
501
- return [
502
- 2
503
- ];
504
- }
505
- });
506
- })();
507
- }
508
- function postJson(url, licenseKey, body) {
509
- return _async_to_generator(function() {
510
- var response;
511
- return _ts_generator(this, function(_state) {
512
- switch(_state.label){
513
- case 0:
514
- return [
515
- 4,
516
- fetch(url, {
517
- method: "POST",
518
- headers: buildHeaders(licenseKey),
519
- body: JSON.stringify(body)
520
- })
521
- ];
522
- case 1:
523
- response = _state.sent();
524
- if (!response.ok) {
525
- throw new Error("HTTP error! status: ".concat(response.status));
526
- }
527
- return [
528
- 4,
529
- response.json()
530
- ];
531
- case 2:
532
- _state.sent();
533
- return [
534
- 2
535
- ];
536
- }
537
- });
538
- })();
539
- }
540
- function buildPlayerMetricEvent(_0) {
541
- return _async_to_generator(function(licenseKey) {
542
- var context, flags, _flags_captureAt, clientInfo, browserId, captureAt;
563
+ var context, flags, _flags_captureAt, _flags_adLoaded, _flags_adDetect, clientInfo, playerId, captureAt;
543
564
  var _arguments = arguments;
544
565
  return _ts_generator(this, function(_state) {
545
566
  switch(_state.label){
546
567
  case 0:
547
- context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
568
+ context = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {}, flags = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
548
569
  clientInfo = getClientInfo();
549
570
  return [
550
571
  4,
551
572
  getBrowserID(clientInfo)
552
573
  ];
553
574
  case 1:
554
- browserId = _state.sent();
575
+ playerId = _state.sent();
555
576
  captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
556
577
  return [
557
578
  2,
558
- {
559
- player_id: browserId,
560
- browserId: browserId,
579
+ _object_spread({
580
+ player_id: playerId,
561
581
  device_type: clientInfo.deviceType,
562
- deviceType: clientInfo.deviceType,
563
- input_stream_type: context.inputStreamType,
564
- os: clientInfo.os,
565
- ad_loaded: flags.adLoaded,
566
- ad_detect: flags.adDetect,
567
- license_key: licenseKey,
568
- capture_at: captureAt,
569
- timestamp: captureAt
570
- }
582
+ os: clientInfo.os.toLowerCase(),
583
+ ad_loaded: (_flags_adLoaded = flags.adLoaded) !== null && _flags_adLoaded !== void 0 ? _flags_adLoaded : false,
584
+ ad_detect: (_flags_adDetect = flags.adDetect) !== null && _flags_adDetect !== void 0 ? _flags_adDetect : false,
585
+ capture_at: captureAt
586
+ }, context.inputStreamType ? {
587
+ input_stream_type: context.inputStreamType
588
+ } : {})
571
589
  ];
572
590
  }
573
591
  });
574
592
  }).apply(this, arguments);
575
593
  }
594
+ function publishTracking(licenseKey, channel, body) {
595
+ ensureMQTTClient();
596
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
597
+ }
576
598
  function sendInitialTracking(_0) {
577
599
  return _async_to_generator(function(licenseKey) {
578
- var context, clientInfo, browserId, trackingData, error;
600
+ var context, metricEvent, error;
579
601
  var _arguments = arguments;
580
602
  return _ts_generator(this, function(_state) {
581
603
  switch(_state.label){
582
604
  case 0:
583
605
  context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
606
+ if (!canPublish(licenseKey)) return [
607
+ 2
608
+ ];
584
609
  _state.label = 1;
585
610
  case 1:
586
611
  _state.trys.push([
587
612
  1,
588
- 4,
613
+ 3,
589
614
  ,
590
- 5
615
+ 4
591
616
  ]);
592
- clientInfo = getClientInfo();
593
617
  return [
594
618
  4,
595
- getBrowserID(clientInfo)
596
- ];
597
- case 2:
598
- browserId = _state.sent();
599
- trackingData = _object_spread({
600
- browserId: browserId
601
- }, clientInfo);
602
- return [
603
- 4,
604
- sendTrackRequest(licenseKey, {
605
- events: [
606
- {
607
- player_id: browserId,
608
- device_type: clientInfo.deviceType,
609
- input_stream_type: context.inputStreamType,
610
- os: clientInfo.os,
611
- ad_loaded: false,
612
- ad_detect: false,
613
- license_key: licenseKey,
614
- capture_at: /* @__PURE__ */ new Date().toISOString()
615
- }
616
- ],
617
- trackingData: trackingData
619
+ buildPlayerMetricEvent(context, {
620
+ adLoaded: false,
621
+ adDetect: false
618
622
  })
619
623
  ];
620
- case 3:
621
- _state.sent();
624
+ case 2:
625
+ metricEvent = _state.sent();
626
+ publishTracking(licenseKey, "metrics", {
627
+ events: [
628
+ metricEvent
629
+ ]
630
+ });
622
631
  return [
623
632
  3,
624
- 5
633
+ 4
625
634
  ];
626
- case 4:
635
+ case 3:
627
636
  error = _state.sent();
628
637
  console.error("[StormcloudVideoPlayer] Error sending initial tracking data:", error);
629
638
  return [
630
639
  3,
631
- 5
640
+ 4
632
641
  ];
633
- case 5:
642
+ case 4:
634
643
  return [
635
644
  2
636
645
  ];
@@ -734,53 +743,48 @@ function sendAdImpressionTracking(_0, _1) {
734
743
  switch(_state.label){
735
744
  case 0:
736
745
  context = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
746
+ if (!canPublish(licenseKey)) return [
747
+ 2
748
+ ];
737
749
  _state.label = 1;
738
750
  case 1:
739
751
  _state.trys.push([
740
752
  1,
741
- 4,
753
+ 3,
742
754
  ,
743
- 5
755
+ 4
744
756
  ]);
745
757
  return [
746
758
  4,
747
- buildPlayerMetricEvent(licenseKey, context, {
759
+ buildPlayerMetricEvent(context, {
748
760
  captureAt: adImpressionInfo.timestamp
749
761
  })
750
762
  ];
751
763
  case 2:
752
764
  metricEvent = _state.sent();
753
- return [
754
- 4,
755
- Promise.all([
756
- postJson(HEARTBEAT_URL, licenseKey, metricEvent),
757
- postJson(IMPRESSIONS_URL, licenseKey, {
758
- events: [
759
- {
760
- player_id: metricEvent.player_id,
761
- ad_played_count: 1,
762
- ad_url: adImpressionInfo.adUrl,
763
- license_key: licenseKey,
764
- capture_at: adImpressionInfo.timestamp
765
- }
766
- ]
767
- })
768
- ])
769
- ];
770
- case 3:
771
- _state.sent();
765
+ publishTracking(licenseKey, "heartbeat", metricEvent);
766
+ publishTracking(licenseKey, "impressions", {
767
+ events: [
768
+ {
769
+ player_id: metricEvent.player_id,
770
+ ad_played_count: 1,
771
+ ad_url: adImpressionInfo.adUrl,
772
+ capture_at: adImpressionInfo.timestamp
773
+ }
774
+ ]
775
+ });
772
776
  return [
773
777
  3,
774
- 5
778
+ 4
775
779
  ];
776
- case 4:
780
+ case 3:
777
781
  error = _state.sent();
778
782
  console.error("[StormcloudVideoPlayer] Error sending ad impression tracking:", error);
779
783
  return [
780
784
  3,
781
- 5
785
+ 4
782
786
  ];
783
- case 5:
787
+ case 4:
784
788
  return [
785
789
  2
786
790
  ];
@@ -796,38 +800,36 @@ function sendHeartbeat(_0) {
796
800
  switch(_state.label){
797
801
  case 0:
798
802
  context = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {}, flags = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : {};
803
+ if (!canPublish(licenseKey)) return [
804
+ 2
805
+ ];
799
806
  _state.label = 1;
800
807
  case 1:
801
808
  _state.trys.push([
802
809
  1,
803
- 4,
810
+ 3,
804
811
  ,
805
- 5
812
+ 4
806
813
  ]);
807
814
  return [
808
815
  4,
809
- buildPlayerMetricEvent(licenseKey, context, flags)
816
+ buildPlayerMetricEvent(context, flags)
810
817
  ];
811
818
  case 2:
812
819
  heartbeatData = _state.sent();
813
- return [
814
- 4,
815
- postJson(HEARTBEAT_URL, licenseKey, heartbeatData)
816
- ];
817
- case 3:
818
- _state.sent();
820
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
819
821
  return [
820
822
  3,
821
- 5
823
+ 4
822
824
  ];
823
- case 4:
825
+ case 3:
824
826
  error = _state.sent();
825
827
  console.error("[StormcloudVideoPlayer] Error sending heartbeat:", error);
826
828
  return [
827
829
  3,
828
- 5
830
+ 4
829
831
  ];
830
- case 5:
832
+ case 4:
831
833
  return [
832
834
  2
833
835
  ];