mparticle-roku-sdk 2.1.16

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.
Files changed (35) hide show
  1. package/.github/workflows/build.yml +26 -0
  2. package/.gitmodules +3 -0
  3. package/LICENSE +191 -0
  4. package/README.md +24 -0
  5. package/example-legacy-sdk/images/MainMenu_Icon_Center_HD.png +0 -0
  6. package/example-legacy-sdk/images/MainMenu_Icon_Center_SD43.png +0 -0
  7. package/example-legacy-sdk/images/MainMenu_Icon_Side_HD.png +0 -0
  8. package/example-legacy-sdk/images/MainMenu_Icon_Side_SD43.png +0 -0
  9. package/example-legacy-sdk/images/splash_fhd.jpg +0 -0
  10. package/example-legacy-sdk/images/splash_hd.jpg +0 -0
  11. package/example-legacy-sdk/images/splash_sd.jpg +0 -0
  12. package/example-legacy-sdk/manifest +26 -0
  13. package/example-legacy-sdk/source/main.brs +45 -0
  14. package/example-scenegraph-sdk/LICENSE +1 -0
  15. package/example-scenegraph-sdk/README.md +2 -0
  16. package/example-scenegraph-sdk/source/Makefile +6 -0
  17. package/example-scenegraph-sdk/source/app.mk +675 -0
  18. package/example-scenegraph-sdk/source/components/helloworld.brs +300 -0
  19. package/example-scenegraph-sdk/source/components/helloworld.xml +66 -0
  20. package/example-scenegraph-sdk/source/images/channel-poster_fhd.png +0 -0
  21. package/example-scenegraph-sdk/source/images/channel-poster_hd.png +0 -0
  22. package/example-scenegraph-sdk/source/images/channel-poster_sd.png +0 -0
  23. package/example-scenegraph-sdk/source/images/splash-screen_fhd.jpg +0 -0
  24. package/example-scenegraph-sdk/source/images/splash-screen_hd.jpg +0 -0
  25. package/example-scenegraph-sdk/source/images/splash-screen_sd.jpg +0 -0
  26. package/example-scenegraph-sdk/source/manifest +12 -0
  27. package/example-scenegraph-sdk/source/source/Main.brs +46 -0
  28. package/example-scenegraph-sdk/source/testFramework/UnitTestFramework.brs +2867 -0
  29. package/example-scenegraph-sdk/source/tests/TestBasics.brs +266 -0
  30. package/mParticleBundle.crt +68 -0
  31. package/mParticleCore.brs +2301 -0
  32. package/mParticleTask.brs +78 -0
  33. package/mParticleTask.xml +12 -0
  34. package/package.json +5 -0
  35. package/testing/tests/Test__mParticle.brs +88 -0
@@ -0,0 +1,2301 @@
1
+ '*************************************************************
2
+ ' mParticle Roku SDK - Core APIs
3
+ ' Copyright 2019 mParticle, Inc.
4
+ '*************************************************************
5
+
6
+ '
7
+ ' mParticleConstants() surface various fields for interacting with the mParticle APIs
8
+ '
9
+ function mParticleConstants() as object
10
+ SDK_VERSION = "2.1.16"
11
+ LOG_LEVEL = {
12
+ NONE: 0,
13
+ ERROR: 1,
14
+ INFO: 2,
15
+ DEBUG: 3
16
+ }
17
+ ENVIRONMENT = {
18
+ AUTO_DETECT: 0,
19
+ FORCE_DEVELOPMENT: 1,
20
+ FORCE_PRODUCTION: 2
21
+ }
22
+ 'You may pass in any of these options to the mParticle SDK, via mParticleStart
23
+ 'or via the Global mParticle options field
24
+ DEFAULT_OPTIONS = {
25
+ apiKey: "",
26
+ apiSecret: "",
27
+ environment: ENVIRONMENT.AUTO_DETECT,
28
+ logLevel: LOG_LEVEL.ERROR,
29
+ enablePinning: true,
30
+ certificateDir: "pkg:/source/mparticle/mParticleBundle.crt",
31
+ sessionTimeoutMillis: 60 * 1000,
32
+ batchUploads: false,
33
+ }
34
+ SCENEGRAPH_NODES = {
35
+ API_CALL_NODE: "mParticleApiCall",
36
+ CURRENT_USER_NODE: "mParticleCurrentUser",
37
+ IDENTITY_RESULT_NODE: "mParticleIdentityResult"
38
+ }
39
+ USER_ATTRIBUTES = {
40
+ FIRSTNAME: "$FirstName",
41
+ LASTNAME: "$LastName",
42
+ ADDRESS: "$Address",
43
+ STATE: "$State",
44
+ CITY: "$City",
45
+ ZIPCODE: "$Zip",
46
+ COUNTRY: "$Country",
47
+ AGE: "$Age",
48
+ GENDER: "$Gender",
49
+ MOBILE_NUMBER: "$Mobile"
50
+ }
51
+ MESSAGE_TYPE = {
52
+ SESSION_START: "ss",
53
+ SESSION_END: "se",
54
+ CUSTOM: "e",
55
+ SCREEN: "v",
56
+ OPT_OUT: "o",
57
+ ERROR: "x",
58
+ BREADCRUMB: "b",
59
+ APP_STATE_TRANSITION: "ast",
60
+ COMMERCE: "cm",
61
+ USER_ATTRIBUTE_CHANGE: "uac",
62
+ USER_IDENTITY_CHANGE: "uic"
63
+ }
64
+ CUSTOM_EVENT_TYPE = {
65
+ NAVIGATION: "navigation",
66
+ LOCATION: "location",
67
+ SEARCH: "search",
68
+ TRANSACTION: "transaction",
69
+ USER_CONTENT: "usercontent",
70
+ USER_PREFERENCE: "userpreference",
71
+ SOCIAL: "social",
72
+ OTHER: "other",
73
+ MEDIA: "media"
74
+ }
75
+ MEDIA_EVENT_NAME = {
76
+ PLAY: "Play",
77
+ PAUSE: "Pause",
78
+ CONTENT_END: "Media Content End",
79
+ SESSION_START: "Media Session Start",
80
+ SESSION_END: "Media Session End",
81
+ SEEK_START: "Seek Start",
82
+ SEEK_END: "Seek End",
83
+ BUFFER_START: "Buffer Start",
84
+ BUFFER_END: "Buffer End",
85
+ UPDATE_PLAYHEAD_POSITION: "Update Playhead Position",
86
+ AD_CLICK: "Ad Click",
87
+ AD_BREAK_START: "Ad Break Start",
88
+ AD_BREAK_END: "Ad Break End",
89
+ AD_START: "Ad Start",
90
+ AD_END: "Ad End",
91
+ AD_SKIP: "Ad Skip",
92
+ SEGMENT_START: "Segment Start",
93
+ SEGMENT_SKIP: "Segment Skip",
94
+ SEGMENT_END: "Segment End",
95
+ UPDATE_QOS: "Update QoS",
96
+ MILESTONE: "Milestone",
97
+ SESSION_SUMMARY: "Media Session Summary",
98
+ AD_SUMMARY: "Ad Session Summary",
99
+ SEGMENT_SUMMARY: "Segment Session Summary"
100
+ }
101
+ MEDIA_CONTENT_TYPE = {
102
+ VIDEO: "Video",
103
+ AUDIO: "Audio"
104
+ }
105
+ MEDIA_STREAM_TYPE = {
106
+ LIVE_STREAM: "LiveStream",
107
+ ON_DEMAND: "OnDemand",
108
+ LINEAR: "Linear",
109
+ PODCAST: "Podcast",
110
+ AUDIOBOOK: "Audiobook"
111
+ }
112
+ IDENTITY_TYPE_INT = {
113
+ OTHER: 0,
114
+ CUSTOMER_ID: 1,
115
+ FACEBOOK: 2,
116
+ TWITTER: 3,
117
+ GOOGLE: 4,
118
+ MICROSOFT: 5,
119
+ YAHOO: 6,
120
+ EMAIL: 7,
121
+ FACEBOOK_AUDIENCE_ID: 9,
122
+ OTHER2: 10,
123
+ OTHER3: 11,
124
+ OTHER4: 12,
125
+ OTHER5: 13,
126
+ OTHER6: 14,
127
+ OTHER7: 15,
128
+ OTHER8: 16,
129
+ OTHER9: 17,
130
+ OTHER10: 18,
131
+ MOBILE_NUMBER: 19,
132
+ PHONE_NUMBER2: 20,
133
+ PHONE_NUMBER3: 21,
134
+ parseString: function(identityTypeString as string) as integer
135
+ IDENTITY_TYPE = mparticleconstants().IDENTITY_TYPE
136
+ if (identityTypeString = IDENTITY_TYPE.OTHER) then
137
+ return m.OTHER
138
+ else if (identityTypeString = IDENTITY_TYPE.CUSTOMER_ID) then
139
+ return m.CUSTOMER_ID
140
+ else if (identityTypeString = IDENTITY_TYPE.FACEBOOK) then
141
+ return m.FACEBOOK
142
+ else if (identityTypeString = IDENTITY_TYPE.TWITTER) then
143
+ return m.TWITTER
144
+ else if (identityTypeString = IDENTITY_TYPE.GOOGLE) then
145
+ return m.GOOGLE
146
+ else if (identityTypeString = IDENTITY_TYPE.MICROSOFT) then
147
+ return m.MICROSOFT
148
+ else if (identityTypeString = IDENTITY_TYPE.YAHOO) then
149
+ return m.YAHOO
150
+ else if (identityTypeString = IDENTITY_TYPE.EMAIL) then
151
+ return m.EMAIL
152
+ else if (identityTypeString = IDENTITY_TYPE.FACEBOOK_AUDIENCE_ID) then
153
+ return m.FACEBOOK_AUDIENCE_ID
154
+ else if (identityTypeString = IDENTITY_TYPE.OTHER2) then
155
+ return m.OTHER2
156
+ else if (identityTypeString = IDENTITY_TYPE.OTHER3) then
157
+ return m.OTHER3
158
+ else if (identityTypeString = IDENTITY_TYPE.OTHER4) then
159
+ return m.OTHER4
160
+ else if (identityTypeString = IDENTITY_TYPE.OTHER5) then
161
+ return m.OTHER5
162
+ else if (identityTypeString = IDENTITY_TYPE.OTHER6) then
163
+ return m.OTHER6
164
+ else if (identityTypeString = IDENTITY_TYPE.OTHER7) then
165
+ return m.OTHER7
166
+ else if (identityTypeString = IDENTITY_TYPE.OTHER8) then
167
+ return m.OTHER8
168
+ else if (identityTypeString = IDENTITY_TYPE.OTHER9) then
169
+ return m.OTHER9
170
+ else if (identityTypeString = IDENTITY_TYPE.OTHER10) then
171
+ return m.OTHER10
172
+ else if (identityTypeString = IDENTITY_TYPE.MOBILE_NUMBER) then
173
+ return m.MOBILE_NUMBER
174
+ else if (identityTypeString = IDENTITY_TYPE.PHONE_NUMBER2) then
175
+ return m.PHONE_NUMBER2
176
+ else if (identityTypeString = IDENTITY_TYPE.PHONE_NUMBER3) then
177
+ return m.PHONE_NUMBER3
178
+ end if
179
+ return 0
180
+ end function
181
+ }
182
+
183
+ IDENTITY_TYPE = {
184
+ OTHER: "other",
185
+ CUSTOMER_ID: "customerid",
186
+ FACEBOOK: "facebook",
187
+ TWITTER: "twitter",
188
+ GOOGLE: "google",
189
+ MICROSOFT: "microsoft",
190
+ YAHOO: "yahoo",
191
+ EMAIL: "email",
192
+ FACEBOOK_AUDIENCE_ID: "facebookcustomaudienceid",
193
+ OTHER2: "other2",
194
+ OTHER3: "other3",
195
+ OTHER4: "other4",
196
+ OTHER5: "other5",
197
+ OTHER6: "other6",
198
+ OTHER7: "other7",
199
+ OTHER8: "other8",
200
+ OTHER9: "other9",
201
+ OTHER10: "other10",
202
+ MOBILE_NUMBER: "mobile_number",
203
+ PHONE_NUMBER2: "phone_number_2",
204
+ PHONE_NUMBER3: "phone_number_3",
205
+ isValidIdentityType: function(identityType as string) as boolean
206
+ allTypes = m.Keys()
207
+ mputils = mparticle()._internal.utils
208
+ for each idType in allTypes
209
+ if (mputils.isString(m[idType]) and m[idType] = identityType) then
210
+ return true
211
+ end if
212
+ end for
213
+ return false
214
+ end function
215
+
216
+ }
217
+ '
218
+ ' Consent Management
219
+ '
220
+ ConsentState = {
221
+ build: function()
222
+ consentState = {}
223
+ consentState.gdpr = {}
224
+ consentState.ccpa = {}
225
+ return consentState
226
+ end function,
227
+
228
+ ' GDPR
229
+ addGDPRConsentState: function(consentState as object, purpose as string, gdprConsent as object)
230
+ consentState.gdpr.AddReplace(purpose, gdprConsent)
231
+ end function,
232
+ getCCPAConsentState: function(consentState as object)
233
+ return consentState.ccpa
234
+ end function,
235
+ getGDPRConsentState: function(consentState as object)
236
+ return consentState.gdpr
237
+ end function,
238
+ removeGDPRConsentState: function(consentState as object, purpose as string)
239
+ if (consentState.gdpr.DoesExist(purpose)) then
240
+ consentState.gdpr.Delete(purpose)
241
+ end if
242
+ end function,
243
+
244
+ ' CCPA
245
+ setCCPAConsentState: function(consentState as object, ccpaConsent as object)
246
+ consentState.ccpa.AddReplace("data_sale_opt_out", ccpaConsent)
247
+ end function,
248
+ removeCCPAConsentState: function(consentState as object)
249
+ consentState.ccpa.Delete("data_sale_opt_out")
250
+ end function
251
+ }
252
+ CCPAConsentState = {
253
+ build: function(consented as boolean, timestamp as longinteger)
254
+ ccpaConsentState = {}
255
+ ccpaConsentState.c = consented
256
+ ccpaConsentState.ts = timestamp
257
+ return ccpaConsentState
258
+ end function
259
+ setDocument: function(ccpaConsentState as object, document as string)
260
+ ccpaConsentState.d = document
261
+ end function,
262
+ setConsented: function(ccpaConsentState as object, consented as boolean)
263
+ ccpaConsentState.c = consented
264
+ end function,
265
+ setLocation: function(ccpaConsentState as object, location as string)
266
+ ccpaConsentState.l = location
267
+ end function,
268
+ setTimestamp: function(ccpaConsentState as object, timestamp as longinteger)
269
+ ccpaConsentState.ts = timestamp
270
+ end function,
271
+ setHardwareId: function(ccpaConsentState as object, hardwareId as string)
272
+ ccpaConsentState.h = hardwareId
273
+ end function,
274
+ }
275
+ GDPRConsentState = {
276
+ build: function(consented as boolean, timestamp as longinteger)
277
+ gdprConsentState = {}
278
+ gdprConsentState.c = consented
279
+ gdprConsentState.ts = timestamp
280
+ return gdprConsentState
281
+ end function,
282
+ setDocument: function(gdprConsentState as object, document as string)
283
+ gdprConsentState.d = document
284
+ end function,
285
+ setConsented: function(gdprConsentState as object, consented as boolean)
286
+ gdprConsentState.c = consented
287
+ end function,
288
+ setLocation: function(gdprConsentState as object, location as string)
289
+ gdprConsentState.l = location
290
+ end function,
291
+ setTimestamp: function(gdprConsentState as object, timestamp as longinteger)
292
+ gdprConsentState.ts = timestamp
293
+ end function,
294
+ setHardwareId: function(gdprConsentState as object, hardwareId as string)
295
+ gdprConsentState.h = hardwareId
296
+ end function,
297
+ }
298
+
299
+
300
+ '
301
+ ' eCommerce APIs
302
+ '
303
+ PromotionAction = {
304
+ ACTION_TYPE: {
305
+ VIEW: "view",
306
+ CLICK: "click"
307
+ },
308
+ build: function(actionType as string, promotionList as object)
309
+ return {
310
+ an: actionType,
311
+ pl: promotionList
312
+ }
313
+ end function,
314
+ }
315
+
316
+ Promotion = {
317
+ build: function(promotionId as string, name as string, creative as string, position as string)
318
+ return {
319
+ id: promotionId,
320
+ nm: name,
321
+ cr: creative,
322
+ ps: position
323
+ }
324
+ end function
325
+ }
326
+
327
+ Impression = {
328
+ build: function(impressionList as string, productList as object)
329
+ return {
330
+ pil: impressionList,
331
+ pl: productList
332
+ }
333
+ end function
334
+ }
335
+
336
+ ProductAction = {
337
+ ACTION_TYPE: {
338
+ ADD_TO_CART: "add_to_cart",
339
+ REMOVE_FROM_CART: "remove_from_cart",
340
+ CHECKOUT: "checkout",
341
+ CLICK: "click",
342
+ VIEW: "view",
343
+ VIEW_DETAIL: "view_detail",
344
+ PURCHASE: "purchase",
345
+ REFUND: "refund",
346
+ ADD_TO_WISHLIST: "add_to_wishlist",
347
+ REMOVE_FROM_WISHLIST: "remove_from_wishlist"
348
+ },
349
+ build: function(actionType as string, totalAmount as double, productList as object)
350
+ return {
351
+ an: actionType,
352
+ tr: totalAmount,
353
+ pl: productList
354
+ }
355
+ end function,
356
+ setCheckoutStep: function(productAction as object, checkoutStep as integer)
357
+ productAction.cs = checkoutStep
358
+ end function,
359
+ setCheckoutOptions: function(productAction as object, checkoutOptions as string)
360
+ productAction.co = checkoutOptions
361
+ end function,
362
+ setProductActionList: function(productAction as object, productActionList as string)
363
+ productAction.pal = productActionList
364
+ end function,
365
+ setProductListSource: function(productAction as object, productListSource as string)
366
+ productAction.pls = productListSource
367
+ end function,
368
+ setTransactionId: function(productAction as object, transactionId as string)
369
+ productAction.ti = transactionId
370
+ end function,
371
+ setAffiliation: function(productAction as object, affiliation as string)
372
+ productAction.ta = affiliation
373
+ end function,
374
+ setTaxAmount: function(productAction as object, taxAmount as double)
375
+ productAction.tt = taxAmount
376
+ end function,
377
+ setShippingAmount: function(productAction as object, shippingAmout as double)
378
+ productAction.ts = shippingAmout
379
+ end function,
380
+ setCouponCode: function(productAction as object, couponCode as string)
381
+ productAction.cc = couponCode
382
+ end function
383
+ }
384
+
385
+ Product = {
386
+ build: function(sku as string, name as string, price = 0 as double, quantity = 1 as integer, customAttributes = {} as object)
387
+ product = {}
388
+ product.id = sku
389
+ product.nm = name
390
+ product.pr = price
391
+ product.qt = quantity
392
+ product.tpa = price * quantity
393
+ product.attrs = customAttributes
394
+ return product
395
+ end function,
396
+ setBrand: function(product as object, brand as string)
397
+ product.cs = brand
398
+ end function,
399
+ setCategory: function(product as object, category as string)
400
+ product.ca = category
401
+ end function,
402
+ setVariant: function(product as object, variant as string)
403
+ product.va = variant
404
+ end function,
405
+ setPosition: function(product as object, position as integer)
406
+ product.ps = position
407
+ end function,
408
+ setCouponCode: function(product as object, couponCode as string)
409
+ product.cc = couponCode
410
+ end function
411
+ }
412
+
413
+ '
414
+ ' Media APIs
415
+ '
416
+
417
+ MediaSession = {
418
+ build: function(contentId as string, title as string, contentType as string, streamType as string, duration = 0 as integer)
419
+ session = {}
420
+ session.contentId = contentId
421
+ session.title = title
422
+ session.duration = duration
423
+ session.contentType = contentType
424
+ session.streamType = streamType
425
+ session.mediaSessionId = CreateObject("roDeviceInfo").GetRandomUUID()
426
+ session.currentPlayheadPosition = 0
427
+ session.mediaContentComplete = false
428
+ session.mediaContentTimeSpent = 0
429
+ session.mediaSessionSegmentTotal = 0
430
+ session.mediaSessionAdTotal = 0
431
+ session.mediaTotalAdTimeSpent = 0
432
+ session.mediaAdTimeSpentRate = 0.0
433
+ session.mediaSessionAdObjects = CreateObject("roArray", 0, true)
434
+ return session
435
+ end function,
436
+ setDuration: function(session as object, duration as integer)
437
+ session.duration = duration
438
+ end function,
439
+ setCurrentPlayheadPosition: function(session as object, playheadPosition as integer)
440
+ session.currentPlayheadPosition = playheadPosition
441
+ end function,
442
+ setAdContent: function(session as object, adContent as object)
443
+ session.adContent = adContent
444
+ end function,
445
+ setAdBreak: function(session as object, adBreak as object)
446
+ session.adBreak = adBreak
447
+ end function,
448
+ setSegment: function(session as object, segment as object)
449
+ session.segment = segment
450
+ end function,
451
+ setMediaSessionStartTime: function(session as object, mediaSessionStartTime as longinteger)
452
+ session.mediaSessionStartTime = mediaSessionStartTime
453
+ end function,
454
+ setMediaSessionEndTime: function(session as object, mediaSessionEndTime as longinteger)
455
+ session.mediaSessionEndTime = mediaSessionEndTime
456
+ end function,
457
+ setMediaContentComplete: function(session as object, mediaContentComplete as boolean)
458
+ session.mediaContentComplete = mediaContentComplete
459
+ end function,
460
+ setMediaContentTimeSpent: function(session as object, mediaContentTimeSpent as longinteger)
461
+ session.mediaContentTimeSpent = mediaContentTimeSpent
462
+ end function,
463
+ setMediaSessionSegmentTotal: function(session as object, mediaSessionSegmentTotal as integer)
464
+ session.mediaSessionSegmentTotal = mediaSessionSegmentTotal
465
+ end function,
466
+ setMediaSessionAdTotal: function(session as object, mediaSessionAdTotal as integer)
467
+ session.mediaSessionAdTotal = mediaSessionAdTotal
468
+ end function,
469
+ setMediaTotalAdTimeSpent: function(session as object, mediaTotalAdTimeSpent as longinteger)
470
+ session.mediaTotalAdTimeSpent = mediaTotalAdTimeSpent
471
+ end function,
472
+ setMediaAdTimeSpentRate: function(session as object, mediaAdTimeSpentRate as double)
473
+ session.mediaAdTimeSpentRate = mediaAdTimeSpentRate
474
+ end function,
475
+ setMediaSessionAdObjects: function(session as object, mediaSessionAdObjects as object)
476
+ session.mediaSessionAdObjects = mediaSessionAdObjects
477
+ end function
478
+ }
479
+
480
+ AdContent = {
481
+ build: function(id as string, title as string)
482
+ ad = {}
483
+ ad.id = id
484
+ ad.title = title
485
+ ad.adCompleted = false
486
+ ad.adSkipped = false
487
+ return ad
488
+ end function,
489
+ setDuration: function(ad as object, duration as integer)
490
+ ad.duration = duration
491
+ end function,
492
+ setAdvertiser: function(ad as object, advertiser as string)
493
+ ad.advertiser = advertiser
494
+ end function,
495
+ setCampaign: function(ad as object, campaign as string)
496
+ ad.campaign = campaign
497
+ end function,
498
+ setCreative: function(ad as object, creative as string)
499
+ ad.creative = creative
500
+ end function,
501
+ setPlacement: function(ad as object, placement as string)
502
+ ad.placement = placement
503
+ end function,
504
+ setPosition: function(ad as object, position as integer)
505
+ ad.position = position
506
+ end function,
507
+ setSiteId: function(ad as object, siteId as string)
508
+ ad.siteId = siteId
509
+ end function,
510
+ setAdStartTime: function(ad as object, adStartTime as longinteger)
511
+ ad.adStartTime = adStartTime
512
+ end function,
513
+ setAdEndTime: function(ad as object, adEndTime as longinteger)
514
+ ad.adEndTime = adEndTime
515
+ end function,
516
+ setAdCompleted: function(ad as object, adCompleted as boolean)
517
+ ad.adCompleted = adCompleted
518
+ end function,
519
+ setAdSkipped: function(ad as object, adSkipped as boolean)
520
+ ad.adSkipped = adSkipped
521
+ end function
522
+ }
523
+
524
+ AdBreak = {
525
+ build: function(id as string, title as string)
526
+ adBreak = {}
527
+ adBreak.id = id
528
+ adBreak.title = title
529
+ return adBreak
530
+ end function,
531
+ setDuration: function(adBreak as object, duration as integer)
532
+ adBreak.duration = duration
533
+ end function
534
+ }
535
+
536
+ Segment = {
537
+ build: function(title as string, index as integer, duration as integer)
538
+ segment = {}
539
+ segment.title = title
540
+ segment.index = index
541
+ segment.duration = duration
542
+ segment.segmentCompleted = false
543
+ segment.segmentSkipped = false
544
+ return segment
545
+ end function,
546
+ setDuration: function(segment as object, duration as integer)
547
+ segment.duration = duration
548
+ end function,
549
+ setSegmentStartTime: function(segment as object, segmentStartTime as longinteger)
550
+ segment.segmentStartTime = segmentStartTime
551
+ end function,
552
+ setSegmentEndTime: function(segment as object, segmentEndTime as longinteger)
553
+ segment.segmentEndTime = segmentEndTime
554
+ end function,
555
+ setSegmentCompleted: function(segment as object, segmentCompleted as boolean)
556
+ segment.segmentCompleted = segmentCompleted
557
+ end function,
558
+ setSegmentSkipped: function(segment as object, segmentSkipped as boolean)
559
+ segment.segmentSkipped = segmentSkipped
560
+ end function
561
+ }
562
+
563
+ return {
564
+ SDK_VERSION: SDK_VERSION,
565
+ LOG_LEVEL: LOG_LEVEL,
566
+ DEFAULT_OPTIONS: DEFAULT_OPTIONS,
567
+ SCENEGRAPH_NODES: SCENEGRAPH_NODES,
568
+ MESSAGE_TYPE: MESSAGE_TYPE,
569
+ CUSTOM_EVENT_TYPE: CUSTOM_EVENT_TYPE,
570
+ IDENTITY_TYPE: IDENTITY_TYPE,
571
+ IDENTITY_TYPE_INT: IDENTITY_TYPE_INT,
572
+ ENVIRONMENT: ENVIRONMENT,
573
+ MEDIA_EVENT_NAME: MEDIA_EVENT_NAME,
574
+ MEDIA_CONTENT_TYPE: MEDIA_CONTENT_TYPE,
575
+ MEDIA_STREAM_TYPE: MEDIA_STREAM_TYPE,
576
+ ProductAction: ProductAction,
577
+ Product: Product,
578
+ PromotionAction: PromotionAction
579
+ Promotion: Promotion,
580
+ Impression: Impression,
581
+ ConsentState: ConsentState,
582
+ CCPAConsentState: CCPAConsentState,
583
+ GDPRConsentState: GDPRConsentState,
584
+ MediaSession: MediaSession,
585
+ AdContent: AdContent,
586
+ AdBreak: AdBreak,
587
+ Segment: Segment
588
+ }
589
+
590
+ end function
591
+
592
+ '
593
+ ' Retrieve a reference to the global mParticle object.
594
+ ' Note: this only applies to legacy SDK channels. For Scene Graph, you must use the mParticleSGBridge (below)
595
+ '
596
+ function mParticle() as object
597
+ if (getGlobalAA().mParticleInstance = invalid) then
598
+ print "mParticle SDK: mParticle() called prior to mParticleStart!"
599
+ end if
600
+ return getGlobalAA().mParticleInstance
601
+ end function
602
+
603
+ '
604
+ ' Initialize mParticle with your API key and secret for a Roku Input Configuration
605
+ '
606
+ ' Optionally pass in additional configuration options, see mParticleConstants().DEFAULT_OPTIONS
607
+ ' Note: this only applies to legacy SDK channels. For Scene Graph, the mParticleTask will call this
608
+ '
609
+ function mParticleStart(options as object, messagePort as object)
610
+ if (getGlobalAA().mparticleInstance <> invalid) then
611
+ mplogger = mparticle()._internal.logger
612
+ mplogger.info("mParticleStart called twice.")
613
+ return mParticle()
614
+ end if
615
+
616
+ mpLogger = {
617
+ PREFIX: "mParticle SDK",
618
+
619
+ debug: function(message as string) as void
620
+ m.printlog(mParticleConstants().LOG_LEVEL.DEBUG, message)
621
+ end function,
622
+
623
+ info: function(message as string) as void
624
+ m.printlog(mParticleConstants().LOG_LEVEL.INFO, message)
625
+ end function,
626
+
627
+ error: function(message as string) as void
628
+ m.printlog(mParticleConstants().LOG_LEVEL.ERROR, message)
629
+ end function,
630
+
631
+ printlog: function(level as integer, message as string) as void
632
+ if (mparticle()._internal.configuration.logLevel >= level) then
633
+ print "============== " + m.PREFIX + " ====================="
634
+ print message
635
+ print "=================================================="
636
+ end if
637
+ end function
638
+ }
639
+
640
+ mpUtils = {
641
+ currentChannelVersion: function() as string
642
+ info = CreateObject("roDeviceInfo")
643
+ osVersion = info.GetOSVersion()
644
+ return osVersion["major"] + "." + osVersion["minor"]
645
+ end function,
646
+ randomGuid: function() as string
647
+ return CreateObject("roDeviceInfo").GetRandomUUID()
648
+ end function,
649
+
650
+ unixTimeMillis: function() as longinteger
651
+ date = CreateObject("roDateTime")
652
+ currentTime = CreateObject("roLongInteger")
653
+ currentTime.SetLongInt(date.asSeconds())
654
+ return (currentTime * 1000) + date.getMilliseconds()
655
+ end function,
656
+
657
+ isEmpty: function(input as dynamic) as boolean
658
+ if input = invalid
659
+ return true
660
+ else
661
+ if (LCase(type(input)) = "roarray" or LCase(type(input)) = "array")
662
+ return input.Count() = 0
663
+ end if
664
+ if (LCase(type(input)) = "rostring" or LCase(type(input)) = "string")
665
+ return Len(input) = 0
666
+ end if
667
+ end if
668
+ return false
669
+ end function,
670
+
671
+ isString: function(input as object) as boolean
672
+ return input <> invalid and (LCase(type(input)) = "rostring" or LCase(type(input)) = "string")
673
+ end function,
674
+
675
+ isArray: function(input as object) as boolean
676
+ return input <> invalid and (LCase(type(input)) = "roarray" or LCase(type(input)) = "array")
677
+ end function
678
+ }
679
+
680
+ mpCreateStorage = function()
681
+ storage = {}
682
+ 'channels can share registry when packaged by the same developer token
683
+ 'token, so include the channel ID
684
+ appInfo = CreateObject("roAppInfo")
685
+ storage.mpkeys = {
686
+ SECTION_NAME: "mparticle_storage_" + appInfo.getid(),
687
+ USER_IDENTITIES: "user_identities",
688
+ USER_ATTRIBUTES: "user_attributes",
689
+ CONSENT_STATE: "consent_state",
690
+ CURRENT_MPID: "current_mpid",
691
+ COOKIES: "cookies",
692
+ SESSION: "saved_session",
693
+ CHANNEL_VERSION: "channel_version",
694
+ LTV: "ltv",
695
+ OPT_OUT: "opt_out",
696
+ DAS: "das",
697
+ INTEGRATION_ATTRIBUTES: "integration_attributes"
698
+ }
699
+ storage.section = CreateObject("roRegistrySection", storage.mpkeys.SECTION_NAME)
700
+
701
+ storage.cleanCookies = sub()
702
+ cookies = m.getCookies()
703
+ validCookies = {}
704
+ nowSeconds = CreateObject("roDateTime").AsSeconds()
705
+ for each cookieKey in cookies
706
+ expiration = CreateObject("roDateTime")
707
+ expiration.FromISO8601String(cookies[cookieKey].e)
708
+ if (expiration.AsSeconds() > nowSeconds) then
709
+ validCookie = {}
710
+ validCookie[cookieKey] = cookies[cookieKey]
711
+ validCookies.append(validCookie)
712
+ end if
713
+ end for
714
+ if (validCookies.Count() <> cookies.Count()) then
715
+ m.setCookies(validCookies)
716
+ end if
717
+ end sub
718
+
719
+ storage.set = function(key as string, value as string) as boolean
720
+ return m.section.Write(key, value)
721
+ end function
722
+
723
+ storage.flush = function() as boolean
724
+ return m.section.Flush()
725
+ end function
726
+
727
+ storage.get = function(key as string) as string
728
+ return m.section.Read(key)
729
+ end function
730
+
731
+ storage.clear = function()
732
+ for each key in m.mpkeys
733
+ m.section.delete(key)
734
+ end for
735
+ m.flush()
736
+ end function
737
+
738
+ storage.setUserIdentity = function(mpid as string, identityType as string, identityValue as string) as void
739
+ if (not mparticleConstants().IDENTITY_TYPE.isValidIdentityType(identityType)) then
740
+ return
741
+ end if
742
+ identities = m.getUserIdentities(mpid)
743
+ identity = identities.Lookup(identityType)
744
+ oldIdentity = identities["i"]
745
+ if (identity = invalid and identityValue.len() > 0) then
746
+ identities[identityType] = mparticle()._internal.internalModel.UserIdentity(identityType, identityValue)
747
+ else
748
+ if (identityValue.len() = 0) then
749
+ identities.Delete(identityType)
750
+ else
751
+ identities[identityType].i = identityValue
752
+ identities[identityType].f = false
753
+ end if
754
+ end if
755
+ m.set(m.mpkeys.USER_IDENTITIES + mpid, FormatJson(identities))
756
+ m.flush()
757
+
758
+ if (oldIdentity <> identityValue) then
759
+ mparticle().logMessage(mparticle().model.UserIdentityChange(identityValue, oldIdentity))
760
+ end if
761
+ end function
762
+
763
+ storage.getUserIdentities = function(mpid as string) as object
764
+ identityJson = m.get(m.mpkeys.USER_IDENTITIES + mpid)
765
+ userIdentities = {}
766
+ if (not mparticle()._internal.utils.isEmpty(identityJson)) then
767
+ userIdentities = ParseJson(identityJson)
768
+ end if
769
+ return userIdentities
770
+ end function
771
+
772
+ storage.setUserAttribute = function(mpid as string, attributeKey as string, attributeValue as object) as void
773
+ attributes = m.getUserAttributes(mpid)
774
+ oldValue = attributes[attributeKey]
775
+ attributes[attributeKey] = attributeValue
776
+ m.set(m.mpkeys.USER_ATTRIBUTES + mpid, FormatJson(attributes))
777
+ m.flush()
778
+
779
+ if (FormatJSON(attributeValue) <> FormatJSON(oldValue)) then
780
+ deleted = false
781
+ if (mparticle()._internal.utils.isEmpty(attributeValue) or FormatJSON(attributeValue).len() = 0) then
782
+ deleted = true
783
+ end if
784
+ isNewAttribute = false
785
+ if (mparticle()._internal.utils.isEmpty(oldValue) or FormatJSON(oldValue).len() = 0) then
786
+ isNewAttribute = true
787
+ end if
788
+ mparticle().logMessage(mparticle().model.UserAttributeChange(attributeKey, attributeValue, oldValue, deleted, isNewAttribute))
789
+ end if
790
+ end function
791
+
792
+ storage.removeUserAttribute = function(mpid as string, attributeKey as string) as void
793
+ attributes = m.getUserAttributes(mpid)
794
+ oldValue = attributes[attributeKey]
795
+ attributes.delete(attributeKey)
796
+ m.set(m.mpkeys.USER_ATTRIBUTES + mpid, FormatJson(attributes))
797
+ m.flush()
798
+ mparticle().logMessage(mparticle().model.UserAttributeChange(attributeKey, invalid, oldValue, true, false))
799
+ end function
800
+
801
+ storage.getUserAttributes = function(mpid as string) as object
802
+ attributeJson = m.get(m.mpkeys.USER_ATTRIBUTES + mpid)
803
+ userAttributes = {}
804
+ if (not mparticle()._internal.utils.isEmpty(attributeJson)) then
805
+ userAttributes = ParseJson(attributeJson)
806
+ end if
807
+ return userAttributes
808
+ end function
809
+
810
+ storage.setIntegrationAttribute = function(mpid as string, integrationId as string, attributeKey as string, attributeValue as object) as void
811
+ attributes = m.getIntegrationAttributes(mpid)
812
+ if (mparticle()._internal.utils.isEmpty(attributes[integrationId])) then
813
+ integrationAttributes = {}
814
+ else
815
+ interationAttributes = attributes[integrationId]
816
+ end if
817
+ interationAttributes[attributeKey] = attributeValue
818
+ attributes[integrationId] = interationAttributes
819
+ m.set(m.mpkeys.USER_ATTRIBUTES + mpid, FormatJson(attributes))
820
+ m.flush()
821
+ end function
822
+
823
+ storage.getIntegrationAttributes = function(mpid as string) as object
824
+ attributeJson = m.get(m.mpkeys.INTEGRATION_ATTRIBUTES + mpid)
825
+ integrationAttributes = {}
826
+ if (not mparticle()._internal.utils.isEmpty(attributeJson)) then
827
+ integrationAttributes = ParseJson(attributeJson)
828
+ end if
829
+ return integrationAttributes
830
+ end function
831
+
832
+ storage.setConsentState = function(mpid as string, consentState as object) as void
833
+ m.set(m.mpkeys.CONSENT_STATE + mpid, FormatJson(consentState))
834
+ m.flush()
835
+ end function
836
+
837
+ storage.getConsentState = function(mpid as string) as object
838
+ consentJson = m.get(m.mpkeys.CONSENT_STATE + mpid)
839
+ consentState = {}
840
+ if (not mparticle()._internal.utils.isEmpty(consentJson)) then
841
+ consentState = ParseJson(consentJson)
842
+ end if
843
+ return consentState
844
+ end function
845
+
846
+ storage.setCurrentMpid = function(mpid as string) as void
847
+ m.set(m.mpkeys.CURRENT_MPID, mpid)
848
+ m.flush()
849
+ end function
850
+
851
+ storage.getCurrentMpid = function() as string
852
+ mpid = m.get(m.mpkeys.CURRENT_MPID)
853
+ if (mparticle()._internal.utils.isEmpty(mpid)) then
854
+ return "0"
855
+ end if
856
+ return mpid
857
+ end function
858
+
859
+ storage.getDas = function() as string
860
+ das = m.get(m.mpkeys.DAS)
861
+ if (mparticle()._internal.utils.isEmpty(das)) then
862
+ das = mparticle()._internal.utils.randomGuid()
863
+ m.setDas(das)
864
+ end if
865
+ return das
866
+ end function
867
+
868
+ storage.setDas = function(das as string)
869
+ m.set(m.mpkeys.DAS, das)
870
+ m.flush()
871
+ end function
872
+
873
+ storage.setCookies = function(cookies as object)
874
+ currentCookies = m.getCookies()
875
+ currentCookies.append(cookies)
876
+ m.set(m.mpkeys.COOKIES, FormatJson(currentCookies))
877
+ m.flush()
878
+ end function
879
+
880
+ storage.getCookies = function() as object
881
+ if (m.cookies = invalid) then
882
+ cookieJson = m.get(m.mpkeys.COOKIES)
883
+ if (not mparticle()._internal.utils.isEmpty(cookieJson)) then
884
+ m.cookies = ParseJson(cookieJson)
885
+ end if
886
+ if (m.cookies = invalid) then
887
+ m.cookies = {}
888
+ end if
889
+ end if
890
+ return m.cookies
891
+ end function
892
+
893
+ storage.setSession = function(session as object)
894
+ if (session <> invalid) then
895
+ m.set(m.mpkeys.SESSION, FormatJson(session))
896
+ m.flush()
897
+ end if
898
+ end function
899
+
900
+ storage.getSession = function() as object
901
+ sessionJson = m.get(m.mpkeys.SESSION)
902
+ if (not mparticle()._internal.utils.isEmpty(sessionJson)) then
903
+ return ParseJson(sessionJson)
904
+ else
905
+ return invalid
906
+ end if
907
+ end function
908
+
909
+ storage.getChannelVersion = function() as string
910
+ return m.get(m.mpkeys.CHANNEL_VERSION)
911
+ end function
912
+
913
+ storage.setChannelVersion = function(version as string)
914
+ m.set(m.mpkeys.CHANNEL_VERSION, version)
915
+ m.flush()
916
+ end function
917
+
918
+ storage.setLtv = function(ltv as double)
919
+ m.set(m.mpkeys.LTV, ltv.tostr())
920
+ m.flush()
921
+ end function
922
+
923
+ storage.getLtv = function() as double
924
+ ltv = m.get(m.mpkeys.LTV)
925
+ if (not mparticle()._internal.utils.isEmpty(ltv)) then
926
+ return ParseJson(ltv)
927
+ else
928
+ return 0
929
+ end if
930
+ end function
931
+
932
+ storage.setOptOut = function(optOut as boolean)
933
+ m.set(m.mpkeys.OPT_OUT, optOut.tostr())
934
+ m.flush()
935
+ end function
936
+
937
+ storage.getOptOut = function() as boolean
938
+ mpOptOut = m.get(m.mpkeys.OPT_OUT)
939
+ return "true" = mpOptOut
940
+ end function
941
+
942
+ return storage
943
+ end function
944
+
945
+ mpInternalModel = {
946
+
947
+ Batch: function(messages as object) as object
948
+ currentMpid = mparticle()._internal.storage.getCurrentMpid()
949
+ mpBatch = {}
950
+ mpBatch.dbg = mparticle()._internal.configuration.development
951
+ mpBatch.dt = "h"
952
+ mpBatch.mpid = mparticle()._internal.storage.getCurrentMpid()
953
+ mpBatch.ltv = mparticle()._internal.storage.getLtv()
954
+ mpBatch.id = mParticle()._internal.utils.randomGuid()
955
+ mpBatch.ct = mParticle()._internal.utils.unixTimeMillis()
956
+ mpBatch.sdk = mParticleConstants().SDK_VERSION
957
+ mpBatch.ui = []
958
+ identities = mparticle()._internal.storage.getUserIdentities(currentMpid)
959
+ for each identity in identities
960
+ mpBatch.ui.push(identities[identity])
961
+ end for
962
+ mpBatch.ua = mparticle()._internal.storage.getUserAttributes(currentMpid)
963
+ mpBatch.msgs = messages
964
+ mpBatch.ai = m.ApplicationInformation()
965
+ mpBatch.di = m.DeviceInformation()
966
+ mpBatch.ck = mparticle()._internal.storage.getCookies()
967
+ mpBatch.das = mparticle()._internal.storage.getDas()
968
+ mpBatch.con = mparticle()._internal.storage.getConsentState(currentMpid)
969
+ mpBatch.ia = mparticle()._internal.storage.getIntegrationAttributes(currentMpid)
970
+ mplogger = mparticle()._internal.logger
971
+ if (mparticle()._internal.configuration.dataPlanId <> invalid) then
972
+ if ((LCase(type(mparticle()._internal.configuration.dataPlanId))) = "rostring") then
973
+ mpBatch.ctx = {}
974
+ mpBatch.ctx.dpln = {}
975
+ mpBatch.ctx.dpln.id = mparticle()._internal.configuration.dataPlanId
976
+ if (mparticle()._internal.configuration.dataPlanVersion <> invalid) then
977
+ if ((LCase(type(mparticle()._internal.configuration.dataPlanVersion))) = "roint") then
978
+ mpBatch.ctx.dpln.v = mparticle()._internal.configuration.dataPlanVersion
979
+ else
980
+ mplogger.error("Your data plan version must be a integer.")
981
+ end if
982
+ end if
983
+ else
984
+ mplogger.error("Your data plan id must be a string.")
985
+ end if
986
+ end if
987
+ return mpBatch
988
+ end function,
989
+
990
+ UserIdentity: function(identityType as string, identityValue as string) as object
991
+ return {
992
+ n: mParticleConstants().IDENTITY_TYPE_INT.parseString(identityType),
993
+ i: identityValue,
994
+ dfs: mparticle()._internal.utils.unixTimeMillis(),
995
+ f: true
996
+ }
997
+ end function,
998
+
999
+ ApplicationInformation: function() as object
1000
+ if (m.collectedApplicationInfo = invalid) then
1001
+ appInfo = CreateObject("roAppInfo")
1002
+ deviceInfo = CreateObject("roDeviceInfo")
1003
+ env = 2
1004
+ osVersion = deviceInfo.GetOSVersion()
1005
+ if (mparticle()._internal.configuration.development) then
1006
+ env = 1
1007
+ end if
1008
+ m.collectedApplicationInfo = {
1009
+ an: appInfo.GetTitle(),
1010
+ av: appInfo.getVersion(),
1011
+ apn: appInfo.GetID(),
1012
+ abn: appInfo.GetValue("build_version"),
1013
+ env: env
1014
+ }
1015
+ end if
1016
+ return m.collectedApplicationInfo
1017
+ end function,
1018
+
1019
+ DeviceInformation: function() as object
1020
+ if (m.collectedDeviceInfo = invalid) then
1021
+ info = CreateObject("roDeviceInfo")
1022
+
1023
+ tempDatetime = CreateObject ("roDateTime")
1024
+ utcSeconds = tempDatetime.AsSeconds ()
1025
+ tempDatetime.ToLocalTime ()
1026
+ localSeconds = tempDatetime.AsSeconds ()
1027
+ utcSecondsOffset = localSeconds - utcSeconds
1028
+ utcHoursOffset = utcSecondsOffset / 3600
1029
+ versionArray = info.GetOsVersion()
1030
+ versionString = versionArray["major"] + "." + versionArray["minor"]
1031
+
1032
+ m.collectedDeviceInfo = {
1033
+ dp: "Roku",
1034
+ dn: info.GetModelDisplayName(),
1035
+ p: info.GetModel(),
1036
+ vr: versionString,
1037
+ rida: info.GetRIDA(),
1038
+ lat: info.IsRIDADisabled(),
1039
+ rpb: info.GetChannelClientId(),
1040
+ dmdl: info.GetModel(),
1041
+ dc: info.GetCountryCode(),
1042
+ dll: info.GetCurrentLocale(),
1043
+ dlc: info.GetUserCountryCode(),
1044
+ tzn: info.GetTimeZone(),
1045
+ dr: info.GetConnectionType(),
1046
+ tz: utcHoursOffset
1047
+ }
1048
+
1049
+ modelDetails = info.GetModelDetails()
1050
+ if (modelDetails <> invalid) then
1051
+ m.collectedDeviceInfo.b = modelDetails["VendorName"]
1052
+ m.collectedDeviceInfo.dma = modelDetails["VendorName"]
1053
+ end if
1054
+
1055
+ displaySize = info.GetDisplaySize()
1056
+ if (displaySize <> invalid) then
1057
+ m.collectedDeviceInfo.dsh = displaySize["h"]
1058
+ m.collectedDeviceInfo.dsw = displaySize["w"]
1059
+ end if
1060
+
1061
+
1062
+ buildIdArray = CreateObject("roByteArray")
1063
+ buildIdArray.FromAsciiString(mparticle()._internal.utils.currentChannelVersion())
1064
+ digest = CreateObject("roEVPDigest")
1065
+ digest.Setup("md5")
1066
+ digest.update(buildIdArray)
1067
+ m.collectedDeviceInfo.bid = digest.final()
1068
+ m.collectedDeviceInfo.dosv = versionString
1069
+
1070
+ end if
1071
+ return m.collectedDeviceInfo
1072
+ end function
1073
+ }
1074
+
1075
+ mpNetworking = {
1076
+ messagePort: messagePort,
1077
+ mpBackoff: {
1078
+ nextAllowedUploadTime: 0,
1079
+ currentBackoffDuration: 0,
1080
+ reset: function()
1081
+ m.currentBackoffDuration = 0
1082
+ m.nextAllowedUploadTime = 0
1083
+ end function,
1084
+ increase: function()
1085
+ maxDuration = 2 * 60 * 60 * 1000
1086
+ base = 1000
1087
+ intervalMillis = 5000
1088
+ if (m.currentBackoffDuration = 0) then
1089
+ m.currentBackoffDuration = base
1090
+ else
1091
+ m.currentBackoffDuration = m.currentBackoffDuration * 2
1092
+ if (m.currentBackoffDuration > maxDuration) then
1093
+ m.currentBackoffDuration = maxDuration
1094
+ end if
1095
+ end if
1096
+
1097
+ m.nextAllowedUploadTime = mparticle()._internal.utils.unixTimeMillis() + m.currentBackoffDuration
1098
+ end function,
1099
+ setBackoff: function(backoffDuration as longinteger)
1100
+ m.nextAllowedUploadTime = mparticle()._internal.utils.unixTimeMillis() + backoffDuration
1101
+ end function,
1102
+ canUpload: function() as boolean
1103
+ if (m.nextAllowedUploadTime = 0)
1104
+ return true
1105
+ else
1106
+ currentTime = mparticle()._internal.utils.unixTimeMillis()
1107
+ return currentTime >= m.nextAllowedUploadTime
1108
+ end if
1109
+ end function
1110
+ },
1111
+ pendingTransfers: {},
1112
+ messageQueue: [],
1113
+ uploadQueue: [],
1114
+ queueMessage: function(message as object)
1115
+ storage = mparticle()._internal.storage
1116
+ if (message.dt = mParticleConstants().MESSAGE_TYPE.OPT_OUT) then
1117
+ storage.setOptOut(message.lookup("s"))
1118
+ else if (storage.getOptOut()) then
1119
+ return 0
1120
+ end if
1121
+ m.messageQueue.push(message)
1122
+ if (not mparticle()._internal.configuration.batchUploads) then
1123
+ m.queueUpload()
1124
+ m.processUploads()
1125
+ end if
1126
+ end function,
1127
+ queueUpload: function()
1128
+ if (m.messageQueue.count() > 0 and mparticle()._internal.storage.getCurrentMpid() <> "0") then
1129
+ upload = mparticle()._internal.internalModel.Batch(m.messageQueue)
1130
+ m.uploadQueue.push(upload)
1131
+ m.messageQueue = []
1132
+ end if
1133
+ end function,
1134
+ processUploads: function()
1135
+ if (m.mpBackoff.canUpload()) then
1136
+ m.mpBackoff.reset()
1137
+ else
1138
+ return -1
1139
+ end if
1140
+ mplogger = mparticle()._internal.logger
1141
+ mplinkStatus = CreateObject("roDeviceInfo").GetLinkStatus()
1142
+ if (not mplinkStatus) then
1143
+ mplogger.error("No active network connection - deferring upload.")
1144
+ return -1
1145
+ end if
1146
+ while (m.uploadQueue.count() > 0)
1147
+ nextUpload = m.uploadQueue.shift()
1148
+ m.mpUploadBatch(nextUpload)
1149
+ end while
1150
+ end function,
1151
+
1152
+ mpUploadBatch: function(mpBatch as object)
1153
+ urlTransfer = CreateObject("roUrlTransfer")
1154
+ if (mparticle()._internal.configuration.enablePinning) then
1155
+ urlTransfer.SetCertificatesFile(mparticle()._internal.configuration.certificateDir)
1156
+ end if
1157
+ urlTransfer.SetUrl("https://nativesdks.mparticle.com/v2/" + mparticle()._internal.configuration.apikey + "/events")
1158
+ urlTransfer.EnableEncodings(true)
1159
+ requestId = urlTransfer.GetIdentity().ToStr()
1160
+ m.pendingTransfers[requestId] = { "transfer": urlTransfer, "batch": mpBatch }
1161
+ dateString = CreateObject("roDateTime").ToISOString()
1162
+ jsonBatch = FormatJson(mpBatch)
1163
+ hashString = "POST" + Chr(10) + dateString + Chr(10) + "/v2/" + mparticle()._internal.configuration.apikey + "/events" + jsonBatch
1164
+
1165
+ signature_key = CreateObject("roByteArray")
1166
+ signature_key.fromAsciiString(mparticle()._internal.configuration.apisecret)
1167
+
1168
+ hmac = CreateObject("roHMAC")
1169
+ hmac.Setup("sha256", signature_key)
1170
+ message = CreateObject("roByteArray")
1171
+ message.FromAsciiString(hashString)
1172
+ result = hmac.process(message)
1173
+ hashResult = LCase(result.ToHexString())
1174
+
1175
+ urlTransfer.AddHeader("Date", dateString)
1176
+ urlTransfer.AddHeader("x-mp-signature", hashResult)
1177
+ urlTransfer.AddHeader("Content-Type", "application/json")
1178
+ urlTransfer.AddHeader("User-Agent", "mParticle Roku SDK/" + mpBatch.sdk)
1179
+ urlTransfer.RetainBodyOnError(true)
1180
+ mplogger = mparticle()._internal.logger
1181
+ mplogger.debug("Uploading batch: " + jsonBatch)
1182
+ urlTransfer.setPort(m.messagePort)
1183
+ urlTransfer.AsyncPostFromString(jsonBatch)
1184
+ end function,
1185
+
1186
+ mpHandleUrlEvent: function(urlEvent as object)
1187
+ if (urlEvent <> invalid)
1188
+ requestId = urlEvent.GetSourceIdentity().ToStr()
1189
+ transfer = m.pendingTransfers[requestId]
1190
+ mplogger = mparticle()._internal.logger
1191
+ if (transfer = invalid)
1192
+ mplogger.debug("Unknown URL event passed to mParticle, ignoring...")
1193
+ else
1194
+ m.pendingTransfers.delete(requestId)
1195
+ responseCode = urlEvent.GetResponseCode()
1196
+ responseBody = urlEvent.GetString()
1197
+ mplogger.debug("Batch response: code" + str(responseCode) + " body: " + responseBody)
1198
+
1199
+ if (responseCode = -77) then
1200
+ mplogger.error("SSL error - please make sure " + mparticle()._internal.configuration.certificateDir + " is present.")
1201
+ else if (responseCode = 400) then
1202
+ mplogger.error("HTTP 400 - please check that your mParticle key and secret are valid.")
1203
+ else if (responseCode = 429 or responseCode = 503) then
1204
+ headers = urlEvent.GetResponseHeadersArray()
1205
+ m.uploadQueue.unshift(transfer.batch)
1206
+ for each header in headers
1207
+ if (header["Retry-After"] <> invalid) then
1208
+ backoff = header["Retry-After"]
1209
+ end if
1210
+ end for
1211
+ if (backoff <> invalid) then
1212
+ m.mpBackoff.setBackoff(backoff)
1213
+ else
1214
+ m.mpBackoff.increase()
1215
+ end if
1216
+ else if (responseCode = 202 and responseBody <> invalid) then
1217
+ responseObject = parsejson(responseBody)
1218
+ if (responseObject <> invalid) then
1219
+ storage = mparticle()._internal.storage
1220
+ if (responseObject.DoesExist("ci") and responseObject.ci.DoesExist("ck")) then
1221
+ storage.setCookies(responseObject.ci.ck)
1222
+ end if
1223
+ if (responseObject.DoesExist("iltv")) then
1224
+ storage.setLtv(responseObject.iltv)
1225
+ end if
1226
+ end if
1227
+ else
1228
+ m.uploadQueue.unshift(transfer.batch)
1229
+ mplogger.error("Unknown error while performing upload.")
1230
+ end if
1231
+ end if
1232
+ end if
1233
+ end function
1234
+
1235
+ }
1236
+
1237
+ mpCreateSessionManager = function(startupArgs as object) as object
1238
+ sessionManager = {}
1239
+ sessionManager.startupArgs = startupArgs
1240
+ sessionManagerApi = {
1241
+ onSdkStart: function()
1242
+ isFirstRun = true
1243
+ isUpgrade = false
1244
+ logAst = false
1245
+ storedChannelVersion = mparticle()._internal.storage.getChannelVersion()
1246
+ currentChannelVersion = mparticle()._internal.utils.currentChannelVersion()
1247
+ if (not mparticle()._internal.utils.isEmpty(storedChannelVersion) and storedChannelVersion <> currentChannelVersion) then
1248
+ isUpgrade = true
1249
+ end if
1250
+ if (isUpgrade or mparticle()._internal.utils.isEmpty(storedChannelVersion)) then
1251
+ storage = mparticle()._internal.storage
1252
+ storage.setChannelVersion(currentChannelVersion)
1253
+ end if
1254
+ mplogger = mparticle()._internal.logger
1255
+ if (m.currentSession = invalid) then
1256
+ mplogger.debug("Restoring previous session.")
1257
+ m.currentSession = mparticle()._internal.storage.getSession()
1258
+ if (m.currentSession = invalid) then
1259
+ mplogger.debug("No previous session found, creating new session.")
1260
+ m.onSessionStart()
1261
+ logAst = true
1262
+ else
1263
+ isFirstRun = false
1264
+ currentTime = mparticle()._internal.utils.unixTimeMillis()
1265
+ sessionTimeoutMillis = mparticle()._internal.configuration.sessionTimeoutMillis
1266
+ lastEventTime = m.currentSession.lastEventTime
1267
+ if ((currentTime - lastEventTime) >= sessionTimeoutMillis) then
1268
+ mplogger.debug("Previous session timed out - creating new session.")
1269
+ m.onSessionEnd(m.currentSession)
1270
+ m.onSessionStart(m.currentSession)
1271
+ logAst = true
1272
+ else
1273
+ mplogger.debug("Previous session still valid - it will be reused.")
1274
+ m.onForeground(currentTime)
1275
+ end if
1276
+ end if
1277
+ end if
1278
+ if (logAst) then
1279
+ mparticle().logMessage(mparticle().model.AppStateTransition("app_init", isFirstRun, isUpgrade, m.startupArgs))
1280
+ end if
1281
+ end function,
1282
+ getCurrentSession: function()
1283
+ return m.currentSession
1284
+ end function,
1285
+ updateLastEventTime: function(time as longinteger)
1286
+ m.currentSession.lastEventTime = time
1287
+ m.saveSession()
1288
+ end function,
1289
+ onForeground: function(time as longinteger)
1290
+ m.updateLastEventTime(time)
1291
+ end function,
1292
+ setSessionAttribute: function(attributeKey as string, attributeValue as object)
1293
+ m.currentSession.attributes[attributeKey] = attributeValue
1294
+ m.updateLastEventTime(mparticle()._internal.utils.unixTimeMillis())
1295
+ end function,
1296
+ onSessionStart: function(previousSession = invalid as object)
1297
+ m.currentSession = m.createSession(previousSession)
1298
+ m.saveSession()
1299
+ mparticle().logMessage(mparticle().model.SessionStart(m.currentSession))
1300
+ end function,
1301
+ onSessionEnd: function(session as object)
1302
+ mparticle().logMessage(mparticle().model.SessionEnd(session))
1303
+ end function,
1304
+ saveSession: function()
1305
+ storage = mparticle()._internal.storage
1306
+ storage.setSession(m.currentSession)
1307
+ end function,
1308
+ setSessionAttribute: function(attributekey as string, attributevalue as string)
1309
+ attributes = m.currentSession.attributes
1310
+ if (attributes = invalid) then
1311
+ attributes = {}
1312
+ end if
1313
+ attributes[attributekey] = attributevalue
1314
+ m.saveSession()
1315
+ end function,
1316
+ addSessionMpid: function(mpid as string) as void
1317
+ m.currentSession.sessionMpids.push(mpid)
1318
+ m.saveSession()
1319
+ end function,
1320
+ createSession: function(previousSession = invalid as object)
1321
+ deviceInfo = CreateObject("roDeviceInfo")
1322
+ currentTime = mparticle()._internal.utils.unixTimeMillis()
1323
+ launchReferrer = invalid
1324
+ if (m.startupArgs <> invalid) then
1325
+ launchReferrer = m.startupArgs.contentId
1326
+ end if
1327
+ previousSessionLength = invalid
1328
+ previousSessionId = invalid
1329
+ previousSessionStartTime = invalid
1330
+ if (previousSession <> invalid) then
1331
+ previousSessionLength = m.sessionLength(previousSession)
1332
+ previousSessionId = previousSession.sessionId
1333
+ previousSessionStartTime = previousSession.startTime
1334
+ end if
1335
+
1336
+ return {
1337
+ sessionId: mparticle()._internal.utils.randomGuid(),
1338
+ startTime: currentTime,
1339
+ dataConnection: deviceInfo.GetConnectionType(),
1340
+ launchReferrer: launchReferrer
1341
+ lastEventTime: currentTime,
1342
+ previousSessionLength: previousSessionLength,
1343
+ previousSessionId: previousSessionId,
1344
+ previousSessionStartTime: previousSessionStartTime,
1345
+ attributes: {},
1346
+ sessionMpids: [mparticle()._internal.storage.getCurrentMpid()]
1347
+ }
1348
+ end function,
1349
+ sessionLength: function(session as object) as integer
1350
+ return (session.lastEventTime - session.startTime)
1351
+ end function,
1352
+ }
1353
+ sessionManager.append(sessionManagerApi)
1354
+ return sessionManager
1355
+ end function
1356
+
1357
+ mpPublicModels = {
1358
+ Message: function(messageType as string, attributes = {}) as object
1359
+ currentSession = mparticle()._internal.sessionManager.getCurrentSession()
1360
+ if (attributes <> invalid)
1361
+ if (attributes.count() = 0) then
1362
+ attributes = invalid
1363
+ else
1364
+ mputils = mparticle()._internal.utils
1365
+ attributeKeys = attributes.Keys()
1366
+ validAttributes = {}
1367
+ for each attributeKey in attributeKeys
1368
+ if (mputils.isString(attributes[attributeKey])) then
1369
+ validAttributes[attributeKey] = attributes[attributeKey]
1370
+ end if
1371
+ end for
1372
+ attributes = validAttributes
1373
+ end if
1374
+ end if
1375
+ return {
1376
+ dt: messageType,
1377
+ id: mparticle()._internal.utils.randomGuid(),
1378
+ ct: mparticle()._internal.utils.unixTimeMillis(),
1379
+ attrs: attributes,
1380
+ sid: currentSession.sessionId,
1381
+ sct: currentSession.startTime
1382
+ }
1383
+ end function,
1384
+
1385
+ CustomEvent: function(eventName as string, eventType as string, customAttributes = {}) as object
1386
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.CUSTOM, customAttributes)
1387
+ message.n = eventName
1388
+ message.et = eventType
1389
+ message.est = message.ct
1390
+ return message
1391
+ end function,
1392
+
1393
+ ScreenEvent: function(screenName as string, customAttributes = {}) as object
1394
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.SCREEN, customAttributes)
1395
+ message.n = screenName
1396
+ message.est = message.ct
1397
+ return message
1398
+ end function,
1399
+
1400
+ SessionStart: function(session as object) as object
1401
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.SESSION_START)
1402
+ message.ct = session.startTime
1403
+ message.id = session.sessionId
1404
+ message.dct = session.dataConnection
1405
+ message.lr = session.launchReferrer
1406
+ if (session.previousSessionLength <> invalid) then
1407
+ message.psl = session.previousSessionLength / 1000
1408
+ end if
1409
+ message.pid = session.previousSessionId
1410
+ message.pss = session.previousSessionStartTime
1411
+ return message
1412
+ end function,
1413
+
1414
+ SessionEnd: function(session as object) as object
1415
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.SESSION_END)
1416
+ message.dct = session.dataConnection
1417
+ message.slx = mparticle()._internal.sessionManager.sessionLength(session)
1418
+ message.sl = message.slx
1419
+ message.attrs = session.attributes
1420
+ message.smpids = session.sessionMpids
1421
+ return message
1422
+ end function,
1423
+
1424
+ OptOut: function(optOut as boolean) as object
1425
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.OPT_OUT)
1426
+ message.s = optOut
1427
+ return message
1428
+ end function,
1429
+
1430
+ CommerceEvent: function(productAction = {} as object, promotionAction = {} as object, impressions = [] as object, customAttributes = {} as object, screenName = invalid as string) as object
1431
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.COMMERCE, customAttributes)
1432
+ if (productAction <> invalid and productAction.count() > 0) then
1433
+ message.pd = productAction
1434
+ end if
1435
+ if (promotionAction <> invalid and promotionAction.count() > 0) then
1436
+ message.pm = promotionAction
1437
+ end if
1438
+ if (impressions <> invalid and impressions.count() > 0) then
1439
+ message.pi = impressions
1440
+ end if
1441
+ if (not mparticle()._internal.utils.isEmpty(screenName)) then
1442
+ message.sn = screenName
1443
+ end if
1444
+ return message
1445
+ end function,
1446
+
1447
+ AppStateTransition: function(astType as string, firstRun as boolean, isUpgrade as boolean, startupArgs as object) as object
1448
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.APP_STATE_TRANSITION)
1449
+ message.t = astType
1450
+ message.ifr = firstRun
1451
+ message.iu = isUpgrade
1452
+ deviceInfo = CreateObject("roDeviceInfo")
1453
+ message.dct = deviceInfo.GetConnectionType()
1454
+ if (startupArgs <> invalid) then
1455
+ message.lr = startupArgs.contentId
1456
+ message.lpr = formatjson(startupArgs)
1457
+ end if
1458
+
1459
+ return message
1460
+ end function,
1461
+
1462
+ UserAttributeChange: function(userAttributeKey as string, newValue as object, oldValue as object, deleted as boolean, isNewAttribute as boolean) as object
1463
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.USER_ATTRIBUTE_CHANGE)
1464
+ message.n = userAttributeKey
1465
+ message.nv = newValue
1466
+ message.ov = oldValue
1467
+ message.d = deleted
1468
+ message.na = isNewAttribute
1469
+
1470
+ return message
1471
+ end function,
1472
+
1473
+ UserIdentityChange: function(newIdentity as object, oldIdentity as object) as object
1474
+ message = m.Message(mParticleConstants().MESSAGE_TYPE.USER_IDENTITY_CHANGE)
1475
+ message.ni = newIdentity
1476
+ message.oi = oldIdentity
1477
+
1478
+ return message
1479
+ end function,
1480
+
1481
+ }
1482
+
1483
+ mpInternalIdentityApi = {
1484
+ context: "",
1485
+ IDENTITY_API_PATHS: {
1486
+ IDENTIFY: "identify",
1487
+ LOGIN: "login",
1488
+ LOGOUT: "logout",
1489
+ MODIFY: "modify"
1490
+ },
1491
+ pendingApiRequests: {},
1492
+ messagePort: messagePort,
1493
+ identify: function(identityApiRequest as object) as void
1494
+ m.performIdentityHttpRequest(m.IDENTITY_API_PATHS.IDENTIFY, identityApiRequest)
1495
+ end function,
1496
+ login: function(identityApiRequest as object) as void
1497
+ m.performIdentityHttpRequest(m.IDENTITY_API_PATHS.LOGIN, identityApiRequest)
1498
+ end function,
1499
+ logout: function(identityApiRequest as object) as void
1500
+ m.performIdentityHttpRequest(m.IDENTITY_API_PATHS.LOGOUT, identityApiRequest)
1501
+ end function,
1502
+ modify: function(identityApiRequest as object) as void
1503
+ modifyPath = mparticle()._internal.storage.getCurrentMpid() + "/" + m.IDENTITY_API_PATHS.MODIFY
1504
+ m.performIdentityHttpRequest(modifyPath, identityApiRequest)
1505
+ end function,
1506
+ generateIdentityHttpBody: function(path as string, identityApiRequest as object) as object
1507
+ environmentString = "production"
1508
+ if (mparticle()._internal.configuration.development) then
1509
+ environmentString = "development"
1510
+ end if
1511
+ identityHttpRequest = {
1512
+ client_sdk: {
1513
+ platform: "roku",
1514
+ sdk_vendor: "mparticle",
1515
+ sdk_version: mParticleConstants().SDK_VERSION
1516
+ },
1517
+ environment: environmentString,
1518
+ requestId: mparticle()._internal.utils.randomGuid(),
1519
+ request_timestamp_ms: mparticle()._internal.utils.unixTimeMillis(),
1520
+ context: m.context
1521
+ }
1522
+ mplogger = mparticle()._internal.logger
1523
+ if (identityApiRequest <> invalid) then
1524
+ if (not identityApiRequest.DoesExist("userIdentities")) then
1525
+ identityApiRequest.userIdentities = {}
1526
+ end if
1527
+ identityKeys = identityApiRequest.userIdentities.Keys()
1528
+ if (path.Instr(m.IDENTITY_API_PATHS.MODIFY) = -1) then
1529
+ identityHttpRequest.known_identities = {}
1530
+ for each identityType in identityKeys
1531
+ if (mparticleConstants().IDENTITY_TYPE.isValidIdentityType(identityType)) then
1532
+ identityHttpRequest.known_identities[identityType] = identityApiRequest.userIdentities[identityType]
1533
+ else
1534
+ mplogger.error("Invalid identity passed to identity API: " + path)
1535
+ end if
1536
+ end for
1537
+ identityHttpRequest.known_identities.device_application_stamp = mparticle()._internal.storage.getDas()
1538
+ deviceInfo = CreateObject("roDeviceInfo")
1539
+ if (not deviceInfo.IsRIDADisabled()) then
1540
+ identityHttpRequest.known_identities.roku_aid = deviceInfo.GetRIDA()
1541
+ end if
1542
+ identityHttpRequest.known_identities.roku_publisher_id = deviceInfo.GetChannelClientId()
1543
+ else
1544
+ identityHttpRequest.identity_changes = []
1545
+ currentUserIdentities = m.getCurrentUser().userIdentities
1546
+ for each identityType in identityKeys
1547
+ if (mparticleConstants().IDENTITY_TYPE.isValidIdentityType(identityType))
1548
+ identityChange = { identity_type: identityType }
1549
+ if (identityApiRequest.userIdentities[identityType].len() > 0) then
1550
+ identityChange.new_value = identityApiRequest.userIdentities[identityType]
1551
+ end if
1552
+ if (currentUserIdentities.DoesExist(identityType))
1553
+ identityChange.old_value = currentUserIdentities[identityType]
1554
+ end if
1555
+ identityHttpRequest.identity_changes.Push(identityChange)
1556
+ end if
1557
+ end for
1558
+ end if
1559
+ end if
1560
+ return identityHttpRequest
1561
+ end function,
1562
+ performIdentityHttpRequest: function(path as string, identityApiRequest as object) as object
1563
+ mplogger = mparticle()._internal.logger
1564
+ mplogger.debug("Starting Identity API request: " + path)
1565
+ identityHttpBody = m.generateIdentityHttpBody(path, identityApiRequest)
1566
+ mplogger.debug("Identity API request:" + Chr(10) + "Path:" + path + Chr(10) + "Body:" + formatjson(identityHttpBody))
1567
+ urlTransfer = CreateObject("roUrlTransfer")
1568
+ if (mparticle()._internal.configuration.enablePinning) then
1569
+ urlTransfer.SetCertificatesFile(mparticle()._internal.configuration.certificateDir)
1570
+ end if
1571
+ urlTransfer.SetUrl("https://identity.mparticle.com/v1/" + path)
1572
+ urlTransfer.EnableEncodings(true)
1573
+ requestId = urlTransfer.GetIdentity().ToStr()
1574
+ m.pendingApiRequests[requestId] = { "transfer": urlTransfer, "originalPublicRequest": identityApiRequest, "path": path }
1575
+ dateString = CreateObject("roDateTime").ToISOString()
1576
+ jsonRequest = FormatJson(identityHttpBody)
1577
+ hashString = "POST" + Chr(10) + dateString + Chr(10) + "/v1/" + path + jsonRequest
1578
+
1579
+ signature_key = CreateObject("roByteArray")
1580
+ signature_key.fromAsciiString(mparticle()._internal.configuration.apisecret)
1581
+
1582
+ hmac = CreateObject("roHMAC")
1583
+ hmac.Setup("sha256", signature_key)
1584
+ message = CreateObject("roByteArray")
1585
+ message.FromAsciiString(hashString)
1586
+ result = hmac.process(message)
1587
+ hashResult = LCase(result.ToHexString())
1588
+
1589
+ urlTransfer.AddHeader("Date", dateString)
1590
+ urlTransfer.AddHeader("x-mp-key", mparticle()._internal.configuration.apikey)
1591
+ urlTransfer.AddHeader("x-mp-signature", hashResult)
1592
+ urlTransfer.AddHeader("Content-Type", "application/json")
1593
+ urlTransfer.AddHeader("User-Agent", "mParticle Roku SDK/" + mParticleConstants().SDK_VERSION)
1594
+ urlTransfer.RetainBodyOnError(true)
1595
+ urlTransfer.setPort(m.messagePort)
1596
+ urlTransfer.AsyncPostFromString(jsonRequest)
1597
+ end function,
1598
+ mpHandleUrlEvent: function(urlEvent as object) as object
1599
+ mplogger = mparticle()._internal.logger
1600
+ requestId = urlEvent.GetSourceIdentity().ToStr()
1601
+ requestWrapper = m.pendingApiRequests[requestId]
1602
+ if (requestWrapper = invalid)
1603
+ mplogger.debug("Unknown URL event passed to mParticle, ignoring...")
1604
+ else
1605
+ m.pendingApiRequests.delete(requestId)
1606
+ responseCode = urlEvent.GetResponseCode()
1607
+ responseBody = urlEvent.GetString()
1608
+ mplogger.debug("Identity response: code" + str(responseCode) + " body: " + responseBody)
1609
+ responseObject = {}
1610
+ if (responseBody <> invalid and responseBody.Len() > 0) then
1611
+ responseObject = parsejson(responseBody)
1612
+ end if
1613
+
1614
+ if (responseCode = -77) then
1615
+ mplogger.error("SSL error - please make sure " + mparticle()._internal.configuration.certificateDir + " is present.")
1616
+ else if (responseCode = 400) then
1617
+ mplogger.error("HTTP 400 - bad request.")
1618
+ else if (responseCode = 401) then
1619
+ mplogger.error("HTTP 401 - please check that your mParticle key and secret are valid.")
1620
+ else if (responseCode = 429 or responseCode = 503) then
1621
+ mplogger.error("Identity request is being throttled - please try again later.")
1622
+ else if (responseCode = 200) then
1623
+ storage = mparticle()._internal.storage
1624
+ updateMpid = storage.getCurrentMpid()
1625
+ if (requestWrapper.path.Instr(m.IDENTITY_API_PATHS.MODIFY) = -1) then
1626
+ if (responseObject <> invalid and responseObject.DoesExist("mpid")) then
1627
+ if (responseObject.DoesExist("context")) then
1628
+ m.context = responseObject.context
1629
+ end if
1630
+ if (responseObject.DoesExist("mpid")) then
1631
+ m.onMpidChanged(responseObject.mpid)
1632
+ end if
1633
+ updateMpid = responseObject.mpid
1634
+ else
1635
+ mplogger.error("Identity API returned 200, but there was no MPID present in response.")
1636
+ end if
1637
+ end if
1638
+ m.onIdentitySuccess(updateMpid, requestWrapper.originalPublicRequest)
1639
+ else
1640
+ mplogger.error("Unknown error while performing identity request.")
1641
+ end if
1642
+ return {
1643
+ httpCode: responseCode,
1644
+ body: responseObject
1645
+ }
1646
+ end if
1647
+ end function,
1648
+ isIdentityRequest: function(requestId as string) as boolean
1649
+ return m.pendingApiRequests.DoesExist(requestId)
1650
+ end function,
1651
+ onIdentitySuccess: function(mpid as string, originalRequest as object)
1652
+ storage = mparticle()._internal.storage
1653
+ if (originalRequest <> invalid and originalRequest.userIdentities <> invalid) then
1654
+ for each identityType in originalRequest.userIdentities.keys()
1655
+ storage.setUserIdentity(mpid, identityType, originalRequest.userIdentities[identityType])
1656
+ end for
1657
+ end if
1658
+ end function,
1659
+ onMpidChanged: function(mpid as string) as void
1660
+ storage = mparticle()._internal.storage
1661
+ if (mpid <> storage.getCurrentMpid()) then
1662
+ networking = mparticle()._internal.networking
1663
+ networking.queueUpload()
1664
+ storage.setCurrentMpid(mpid)
1665
+ sessionManager = mparticle()._internal.sessionManager
1666
+ sessionManager.addSessionMpid(mpid)
1667
+ end if
1668
+ end function,
1669
+ getCurrentUser: function() as object
1670
+ storage = mparticle()._internal.storage
1671
+ currentMpid = storage.getCurrentMpid()
1672
+ internalIdentities = storage.getUserIdentities(currentMpid)
1673
+ publicIdentities = {}
1674
+ if (internalIdentities <> invalid) then
1675
+ keys = internalIdentities.Keys()
1676
+ for each identity in keys
1677
+ publicIdentities[identity] = internalIdentities[identity].i
1678
+ end for
1679
+ end if
1680
+ return {
1681
+ mpid: currentMpid,
1682
+ userIdentities: publicIdentities,
1683
+ userAttributes: storage.getUserAttributes(currentMpid)
1684
+ }
1685
+ end function
1686
+ }
1687
+
1688
+ mpIdentityApi = {
1689
+ identify: function(identityApiRequest as object) as void
1690
+ identity = mparticle()._internal.identity
1691
+ identity.identify(identityApiRequest)
1692
+ end function,
1693
+ login: function(identityApiRequest as object) as void
1694
+ identity = mparticle()._internal.identity
1695
+ identity.login(identityApiRequest)
1696
+ end function,
1697
+ logout: function(identityApiRequest as object) as void
1698
+ identity = mparticle()._internal.identity
1699
+ identity.logout(identityApiRequest)
1700
+ end function,
1701
+ modify: function(identityApiRequest as object) as void
1702
+ identity = mparticle()._internal.identity
1703
+ identity.modify(identityApiRequest)
1704
+ end function,
1705
+ setUserAttribute: function(attributeKey as string, attributeValue as object) as void
1706
+ mputils = mparticle()._internal.utils
1707
+ mplogger = mparticle()._internal.logger
1708
+ mpGenericMessage = "User attribute values must be strings or arrays of strings. Discarding value passed to setUserAttribute(): "
1709
+ if (attributeValue = invalid) then
1710
+ mplogger.error(mpGenericMessage + "<invalid>")
1711
+ return
1712
+ end if
1713
+ if (not mputils.isString(attributeValue)) then
1714
+ if (not mputils.isArray(attributeValue)) then
1715
+ mplogger.error(mpGenericMessage + type(attributeValue))
1716
+ return
1717
+ end if
1718
+ for each value in attributeValue
1719
+ if (not mputils.isString(value)) then
1720
+ mplogger.error(mpGenericMessage + type(value))
1721
+ return
1722
+ end if
1723
+ end for
1724
+ end if
1725
+ storage = mparticle()._internal.storage
1726
+ storage.setUserAttribute(storage.getCurrentMpid(), attributeKey, attributeValue)
1727
+ end function,
1728
+ removeUserAttribute: function(attributeKey as string) as void
1729
+ mputils = mparticle()._internal.utils
1730
+ mplogger = mparticle()._internal.logger
1731
+ mpGenericMessage = "User attribute must exist. Discarding user attribue passed to removeUserAttribute(): "
1732
+ currentMpid = mparticle()._internal.storage.getCurrentMpid()
1733
+ attributes = mparticle()._internal.storage.getUserAttributes(currentMpid)
1734
+ if (not attributes.DoesExist(attributeKey)) then
1735
+ mplogger.error(mpGenericMessage + attributeKey)
1736
+ return
1737
+ end if
1738
+ storage = mparticle()._internal.storage
1739
+ storage.removeUserAttribute(currentMpid, attributeKey)
1740
+ end function,
1741
+ setIntegrationAttribute: function(integrationId as string, attributeKey as string, attributeValue as object) as void
1742
+ mputils = mparticle()._internal.utils
1743
+ mplogger = mparticle()._internal.logger
1744
+ mpGenericMessage = "Integration Attribute values must be strings or arrays of strings. Discarding value passed to setIntegrationAttribute(): "
1745
+ if (attributeValue = invalid) then
1746
+ mplogger.error(mpGenericMessage + "<invalid>")
1747
+ return
1748
+ end if
1749
+ if (not mputils.isString(attributeValue)) then
1750
+ if (not mputils.isArray(attributeValue)) then
1751
+ mplogger.error(mpGenericMessage + type(attributeValue))
1752
+ return
1753
+ end if
1754
+ for each value in attributeValue
1755
+ if (not mputils.isString(value)) then
1756
+ mplogger.error(mpGenericMessage + type(value))
1757
+ return
1758
+ end if
1759
+ end for
1760
+ end if
1761
+ storage = mparticle()._internal.storage
1762
+ storage.setIntegrationAttribute(storage.getCurrentMpid(), integrationId, attributeKey, attributeValue)
1763
+ end function,
1764
+ setConsentState: function(consentState as object) as void
1765
+ storage = mparticle()._internal.storage
1766
+ storage.setConsentState(storage.getCurrentMpid(), consentState)
1767
+ end function,
1768
+ IdentityApiRequest: function(userIdentities as object, copyUserAttributes as boolean) as object
1769
+ return {
1770
+ "userIdentities": userIdentities,
1771
+ "copyUserAttributes": copyUserAttributes
1772
+ }
1773
+
1774
+ end function,
1775
+ getCurrentUser: function() as object
1776
+ identity = mparticle()._internal.identity
1777
+ return identity.getCurrentUser()
1778
+ end function
1779
+ }
1780
+
1781
+ mpMediaApi = {
1782
+ getEventAttributes: function(mediaSession as object, customAttributes = {} as object) as object
1783
+ eventAttributes = customAttributes
1784
+ if (mediaSession <> invalid) then
1785
+ eventAttributes.media_session_id = mediaSession.mediaSessionId
1786
+ if (mediaSession.currentPlayheadPosition <> invalid) then
1787
+ eventAttributes.playhead_position = mediaSession.currentPlayheadPosition.ToStr()
1788
+ end if
1789
+ eventAttributes.content_title = mediaSession.title
1790
+ eventAttributes.content_id = mediaSession.contentId
1791
+ if (mediaSession.duration <> invalid) then
1792
+ eventAttributes.content_duration = mediaSession.duration.ToStr()
1793
+ end if
1794
+ eventAttributes.stream_type = mediaSession.streamType
1795
+ eventAttributes.content_type = mediaSession.contentType
1796
+
1797
+ if (mediaSession.adContent <> invalid) then
1798
+ eventAttributes.ad_content_title = mediaSession.adContent.title
1799
+ if (mediaSession.adContent.duration <> invalid) then
1800
+ eventAttributes.ad_content_duration = mediaSession.adContent.duration.ToStr()
1801
+ end if
1802
+ eventAttributes.ad_content_id = mediaSession.adContent.id
1803
+ eventAttributes.ad_content_advertiser = mediaSession.adContent.advertiser
1804
+ eventAttributes.ad_content_campaign = mediaSession.adContent.campaign
1805
+ eventAttributes.ad_content_creative = mediaSession.adContent.creative
1806
+ eventAttributes.ad_content_placement = mediaSession.adContent.placement
1807
+ if (mediaSession.adContent.position <> invalid) then
1808
+ eventAttributes.ad_content_position = mediaSession.adContent.position.ToStr()
1809
+ end if
1810
+ eventAttributes.ad_content_site_id = mediaSession.adContent.siteId
1811
+ end if
1812
+
1813
+ if (mediaSession.adBreak <> invalid) then
1814
+ eventAttributes.ad_break_title = mediaSession.adBreak.title
1815
+ if (mediaSession.adBreak.duration <> invalid) then
1816
+ eventAttributes.ad_break_duration = mediaSession.adBreak.duration.ToStr()
1817
+ end if
1818
+ if (mediaSession.currentPlayheadPosition <> invalid) then
1819
+ eventAttributes.ad_break_playback_time = mediaSession.currentPlayheadPosition.ToStr()
1820
+ end if
1821
+ eventAttributes.ad_break_id = mediaSession.adBreak.id
1822
+ end if
1823
+
1824
+ if (mediaSession.segment <> invalid) then
1825
+ eventAttributes.segment_title = mediaSession.segment.title
1826
+ if (mediaSession.segment.index <> invalid) then
1827
+ eventAttributes.segment_index = mediaSession.segment.index.ToStr()
1828
+ end if
1829
+ if (mediaSession.segment.duration <> invalid) then
1830
+ eventAttributes.segment_duration = mediaSession.segment.duration.ToStr()
1831
+ end if
1832
+ end if
1833
+ end if
1834
+
1835
+ return eventAttributes
1836
+ end function
1837
+ getSummaryAttributes: function(mediaSession as object, customAttributes = {} as object) as object
1838
+ eventAttributes = m.getEventAttributes(mediaSession, customAttributes)
1839
+ if (mediaSession <> invalid) then
1840
+ if (mediaSession.mediaSessionStartTime <> invalid) then
1841
+ eventAttributes.media_session_start_time = mediaSession.mediaSessionStartTime.ToStr()
1842
+ if (mediaSession.mediaSessionEndTime <> invalid) then
1843
+ eventAttributes.media_session_end_time = mediaSession.mediaSessionEndTime.ToStr()
1844
+
1845
+ timeSpent = mediaSession.mediaSessionEndTime - mediaSession.mediaSessionStartTime
1846
+ eventAttributes.media_time_spent = timeSpent.ToStr()
1847
+ end if
1848
+ end if
1849
+ if (mediaSession.mediaContentComplete)
1850
+ eventAttributes.media_content_complete = "true"
1851
+ else
1852
+ eventAttributes.media_content_complete = "false"
1853
+ end if
1854
+ if (mediaSession.mediaContentTimeSpent <> invalid) then
1855
+ eventAttributes.media_content_time_spent = mediaSession.mediaContentTimeSpent.ToStr()
1856
+ end if
1857
+ eventAttributes.media_session_segment_total = mediaSession.mediaSessionSegmentTotal.ToStr()
1858
+ eventAttributes.media_session_ad_total = mediaSession.mediaSessionAdTotal.ToStr()
1859
+ eventAttributes.media_total_ad_time_spent = mediaSession.mediaTotalAdTimeSpent.ToStr()
1860
+ eventAttributes.media_ad_time_spent_rate = mediaSession.mediaAdTimeSpentRate.ToStr()
1861
+ eventAttributes.media_session_ad_objects = formatjson(mediaSession.mediaSessionAdObjects)
1862
+
1863
+ if (mediaSession.adContent <> invalid) then
1864
+ if (mediaSession.adContent.adStartTime <> invalid) then
1865
+ eventAttributes.ad_content_start_time = mediaSession.adContent.adStartTime.ToStr()
1866
+ end if
1867
+ if (mediaSession.adContent.adEndTime <> invalid) then
1868
+ eventAttributes.ad_content_end_time = mediaSession.adContent.adEndTime.ToStr()
1869
+ end if
1870
+ eventAttributes.ad_completed = mediaSession.adContent.adCompleted
1871
+ eventAttributes.ad_skipped = mediaSession.adContent.adSkipped
1872
+ end if
1873
+
1874
+ if (mediaSession.segment <> invalid) then
1875
+ if (mediaSession.segment.segmentStartTime <> invalid) then
1876
+ eventAttributes.segment_start_time = mediaSession.segment.segmentStartTime.ToStr()
1877
+ if (mediaSession.segment.segmentEndTime <> invalid) then
1878
+ eventAttributes.segment_end_time = mediaSession.segment.segmentEndTime.ToStr()
1879
+ timeSpent = mediaSession.segment.segmentEndTime - mediaSession.segment.segmentStartTime
1880
+ eventAttributes.media_segment_time_spent = timeSpent.ToStr()
1881
+ end if
1882
+ end if
1883
+ if (mediaSession.segment.segmentCompleted)
1884
+ eventAttributes.segment_completed = "true"
1885
+ else
1886
+ eventAttributes.segment_completed = "false"
1887
+ end if
1888
+ if (mediaSession.segment.segmentSkipped)
1889
+ eventAttributes.segment_skipped = "true"
1890
+ else
1891
+ eventAttributes.segment_skipped = "false"
1892
+ end if
1893
+ end if
1894
+ end if
1895
+
1896
+ return eventAttributes
1897
+ end function
1898
+ sendMediaMessage: function(eventName as string, eventType as string, attributes = {}) as void
1899
+ messageType = mParticleConstants().MESSAGE_TYPE.CUSTOM
1900
+ currentSession = mparticle()._internal.sessionManager.getCurrentSession()
1901
+ if (attributes <> invalid)
1902
+ if (attributes.count() = 0) then
1903
+ attributes = invalid
1904
+ else
1905
+ mputils = mparticle()._internal.utils
1906
+ attributeKeys = attributes.Keys()
1907
+ validAttributes = {}
1908
+ for each attributeKey in attributeKeys
1909
+ if (mputils.isString(attributes[attributeKey])) then
1910
+ validAttributes[attributeKey] = attributes[attributeKey]
1911
+ end if
1912
+ end for
1913
+ attributes = validAttributes
1914
+ end if
1915
+ end if
1916
+ message = {
1917
+ dt: messageType,
1918
+ id: mparticle()._internal.utils.randomGuid(),
1919
+ ct: mparticle()._internal.utils.unixTimeMillis(),
1920
+ attrs: attributes,
1921
+ sid: currentSession.sessionId,
1922
+ sct: currentSession.startTime
1923
+ }
1924
+ message.n = eventName
1925
+ message.et = eventType
1926
+ message.est = message.ct
1927
+ mparticle().logMessage(message)
1928
+ end function,
1929
+ logMediaSessionStart: function(mediaSession as object, options = {} as object) as void
1930
+ customAttributes = m.getEventAttributes(mediaSession, options)
1931
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SESSION_START, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1932
+ end function
1933
+ logMediaSessionEnd: function(mediaSession as object, options = {} as object) as void
1934
+ customAttributes = m.getEventAttributes(mediaSession, options)
1935
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SESSION_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1936
+ end function
1937
+ logMediaSessionSummary: function(mediaSession as object, options = {} as object) as void
1938
+ customAttributes = m.getSummaryAttributes(mediaSession, options)
1939
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SESSION_SUMMARY, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1940
+ end function
1941
+ logMediaContentEnd: function(mediaSession as object, options = {} as object) as void
1942
+ customAttributes = m.getEventAttributes(mediaSession, options)
1943
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.CONTENT_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1944
+ end function
1945
+ logPlay: function(mediaSession as object, options = {} as object) as void
1946
+ customAttributes = m.getEventAttributes(mediaSession, options)
1947
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.PLAY, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1948
+ end function
1949
+ logPause: function(mediaSession as object, options = {} as object) as void
1950
+ customAttributes = m.getEventAttributes(mediaSession, options)
1951
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.PAUSE, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1952
+ end function
1953
+ logSeekStart: function(mediaSession as object, position as double, options = {} as object) as void
1954
+ customAttributes = m.getEventAttributes(mediaSession, options)
1955
+ customAttributes.seek_position = position
1956
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SEEK_START, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1957
+ end function
1958
+ logSeekEnd: function(mediaSession as object, position as double, options = {} as object) as void
1959
+ customAttributes = m.getEventAttributes(mediaSession, options)
1960
+ customAttributes.seek_position = position
1961
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SEEK_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1962
+ end function
1963
+ logBufferStart: function(mediaSession as object, duration as double, bufferPercent as double, position as double, options = {} as object) as void
1964
+ customAttributes = m.getEventAttributes(mediaSession, options)
1965
+ customAttributes.buffer_duration = duration.ToStr()
1966
+ customAttributes.buffer_percent = bufferPercent.ToStr()
1967
+ customAttributes.buffer_position = position.ToStr()
1968
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.BUFFER_START, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1969
+ end function
1970
+ logBufferEnd: function(mediaSession as object, duration as double, bufferPercent as double, position as double, options = {} as object) as void
1971
+ customAttributes = m.getEventAttributes(mediaSession, options)
1972
+ customAttributes.buffer_duration = duration.ToStr()
1973
+ customAttributes.buffer_percent = bufferPercent.ToStr()
1974
+ customAttributes.buffer_position = position.ToStr()
1975
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.BUFFER_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1976
+ end function
1977
+ logAdBreakStart: function(mediaSession as object, options = {} as object) as void
1978
+ customAttributes = m.getEventAttributes(mediaSession, options)
1979
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_BREAK_START, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1980
+ end function
1981
+ logAdBreakEnd: function(mediaSession as object, options = {} as object) as void
1982
+ customAttributes = m.getEventAttributes(mediaSession, options)
1983
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_BREAK_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1984
+ mediaSession.adBreak = invalid
1985
+ end function
1986
+ logAdStart: function(mediaSession as object, options = {} as object) as void
1987
+ customAttributes = m.getEventAttributes(mediaSession, options)
1988
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_START, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1989
+ end function
1990
+ logAdClick: function(mediaSession as object, options = {} as object) as void
1991
+ customAttributes = m.getEventAttributes(mediaSession, options)
1992
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_CLICK, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1993
+ end function
1994
+ logAdSkip: function(mediaSession as object, options = {} as object) as void
1995
+ customAttributes = m.getEventAttributes(mediaSession, options)
1996
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_SKIP, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
1997
+ mediaSession.adContent = invalid
1998
+ end function
1999
+ logAdEnd: function(mediaSession as object, options = {} as object) as void
2000
+ customAttributes = m.getEventAttributes(mediaSession, options)
2001
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2002
+ mediaSession.adContent = invalid
2003
+ end function
2004
+ logAdSummary: function(mediaSession as object, options = {} as object) as void
2005
+ customAttributes = m.getSummaryAttributes(mediaSession, options)
2006
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.AD_SUMMARY, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2007
+ end function
2008
+ logSegmentStart: function(mediaSession as object, options = {} as object) as void
2009
+ customAttributes = m.getEventAttributes(mediaSession, options)
2010
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SEGMENT_START, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2011
+ end function
2012
+ logSegmentSkip: function(mediaSession as object, options = {} as object) as void
2013
+ customAttributes = m.getEventAttributes(mediaSession, options)
2014
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SEGMENT_SKIP, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2015
+ mediaSession.segment = invalid
2016
+ end function
2017
+ logSegmentEnd: function(mediaSession as object, options = {} as object) as void
2018
+ customAttributes = m.getEventAttributes(mediaSession, options)
2019
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SEGMENT_END, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2020
+ mediaSession.segment = invalid
2021
+ end function
2022
+ logSegmentSummary: function(mediaSession as object, options = {} as object) as void
2023
+ customAttributes = m.getSummaryAttributes(mediaSession, options)
2024
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.SEGMENT_SUMMARY, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2025
+ end function
2026
+ logPlayheadPosition: function(mediaSession as object, options = {} as object) as void
2027
+ customAttributes = m.getEventAttributes(mediaSession, options)
2028
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.UPDATE_PLAYHEAD_POSITION, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2029
+ end function
2030
+ logQoS: function(mediaSession as object, startupTime as integer, droppedFrames as integer, bitRate as integer, fps as integer, options = {} as object) as void
2031
+ customAttributes = m.getEventAttributes(mediaSession, options)
2032
+ customAttributes.qos_bitrate = bitRate.ToStr()
2033
+ customAttributes.qos_fps = fps.ToStr()
2034
+ customAttributes.qos_startup_time = startupTime.ToStr()
2035
+ customAttributes.qos_dropped_frames = droppedFrames.ToStr()
2036
+ m.sendMediaMessage(mparticleConstants().MEDIA_EVENT_NAME.UPDATE_QOS, mparticleConstants().CUSTOM_EVENT_TYPE.MEDIA, customAttributes)
2037
+ end function
2038
+ }
2039
+
2040
+ if (mpUtils.isEmpty(options.apiKey) or mpUtils.isEmpty(options.apiSecret)) then
2041
+ print "mParticleStart() called with empty API key or secret!"
2042
+ end if
2043
+
2044
+ mpCreateConfiguration = function(options as object) as object
2045
+ configuration = mParticleConstants().DEFAULT_OPTIONS
2046
+ for each key in options
2047
+ configuration.AddReplace(key, options[key])
2048
+ end for
2049
+
2050
+ if configuration.environment = mParticleConstants().ENVIRONMENT.FORCE_DEVELOPMENT then
2051
+ configuration.development = true
2052
+ else if configuration.environment = mParticleConstants().ENVIRONMENT.FORCE_PRODUCTION then
2053
+ configuration.development = false
2054
+ else
2055
+ appInfo = CreateObject("roAppInfo")
2056
+ configuration.development = appInfo.IsDev()
2057
+ end if
2058
+ return configuration
2059
+ end function
2060
+
2061
+ 'this is called after everything is initialized
2062
+ 'perform whatever we need to on every startup
2063
+ mpPerformStartupTasks = function(options as object)
2064
+ storage = mparticle()._internal.storage
2065
+ storage.cleanCookies()
2066
+ sessionManager = mparticle()._internal.sessionManager
2067
+ sessionManager.onSdkStart()
2068
+
2069
+ identityApi = mparticle().identity
2070
+ identifyRequest = options.identifyRequest
2071
+ if (identifyRequest = invalid) then
2072
+ identifyRequest = { userIdentities: identityApi.getCurrentUser().userIdentities }
2073
+ end if
2074
+
2075
+ identityApi.identify(identifyRequest)
2076
+ end function
2077
+
2078
+
2079
+ '
2080
+ ' Public API implementations
2081
+ '
2082
+ mpPublicApi = {
2083
+ logEvent: function(eventName as string, eventType = mParticleConstants().CUSTOM_EVENT_TYPE.OTHER, customAttributes = {}) as void
2084
+ m.logMessage(m.model.CustomEvent(eventName, eventType, customAttributes))
2085
+ end function,
2086
+ logScreenEvent: function(screenName as string, customAttributes = {}) as void
2087
+ m.logMessage(m.model.ScreenEvent(screenName, customAttributes))
2088
+ end function,
2089
+ logCommerceEvent: function(productAction = {} as object, promotionAction = {} as object, impressions = [] as object, customAttributes = {} as object, screenName = invalid as string)
2090
+ m.logMessage(m.model.CommerceEvent(productAction, promotionAction, impressions, customAttributes, screenName))
2091
+ end function,
2092
+ logMessage: function(message as object) as void
2093
+ mplogger = mparticle()._internal.logger
2094
+ mplogger.debug("Logging message: " + formatjson(message))
2095
+ m._internal.networking.queueMessage(message)
2096
+ end function,
2097
+ setSessionAttribute: function(attributeKey as string, attributeValue as string) as void
2098
+ m._internal.sessionManager.setSessionAttribute(attributeKey, attributeValue)
2099
+ end function,
2100
+ setOptOut: function(optOut as boolean) as void
2101
+ m.logMessage(m.model.OptOut(optOut))
2102
+ end function,
2103
+ onUrlEvent: function(urlEvent as object)
2104
+ if (m._internal.identity.isIdentityRequest(urlEvent.getSourceIdentity().tostr())) then
2105
+ return m._internal.identity.mpHandleUrlEvent(urlEvent)
2106
+ else
2107
+ m._internal.networking.mpHandleUrlEvent(urlEvent)
2108
+ end if
2109
+ end function,
2110
+ isMparticleEvent: function(sourceIdentity as integer) as boolean
2111
+ isBatchUpload = m._internal.networking.pendingTransfers.DoesExist(sourceIdentity.tostr())
2112
+ isIdentityRequest = m._internal.identity.isIdentityRequest(sourceIdentity.tostr())
2113
+ return isBatchUpload or isIdentityRequest
2114
+ end function,
2115
+ upload: function() as void
2116
+ m._internal.networking.queueUpload()
2117
+ m._internal.networking.processUploads()
2118
+ end function,
2119
+ identity: mpIdentityApi,
2120
+ media: mpMediaApi,
2121
+ model: mpPublicModels
2122
+ }
2123
+
2124
+ internalApi = {
2125
+ utils: mpUtils,
2126
+ logger: mpLogger,
2127
+ configuration: mpCreateConfiguration(options),
2128
+ networking: mpNetworking,
2129
+ storage: mpCreateStorage(),
2130
+ sessionManager: mpCreateSessionManager(options.startupArgs)
2131
+ internalModel: mpInternalModel,
2132
+ identity: mpInternalIdentityApi
2133
+ }
2134
+
2135
+ mpPublicApi.append({ _internal: internalApi })
2136
+ getGlobalAA().mparticleInstance = mpPublicApi
2137
+ mpPerformStartupTasks(options)
2138
+ end function
2139
+
2140
+
2141
+ ' mParticle Scene Graph Bridge
2142
+ ' Use an instance of this class to make calls to mParticle over Scene Graph
2143
+ function mParticleSGBridge(task as object) as object
2144
+ mpCreateSGBridgeIdentityApi = function(task as object) as object
2145
+ return {
2146
+ mParticleTask: task
2147
+ identify: function(identityApiRequest) as void
2148
+ m.invokeFunction("identity/identify", [identityApiRequest])
2149
+ end function,
2150
+ login: function(identityApiRequest) as void
2151
+ m.invokeFunction("identity/login", [identityApiRequest])
2152
+ end function,
2153
+ logout: function(identityApiRequest) as void
2154
+ m.invokeFunction("identity/logout", [identityApiRequest])
2155
+ end function,
2156
+ modify: function(identityApiRequest) as void
2157
+ m.invokeFunction("identity/modify", [identityApiRequest])
2158
+ end function,
2159
+ setUserAttribute: function(attributeKey as string, attributeValue as object) as void
2160
+ m.invokeFunction("identity/setUserAttribute", [attributeKey, attributeValue])
2161
+ end function,
2162
+ removeUserAttribute: function(attributeKey as string) as void
2163
+ m.invokeFunction("identity/removeUserAttribute", [attributeKey])
2164
+ end function
2165
+ setIntegrationAttribute: function(integrationId as string, attributeKey as string, attributeValue as object) as void
2166
+ m.invokeFunction("identity/setIntegrationAttribute", [integrationId, attributeKey, attributeValue])
2167
+ end function,
2168
+ setConsentState: function(consentState as object) as void
2169
+ m.invokeFunction("identity/setConsentState", [consentState])
2170
+ end function
2171
+ invokeFunction: function(name as string, args)
2172
+ invocation = {}
2173
+ invocation.methodName = name
2174
+ invocation.args = args
2175
+ m.mParticleTask[mParticleConstants().SCENEGRAPH_NODES.API_CALL_NODE] = invocation
2176
+ end function
2177
+ }
2178
+ end function
2179
+ mpCreateSGBridgeMediaApi = function(task as object) as object
2180
+ return {
2181
+ mParticleTask: task
2182
+ logMediaSessionStart: function(mediaSession as object, options = {} as object) as void
2183
+ m.invokeFunction("media/logMediaSessionStart", [mediaSession, options])
2184
+ end function,
2185
+ logMediaSessionEnd: function(mediaSession as object, options = {} as object) as void
2186
+ m.invokeFunction("media/logMediaSessionEnd", [mediaSession, options])
2187
+ end function,
2188
+ logMediaSessionSummary: function(mediaSession as object, options = {} as object) as void
2189
+ m.invokeFunction("media/logMediaSessionSummary", [mediaSession, options])
2190
+ end function,
2191
+ logMediaContentEnd: function(mediaSession as object, options = {} as object) as void
2192
+ m.invokeFunction("media/logMediaContentEnd", [mediaSession, options])
2193
+ end function,
2194
+ logPlay: function(mediaSession as object, options = {} as object) as void
2195
+ m.invokeFunction("media/logPlay", [mediaSession, options])
2196
+ end function,
2197
+ logPause: function(mediaSession as object, options = {} as object) as void
2198
+ m.invokeFunction("media/logPause", [mediaSession, options])
2199
+ end function,
2200
+ logSeekStart: function(mediaSession as object, position as double, options = {} as object) as void
2201
+ m.invokeFunction("media/logSeekStart", [mediaSession, position, options])
2202
+ end function,
2203
+ logSeekEnd: function(mediaSession as object, position as double, options = {} as object) as void
2204
+ m.invokeFunction("media/logSeekEnd", [mediaSession, position, options])
2205
+ end function,
2206
+ logBufferStart: function(mediaSession as object, duration as double, bufferPercent as double, position as double, options = {} as object) as void
2207
+ m.invokeFunction("media/logBufferStart", [mediaSession, duration, bufferPercent, position, options])
2208
+ end function,
2209
+ logBufferEnd: function(mediaSession as object, duration as double, bufferPercent as double, position as double, options = {} as object) as void
2210
+ m.invokeFunction("media/logBufferEnd", [mediaSession, duration, bufferPercent, position, options])
2211
+ end function,
2212
+ logAdBreakStart: function(mediaSession as object, options = {} as object) as void
2213
+ m.invokeFunction("media/logAdBreakStart", [mediaSession, options])
2214
+ end function,
2215
+ logAdBreakEnd: function(mediaSession as object, options = {} as object) as void
2216
+ m.invokeFunction("media/logAdBreakEnd", [mediaSession, options])
2217
+ end function,
2218
+ logAdStart: function(mediaSession as object, options = {} as object) as void
2219
+ m.invokeFunction("media/logAdStart", [mediaSession, options])
2220
+ end function,
2221
+ logAdClick: function(mediaSession as object, options = {} as object) as void
2222
+ m.invokeFunction("media/logAdClick", [mediaSession, options])
2223
+ end function,
2224
+ logAdSkip: function(mediaSession as object, options = {} as object) as void
2225
+ m.invokeFunction("media/logAdSkip", [mediaSession, options])
2226
+ end function,
2227
+ logAdEnd: function(mediaSession as object, options = {} as object) as void
2228
+ m.invokeFunction("media/logAdEnd", [mediaSession, options])
2229
+ end function,
2230
+ logAdSummary: function(mediaSession as object, options = {} as object) as void
2231
+ m.invokeFunction("media/logAdSummary", [mediaSession, options])
2232
+ end function,
2233
+ logSegmentStart: function(mediaSession as object, options = {} as object) as void
2234
+ m.invokeFunction("media/logSegmentStart", [mediaSession, options])
2235
+ end function,
2236
+ logSegmentSkip: function(mediaSession as object, options = {} as object) as void
2237
+ m.invokeFunction("media/logSegmentSkip", [mediaSession, options])
2238
+ end function,
2239
+ logSegmentEnd: function(mediaSession as object, options = {} as object) as void
2240
+ m.invokeFunction("media/logSegmentEnd", [mediaSession, options])
2241
+ end function,
2242
+ logSegmentSummary: function(mediaSession as object, options = {} as object) as void
2243
+ m.invokeFunction("media/logSegmentSummary", [mediaSession, options])
2244
+ end function,
2245
+ logPlayheadPosition: function(mediaSession as object, options = {} as object) as void
2246
+ m.invokeFunction("media/logPlayheadPosition", [mediaSession, options])
2247
+ end function,
2248
+ logQoS: function(mediaSession as object, startupTime as integer, droppedFrames as integer, bitRate as integer, fps as integer, options = {} as object) as void
2249
+ m.invokeFunction("media/logQoS", [mediaSession, startupTime, droppedFrames, bitRate, fps, options])
2250
+ end function,
2251
+ invokeFunction: function(name as string, args)
2252
+ invocation = {}
2253
+ invocation.methodName = name
2254
+ invocation.args = args
2255
+ m.mParticleTask[mParticleConstants().SCENEGRAPH_NODES.API_CALL_NODE] = invocation
2256
+ end function
2257
+ }
2258
+ end function
2259
+ return {
2260
+ mParticleTask: task
2261
+ logEvent: function(eventName as string, eventType = mParticleConstants().CUSTOM_EVENT_TYPE.OTHER, customAttributes = {}) as void
2262
+ m.invokeFunction("logEvent", [eventName, eventType, customAttributes])
2263
+ end function,
2264
+ logScreenEvent: function(screenName as string, customAttributes = {}) as void
2265
+ m.invokeFunction("logScreenEvent", [screenName, customAttributes])
2266
+ end function,
2267
+ logCommerceEvent: function(productAction = {} as object, promotionAction = {} as object, impressions = [] as object, customAttributes = {} as object, screenName = "" as string)
2268
+ m.invokeFunction("logCommerceEvent", [productAction, promotionAction, impressions, customAttributes, screenName])
2269
+ end function,
2270
+ logMessage: function(message as object) as void
2271
+ m.invokeFunction("logMessage", [message])
2272
+ end function,
2273
+ setUserAttribute: function(attributeKey as string, attributeValue as object) as void
2274
+ m.invokeFunction("setUserAttribute", [attributeKey, attributeValue])
2275
+ end function,
2276
+ removeUserAttribute: function(attributeKey as string) as void
2277
+ m.invokeFunction("removeUserAttribute", [attributeKey])
2278
+ end function,
2279
+ setIntegrationAttribute: function(integrationId as string, attributeKey as string, attributeValue as object) as void
2280
+ m.invokeFunction("setIntegrationAttribute", [integrationId, attributeKey, attributeValue])
2281
+ end function,
2282
+ setConsentState: function(consentState as object) as void
2283
+ m.invokeFunction("setConsentState", [consentState])
2284
+ end function,
2285
+ setSessionAttribute: function(attributeKey as string, attributeValue as object) as void
2286
+ m.invokeFunction("setSessionAttribute", [attributeKey, attributeValue])
2287
+ end function,
2288
+ upload: function() as void
2289
+ m.invokeFunction("upload", [])
2290
+ end function,
2291
+ identity: mpCreateSGBridgeIdentityApi(task),
2292
+ media: mpCreateSGBridgeMediaApi(task),
2293
+ invokeFunction: function(name as string, args)
2294
+ invocation = {}
2295
+ invocation.methodName = name
2296
+ invocation.args = args
2297
+ m.mParticleTask[mParticleConstants().SCENEGRAPH_NODES.API_CALL_NODE] = invocation
2298
+ end function
2299
+ }
2300
+
2301
+ end function