@kalamba/sdk 0.1.0

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.
@@ -0,0 +1,2563 @@
1
+ /**
2
+ * BSD 3-Clause License
3
+ * Copyright (c) 2024, Kalamba Games Limited
4
+ */
5
+ var Gt = Object.defineProperty;
6
+ var Nt = (i, t, e) => t in i ? Gt(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
7
+ var w = (i, t, e) => (Nt(i, typeof t != "symbol" ? t + "" : t, e), e), at = (i, t, e) => {
8
+ if (!t.has(i))
9
+ throw TypeError("Cannot " + e);
10
+ };
11
+ var y = (i, t, e) => (at(i, t, "read from private field"), e ? e.call(i) : t.get(i)), v = (i, t, e) => {
12
+ if (t.has(i))
13
+ throw TypeError("Cannot add the same private member more than once");
14
+ t instanceof WeakSet ? t.add(i) : t.set(i, e);
15
+ }, E = (i, t, e, s) => (at(i, t, "write to private field"), s ? s.call(i, e) : t.set(i, e), e);
16
+ import { a as ot } from "./noop-3336849b.js";
17
+ function U(i, t) {
18
+ return (e, ...s) => {
19
+ console.log(`[%c${i}\x1B[m] %s`, t, e, ...s);
20
+ };
21
+ }
22
+ function Ut(i, t) {
23
+ return Math.round(i * 100 / t);
24
+ }
25
+ class $ {
26
+ constructor(t) {
27
+ w(this, "config");
28
+ this.config = t;
29
+ }
30
+ on(t, e, s) {
31
+ const n = function(a) {
32
+ a.data.message !== `kalamba:wrapper-casino:${t}` && a.data.message !== `kalamba:wrapper:${t}` || e(a.data.payload);
33
+ };
34
+ window.addEventListener("message", n, s);
35
+ }
36
+ send(t, ...[e]) {
37
+ window.postMessage({
38
+ message: `kalamba:casino:${t}`,
39
+ payload: e
40
+ });
41
+ }
42
+ }
43
+ const Ht = U("BasicPlugin", "color:#000000;font-weight:bold;");
44
+ class Pi extends $ {
45
+ constructor(...t) {
46
+ super(...t), this.registerToSdkEvents(), this.registerFromSdkEvents(), Ht("configured");
47
+ }
48
+ registerToSdkEvents() {
49
+ window.addEventListener("message", (t) => {
50
+ try {
51
+ const { type: e, payload: s } = t.data;
52
+ switch (e) {
53
+ case "doAudioSettings":
54
+ this.send("settings", { music: s == null ? void 0 : s.musicEnabled, sounds: s == null ? void 0 : s.soundEnabled });
55
+ return;
56
+ case "doBalanceUpdate":
57
+ const { currency: n, coinValueInCents: l } = this.config.api;
58
+ s.currency === n && typeof s.balanceInCurrency == "number" ? this.send("balance", { balance: Ut(s.balanceInCurrency, l) }) : (s.balanceInCoins, this.send("balance", { balance: s.balanceInCoins }));
59
+ return;
60
+ case "doGamePause":
61
+ this.send("freeze");
62
+ return;
63
+ case "doGameResume":
64
+ this.send("unfreeze");
65
+ return;
66
+ case "doGameSuspend":
67
+ this.send("suspend");
68
+ return;
69
+ default:
70
+ return;
71
+ }
72
+ } catch {
73
+ }
74
+ });
75
+ }
76
+ registerFromSdkEvents() {
77
+ this.on("close", () => {
78
+ if (this.config.api.homeUrl)
79
+ try {
80
+ window.top.location = this.config.api.homeUrl;
81
+ } catch {
82
+ window.location = this.config.api.homeUrl;
83
+ }
84
+ else
85
+ try {
86
+ window.top.history.back();
87
+ } catch {
88
+ window.history.back();
89
+ }
90
+ });
91
+ }
92
+ }
93
+ const k = U("▼ DebuggingPlugin IN ▼", "color:#444444;font-weight:bold;"), zt = U("▲ DebuggingPlugin OUT ▲", "color:#444444;font-weight:bold;");
94
+ class Ui extends $ {
95
+ constructor(...t) {
96
+ super(...t), this.registerDebugToSdkEvents(), this.registerSdkToDebugEvents();
97
+ }
98
+ // TODO add types
99
+ registerDebugToSdkEvents() {
100
+ window.DebuggingPlugin = {
101
+ balance: (t) => this._send("balance", t),
102
+ bet: (t) => this._send("bet", t),
103
+ choice: (t) => this._send("choice", t),
104
+ close: (t) => this._send("close", t),
105
+ help: (t) => this._send("help", t),
106
+ history: (t) => this._send("history", t),
107
+ freeze: (t) => this._send("freeze", t),
108
+ paytable: (t) => this._send("paytable", t),
109
+ settings: (t) => this._send("settings", t),
110
+ suspend: (t) => this._send("suspend", t),
111
+ unfreeze: (t) => this._send("unfreeze", t)
112
+ };
113
+ }
114
+ registerSdkToDebugEvents() {
115
+ this.on("autoplay", (t) => k("autoplay", t)), this.on("balance", (t) => k("balance", t)), this.on("bet", (t) => k("bet", t)), this.on("cashier", (t) => k("cashier", t)), this.on("choice", (t) => k("choice", t)), this.on("close", (t) => k("close", t)), this.on("error", (t) => k("error", t)), this.on("loadEnd", (t) => k("loadEnd", t)), this.on("loadProgress", (t) => k("loadProgress", t)), this.on("loadStart", (t) => k("loadStart", t)), this.on("playCycleStart", (t) => k("playCycleStart", t)), this.on("playCycleEnd", (t) => k("playCycleEnd", t)), this.on("playEnd", (t) => k("playEnd", t)), this.on("playError", (t) => k("playError", t)), this.on("playReady", (t) => k("playReady", t)), this.on("playStart", (t) => k("playStart", t)), this.on("settings", (t) => k("settings", t));
116
+ }
117
+ _send(...t) {
118
+ zt(...t), this.send(...t);
119
+ }
120
+ }
121
+ const Vt = U("GigPlugin", "color:#000000;font-weight:bold;");
122
+ class xi extends $ {
123
+ constructor(...t) {
124
+ super(...t), this.registerToSdkEvents(), this.registerFromSdkEvents(), Vt("configured");
125
+ }
126
+ postMessage(t) {
127
+ const e = {
128
+ event: t
129
+ };
130
+ window.top.postMessage(e, "*");
131
+ }
132
+ registerToSdkEvents() {
133
+ window.addEventListener("message", (t) => {
134
+ try {
135
+ const { data: e } = t;
136
+ switch (e) {
137
+ case "STOP_AUTO_PLAY":
138
+ this.send("suspend");
139
+ return;
140
+ case "BLOCK_BETS":
141
+ this.send("freeze");
142
+ return;
143
+ case "UNBLOCK_BETS":
144
+ this.send("unfreeze");
145
+ return;
146
+ default:
147
+ return;
148
+ }
149
+ } catch {
150
+ }
151
+ });
152
+ }
153
+ registerFromSdkEvents() {
154
+ this.on("close", () => {
155
+ if (this.config.api.homeUrl)
156
+ try {
157
+ window.top.location = this.config.api.homeUrl;
158
+ } catch {
159
+ window.location = this.config.api.homeUrl;
160
+ }
161
+ else
162
+ try {
163
+ window.top.history.back();
164
+ } catch {
165
+ window.history.back();
166
+ }
167
+ }), this.on("playReady", () => {
168
+ this.postMessage("GAME_READY");
169
+ });
170
+ }
171
+ }
172
+ const qt = U("OryxPlugin", "color:#000000;font-weight:bold;");
173
+ class Oi extends $ {
174
+ constructor(...t) {
175
+ super(...t), this.registerToSdkEvents(), this.registerFromSdkEvents(), qt("configured");
176
+ }
177
+ registerToSdkEvents() {
178
+ window.addEventListener("message", (t) => {
179
+ try {
180
+ const { type: e, param: s } = t.data;
181
+ switch (e) {
182
+ case "doBalanceUpdate":
183
+ this.send("balance", { balance: s });
184
+ return;
185
+ case "doGamePause":
186
+ this.send("freeze");
187
+ return;
188
+ case "doGameResume":
189
+ this.send("unfreeze");
190
+ return;
191
+ case "doGameSuspend":
192
+ this.send("suspend");
193
+ return;
194
+ default:
195
+ return;
196
+ }
197
+ } catch {
198
+ }
199
+ });
200
+ }
201
+ registerFromSdkEvents() {
202
+ let t = 0;
203
+ this.on("close", () => {
204
+ window.top.postMessage({ wpgaction: "close" }, "*"), window.parent.postMessage({ wpgaction: "close.parent" }, "*");
205
+ }), this.on("balance", ({ balance: e }) => {
206
+ t !== e && (t = e, window.top.postMessage({ param: {}, wpgaction: "balance" }, "*"), window.parent.postMessage({ param: {}, wpgaction: "balance.parent" }, "*"));
207
+ }), this.on("loadStart", () => {
208
+ window.top.postMessage({ wpgaction: "loadStart" }, "*"), window.parent.postMessage({ wpgaction: "loadStart.parent" }, "*");
209
+ }), this.on("loadEnd", () => {
210
+ window.top.postMessage({ wpgaction: "loadEnd" }, "*"), window.parent.postMessage({ wpgaction: "loadEnd.parent" }, "*");
211
+ }), this.on("playStart", () => {
212
+ window.top.postMessage({ wpgaction: "gameSpinStart" }, "*"), window.parent.postMessage({ wpgaction: "gameSpinStart.parent" }, "*");
213
+ }), this.on("playEnd", () => {
214
+ window.top.postMessage({ wpgaction: "gameSpinEnd" }, "*"), window.parent.postMessage({ wpgaction: "gameSpinEnd.parent" }, "*");
215
+ }), this.on("cashier", ({ type: e }) => {
216
+ switch (e) {
217
+ case "BALANCE_LOW":
218
+ window.top.postMessage({ wpgaction: "cashier" }, "*"), window.parent.postMessage({ wpgaction: "cashier.parent" }, "*");
219
+ break;
220
+ case "BALANCE_INSUFFICIENT":
221
+ window.top.postMessage({ wpgaction: "errorOutOfMoney" }, "*"), window.parent.postMessage({ wpgaction: "errorOutOfMoney.parent" }, "*");
222
+ break;
223
+ }
224
+ });
225
+ }
226
+ }
227
+ const rt = U("PariplayPlugin", "color:#000000;font-weight:bold;");
228
+ function Ge(i) {
229
+ try {
230
+ window.top.location = i;
231
+ } catch {
232
+ window.location = i;
233
+ }
234
+ }
235
+ function Ne(i, t) {
236
+ return new Promise(function(s, n) {
237
+ const l = new XMLHttpRequest();
238
+ l.onload = function() {
239
+ l.status >= 200 && l.status < 300 ? s(l.responseText) : n(l.responseText);
240
+ }, l.open(i, t), l.send();
241
+ });
242
+ }
243
+ function He() {
244
+ }
245
+ function Wt(i) {
246
+ return i.filter(function(e) {
247
+ return e.messageType.toUpperCase() === "DATA";
248
+ });
249
+ }
250
+ function ze(i) {
251
+ return i.filter(function(e) {
252
+ return ["NOTIFICATION", "POPUP"].includes(e.messageType.toUpperCase());
253
+ });
254
+ }
255
+ function xt(i) {
256
+ try {
257
+ return JSON.parse(i.text);
258
+ } catch {
259
+ return {};
260
+ }
261
+ }
262
+ function $t(i) {
263
+ return i.map(xt).filter(Boolean).find(function(e) {
264
+ return e.betId != null && e.winId != null;
265
+ }) || {};
266
+ }
267
+ function jt(i) {
268
+ return i.map(xt).filter(Boolean).find(function(e) {
269
+ return e.TotalBet != null && e.TotalWin != null;
270
+ }) || {};
271
+ }
272
+ class Li extends $ {
273
+ constructor(...t) {
274
+ super(...t), this.registerToSdkEvents(), this.registerFromSdkEvents(), rt("configured");
275
+ }
276
+ postMessage(t, e) {
277
+ const s = {
278
+ lang: this.config.ui.language,
279
+ sender: this.config.api.game,
280
+ type: t
281
+ };
282
+ e != null && (s.data = e), rt("postMessage", s), window.parent.postMessage(s, "*");
283
+ }
284
+ coinsToCurrency(t) {
285
+ return t * this.config.api.coinValueInCents / 100;
286
+ }
287
+ handleContinueButton(t, e) {
288
+ t.link && Ne("GET", t.link), e();
289
+ }
290
+ handleLinkButton(t, e) {
291
+ switch (t.linkType.toUpperCase()) {
292
+ case "AJAX":
293
+ Ne("GET", t.link), e();
294
+ return;
295
+ case "AJAXRESPONSE":
296
+ Ne("GET", t.link).then(() => {
297
+ e();
298
+ });
299
+ return;
300
+ case "REDIRECT":
301
+ Ge(t.link), e();
302
+ return;
303
+ }
304
+ }
305
+ handleQuitButton(t, e) {
306
+ this.send("close"), e();
307
+ }
308
+ handleCashierButton(t, e) {
309
+ this.send("cashier", { type: "ON_DEMAND" }), e();
310
+ }
311
+ handleHistoryButton(t, e) {
312
+ this.send("history", { source: "casino" }), e();
313
+ }
314
+ get buttonActions() {
315
+ return {
316
+ CASHIER: this.handleCashierButton,
317
+ CONTINUE: this.handleContinueButton,
318
+ HISTORY: this.handleHistoryButton,
319
+ LINK: this.handleLinkButton,
320
+ QUIT: this.handleQuitButton
321
+ };
322
+ }
323
+ processInfoUiMessages(t) {
324
+ return t.reduce((e, s) => e.then(() => new Promise((n) => {
325
+ Object.assign({}, s, {
326
+ buttons: s.buttons.filter((l) => l.action.toUpperCase() === "CASHIER" ? !!this.config.api.cashierUrl : !0).map((l) => Object.assign({}, l, {
327
+ onRelease: () => {
328
+ const a = s.messageType.toUpperCase() === "POPUP" ? He : n, h = this.buttonActions[l.action.toUpperCase()];
329
+ h ? h(l, a) : a();
330
+ }
331
+ }))
332
+ });
333
+ }).catch(He)), Promise.resolve()).then(() => {
334
+ }).catch(He);
335
+ }
336
+ registerToSdkEvents() {
337
+ window.addEventListener("message", (t) => {
338
+ try {
339
+ const { type: e } = t.data;
340
+ switch (e) {
341
+ case "pause":
342
+ case "disableSpin":
343
+ this.send("freeze");
344
+ return;
345
+ case "resume":
346
+ case "enableSpin":
347
+ this.send("unfreeze");
348
+ return;
349
+ case "stopAutobet":
350
+ this.send("suspend");
351
+ return;
352
+ default:
353
+ return;
354
+ }
355
+ } catch {
356
+ }
357
+ });
358
+ }
359
+ registerFromSdkEvents() {
360
+ let t = 0;
361
+ this.on("openGameResponse", (e) => {
362
+ let s;
363
+ try {
364
+ const n = JSON.parse(
365
+ JSON.parse(atob(this.config.api.integrationData.token.split(".")[1])).token
366
+ ), l = JSON.parse(n.integrationSpecificAttributes.sessionData || "{}");
367
+ s = {
368
+ ClientToken: n.integrationSpecificAttributes.clientToken,
369
+ CurrencyCode: n.currency,
370
+ PlayerTokenId: n.user,
371
+ SessionData: l
372
+ };
373
+ } catch {
374
+ s = void 0;
375
+ }
376
+ this.postMessage("gameDataLoaded", {
377
+ LoadGameData: s,
378
+ success: !0
379
+ });
380
+ try {
381
+ const n = ze(e.data.uiMessages);
382
+ this.processInfoUiMessages(n);
383
+ } catch {
384
+ }
385
+ }), this.on("balance", ({ balance: e }) => {
386
+ t !== e && (t = e, this.postMessage("balance", {
387
+ amount: this.coinsToCurrency(e)
388
+ }));
389
+ }), this.on("close", () => {
390
+ if (this.config.api.homeUrl)
391
+ if (this.config.api.homeUrl === "(back)")
392
+ try {
393
+ window.top.history.back();
394
+ } catch {
395
+ window.history.back();
396
+ }
397
+ else
398
+ this.config.api.homeUrl === "(api)" ? this.postMessage("quit") : Ge(this.config.api.homeUrl);
399
+ }), this.on("playEnd", (e) => {
400
+ this.postMessage("roundEnded", {
401
+ balanceAfter: this.coinsToCurrency(e.balance),
402
+ win: this.coinsToCurrency(e.data.gameRoundResult.win)
403
+ });
404
+ try {
405
+ const s = ze(e.data.uiMessages);
406
+ this.processInfoUiMessages(s);
407
+ } catch {
408
+ }
409
+ }), this.on("playError", (e) => {
410
+ this.postMessage("ticketReceived", {
411
+ ErrorCode: e.data.data.data.operatorSpecificErrorCode,
412
+ ErrorMessage: e.data.data.data.operatorSpecificErrorMessage,
413
+ Status: {
414
+ ErrCode: e.data.data.data.operatorSpecificErrorCode
415
+ }
416
+ });
417
+ }), this.on("playResponse", (e) => {
418
+ this.postMessage("roundStarted", {
419
+ balanceBefore: this.coinsToCurrency(e.balance + e.data.gameState.totalBetFromCurrentGameCycle)
420
+ });
421
+ const s = e.data.gameState.stateTypeThisRound === "BaseGame", n = Wt(e.data.uiMessages), l = ze(e.data.uiMessages), a = $t(n), h = jt(n);
422
+ this.postMessage("ticketReceived", {
423
+ Balance: this.coinsToCurrency(e.balance),
424
+ BetAmount: s ? this.coinsToCurrency(e.data.gameState.totalBetFromCurrentGameCycle) : 0,
425
+ CreditTransactionId: a.betId,
426
+ DebitTransactionId: a.winId,
427
+ Message: l,
428
+ SessionData: h,
429
+ Status: {
430
+ ErrCode: 0
431
+ },
432
+ WinAmount: this.coinsToCurrency(e.data.gameRoundResult.win)
433
+ });
434
+ }), this.on("playStart", (e) => {
435
+ "bet" in e && this.postMessage("roundStart", {
436
+ totalBet: this.coinsToCurrency(e.bet.base * e.bet.multiplier)
437
+ });
438
+ }), this.on("loadEnd", () => {
439
+ this.postMessage("gameReady");
440
+ }), this.on("loadStart", () => {
441
+ this.postMessage("onAppFrameReady");
442
+ }), this.on("cashier", () => {
443
+ this.config.api.cashierUrl && (this.config.api.cashierUrl === "(api)" ? this.postMessage("cashier") : Ge(this.config.api.cashierUrl));
444
+ });
445
+ }
446
+ }
447
+ const he = U("RelaxFEIMPlugin", "color:#000000;font-weight:bold;");
448
+ class _i extends $ {
449
+ constructor(...e) {
450
+ super(...e);
451
+ w(this, "VERSION", "1.15.0");
452
+ const s = document.createElement("script");
453
+ s.src = `https://d3nsdzdtjbr5ml.cloudfront.net/casino/relaxlibs/feim/${this.VERSION}/rlxfeim.min.js`, s.onload = () => {
454
+ he("loaded"), window.FEIM.configure({
455
+ p2pConfig: {
456
+ currency: this.config.api.currency,
457
+ launchParams: {
458
+ // unified with KalambaSdkConfig
459
+ homeurl: "homeUrl"
460
+ }
461
+ }
462
+ }), he("configured"), this.registerToSdkEvents(), this.registerFromSdkEvents();
463
+ }, document.body.appendChild(s);
464
+ }
465
+ registerToSdkEvents() {
466
+ window.FEIM.on.errorMessageDismissed(() => this.send("unfreeze")), window.FEIM.on.errorMessageDisplayed(() => this.send("freeze")), window.FEIM.on.exitingGame(() => he("!!! NOT IMPLEMENTED: exitingGame !!!")), window.FEIM.on.freeze(() => this.send("freeze")), window.FEIM.on.initialized(() => he("!!! NOT IMPLEMENTED: initialized !!!")), window.FEIM.on.pauseAutoPlay(() => this.send("suspend")), window.FEIM.on.refreshBalance(() => he("!!! NOT IMPLEMENTED: refreshBalance !!!")), window.FEIM.on.toggleGameHelp(() => {
467
+ this.send("help", {});
468
+ }), window.FEIM.on.togglePaytable(() => {
469
+ this.send("paytable", {});
470
+ }), window.FEIM.on.unfreeze(() => this.send("unfreeze")), window.FEIM.on.updateSettings(
471
+ ({ payload: [e] }) => this.send("settings", { sounds: e.sounds, fastPlay: e.fastPlay })
472
+ );
473
+ }
474
+ registerFromSdkEvents() {
475
+ this.on("autoplay", ({ action: e }) => {
476
+ switch (e) {
477
+ case "start":
478
+ window.FEIM.send.autoPlayStarted();
479
+ break;
480
+ case "stop":
481
+ window.FEIM.send.autoPlayFinished();
482
+ break;
483
+ }
484
+ }), this.on("balance", ({ balance: e }) => {
485
+ window.FEIM.send.balanceUpdate(e);
486
+ }), this.on("bet", ({ base: e, multiplier: s }) => {
487
+ window.FEIM.send.betUpdate(e * s);
488
+ }), this.on("error", ({ message: e }) => {
489
+ window.FEIM.send.errorMessage(e);
490
+ }), this.on("close", () => {
491
+ window.FEIM.send.exitGame();
492
+ }), this.on("loadEnd", () => {
493
+ window.FEIM.send.gameLoadCompleted();
494
+ }), this.on("loadProgress", ({ progress: e }) => {
495
+ window.FEIM.send.gameLoadProgress(e);
496
+ }), this.on("loadStart", () => {
497
+ window.FEIM.send.gameLoadStarted();
498
+ }), this.on("cashier", () => {
499
+ window.FEIM.send.openQuickDeposit();
500
+ }), this.on("playCycleEnd", (e) => {
501
+ const s = {
502
+ balance: e.balance,
503
+ // TODO: response should be processed by adapter
504
+ // Current implementation works only with Kalamba RGS
505
+ bet: e.data.gameState.totalBetFromCurrentGameCycle,
506
+ win: {
507
+ win: e.data.gameState.totalWinFromCurrentGameCycle
508
+ }
509
+ };
510
+ window.FEIM.send.roundFinished(s);
511
+ }), this.on("playResponse", (e) => {
512
+ const s = {
513
+ balance: e.balance,
514
+ playResponse: e.data
515
+ };
516
+ window.FEIM.send.roundStarted(s);
517
+ }), this.on("history", () => {
518
+ window.FEIM.send.showHistory();
519
+ }), this.on("settings", (e) => {
520
+ window.FEIM.send.updateSettings(e);
521
+ });
522
+ }
523
+ }
524
+ const Ve = U("TukoPlugin", "color:#000000;font-weight:bold;");
525
+ class Fi extends $ {
526
+ constructor(...e) {
527
+ super(...e);
528
+ w(this, "PING_INTERVAL", 1e4);
529
+ const n = new URLSearchParams(window.location.search).get("pingCallbackUrl");
530
+ n && window.setInterval(() => {
531
+ this.ping(n);
532
+ }, this.PING_INTERVAL), this.registerToSdkEvents(), this.registerFromSdkEvents(), Ve("configured");
533
+ }
534
+ ping(e) {
535
+ const s = new XMLHttpRequest();
536
+ s.onreadystatechange = function() {
537
+ s.readyState === XMLHttpRequest.DONE && (s.status === 0 || s.status >= 200 && s.status < 400 ? Ve("ping ok", s) : Ve("ping error", s));
538
+ }, s.open("GET", e), s.send();
539
+ }
540
+ registerToSdkEvents() {
541
+ window.addEventListener("message", (e) => {
542
+ try {
543
+ const { type: s, payload: n } = e.data;
544
+ switch (s) {
545
+ case "doAudioSettings":
546
+ this.send("settings", { music: n == null ? void 0 : n.musicEnabled, sounds: n == null ? void 0 : n.soundEnabled });
547
+ return;
548
+ case "doBalanceUpdate":
549
+ const { currency: l, coinValueInCents: a } = this.config.api;
550
+ n.currency === l && typeof n.balanceInCurrency == "number" ? this.send("balance", { balance: Ut(n.balanceInCurrency, a) }) : (n.balanceInCoins, this.send("balance", { balance: n.balanceInCoins }));
551
+ return;
552
+ case "doGamePause":
553
+ this.send("freeze");
554
+ return;
555
+ case "doGameResume":
556
+ this.send("unfreeze");
557
+ return;
558
+ case "doGameSuspend":
559
+ this.send("suspend");
560
+ return;
561
+ default:
562
+ return;
563
+ }
564
+ } catch {
565
+ }
566
+ });
567
+ }
568
+ registerFromSdkEvents() {
569
+ this.on("close", () => {
570
+ if (this.config.api.homeUrl)
571
+ try {
572
+ window.top.location = this.config.api.homeUrl;
573
+ } catch {
574
+ window.location = this.config.api.homeUrl;
575
+ }
576
+ else
577
+ try {
578
+ window.top.history.back();
579
+ } catch {
580
+ window.history.back();
581
+ }
582
+ });
583
+ }
584
+ }
585
+ class Qt {
586
+ constructor(t) {
587
+ w(this, "socket", null);
588
+ w(this, "webSocketUrl");
589
+ w(this, "eventListeners", {
590
+ close: [],
591
+ error: [],
592
+ message: []
593
+ });
594
+ w(this, "connect", () => {
595
+ const t = new WebSocket(this.webSocketUrl);
596
+ return t.addEventListener("message", this.handleMessage), new Promise((e) => {
597
+ t.addEventListener("open", (s) => {
598
+ this.handleOpen(s), e(this.socket);
599
+ });
600
+ });
601
+ });
602
+ w(this, "send", (t) => {
603
+ if (this.socket == null)
604
+ throw new Error("Cannot send message, the WebSocket connection is not open");
605
+ this.socket.send(t);
606
+ });
607
+ w(this, "close", () => {
608
+ if (this.socket == null)
609
+ throw new Error("Cannot close the WebSocket connection that is not open");
610
+ this.socket.close(), this.addEventListener("error", (t) => {
611
+ console.log(t);
612
+ });
613
+ });
614
+ w(this, "handleClose", (t) => {
615
+ this.eventListeners.close.forEach((e) => {
616
+ e(t);
617
+ });
618
+ });
619
+ w(this, "handleError", (t) => {
620
+ this.eventListeners.error.forEach((e) => {
621
+ e(t);
622
+ });
623
+ });
624
+ w(this, "handleMessage", (t) => {
625
+ this.eventListeners.message.forEach((e) => {
626
+ e(t);
627
+ });
628
+ });
629
+ w(this, "handleOpen", (t) => {
630
+ const e = t.target;
631
+ e.addEventListener("close", this.handleClose), e.addEventListener("error", this.handleError), this.socket = e;
632
+ });
633
+ this.webSocketUrl = t;
634
+ }
635
+ addEventListener(t, e) {
636
+ this.eventListeners[t].push(e);
637
+ }
638
+ removeEventListener(t, e) {
639
+ const s = this.eventListeners[t].indexOf(e);
640
+ s !== -1 && this.eventListeners[t].splice(s, 1);
641
+ }
642
+ }
643
+ function Me(i) {
644
+ try {
645
+ return JSON.parse(i == null ? void 0 : i.data);
646
+ } catch (t) {
647
+ return console.error("fakap", t), null;
648
+ }
649
+ }
650
+ function oe(i) {
651
+ var t;
652
+ return ((t = i == null ? void 0 : i.header) == null ? void 0 : t.name) === "GameEvent";
653
+ }
654
+ function Xt(i) {
655
+ return oe(i) && i.body.event === "OPEN_GAME";
656
+ }
657
+ function Kt(i) {
658
+ return oe(i) && i.body.event === "SPIN_ERROR";
659
+ }
660
+ function Jt(i) {
661
+ return oe(i) && i.body.event === "SPIN_RESULT";
662
+ }
663
+ function Yt(i) {
664
+ return oe(i) && i.body.event === "BG_RESULT";
665
+ }
666
+ function Zt(i) {
667
+ var t;
668
+ return ((t = i == null ? void 0 : i.header) == null ? void 0 : t.name) === "OpenGame";
669
+ }
670
+ function ei(i) {
671
+ var t;
672
+ return ((t = i == null ? void 0 : i.header) == null ? void 0 : t.name) === "Ping";
673
+ }
674
+ function ct(i) {
675
+ var t;
676
+ return ((t = i == null ? void 0 : i.header) == null ? void 0 : t.name) === "RealityCheck";
677
+ }
678
+ var Z, ye;
679
+ class ti extends Qt {
680
+ constructor(e, s) {
681
+ const n = new URL(e.apiUrl);
682
+ n.searchParams.set("cageCode", e.cageCode), n.searchParams.set("gameCode", e.gameCode), n.searchParams.set("operatorCode", e.operatorCode), n.searchParams.set("playMode", e.playMode), n.searchParams.set("token", e.token), n.searchParams.set("username", e.username);
683
+ super(n.toString());
684
+ /*
685
+ * Correlation ID. Used in Request and Response types.
686
+ * ----
687
+ * Since web socket communication is async, correlation id enables us
688
+ * to connect requests and responses together. This is suitable also for
689
+ * troubleshooting. Connected requests and responses must have
690
+ * same correlation id. Correlation id should increase with every
691
+ * request sent. Client and server independently maintain their own
692
+ * correlation id counter.
693
+ */
694
+ w(this, "cId", 0);
695
+ // Initial values for header
696
+ /*
697
+ * Increasing message ID
698
+ * ----
699
+ * mId should be increased with every message sent and is independently
700
+ * maintained by client and server (ids on server and ids on client are not
701
+ * correlated). This id is used by accepting party to keep incoming
702
+ * messages in order (network issues could be the cause that messages are
703
+ * received out of sync).
704
+ */
705
+ // TODO make sure messages are processed in order
706
+ w(this, "mId", 0);
707
+ // Initial values for body
708
+ /*
709
+ * Sequence ID. Action/Event correlation.
710
+ */
711
+ w(this, "seqId", 10);
712
+ w(this, "gameCode");
713
+ v(this, Z, void 0);
714
+ v(this, ye, void 0);
715
+ w(this, "onMessage", (e) => {
716
+ const s = Me(e);
717
+ (oe(s) || ei(s) || ct(s)) && this.sendAcknowledgement(s), ct(s) && this.handleRealityCheck(s);
718
+ });
719
+ this.eventListeners.realityCheck = [], this.gameCode = e.gameCode, E(this, Z, s.requestTimeoutMs), E(this, ye, s.gameVersion ?? "unknown"), this.addEventListener("message", this.onMessage);
720
+ }
721
+ handleRealityCheck(e) {
722
+ this.eventListeners.realityCheck.forEach((s) => {
723
+ s(e.body);
724
+ });
725
+ }
726
+ addEventListener(e, s) {
727
+ super.addEventListener(e, s);
728
+ }
729
+ removeEventListener(e, s) {
730
+ super.removeEventListener(e, s);
731
+ }
732
+ buildHeader(e, s = null) {
733
+ return {
734
+ // Assign new cId if it is not provided
735
+ cId: s ?? ++this.cId,
736
+ code: s !== null ? 1 : void 0,
737
+ mId: ++this.mId,
738
+ name: e
739
+ };
740
+ }
741
+ // TODO infer body from header
742
+ buildPayload(e, s) {
743
+ return JSON.stringify({
744
+ body: s,
745
+ header: e
746
+ });
747
+ }
748
+ getBodyExtras(e) {
749
+ return {
750
+ action: e,
751
+ seqId: ++this.seqId
752
+ };
753
+ }
754
+ request(e, s) {
755
+ const n = this.buildPayload(e, s);
756
+ return new Promise((l, a) => {
757
+ setTimeout(() => a({ request: { body: s, header: e }, type: "timeout" }), y(this, Z));
758
+ const h = (p) => {
759
+ const g = Me(p);
760
+ try {
761
+ e.cId === (g == null ? void 0 : g.header.cId) && (this.removeEventListener("message", h), g.header.code === 1 ? l(g) : a({ response: g, type: "response" }));
762
+ } catch {
763
+ a({ response: g, type: "error" });
764
+ }
765
+ };
766
+ this.addEventListener("message", h), this.send(n);
767
+ });
768
+ }
769
+ activateFreeRound(e) {
770
+ const s = this.buildHeader("ActivateFreeRound");
771
+ return this.request(
772
+ s,
773
+ e
774
+ );
775
+ }
776
+ authenticate(e = !1) {
777
+ const s = this.buildHeader("Authenticate"), n = {
778
+ clientType: 3,
779
+ version: y(this, ye),
780
+ reconnect: e
781
+ };
782
+ return this.request(
783
+ s,
784
+ n
785
+ ).then((l) => l.body);
786
+ }
787
+ openGame() {
788
+ const e = this.buildHeader("OpenGame"), s = {
789
+ gameCode: this.gameCode
790
+ };
791
+ return new Promise((n, l) => {
792
+ const a = (h) => {
793
+ const p = Me(h);
794
+ Xt(p) && (this.removeEventListener("message", a), n(p.body));
795
+ };
796
+ this.addEventListener("message", a), this.request(e, s).catch((h) => {
797
+ Zt(h.response) && l(h), l(h);
798
+ });
799
+ });
800
+ }
801
+ sendAcknowledgement(e) {
802
+ const { name: s, cId: n } = e.header, l = this.buildHeader(s, n), a = this.buildPayload(l, {});
803
+ this.send(a);
804
+ }
805
+ sendAction(e, s) {
806
+ const n = this.buildHeader("GameAction"), l = {
807
+ ...this.getBodyExtras(e),
808
+ data: s
809
+ };
810
+ return new Promise((a, h) => {
811
+ const p = (g) => {
812
+ const f = Me(g);
813
+ oe(f) && l.seqId === f.body.correlationSeqId && (this.removeEventListener("message", p), Jt(f) || Yt(f) ? a(f.body) : Kt(f) && h(f.body));
814
+ };
815
+ this.addEventListener("message", p), this.request(n, l).catch(
816
+ (g) => {
817
+ h(g);
818
+ }
819
+ );
820
+ });
821
+ }
822
+ spin(e) {
823
+ return this.sendAction("SPIN", e);
824
+ }
825
+ bgAction(e) {
826
+ return this.sendAction("BG_ACTION", e);
827
+ }
828
+ setRequestTimeoutMs(e) {
829
+ E(this, Z, e);
830
+ }
831
+ }
832
+ Z = new WeakMap(), ye = new WeakMap();
833
+ class ii {
834
+ constructor(t) {
835
+ w(this, "config");
836
+ this.config = t;
837
+ }
838
+ on(t, e, s) {
839
+ const n = function(a) {
840
+ a.data.message !== `kalamba:wrapper-rgs:${t}` && a.data.message !== `kalamba:wrapper:${t}` || e(a.data.payload);
841
+ };
842
+ window.addEventListener("message", n, s);
843
+ }
844
+ send(t, ...[e]) {
845
+ window.postMessage({
846
+ message: `kalamba:rgs:${t}`,
847
+ payload: e
848
+ });
849
+ }
850
+ }
851
+ const si = {
852
+ bul: "bg",
853
+ chi: "zh",
854
+ zho: "zh",
855
+ hrv: "hr",
856
+ cze: "cs",
857
+ dan: "da",
858
+ dut: "nl",
859
+ eng: "en",
860
+ est: "et",
861
+ fin: "fi",
862
+ fra: "fr",
863
+ ger: "de",
864
+ gre: "el",
865
+ hun: "hu",
866
+ ind: "id",
867
+ ita: "it",
868
+ jpn: "ja",
869
+ kor: "ko",
870
+ nor: "no",
871
+ pol: "pl",
872
+ por: "pt",
873
+ rum: "ro",
874
+ rus: "ru",
875
+ srp: "sr",
876
+ slo: "sk",
877
+ spa: "es",
878
+ swe: "sv",
879
+ tha: "th",
880
+ tur: "tr",
881
+ ukr: "uk",
882
+ vie: "vi"
883
+ }, ni = U("KalambaBullseyePlugin", "color:#000000;font-weight:bold;");
884
+ var Ee;
885
+ class Di extends ii {
886
+ constructor(...e) {
887
+ super(...e);
888
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
889
+ // @ts-ignore
890
+ w(this, "socket");
891
+ v(this, Ee, "");
892
+ this.on("openGame", async () => {
893
+ try {
894
+ const s = await this.openGame();
895
+ this.send("openGameResponse", s);
896
+ } catch (s) {
897
+ this.send("openGameError", s);
898
+ }
899
+ }), this.on("play", async (s) => {
900
+ try {
901
+ const n = await this.play(s);
902
+ this.send("playResponse", n);
903
+ } catch (n) {
904
+ this.send("playError", n);
905
+ }
906
+ }), this.on("state", ({ version: s }) => {
907
+ E(this, Ee, s);
908
+ }), this.on("configured", (s) => {
909
+ this.socket.setRequestTimeoutMs(s.ui.requestTimeoutMs);
910
+ }), this.registerFromSdkEvents();
911
+ }
912
+ initialize(e) {
913
+ this.socket = new ti(e, {
914
+ gameVersion: y(this, Ee),
915
+ requestTimeoutMs: this.config.ui.requestTimeoutMs
916
+ }), this.socket.addEventListener("close", (s) => {
917
+ s.code === 1006 && this.reconnect(e);
918
+ }), document.addEventListener("visibilitychange", () => {
919
+ document.visibilityState === "visible" && this.socket.socket && this.socket.socket.readyState !== WebSocket.OPEN && this.reconnect(e);
920
+ }), this.socket.addEventListener("error", (s) => ni("error", s)), this.socket.addEventListener("realityCheck", (s) => {
921
+ this.send("realityCheck", s);
922
+ });
923
+ }
924
+ async reconnect(e) {
925
+ this.initialize(e), await this.socket.connect(), await this.socket.authenticate(!0), await this.socket.openGame();
926
+ }
927
+ async openGame() {
928
+ const e = new URLSearchParams(window.location.search), s = e.get("apiUrl"), n = e.get("cageCode"), l = e.get("gameCode"), a = e.get("operatorCode"), h = e.get("playMode"), p = e.get("token"), g = e.get("username"), f = e.get("gameHistoryUrl"), A = e.get("homeUrl") ?? void 0, D = e.get("cashierUrl") ?? void 0;
929
+ this.initialize({ apiUrl: s, cageCode: n, gameCode: l, operatorCode: a, playMode: h, token: p, username: g }), await this.socket.connect();
930
+ const B = await this.socket.authenticate(), le = await this.socket.openGame();
931
+ this.config.api = {
932
+ brand: n,
933
+ game: l,
934
+ integration: a,
935
+ jurisdiction: B.jurisdictionCode,
936
+ playMode: h,
937
+ user: B.username,
938
+ integrationData: {
939
+ token: p
940
+ },
941
+ country: B.countryCode,
942
+ currency: B.currencyCode,
943
+ coinValueInCents: B.coinValueInCents,
944
+ gameHistoryUrl: f,
945
+ homeUrl: A,
946
+ cashierUrl: D
947
+ };
948
+ const x = e.get("languageCode");
949
+ return x && (this.config.ui.language = x.length === 3 ? si[x] ?? x : x), le;
950
+ }
951
+ // TODO: redefine PlayResponse type
952
+ play(e) {
953
+ if ("userInput" in e && e.userInput != null)
954
+ return this.socket.bgAction(e);
955
+ if ("opaqueGameAttributes" in e && e.opaqueGameAttributes)
956
+ return this.socket.spin(e);
957
+ if ("bet" in e && e.bet) {
958
+ const { bet: s, ...n } = e;
959
+ return this.socket.spin({
960
+ bet: { baseBet: s.base, betMultiplier: s.multiplier },
961
+ ...n
962
+ });
963
+ }
964
+ }
965
+ registerFromSdkEvents() {
966
+ this.on("history", () => {
967
+ const {
968
+ api: { game: e, integration: s, integrationData: n, jurisdiction: l, user: a, gameHistoryUrl: h },
969
+ ui: { language: p }
970
+ } = this.config, g = a.replace(/^user_/, "").replace(new RegExp(`_${s}$`), ""), f = new URL(h);
971
+ f.searchParams.set("gameCode", e), f.searchParams.set("jurisdiction", l), f.searchParams.set("operatorCode", s), f.searchParams.set("token", n.token), f.searchParams.set("username", g), f.searchParams.set("languageCode", p), window.open(f.toString(), "_blank");
972
+ });
973
+ }
974
+ }
975
+ Ee = new WeakMap();
976
+ var ai = "2.0.0-beta.2", re = "", dt = "?", Ke = "function", H = "undefined", ce = "object", Je = "string", fe = "major", c = "model", o = "name", d = "type", u = "vendor", r = "version", M = "architecture", K = "console", m = "mobile", b = "tablet", I = "smarttv", X = "wearable", Ye = "embedded", lt = "user-agent", Ze = 500, it = "brands", q = "formFactor", st = "fullVersionList", J = "platform", nt = "platformVersion", De = "bitness", V = "sec-ch-ua", oi = V + "-full-version-list", ri = V + "-arch", ci = V + "-" + De, di = V + "-form-factor", li = V + "-" + m, ui = V + "-" + c, Ot = V + "-" + J, hi = Ot + "-version", Lt = [it, st, m, c, J, nt, M, q, De], T = "browser", O = "cpu", P = "device", L = "engine", R = "os", Y = "result", Ce = "Amazon", pe = "Apple", ut = "ASUS", ht = "BlackBerry", Ie = "Google", pt = "Huawei", gt = "Lenovo", qe = "LG", xe = "Microsoft", wt = "Motorola", Te = "Samsung", mt = "Sharp", Ae = "Sony", We = "Xiaomi", $e = "Zebra", j = "Mobile ", Q = " Browser", Re = "Chrome", pi = "Edge", ge = "Firefox", we = "Opera", ft = "Facebook", bt = "Sogou", et = "Windows", gi = typeof window !== H, C = gi && window.navigator ? window.navigator : void 0, G = C && C.userAgentData ? C.userAgentData : void 0, wi = function(i, t) {
977
+ var e = {};
978
+ for (var s in i)
979
+ e[s] = t[s] && t[s].length % 2 === 0 ? t[s].concat(i[s]) : i[s];
980
+ return e;
981
+ }, Be = function(i) {
982
+ for (var t = {}, e = 0; e < i.length; e++)
983
+ t[i[e].toUpperCase()] = i[e];
984
+ return t;
985
+ }, tt = function(i, t) {
986
+ if (typeof i === ce && i.length > 0) {
987
+ for (var e in i)
988
+ if (z(i[e]) == z(t))
989
+ return !0;
990
+ return !1;
991
+ }
992
+ return de(i) ? z(t).indexOf(z(i)) !== -1 : !1;
993
+ }, yt = function(i) {
994
+ for (var t in i)
995
+ return /^(browser|cpu|device|engine|os)$/.test(t);
996
+ }, de = function(i) {
997
+ return typeof i === Je;
998
+ }, je = function(i) {
999
+ if (i) {
1000
+ for (var t = [], e = W(/\\?\"/g, i).split(","), s = 0; s < e.length; s++)
1001
+ if (e[s].indexOf(";") > -1) {
1002
+ var n = be(e[s]).split(";v=");
1003
+ t[s] = { brand: n[0], version: n[1] };
1004
+ } else
1005
+ t[s] = be(e[s]);
1006
+ return t;
1007
+ }
1008
+ }, z = function(i) {
1009
+ return de(i) ? i.toLowerCase() : i;
1010
+ }, Qe = function(i) {
1011
+ return de(i) ? W(/[^\d\.]/g, i).split(".")[0] : void 0;
1012
+ }, _ = function(i) {
1013
+ for (var t in i) {
1014
+ var e = i[t];
1015
+ typeof e == ce && e.length == 2 ? this[e[0]] = e[1] : this[e] = void 0;
1016
+ }
1017
+ return this;
1018
+ }, W = function(i, t) {
1019
+ return de(t) ? t.replace(i, re) : t;
1020
+ }, me = function(i) {
1021
+ return W(/\\?\"/g, i);
1022
+ }, be = function(i, t) {
1023
+ if (de(i))
1024
+ return i = W(/^\s\s*/, i), typeof t === H ? i : i.substring(0, Ze);
1025
+ }, Et = function(i, t) {
1026
+ if (!(!i || !t))
1027
+ for (var e = 0, s, n, l, a, h, p; e < t.length && !h; ) {
1028
+ var g = t[e], f = t[e + 1];
1029
+ for (s = n = 0; s < g.length && !h && g[s]; )
1030
+ if (h = g[s++].exec(i), h)
1031
+ for (l = 0; l < f.length; l++)
1032
+ p = h[++n], a = f[l], typeof a === ce && a.length > 0 ? a.length === 2 ? typeof a[1] == Ke ? this[a[0]] = a[1].call(this, p) : this[a[0]] = a[1] : a.length === 3 ? typeof a[1] === Ke && !(a[1].exec && a[1].test) ? this[a[0]] = p ? a[1].call(this, p, a[2]) : void 0 : this[a[0]] = p ? p.replace(a[1], a[2]) : void 0 : a.length === 4 && (this[a[0]] = p ? a[3].call(this, p.replace(a[1], a[2])) : void 0) : this[a] = p || void 0;
1033
+ e += 2;
1034
+ }
1035
+ }, Oe = function(i, t) {
1036
+ for (var e in t)
1037
+ if (typeof t[e] === ce && t[e].length > 0) {
1038
+ for (var s = 0; s < t[e].length; s++)
1039
+ if (tt(t[e][s], i))
1040
+ return e === dt ? void 0 : e;
1041
+ } else if (tt(t[e], i))
1042
+ return e === dt ? void 0 : e;
1043
+ return t.hasOwnProperty("*") ? t["*"] : i;
1044
+ }, vt = {
1045
+ ME: "4.90",
1046
+ "NT 3.11": "NT3.51",
1047
+ "NT 4.0": "NT4.0",
1048
+ 2e3: "NT 5.0",
1049
+ XP: ["NT 5.1", "NT 5.2"],
1050
+ Vista: "NT 6.0",
1051
+ 7: "NT 6.1",
1052
+ 8: "NT 6.2",
1053
+ "8.1": "NT 6.3",
1054
+ 10: ["NT 6.4", "NT 10.0"],
1055
+ RT: "ARM"
1056
+ }, kt = {
1057
+ embedded: "Automotive",
1058
+ mobile: "Mobile",
1059
+ tablet: ["Tablet", "EInk"],
1060
+ smarttv: "TV",
1061
+ wearable: ["VR", "XR", "Watch"],
1062
+ "?": ["Desktop", "Unknown"],
1063
+ "*": void 0
1064
+ }, St = {
1065
+ browser: [
1066
+ [
1067
+ // Most common regardless engine
1068
+ /\b(?:crmo|crios)\/([\w\.]+)/i
1069
+ // Chrome for Android/iOS
1070
+ ],
1071
+ [r, [o, j + "Chrome"]],
1072
+ [
1073
+ /edg(?:e|ios|a)?\/([\w\.]+)/i
1074
+ // Microsoft Edge
1075
+ ],
1076
+ [r, [o, "Edge"]],
1077
+ [
1078
+ // Presto based
1079
+ /(opera mini)\/([-\w\.]+)/i,
1080
+ // Opera Mini
1081
+ /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i,
1082
+ // Opera Mobi/Tablet
1083
+ /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i
1084
+ // Opera
1085
+ ],
1086
+ [o, r],
1087
+ [
1088
+ /opios[\/ ]+([\w\.]+)/i
1089
+ // Opera mini on iphone >= 8.0
1090
+ ],
1091
+ [r, [o, we + " Mini"]],
1092
+ [
1093
+ /\bop(?:rg)?x\/([\w\.]+)/i
1094
+ // Opera GX
1095
+ ],
1096
+ [r, [o, we + " GX"]],
1097
+ [
1098
+ /\bopr\/([\w\.]+)/i
1099
+ // Opera Webkit
1100
+ ],
1101
+ [r, [o, we]],
1102
+ [
1103
+ // Mixed
1104
+ /\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i
1105
+ // Baidu
1106
+ ],
1107
+ [r, [o, "Baidu"]],
1108
+ [
1109
+ /(kindle)\/([\w\.]+)/i,
1110
+ // Kindle
1111
+ /(lunascape|maxthon|netfront|jasmine|blazer)[\/ ]?([\w\.]*)/i,
1112
+ // Lunascape/Maxthon/Netfront/Jasmine/Blazer
1113
+ // Trident based
1114
+ /(avant|iemobile|slim)\s?(?:browser)?[\/ ]?([\w\.]*)/i,
1115
+ // Avant/IEMobile/SlimBrowser
1116
+ /(?:ms|\()(ie) ([\w\.]+)/i,
1117
+ // Internet Explorer
1118
+ // Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon
1119
+ /(flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|quark|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|qq|duckduckgo)\/([-\w\.]+)/i,
1120
+ // Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo
1121
+ /(heytap|ovi)browser\/([\d\.]+)/i,
1122
+ // HeyTap/Ovi
1123
+ /(weibo)__([\d\.]+)/i
1124
+ // Weibo
1125
+ ],
1126
+ [o, r],
1127
+ [
1128
+ /(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i
1129
+ // UCBrowser
1130
+ ],
1131
+ [r, [o, "UCBrowser"]],
1132
+ [
1133
+ /microm.+\bqbcore\/([\w\.]+)/i,
1134
+ // WeChat Desktop for Windows Built-in Browser
1135
+ /\bqbcore\/([\w\.]+).+microm/i,
1136
+ /micromessenger\/([\w\.]+)/i
1137
+ // WeChat
1138
+ ],
1139
+ [r, [o, "WeChat"]],
1140
+ [
1141
+ /konqueror\/([\w\.]+)/i
1142
+ // Konqueror
1143
+ ],
1144
+ [r, [o, "Konqueror"]],
1145
+ [
1146
+ /trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i
1147
+ // IE11
1148
+ ],
1149
+ [r, [o, "IE"]],
1150
+ [
1151
+ /ya(?:search)?browser\/([\w\.]+)/i
1152
+ // Yandex
1153
+ ],
1154
+ [r, [o, "Yandex"]],
1155
+ [
1156
+ /slbrowser\/([\w\.]+)/i
1157
+ // Smart Lenovo Browser
1158
+ ],
1159
+ [r, [o, "Smart " + gt + Q]],
1160
+ [
1161
+ /(avast|avg)\/([\w\.]+)/i
1162
+ // Avast/AVG Secure Browser
1163
+ ],
1164
+ [[o, /(.+)/, "$1 Secure" + Q], r],
1165
+ [
1166
+ /\bfocus\/([\w\.]+)/i
1167
+ // Firefox Focus
1168
+ ],
1169
+ [r, [o, ge + " Focus"]],
1170
+ [
1171
+ /\bopt\/([\w\.]+)/i
1172
+ // Opera Touch
1173
+ ],
1174
+ [r, [o, we + " Touch"]],
1175
+ [
1176
+ /coc_coc\w+\/([\w\.]+)/i
1177
+ // Coc Coc Browser
1178
+ ],
1179
+ [r, [o, "Coc Coc"]],
1180
+ [
1181
+ /dolfin\/([\w\.]+)/i
1182
+ // Dolphin
1183
+ ],
1184
+ [r, [o, "Dolphin"]],
1185
+ [
1186
+ /coast\/([\w\.]+)/i
1187
+ // Opera Coast
1188
+ ],
1189
+ [r, [o, we + " Coast"]],
1190
+ [
1191
+ /miuibrowser\/([\w\.]+)/i
1192
+ // MIUI Browser
1193
+ ],
1194
+ [r, [o, "MIUI" + Q]],
1195
+ [
1196
+ /fxios\/([\w\.-]+)/i
1197
+ // Firefox for iOS
1198
+ ],
1199
+ [r, [o, j + ge]],
1200
+ [
1201
+ /\bqihu|(qi?ho?o?|360)browser/i
1202
+ // 360
1203
+ ],
1204
+ [[o, "360" + Q]],
1205
+ [
1206
+ /(oculus|sailfish|huawei|vivo)browser\/([\w\.]+)/i
1207
+ ],
1208
+ [[o, /(.+)/, "$1" + Q], r],
1209
+ [
1210
+ // Oculus/Sailfish/HuaweiBrowser/VivoBrowser
1211
+ /samsungbrowser\/([\w\.]+)/i
1212
+ // Samsung Internet
1213
+ ],
1214
+ [r, [o, Te + " Internet"]],
1215
+ [
1216
+ /(comodo_dragon)\/([\w\.]+)/i
1217
+ // Comodo Dragon
1218
+ ],
1219
+ [[o, /_/g, " "], r],
1220
+ [
1221
+ /metasr[\/ ]?([\d\.]+)/i
1222
+ // Sogou Explorer
1223
+ ],
1224
+ [r, [o, bt + " Explorer"]],
1225
+ [
1226
+ /(sogou)mo\w+\/([\d\.]+)/i
1227
+ // Sogou Mobile
1228
+ ],
1229
+ [[o, bt + " Mobile"], r],
1230
+ [
1231
+ /(electron)\/([\w\.]+) safari/i,
1232
+ // Electron-based App
1233
+ /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i,
1234
+ // Tesla
1235
+ /m?(qqbrowser|2345Explorer)[\/ ]?([\w\.]+)/i
1236
+ // QQBrowser/2345 Browser
1237
+ ],
1238
+ [o, r],
1239
+ [
1240
+ /(lbbrowser)/i,
1241
+ // LieBao Browser
1242
+ /\[(linkedin)app\]/i
1243
+ // LinkedIn App for iOS & Android
1244
+ ],
1245
+ [o],
1246
+ [
1247
+ // WebView
1248
+ /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i
1249
+ // Facebook App for iOS & Android
1250
+ ],
1251
+ [[o, ft], r],
1252
+ [
1253
+ /(Klarna)\/([\w\.]+)/i,
1254
+ // Klarna Shopping Browser for iOS & Android
1255
+ /(kakao(?:talk|story))[\/ ]([\w\.]+)/i,
1256
+ // Kakao App
1257
+ /(naver)\(.*?(\d+\.[\w\.]+).*\)/i,
1258
+ // Naver InApp
1259
+ /safari (line)\/([\w\.]+)/i,
1260
+ // Line App for iOS
1261
+ /\b(line)\/([\w\.]+)\/iab/i,
1262
+ // Line App for Android
1263
+ /(alipay)client\/([\w\.]+)/i,
1264
+ // Alipay
1265
+ /(chromium|instagram|snapchat)[\/ ]([-\w\.]+)/i
1266
+ // Chromium/Instagram/Snapchat
1267
+ ],
1268
+ [o, r],
1269
+ [
1270
+ /\bgsa\/([\w\.]+) .*safari\//i
1271
+ // Google Search Appliance on iOS
1272
+ ],
1273
+ [r, [o, "GSA"]],
1274
+ [
1275
+ /musical_ly(?:.+app_?version\/|_)([\w\.]+)/i
1276
+ // TikTok
1277
+ ],
1278
+ [r, [o, "TikTok"]],
1279
+ [
1280
+ /headlesschrome(?:\/([\w\.]+)| )/i
1281
+ // Chrome Headless
1282
+ ],
1283
+ [r, [o, Re + " Headless"]],
1284
+ [
1285
+ / wv\).+(chrome)\/([\w\.]+)/i
1286
+ // Chrome WebView
1287
+ ],
1288
+ [[o, Re + " WebView"], r],
1289
+ [
1290
+ /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i
1291
+ // Android Browser
1292
+ ],
1293
+ [r, [o, "Android" + Q]],
1294
+ [
1295
+ /chrome\/([\w\.]+) mobile/i
1296
+ // Chrome Mobile
1297
+ ],
1298
+ [r, [o, j + "Chrome"]],
1299
+ [
1300
+ /(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i
1301
+ // Chrome/OmniWeb/Arora/Tizen/Nokia
1302
+ ],
1303
+ [o, r],
1304
+ [
1305
+ /version\/([\w\.\,]+) .*mobile(?:\/\w+ | ?)safari/i
1306
+ // Safari Mobile
1307
+ ],
1308
+ [r, [o, j + "Safari"]],
1309
+ [
1310
+ /iphone .*mobile(?:\/\w+ | ?)safari/i
1311
+ ],
1312
+ [[o, j + "Safari"]],
1313
+ [
1314
+ /version\/([\w\.\,]+) .*(safari)/i
1315
+ // Safari
1316
+ ],
1317
+ [r, o],
1318
+ [
1319
+ /webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i
1320
+ // Safari < 3.0
1321
+ ],
1322
+ [o, [r, "1"]],
1323
+ [
1324
+ /(webkit|khtml)\/([\w\.]+)/i
1325
+ ],
1326
+ [o, r],
1327
+ [
1328
+ // Gecko based
1329
+ /(?:mobile|tablet);.*(firefox)\/([\w\.-]+)/i
1330
+ // Firefox Mobile
1331
+ ],
1332
+ [[o, j + ge], r],
1333
+ [
1334
+ /(navigator|netscape\d?)\/([-\w\.]+)/i
1335
+ // Netscape
1336
+ ],
1337
+ [[o, "Netscape"], r],
1338
+ [
1339
+ /mobile vr; rv:([\w\.]+)\).+firefox/i
1340
+ // Firefox Reality
1341
+ ],
1342
+ [r, [o, ge + " Reality"]],
1343
+ [
1344
+ /ekiohf.+(flow)\/([\w\.]+)/i,
1345
+ // Flow
1346
+ /(swiftfox)/i,
1347
+ // Swiftfox
1348
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror|klar)[\/ ]?([\w\.\+]+)/i,
1349
+ // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror/Klar
1350
+ /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|palemoon|basilisk|waterfox)\/([-\w\.]+)$/i,
1351
+ // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
1352
+ /(firefox)\/([\w\.]+)/i,
1353
+ // Other Firefox-based
1354
+ /(mozilla)\/([\w\.]+) .+rv\:.+gecko\/\d+/i,
1355
+ // Mozilla
1356
+ // Other
1357
+ /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir|obigo|mosaic|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
1358
+ // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir/Obigo/Mosaic/Go/ICE/UP.Browser
1359
+ /(links) \(([\w\.]+)/i,
1360
+ // Links
1361
+ /panasonic;(viera)/i
1362
+ // Panasonic Viera
1363
+ ],
1364
+ [o, r],
1365
+ [
1366
+ /(cobalt)\/([\w\.]+)/i
1367
+ // Cobalt
1368
+ ],
1369
+ [o, [r, /[^\d\.]+./, re]]
1370
+ ],
1371
+ cpu: [
1372
+ [
1373
+ /\b(?:(amd|x|x86[-_]?|wow|win)64)\b/i
1374
+ // AMD64 (x64)
1375
+ ],
1376
+ [[M, "amd64"]],
1377
+ [
1378
+ /(ia32(?=;))/i,
1379
+ // IA32 (quicktime)
1380
+ /((?:i[346]|x)86)[;\)]/i
1381
+ // IA32 (x86)
1382
+ ],
1383
+ [[M, "ia32"]],
1384
+ [
1385
+ /\b(aarch64|arm(v?8e?l?|_?64))\b/i
1386
+ // ARM64
1387
+ ],
1388
+ [[M, "arm64"]],
1389
+ [
1390
+ /\b(arm(?:v[67])?ht?n?[fl]p?)\b/i
1391
+ // ARMHF
1392
+ ],
1393
+ [[M, "armhf"]],
1394
+ [
1395
+ // PocketPC mistakenly identified as PowerPC
1396
+ /windows (ce|mobile); ppc;/i
1397
+ ],
1398
+ [[M, "arm"]],
1399
+ [
1400
+ /((?:ppc|powerpc)(?:64)?)(?: mac|;|\))/i
1401
+ // PowerPC
1402
+ ],
1403
+ [[M, /ower/, re, z]],
1404
+ [
1405
+ /(sun4\w)[;\)]/i
1406
+ // SPARC
1407
+ ],
1408
+ [[M, "sparc"]],
1409
+ [
1410
+ /((?:avr32|ia64(?=;))|68k(?=\))|\barm(?=v(?:[1-7]|[5-7]1)l?|;|eabi)|(?=atmel )avr|(?:irix|mips|sparc)(?:64)?\b|pa-risc)/i
1411
+ // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC
1412
+ ],
1413
+ [[M, z]]
1414
+ ],
1415
+ device: [
1416
+ [
1417
+ //////////////////////////
1418
+ // MOBILES & TABLETS
1419
+ /////////////////////////
1420
+ // Samsung
1421
+ /\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i
1422
+ ],
1423
+ [c, [u, Te], [d, b]],
1424
+ [
1425
+ /\b((?:s[cgp]h|gt|sm)-\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
1426
+ /samsung[- ]([-\w]+)/i,
1427
+ /sec-(sgh\w+)/i
1428
+ ],
1429
+ [c, [u, Te], [d, m]],
1430
+ [
1431
+ // Apple
1432
+ /(?:\/|\()(ip(?:hone|od)[\w, ]*)(?:\/|;)/i
1433
+ // iPod/iPhone
1434
+ ],
1435
+ [c, [u, pe], [d, m]],
1436
+ [
1437
+ /\((ipad);[-\w\),; ]+apple/i,
1438
+ // iPad
1439
+ /applecoremedia\/[\w\.]+ \((ipad)/i,
1440
+ /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
1441
+ ],
1442
+ [c, [u, pe], [d, b]],
1443
+ [
1444
+ /(macintosh);/i
1445
+ ],
1446
+ [c, [u, pe]],
1447
+ [
1448
+ // Sharp
1449
+ /\b(sh-?[altvz]?\d\d[a-ekm]?)/i
1450
+ ],
1451
+ [c, [u, mt], [d, m]],
1452
+ [
1453
+ // Huawei
1454
+ /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i
1455
+ ],
1456
+ [c, [u, pt], [d, b]],
1457
+ [
1458
+ /(?:huawei|honor)([-\w ]+)[;\)]/i,
1459
+ /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i
1460
+ ],
1461
+ [c, [u, pt], [d, m]],
1462
+ [
1463
+ // Xiaomi
1464
+ /\b(poco[\w ]+|m2\d{3}j\d\d[a-z]{2})(?: bui|\))/i,
1465
+ // Xiaomi POCO
1466
+ /\b; (\w+) build\/hm\1/i,
1467
+ // Xiaomi Hongmi 'numeric' models
1468
+ /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
1469
+ // Xiaomi Hongmi
1470
+ /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i,
1471
+ // Xiaomi Redmi
1472
+ /oid[^\)]+; (m?[12][0-389][01]\w{3,6}[c-y])( bui|; wv|\))/i,
1473
+ // Xiaomi Redmi 'numeric' models
1474
+ /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i
1475
+ // Xiaomi Mi
1476
+ ],
1477
+ [[c, /_/g, " "], [u, We], [d, m]],
1478
+ [
1479
+ /oid[^\)]+; (2\d{4}(283|rpbf)[cgl])( bui|\))/i,
1480
+ // Redmi Pad
1481
+ /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i
1482
+ // Mi Pad tablets
1483
+ ],
1484
+ [[c, /_/g, " "], [u, We], [d, b]],
1485
+ [
1486
+ // OPPO
1487
+ /; (\w+) bui.+ oppo/i,
1488
+ /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i
1489
+ ],
1490
+ [c, [u, "OPPO"], [d, m]],
1491
+ [
1492
+ // Vivo
1493
+ /vivo (\w+)(?: bui|\))/i,
1494
+ /\b(v[12]\d{3}\w?[at])(?: bui|;)/i
1495
+ ],
1496
+ [c, [u, "Vivo"], [d, m]],
1497
+ [
1498
+ // Realme
1499
+ /\b(rmx[1-3]\d{3})(?: bui|;|\))/i
1500
+ ],
1501
+ [c, [u, "Realme"], [d, m]],
1502
+ [
1503
+ // Motorola
1504
+ /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
1505
+ /\bmot(?:orola)?[- ](\w*)/i,
1506
+ /((?:moto[\w\(\) ]+|xt\d{3,4}|nexus 6)(?= bui|\)))/i
1507
+ ],
1508
+ [c, [u, wt], [d, m]],
1509
+ [
1510
+ /\b(mz60\d|xoom[2 ]{0,2}) build\//i
1511
+ ],
1512
+ [c, [u, wt], [d, b]],
1513
+ [
1514
+ // LG
1515
+ /((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
1516
+ ],
1517
+ [c, [u, qe], [d, b]],
1518
+ [
1519
+ /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
1520
+ /\blg[-e;\/ ]+((?!browser|netcast|android tv)\w+)/i,
1521
+ /\blg-?([\d\w]+) bui/i
1522
+ ],
1523
+ [c, [u, qe], [d, m]],
1524
+ [
1525
+ // Lenovo
1526
+ /(ideatab[-\w ]+)/i,
1527
+ /lenovo ?(s[56]000[-\w]+|tab(?:[\w ]+)|yt[-\d\w]{6}|tb[-\d\w]{6})/i
1528
+ ],
1529
+ [c, [u, gt], [d, b]],
1530
+ [
1531
+ // Nokia
1532
+ /(?:maemo|nokia).*(n900|lumia \d+)/i,
1533
+ /nokia[-_ ]?([-\w\.]*)/i
1534
+ ],
1535
+ [[c, /_/g, " "], [u, "Nokia"], [d, m]],
1536
+ [
1537
+ // Google
1538
+ /(pixel c)\b/i
1539
+ // Google Pixel C
1540
+ ],
1541
+ [c, [u, Ie], [d, b]],
1542
+ [
1543
+ /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i
1544
+ // Google Pixel
1545
+ ],
1546
+ [c, [u, Ie], [d, m]],
1547
+ [
1548
+ // Sony
1549
+ /droid.+ (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-a\w[4-7][12])(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i
1550
+ ],
1551
+ [c, [u, Ae], [d, m]],
1552
+ [
1553
+ /sony tablet [ps]/i,
1554
+ /\b(?:sony)?sgp\w+(?: bui|\))/i
1555
+ ],
1556
+ [[c, "Xperia Tablet"], [u, Ae], [d, b]],
1557
+ [
1558
+ // OnePlus
1559
+ / (kb2005|in20[12]5|be20[12][59])\b/i,
1560
+ /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
1561
+ ],
1562
+ [c, [u, "OnePlus"], [d, m]],
1563
+ [
1564
+ // Amazon
1565
+ /(alexa)webm/i,
1566
+ /(kf[a-z]{2}wi|aeo[c-r]{2})( bui|\))/i,
1567
+ // Kindle Fire without Silk / Echo Show
1568
+ /(kf[a-z]+)( bui|\)).+silk\//i
1569
+ // Kindle Fire HD
1570
+ ],
1571
+ [c, [u, Ce], [d, b]],
1572
+ [
1573
+ /((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i
1574
+ // Fire Phone
1575
+ ],
1576
+ [[c, /(.+)/g, "Fire Phone $1"], [u, Ce], [d, m]],
1577
+ [
1578
+ // BlackBerry
1579
+ /(playbook);[-\w\),; ]+(rim)/i
1580
+ // BlackBerry PlayBook
1581
+ ],
1582
+ [c, u, [d, b]],
1583
+ [
1584
+ /\b((?:bb[a-f]|st[hv])100-\d)/i,
1585
+ /\(bb10; (\w+)/i
1586
+ // BlackBerry 10
1587
+ ],
1588
+ [c, [u, ht], [d, m]],
1589
+ [
1590
+ // Asus
1591
+ /(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i
1592
+ ],
1593
+ [c, [u, ut], [d, b]],
1594
+ [
1595
+ / (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i
1596
+ ],
1597
+ [c, [u, ut], [d, m]],
1598
+ [
1599
+ // HTC
1600
+ /(nexus 9)/i
1601
+ // HTC Nexus 9
1602
+ ],
1603
+ [c, [u, "HTC"], [d, b]],
1604
+ [
1605
+ /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
1606
+ // HTC
1607
+ // ZTE
1608
+ /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
1609
+ /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i
1610
+ // Alcatel/GeeksPhone/Nexian/Panasonic/Sony
1611
+ ],
1612
+ [u, [c, /_/g, " "], [d, m]],
1613
+ [
1614
+ // Acer
1615
+ /droid.+; ([ab][1-7]-?[0178a]\d\d?)/i
1616
+ ],
1617
+ [c, [u, "Acer"], [d, b]],
1618
+ [
1619
+ // Meizu
1620
+ /droid.+; (m[1-5] note) bui/i,
1621
+ /\bmz-([-\w]{2,})/i
1622
+ ],
1623
+ [c, [u, "Meizu"], [d, m]],
1624
+ [
1625
+ // Ulefone
1626
+ /; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i
1627
+ ],
1628
+ [c, [u, "Ulefone"], [d, m]],
1629
+ [
1630
+ // MIXED
1631
+ /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron|infinix|tecno)[-_ ]?([-\w]*)/i,
1632
+ // BlackBerry/BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron
1633
+ /(hp) ([\w ]+\w)/i,
1634
+ // HP iPAQ
1635
+ /(asus)-?(\w+)/i,
1636
+ // Asus
1637
+ /(microsoft); (lumia[\w ]+)/i,
1638
+ // Microsoft Lumia
1639
+ /(lenovo)[-_ ]?([-\w]+)/i,
1640
+ // Lenovo
1641
+ /(jolla)/i,
1642
+ // Jolla
1643
+ /(oppo) ?([\w ]+) bui/i
1644
+ // OPPO
1645
+ ],
1646
+ [u, c, [d, m]],
1647
+ [
1648
+ /(kobo)\s(ereader|touch)/i,
1649
+ // Kobo
1650
+ /(archos) (gamepad2?)/i,
1651
+ // Archos
1652
+ /(hp).+(touchpad(?!.+tablet)|tablet)/i,
1653
+ // HP TouchPad
1654
+ /(kindle)\/([\w\.]+)/i
1655
+ // Kindle
1656
+ ],
1657
+ [u, c, [d, b]],
1658
+ [
1659
+ /(surface duo)/i
1660
+ // Surface Duo
1661
+ ],
1662
+ [c, [u, xe], [d, b]],
1663
+ [
1664
+ /droid [\d\.]+; (fp\du?)(?: b|\))/i
1665
+ // Fairphone
1666
+ ],
1667
+ [c, [u, "Fairphone"], [d, m]],
1668
+ [
1669
+ /(shield[\w ]+) b/i
1670
+ // Nvidia Shield Tablets
1671
+ ],
1672
+ [c, [u, "Nvidia"], [d, b]],
1673
+ [
1674
+ /(sprint) (\w+)/i
1675
+ // Sprint Phones
1676
+ ],
1677
+ [u, c, [d, m]],
1678
+ [
1679
+ /(kin\.[onetw]{3})/i
1680
+ // Microsoft Kin
1681
+ ],
1682
+ [[c, /\./g, " "], [u, xe], [d, m]],
1683
+ [
1684
+ /droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i
1685
+ // Zebra
1686
+ ],
1687
+ [c, [u, $e], [d, b]],
1688
+ [
1689
+ /droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i
1690
+ ],
1691
+ [c, [u, $e], [d, m]],
1692
+ [
1693
+ ///////////////////
1694
+ // SMARTTVS
1695
+ ///////////////////
1696
+ /smart-tv.+(samsung)/i
1697
+ // Samsung
1698
+ ],
1699
+ [u, [d, I]],
1700
+ [
1701
+ /hbbtv.+maple;(\d+)/i
1702
+ ],
1703
+ [[c, /^/, "SmartTV"], [u, Te], [d, I]],
1704
+ [
1705
+ /(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i
1706
+ // LG SmartTV
1707
+ ],
1708
+ [[u, qe], [d, I]],
1709
+ [
1710
+ /(apple) ?tv/i
1711
+ // Apple TV
1712
+ ],
1713
+ [u, [c, pe + " TV"], [d, I]],
1714
+ [
1715
+ /crkey/i
1716
+ // Google Chromecast
1717
+ ],
1718
+ [[c, Re + "cast"], [u, Ie], [d, I]],
1719
+ [
1720
+ /droid.+aft(\w+)( bui|\))/i
1721
+ // Fire TV
1722
+ ],
1723
+ [c, [u, Ce], [d, I]],
1724
+ [
1725
+ /\(dtv[\);].+(aquos)/i,
1726
+ /(aquos-tv[\w ]+)\)/i
1727
+ // Sharp
1728
+ ],
1729
+ [c, [u, mt], [d, I]],
1730
+ [
1731
+ /(bravia[\w ]+)( bui|\))/i
1732
+ // Sony
1733
+ ],
1734
+ [c, [u, Ae], [d, I]],
1735
+ [
1736
+ /(mitv-\w{5}) bui/i
1737
+ // Xiaomi
1738
+ ],
1739
+ [c, [u, We], [d, I]],
1740
+ [
1741
+ /Hbbtv.*(technisat) (.*);/i
1742
+ // TechniSAT
1743
+ ],
1744
+ [u, c, [d, I]],
1745
+ [
1746
+ /\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i,
1747
+ // Roku
1748
+ /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i
1749
+ // HbbTV devices
1750
+ ],
1751
+ [[u, be], [c, be], [d, I]],
1752
+ [
1753
+ /\b(android tv|smart[- ]?tv|opera tv|tv; rv:)\b/i
1754
+ // SmartTV from Unidentified Vendors
1755
+ ],
1756
+ [[d, I]],
1757
+ [
1758
+ ///////////////////
1759
+ // CONSOLES
1760
+ ///////////////////
1761
+ /(ouya)/i,
1762
+ // Ouya
1763
+ /(nintendo) (\w+)/i
1764
+ // Nintendo
1765
+ ],
1766
+ [u, c, [d, K]],
1767
+ [
1768
+ /droid.+; (shield) bui/i
1769
+ // Nvidia
1770
+ ],
1771
+ [c, [u, "Nvidia"], [d, K]],
1772
+ [
1773
+ /(playstation \w+)/i
1774
+ // Playstation
1775
+ ],
1776
+ [c, [u, Ae], [d, K]],
1777
+ [
1778
+ /\b(xbox(?: one)?(?!; xbox))[\); ]/i
1779
+ // Microsoft Xbox
1780
+ ],
1781
+ [c, [u, xe], [d, K]],
1782
+ [
1783
+ ///////////////////
1784
+ // WEARABLES
1785
+ ///////////////////
1786
+ /((pebble))app/i
1787
+ // Pebble
1788
+ ],
1789
+ [u, c, [d, X]],
1790
+ [
1791
+ /(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i
1792
+ // Apple Watch
1793
+ ],
1794
+ [c, [u, pe], [d, X]],
1795
+ [
1796
+ /droid.+; (glass) \d/i
1797
+ // Google Glass
1798
+ ],
1799
+ [c, [u, Ie], [d, X]],
1800
+ [
1801
+ /droid.+; (wt63?0{2,3})\)/i
1802
+ ],
1803
+ [c, [u, $e], [d, X]],
1804
+ [
1805
+ /(quest( 2| pro)?)/i
1806
+ // Oculus Quest
1807
+ ],
1808
+ [c, [u, ft], [d, X]],
1809
+ [
1810
+ ///////////////////
1811
+ // EMBEDDED
1812
+ ///////////////////
1813
+ /(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i
1814
+ // Tesla
1815
+ ],
1816
+ [u, [d, Ye]],
1817
+ [
1818
+ /(aeobc)\b/i
1819
+ // Echo Dot
1820
+ ],
1821
+ [c, [u, Ce], [d, Ye]],
1822
+ [
1823
+ ////////////////////
1824
+ // MIXED (GENERIC)
1825
+ ///////////////////
1826
+ /droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew).+? mobile safari/i
1827
+ // Android Phones from Unidentified Vendors
1828
+ ],
1829
+ [c, [d, m]],
1830
+ [
1831
+ /droid .+?; ([^;]+?)(?: bui|\) applew).+?(?! mobile) safari/i
1832
+ // Android Tablets from Unidentified Vendors
1833
+ ],
1834
+ [c, [d, b]],
1835
+ [
1836
+ /\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i
1837
+ // Unidentifiable Tablet
1838
+ ],
1839
+ [[d, b]],
1840
+ [
1841
+ /(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i
1842
+ // Unidentifiable Mobile
1843
+ ],
1844
+ [[d, m]],
1845
+ [
1846
+ /(android[-\w\. ]{0,9});.+buil/i
1847
+ // Generic Android Device
1848
+ ],
1849
+ [c, [u, "Generic"]]
1850
+ ],
1851
+ engine: [
1852
+ [
1853
+ /windows.+ edge\/([\w\.]+)/i
1854
+ // EdgeHTML
1855
+ ],
1856
+ [r, [o, pi + "HTML"]],
1857
+ [
1858
+ /webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i
1859
+ // Blink
1860
+ ],
1861
+ [r, [o, "Blink"]],
1862
+ [
1863
+ /(presto)\/([\w\.]+)/i,
1864
+ // Presto
1865
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna)\/([\w\.]+)/i,
1866
+ // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna
1867
+ /ekioh(flow)\/([\w\.]+)/i,
1868
+ // Flow
1869
+ /(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i,
1870
+ // KHTML/Tasman/Links
1871
+ /(icab)[\/ ]([23]\.[\d\.]+)/i,
1872
+ // iCab
1873
+ /\b(libweb)/i
1874
+ ],
1875
+ [o, r],
1876
+ [
1877
+ /rv\:([\w\.]{1,9})\b.+(gecko)/i
1878
+ // Gecko
1879
+ ],
1880
+ [r, o]
1881
+ ],
1882
+ os: [
1883
+ [
1884
+ // Windows
1885
+ /microsoft (windows) (vista|xp)/i
1886
+ // Windows (iTunes)
1887
+ ],
1888
+ [o, r],
1889
+ [
1890
+ /(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i
1891
+ // Windows Phone
1892
+ ],
1893
+ [o, [r, Oe, vt]],
1894
+ [
1895
+ /windows nt 6\.2; (arm)/i,
1896
+ // Windows RT
1897
+ /windows[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i,
1898
+ /(?:win(?=3|9|n)|win 9x )([nt\d\.]+)/i
1899
+ ],
1900
+ [[r, Oe, vt], [o, et]],
1901
+ [
1902
+ // iOS/macOS
1903
+ /ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i,
1904
+ // iOS
1905
+ /(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
1906
+ /cfnetwork\/.+darwin/i
1907
+ ],
1908
+ [[r, /_/g, "."], [o, "iOS"]],
1909
+ [
1910
+ /(mac os x) ?([\w\. ]*)/i,
1911
+ /(macintosh|mac_powerpc\b)(?!.+haiku)/i
1912
+ // Mac OS
1913
+ ],
1914
+ [[o, "macOS"], [r, /_/g, "."]],
1915
+ [
1916
+ // Mobile OSes
1917
+ /droid ([\w\.]+)\b.+(android[- ]x86|harmonyos)/i
1918
+ // Android-x86/HarmonyOS
1919
+ ],
1920
+ [r, o],
1921
+ [
1922
+ // Android/WebOS/QNX/Bada/RIM/Maemo/MeeGo/Sailfish OS
1923
+ /(android|webos|qnx|bada|rim tablet os|maemo|meego|sailfish)[-\/ ]?([\w\.]*)/i,
1924
+ /(blackberry)\w*\/([\w\.]*)/i,
1925
+ // Blackberry
1926
+ /(tizen|kaios)[\/ ]([\w\.]+)/i,
1927
+ // Tizen/KaiOS
1928
+ /\((series40);/i
1929
+ // Series 40
1930
+ ],
1931
+ [o, r],
1932
+ [
1933
+ /\(bb(10);/i
1934
+ // BlackBerry 10
1935
+ ],
1936
+ [r, [o, ht]],
1937
+ [
1938
+ /(?:symbian ?os|symbos|s60(?=;)|series60)[-\/ ]?([\w\.]*)/i
1939
+ // Symbian
1940
+ ],
1941
+ [r, [o, "Symbian"]],
1942
+ [
1943
+ /mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i
1944
+ // Firefox OS
1945
+ ],
1946
+ [r, [o, ge + " OS"]],
1947
+ [
1948
+ /web0s;.+rt(tv)/i,
1949
+ /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i
1950
+ // WebOS
1951
+ ],
1952
+ [r, [o, "webOS"]],
1953
+ [
1954
+ /watch(?: ?os[,\/]|\d,\d\/)([\d\.]+)/i
1955
+ // watchOS
1956
+ ],
1957
+ [r, [o, "watchOS"]],
1958
+ [
1959
+ // Google Chromecast
1960
+ /crkey\/([\d\.]+)/i
1961
+ // Google Chromecast
1962
+ ],
1963
+ [r, [o, Re + "cast"]],
1964
+ [
1965
+ /(cros) [\w]+(?:\)| ([\w\.]+)\b)/i
1966
+ // Chromium OS
1967
+ ],
1968
+ [[o, "Chrome OS"], r],
1969
+ [
1970
+ // Smart TVs
1971
+ /panasonic;(viera)/i,
1972
+ // Panasonic Viera
1973
+ /(netrange)mmh/i,
1974
+ // Netrange
1975
+ /(nettv)\/(\d+\.[\w\.]+)/i,
1976
+ // NetTV
1977
+ // Console
1978
+ /(nintendo|playstation) (\w+)/i,
1979
+ // Nintendo/Playstation
1980
+ /(xbox); +xbox ([^\);]+)/i,
1981
+ // Microsoft Xbox (360, One, X, S, Series X, Series S)
1982
+ // Other
1983
+ /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,
1984
+ // Joli/Palm
1985
+ /(mint)[\/\(\) ]?(\w*)/i,
1986
+ // Mint
1987
+ /(mageia|vectorlinux)[; ]/i,
1988
+ // Mageia/VectorLinux
1989
+ /([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
1990
+ // Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware/Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus/Raspbian/Plan9/Minix/RISCOS/Contiki/Deepin/Manjaro/elementary/Sabayon/Linspire
1991
+ /(hurd|linux) ?([\w\.]*)/i,
1992
+ // Hurd/Linux
1993
+ /(gnu) ?([\w\.]*)/i,
1994
+ // GNU
1995
+ /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,
1996
+ // FreeBSD/NetBSD/OpenBSD/PC-BSD/GhostBSD/DragonFly
1997
+ /(haiku) (\w+)/i
1998
+ // Haiku
1999
+ ],
2000
+ [o, r],
2001
+ [
2002
+ /(sunos) ?([\w\.\d]*)/i
2003
+ // Solaris
2004
+ ],
2005
+ [[o, "Solaris"], r],
2006
+ [
2007
+ /((?:open)?solaris)[-\/ ]?([\w\.]*)/i,
2008
+ // Solaris
2009
+ /(aix) ((\d)(?=\.|\)| )[\w\.])*/i,
2010
+ // AIX
2011
+ /\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux|serenityos)/i,
2012
+ // BeOS/OS2/AmigaOS/MorphOS/OpenVMS/Fuchsia/HP-UX/SerenityOS
2013
+ /(unix) ?([\w\.]*)/i
2014
+ // UNIX
2015
+ ],
2016
+ [o, r]
2017
+ ]
2018
+ }, Pe = function() {
2019
+ var i = { init: {}, isIgnore: {}, isIgnoreRgx: {}, toString: {} };
2020
+ return _.call(i.init, [
2021
+ [T, [o, r, fe]],
2022
+ [O, [M]],
2023
+ [P, [d, c, u]],
2024
+ [L, [o, r]],
2025
+ [R, [o, r]]
2026
+ ]), _.call(i.isIgnore, [
2027
+ [T, [r, fe]],
2028
+ [L, [r]],
2029
+ [R, [r]]
2030
+ ]), _.call(i.isIgnoreRgx, [
2031
+ [T, / ?browser$/i],
2032
+ [R, / ?os$/i]
2033
+ ]), _.call(i.toString, [
2034
+ [T, [o, r]],
2035
+ [O, [M]],
2036
+ [P, [u, c]],
2037
+ [L, [o, r]],
2038
+ [R, [o, r]]
2039
+ ]), i;
2040
+ }(), mi = function(i, t) {
2041
+ var e = Pe.init[t], s = Pe.isIgnore[t] || 0, n = Pe.isIgnoreRgx[t] || 0, l = Pe.toString[t] || 0;
2042
+ function a() {
2043
+ _.call(this, e);
2044
+ }
2045
+ return a.prototype.getItem = function() {
2046
+ return i;
2047
+ }, a.prototype.withClientHints = function() {
2048
+ return G ? G.getHighEntropyValues(Lt).then(function(h) {
2049
+ return i.setCH(new _t(h, !1)).parseCH().get();
2050
+ }) : i.parseCH().get();
2051
+ }, a.prototype.withFeatureCheck = function() {
2052
+ return i.detectFeature().get();
2053
+ }, t != Y && (a.prototype.is = function(h) {
2054
+ var p = !1;
2055
+ for (var g in this)
2056
+ if (this.hasOwnProperty(g) && !tt(s, g) && z(n ? W(n, this[g]) : this[g]) == z(n ? W(n, h) : h)) {
2057
+ if (p = !0, h != H)
2058
+ break;
2059
+ } else if (h == H && p) {
2060
+ p = !p;
2061
+ break;
2062
+ }
2063
+ return p;
2064
+ }, a.prototype.toString = function() {
2065
+ var h = re;
2066
+ for (var p in l)
2067
+ typeof this[l[p]] !== H && (h += (h ? " " : re) + this[l[p]]);
2068
+ return h || H;
2069
+ }), G || (a.prototype.then = function(h) {
2070
+ var p = this, g = function() {
2071
+ for (var A in p)
2072
+ p.hasOwnProperty(A) && (this[A] = p[A]);
2073
+ };
2074
+ g.prototype = {
2075
+ is: a.prototype.is,
2076
+ toString: a.prototype.toString
2077
+ };
2078
+ var f = new g();
2079
+ return h(f), f;
2080
+ }), new a();
2081
+ };
2082
+ function _t(i, t) {
2083
+ if (i = i || {}, _.call(this, Lt), t)
2084
+ _.call(this, [
2085
+ [it, je(i[V])],
2086
+ [st, je(i[oi])],
2087
+ [m, /\?1/.test(i[li])],
2088
+ [c, me(i[ui])],
2089
+ [J, me(i[Ot])],
2090
+ [nt, me(i[hi])],
2091
+ [M, me(i[ri])],
2092
+ [q, je(i[di])],
2093
+ [De, me(i[ci])]
2094
+ ]);
2095
+ else
2096
+ for (var e in i)
2097
+ this.hasOwnProperty(e) && typeof i[e] !== H && (this[e] = i[e]);
2098
+ }
2099
+ function Mt(i, t, e, s) {
2100
+ return this.get = function(n) {
2101
+ return n ? this.data.hasOwnProperty(n) ? this.data[n] : void 0 : this.data;
2102
+ }, this.set = function(n, l) {
2103
+ return this.data[n] = l, this;
2104
+ }, this.setCH = function(n) {
2105
+ return this.uaCH = n, this;
2106
+ }, this.detectFeature = function() {
2107
+ if (C && C.userAgent == this.ua)
2108
+ switch (this.itemType) {
2109
+ case T:
2110
+ C.brave && typeof C.brave.isBrave == Ke && this.set(o, "Brave");
2111
+ break;
2112
+ case P:
2113
+ !this.get(d) && G && G[m] && this.set(d, m), this.get(c) == "Macintosh" && C && typeof C.standalone !== H && C.maxTouchPoints && C.maxTouchPoints > 2 && this.set(c, "iPad").set(d, b);
2114
+ break;
2115
+ case R:
2116
+ !this.get(o) && G && G[J] && this.set(o, G[J]);
2117
+ break;
2118
+ case Y:
2119
+ var n = this.data, l = function(a) {
2120
+ return n[a].getItem().detectFeature().get();
2121
+ };
2122
+ this.set(T, l(T)).set(O, l(O)).set(P, l(P)).set(L, l(L)).set(R, l(R));
2123
+ }
2124
+ return this;
2125
+ }, this.parseUA = function() {
2126
+ return this.itemType != Y && Et.call(this.data, this.ua, this.rgxMap), this.itemType == T && this.set(fe, Qe(this.get(r))), this;
2127
+ }, this.parseCH = function() {
2128
+ var n = this.uaCH, l = this.rgxMap;
2129
+ switch (this.itemType) {
2130
+ case T:
2131
+ var a = n[st] || n[it], h;
2132
+ if (a)
2133
+ for (var p in a) {
2134
+ var g = W(/(Google|Microsoft) /, a[p].brand || a[p]), f = a[p].version;
2135
+ !/not.a.brand/i.test(g) && (!h || /chrom/i.test(h) && !/chromi/i.test(g)) && (this.set(o, g).set(r, f).set(fe, Qe(f)), h = g);
2136
+ }
2137
+ break;
2138
+ case O:
2139
+ var A = n[M];
2140
+ A && (A && n[De] == "64" && (A += "64"), Et.call(this.data, A + ";", l));
2141
+ break;
2142
+ case P:
2143
+ if (n[m] && this.set(d, m), n[c] && this.set(c, n[c]), n[c] == "Xbox" && this.set(d, K).set(u, xe), n[q]) {
2144
+ var D;
2145
+ if (typeof n[q] != "string")
2146
+ for (var B = 0; !D && B < n[q].length; )
2147
+ D = Oe(n[q][B++], kt);
2148
+ else
2149
+ D = Oe(n[q], kt);
2150
+ this.set(d, D);
2151
+ }
2152
+ break;
2153
+ case R:
2154
+ var le = n[J];
2155
+ if (le) {
2156
+ var x = n[nt];
2157
+ le == et && (x = parseInt(Qe(x), 10) >= 13 ? "11" : "10"), this.set(o, le).set(r, x);
2158
+ }
2159
+ this.get(o) == et && n[c] == "Xbox" && this.set(o, "Xbox").set(r, void 0);
2160
+ break;
2161
+ case Y:
2162
+ var Dt = this.data, ue = function(Bt) {
2163
+ return Dt[Bt].getItem().setCH(n).parseCH().get();
2164
+ };
2165
+ this.set(T, ue(T)).set(O, ue(O)).set(P, ue(P)).set(L, ue(L)).set(R, ue(R));
2166
+ }
2167
+ return this;
2168
+ }, _.call(this, [
2169
+ ["itemType", i],
2170
+ ["ua", t],
2171
+ ["uaCH", s],
2172
+ ["rgxMap", e],
2173
+ ["data", mi(this, i)]
2174
+ ]), this;
2175
+ }
2176
+ function F(i, t, e) {
2177
+ if (typeof i === ce ? (yt(i) ? (typeof t === ce && (e = t), t = i) : (e = i, t = void 0), i = void 0) : typeof i === Je && !yt(t) && (e = t, t = void 0), !(this instanceof F))
2178
+ return new F(i, t, e).getResult();
2179
+ var s = typeof i === Je ? i : (
2180
+ // Passed user-agent string
2181
+ C && C.userAgent ? C.userAgent : (
2182
+ // navigator.userAgent
2183
+ e && e[lt] ? e[lt] : (
2184
+ // User-Agent from passed headers
2185
+ re
2186
+ )
2187
+ )
2188
+ ), n = new _t(e, !0), l = t ? wi(St, t) : St, a = function(h) {
2189
+ return h == Y ? function() {
2190
+ return new Mt(h, s, l, n).set("ua", s).set(T, this.getBrowser()).set(O, this.getCPU()).set(P, this.getDevice()).set(L, this.getEngine()).set(R, this.getOS()).get();
2191
+ } : function() {
2192
+ return new Mt(h, s, l[h], n).parseUA().get();
2193
+ };
2194
+ };
2195
+ return _.call(this, [
2196
+ ["getBrowser", a(T)],
2197
+ ["getCPU", a(O)],
2198
+ ["getDevice", a(P)],
2199
+ ["getEngine", a(L)],
2200
+ ["getOS", a(R)],
2201
+ ["getResult", a(Y)],
2202
+ ["getUA", function() {
2203
+ return s;
2204
+ }],
2205
+ ["setUA", function(h) {
2206
+ return de(h) && (s = h.length > Ze ? be(h, Ze) : h), this;
2207
+ }]
2208
+ ]).setUA(s), this;
2209
+ }
2210
+ F.VERSION = ai;
2211
+ F.BROWSER = Be([o, r, fe]);
2212
+ F.CPU = Be([M]);
2213
+ F.DEVICE = Be([c, u, d, K, m, I, b, X, Ye]);
2214
+ F.ENGINE = F.OS = Be([o, r]);
2215
+ class fi {
2216
+ constructor(t, e) {
2217
+ w(this, "trackers");
2218
+ w(this, "config");
2219
+ this.trackers = t, this.config = e;
2220
+ }
2221
+ on(t, e, s) {
2222
+ const n = function(a) {
2223
+ a.data.message !== `kalamba:wrapper-telemetry:${t}` && a.data.message !== `kalamba:wrapper:${t}` || e(a.data.payload);
2224
+ };
2225
+ window.addEventListener("message", n, s);
2226
+ }
2227
+ track(t, e) {
2228
+ this.trackers.forEach((s) => s.track(t, e));
2229
+ }
2230
+ }
2231
+ function Ct(i) {
2232
+ return i.reduce((t, e) => t + e, 0);
2233
+ }
2234
+ function bi(i) {
2235
+ const t = i.length, e = Ct(i) / t, s = i.map((l) => Math.pow(l - e, 2)), n = Ct(s) / t;
2236
+ return Math.sqrt(n);
2237
+ }
2238
+ class It {
2239
+ constructor() {
2240
+ w(this, "rafId", -1);
2241
+ w(this, "startTime", 0);
2242
+ w(this, "stopTime", 0);
2243
+ w(this, "frames", []);
2244
+ w(this, "calculateFPS", () => {
2245
+ const t = Math.floor((this.stopTime - this.startTime) / 1e3);
2246
+ return this.frames.map((e) => Math.floor((e - this.startTime) / 1e3)).reduce((e, s, n, l) => (l[n] !== l[n - 1] ? e.push(1) : e[e.length - 1]++, e), []).slice(0, t);
2247
+ });
2248
+ w(this, "getReport", () => {
2249
+ const t = this.calculateFPS(), e = Math.floor(this.frames.length / ((this.stopTime - this.startTime) / 1e3)), s = t.length > 0 ? Math.max(...t) : e, n = t.length > 0 ? Math.min(...t) : e, l = t.length > 0 ? bi(t) : 0;
2250
+ return { fpsAvg: e, fpsMax: s, fpsMin: n, fpsStdDev: l };
2251
+ });
2252
+ w(this, "start", () => {
2253
+ this.startTime = Date.now(), this.trackFrames();
2254
+ });
2255
+ w(this, "stop", () => {
2256
+ cancelAnimationFrame(this.rafId), this.stopTime = Date.now();
2257
+ });
2258
+ w(this, "trackFrames", () => {
2259
+ this.frames.push(Date.now()), this.rafId = requestAnimationFrame(this.trackFrames);
2260
+ });
2261
+ }
2262
+ }
2263
+ const yi = "landscape", Ei = "portrait";
2264
+ function vi() {
2265
+ try {
2266
+ const i = document.createElement("canvas");
2267
+ return !!window.WebGLRenderingContext && (i.getContext("webgl") || i.getContext("experimental-webgl")) instanceof WebGLRenderingContext;
2268
+ } catch {
2269
+ return !1;
2270
+ }
2271
+ }
2272
+ async function ki() {
2273
+ if (!window.createImageBitmap)
2274
+ return !1;
2275
+ const e = await (await fetch("data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoCAAEAAQAcJaQAA3AA/v3AgAA=")).blob();
2276
+ try {
2277
+ return await createImageBitmap(e), !0;
2278
+ } catch {
2279
+ return !1;
2280
+ }
2281
+ }
2282
+ function Xe() {
2283
+ return window.innerWidth >= window.innerHeight ? yi : Ei;
2284
+ }
2285
+ var Le, ee, te, ie, ve, _e, ke, Fe;
2286
+ class Bi extends fi {
2287
+ constructor(...e) {
2288
+ super(...e);
2289
+ w(this, "FPS_SAMPLE_INTERVAL", 1e4);
2290
+ // wrapper state
2291
+ v(this, Le, 0);
2292
+ v(this, ee, "");
2293
+ v(this, te, void 0);
2294
+ v(this, ie, void 0);
2295
+ v(this, ve, !1);
2296
+ v(this, _e, !1);
2297
+ v(this, ke, "");
2298
+ v(this, Fe, []);
2299
+ E(this, te, {}), E(this, ie, this.deviceInfo()), this.on("state", ({ balance: s, version: n }) => {
2300
+ E(this, ee, n), E(this, Le, s);
2301
+ }), this.on("autoplay", ({ action: s }) => {
2302
+ ["start", "resume"].includes(s) ? E(this, ve, !0) : E(this, ve, !1);
2303
+ }), this.on("settings", ({ fastPlay: s }) => {
2304
+ s !== void 0 && E(this, _e, s);
2305
+ }), this.registerEvents();
2306
+ }
2307
+ async registerEvents() {
2308
+ y(this, ie).then((e) => {
2309
+ this.track("Device Information", e);
2310
+ }), this.on("loadStart", () => {
2311
+ this.track("Game Loading", { progress: 0, step: "initial" });
2312
+ }), this.on("loadProgress", (e) => {
2313
+ this.track("Game Loading", { progress: e.progress });
2314
+ }), this.on("loadEnd", () => {
2315
+ this.track("Game Loading", { progress: 100, step: "complete" });
2316
+ }), this.on("error", (e) => {
2317
+ this.track("System Message", {
2318
+ systemMessageText: e.messageKey,
2319
+ systemMessageType: e.type
2320
+ });
2321
+ }), this.on("openGameResponse", async (e) => {
2322
+ E(this, ke, e.data.gameState.stateTypeNextRound), E(this, te, {
2323
+ balanceInCoins: e.balance,
2324
+ clientVersion: y(this, ee),
2325
+ coinValueInCents: this.config.api.coinValueInCents,
2326
+ coinValueInCentsFloat: this.config.api.coinValueInCents,
2327
+ currency: this.config.api.currency,
2328
+ defaultBaseBet: e.data.additionalConfigData.defaultBet.baseBet,
2329
+ defaultBetMultiplier: e.data.additionalConfigData.defaultBet.betMultiplier,
2330
+ environment: "release",
2331
+ gameCode: this.config.api.game,
2332
+ gameCodeServer: this.config.api.game,
2333
+ gameModelFile: e.data.additionalConfigData.gameModelFile,
2334
+ jurisdiction: this.config.api.jurisdiction,
2335
+ languageCode: this.config.ui.language,
2336
+ operatorName: "kalamba",
2337
+ partnerId: this.config.api.brand,
2338
+ partnerParentId: this.config.api.integration,
2339
+ platform: "WEB",
2340
+ playMode: this.config.api.playMode,
2341
+ referrer: window.location.hostname,
2342
+ // rootTrackingSessionID: 'unknown',
2343
+ // rtpVariant: 'unknown',
2344
+ serverVersion: e.data.gameConfigData.metaData.version
2345
+ // testVariants: '',
2346
+ }), this.track("Game Open", y(this, te));
2347
+ }), this.on("playCycleEnd", async (e) => {
2348
+ const s = await y(this, ie), { baseBet: n, betMultiplier: l, specialAction: a } = e.data.gameState.lastPlacedMainGameBet ?? {}, h = e.balance, p = e.data.gameState.totalBetFromCurrentGameCycle, g = e.data.gameState.totalWinFromCurrentGameCycle, f = g - p, A = a || "spin", D = e.data.gameState.cycleId;
2349
+ this.track("Betting Activity", {
2350
+ balance: h - f,
2351
+ balanceAfter: h,
2352
+ baseBet: n,
2353
+ // baseBetIndex,
2354
+ betMultiplier: l,
2355
+ betType: A,
2356
+ gameVersion: y(this, ee),
2357
+ coinValueInCents: this.config.api.coinValueInCents,
2358
+ coinValueInCentsFloat: this.config.api.coinValueInCents,
2359
+ currency: this.config.api.currency,
2360
+ environment: "release",
2361
+ gameCode: this.config.api.game,
2362
+ gameCodeServer: this.config.api.game,
2363
+ isMobile: s.isMobile,
2364
+ netResult: f,
2365
+ operatorName: "kalamba",
2366
+ orientation: Xe(),
2367
+ partnerId: this.config.api.brand,
2368
+ partnerParentId: this.config.api.integration,
2369
+ platform: "WEB",
2370
+ playMode: this.config.api.playMode,
2371
+ roundId: D,
2372
+ // TODO: uncomment when tracking TrackingEvent.GameSpin is implemented
2373
+ // roundTypes: [...this.#roundTypes],
2374
+ roundTypes: ["BaseGame"],
2375
+ totalBet: p,
2376
+ totalWin: g
2377
+ }), E(this, Fe, []);
2378
+ }), this.on("telemetry.click", (e) => {
2379
+ this.track("UI Interaction", {
2380
+ action: "click",
2381
+ ...this.getExtraUiInteractionData(),
2382
+ ...e
2383
+ });
2384
+ }), this.on("telemetry.orientationChange", () => {
2385
+ this.track("UI Interaction", {
2386
+ action: "orientationChange",
2387
+ ...this.getExtraUiInteractionData()
2388
+ });
2389
+ }), this.reportFpsSample(), this.reportFpsRound();
2390
+ }
2391
+ reportFpsSample() {
2392
+ const e = new It(), s = () => {
2393
+ e.stop();
2394
+ const l = e.getReport();
2395
+ this.track("FPS Performance", { ...l, fpsType: "sample" }), n();
2396
+ }, n = async () => {
2397
+ e.start(), setTimeout(s, this.FPS_SAMPLE_INTERVAL);
2398
+ };
2399
+ n();
2400
+ }
2401
+ reportFpsRound() {
2402
+ const e = new It();
2403
+ this.on("playCycleStart", () => {
2404
+ e.start();
2405
+ }), this.on("playCycleEnd", () => {
2406
+ e.stop();
2407
+ const s = e.getReport();
2408
+ this.track("FPS Performance", { ...s, fpsType: "playCycleStart->playCycleEnd" });
2409
+ });
2410
+ }
2411
+ getExtraUiInteractionData() {
2412
+ return {
2413
+ orientation: Xe(),
2414
+ stateType: y(this, ke)
2415
+ };
2416
+ }
2417
+ async deviceInfo() {
2418
+ var p;
2419
+ const e = new F(navigator.userAgent), s = vi(), n = await ki(), l = e.getBrowser(), a = e.getDevice(), h = e.getOS();
2420
+ return {
2421
+ browserName: l.name,
2422
+ browserVersion: l.version,
2423
+ connection: (p = navigator.connection) == null ? void 0 : p.effectiveType,
2424
+ deviceName: a.model,
2425
+ deviceType: a.type,
2426
+ isMobile: ["mobile", "tablet"].includes(a.type ?? ""),
2427
+ isWebGLSupported: s,
2428
+ isWebPSupported: n,
2429
+ manufacturer: a.vendor,
2430
+ operatingSystem: h.name,
2431
+ operatingSystemVersion: h.version,
2432
+ orientation: Xe(),
2433
+ pixelRatio: window.devicePixelRatio,
2434
+ screenHeight: window.screen.height,
2435
+ screenSize: `${window.screen.width}x${window.screen.height}`,
2436
+ screenWidth: window.screen.width,
2437
+ timezoneOffsetMinutes: (/* @__PURE__ */ new Date()).getTimezoneOffset(),
2438
+ windowHeight: window.innerHeight,
2439
+ windowSize: `${window.innerWidth}x${window.innerHeight}`,
2440
+ windowWidth: window.innerWidth
2441
+ };
2442
+ }
2443
+ }
2444
+ Le = new WeakMap(), ee = new WeakMap(), te = new WeakMap(), ie = new WeakMap(), ve = new WeakMap(), _e = new WeakMap(), ke = new WeakMap(), Fe = new WeakMap();
2445
+ let Ue;
2446
+ const Si = new Uint8Array(16);
2447
+ function Mi() {
2448
+ if (!Ue && (Ue = typeof crypto < "u" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto), !Ue))
2449
+ throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
2450
+ return Ue(Si);
2451
+ }
2452
+ const S = [];
2453
+ for (let i = 0; i < 256; ++i)
2454
+ S.push((i + 256).toString(16).slice(1));
2455
+ function Ci(i, t = 0) {
2456
+ return S[i[t + 0]] + S[i[t + 1]] + S[i[t + 2]] + S[i[t + 3]] + "-" + S[i[t + 4]] + S[i[t + 5]] + "-" + S[i[t + 6]] + S[i[t + 7]] + "-" + S[i[t + 8]] + S[i[t + 9]] + "-" + S[i[t + 10]] + S[i[t + 11]] + S[i[t + 12]] + S[i[t + 13]] + S[i[t + 14]] + S[i[t + 15]];
2457
+ }
2458
+ const Ii = typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto), Tt = {
2459
+ randomUUID: Ii
2460
+ };
2461
+ function At(i, t, e) {
2462
+ if (Tt.randomUUID && !t && !i)
2463
+ return Tt.randomUUID();
2464
+ i = i || {};
2465
+ const s = i.random || (i.rng || Mi)();
2466
+ if (s[6] = s[6] & 15 | 64, s[8] = s[8] & 63 | 128, t) {
2467
+ e = e || 0;
2468
+ for (let n = 0; n < 16; ++n)
2469
+ t[e + n] = s[n];
2470
+ return t;
2471
+ }
2472
+ return Ci(s);
2473
+ }
2474
+ class Ft {
2475
+ constructor(t) {
2476
+ w(this, "config");
2477
+ this.config = t;
2478
+ }
2479
+ }
2480
+ const Rt = 25, Pt = 1e4;
2481
+ var se, ne, ae, N, Se;
2482
+ class Gi extends Ft {
2483
+ constructor(...e) {
2484
+ super(...e);
2485
+ v(this, se, "https://europe-west3-stargazer-328808.cloudfunctions.net/collect-events");
2486
+ v(this, ne, void 0);
2487
+ v(this, ae, void 0);
2488
+ v(this, N, []);
2489
+ v(this, Se, void 0);
2490
+ w(this, "processQueueForced");
2491
+ E(this, ne, /* @__PURE__ */ (/* @__PURE__ */ new Date()).getTime()), E(this, N, []), E(this, Se, At()), this.processQueueForced = this.processQueue.bind(this, !0), this.schedule(), fetch(y(this, se), {
2492
+ method: "OPTIONS"
2493
+ }).catch(ot), this.subscribe();
2494
+ }
2495
+ subscribe() {
2496
+ window.addEventListener("beforeunload", this.processQueueForced, !1), window.addEventListener("pagehide", this.processQueueForced, !1), window.addEventListener("visibilitychange", this.processQueueForced, !1);
2497
+ }
2498
+ schedule() {
2499
+ y(this, ae) && clearTimeout(y(this, ae)), E(this, ae, window.setTimeout(() => this.processQueue(), Pt));
2500
+ }
2501
+ send(e) {
2502
+ E(this, ne, /* @__PURE__ */ (/* @__PURE__ */ new Date()).getTime());
2503
+ try {
2504
+ navigator.sendBeacon(y(this, se), JSON.stringify(e));
2505
+ } catch {
2506
+ fetch(y(this, se), {
2507
+ body: JSON.stringify(e),
2508
+ method: "POST",
2509
+ headers: {
2510
+ "Content-Type": "application/json"
2511
+ },
2512
+ keepalive: !0
2513
+ }).catch(ot);
2514
+ }
2515
+ this.schedule();
2516
+ }
2517
+ addToQueue(e) {
2518
+ y(this, N).push(e), this.processQueue();
2519
+ }
2520
+ processQueue(e = !1) {
2521
+ if (!(this.config == null || !this.config.ui.feature.allowTelemetry) && !(!e && y(this, N).length < Rt && /* @__PURE__ */ (/* @__PURE__ */ new Date()).getTime() - y(this, ne) < Pt))
2522
+ for (; y(this, N).length; ) {
2523
+ const s = y(this, N).splice(0, Rt).map((n) => ({
2524
+ ...n,
2525
+ sessionID: y(this, Se),
2526
+ userID: this.config.api.user
2527
+ }));
2528
+ this.send(s);
2529
+ }
2530
+ }
2531
+ track(e, s) {
2532
+ this.addToQueue({
2533
+ eventName: e,
2534
+ eventParams: s,
2535
+ eventTimestamp: /* @__PURE__ */ (/* @__PURE__ */ new Date()).getTime(),
2536
+ eventUUID: At()
2537
+ });
2538
+ }
2539
+ }
2540
+ se = new WeakMap(), ne = new WeakMap(), ae = new WeakMap(), N = new WeakMap(), Se = new WeakMap();
2541
+ const Ti = U("LoggingTracker", "color:#000000;font-weight:bold;");
2542
+ class Ni extends Ft {
2543
+ track(t, e) {
2544
+ Ti(`@${this.config.api.user}`, `[${t}]`, e);
2545
+ }
2546
+ }
2547
+ export {
2548
+ Pi as BasicPlugin,
2549
+ $ as CasinoPlugin,
2550
+ Ui as DebuggingPlugin,
2551
+ xi as GigPlugin,
2552
+ Di as KalambaBullseyePlugin,
2553
+ Bi as KalambaStargazerPlugin,
2554
+ Gi as KalambaStargazerTracker,
2555
+ Ni as LoggingTracker,
2556
+ Oi as OryxPlugin,
2557
+ Li as PariplayPlugin,
2558
+ _i as RelaxFEIMPlugin,
2559
+ ii as RgsPlygin,
2560
+ fi as TelemetryPlugin,
2561
+ Ft as Tracker,
2562
+ Fi as TukoPlugin
2563
+ };