@meltwater/conversations-api-services 1.0.19 → 1.0.21

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 (70) hide show
  1. package/.github/workflows/release.yml +2 -0
  2. package/babel.config.js +18 -0
  3. package/dist/cjs/data-access/http/InstagramVideoClient.js +42 -0
  4. package/dist/cjs/data-access/http/WarpZoneApi.client.js +32 -0
  5. package/dist/cjs/data-access/http/amazonS3.js +44 -0
  6. package/dist/cjs/data-access/http/asset-manager-tvm.client.js +35 -0
  7. package/dist/cjs/data-access/http/companiesApi.client.js +38 -0
  8. package/dist/cjs/data-access/http/credentialsApi.client.js +102 -0
  9. package/dist/cjs/data-access/http/entitlementsApi.client.js +40 -0
  10. package/dist/cjs/data-access/http/facebook.native.js +344 -0
  11. package/dist/cjs/data-access/http/facebookApi.client.js +631 -0
  12. package/dist/cjs/data-access/http/featureToggleApi.client.js +31 -0
  13. package/dist/cjs/data-access/http/identityServices.client.js +97 -0
  14. package/dist/cjs/data-access/http/instagramApi.client.js +428 -0
  15. package/dist/cjs/data-access/http/ir.client.js +242 -0
  16. package/dist/cjs/data-access/http/linkedInApi.client.js +491 -0
  17. package/dist/cjs/data-access/http/masf.client.js +101 -0
  18. package/dist/cjs/data-access/http/tiktok.native.js +162 -0
  19. package/dist/cjs/data-access/http/tiktokApi.client.js +441 -0
  20. package/dist/cjs/data-access/index.js +132 -0
  21. package/dist/cjs/errors/engage-error.js +16 -0
  22. package/dist/cjs/errors/http-error.js +23 -0
  23. package/dist/cjs/lib/applicationTags.helpers.js +30 -0
  24. package/dist/cjs/lib/configuration.js +14 -0
  25. package/dist/cjs/lib/document-action-events.js +12 -0
  26. package/dist/cjs/lib/externalId.helpers.js +19 -0
  27. package/dist/cjs/lib/hidden.helpers.js +13 -0
  28. package/dist/cjs/lib/hiddenComment.helper.js +119 -0
  29. package/dist/cjs/lib/logger.helpers.js +68 -0
  30. package/dist/cjs/lib/logger.js +23 -0
  31. package/dist/cjs/lib/message.helpers.js +58 -0
  32. package/dist/cjs/lib/metrics.helper.js +97 -0
  33. package/dist/esm/data-access/http/InstagramVideoClient.js +34 -0
  34. package/dist/esm/data-access/http/WarpZoneApi.client.js +24 -0
  35. package/dist/esm/data-access/http/amazonS3.js +37 -0
  36. package/dist/esm/data-access/http/asset-manager-tvm.client.js +28 -0
  37. package/dist/esm/data-access/http/companiesApi.client.js +30 -0
  38. package/dist/esm/data-access/http/credentialsApi.client.js +92 -0
  39. package/dist/esm/data-access/http/entitlementsApi.client.js +32 -0
  40. package/dist/esm/data-access/http/facebook.native.js +325 -0
  41. package/dist/esm/data-access/http/facebookApi.client.js +621 -0
  42. package/dist/esm/data-access/http/featureToggleApi.client.js +23 -0
  43. package/dist/esm/data-access/http/identityServices.client.js +89 -0
  44. package/dist/esm/data-access/http/instagramApi.client.js +420 -0
  45. package/dist/esm/data-access/http/ir.client.js +234 -0
  46. package/dist/esm/data-access/http/linkedInApi.client.js +481 -0
  47. package/dist/esm/data-access/http/masf.client.js +93 -0
  48. package/dist/esm/data-access/http/tiktok.native.js +146 -0
  49. package/dist/esm/data-access/http/tiktokApi.client.js +433 -0
  50. package/dist/esm/data-access/index.js +30 -0
  51. package/dist/esm/errors/engage-error.js +9 -0
  52. package/dist/esm/errors/http-error.js +16 -0
  53. package/dist/esm/lib/applicationTags.helpers.js +22 -0
  54. package/dist/esm/lib/configuration.js +8 -0
  55. package/dist/esm/lib/document-action-events.js +6 -0
  56. package/dist/esm/lib/externalId.helpers.js +12 -0
  57. package/dist/esm/lib/hidden.helpers.js +6 -0
  58. package/dist/esm/lib/hiddenComment.helper.js +112 -0
  59. package/dist/esm/lib/logger.helpers.js +60 -0
  60. package/dist/esm/lib/logger.js +16 -0
  61. package/dist/esm/lib/message.helpers.js +52 -0
  62. package/dist/esm/lib/metrics.helper.js +90 -0
  63. package/package.json +14 -4
  64. package/src/data-access/http/facebook.native.js +542 -0
  65. package/src/data-access/http/tiktok.native.js +248 -0
  66. package/src/data-access/index.js +4 -0
  67. package/src/errors/engage-error.js +11 -0
  68. package/src/errors/http-error.js +19 -0
  69. package/src/lib/logger.helpers.js +15 -0
  70. package/src/lib/message.helpers.js +7 -1
@@ -0,0 +1,621 @@
1
+ import superagent from 'superagent'; // @todo remove superagent
2
+ import logger from '../../lib/logger.js';
3
+ import { removePrefix } from '../../lib/externalId.helpers.js';
4
+ import { CredentialsApiClient } from '../http/credentialsApi.client.js';
5
+ import { MeltwaterAttributes } from '../../lib/logger.helpers.js';
6
+ const FACEBOOK_URL = 'https://graph.facebook.com';
7
+ export class FacebookApiClient {
8
+ constructor() {
9
+ this.credentialsAPI = new CredentialsApiClient();
10
+ }
11
+
12
+ // assumes all documents are from same credential
13
+ async shareCount(documents) {
14
+ const {
15
+ documentId,
16
+ metaData: {
17
+ discussionType = 'og'
18
+ } = {},
19
+ systemData: {
20
+ connectionsCredential: credentialId,
21
+ policies: {
22
+ storage: {
23
+ privateTo: companyId
24
+ } = {}
25
+ } = {}
26
+ } = {}
27
+ } = documents;
28
+ if (discussionType !== 'og') {
29
+ return;
30
+ }
31
+ try {
32
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
33
+ const response = await this.getApi(`${FACEBOOK_URL}/${removePrefix(documents.metaData.externalId)}/?fields=shares`, token.token, documentId);
34
+ return response.body.shares && response.body.shares.count;
35
+ } catch (error) {
36
+ logger.error(`${documentId} - error recieved - ${error.code}`, error, {
37
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
38
+ [MeltwaterAttributes.COMPANYID]: companyId,
39
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
40
+ });
41
+ return undefined;
42
+ }
43
+ }
44
+ async reactions(documents) {
45
+ const {
46
+ documentId,
47
+ systemData: {
48
+ connectionsCredential: credentialId,
49
+ policies: {
50
+ storage: {
51
+ privateTo: companyId
52
+ } = {}
53
+ } = {}
54
+ } = {}
55
+ } = documents[0];
56
+ try {
57
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
58
+ const response = await this.getApi(`${FACEBOOK_URL}?ids=${documents.map(doc => removePrefix(doc.metaData.externalId)).join(',')}&fields=` + `reactions.limit(0).summary(viewer_reaction).as(fb_post_reaction_of_user),` + `reactions.type(LOVE).limit(0).summary(total_count).as(fb_post_reactions_love),` + `reactions.type(WOW).limit(0).summary(total_count).as(fb_post_reactions_wow),` + `reactions.type(SAD).limit(0).summary(total_count).as(fb_post_reactions_sad),` + `reactions.type(LIKE).limit(0).summary(total_count).as(fb_post_reactions_like),` + `reactions.type(ANGRY).limit(0).summary(total_count).as(fb_post_reactions_angry),` + `reactions.type(HAHA).limit(0).summary(total_count).as(fb_post_reactions_haha)`, token.token, documentId);
59
+ return response.body;
60
+ } catch (error) {
61
+ logger.error(`${documentId} - error recieved - ${error.code}`, error, {
62
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
63
+ [MeltwaterAttributes.COMPANYID]: companyId,
64
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
65
+ });
66
+ return undefined;
67
+ }
68
+ }
69
+ async comment(accessToken, payload) {
70
+ let response;
71
+ const {
72
+ inReplyToId,
73
+ text,
74
+ documentId,
75
+ attachment
76
+ } = payload;
77
+ const isGif = attachment && attachment.mimeType === 'image/gif';
78
+ const loggerChild = logger.child({
79
+ [MeltwaterAttributes.DOCUMENTID]: documentId
80
+ });
81
+ loggerChild.debug(`Starting to call facebook comment api for documentId ${documentId}`, {
82
+ payload: JSON.stringify(payload)
83
+ });
84
+ response = await this.postApi(`${FACEBOOK_URL}/${removePrefix(inReplyToId)}/comments`, accessToken.token, documentId, {
85
+ ...(text && text.length && {
86
+ message: text
87
+ }),
88
+ ...(attachment && !isGif && {
89
+ attachment_url: attachment.link
90
+ }),
91
+ ...(attachment && isGif && {
92
+ attachment_share_url: attachment.link
93
+ })
94
+ });
95
+ loggerChild.info(`Native Facebook API Publish Comment Response for documentId ${documentId}`, {
96
+ ok: response.ok,
97
+ status: response.status,
98
+ [MeltwaterAttributes.DOCUMENTID]: documentId
99
+ });
100
+ return response.body;
101
+ }
102
+ async privateMessage(accessToken, payload) {
103
+ let response;
104
+ const {
105
+ profileId,
106
+ recipientId,
107
+ text,
108
+ documentId,
109
+ attachment
110
+ } = payload;
111
+ const isGif = attachment && attachment.mimeType === 'image/gif';
112
+ const loggerChild = logger.child({
113
+ [MeltwaterAttributes.DOCUMENTID]: documentId
114
+ });
115
+ loggerChild.debug(`Starting to call facebook messages api for documentId ${documentId}`, {
116
+ payload: JSON.stringify(payload)
117
+ });
118
+ response = await this.postApi(`${FACEBOOK_URL}/me/messages`, accessToken.token, documentId, {
119
+ recipient: {
120
+ id: removePrefix(profileId || recipientId)
121
+ },
122
+ message: {
123
+ text: text,
124
+ ...(attachment && {
125
+ attachment: {
126
+ type: isGif ? 'video' : attachment.mimeType.split('/')[0],
127
+ payload: {
128
+ url: attachment.link,
129
+ is_reusable: true
130
+ }
131
+ }
132
+ })
133
+ },
134
+ tag: 'HUMAN_AGENT'
135
+ });
136
+ loggerChild.info(`Native Facebook API Publish Private Message Response for documentId ${documentId}`, {
137
+ status: response.status,
138
+ ok: response.ok
139
+ });
140
+ return response.body;
141
+ }
142
+ async getApi(apiUrl, accessToken, documentId, payload) {
143
+ let queryParams = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
144
+ const loggerChild = logger.child({
145
+ [MeltwaterAttributes.DOCUMENTID]: documentId
146
+ });
147
+ let response = {};
148
+ try {
149
+ response = await superagent.get(apiUrl).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
150
+ access_token: accessToken,
151
+ ...queryParams
152
+ }).send(payload);
153
+ } catch (err) {
154
+ let errorText = '';
155
+ if (err && err.response && err.response.body && err.response.body.error) {
156
+ errorText = `Failed to call facebook api for documentId ${documentId}: ${err.response.body.error.message}`;
157
+ loggerChild.error(errorText);
158
+ } else {
159
+ errorText = `Failed to call facebook api for documentId ${documentId}`;
160
+ loggerChild.error(errorText, err);
161
+ }
162
+ throw new Error(errorText);
163
+ }
164
+ if (response.status !== 200) {
165
+ loggerChild.error(`Failed to call facebook api for documentId ${documentId}`, {
166
+ response: JSON.stringify(response.body)
167
+ });
168
+ let error = new Error(`Failed to call facebook api for documentId ${documentId}`);
169
+ error.code = response.status;
170
+ throw error;
171
+ }
172
+ return response;
173
+ }
174
+ async postApi(apiUrl, accessToken, documentId, payload) {
175
+ let response = {};
176
+ const loggerChild = logger.child({
177
+ [MeltwaterAttributes.DOCUMENTID]: documentId
178
+ });
179
+ try {
180
+ response = await superagent.post(apiUrl).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
181
+ access_token: accessToken
182
+ }).send(payload);
183
+ } catch (err) {
184
+ let errorText = '';
185
+ if (err && err.response && err.response.body && err.response.body.error) {
186
+ errorText = `Failed to call facebook api for documentId ${documentId}: ${err.response.body.error.message}`;
187
+ loggerChild.error(errorText);
188
+ } else {
189
+ errorText = `Failed to call facebook api for documentId ${documentId}`;
190
+ loggerChild.error(errorText, err);
191
+ }
192
+ throw new Error(errorText);
193
+ }
194
+ if (response.status !== 200) {
195
+ loggerChild.error(`Failed to call facebook api for documentId ${documentId}`, {
196
+ response: JSON.stringify(response.body)
197
+ });
198
+ let error = new Error(`Failed to call facebook api for documentId ${documentId}`);
199
+ error.code = response.status;
200
+ throw error;
201
+ }
202
+ return response;
203
+ }
204
+ async deleteApi(apiUrl, accessToken, documentId, payload) {
205
+ const loggerChild = logger.child({
206
+ [MeltwaterAttributes.DOCUMENTID]: documentId
207
+ });
208
+ let response = {};
209
+ try {
210
+ response = await superagent.delete(apiUrl).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
211
+ access_token: accessToken
212
+ }).send(payload);
213
+ } catch (err) {
214
+ let errorText = '';
215
+ if (err && err.response && err.response.body && err.response.body.error) {
216
+ errorText = `Failed to call facebook api for documentId ${documentId}: ${err.response.body.error.message}`;
217
+ loggerChild.error(errorText);
218
+ } else {
219
+ errorText = `Failed to call facebook api for documentId ${documentId}`;
220
+ loggerChild.error(errorText, err);
221
+ }
222
+ throw new Error(errorText);
223
+ }
224
+ if (response.status !== 200) {
225
+ loggerChild.error(`Failed to call facebook api for documentId ${documentId}`, {
226
+ response: JSON.stringify(response.body)
227
+ });
228
+ let error = new Error(`Failed to call facebook api for documentId ${documentId}`);
229
+ error.code = response.status;
230
+ throw error;
231
+ }
232
+ return response;
233
+ }
234
+ async publish(document) {
235
+ const {
236
+ documentId,
237
+ body: {
238
+ content: {
239
+ text
240
+ }
241
+ },
242
+ attachments: [attachment] = [],
243
+ metaData: {
244
+ discussionType,
245
+ inReplyTo: {
246
+ id: inReplyToId,
247
+ recipientId,
248
+ profileId
249
+ }
250
+ },
251
+ systemData: {
252
+ connectionsCredential: credentialId,
253
+ policies: {
254
+ storage: {
255
+ privateTo: companyId
256
+ } = {}
257
+ } = {}
258
+ } = {}
259
+ } = document;
260
+ const loggerChild = logger.child({
261
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
262
+ [MeltwaterAttributes.COMPANYID]: companyId,
263
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
264
+ });
265
+ let updatedDocument;
266
+ let apiResponse;
267
+ try {
268
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
269
+ loggerChild.debug(`finished fetching token for Facebook for ${documentId} on company ${companyId}`);
270
+ let payload;
271
+ switch (discussionType) {
272
+ case 'qt':
273
+ case 're':
274
+ payload = {
275
+ documentId,
276
+ companyId,
277
+ credentialId,
278
+ text,
279
+ inReplyToId,
280
+ attachment
281
+ };
282
+ apiResponse = await this.comment(token, payload);
283
+ break;
284
+ case 'dm':
285
+ payload = {
286
+ documentId,
287
+ companyId,
288
+ credentialId,
289
+ text,
290
+ recipientId,
291
+ profileId,
292
+ attachment
293
+ };
294
+ apiResponse = await this.privateMessage(token, payload);
295
+ break;
296
+ default:
297
+ throw new Error('Unsupported discussion type');
298
+ }
299
+ if (apiResponse) {
300
+ let findQuery = {
301
+ documentId
302
+ };
303
+ findQuery['systemData.policies.storage.privateTo'] = companyId;
304
+ let updateObj = {};
305
+ updateObj['systemData.status'] = DOCUMENT_STATUS.SUCCESS;
306
+ updateObj['metaData.externalId'] = apiResponse.id || apiResponse.message_id;
307
+ updateObj.documentId = Buffer.from(`${updateObj['metaData.externalId']}`).toString('base64');
308
+ updatedDocument = await messagesRepository.updateOne(findQuery, updateObj);
309
+ } else {
310
+ throw new Error('Invalid response from Facebook publish endpoints');
311
+ }
312
+ } catch (exception) {
313
+ loggerChild.error(`${documentId} - exception details`, exception);
314
+ let findQuery = {
315
+ documentId
316
+ };
317
+ findQuery['systemData.policies.storage.privateTo'] = companyId;
318
+ let updateQuery = {};
319
+ updateQuery['systemData.status'] = DOCUMENT_STATUS.FAILED;
320
+ updateQuery['systemData.error'] = exception && exception.response && exception.response.error ? exception.response.error : exception;
321
+ updatedDocument = await messagesRepository.updateOne(findQuery, updateQuery);
322
+ }
323
+ return apiResponse;
324
+ }
325
+ async toggleHide(document) {
326
+ const {
327
+ documentId,
328
+ appData: {
329
+ hidden: hiddenOnNative
330
+ },
331
+ metaData: {
332
+ externalId
333
+ },
334
+ systemData: {
335
+ connectionsCredential: credentialId,
336
+ policies: {
337
+ storage: {
338
+ privateTo: companyId
339
+ } = {}
340
+ } = {}
341
+ } = {},
342
+ version
343
+ } = document;
344
+ let hideResponse;
345
+ const loggerChild = logger.child({
346
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
347
+ [MeltwaterAttributes.COMPANYID]: companyId,
348
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
349
+ });
350
+ try {
351
+ loggerChild.debug(`processing Facebook Version ${version} for documentID ${documentId} on company ${companyId}`);
352
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
353
+ loggerChild.debug(`finished fetching token for facebook for ${documentId} on company ${companyId} `);
354
+ if (hiddenOnNative) {
355
+ hideResponse = await this.hide(token, {
356
+ externalId,
357
+ documentId
358
+ });
359
+ } else {
360
+ hideResponse = await this.unhide(token, {
361
+ externalId,
362
+ documentId
363
+ });
364
+ }
365
+ loggerChild.debug(`finished hiding in facebook for ${documentId} on company ${companyId} `, {
366
+ hideResponse: JSON.stringify(hideResponse)
367
+ });
368
+ return hideResponse;
369
+ } catch (error) {
370
+ loggerChild.error(`${documentId} - error recieved - ${error.code}`, error);
371
+ }
372
+ }
373
+ async toggleBan(document, banStatus) {
374
+ let {
375
+ documentId,
376
+ metaData: {
377
+ source: {
378
+ id: sourceId
379
+ },
380
+ authors: authors
381
+ },
382
+ systemData: {
383
+ connectionsCredential: credentialId,
384
+ policies: {
385
+ storage: {
386
+ privateTo: companyId
387
+ } = {}
388
+ } = {}
389
+ } = {},
390
+ version
391
+ } = document;
392
+ const loggerChild = logger.child({
393
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
394
+ [MeltwaterAttributes.COMPANYID]: companyId,
395
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
396
+ });
397
+ let banResponse;
398
+ let authorId = authors[0].authorInfo.externalId;
399
+ try {
400
+ loggerChild.debug(`processing Facebook Version ${version} for profileId ${authorId} on company ${companyId}`);
401
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
402
+ loggerChild.debug(`finished fetching token for facebook for ${authorId} on company ${companyId} `);
403
+ if (!banStatus) {
404
+ banResponse = await this.unban(token, {
405
+ sourceId,
406
+ authorId
407
+ });
408
+ } else if (banStatus) {
409
+ banResponse = await this.ban(token, {
410
+ sourceId,
411
+ authorId
412
+ });
413
+ }
414
+ loggerChild.debug(`finished banning in facebook for ${authorId} on company ${companyId} `, {
415
+ banResponse: JSON.stringify(banResponse)
416
+ });
417
+ } catch (error) {
418
+ loggerChild.error(`${authorId} - error recieved - ${error.code}`, error);
419
+ }
420
+ }
421
+ async toggleLike(document) {
422
+ const {
423
+ documentId,
424
+ enrichments: {
425
+ socialScores: {
426
+ fb_liked_by_user: likedByUser
427
+ }
428
+ },
429
+ metaData: {
430
+ externalId
431
+ },
432
+ systemData: {
433
+ connectionsCredential: credentialId,
434
+ policies: {
435
+ storage: {
436
+ privateTo: companyId
437
+ } = {}
438
+ } = {}
439
+ } = {},
440
+ version
441
+ } = document;
442
+ const loggerChild = logger.child({
443
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
444
+ [MeltwaterAttributes.COMPANYID]: companyId,
445
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
446
+ });
447
+ try {
448
+ loggerChild.debug(`processing Facebook Version ${version} for documentID ${documentId}`);
449
+ loggerChild.debug(`starting to fetch tokens for facebook for ${documentId} on company ${companyId} `);
450
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
451
+ loggerChild.debug(`finished fetching token for facebook for ${documentId} on company ${companyId} `);
452
+ let likeResponse = await (likedByUser ? this.like(token, {
453
+ externalId,
454
+ documentId
455
+ }) : this.unlike(token, {
456
+ externalId,
457
+ documentId
458
+ }));
459
+ loggerChild.debug(`finished liking in facebook for ${documentId} on company ${companyId} `, {
460
+ likeResponse: JSON.stringify(likeResponse)
461
+ });
462
+ } catch (error) {
463
+ loggerChild.error(`${document} - error recieved - ${error.code}`, error);
464
+ throw error;
465
+ }
466
+ }
467
+ async like(accessToken, command) {
468
+ let response;
469
+ const {
470
+ externalId,
471
+ documentId
472
+ } = command;
473
+ const loggerChild = logger.child({
474
+ [MeltwaterAttributes.DOCUMENTID]: documentId
475
+ });
476
+ loggerChild.debug(`Starting to call facebook like api for documentId ${documentId}`, {
477
+ command: JSON.stringify(command)
478
+ });
479
+ response = await this.postApi(`${FACEBOOK_URL}/${removePrefix(externalId)}/likes`, accessToken.token, documentId);
480
+ loggerChild.info(`Native Facebook API Like Response for documentId ${documentId}`, {
481
+ status: response.status,
482
+ ok: response.ok
483
+ });
484
+ return response.body;
485
+ }
486
+ async unlike(accessToken, command) {
487
+ let response;
488
+ const {
489
+ externalId,
490
+ documentId
491
+ } = command;
492
+ const loggerChild = logger.child({
493
+ [MeltwaterAttributes.DOCUMENTID]: documentId
494
+ });
495
+ loggerChild.debug(`Starting to call facebook unlike api for documentId ${documentId}`, {
496
+ command: JSON.stringify(command)
497
+ });
498
+ response = await this.deleteApi(`${FACEBOOK_URL}/${removePrefix(externalId)}/likes`, accessToken.token, documentId);
499
+ loggerChild.info(`Native Facebook API Unlike Response for documentId ${documentId}`, {
500
+ status: response.status,
501
+ ok: response.ok
502
+ });
503
+ return response.body;
504
+ }
505
+ async hide(accessToken, command) {
506
+ let response;
507
+ const {
508
+ externalId,
509
+ documentId
510
+ } = command;
511
+ const loggerChild = logger.child({
512
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
513
+ [MeltwaterAttributes.DOCUMENTEXTERNALID]: externalId
514
+ });
515
+ loggerChild.debug(`Starting to call facebook hide api for documentId ${documentId}`, {
516
+ command: JSON.stringify(command)
517
+ });
518
+ response = await this.postApi(`${FACEBOOK_URL}/${removePrefix(externalId)}`, accessToken.token, documentId, {
519
+ is_hidden: true
520
+ });
521
+ loggerChild.info(`Native Facebook API Hide Response for documentId ${documentId}`, {
522
+ status: response.status,
523
+ ok: response.ok
524
+ });
525
+ return response.body;
526
+ }
527
+ async unhide(accessToken, command) {
528
+ let response;
529
+ const {
530
+ externalId,
531
+ documentId
532
+ } = command;
533
+ const loggerChild = logger.child({
534
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
535
+ [MeltwaterAttributes.DOCUMENTEXTERNALID]: externalId
536
+ });
537
+ loggerChild.debug(`Starting to call facebook unhide api for documentId ${documentId}`, {
538
+ command: JSON.stringify(command)
539
+ });
540
+ response = await this.postApi(`${FACEBOOK_URL}/${removePrefix(externalId)}`, accessToken.token, documentId, {
541
+ is_hidden: false
542
+ });
543
+ loggerChild.info(`Native Facebook API Unhide Response for documentId ${documentId}`, {
544
+ status: response.status,
545
+ ok: response.ok
546
+ });
547
+ return response.body;
548
+ }
549
+ async isUserBanned(_ref) {
550
+ let {
551
+ credentialId,
552
+ companyId,
553
+ userId,
554
+ pageId
555
+ } = _ref;
556
+ const token = await this.credentialsAPI.getToken(credentialId, companyId);
557
+ const response = await this.getApi(`${FACEBOOK_URL}/${pageId}/blocked`, token.token, `${companyId}-${credentialId}-${userId}-${pageId}`, undefined,
558
+ // payload
559
+ {
560
+ user: removePrefix(userId)
561
+ });
562
+ if (response && response.body && response.body.data) {
563
+ const userNoPrefix = removePrefix(userId);
564
+ const user = response.body.data.find(user => {
565
+ if (user.id == userNoPrefix) {
566
+ return user;
567
+ }
568
+ });
569
+ if (user) {
570
+ return true;
571
+ } else {
572
+ return false;
573
+ }
574
+ }
575
+ logger.info(`Native Facebook API is User Banned Response was invalid for userId ${userId} ${credentialId}`, {
576
+ ok: response.ok,
577
+ status: response.status,
578
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
579
+ [MeltwaterAttributes.CREDENTIALID]: credentialId,
580
+ [MeltwaterAttributes.COMPANYID]: companyId,
581
+ [MeltwaterAttributes.USERID]: userId
582
+ });
583
+ return false;
584
+ }
585
+ async ban(accessToken, command) {
586
+ let response;
587
+ const {
588
+ sourceId,
589
+ authorId
590
+ } = command;
591
+ logger.debug(`Starting to call facebook ban api for externalAuthorId ${authorId}`, {
592
+ command: JSON.stringify(command)
593
+ });
594
+ response = await this.postApi(`${FACEBOOK_URL}/${removePrefix(sourceId)}/blocked`, accessToken.token, removePrefix(authorId), {
595
+ psid: [removePrefix(authorId)]
596
+ });
597
+ logger.info(`Native Facebook API Hide Response for externalAuthorId ${authorId}`, {
598
+ status: response.status,
599
+ ok: response.ok
600
+ });
601
+ return response.body;
602
+ }
603
+ async unban(accessToken, command) {
604
+ let response;
605
+ const {
606
+ sourceId,
607
+ authorId
608
+ } = command;
609
+ logger.debug(`Starting to call facebook unban api for externalAuthorId ${authorId}`, {
610
+ command: JSON.stringify(command)
611
+ });
612
+ response = await this.deleteApi(`${FACEBOOK_URL}/${removePrefix(sourceId)}/blocked`, accessToken.token, removePrefix(authorId), {
613
+ psid: [removePrefix(authorId)]
614
+ });
615
+ logger.info(`Native Facebook API Unban Response for externalAuthorId ${authorId}`, {
616
+ status: response.status,
617
+ ok: response.ok
618
+ });
619
+ return response.body;
620
+ }
621
+ }
@@ -0,0 +1,23 @@
1
+ import superagent from 'superagent';
2
+ import logger from '../../lib/logger.js';
3
+ import configuration from '../../lib/configuration.js';
4
+ import { MeltwaterAttributes } from '../../lib/logger.helpers.js';
5
+ export class FeatureToggleClient {
6
+ constructor() {
7
+ this.featureToggleUrl = configuration.get('FEATURE_TOGGLE_URL');
8
+ this.featureToggleNames = ['CONNECTIONS-SOCIAL-GOVERNANCE', 'conversations-googlebusiness-display', 'CONVERSATIONS_FACEBOOK_MENTIONS'];
9
+ }
10
+ async get(companyId, jwt) {
11
+ try {
12
+ const result = await superagent.post(`${this.featureToggleUrl}/treatments/${companyId}`).set('Authorization', jwt).send({
13
+ features: this.featureToggleNames,
14
+ attributes: {}
15
+ }).timeout(5000);
16
+ return result.body.treatments;
17
+ } catch (error) {
18
+ logger.error(`Failed requesting Feature Toggle service for feature toggle get `, error, {
19
+ [MeltwaterAttributes.COMPANYID]: companyId
20
+ });
21
+ }
22
+ }
23
+ }