adgent-sdk 0.1.1 → 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 -311
- 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,31 +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
|
-
if (this.config = { ...I, ...e }, !this.config.container)
|
|
1016
|
-
throw new Error("Container element is required");
|
|
1017
|
-
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({
|
|
1018
997
|
maxWrapperDepth: this.config.maxWrapperDepth,
|
|
1019
998
|
timeout: this.config.timeout,
|
|
1020
999
|
debug: this.config.debug
|
|
@@ -1034,26 +1013,26 @@ class N {
|
|
|
1034
1013
|
* Initialize the SDK: fetch VAST, create video element, attempt autoplay
|
|
1035
1014
|
*/
|
|
1036
1015
|
async init() {
|
|
1037
|
-
var e,
|
|
1016
|
+
var e, t;
|
|
1038
1017
|
if (!this.config.container)
|
|
1039
1018
|
throw new Error("Container element not found");
|
|
1040
1019
|
this.updateState({ status: d.Loading });
|
|
1041
1020
|
try {
|
|
1042
|
-
const
|
|
1043
|
-
if (!
|
|
1021
|
+
const i = await this.parser.parse(this.config.vastUrl);
|
|
1022
|
+
if (!i.success || !i.response)
|
|
1044
1023
|
throw this.createError(
|
|
1045
|
-
((e =
|
|
1046
|
-
((
|
|
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"
|
|
1047
1026
|
);
|
|
1048
|
-
if (this.ads =
|
|
1027
|
+
if (this.ads = i.response.ads, this.ads.length === 0)
|
|
1049
1028
|
throw this.createError(
|
|
1050
|
-
|
|
1029
|
+
h.NO_VAST_RESPONSE,
|
|
1051
1030
|
"No ads in VAST response"
|
|
1052
1031
|
);
|
|
1053
1032
|
const s = this.getFirstLinearCreative();
|
|
1054
1033
|
if (!s)
|
|
1055
1034
|
throw this.createError(
|
|
1056
|
-
|
|
1035
|
+
h.GENERAL_LINEAR_ERROR,
|
|
1057
1036
|
"No linear creative found"
|
|
1058
1037
|
);
|
|
1059
1038
|
const a = this.parser.selectBestMediaFile(
|
|
@@ -1062,14 +1041,14 @@ class N {
|
|
|
1062
1041
|
);
|
|
1063
1042
|
if (!a)
|
|
1064
1043
|
throw this.createError(
|
|
1065
|
-
|
|
1044
|
+
h.FILE_NOT_FOUND,
|
|
1066
1045
|
"No suitable media file found"
|
|
1067
1046
|
);
|
|
1068
1047
|
this.updateState({ mediaFile: a });
|
|
1069
1048
|
const n = this.parser.aggregateTrackingEvents(this.ads);
|
|
1070
|
-
this.tracker = new
|
|
1071
|
-
} catch (
|
|
1072
|
-
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;
|
|
1073
1052
|
this.handleError(s);
|
|
1074
1053
|
}
|
|
1075
1054
|
}
|
|
@@ -1078,9 +1057,9 @@ class N {
|
|
|
1078
1057
|
*/
|
|
1079
1058
|
getFirstLinearCreative() {
|
|
1080
1059
|
for (const e of this.ads)
|
|
1081
|
-
for (const
|
|
1082
|
-
if (
|
|
1083
|
-
return
|
|
1060
|
+
for (const t of e.creatives)
|
|
1061
|
+
if (t.linear)
|
|
1062
|
+
return t.linear;
|
|
1084
1063
|
return null;
|
|
1085
1064
|
}
|
|
1086
1065
|
/**
|
|
@@ -1088,37 +1067,37 @@ class N {
|
|
|
1088
1067
|
* Applies muted, playsinline, autoplay for maximum TV compatibility
|
|
1089
1068
|
*/
|
|
1090
1069
|
createVideoElement(e) {
|
|
1091
|
-
const
|
|
1092
|
-
Object.entries(
|
|
1093
|
-
typeof a == "boolean" ? a &&
|
|
1094
|
-
}),
|
|
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 = `
|
|
1095
1074
|
width: 100%;
|
|
1096
1075
|
height: 100%;
|
|
1097
1076
|
object-fit: contain;
|
|
1098
1077
|
background: #000;
|
|
1099
|
-
`,
|
|
1078
|
+
`, t.addEventListener("loadedmetadata", () => {
|
|
1100
1079
|
this.updateState({
|
|
1101
|
-
duration:
|
|
1080
|
+
duration: t.duration,
|
|
1102
1081
|
status: d.Ready
|
|
1103
1082
|
}), this.emit({ type: "loaded" });
|
|
1104
|
-
}),
|
|
1105
|
-
this.handleTimeUpdate(
|
|
1106
|
-
}),
|
|
1083
|
+
}), t.addEventListener("timeupdate", () => {
|
|
1084
|
+
this.handleTimeUpdate(t);
|
|
1085
|
+
}), t.addEventListener("ended", () => {
|
|
1107
1086
|
this.handleComplete();
|
|
1108
|
-
}),
|
|
1109
|
-
const s =
|
|
1087
|
+
}), t.addEventListener("error", () => {
|
|
1088
|
+
const s = t.error;
|
|
1110
1089
|
this.handleError(
|
|
1111
1090
|
this.createError(
|
|
1112
|
-
|
|
1091
|
+
h.MEDIA_NOT_SUPPORTED,
|
|
1113
1092
|
(s == null ? void 0 : s.message) || "Video playback error"
|
|
1114
1093
|
)
|
|
1115
1094
|
);
|
|
1116
|
-
}),
|
|
1095
|
+
}), t.addEventListener("play", () => {
|
|
1117
1096
|
this.updateState({ status: d.Playing });
|
|
1118
|
-
}),
|
|
1097
|
+
}), t.addEventListener("pause", () => {
|
|
1119
1098
|
var s;
|
|
1120
1099
|
this.state.status !== d.Completed && (this.updateState({ status: d.Paused }), this.emit({ type: "pause" }), (s = this.tracker) == null || s.track("pause"));
|
|
1121
|
-
}), this.config.container.appendChild(
|
|
1100
|
+
}), this.config.container.appendChild(t), this.videoElement = t, this.log(`Video element created with src: ${e.url}`);
|
|
1122
1101
|
}
|
|
1123
1102
|
/**
|
|
1124
1103
|
* Attempt autoplay with soft-fail handling
|
|
@@ -1168,8 +1147,8 @@ class N {
|
|
|
1168
1147
|
</button>
|
|
1169
1148
|
</div>
|
|
1170
1149
|
`, e.style.cssText = "position: absolute; top: 0; left: 0; width: 100%; height: 100%;";
|
|
1171
|
-
const
|
|
1172
|
-
|
|
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();
|
|
1173
1152
|
}
|
|
1174
1153
|
/**
|
|
1175
1154
|
* Handle start button click (from overlay)
|
|
@@ -1181,7 +1160,7 @@ class N {
|
|
|
1181
1160
|
} catch (e) {
|
|
1182
1161
|
this.handleError(
|
|
1183
1162
|
this.createError(
|
|
1184
|
-
|
|
1163
|
+
h.GENERAL_LINEAR_ERROR,
|
|
1185
1164
|
`Playback failed: ${e}`
|
|
1186
1165
|
)
|
|
1187
1166
|
);
|
|
@@ -1197,30 +1176,30 @@ class N {
|
|
|
1197
1176
|
* Handle successful playback start
|
|
1198
1177
|
*/
|
|
1199
1178
|
handlePlaybackStart() {
|
|
1200
|
-
var
|
|
1201
|
-
this.updateState({ status: d.Playing }), this.emit({ type: "start" }), (t = (
|
|
1202
|
-
const
|
|
1203
|
-
(
|
|
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");
|
|
1204
1183
|
}
|
|
1205
1184
|
/**
|
|
1206
1185
|
* Handle time updates for progress tracking
|
|
1207
1186
|
*/
|
|
1208
1187
|
handleTimeUpdate(e) {
|
|
1209
|
-
var
|
|
1210
|
-
const
|
|
1211
|
-
if (!
|
|
1212
|
-
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);
|
|
1213
1192
|
this.updateState({
|
|
1214
|
-
currentTime:
|
|
1215
|
-
duration:
|
|
1216
|
-
}), this.updateSkipCountdown(
|
|
1217
|
-
const
|
|
1218
|
-
currentTime:
|
|
1219
|
-
duration:
|
|
1220
|
-
percentage:
|
|
1221
|
-
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
|
|
1222
1201
|
};
|
|
1223
|
-
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);
|
|
1224
1203
|
}
|
|
1225
1204
|
/**
|
|
1226
1205
|
* Calculate current quartile (0-4)
|
|
@@ -1233,24 +1212,25 @@ class N {
|
|
|
1233
1212
|
*/
|
|
1234
1213
|
fireQuartileEvents(e) {
|
|
1235
1214
|
var t;
|
|
1236
|
-
const
|
|
1215
|
+
const i = [
|
|
1237
1216
|
{ threshold: 25, event: "firstQuartile" },
|
|
1238
1217
|
{ threshold: 50, event: "midpoint" },
|
|
1239
1218
|
{ threshold: 75, event: "thirdQuartile" }
|
|
1240
1219
|
];
|
|
1241
|
-
for (const { threshold: s, event: a } of
|
|
1220
|
+
for (const { threshold: s, event: a } of i)
|
|
1242
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}`));
|
|
1243
1222
|
}
|
|
1244
1223
|
/**
|
|
1245
1224
|
* Set up skip button
|
|
1246
1225
|
*/
|
|
1247
1226
|
setupSkipButton() {
|
|
1248
|
-
|
|
1249
|
-
|
|
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)
|
|
1250
1230
|
return;
|
|
1251
|
-
this.updateState({ skipCountdown:
|
|
1252
|
-
const
|
|
1253
|
-
|
|
1231
|
+
this.updateState({ skipCountdown: i, canSkip: !1 });
|
|
1232
|
+
const s = document.createElement("button");
|
|
1233
|
+
s.id = "adgent-skip-btn", s.style.cssText = `
|
|
1254
1234
|
position: absolute;
|
|
1255
1235
|
bottom: 20px;
|
|
1256
1236
|
right: 20px;
|
|
@@ -1263,63 +1243,64 @@ class N {
|
|
|
1263
1243
|
cursor: pointer;
|
|
1264
1244
|
z-index: 101;
|
|
1265
1245
|
transition: opacity 0.3s;
|
|
1266
|
-
`,
|
|
1246
|
+
`, s.textContent = `Skip in ${i}s`, s.addEventListener("click", () => this.skip()), this.config.container.appendChild(s), this.skipButtonElement = s;
|
|
1267
1247
|
}
|
|
1268
1248
|
/**
|
|
1269
1249
|
* Update skip countdown
|
|
1270
1250
|
*/
|
|
1271
1251
|
updateSkipCountdown(e) {
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
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");
|
|
1276
1257
|
}
|
|
1277
1258
|
/**
|
|
1278
1259
|
* Skip the ad
|
|
1279
1260
|
*/
|
|
1280
1261
|
skip() {
|
|
1281
|
-
var e,
|
|
1262
|
+
var e, t, i;
|
|
1282
1263
|
if (!this.state.canSkip) {
|
|
1283
1264
|
this.log("Skip not available yet");
|
|
1284
1265
|
return;
|
|
1285
1266
|
}
|
|
1286
|
-
(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");
|
|
1287
1268
|
}
|
|
1288
1269
|
/**
|
|
1289
1270
|
* Handle ad completion
|
|
1290
1271
|
*/
|
|
1291
1272
|
handleComplete() {
|
|
1292
|
-
var e,
|
|
1293
|
-
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");
|
|
1294
1275
|
}
|
|
1295
1276
|
/**
|
|
1296
1277
|
* Handle errors with recovery attempt or callback
|
|
1297
1278
|
*/
|
|
1298
1279
|
handleError(e) {
|
|
1299
|
-
var t,
|
|
1280
|
+
var t, i, s;
|
|
1300
1281
|
this.updateState({
|
|
1301
1282
|
status: d.Error,
|
|
1302
1283
|
error: e
|
|
1303
1284
|
});
|
|
1304
|
-
const
|
|
1285
|
+
const a = [];
|
|
1305
1286
|
for (const n of this.ads)
|
|
1306
|
-
|
|
1307
|
-
(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}`);
|
|
1308
1289
|
}
|
|
1309
1290
|
/**
|
|
1310
1291
|
* Set up focus management to capture remote keys
|
|
1311
1292
|
*/
|
|
1312
1293
|
setupFocusManagement() {
|
|
1313
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) => {
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1295
|
+
const t = this.platform.normalizeKeyCode(e.keyCode);
|
|
1296
|
+
t && (e.preventDefault(), e.stopPropagation(), this.handleKeyAction(t));
|
|
1316
1297
|
}, document.addEventListener("keydown", this.boundKeyHandler, !0);
|
|
1317
1298
|
}
|
|
1318
1299
|
/**
|
|
1319
1300
|
* Handle key actions from remote control
|
|
1320
1301
|
*/
|
|
1321
1302
|
handleKeyAction(e) {
|
|
1322
|
-
var
|
|
1303
|
+
var t, i;
|
|
1323
1304
|
switch (this.log(`Key action: ${e}`), e) {
|
|
1324
1305
|
case c.Enter:
|
|
1325
1306
|
this.state.status === d.WaitingForInteraction ? this.onStartClick() : this.state.canSkip && this.skip();
|
|
@@ -1328,10 +1309,10 @@ class N {
|
|
|
1328
1309
|
this.log("Back pressed - ignoring during ad");
|
|
1329
1310
|
break;
|
|
1330
1311
|
case c.Play:
|
|
1331
|
-
(
|
|
1312
|
+
(t = this.videoElement) == null || t.play();
|
|
1332
1313
|
break;
|
|
1333
1314
|
case c.Pause:
|
|
1334
|
-
(
|
|
1315
|
+
(i = this.videoElement) == null || i.pause();
|
|
1335
1316
|
break;
|
|
1336
1317
|
case c.Left:
|
|
1337
1318
|
case c.Right:
|
|
@@ -1370,8 +1351,8 @@ class N {
|
|
|
1370
1351
|
* Clean up all resources
|
|
1371
1352
|
*/
|
|
1372
1353
|
destroy() {
|
|
1373
|
-
var e,
|
|
1374
|
-
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");
|
|
1375
1356
|
}
|
|
1376
1357
|
/**
|
|
1377
1358
|
* Update internal state
|
|
@@ -1383,18 +1364,18 @@ class N {
|
|
|
1383
1364
|
* Emit event to listeners
|
|
1384
1365
|
*/
|
|
1385
1366
|
emit(e) {
|
|
1386
|
-
for (const
|
|
1367
|
+
for (const t of this.listeners)
|
|
1387
1368
|
try {
|
|
1388
|
-
|
|
1389
|
-
} catch (
|
|
1390
|
-
this.log(`Listener error: ${
|
|
1369
|
+
t(e);
|
|
1370
|
+
} catch (i) {
|
|
1371
|
+
this.log(`Listener error: ${i}`);
|
|
1391
1372
|
}
|
|
1392
1373
|
}
|
|
1393
1374
|
/**
|
|
1394
1375
|
* Create error object
|
|
1395
1376
|
*/
|
|
1396
|
-
createError(e,
|
|
1397
|
-
return { code: e, message:
|
|
1377
|
+
createError(e, t, i = !1) {
|
|
1378
|
+
return { code: e, message: t, recoverable: i };
|
|
1398
1379
|
}
|
|
1399
1380
|
/**
|
|
1400
1381
|
* Debug logging
|
|
@@ -1404,17 +1385,17 @@ class N {
|
|
|
1404
1385
|
}
|
|
1405
1386
|
}
|
|
1406
1387
|
export {
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1388
|
+
$ as AdPlayer,
|
|
1389
|
+
L as AdTracker,
|
|
1390
|
+
$ as AdgentSDK,
|
|
1391
|
+
I as DEFAULT_KEY_CODES,
|
|
1411
1392
|
c as KeyAction,
|
|
1412
|
-
|
|
1393
|
+
x as PLATFORM_DETECTION_PATTERNS,
|
|
1413
1394
|
o as Platform,
|
|
1414
|
-
|
|
1395
|
+
F as PlatformAdapter,
|
|
1415
1396
|
d as PlaybackStatus,
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1397
|
+
h as VASTErrorCode,
|
|
1398
|
+
O as VASTParser,
|
|
1399
|
+
_ as getPlatformAdapter,
|
|
1400
|
+
g as replaceMacros
|
|
1420
1401
|
};
|