mparticle-roku-sdk 2.1.16
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/build.yml +26 -0
- package/.gitmodules +3 -0
- package/LICENSE +191 -0
- package/README.md +24 -0
- package/example-legacy-sdk/images/MainMenu_Icon_Center_HD.png +0 -0
- package/example-legacy-sdk/images/MainMenu_Icon_Center_SD43.png +0 -0
- package/example-legacy-sdk/images/MainMenu_Icon_Side_HD.png +0 -0
- package/example-legacy-sdk/images/MainMenu_Icon_Side_SD43.png +0 -0
- package/example-legacy-sdk/images/splash_fhd.jpg +0 -0
- package/example-legacy-sdk/images/splash_hd.jpg +0 -0
- package/example-legacy-sdk/images/splash_sd.jpg +0 -0
- package/example-legacy-sdk/manifest +26 -0
- package/example-legacy-sdk/source/main.brs +45 -0
- package/example-scenegraph-sdk/LICENSE +1 -0
- package/example-scenegraph-sdk/README.md +2 -0
- package/example-scenegraph-sdk/source/Makefile +6 -0
- package/example-scenegraph-sdk/source/app.mk +675 -0
- package/example-scenegraph-sdk/source/components/helloworld.brs +300 -0
- package/example-scenegraph-sdk/source/components/helloworld.xml +66 -0
- package/example-scenegraph-sdk/source/images/channel-poster_fhd.png +0 -0
- package/example-scenegraph-sdk/source/images/channel-poster_hd.png +0 -0
- package/example-scenegraph-sdk/source/images/channel-poster_sd.png +0 -0
- package/example-scenegraph-sdk/source/images/splash-screen_fhd.jpg +0 -0
- package/example-scenegraph-sdk/source/images/splash-screen_hd.jpg +0 -0
- package/example-scenegraph-sdk/source/images/splash-screen_sd.jpg +0 -0
- package/example-scenegraph-sdk/source/manifest +12 -0
- package/example-scenegraph-sdk/source/source/Main.brs +46 -0
- package/example-scenegraph-sdk/source/testFramework/UnitTestFramework.brs +2867 -0
- package/example-scenegraph-sdk/source/tests/TestBasics.brs +266 -0
- package/mParticleBundle.crt +68 -0
- package/mParticleCore.brs +2301 -0
- package/mParticleTask.brs +78 -0
- package/mParticleTask.xml +12 -0
- package/package.json +5 -0
- 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
|