mparticle-roku-sdk 2.1.16

Sign up to get free protection for your applications and to get access to all the features.
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