adgent-sdk 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adgent-sdk.es.js +292 -309
- package/dist/adgent-sdk.umd.js +4 -4
- package/package.json +1 -1
package/dist/adgent-sdk.es.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
var R = Object.defineProperty;
|
|
2
|
-
var S = (i, e, r) => e in i ? R(i, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : i[e] = r;
|
|
3
|
-
var l = (i, e, r) => S(i, typeof e != "symbol" ? e + "" : e, r);
|
|
4
1
|
import { XMLParser as T } from "fast-xml-parser";
|
|
5
|
-
var d = /* @__PURE__ */ ((
|
|
6
|
-
class
|
|
2
|
+
var d = /* @__PURE__ */ ((r) => (r.Idle = "idle", r.Loading = "loading", r.Ready = "ready", r.Playing = "playing", r.Paused = "paused", r.Completed = "completed", r.Error = "error", r.WaitingForInteraction = "waiting_for_interaction", r))(d || {}), h = /* @__PURE__ */ ((r) => (r[r.XML_PARSING_ERROR = 100] = "XML_PARSING_ERROR", r[r.VAST_SCHEMA_VALIDATION_ERROR = 101] = "VAST_SCHEMA_VALIDATION_ERROR", r[r.VAST_VERSION_NOT_SUPPORTED = 102] = "VAST_VERSION_NOT_SUPPORTED", r[r.GENERAL_WRAPPER_ERROR = 300] = "GENERAL_WRAPPER_ERROR", r[r.WRAPPER_TIMEOUT = 301] = "WRAPPER_TIMEOUT", r[r.WRAPPER_LIMIT_REACHED = 302] = "WRAPPER_LIMIT_REACHED", r[r.NO_VAST_RESPONSE = 303] = "NO_VAST_RESPONSE", r[r.GENERAL_LINEAR_ERROR = 400] = "GENERAL_LINEAR_ERROR", r[r.FILE_NOT_FOUND = 401] = "FILE_NOT_FOUND", r[r.MEDIA_TIMEOUT = 402] = "MEDIA_TIMEOUT", r[r.MEDIA_NOT_SUPPORTED = 403] = "MEDIA_NOT_SUPPORTED", r[r.GENERAL_COMPANION_ERROR = 600] = "GENERAL_COMPANION_ERROR", r[r.UNDEFINED_ERROR = 900] = "UNDEFINED_ERROR", r))(h || {}), P = Object.defineProperty, A = (r, e, t) => e in r ? P(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, E = (r, e, t) => A(r, typeof e != "symbol" ? e + "" : e, t);
|
|
3
|
+
class O {
|
|
7
4
|
constructor(e = {}) {
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
E(this, "config"), E(this, "xmlParser");
|
|
6
|
+
var t, i, s, a;
|
|
10
7
|
this.config = {
|
|
11
|
-
maxWrapperDepth: e.maxWrapperDepth
|
|
12
|
-
timeout: e.timeout
|
|
13
|
-
debug: e.debug
|
|
14
|
-
fetchFn: e.fetchFn
|
|
8
|
+
maxWrapperDepth: (t = e.maxWrapperDepth) != null ? t : 5,
|
|
9
|
+
timeout: (i = e.timeout) != null ? i : 1e4,
|
|
10
|
+
debug: (s = e.debug) != null ? s : !1,
|
|
11
|
+
fetchFn: (a = e.fetchFn) != null ? a : fetch.bind(globalThis)
|
|
15
12
|
}, this.xmlParser = new T({
|
|
16
13
|
ignoreAttributes: !1,
|
|
17
14
|
attributeNamePrefix: "@_",
|
|
@@ -27,13 +24,13 @@ class A {
|
|
|
27
24
|
async parse(e) {
|
|
28
25
|
try {
|
|
29
26
|
return { success: !0, response: await this.fetchAndParse(e, 0) };
|
|
30
|
-
} catch (
|
|
31
|
-
const
|
|
27
|
+
} catch (t) {
|
|
28
|
+
const i = t instanceof Error ? t.message : "Unknown error";
|
|
32
29
|
return {
|
|
33
30
|
success: !1,
|
|
34
31
|
error: {
|
|
35
|
-
code:
|
|
36
|
-
message:
|
|
32
|
+
code: h.GENERAL_WRAPPER_ERROR,
|
|
33
|
+
message: i
|
|
37
34
|
}
|
|
38
35
|
};
|
|
39
36
|
}
|
|
@@ -41,16 +38,16 @@ class A {
|
|
|
41
38
|
/**
|
|
42
39
|
* Fetch and parse VAST document with wrapper resolution
|
|
43
40
|
*/
|
|
44
|
-
async fetchAndParse(e,
|
|
45
|
-
if (
|
|
41
|
+
async fetchAndParse(e, t) {
|
|
42
|
+
if (t >= this.config.maxWrapperDepth)
|
|
46
43
|
throw new Error(
|
|
47
44
|
`Wrapper limit exceeded (max: ${this.config.maxWrapperDepth})`
|
|
48
45
|
);
|
|
49
|
-
this.log(`Fetching VAST (depth: ${
|
|
50
|
-
const
|
|
46
|
+
this.log(`Fetching VAST (depth: ${t}): ${e}`);
|
|
47
|
+
const i = await this.fetchWithTimeout(e), s = this.parseXml(i), a = await Promise.all(
|
|
51
48
|
s.ads.map(async (n) => {
|
|
52
|
-
var
|
|
53
|
-
return (
|
|
49
|
+
var u;
|
|
50
|
+
return (u = n.wrapper) != null && u.vastAdTagURI ? this.resolveWrapper(n, t + 1) : n;
|
|
54
51
|
})
|
|
55
52
|
);
|
|
56
53
|
return {
|
|
@@ -61,14 +58,14 @@ class A {
|
|
|
61
58
|
/**
|
|
62
59
|
* Resolve a wrapper ad by fetching the nested VAST
|
|
63
60
|
*/
|
|
64
|
-
async resolveWrapper(e,
|
|
65
|
-
var
|
|
66
|
-
if (!((
|
|
61
|
+
async resolveWrapper(e, t) {
|
|
62
|
+
var i;
|
|
63
|
+
if (!((i = e.wrapper) != null && i.vastAdTagURI))
|
|
67
64
|
return [e];
|
|
68
65
|
try {
|
|
69
66
|
return (await this.fetchAndParse(
|
|
70
67
|
e.wrapper.vastAdTagURI,
|
|
71
|
-
|
|
68
|
+
t
|
|
72
69
|
)).ads.map(
|
|
73
70
|
(a) => this.mergeWrapperTracking(e, a)
|
|
74
71
|
);
|
|
@@ -81,21 +78,21 @@ class A {
|
|
|
81
78
|
/**
|
|
82
79
|
* Merge tracking events from wrapper into nested ad
|
|
83
80
|
*/
|
|
84
|
-
mergeWrapperTracking(e,
|
|
81
|
+
mergeWrapperTracking(e, t) {
|
|
85
82
|
return {
|
|
86
|
-
...
|
|
83
|
+
...t,
|
|
87
84
|
impressions: [
|
|
88
85
|
...e.impressions,
|
|
89
|
-
...
|
|
86
|
+
...t.impressions
|
|
90
87
|
],
|
|
91
|
-
errors: [...e.errors, ...
|
|
92
|
-
creatives:
|
|
93
|
-
...
|
|
94
|
-
linear:
|
|
95
|
-
...
|
|
88
|
+
errors: [...e.errors, ...t.errors],
|
|
89
|
+
creatives: t.creatives.map((i) => ({
|
|
90
|
+
...i,
|
|
91
|
+
linear: i.linear ? {
|
|
92
|
+
...i.linear,
|
|
96
93
|
trackingEvents: [
|
|
97
94
|
...this.getWrapperTrackingEvents(e),
|
|
98
|
-
...
|
|
95
|
+
...i.linear.trackingEvents
|
|
99
96
|
]
|
|
100
97
|
} : void 0
|
|
101
98
|
}))
|
|
@@ -106,79 +103,79 @@ class A {
|
|
|
106
103
|
*/
|
|
107
104
|
getWrapperTrackingEvents(e) {
|
|
108
105
|
var t;
|
|
109
|
-
const
|
|
106
|
+
const i = [];
|
|
110
107
|
for (const s of e.creatives)
|
|
111
|
-
(t = s.linear) != null && t.trackingEvents &&
|
|
112
|
-
return
|
|
108
|
+
(t = s.linear) != null && t.trackingEvents && i.push(...s.linear.trackingEvents);
|
|
109
|
+
return i;
|
|
113
110
|
}
|
|
114
111
|
/**
|
|
115
112
|
* Fetch URL with timeout
|
|
116
113
|
*/
|
|
117
114
|
async fetchWithTimeout(e) {
|
|
118
|
-
const
|
|
119
|
-
() =>
|
|
115
|
+
const t = new AbortController(), i = setTimeout(
|
|
116
|
+
() => t.abort(),
|
|
120
117
|
this.config.timeout
|
|
121
118
|
);
|
|
122
119
|
try {
|
|
123
120
|
const s = await this.config.fetchFn(e, {
|
|
124
|
-
signal:
|
|
121
|
+
signal: t.signal
|
|
125
122
|
});
|
|
126
123
|
if (!s.ok)
|
|
127
124
|
throw new Error(`HTTP ${s.status}: ${s.statusText}`);
|
|
128
125
|
return s.text();
|
|
129
126
|
} finally {
|
|
130
|
-
clearTimeout(
|
|
127
|
+
clearTimeout(i);
|
|
131
128
|
}
|
|
132
129
|
}
|
|
133
130
|
/**
|
|
134
131
|
* Parse raw VAST XML into structured response
|
|
135
132
|
*/
|
|
136
133
|
parseXml(e) {
|
|
137
|
-
const
|
|
138
|
-
if (!
|
|
134
|
+
const i = this.xmlParser.parse(e).VAST;
|
|
135
|
+
if (!i)
|
|
139
136
|
throw new Error("Invalid VAST: missing VAST element");
|
|
140
|
-
const s =
|
|
137
|
+
const s = i["@_version"] || "4.0", a = this.parseAds(i.Ad);
|
|
141
138
|
return {
|
|
142
139
|
version: s,
|
|
143
140
|
ads: a,
|
|
144
|
-
errors: this.parseErrors(
|
|
141
|
+
errors: this.parseErrors(i.Error)
|
|
145
142
|
};
|
|
146
143
|
}
|
|
147
144
|
/**
|
|
148
145
|
* Parse Ad elements
|
|
149
146
|
*/
|
|
150
147
|
parseAds(e) {
|
|
151
|
-
return e ? (Array.isArray(e) ? e : [e]).map((
|
|
148
|
+
return e ? (Array.isArray(e) ? e : [e]).map((i) => this.parseAd(i)) : [];
|
|
152
149
|
}
|
|
153
150
|
/**
|
|
154
151
|
* Parse a single Ad element
|
|
155
152
|
*/
|
|
156
153
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
157
154
|
parseAd(e) {
|
|
158
|
-
var
|
|
159
|
-
const
|
|
155
|
+
var t, i, s;
|
|
156
|
+
const a = !!e.Wrapper, n = e.InLine || e.Wrapper;
|
|
160
157
|
return {
|
|
161
158
|
id: e["@_id"] || "",
|
|
162
159
|
sequence: e["@_sequence"],
|
|
163
|
-
adSystem:
|
|
164
|
-
name: typeof
|
|
165
|
-
version: (
|
|
160
|
+
adSystem: n != null && n.AdSystem ? {
|
|
161
|
+
name: typeof n.AdSystem == "string" ? n.AdSystem : n.AdSystem["#text"] || "",
|
|
162
|
+
version: (t = n.AdSystem) == null ? void 0 : t["@_version"]
|
|
166
163
|
} : void 0,
|
|
167
|
-
adTitle:
|
|
168
|
-
impressions: this.parseImpressions(
|
|
169
|
-
errors: this.parseErrors(
|
|
170
|
-
creatives: this.parseCreatives((
|
|
171
|
-
wrapper:
|
|
172
|
-
vastAdTagURI:
|
|
173
|
-
followAdditionalWrappers:
|
|
174
|
-
allowMultipleAds:
|
|
175
|
-
fallbackOnNoAd:
|
|
164
|
+
adTitle: n == null ? void 0 : n.AdTitle,
|
|
165
|
+
impressions: this.parseImpressions(n == null ? void 0 : n.Impression),
|
|
166
|
+
errors: this.parseErrors(n == null ? void 0 : n.Error),
|
|
167
|
+
creatives: this.parseCreatives((i = n == null ? void 0 : n.Creatives) == null ? void 0 : i.Creative),
|
|
168
|
+
wrapper: a ? {
|
|
169
|
+
vastAdTagURI: n.VASTAdTagURI,
|
|
170
|
+
followAdditionalWrappers: n["@_followAdditionalWrappers"] !== !1,
|
|
171
|
+
allowMultipleAds: n["@_allowMultipleAds"],
|
|
172
|
+
fallbackOnNoAd: n["@_fallbackOnNoAd"]
|
|
176
173
|
} : void 0,
|
|
177
|
-
inLine:
|
|
178
|
-
adTitle: (
|
|
179
|
-
description:
|
|
180
|
-
advertiser:
|
|
181
|
-
creatives: this.parseCreatives((
|
|
174
|
+
inLine: a ? void 0 : {
|
|
175
|
+
adTitle: (n == null ? void 0 : n.AdTitle) || "",
|
|
176
|
+
description: n == null ? void 0 : n.Description,
|
|
177
|
+
advertiser: n == null ? void 0 : n.Advertiser,
|
|
178
|
+
creatives: this.parseCreatives((s = n == null ? void 0 : n.Creatives) == null ? void 0 : s.Creative)
|
|
182
179
|
}
|
|
183
180
|
};
|
|
184
181
|
}
|
|
@@ -186,20 +183,20 @@ class A {
|
|
|
186
183
|
* Parse Impression elements
|
|
187
184
|
*/
|
|
188
185
|
parseImpressions(e) {
|
|
189
|
-
return e ? (Array.isArray(e) ? e : [e]).map((
|
|
190
|
-
id:
|
|
191
|
-
url: typeof
|
|
186
|
+
return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
|
|
187
|
+
id: i["@_id"],
|
|
188
|
+
url: typeof i == "string" ? i : i["#text"] || ""
|
|
192
189
|
})) : [];
|
|
193
190
|
}
|
|
194
191
|
/**
|
|
195
192
|
* Parse Creative elements
|
|
196
193
|
*/
|
|
197
194
|
parseCreatives(e) {
|
|
198
|
-
return e ? (Array.isArray(e) ? e : [e]).map((
|
|
199
|
-
id:
|
|
200
|
-
sequence:
|
|
201
|
-
adId:
|
|
202
|
-
linear:
|
|
195
|
+
return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
|
|
196
|
+
id: i["@_id"],
|
|
197
|
+
sequence: i["@_sequence"],
|
|
198
|
+
adId: i["@_adId"],
|
|
199
|
+
linear: i.Linear ? this.parseLinear(i.Linear) : void 0
|
|
203
200
|
})) : [];
|
|
204
201
|
}
|
|
205
202
|
/**
|
|
@@ -207,13 +204,13 @@ class A {
|
|
|
207
204
|
*/
|
|
208
205
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
209
206
|
parseLinear(e) {
|
|
210
|
-
var
|
|
207
|
+
var t, i;
|
|
211
208
|
return {
|
|
212
209
|
duration: this.parseDuration(e.Duration),
|
|
213
210
|
skipOffset: e["@_skipoffset"] ? this.parseDuration(e["@_skipoffset"]) : void 0,
|
|
214
|
-
mediaFiles: this.parseMediaFiles((
|
|
211
|
+
mediaFiles: this.parseMediaFiles((t = e.MediaFiles) == null ? void 0 : t.MediaFile),
|
|
215
212
|
trackingEvents: this.parseTrackingEvents(
|
|
216
|
-
(
|
|
213
|
+
(i = e.TrackingEvents) == null ? void 0 : i.Tracking
|
|
217
214
|
),
|
|
218
215
|
videoClicks: e.VideoClicks ? {
|
|
219
216
|
clickThrough: e.VideoClicks.ClickThrough ? {
|
|
@@ -228,34 +225,34 @@ class A {
|
|
|
228
225
|
* Parse MediaFile elements
|
|
229
226
|
*/
|
|
230
227
|
parseMediaFiles(e) {
|
|
231
|
-
return e ? (Array.isArray(e) ? e : [e]).map((
|
|
232
|
-
id:
|
|
233
|
-
url: typeof
|
|
234
|
-
delivery:
|
|
235
|
-
type:
|
|
236
|
-
width: parseInt(
|
|
237
|
-
height: parseInt(
|
|
238
|
-
bitrate:
|
|
239
|
-
codec:
|
|
240
|
-
scalable:
|
|
241
|
-
maintainAspectRatio:
|
|
228
|
+
return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
|
|
229
|
+
id: i["@_id"],
|
|
230
|
+
url: typeof i == "string" ? i : i["#text"] || "",
|
|
231
|
+
delivery: i["@_delivery"] || "progressive",
|
|
232
|
+
type: i["@_type"] || "video/mp4",
|
|
233
|
+
width: parseInt(i["@_width"], 10) || 0,
|
|
234
|
+
height: parseInt(i["@_height"], 10) || 0,
|
|
235
|
+
bitrate: i["@_bitrate"] ? parseInt(i["@_bitrate"], 10) : void 0,
|
|
236
|
+
codec: i["@_codec"],
|
|
237
|
+
scalable: i["@_scalable"],
|
|
238
|
+
maintainAspectRatio: i["@_maintainAspectRatio"]
|
|
242
239
|
})) : [];
|
|
243
240
|
}
|
|
244
241
|
/**
|
|
245
242
|
* Parse Tracking elements
|
|
246
243
|
*/
|
|
247
244
|
parseTrackingEvents(e) {
|
|
248
|
-
return e ? (Array.isArray(e) ? e : [e]).map((
|
|
249
|
-
event:
|
|
250
|
-
url: typeof
|
|
251
|
-
offset:
|
|
245
|
+
return e ? (Array.isArray(e) ? e : [e]).map((i) => ({
|
|
246
|
+
event: i["@_event"],
|
|
247
|
+
url: typeof i == "string" ? i : i["#text"] || "",
|
|
248
|
+
offset: i["@_offset"] ? this.parseDuration(i["@_offset"]) : void 0
|
|
252
249
|
})) : [];
|
|
253
250
|
}
|
|
254
251
|
/**
|
|
255
252
|
* Parse Error elements
|
|
256
253
|
*/
|
|
257
254
|
parseErrors(e) {
|
|
258
|
-
return e ? (Array.isArray(e) ? e : [e]).map((
|
|
255
|
+
return e ? (Array.isArray(e) ? e : [e]).map((i) => typeof i == "string" ? i : i["#text"] || "") : [];
|
|
259
256
|
}
|
|
260
257
|
/**
|
|
261
258
|
* Parse duration string (HH:MM:SS or seconds) to seconds
|
|
@@ -265,10 +262,10 @@ class A {
|
|
|
265
262
|
if (typeof e != "string") return 0;
|
|
266
263
|
if (e.endsWith("%"))
|
|
267
264
|
return parseFloat(e) / 100;
|
|
268
|
-
const
|
|
269
|
-
if (
|
|
270
|
-
const [,
|
|
271
|
-
return parseInt(
|
|
265
|
+
const t = e.match(/(\d+):(\d+):(\d+(?:\.\d+)?)/);
|
|
266
|
+
if (t) {
|
|
267
|
+
const [, i, s, a] = t;
|
|
268
|
+
return parseInt(i, 10) * 3600 + parseInt(s, 10) * 60 + parseFloat(a);
|
|
272
269
|
}
|
|
273
270
|
return parseFloat(e) || 0;
|
|
274
271
|
}
|
|
@@ -276,14 +273,14 @@ class A {
|
|
|
276
273
|
* Select the best media file based on target bitrate
|
|
277
274
|
* Prefers 1080p/720p over 4K for TV compatibility
|
|
278
275
|
*/
|
|
279
|
-
selectBestMediaFile(e,
|
|
276
|
+
selectBestMediaFile(e, t = 2500) {
|
|
280
277
|
if (e.length === 0) return null;
|
|
281
|
-
const
|
|
278
|
+
const i = e.filter(
|
|
282
279
|
(n) => n.type.includes("mp4") || n.type.includes("video/mp4")
|
|
283
280
|
);
|
|
284
|
-
return [...
|
|
285
|
-
const
|
|
286
|
-
return
|
|
281
|
+
return [...i.length > 0 ? i : e].sort((n, u) => {
|
|
282
|
+
const m = n.bitrate || 0, f = u.bitrate || 0, k = n.height > 1080 ? 1e4 : 0, w = u.height > 1080 ? 1e4 : 0, R = Math.abs(m - t) + k, S = Math.abs(f - t) + w;
|
|
283
|
+
return R - S;
|
|
287
284
|
})[0] || null;
|
|
288
285
|
}
|
|
289
286
|
/**
|
|
@@ -291,21 +288,21 @@ class A {
|
|
|
291
288
|
*/
|
|
292
289
|
aggregateTrackingEvents(e) {
|
|
293
290
|
var t;
|
|
294
|
-
const
|
|
291
|
+
const i = [];
|
|
295
292
|
for (const s of e)
|
|
296
293
|
for (const a of s.creatives)
|
|
297
|
-
(t = a.linear) != null && t.trackingEvents &&
|
|
298
|
-
return
|
|
294
|
+
(t = a.linear) != null && t.trackingEvents && i.push(...a.linear.trackingEvents);
|
|
295
|
+
return i;
|
|
299
296
|
}
|
|
300
297
|
/**
|
|
301
298
|
* Get all impression URLs from parsed ads
|
|
302
299
|
*/
|
|
303
300
|
aggregateImpressions(e) {
|
|
304
|
-
const
|
|
305
|
-
for (const
|
|
306
|
-
for (const s of
|
|
307
|
-
|
|
308
|
-
return
|
|
301
|
+
const t = [];
|
|
302
|
+
for (const i of e)
|
|
303
|
+
for (const s of i.impressions)
|
|
304
|
+
t.push(s.url);
|
|
305
|
+
return t;
|
|
309
306
|
}
|
|
310
307
|
/**
|
|
311
308
|
* Debug logging
|
|
@@ -314,31 +311,31 @@ class A {
|
|
|
314
311
|
this.config.debug && console.log(`[VASTParser] ${e}`);
|
|
315
312
|
}
|
|
316
313
|
}
|
|
317
|
-
function
|
|
318
|
-
let
|
|
319
|
-
return
|
|
314
|
+
function g(r, e = {}) {
|
|
315
|
+
let t = r;
|
|
316
|
+
return t = t.replace(/\[TIMESTAMP\]/g, Date.now().toString()), t = t.replace(
|
|
320
317
|
/\[CACHEBUSTING\]/g,
|
|
321
318
|
Math.random().toString(36).substring(2, 15)
|
|
322
|
-
), e.assetUri && (
|
|
319
|
+
), e.assetUri && (t = t.replace(
|
|
323
320
|
/\[ASSETURI\]/g,
|
|
324
321
|
encodeURIComponent(e.assetUri)
|
|
325
|
-
)), e.contentPlayhead !== void 0 && (
|
|
322
|
+
)), e.contentPlayhead !== void 0 && (t = t.replace(
|
|
326
323
|
/\[CONTENTPLAYHEAD\]/g,
|
|
327
|
-
|
|
328
|
-
)), e.adPlayhead !== void 0 && (
|
|
324
|
+
b(e.contentPlayhead)
|
|
325
|
+
)), e.adPlayhead !== void 0 && (t = t.replace(
|
|
329
326
|
/\[ADPLAYHEAD\]/g,
|
|
330
|
-
|
|
331
|
-
)), e.errorCode !== void 0 && (
|
|
327
|
+
b(e.adPlayhead)
|
|
328
|
+
)), e.errorCode !== void 0 && (t = t.replace(/\[ERRORCODE\]/g, e.errorCode.toString())), e.breakPosition !== void 0 && (t = t.replace(
|
|
332
329
|
/\[BREAKPOSITION\]/g,
|
|
333
330
|
e.breakPosition.toString()
|
|
334
|
-
)), e.adType && (
|
|
331
|
+
)), e.adType && (t = t.replace(/\[ADTYPE\]/g, e.adType)), t;
|
|
335
332
|
}
|
|
336
|
-
function
|
|
337
|
-
const e = Math.floor(
|
|
338
|
-
return e.toString().padStart(2, "0") + ":" +
|
|
333
|
+
function b(r) {
|
|
334
|
+
const e = Math.floor(r / 3600), t = Math.floor(r % 3600 / 60), i = Math.floor(r % 60), s = Math.floor(r % 1 * 1e3);
|
|
335
|
+
return e.toString().padStart(2, "0") + ":" + t.toString().padStart(2, "0") + ":" + i.toString().padStart(2, "0") + "." + s.toString().padStart(3, "0");
|
|
339
336
|
}
|
|
340
|
-
var o = /* @__PURE__ */ ((
|
|
341
|
-
const
|
|
337
|
+
var o = /* @__PURE__ */ ((r) => (r.WebOS = "webos", r.Tizen = "tizen", r.Vidaa = "vidaa", r.WhaleOS = "whaleos", r.FireTV = "firetv", r.Roku = "roku", r.Xbox = "xbox", r.PlayStation = "playstation", r.AndroidTV = "androidtv", r.Vizio = "vizio", r.Generic = "generic", r))(o || {}), c = /* @__PURE__ */ ((r) => (r.Enter = "enter", r.Back = "back", r.Left = "left", r.Right = "right", r.Up = "up", r.Down = "down", r.Play = "play", r.Pause = "pause", r.PlayPause = "playPause", r.Stop = "stop", r.FastForward = "fastForward", r.Rewind = "rewind", r.Menu = "menu", r.Info = "info", r.Red = "red", r.Green = "green", r.Yellow = "yellow", r.Blue = "blue", r.ChannelUp = "channelUp", r.ChannelDown = "channelDown", r.VolumeUp = "volumeUp", r.VolumeDown = "volumeDown", r.Mute = "mute", r))(c || {});
|
|
338
|
+
const I = {
|
|
342
339
|
webos: {
|
|
343
340
|
13: "enter",
|
|
344
341
|
461: "back",
|
|
@@ -520,7 +517,7 @@ const _ = {
|
|
|
520
517
|
/* Mute */
|
|
521
518
|
// M key
|
|
522
519
|
}
|
|
523
|
-
},
|
|
520
|
+
}, x = {
|
|
524
521
|
tizen: [
|
|
525
522
|
/Tizen/i,
|
|
526
523
|
/SMART-TV.*Samsung/i
|
|
@@ -575,14 +572,10 @@ const _ = {
|
|
|
575
572
|
],
|
|
576
573
|
generic: []
|
|
577
574
|
};
|
|
578
|
-
|
|
575
|
+
var C = Object.defineProperty, N = (r, e, t) => e in r ? C(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, p = (r, e, t) => N(r, typeof e != "symbol" ? e + "" : e, t);
|
|
576
|
+
class F {
|
|
579
577
|
constructor() {
|
|
580
|
-
|
|
581
|
-
l(this, "capabilities");
|
|
582
|
-
l(this, "deviceInfo");
|
|
583
|
-
l(this, "keyMap");
|
|
584
|
-
l(this, "reverseKeyMap");
|
|
585
|
-
this.platform = this.detectPlatform(), this.keyMap = _[this.platform], this.reverseKeyMap = this.buildReverseKeyMap(), this.capabilities = this.detectCapabilities(), this.deviceInfo = this.detectDeviceInfo();
|
|
578
|
+
p(this, "platform"), p(this, "capabilities"), p(this, "deviceInfo"), p(this, "keyMap"), p(this, "reverseKeyMap"), this.platform = this.detectPlatform(), this.keyMap = I[this.platform], this.reverseKeyMap = this.buildReverseKeyMap(), this.capabilities = this.detectCapabilities(), this.deviceInfo = this.detectDeviceInfo();
|
|
586
579
|
}
|
|
587
580
|
/**
|
|
588
581
|
* Detect the current Smart TV platform using userAgent and global objects
|
|
@@ -590,16 +583,16 @@ class O {
|
|
|
590
583
|
detectPlatform() {
|
|
591
584
|
if (typeof window > "u" || typeof navigator > "u")
|
|
592
585
|
return o.Generic;
|
|
593
|
-
const e = navigator.userAgent,
|
|
594
|
-
if (
|
|
586
|
+
const e = navigator.userAgent, t = window;
|
|
587
|
+
if (t.tizen)
|
|
595
588
|
return o.Tizen;
|
|
596
|
-
if (
|
|
589
|
+
if (t.webOS || t.PalmSystem)
|
|
597
590
|
return o.WebOS;
|
|
598
|
-
for (const [
|
|
599
|
-
if (
|
|
591
|
+
for (const [i, s] of Object.entries(x))
|
|
592
|
+
if (i !== o.Generic) {
|
|
600
593
|
for (const a of s)
|
|
601
594
|
if (a.test(e))
|
|
602
|
-
return
|
|
595
|
+
return i;
|
|
603
596
|
}
|
|
604
597
|
return o.Generic;
|
|
605
598
|
}
|
|
@@ -607,11 +600,11 @@ class O {
|
|
|
607
600
|
* Detect platform capabilities
|
|
608
601
|
*/
|
|
609
602
|
detectCapabilities() {
|
|
610
|
-
const e = typeof navigator < "u",
|
|
603
|
+
const e = typeof navigator < "u", t = typeof document < "u", i = typeof window < "u", s = {
|
|
611
604
|
sendBeacon: e && "sendBeacon" in navigator,
|
|
612
605
|
fetchKeepalive: typeof fetch < "u",
|
|
613
606
|
mutedAutoplayRequired: !0,
|
|
614
|
-
fullscreen:
|
|
607
|
+
fullscreen: t && ("fullscreenEnabled" in document || "webkitFullscreenEnabled" in document),
|
|
615
608
|
hardwareDecodeInfo: !1,
|
|
616
609
|
hdr: !1,
|
|
617
610
|
hdr10Plus: !1,
|
|
@@ -621,7 +614,7 @@ class O {
|
|
|
621
614
|
vp9: this.isCodecSupported('video/webm; codecs="vp9"'),
|
|
622
615
|
av1: this.isCodecSupported('video/mp4; codecs="av01.0.05M.08"'),
|
|
623
616
|
maxResolution: this.detectMaxResolution(),
|
|
624
|
-
touch:
|
|
617
|
+
touch: i && "ontouchstart" in window,
|
|
625
618
|
voice: !1
|
|
626
619
|
};
|
|
627
620
|
switch (this.platform) {
|
|
@@ -693,46 +686,46 @@ class O {
|
|
|
693
686
|
* Detect device information
|
|
694
687
|
*/
|
|
695
688
|
detectDeviceInfo() {
|
|
696
|
-
var
|
|
697
|
-
const
|
|
689
|
+
var e, t, i;
|
|
690
|
+
const s = {
|
|
698
691
|
platform: this.platform
|
|
699
692
|
};
|
|
700
|
-
typeof window < "u" && (
|
|
701
|
-
const
|
|
702
|
-
if (this.platform === o.Tizen && ((
|
|
693
|
+
typeof window < "u" && (s.screenWidth = (e = window.screen) == null ? void 0 : e.width, s.screenHeight = (t = window.screen) == null ? void 0 : t.height, s.devicePixelRatio = window.devicePixelRatio);
|
|
694
|
+
const a = window;
|
|
695
|
+
if (this.platform === o.Tizen && ((i = a.tizen) != null && i.systeminfo))
|
|
703
696
|
try {
|
|
704
|
-
|
|
705
|
-
|
|
697
|
+
a.tizen.systeminfo.getPropertyValue("BUILD", (n) => {
|
|
698
|
+
s.model = n.model, s.manufacturer = n.manufacturer || "Samsung";
|
|
706
699
|
});
|
|
707
700
|
} catch {
|
|
708
|
-
|
|
701
|
+
s.manufacturer = "Samsung";
|
|
709
702
|
}
|
|
710
|
-
if (this.platform === o.WebOS &&
|
|
703
|
+
if (this.platform === o.WebOS && a.webOSSystem)
|
|
711
704
|
try {
|
|
712
|
-
const n =
|
|
713
|
-
|
|
705
|
+
const n = a.webOSSystem.deviceInfo;
|
|
706
|
+
s.model = n == null ? void 0 : n.modelName, s.manufacturer = "LG", s.osVersion = n == null ? void 0 : n.version;
|
|
714
707
|
} catch {
|
|
715
|
-
|
|
708
|
+
s.manufacturer = "LG";
|
|
716
709
|
}
|
|
717
|
-
return
|
|
710
|
+
return s;
|
|
718
711
|
}
|
|
719
712
|
/**
|
|
720
713
|
* Detect maximum supported resolution
|
|
721
714
|
*/
|
|
722
715
|
detectMaxResolution() {
|
|
723
|
-
var
|
|
716
|
+
var e, t;
|
|
724
717
|
if (typeof window > "u") return "unknown";
|
|
725
|
-
const
|
|
726
|
-
return
|
|
718
|
+
const i = ((e = window.screen) == null ? void 0 : e.width) || 0, s = ((t = window.screen) == null ? void 0 : t.height) || 0, a = Math.max(i, s);
|
|
719
|
+
return a >= 3840 ? "4k" : a >= 1920 ? "1080p" : a >= 1280 ? "720p" : "unknown";
|
|
727
720
|
}
|
|
728
721
|
/**
|
|
729
722
|
* Build reverse mapping from KeyAction to key codes
|
|
730
723
|
*/
|
|
731
724
|
buildReverseKeyMap() {
|
|
732
725
|
const e = /* @__PURE__ */ new Map();
|
|
733
|
-
for (const [
|
|
734
|
-
const s = parseInt(
|
|
735
|
-
a.push(s), e.set(
|
|
726
|
+
for (const [t, i] of Object.entries(this.keyMap)) {
|
|
727
|
+
const s = parseInt(t, 10), a = e.get(i) || [];
|
|
728
|
+
a.push(s), e.set(i, a);
|
|
736
729
|
}
|
|
737
730
|
return e;
|
|
738
731
|
}
|
|
@@ -742,7 +735,8 @@ class O {
|
|
|
742
735
|
* @returns KeyAction or null if not mapped
|
|
743
736
|
*/
|
|
744
737
|
normalizeKeyCode(e) {
|
|
745
|
-
|
|
738
|
+
var t;
|
|
739
|
+
return (t = this.keyMap[e]) != null ? t : null;
|
|
746
740
|
}
|
|
747
741
|
/**
|
|
748
742
|
* Get all key codes that map to a specific action
|
|
@@ -760,8 +754,8 @@ class O {
|
|
|
760
754
|
isCodecSupported(e) {
|
|
761
755
|
if (typeof document > "u") return !1;
|
|
762
756
|
try {
|
|
763
|
-
const
|
|
764
|
-
return
|
|
757
|
+
const i = document.createElement("video").canPlayType(e);
|
|
758
|
+
return i === "probably" || i === "maybe";
|
|
765
759
|
} catch {
|
|
766
760
|
return !1;
|
|
767
761
|
}
|
|
@@ -785,9 +779,9 @@ class O {
|
|
|
785
779
|
"ColorF2Yellow",
|
|
786
780
|
"ColorF3Blue",
|
|
787
781
|
"Info"
|
|
788
|
-
].forEach((
|
|
782
|
+
].forEach((i) => {
|
|
789
783
|
try {
|
|
790
|
-
e.tvinputdevice.registerKey(
|
|
784
|
+
e.tvinputdevice.registerKey(i);
|
|
791
785
|
} catch {
|
|
792
786
|
}
|
|
793
787
|
});
|
|
@@ -869,32 +863,31 @@ class O {
|
|
|
869
863
|
}
|
|
870
864
|
}
|
|
871
865
|
}
|
|
872
|
-
let
|
|
873
|
-
function
|
|
874
|
-
return
|
|
866
|
+
let y = null;
|
|
867
|
+
function _() {
|
|
868
|
+
return y || (y = new F()), y;
|
|
875
869
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
l(this, "macroContext");
|
|
870
|
+
var M = Object.defineProperty, D = (r, e, t) => e in r ? M(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, v = (r, e, t) => D(r, typeof e != "symbol" ? e + "" : e, t);
|
|
871
|
+
class L {
|
|
872
|
+
constructor(e = [], t = {}) {
|
|
873
|
+
v(this, "config"), v(this, "trackingEvents"), v(this, "firedEvents"), v(this, "macroContext");
|
|
874
|
+
var i, s, a;
|
|
882
875
|
this.config = {
|
|
883
|
-
debug:
|
|
884
|
-
retry:
|
|
885
|
-
maxRetries:
|
|
876
|
+
debug: (i = t.debug) != null ? i : !1,
|
|
877
|
+
retry: (s = t.retry) != null ? s : !1,
|
|
878
|
+
maxRetries: (a = t.maxRetries) != null ? a : 3
|
|
886
879
|
}, this.trackingEvents = this.groupEventsByType(e), this.firedEvents = /* @__PURE__ */ new Set(), this.macroContext = {};
|
|
887
880
|
}
|
|
888
881
|
/**
|
|
889
882
|
* Group tracking events by their event type
|
|
890
883
|
*/
|
|
891
884
|
groupEventsByType(e) {
|
|
892
|
-
const
|
|
893
|
-
for (const
|
|
894
|
-
const s =
|
|
895
|
-
s.push(
|
|
885
|
+
const t = /* @__PURE__ */ new Map();
|
|
886
|
+
for (const i of e) {
|
|
887
|
+
const s = t.get(i.event) || [];
|
|
888
|
+
s.push(i), t.set(i.event, s);
|
|
896
889
|
}
|
|
897
|
-
return
|
|
890
|
+
return t;
|
|
898
891
|
}
|
|
899
892
|
/**
|
|
900
893
|
* Update macro context for URL replacement
|
|
@@ -907,20 +900,20 @@ class x {
|
|
|
907
900
|
* @param eventType - The VAST event type to track
|
|
908
901
|
* @param once - Only fire once per event type (default: true)
|
|
909
902
|
*/
|
|
910
|
-
track(e,
|
|
911
|
-
const
|
|
912
|
-
if (!
|
|
903
|
+
track(e, t = !0) {
|
|
904
|
+
const i = this.trackingEvents.get(e);
|
|
905
|
+
if (!i) {
|
|
913
906
|
this.log(`No tracking URLs for event: ${e}`);
|
|
914
907
|
return;
|
|
915
908
|
}
|
|
916
|
-
for (const s of
|
|
909
|
+
for (const s of i) {
|
|
917
910
|
const a = `${e}:${s.url}`;
|
|
918
|
-
if (
|
|
911
|
+
if (t && this.firedEvents.has(a)) {
|
|
919
912
|
this.log(`Skipping duplicate event: ${e}`);
|
|
920
913
|
continue;
|
|
921
914
|
}
|
|
922
|
-
const n =
|
|
923
|
-
this.firePixel(n),
|
|
915
|
+
const n = g(s.url, this.macroContext);
|
|
916
|
+
this.firePixel(n), t && this.firedEvents.add(a);
|
|
924
917
|
}
|
|
925
918
|
}
|
|
926
919
|
/**
|
|
@@ -928,12 +921,12 @@ class x {
|
|
|
928
921
|
* Uses sendBeacon when available, falls back to fetch with keepalive
|
|
929
922
|
*/
|
|
930
923
|
firePixel(e) {
|
|
931
|
-
const
|
|
924
|
+
const t = _();
|
|
932
925
|
this.log(`Firing pixel: ${e}`);
|
|
933
926
|
try {
|
|
934
|
-
if (
|
|
927
|
+
if (t.capabilities.sendBeacon && navigator.sendBeacon(e))
|
|
935
928
|
return;
|
|
936
|
-
if (
|
|
929
|
+
if (t.capabilities.fetchKeepalive) {
|
|
937
930
|
fetch(e, {
|
|
938
931
|
method: "GET",
|
|
939
932
|
keepalive: !0,
|
|
@@ -952,17 +945,17 @@ class x {
|
|
|
952
945
|
* Image beacon fallback
|
|
953
946
|
*/
|
|
954
947
|
fireImageBeacon(e) {
|
|
955
|
-
const
|
|
956
|
-
|
|
948
|
+
const t = new Image(1, 1);
|
|
949
|
+
t.src = e;
|
|
957
950
|
}
|
|
958
951
|
/**
|
|
959
952
|
* Fire impression pixels
|
|
960
953
|
* @param impressionUrls - Array of impression URLs
|
|
961
954
|
*/
|
|
962
955
|
fireImpressions(e) {
|
|
963
|
-
for (const
|
|
964
|
-
const
|
|
965
|
-
this.firePixel(
|
|
956
|
+
for (const t of e) {
|
|
957
|
+
const i = g(t, this.macroContext);
|
|
958
|
+
this.firePixel(i);
|
|
966
959
|
}
|
|
967
960
|
}
|
|
968
961
|
/**
|
|
@@ -970,10 +963,10 @@ class x {
|
|
|
970
963
|
* @param errorUrls - Array of error tracking URLs
|
|
971
964
|
* @param errorCode - VAST error code
|
|
972
965
|
*/
|
|
973
|
-
fireError(e,
|
|
974
|
-
const
|
|
966
|
+
fireError(e, t) {
|
|
967
|
+
const i = { ...this.macroContext, errorCode: t };
|
|
975
968
|
for (const s of e) {
|
|
976
|
-
const a =
|
|
969
|
+
const a = g(s, i);
|
|
977
970
|
this.firePixel(a);
|
|
978
971
|
}
|
|
979
972
|
}
|
|
@@ -990,29 +983,17 @@ class x {
|
|
|
990
983
|
this.config.debug && console.log(`[AdTracker] ${e}`);
|
|
991
984
|
}
|
|
992
985
|
}
|
|
993
|
-
|
|
986
|
+
var W = Object.defineProperty, U = (r, e, t) => e in r ? W(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t, l = (r, e, t) => U(r, typeof e != "symbol" ? e + "" : e, t);
|
|
987
|
+
const B = {
|
|
994
988
|
targetBitrate: 2500,
|
|
995
989
|
maxWrapperDepth: 5,
|
|
996
990
|
timeout: 1e4,
|
|
997
991
|
debug: !1,
|
|
998
992
|
skipButtonText: "Skip Ad"
|
|
999
993
|
};
|
|
1000
|
-
class
|
|
994
|
+
class $ {
|
|
1001
995
|
constructor(e) {
|
|
1002
|
-
l(this, "config")
|
|
1003
|
-
l(this, "platform");
|
|
1004
|
-
l(this, "parser");
|
|
1005
|
-
l(this, "videoElement", null);
|
|
1006
|
-
l(this, "overlayElement", null);
|
|
1007
|
-
l(this, "skipButtonElement", null);
|
|
1008
|
-
l(this, "tracker", null);
|
|
1009
|
-
l(this, "state");
|
|
1010
|
-
l(this, "ads", []);
|
|
1011
|
-
l(this, "listeners", /* @__PURE__ */ new Set());
|
|
1012
|
-
l(this, "quartilesFired", /* @__PURE__ */ new Set());
|
|
1013
|
-
l(this, "boundKeyHandler", null);
|
|
1014
|
-
l(this, "focusTrap", null);
|
|
1015
|
-
this.config = { ...I, ...e }, this.platform = y(), this.parser = new A({
|
|
996
|
+
l(this, "config"), l(this, "platform"), l(this, "parser"), l(this, "videoElement", null), l(this, "overlayElement", null), l(this, "skipButtonElement", null), l(this, "tracker", null), l(this, "state"), l(this, "ads", []), l(this, "listeners", /* @__PURE__ */ new Set()), l(this, "quartilesFired", /* @__PURE__ */ new Set()), l(this, "boundKeyHandler", null), l(this, "focusTrap", null), this.config = { ...B, ...e }, this.platform = _(), this.parser = new O({
|
|
1016
997
|
maxWrapperDepth: this.config.maxWrapperDepth,
|
|
1017
998
|
timeout: this.config.timeout,
|
|
1018
999
|
debug: this.config.debug
|
|
@@ -1032,26 +1013,26 @@ class N {
|
|
|
1032
1013
|
* Initialize the SDK: fetch VAST, create video element, attempt autoplay
|
|
1033
1014
|
*/
|
|
1034
1015
|
async init() {
|
|
1035
|
-
var e,
|
|
1016
|
+
var e, t;
|
|
1036
1017
|
if (!this.config.container)
|
|
1037
1018
|
throw new Error("Container element not found");
|
|
1038
1019
|
this.updateState({ status: d.Loading });
|
|
1039
1020
|
try {
|
|
1040
|
-
const
|
|
1041
|
-
if (!
|
|
1021
|
+
const i = await this.parser.parse(this.config.vastUrl);
|
|
1022
|
+
if (!i.success || !i.response)
|
|
1042
1023
|
throw this.createError(
|
|
1043
|
-
((e =
|
|
1044
|
-
((
|
|
1024
|
+
((e = i.error) == null ? void 0 : e.code) || h.NO_VAST_RESPONSE,
|
|
1025
|
+
((t = i.error) == null ? void 0 : t.message) || "Failed to parse VAST"
|
|
1045
1026
|
);
|
|
1046
|
-
if (this.ads =
|
|
1027
|
+
if (this.ads = i.response.ads, this.ads.length === 0)
|
|
1047
1028
|
throw this.createError(
|
|
1048
|
-
|
|
1029
|
+
h.NO_VAST_RESPONSE,
|
|
1049
1030
|
"No ads in VAST response"
|
|
1050
1031
|
);
|
|
1051
1032
|
const s = this.getFirstLinearCreative();
|
|
1052
1033
|
if (!s)
|
|
1053
1034
|
throw this.createError(
|
|
1054
|
-
|
|
1035
|
+
h.GENERAL_LINEAR_ERROR,
|
|
1055
1036
|
"No linear creative found"
|
|
1056
1037
|
);
|
|
1057
1038
|
const a = this.parser.selectBestMediaFile(
|
|
@@ -1060,14 +1041,14 @@ class N {
|
|
|
1060
1041
|
);
|
|
1061
1042
|
if (!a)
|
|
1062
1043
|
throw this.createError(
|
|
1063
|
-
|
|
1044
|
+
h.FILE_NOT_FOUND,
|
|
1064
1045
|
"No suitable media file found"
|
|
1065
1046
|
);
|
|
1066
1047
|
this.updateState({ mediaFile: a });
|
|
1067
1048
|
const n = this.parser.aggregateTrackingEvents(this.ads);
|
|
1068
|
-
this.tracker = new
|
|
1069
|
-
} catch (
|
|
1070
|
-
const s =
|
|
1049
|
+
this.tracker = new L(n, { debug: this.config.debug }), this.tracker.updateMacroContext({ assetUri: a.url }), this.createVideoElement(a), this.setupFocusManagement(), await this.attemptAutoplay();
|
|
1050
|
+
} catch (i) {
|
|
1051
|
+
const s = i instanceof Error ? this.createError(h.UNDEFINED_ERROR, i.message) : i;
|
|
1071
1052
|
this.handleError(s);
|
|
1072
1053
|
}
|
|
1073
1054
|
}
|
|
@@ -1076,9 +1057,9 @@ class N {
|
|
|
1076
1057
|
*/
|
|
1077
1058
|
getFirstLinearCreative() {
|
|
1078
1059
|
for (const e of this.ads)
|
|
1079
|
-
for (const
|
|
1080
|
-
if (
|
|
1081
|
-
return
|
|
1060
|
+
for (const t of e.creatives)
|
|
1061
|
+
if (t.linear)
|
|
1062
|
+
return t.linear;
|
|
1082
1063
|
return null;
|
|
1083
1064
|
}
|
|
1084
1065
|
/**
|
|
@@ -1086,37 +1067,37 @@ class N {
|
|
|
1086
1067
|
* Applies muted, playsinline, autoplay for maximum TV compatibility
|
|
1087
1068
|
*/
|
|
1088
1069
|
createVideoElement(e) {
|
|
1089
|
-
const
|
|
1090
|
-
Object.entries(
|
|
1091
|
-
typeof a == "boolean" ? a &&
|
|
1092
|
-
}),
|
|
1070
|
+
const t = document.createElement("video"), i = this.platform.getVideoAttributes();
|
|
1071
|
+
Object.entries(i).forEach(([s, a]) => {
|
|
1072
|
+
typeof a == "boolean" ? a && t.setAttribute(s, "") : t.setAttribute(s, a);
|
|
1073
|
+
}), t.src = e.url, t.style.cssText = `
|
|
1093
1074
|
width: 100%;
|
|
1094
1075
|
height: 100%;
|
|
1095
1076
|
object-fit: contain;
|
|
1096
1077
|
background: #000;
|
|
1097
|
-
`,
|
|
1078
|
+
`, t.addEventListener("loadedmetadata", () => {
|
|
1098
1079
|
this.updateState({
|
|
1099
|
-
duration:
|
|
1080
|
+
duration: t.duration,
|
|
1100
1081
|
status: d.Ready
|
|
1101
1082
|
}), this.emit({ type: "loaded" });
|
|
1102
|
-
}),
|
|
1103
|
-
this.handleTimeUpdate(
|
|
1104
|
-
}),
|
|
1083
|
+
}), t.addEventListener("timeupdate", () => {
|
|
1084
|
+
this.handleTimeUpdate(t);
|
|
1085
|
+
}), t.addEventListener("ended", () => {
|
|
1105
1086
|
this.handleComplete();
|
|
1106
|
-
}),
|
|
1107
|
-
const s =
|
|
1087
|
+
}), t.addEventListener("error", () => {
|
|
1088
|
+
const s = t.error;
|
|
1108
1089
|
this.handleError(
|
|
1109
1090
|
this.createError(
|
|
1110
|
-
|
|
1091
|
+
h.MEDIA_NOT_SUPPORTED,
|
|
1111
1092
|
(s == null ? void 0 : s.message) || "Video playback error"
|
|
1112
1093
|
)
|
|
1113
1094
|
);
|
|
1114
|
-
}),
|
|
1095
|
+
}), t.addEventListener("play", () => {
|
|
1115
1096
|
this.updateState({ status: d.Playing });
|
|
1116
|
-
}),
|
|
1097
|
+
}), t.addEventListener("pause", () => {
|
|
1117
1098
|
var s;
|
|
1118
1099
|
this.state.status !== d.Completed && (this.updateState({ status: d.Paused }), this.emit({ type: "pause" }), (s = this.tracker) == null || s.track("pause"));
|
|
1119
|
-
}), this.config.container.appendChild(
|
|
1100
|
+
}), this.config.container.appendChild(t), this.videoElement = t, this.log(`Video element created with src: ${e.url}`);
|
|
1120
1101
|
}
|
|
1121
1102
|
/**
|
|
1122
1103
|
* Attempt autoplay with soft-fail handling
|
|
@@ -1166,8 +1147,8 @@ class N {
|
|
|
1166
1147
|
</button>
|
|
1167
1148
|
</div>
|
|
1168
1149
|
`, e.style.cssText = "position: absolute; top: 0; left: 0; width: 100%; height: 100%;";
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1150
|
+
const t = e.querySelector("#adgent-start-btn");
|
|
1151
|
+
t == null || t.addEventListener("click", () => this.onStartClick()), this.config.container.style.position = "relative", this.config.container.appendChild(e), this.overlayElement = e, t == null || t.focus();
|
|
1171
1152
|
}
|
|
1172
1153
|
/**
|
|
1173
1154
|
* Handle start button click (from overlay)
|
|
@@ -1179,7 +1160,7 @@ class N {
|
|
|
1179
1160
|
} catch (e) {
|
|
1180
1161
|
this.handleError(
|
|
1181
1162
|
this.createError(
|
|
1182
|
-
|
|
1163
|
+
h.GENERAL_LINEAR_ERROR,
|
|
1183
1164
|
`Playback failed: ${e}`
|
|
1184
1165
|
)
|
|
1185
1166
|
);
|
|
@@ -1195,30 +1176,30 @@ class N {
|
|
|
1195
1176
|
* Handle successful playback start
|
|
1196
1177
|
*/
|
|
1197
1178
|
handlePlaybackStart() {
|
|
1198
|
-
var
|
|
1199
|
-
this.updateState({ status: d.Playing }), this.emit({ type: "start" }), (t = (
|
|
1200
|
-
const
|
|
1201
|
-
(
|
|
1179
|
+
var e, t, i, s, a;
|
|
1180
|
+
this.updateState({ status: d.Playing }), this.emit({ type: "start" }), (t = (e = this.config).onStart) == null || t.call(e);
|
|
1181
|
+
const n = this.parser.aggregateImpressions(this.ads);
|
|
1182
|
+
(i = this.tracker) == null || i.fireImpressions(n), (s = this.tracker) == null || s.track("start"), (a = this.tracker) == null || a.track("creativeView"), this.setupSkipButton(), this.log("Playback started");
|
|
1202
1183
|
}
|
|
1203
1184
|
/**
|
|
1204
1185
|
* Handle time updates for progress tracking
|
|
1205
1186
|
*/
|
|
1206
1187
|
handleTimeUpdate(e) {
|
|
1207
|
-
var
|
|
1208
|
-
const
|
|
1209
|
-
if (!
|
|
1210
|
-
const
|
|
1188
|
+
var t, i, s;
|
|
1189
|
+
const a = e.currentTime, n = e.duration;
|
|
1190
|
+
if (!n || isNaN(n)) return;
|
|
1191
|
+
const u = a / n * 100, m = this.calculateQuartile(u);
|
|
1211
1192
|
this.updateState({
|
|
1212
|
-
currentTime:
|
|
1213
|
-
duration:
|
|
1214
|
-
}), this.updateSkipCountdown(
|
|
1215
|
-
const
|
|
1216
|
-
currentTime:
|
|
1217
|
-
duration:
|
|
1218
|
-
percentage:
|
|
1219
|
-
quartile:
|
|
1193
|
+
currentTime: a,
|
|
1194
|
+
duration: n
|
|
1195
|
+
}), this.updateSkipCountdown(a), (t = this.tracker) == null || t.updateMacroContext({ adPlayhead: a });
|
|
1196
|
+
const f = {
|
|
1197
|
+
currentTime: a,
|
|
1198
|
+
duration: n,
|
|
1199
|
+
percentage: u,
|
|
1200
|
+
quartile: m
|
|
1220
1201
|
};
|
|
1221
|
-
this.emit({ type: "progress", data:
|
|
1202
|
+
this.emit({ type: "progress", data: f }), (s = (i = this.config).onProgress) == null || s.call(i, f), this.fireQuartileEvents(u);
|
|
1222
1203
|
}
|
|
1223
1204
|
/**
|
|
1224
1205
|
* Calculate current quartile (0-4)
|
|
@@ -1231,24 +1212,25 @@ class N {
|
|
|
1231
1212
|
*/
|
|
1232
1213
|
fireQuartileEvents(e) {
|
|
1233
1214
|
var t;
|
|
1234
|
-
const
|
|
1215
|
+
const i = [
|
|
1235
1216
|
{ threshold: 25, event: "firstQuartile" },
|
|
1236
1217
|
{ threshold: 50, event: "midpoint" },
|
|
1237
1218
|
{ threshold: 75, event: "thirdQuartile" }
|
|
1238
1219
|
];
|
|
1239
|
-
for (const { threshold: s, event: a } of
|
|
1220
|
+
for (const { threshold: s, event: a } of i)
|
|
1240
1221
|
e >= s && !this.quartilesFired.has(s) && (this.quartilesFired.add(s), (t = this.tracker) == null || t.track(a), this.emit({ type: "quartile", data: { quartile: a } }), this.log(`Quartile fired: ${a}`));
|
|
1241
1222
|
}
|
|
1242
1223
|
/**
|
|
1243
1224
|
* Set up skip button
|
|
1244
1225
|
*/
|
|
1245
1226
|
setupSkipButton() {
|
|
1246
|
-
|
|
1247
|
-
|
|
1227
|
+
var e;
|
|
1228
|
+
const t = this.getFirstLinearCreative(), i = (e = this.config.skipOffset) != null ? e : t == null ? void 0 : t.skipOffset;
|
|
1229
|
+
if (!i || i <= 0)
|
|
1248
1230
|
return;
|
|
1249
|
-
this.updateState({ skipCountdown:
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1231
|
+
this.updateState({ skipCountdown: i, canSkip: !1 });
|
|
1232
|
+
const s = document.createElement("button");
|
|
1233
|
+
s.id = "adgent-skip-btn", s.style.cssText = `
|
|
1252
1234
|
position: absolute;
|
|
1253
1235
|
bottom: 20px;
|
|
1254
1236
|
right: 20px;
|
|
@@ -1261,63 +1243,64 @@ class N {
|
|
|
1261
1243
|
cursor: pointer;
|
|
1262
1244
|
z-index: 101;
|
|
1263
1245
|
transition: opacity 0.3s;
|
|
1264
|
-
`,
|
|
1246
|
+
`, s.textContent = `Skip in ${i}s`, s.addEventListener("click", () => this.skip()), this.config.container.appendChild(s), this.skipButtonElement = s;
|
|
1265
1247
|
}
|
|
1266
1248
|
/**
|
|
1267
1249
|
* Update skip countdown
|
|
1268
1250
|
*/
|
|
1269
1251
|
updateSkipCountdown(e) {
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1252
|
+
var t;
|
|
1253
|
+
const i = this.getFirstLinearCreative(), s = (t = this.config.skipOffset) != null ? t : i == null ? void 0 : i.skipOffset;
|
|
1254
|
+
if (!s || !this.skipButtonElement) return;
|
|
1255
|
+
const a = Math.max(0, s - e);
|
|
1256
|
+
this.updateState({ skipCountdown: a }), a <= 0 && !this.state.canSkip ? (this.updateState({ canSkip: !0 }), this.skipButtonElement.textContent = this.config.skipButtonText, this.skipButtonElement.style.opacity = "1") : a > 0 && (this.skipButtonElement.textContent = `Skip in ${Math.ceil(a)}s`, this.skipButtonElement.style.opacity = "0.6");
|
|
1274
1257
|
}
|
|
1275
1258
|
/**
|
|
1276
1259
|
* Skip the ad
|
|
1277
1260
|
*/
|
|
1278
1261
|
skip() {
|
|
1279
|
-
var e,
|
|
1262
|
+
var e, t, i;
|
|
1280
1263
|
if (!this.state.canSkip) {
|
|
1281
1264
|
this.log("Skip not available yet");
|
|
1282
1265
|
return;
|
|
1283
1266
|
}
|
|
1284
|
-
(e = this.tracker) == null || e.track("skip"), this.emit({ type: "skip" }), (
|
|
1267
|
+
(e = this.tracker) == null || e.track("skip"), this.emit({ type: "skip" }), (i = (t = this.config).onSkip) == null || i.call(t), this.destroy(), this.log("Ad skipped");
|
|
1285
1268
|
}
|
|
1286
1269
|
/**
|
|
1287
1270
|
* Handle ad completion
|
|
1288
1271
|
*/
|
|
1289
1272
|
handleComplete() {
|
|
1290
|
-
var e,
|
|
1291
|
-
this.updateState({ status: d.Completed }), (e = this.tracker) == null || e.track("complete"), this.emit({ type: "complete" }), (
|
|
1273
|
+
var e, t, i;
|
|
1274
|
+
this.updateState({ status: d.Completed }), (e = this.tracker) == null || e.track("complete"), this.emit({ type: "complete" }), (i = (t = this.config).onComplete) == null || i.call(t), this.log("Ad completed");
|
|
1292
1275
|
}
|
|
1293
1276
|
/**
|
|
1294
1277
|
* Handle errors with recovery attempt or callback
|
|
1295
1278
|
*/
|
|
1296
1279
|
handleError(e) {
|
|
1297
|
-
var t,
|
|
1280
|
+
var t, i, s;
|
|
1298
1281
|
this.updateState({
|
|
1299
1282
|
status: d.Error,
|
|
1300
1283
|
error: e
|
|
1301
1284
|
});
|
|
1302
|
-
const
|
|
1285
|
+
const a = [];
|
|
1303
1286
|
for (const n of this.ads)
|
|
1304
|
-
|
|
1305
|
-
(t = this.tracker) == null || t.fireError(
|
|
1287
|
+
a.push(...n.errors);
|
|
1288
|
+
(t = this.tracker) == null || t.fireError(a, e.code), this.emit({ type: "error", data: e }), (s = (i = this.config).onError) == null || s.call(i, e), this.log(`Error: ${e.message}`);
|
|
1306
1289
|
}
|
|
1307
1290
|
/**
|
|
1308
1291
|
* Set up focus management to capture remote keys
|
|
1309
1292
|
*/
|
|
1310
1293
|
setupFocusManagement() {
|
|
1311
1294
|
this.focusTrap = document.createElement("div"), this.focusTrap.tabIndex = 0, this.focusTrap.style.cssText = "position: absolute; opacity: 0; width: 0; height: 0;", this.config.container.appendChild(this.focusTrap), this.focusTrap.focus(), this.boundKeyHandler = (e) => {
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1295
|
+
const t = this.platform.normalizeKeyCode(e.keyCode);
|
|
1296
|
+
t && (e.preventDefault(), e.stopPropagation(), this.handleKeyAction(t));
|
|
1314
1297
|
}, document.addEventListener("keydown", this.boundKeyHandler, !0);
|
|
1315
1298
|
}
|
|
1316
1299
|
/**
|
|
1317
1300
|
* Handle key actions from remote control
|
|
1318
1301
|
*/
|
|
1319
1302
|
handleKeyAction(e) {
|
|
1320
|
-
var
|
|
1303
|
+
var t, i;
|
|
1321
1304
|
switch (this.log(`Key action: ${e}`), e) {
|
|
1322
1305
|
case c.Enter:
|
|
1323
1306
|
this.state.status === d.WaitingForInteraction ? this.onStartClick() : this.state.canSkip && this.skip();
|
|
@@ -1326,10 +1309,10 @@ class N {
|
|
|
1326
1309
|
this.log("Back pressed - ignoring during ad");
|
|
1327
1310
|
break;
|
|
1328
1311
|
case c.Play:
|
|
1329
|
-
(
|
|
1312
|
+
(t = this.videoElement) == null || t.play();
|
|
1330
1313
|
break;
|
|
1331
1314
|
case c.Pause:
|
|
1332
|
-
(
|
|
1315
|
+
(i = this.videoElement) == null || i.pause();
|
|
1333
1316
|
break;
|
|
1334
1317
|
case c.Left:
|
|
1335
1318
|
case c.Right:
|
|
@@ -1368,8 +1351,8 @@ class N {
|
|
|
1368
1351
|
* Clean up all resources
|
|
1369
1352
|
*/
|
|
1370
1353
|
destroy() {
|
|
1371
|
-
var e,
|
|
1372
|
-
this.boundKeyHandler && (document.removeEventListener("keydown", this.boundKeyHandler, !0), this.boundKeyHandler = null), (e = this.videoElement) == null || e.remove(), (
|
|
1354
|
+
var e, t, i, s, a;
|
|
1355
|
+
this.boundKeyHandler && (document.removeEventListener("keydown", this.boundKeyHandler, !0), this.boundKeyHandler = null), (e = this.videoElement) == null || e.remove(), (t = this.overlayElement) == null || t.remove(), (i = this.skipButtonElement) == null || i.remove(), (s = this.focusTrap) == null || s.remove(), this.videoElement = null, this.overlayElement = null, this.skipButtonElement = null, this.focusTrap = null, (a = this.tracker) == null || a.reset(), this.quartilesFired.clear(), this.listeners.clear(), this.ads = [], this.emit({ type: "destroy" }), this.log("Player destroyed");
|
|
1373
1356
|
}
|
|
1374
1357
|
/**
|
|
1375
1358
|
* Update internal state
|
|
@@ -1381,18 +1364,18 @@ class N {
|
|
|
1381
1364
|
* Emit event to listeners
|
|
1382
1365
|
*/
|
|
1383
1366
|
emit(e) {
|
|
1384
|
-
for (const
|
|
1367
|
+
for (const t of this.listeners)
|
|
1385
1368
|
try {
|
|
1386
|
-
|
|
1387
|
-
} catch (
|
|
1388
|
-
this.log(`Listener error: ${
|
|
1369
|
+
t(e);
|
|
1370
|
+
} catch (i) {
|
|
1371
|
+
this.log(`Listener error: ${i}`);
|
|
1389
1372
|
}
|
|
1390
1373
|
}
|
|
1391
1374
|
/**
|
|
1392
1375
|
* Create error object
|
|
1393
1376
|
*/
|
|
1394
|
-
createError(e,
|
|
1395
|
-
return { code: e, message:
|
|
1377
|
+
createError(e, t, i = !1) {
|
|
1378
|
+
return { code: e, message: t, recoverable: i };
|
|
1396
1379
|
}
|
|
1397
1380
|
/**
|
|
1398
1381
|
* Debug logging
|
|
@@ -1402,17 +1385,17 @@ class N {
|
|
|
1402
1385
|
}
|
|
1403
1386
|
}
|
|
1404
1387
|
export {
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1388
|
+
$ as AdPlayer,
|
|
1389
|
+
L as AdTracker,
|
|
1390
|
+
$ as AdgentSDK,
|
|
1391
|
+
I as DEFAULT_KEY_CODES,
|
|
1409
1392
|
c as KeyAction,
|
|
1410
|
-
|
|
1393
|
+
x as PLATFORM_DETECTION_PATTERNS,
|
|
1411
1394
|
o as Platform,
|
|
1412
|
-
|
|
1395
|
+
F as PlatformAdapter,
|
|
1413
1396
|
d as PlaybackStatus,
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1397
|
+
h as VASTErrorCode,
|
|
1398
|
+
O as VASTParser,
|
|
1399
|
+
_ as getPlatformAdapter,
|
|
1400
|
+
g as replaceMacros
|
|
1418
1401
|
};
|