backend-manager 3.2.169 → 3.2.171

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/dist/cli/cli.js +1534 -0
  4. package/dist/manager/functions/core/actions/api/admin/backup.js +338 -0
  5. package/dist/manager/functions/core/actions/api/admin/create-post.js +388 -0
  6. package/dist/manager/functions/core/actions/api/admin/cron.js +37 -0
  7. package/dist/manager/functions/core/actions/api/admin/database-read.js +35 -0
  8. package/dist/manager/functions/core/actions/api/admin/database-write.js +39 -0
  9. package/dist/manager/functions/core/actions/api/admin/edit-post.js +158 -0
  10. package/dist/manager/functions/core/actions/api/admin/firestore-query.js +165 -0
  11. package/dist/manager/functions/core/actions/api/admin/firestore-read.js +38 -0
  12. package/dist/manager/functions/core/actions/api/admin/firestore-write.js +54 -0
  13. package/dist/manager/functions/core/actions/api/admin/get-stats.js +269 -0
  14. package/dist/manager/functions/core/actions/api/admin/payment-processor.js +57 -0
  15. package/dist/manager/functions/core/actions/api/admin/run-hook.js +95 -0
  16. package/dist/manager/functions/core/actions/api/admin/send-notification.js +197 -0
  17. package/dist/manager/functions/core/actions/api/admin/sync-users.js +125 -0
  18. package/dist/manager/functions/core/actions/api/admin/templates/post.html +16 -0
  19. package/dist/manager/functions/core/actions/api/firebase/get-providers.js +102 -0
  20. package/dist/manager/functions/core/actions/api/general/emails/general:download-app-link.js +21 -0
  21. package/dist/manager/functions/core/actions/api/general/fetch-post.js +99 -0
  22. package/dist/manager/functions/core/actions/api/general/generate-uuid.js +41 -0
  23. package/dist/manager/functions/core/actions/api/general/send-email.js +112 -0
  24. package/dist/manager/functions/core/actions/api/handler/create-post.js +146 -0
  25. package/dist/manager/functions/core/actions/api/special/setup-electron-manager-client.js +103 -0
  26. package/dist/manager/functions/core/actions/api/template.js +33 -0
  27. package/dist/manager/functions/core/actions/api/test/authenticate.js +22 -0
  28. package/dist/manager/functions/core/actions/api/test/create-test-accounts.js +27 -0
  29. package/dist/manager/functions/core/actions/api/test/lab.js +55 -0
  30. package/dist/manager/functions/core/actions/api/test/redirect.js +26 -0
  31. package/dist/manager/functions/core/actions/api/test/webhook.js +30 -0
  32. package/dist/manager/functions/core/actions/api/user/create-custom-token.js +32 -0
  33. package/dist/manager/functions/core/actions/api/user/delete.js +68 -0
  34. package/dist/manager/functions/core/actions/api/user/get-active-sessions.js +45 -0
  35. package/dist/manager/functions/core/actions/api/user/get-subscription-info.js +49 -0
  36. package/dist/manager/functions/core/actions/api/user/oauth2/discord.js +114 -0
  37. package/dist/manager/functions/core/actions/api/user/oauth2/google.js +99 -0
  38. package/dist/manager/functions/core/actions/api/user/oauth2.js +476 -0
  39. package/dist/manager/functions/core/actions/api/user/regenerate-api-keys.js +54 -0
  40. package/dist/manager/functions/core/actions/api/user/resolve.js +32 -0
  41. package/dist/manager/functions/core/actions/api/user/sign-out-all-sessions.js +118 -0
  42. package/dist/manager/functions/core/actions/api/user/sign-up copy.js +544 -0
  43. package/dist/manager/functions/core/actions/api/user/sign-up.js +99 -0
  44. package/dist/manager/functions/core/actions/api/user/submit-feedback.js +96 -0
  45. package/dist/manager/functions/core/actions/api/user/validate-settings.js +86 -0
  46. package/dist/manager/functions/core/actions/api.js +354 -0
  47. package/dist/manager/functions/core/actions/create-post-handler.js +184 -0
  48. package/dist/manager/functions/core/actions/generate-uuid.js +62 -0
  49. package/dist/manager/functions/core/actions/sign-up-handler.js +205 -0
  50. package/dist/manager/functions/core/admin/create-post.js +206 -0
  51. package/dist/manager/functions/core/admin/firestore-write.js +72 -0
  52. package/dist/manager/functions/core/admin/get-stats.js +218 -0
  53. package/dist/manager/functions/core/admin/query.js +198 -0
  54. package/dist/manager/functions/core/admin/send-notification.js +206 -0
  55. package/dist/manager/functions/core/cron/daily/ghostii-auto-publisher.js +377 -0
  56. package/dist/manager/functions/core/cron/daily/reset-usage.js +197 -0
  57. package/dist/manager/functions/core/cron/daily.js +114 -0
  58. package/dist/manager/functions/core/events/auth/before-create.js +124 -0
  59. package/dist/manager/functions/core/events/auth/before-signin.js +62 -0
  60. package/dist/manager/functions/core/events/auth/on-create copy.js +121 -0
  61. package/dist/manager/functions/core/events/auth/on-create.js +564 -0
  62. package/dist/manager/functions/core/events/auth/on-delete.js +72 -0
  63. package/dist/manager/functions/core/events/firestore/on-subscription.js +107 -0
  64. package/dist/manager/functions/test/authenticate.js +38 -0
  65. package/dist/manager/functions/test/create-test-accounts.js +144 -0
  66. package/dist/manager/functions/test/webhook.js +37 -0
  67. package/dist/manager/functions/wrappers/mailchimp/addToList.js +25 -0
  68. package/dist/manager/helpers/analytics copy.js +217 -0
  69. package/dist/manager/helpers/analytics.js +467 -0
  70. package/dist/manager/helpers/api-manager.js +324 -0
  71. package/dist/manager/helpers/assistant.js +1043 -0
  72. package/dist/manager/helpers/metadata.js +32 -0
  73. package/dist/manager/helpers/middleware.js +154 -0
  74. package/dist/manager/helpers/roles.js +69 -0
  75. package/dist/manager/helpers/settings.js +158 -0
  76. package/dist/manager/helpers/subscription-resolver-new.js +828 -0
  77. package/dist/manager/helpers/subscription-resolver.js +842 -0
  78. package/dist/manager/helpers/usage.js +381 -0
  79. package/dist/manager/helpers/user.js +198 -0
  80. package/dist/manager/helpers/utilities.js +292 -0
  81. package/dist/manager/index.js +1076 -0
  82. package/dist/manager/libraries/openai.js +460 -0
  83. package/dist/manager/routes/restart/index.js +52 -0
  84. package/dist/manager/routes/test/index.js +43 -0
  85. package/dist/manager/schemas/restart.js +13 -0
  86. package/dist/manager/schemas/test.js +13 -0
  87. package/dist/require.js +3 -0
  88. package/package.json +19 -9
@@ -0,0 +1,467 @@
1
+ const fetch = require('wonderful-fetch');
2
+ const moment = require('moment');
3
+ const crypto = require('crypto');
4
+ let uuidv5;
5
+
6
+ const UUID_REGEX = /[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/;
7
+ const BLOCKED_USER_AGENTS = [
8
+ /(node-fetch)/ig,
9
+ ];
10
+
11
+ function Analytics(Manager, options) {
12
+ const self = this;
13
+
14
+ // Set initialized
15
+ self.initialized = false;
16
+
17
+ // Fix options
18
+ options = options || {};
19
+
20
+ // Set properties
21
+ self.Manager = Manager;
22
+ self.assistant = options?.assistant || Manager.Assistant();
23
+
24
+ // Set request properties
25
+ self.request = {
26
+ ip: self.assistant?.request?.geolocation?.ip || '127.0.0.1',
27
+ country: self.assistant?.request?.geolocation?.country || '',
28
+ city: self.assistant?.request?.geolocation?.city || '',
29
+ region: self.assistant?.request?.geolocation?.region || '',
30
+ referrer: self.assistant?.request?.referrer || '',
31
+ userAgent: self.assistant?.request?.client?.userAgent || '',
32
+ language: (self.assistant?.request?.client?.language || '').split(',')[0],
33
+ mobile: self.assistant?.request?.client?.mobile || false,
34
+ platform: self.assistant?.request?.client?.platform || '',
35
+ name: self.assistant?.meta?.name || '',
36
+ }
37
+
38
+ // Remove blacklisted user agents
39
+ self.request.userAgent = BLOCKED_USER_AGENTS.some((regex) => self.request.userAgent.match(regex))
40
+ ? ''
41
+ : self.request.userAgent;
42
+
43
+ // Fix options
44
+ options.dataSource = options.dataSource || 'server';
45
+ options.uuid = options.uuid || self.request.ip || Manager.SERVER_UUID;
46
+ options.isDevelopment = typeof options.isDevelopment === 'undefined' ? self.assistant.isDevelopment() : options.isDevelopment;
47
+ options.pageview = typeof options.pageview === 'undefined' ? true : options.pageview;
48
+ options.version = options.version || Manager.package.version;
49
+ options.userProperties = options.userProperties || {};
50
+ options.userData = options.userData || {};
51
+
52
+ // Set user
53
+ // https://www.optimizesmart.com/how-to-create-and-use-user-properties-in-ga4/
54
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/user-properties?client_type=gtag
55
+ // https://support.google.com/analytics/answer/12980150?hl=en&co=GENIE.Platform%3DAndroid
56
+ const authUser = self.assistant?.usage?.user;
57
+ self.userProperties = {
58
+ app_version: {
59
+ value: options.version,
60
+ },
61
+ // browser: {
62
+ // value: self.request.userAgent,
63
+ // },
64
+ device_category: {
65
+ value: self.request.mobile ? 'mobile' : 'desktop',
66
+ },
67
+ // device_model: {
68
+ // value: 'None',
69
+ // },
70
+ operating_system: {
71
+ value: self.request.platform,
72
+ },
73
+ // os_version: {
74
+ // value: 'None',
75
+ // },
76
+ // os_with_version: {
77
+ // value: 'None',
78
+ // },
79
+ platform: {
80
+ value: 'web',
81
+ },
82
+ // screen_resolution: {
83
+ // value: 'None',
84
+ // },
85
+ age: {
86
+ value: authUser?.personal?.birthday?.timestampUNIX
87
+ ? new Date().getFullYear() - new Date(authUser?.personal?.birthday?.timestampUNIX).getFullYear()
88
+ : 'None',
89
+ },
90
+ country: {
91
+ value: self.request.country
92
+ },
93
+ city: {
94
+ value: self.request.city
95
+ },
96
+ gender: {
97
+ value: authUser?.personal?.gender
98
+ ? authUser?.personal?.gender
99
+ : 'None',
100
+ },
101
+ // interests: {
102
+ // value: 'None',
103
+ // },
104
+ language: {
105
+ value: self.request.language,
106
+ },
107
+
108
+ // TODO
109
+ // Add custom events for user properties, like plan ID, etc, draw from self.assistant.usage, etc
110
+ authenticated: {
111
+ value: authUser?.auth?.uid ? true : false,
112
+ },
113
+ plan_id: {
114
+ value: authUser?.plan?.id || 'basic',
115
+ },
116
+ plan_trial_activated: {
117
+ value: authUser?.plan?.trial?.activated || false,
118
+ },
119
+ activity_created: {
120
+ value: moment(authUser?.activity?.created?.timestampUNIX
121
+ ? authUser?.activity?.created?.timestamp
122
+ : self.assistant.meta.startTime.timestamp).format('YYYY-MM-DD'),
123
+ },
124
+
125
+ // ds? 'app
126
+ // uid?
127
+ // uip?
128
+ // ua?
129
+ // dr? (referrer)
130
+ };
131
+
132
+ // Fix user data
133
+ // https://developers.google.com/analytics/devguides/collection/ga4/uid-data
134
+ // https://stackoverflow.com/questions/68636233/ga4-measurement-protocol-does-not-display-user-data-location-screen-resolution
135
+ self.userData = {
136
+ sha256_email_address: authUser?.auth?.email
137
+ ? toSHA256(authUser?.auth?.email)
138
+ : undefined,
139
+ sha256_phone_number: authUser?.personal?.telephone?.number
140
+ ? toSHA256(authUser?.personal?.telephone?.countryCode + authUser?.personal?.telephone?.number)
141
+ : undefined,
142
+ address: {
143
+ sha256_first_name: authUser?.personal?.name?.first
144
+ ? toSHA256(authUser?.personal?.name?.first)
145
+ : undefined,
146
+ sha256_last_name: authUser?.personal?.name?.last
147
+ ? toSHA256(authUser?.personal?.name?.last)
148
+ : undefined,
149
+ // sha256_street: TODO,
150
+ city: self.request.city || undefined,
151
+ region: self.request.region || undefined,
152
+ // postal_code: TODO,
153
+ country: self.request.country || undefined,
154
+ }
155
+ }
156
+
157
+ // Merge user properties
158
+ self.userProperties = {
159
+ ...self.userProperties,
160
+ ...options.userProperties,
161
+ };
162
+
163
+ // Set id and secret
164
+ self.analyticsId = self?.Manager?.config?.google_analytics?.id;
165
+ self.analyticsSecret = self?.Manager?.config?.google_analytics?.secret;
166
+
167
+ // Check if we have the required properties
168
+ if (!self.analyticsId) {
169
+ self.assistant.log('analytics(): Not initializing because missing analyticsId', self.analyticsId);
170
+ return self;
171
+ } else if (!self.analyticsSecret) {
172
+ self.assistant.log('analytics(): Not initializing because missing analyticsSecret', self.analyticsSecret);
173
+ return self;
174
+ }
175
+
176
+ // Automatically convert the supplied uuid to a valid uuid (in case the user supplies something else like an IP or email)
177
+ options.uuid = options.uuid.match(UUID_REGEX)
178
+ ? options.uuid
179
+ : self.generateId(options.uuid);
180
+
181
+ // Attach options
182
+ self.options = options;
183
+
184
+ // Set initialized
185
+ self.initialized = true;
186
+
187
+ // Send pageview if enabled
188
+ // .. Removed
189
+
190
+ // Return
191
+ return self;
192
+ }
193
+
194
+ Analytics.prototype.generateId = function (id) {
195
+ const self = this;
196
+ const Manager = self.Manager;
197
+ const assistant = self.assistant;
198
+ const options = self.options;
199
+ const request = self.request;
200
+ const userProperties = self.userProperties;
201
+ const userData = self.userData;
202
+
203
+ // Load uuidv5
204
+ uuidv5 = uuidv5 || require('uuid').v5;
205
+
206
+ // Get namespace
207
+ const namespace = Manager?.config?.backend_manager?.namespace || undefined;
208
+
209
+ // Generate id
210
+ return id && namespace
211
+ ? uuidv5(id, namespace)
212
+ : undefined;
213
+ };
214
+
215
+ Analytics.prototype.event = function (payload) {
216
+ const self = this;
217
+ const Manager = self.Manager;
218
+ const assistant = self.assistant;
219
+ const options = self.options;
220
+ const request = self.request;
221
+ const userProperties = self.userProperties;
222
+ const userData = self.userData;
223
+
224
+ // Fix payload
225
+ // https://support.google.com/analytics/answer/13316687?hl=en#zippy=%2Cweb
226
+ // https://support.google.com/analytics/answer/9268042?sjid=4476481583372132143-NC
227
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#screen_view
228
+ payload = payload || {};
229
+
230
+ // Fix event name
231
+ payload.name = (payload.name || '')
232
+ // Replace anything not a letter, number, or underscore with an underscore
233
+ .replace(/[^a-zA-Z0-9_]/g, '_')
234
+ // Remove leading and trailing underscores
235
+ .replace(/^_+|_+$/g, '')
236
+ // Remove multiple underscores
237
+ .replace(/_+/g, '_');
238
+
239
+ // Fix event params
240
+ payload.params = payload.params || {};
241
+
242
+ // Check if initialized
243
+ if (!self.initialized) {
244
+ return self;
245
+ } else if (options.isDevelopment) {
246
+ assistant.log('analytics().event(): Skipping because in development', options.uuid, JSON.stringify(payload));
247
+ return self;
248
+ }
249
+
250
+ // https://stackoverflow.com/questions/71871458/how-to-send-user-properties-to-measurement-protocol-google-analytics-4
251
+
252
+ // USer properties
253
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/user-properties?client_type=gtag
254
+
255
+ // raw
256
+ // https://stackoverflow.com/questions/69105735/google-analytics-4-measurement-protocol-api-used-without-gtag-js-or-firebase
257
+
258
+ // Fix payload
259
+ payload.params.event_source = options.dataSource;
260
+ payload.params.page_location = request.name; // Supposed to be domain
261
+ // payload.params.page_location = `${INSERT DOMAIN HERE}${request.name}`; // Supposed to be domain
262
+ payload.params.page_title = request.name; // Supposed to be title
263
+ payload.params.ip_override = request.ip;
264
+ payload.params.user_agent = request.userAgent;
265
+ payload.params.page_referrer = request.referrer;
266
+ // https://stackoverflow.com/questions/70708893/google-analytics-4-measurement-protocol-shows-events-but-no-users/71811327#71811327
267
+ payload.params.engagement_time_msec = new Date().getTime() - new Date(assistant.meta.startTime.timestamp).getTime();
268
+ // payload.params.engagement_time_msec = 1;
269
+ payload.params.debug_mode = false;
270
+ payload.params.session_id = assistant.id;
271
+ // payload.params.campaign = 'your_campaign';
272
+ // payload.params.source = 'your_source';
273
+ // payload.params.medium = 'your_medium';
274
+ // payload.params.term = 'your_term';
275
+ // payload.params.content = 'your_content';
276
+
277
+
278
+ // https://stackoverflow.com/questions/75998626/city-is-not-populating-in-ga4-measurement-protocol-api
279
+ // {
280
+ // "client_id": "6909975079.1681323722",
281
+ // "events": [
282
+ // {
283
+ // "name": "page_view",
284
+ // "params": {
285
+ // "page_title": "Wedding: QR Code",
286
+ // "hostname": "scan.example.com",
287
+ // "landing_page": "/eRCU",
288
+ // "page_location": "https://scan.example.com/eRCU",
289
+ // "page_referrer": "https://scan.example.com/eRCU",
290
+ // "city": "Mumbai",
291
+ // "continent_code": "AS",
292
+ // "country_code": "IN",
293
+ // "country": "India",
294
+ // "latitude": "19.0748",
295
+ // "longitude": "72.8856",
296
+ // "session_id": 1681313623,
297
+ // "engagement_time_msec": 264,
298
+ // "ip_address": "XX.36.XXX.14"
299
+ // }
300
+ // }
301
+ // ]
302
+ // }
303
+
304
+ // Build url and body
305
+ const url = `https://www.google-analytics.com/mp/collect?measurement_id=${self.analyticsId}&api_secret=${self.analyticsSecret}`;
306
+ const body = {
307
+ client_id: self.options.uuid,
308
+ user_id: self.options.uuid,
309
+ // timestamp_micros: new Date().getTime() * 1000,
310
+ user_properties: userProperties,
311
+ user_data: userData,
312
+ // consent: {},
313
+ // non_personalized_ads: false,
314
+ events: [payload],
315
+ }
316
+
317
+ // Log full payload
318
+ if (assistant.isDevelopment()) {
319
+ assistant.log('analytics().event(): Sending...', url, JSON.stringify(body));
320
+ }
321
+
322
+ // Send event
323
+ fetch(url, {
324
+ method: 'post',
325
+ response: 'text',
326
+ tries: 2,
327
+ timeout: 30000,
328
+ // headers: {
329
+ // "Content-Type": "application/json"
330
+ // },
331
+ body: body,
332
+ })
333
+ .then((r) => {
334
+ if (assistant.isDevelopment()) {
335
+ assistant.log('analytics().event(): Success', r);
336
+ }
337
+ })
338
+ .catch((e) => {
339
+ assistant.error('analytics().event(): Failed', e);
340
+ });
341
+
342
+ // Return
343
+ return self;
344
+ };
345
+
346
+
347
+
348
+
349
+ // Analytics.prototype.send = function (event) {
350
+ // const self = this;
351
+
352
+ // // Check if initialized
353
+ // if (!self.initialized) {
354
+ // return self;
355
+ // } else if (self.options.isDevelopment) {
356
+ // assistant.log('analytics(): Skipping Analytics.event() because in development', self.options.uuid, event);
357
+ // return self;
358
+ // }
359
+
360
+ // /*
361
+ // https://stackoverflow.com/questions/68773179/what-should-the-client-id-be-when-sending-events-to-google-analytics-4-using-the
362
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag
363
+
364
+
365
+ // https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#sc
366
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#recommended_parameters_for_reports
367
+ // https://stackoverflow.com/questions/43049662/how-to-send-measurement-protocol-if-there-is-no-clientid
368
+
369
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/validating-events?client_type=gtag
370
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag
371
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events
372
+ // https://developers.google.com/analytics/devguides/collection/protocol/ga4/ua-feature-matrix
373
+ // */
374
+
375
+
376
+ // /*
377
+
378
+ // */
379
+
380
+ // // Format event
381
+ // // event = event || {};
382
+ // // event.name = event.name || '';
383
+ // // event.params = event.params || {};
384
+ // // event.params.engagement_time_msec = `${new Date().getTime() - new Date(self.assistant.meta.startTime.timestamp).getTime()}`;
385
+ // // event.params.event_source = self.options.dataSource;
386
+ // // event.params.ip_override = self.request.ip;
387
+ // // event.params.user_agent = self.request.userAgent;
388
+ // // event.params.page_location = self.request.name;
389
+ // // event.params.page_referrer = self.request.referrer;
390
+ // // event.params.page_title = self.request.name;
391
+
392
+ // event = event || {};
393
+ // event.name = event.name || '';
394
+ // event.params = event.params || {};
395
+ // // event.params.session_id = self.assistant.id;
396
+ // // event.params.engagement_time_msec = `${new Date().getTime() - new Date(self.assistant.meta.startTime.timestamp).getTime()}`;
397
+ // // event.params.event_source = self.options.dataSource;
398
+ // // event.params.ip_override = self.request.ip;
399
+ // // event.params.user_agent = self.request.userAgent;
400
+ // // event.params.page_location = self.request.name;
401
+ // // event.params.page_referrer = self.request.referrer;
402
+ // // event.params.page_title = self.request.name;
403
+
404
+ // // "event_source": "server",
405
+ // // "page_location": "https:\/\/www.yourdomain.com\/page2",
406
+ // // "page_referrer": "\/page1",
407
+ // // "page_title": "Page 2",
408
+ // // "ip_override": "xxx.xxx.xxx.0",
409
+ // // "campaign": "your_campaign",
410
+ // // "source": "your_source",
411
+ // // "medium": "your_medium",
412
+ // // "term": "your_term",
413
+ // // "content": "your_content"
414
+
415
+ // const url = `https://www.google-analytics.com/mp/collect?measurement_id=${self.analyticsId}&api_secret=${self.analyticsSecret}`;
416
+ // const body = {
417
+ // client_id: self.options.uuid,
418
+ // user_id: self.options.uuid,
419
+ // // timestamp_micros: new Date().getTime() * 1000,
420
+ // user_properties: {},
421
+ // // consent: {},
422
+ // // non_personalized_ads: false,
423
+ // events: [event],
424
+ // }
425
+
426
+ // // Log
427
+ // if (self.assistant.isDevelopment()) {
428
+ // assistant.log('analytics().send(): Sending...', url, JSON.stringify(body));
429
+ // }
430
+
431
+ // // Send event
432
+ // fetch(url, {
433
+ // // fetch(`https://www.google-analytics.com/debug/mp/collect?measurement_id=${self.analyticsId}&api_secret=${self.analyticsSecret}`, {
434
+ // method: 'post',
435
+ // response: 'text',
436
+ // tries: 2,
437
+ // timeout: 30000,
438
+ // // headers: {
439
+ // // "Content-Type": "application/json"
440
+ // // },
441
+ // body: body,
442
+ // })
443
+ // .then((r) => {
444
+ // if (self.assistant.isDevelopment()) {
445
+ // assistant.log('analytics().send(): Success', r);
446
+ // }
447
+ // })
448
+ // .catch((e) => {
449
+ // self.assistant.error('analytics().send(): Failed', e);
450
+ // });
451
+
452
+ // return self;
453
+ // };
454
+
455
+ /*
456
+ Unlike gtag, which automatically hashes sensitive user-provided data, the Measurement Protocol requires a developer to hash sensitive user-provided data using a secure one-way hashing algorithm called SHA256 and encode it using hex string format prior to calling the API.
457
+
458
+ All user data fields starting with the sha256 prefix in their name should be only populated with hashed and hex-encoded values.
459
+
460
+ The following example code performs the necessary encryption and encoding steps:
461
+ */
462
+
463
+ function toSHA256(value) {
464
+ return crypto.createHash('sha256').update(value).digest('hex');
465
+ }
466
+
467
+ module.exports = Analytics;