mparticle-roku-sdk 2.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|