@meltwater/conversations-api-services 1.0.19 → 1.0.20

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 (67) 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/tiktokApi.client.js +441 -0
  19. package/dist/cjs/data-access/index.js +129 -0
  20. package/dist/cjs/errors/engage-error.js +16 -0
  21. package/dist/cjs/errors/http-error.js +23 -0
  22. package/dist/cjs/lib/applicationTags.helpers.js +30 -0
  23. package/dist/cjs/lib/configuration.js +14 -0
  24. package/dist/cjs/lib/document-action-events.js +12 -0
  25. package/dist/cjs/lib/externalId.helpers.js +19 -0
  26. package/dist/cjs/lib/hidden.helpers.js +13 -0
  27. package/dist/cjs/lib/hiddenComment.helper.js +119 -0
  28. package/dist/cjs/lib/logger.helpers.js +68 -0
  29. package/dist/cjs/lib/logger.js +23 -0
  30. package/dist/cjs/lib/message.helpers.js +58 -0
  31. package/dist/cjs/lib/metrics.helper.js +97 -0
  32. package/dist/esm/data-access/http/InstagramVideoClient.js +34 -0
  33. package/dist/esm/data-access/http/WarpZoneApi.client.js +24 -0
  34. package/dist/esm/data-access/http/amazonS3.js +37 -0
  35. package/dist/esm/data-access/http/asset-manager-tvm.client.js +28 -0
  36. package/dist/esm/data-access/http/companiesApi.client.js +30 -0
  37. package/dist/esm/data-access/http/credentialsApi.client.js +92 -0
  38. package/dist/esm/data-access/http/entitlementsApi.client.js +32 -0
  39. package/dist/esm/data-access/http/facebook.native.js +325 -0
  40. package/dist/esm/data-access/http/facebookApi.client.js +621 -0
  41. package/dist/esm/data-access/http/featureToggleApi.client.js +23 -0
  42. package/dist/esm/data-access/http/identityServices.client.js +89 -0
  43. package/dist/esm/data-access/http/instagramApi.client.js +420 -0
  44. package/dist/esm/data-access/http/ir.client.js +234 -0
  45. package/dist/esm/data-access/http/linkedInApi.client.js +481 -0
  46. package/dist/esm/data-access/http/masf.client.js +93 -0
  47. package/dist/esm/data-access/http/tiktokApi.client.js +433 -0
  48. package/dist/esm/data-access/index.js +29 -0
  49. package/dist/esm/errors/engage-error.js +9 -0
  50. package/dist/esm/errors/http-error.js +16 -0
  51. package/dist/esm/lib/applicationTags.helpers.js +22 -0
  52. package/dist/esm/lib/configuration.js +8 -0
  53. package/dist/esm/lib/document-action-events.js +6 -0
  54. package/dist/esm/lib/externalId.helpers.js +12 -0
  55. package/dist/esm/lib/hidden.helpers.js +6 -0
  56. package/dist/esm/lib/hiddenComment.helper.js +112 -0
  57. package/dist/esm/lib/logger.helpers.js +60 -0
  58. package/dist/esm/lib/logger.js +16 -0
  59. package/dist/esm/lib/message.helpers.js +52 -0
  60. package/dist/esm/lib/metrics.helper.js +90 -0
  61. package/package.json +14 -4
  62. package/src/data-access/http/facebook.native.js +542 -0
  63. package/src/data-access/index.js +2 -0
  64. package/src/errors/engage-error.js +11 -0
  65. package/src/errors/http-error.js +19 -0
  66. package/src/lib/logger.helpers.js +15 -0
  67. package/src/lib/message.helpers.js +7 -1
@@ -0,0 +1,433 @@
1
+ import superagent from 'superagent';
2
+ import configuration from '../../lib/configuration.js';
3
+ import logger from '../../lib/logger.js';
4
+ import { removePrefix } from '../../lib/externalId.helpers.js';
5
+ import { CredentialsApiClient } from '../http/credentialsApi.client.js';
6
+ import { MeltwaterAttributes } from '../../lib/logger.helpers.js';
7
+ export class TikTokApiClient {
8
+ constructor() {
9
+ this.tiktokURL = configuration.get('TIKTOK_API_URL');
10
+ this.credentialsAPI = new CredentialsApiClient();
11
+ }
12
+ async getAuthorization(document) {
13
+ const {
14
+ documentId,
15
+ systemData: {
16
+ connectionsCredential: credentialId,
17
+ policies: {
18
+ storage: {
19
+ privateTo: companyId
20
+ } = {}
21
+ } = {}
22
+ } = {}
23
+ } = document;
24
+ try {
25
+ const credential = await this.credentialsAPI.getToken(credentialId, companyId);
26
+ return `${credential.token}`;
27
+ } catch (error) {
28
+ logger.error(`${documentId} - error getting tiktok token - ${error.code}`, error, {
29
+ [MeltwaterAttributes.DOCUMENTID]: documentId,
30
+ [MeltwaterAttributes.COMPANYID]: companyId,
31
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
32
+ });
33
+ }
34
+ }
35
+ async sendPost(_ref) {
36
+ let {
37
+ paramString = '',
38
+ headers = {},
39
+ document,
40
+ postData = undefined
41
+ } = _ref;
42
+ let response = {};
43
+ try {
44
+ response = await superagent.post(this.tiktokURL + paramString).set('Accept', 'application/json').set('Content-Type', 'application/json').set('Access-Token', await this.getAuthorization(document)).send(postData);
45
+ } catch (err) {
46
+ let errorText = '';
47
+ if (err && err.response && err.response.body && err.response.body.error) {
48
+ errorText = `Failed to call tiktok api for paramString ${paramString}: ${err.response.body.error.message}`;
49
+ logger.error(errorText);
50
+ } else {
51
+ errorText = `Failed to call tiktok api for paramString ${paramString}`;
52
+ logger.error(errorText, err);
53
+ }
54
+ throw new Error(errorText);
55
+ }
56
+ return response;
57
+ }
58
+
59
+ // assumes batch calls are using the same credential
60
+ async sendRequest(_ref2) {
61
+ let {
62
+ paramString = '',
63
+ headers = {},
64
+ document
65
+ } = _ref2;
66
+ let response = {};
67
+ try {
68
+ response = await superagent.get(this.tiktokURL + paramString).set('Accept', 'application/json').set('Content-Type', 'application/json').set('Access-Token', await this.getAuthorization(document)).send();
69
+ } catch (err) {
70
+ let errorText = '';
71
+ if (err && err.response && err.response.body && err.response.body.error) {
72
+ errorText = `Failed to call tiktok api for paramString ${paramString}: ${err.response.body.error.message}`;
73
+ logger.error(errorText);
74
+ } else {
75
+ errorText = `Failed to call tiktok api for paramString ${paramString}`;
76
+ logger.error(errorText, err);
77
+ }
78
+ throw new Error(errorText);
79
+ }
80
+ if (response.status !== 200) {
81
+ logger.error(`Failed to call tiktok api for documentId ${document.documentId}`, response.body, {
82
+ [MeltwaterAttributes.DOCUMENTID]: document.documentId
83
+ });
84
+ let error = new Error(`Failed to call tiktok api for documentId ${document.documentId}`);
85
+ error.code = response.status;
86
+ throw error;
87
+ }
88
+ return response.body;
89
+ }
90
+ async getChannelInfoForDocuments(documents) {
91
+ const channelInfo = await this.getStatsForDocuments(documents, 'metaData.authors.0.authorInfo.externalId', {
92
+ og: ['video/list/']
93
+ });
94
+ return channelInfo;
95
+ }
96
+ async getStatsForDocuments(documents) {
97
+ let externalIdFrom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'metaData.externalId';
98
+ let paramsByType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
99
+ og: ['video/list/']
100
+ };
101
+ // for batching separate og and comment/reply requests per credential
102
+ const documentsByTypeAndCredentials = documents.reduce((retObj, document, index) => {
103
+ const paramArray = paramsByType[document.metaData.discussionType];
104
+ if (paramArray) {
105
+ paramArray.forEach(paramString => {
106
+ let discussionTypeBucket = retObj[`${paramString}${document.systemData.connectionsCredential}`];
107
+ if (!discussionTypeBucket) {
108
+ discussionTypeBucket = {
109
+ paramString,
110
+ document,
111
+ externalIds: [],
112
+ externalIdToDocumentIndex: {}
113
+ };
114
+ retObj[`${paramString}${document.systemData.connectionsCredential}`] = discussionTypeBucket;
115
+ }
116
+ const externalIdTrimmed = removePrefix(
117
+ // javascript weirdness to get around '.' notation
118
+ externalIdFrom.split('.').reduce((a, b) => a[b], document));
119
+ discussionTypeBucket.externalIds.push(externalIdTrimmed);
120
+ discussionTypeBucket.externalIdToDocumentIndex[externalIdTrimmed] = index;
121
+ });
122
+ }
123
+ return retObj;
124
+ }, {});
125
+ const sortedResults = Array(documents.length).fill();
126
+ await Promise.all(Object.values(documentsByTypeAndCredentials).map(async documentsByTypeAndCredential => {
127
+ if (documentsByTypeAndCredential.externalIds.length) {
128
+ const {
129
+ metaData: {
130
+ inReplyTo: {
131
+ profileId: business_id
132
+ }
133
+ }
134
+ } = documentsByTypeAndCredential.document;
135
+ const trimmedBusinessId = removePrefix(business_id);
136
+ const requestResult = await this.sendRequest({
137
+ paramString: `${documentsByTypeAndCredential.paramString}?business_id=${trimmedBusinessId}&fields=["item_id","create_time","thumbnail_url","share_url","embed_url","caption","video_views","likes","comments","shares"]&filters=${JSON.stringify({
138
+ video_ids: documentsByTypeAndCredential.externalIds
139
+ })}`,
140
+ document: documentsByTypeAndCredential.document
141
+ });
142
+ requestResult.data.videos.forEach(_ref3 => {
143
+ let {
144
+ item_id,
145
+ create_time,
146
+ thumbnail_url,
147
+ share_url,
148
+ embed_url,
149
+ caption,
150
+ video_views,
151
+ likes,
152
+ comments,
153
+ shares,
154
+ ...args
155
+ } = _ref3;
156
+ const documentIndex = documentsByTypeAndCredential.externalIdToDocumentIndex[item_id];
157
+ sortedResults[documentIndex] = {
158
+ ...sortedResults[documentIndex],
159
+ item_id,
160
+ create_time,
161
+ thumbnail_url,
162
+ externalId: documents[documentIndex].metaData.externalId,
163
+ share_url,
164
+ embed_url,
165
+ caption,
166
+ video_views,
167
+ likes,
168
+ comments,
169
+ shares
170
+ };
171
+ });
172
+ }
173
+ }));
174
+ return sortedResults;
175
+ }
176
+ async publish(message, videoId, markMessageAsCompleteDocumentId) {
177
+ const {
178
+ metaData: {
179
+ discussionType
180
+ }
181
+ } = message;
182
+ let publishedMessage;
183
+ switch (discussionType) {
184
+ case 'qt':
185
+ publishedMessage = await this.insertComment(message);
186
+ break;
187
+ case 're':
188
+ publishedMessage = await this.insertReply(videoId, message, markMessageAsCompleteDocumentId);
189
+ break;
190
+ }
191
+ return publishedMessage;
192
+ }
193
+ async insertComment(document) {
194
+ const {
195
+ body: {
196
+ content: {
197
+ text: text
198
+ }
199
+ },
200
+ metaData: {
201
+ source: {
202
+ id: business_id
203
+ },
204
+ inReplyTo: {
205
+ id: video_id
206
+ }
207
+ }
208
+ } = document;
209
+ const {
210
+ body: publishedMessage
211
+ } = (await this.sendPost({
212
+ paramString: 'comment/create/',
213
+ postData: {
214
+ business_id,
215
+ video_id,
216
+ text
217
+ },
218
+ document
219
+ })) || {};
220
+ return publishedMessage;
221
+ }
222
+ async insertReply(videoId, document, markMessageAsCompleteDocumentId) {
223
+ const {
224
+ body: {
225
+ content: {
226
+ text: text
227
+ }
228
+ },
229
+ metaData: {
230
+ inReplyTo: {
231
+ id: comment_id,
232
+ profileId: business_id
233
+ }
234
+ }
235
+ } = document;
236
+ const {
237
+ body: publishedMessage
238
+ } = (await this.sendPost({
239
+ paramString: 'comment/reply/create/',
240
+ postData: {
241
+ business_id: document.metaData.source.id,
242
+ comment_id: markMessageAsCompleteDocumentId || comment_id,
243
+ video_id: removePrefix(videoId),
244
+ text
245
+ },
246
+ document
247
+ })) || {};
248
+ return publishedMessage;
249
+ }
250
+ async toggleLike(document) {
251
+ const {
252
+ enrichments: {
253
+ socialScores: {
254
+ tt_liked_by_user: likedByUser
255
+ }
256
+ }
257
+ } = document;
258
+ try {
259
+ let likeResponse = await (!likedByUser ? this.like(document) : this.unlike(document));
260
+ return likeResponse;
261
+ } catch (error) {
262
+ logger.error(`${document} - error recieved - ${error.code}`, error);
263
+ throw error;
264
+ }
265
+ }
266
+ async toggleHide(document) {
267
+ let parentDoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
268
+ const {
269
+ documentId,
270
+ appData: {
271
+ hidden: hiddenOnNative
272
+ }
273
+ } = document;
274
+ let response;
275
+ try {
276
+ if (hiddenOnNative) {
277
+ response = await this.hide(document, parentDoc);
278
+ } else {
279
+ response = await this.unhide(document, parentDoc);
280
+ }
281
+ logger.info(`Native Tiktok API Hide Response for documentId ${documentId}`, {
282
+ status: response.status,
283
+ ok: response.ok,
284
+ [MeltwaterAttributes.DOCUMENTID]: documentId
285
+ });
286
+ if (response.message === 'OK') {
287
+ return response;
288
+ }
289
+ } catch (error) {
290
+ logger.error(`${documentId} - error recieved - ${error.code}`, error, {
291
+ [MeltwaterAttributes.DOCUMENTID]: documentId
292
+ });
293
+ }
294
+ }
295
+ async like(document) {
296
+ const {
297
+ metaData: {
298
+ externalId: comment_id,
299
+ source: {
300
+ id: sourceId
301
+ }
302
+ }
303
+ } = document;
304
+ const {
305
+ body: publishedMessage
306
+ } = (await this.sendPost({
307
+ paramString: 'comment/like/',
308
+ postData: {
309
+ business_id: removePrefix(sourceId),
310
+ comment_id: removePrefix(comment_id),
311
+ action: 'LIKE'
312
+ },
313
+ document
314
+ })) || {};
315
+ return publishedMessage;
316
+ }
317
+ async unlike(document) {
318
+ const {
319
+ metaData: {
320
+ inReplyTo: {
321
+ id: comment_id
322
+ },
323
+ source: {
324
+ id: sourceId
325
+ }
326
+ }
327
+ } = document;
328
+ const {
329
+ body: publishedMessage
330
+ } = (await this.sendPost({
331
+ paramString: 'comment/like/',
332
+ postData: {
333
+ business_id: removePrefix(sourceId),
334
+ comment_id: removePrefix(comment_id),
335
+ action: 'unlike'
336
+ },
337
+ document
338
+ })) || {};
339
+ return publishedMessage;
340
+ }
341
+ async hide(document) {
342
+ let parentDoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
343
+ const {
344
+ metaData: {
345
+ externalId: comment_id,
346
+ source: {
347
+ id: sourceId
348
+ },
349
+ discussionType
350
+ }
351
+ } = document;
352
+
353
+ //very small chance we get externalid instead of id
354
+ const video_id = discussionType === 're' ? parentDoc?.metaData?.inReplyTo?.id || parentDoc?.metaData?.inReplyTo?.externalId : document?.metaData?.inReplyTo?.id || document?.metaData?.inReplyTo?.externalId;
355
+ const {
356
+ body: publishedMessage
357
+ } = (await this.sendPost({
358
+ paramString: 'comment/hide/',
359
+ postData: {
360
+ business_id: removePrefix(sourceId),
361
+ comment_id: removePrefix(comment_id),
362
+ video_id: removePrefix(video_id),
363
+ action: 'HIDE'
364
+ },
365
+ document
366
+ })) || {};
367
+ return publishedMessage;
368
+ }
369
+ async unhide(document) {
370
+ let parentDoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
371
+ const {
372
+ metaData: {
373
+ externalId: comment_id,
374
+ source: {
375
+ id: sourceId
376
+ },
377
+ discussionType
378
+ }
379
+ } = document;
380
+ const video_id = discussionType === 're' ? parentDoc?.metaData?.inReplyTo?.id : document?.metaData?.inReplyTo?.id;
381
+ const {
382
+ body: publishedMessage
383
+ } = (await this.sendPost({
384
+ paramString: 'comment/hide/',
385
+ postData: {
386
+ business_id: removePrefix(sourceId),
387
+ comment_id: removePrefix(comment_id),
388
+ video_id: removePrefix(video_id),
389
+ action: 'UNHIDE'
390
+ },
391
+ document
392
+ })) || {};
393
+ return publishedMessage;
394
+ }
395
+ async deleteComment(document) {
396
+ const {
397
+ metaData: {
398
+ inReplyTo: {
399
+ id: comment_id,
400
+ profileId: business_id
401
+ }
402
+ }
403
+ } = document;
404
+ const {
405
+ body: publishedMessage
406
+ } = (await this.sendPost({
407
+ paramString: 'comment/delete/',
408
+ postData: {
409
+ business_id,
410
+ comment_id
411
+ },
412
+ document
413
+ })) || {};
414
+ return publishedMessage;
415
+ }
416
+ async getProfile(business_id, document) {
417
+ const fields = '["username", "display_name", "profile_image"]';
418
+ const profile = (await this.sendRequest({
419
+ paramString: `get/?business_id=${business_id}&fields=${fields}`,
420
+ document
421
+ })) || {};
422
+ return profile;
423
+ }
424
+ async getPostData(business_id, video_id, document) {
425
+ const fields = '["item_id", "thumbnail_url", "create_time", "username", "display_name", "profile_image"]';
426
+ const video_ids = `["${video_id}"]`;
427
+ const profile = (await this.sendRequest({
428
+ paramString: `video/list?business_id=${business_id}&fields=${fields}&filters={"video_ids":${video_ids}}`,
429
+ document
430
+ })) || {};
431
+ return profile;
432
+ }
433
+ }
@@ -0,0 +1,29 @@
1
+ import { awsS3Client } from './http/amazonS3.js';
2
+ import { assetManagerTvmRepository } from './http/asset-manager-tvm.client.js';
3
+ import { CompanyApiClient } from './http/companiesApi.client.js';
4
+ import { CredentialsApiClient } from './http/credentialsApi.client.js';
5
+ import { EntitlementsApiClient } from './http/entitlementsApi.client.js';
6
+ import { FacebookApiClient } from './http/facebookApi.client.js';
7
+ import { FeatureToggleClient } from './http/featureToggleApi.client.js';
8
+ import { IdentityServicesClient } from './http/identityServices.client.js';
9
+ import { InstagramApiClient } from './http/instagramApi.client.js';
10
+ import { InstagramVideoClient } from './http/InstagramVideoClient.js';
11
+ import { IRClient } from './http/ir.client.js';
12
+ import { LinkedInApiClient, getOrganization, getProfile } from './http/linkedInApi.client.js';
13
+ import { TikTokApiClient } from './http/tiktokApi.client.js';
14
+ import { MasfClient } from './http/masf.client.js';
15
+ import { WarpZoneApiClient } from './http/WarpZoneApi.client.js';
16
+ import * as messageHelpers from '../lib/message.helpers.js';
17
+ import * as applicationTagFunctions from '../lib/applicationTags.helpers.js';
18
+ import * as hiddenHelpers from '../lib/hidden.helpers.js';
19
+ import * as FacebookNative from './http/facebook.native.js';
20
+ const DocumentHelperFunctions = {
21
+ ...messageHelpers,
22
+ ...applicationTagFunctions,
23
+ ...hiddenHelpers
24
+ };
25
+ const LinkedInHelpers = {
26
+ getOrganization,
27
+ getProfile
28
+ };
29
+ export { FacebookNative, awsS3Client, assetManagerTvmRepository, CompanyApiClient, CredentialsApiClient, EntitlementsApiClient, FacebookApiClient, FeatureToggleClient, IdentityServicesClient, InstagramApiClient, InstagramVideoClient, IRClient, LinkedInApiClient, TikTokApiClient, MasfClient, WarpZoneApiClient, DocumentHelperFunctions, LinkedInHelpers };
@@ -0,0 +1,9 @@
1
+ export class EngageError extends Error {
2
+ code;
3
+ constructor(code, message) {
4
+ super(message);
5
+ Object.setPrototypeOf(this, new.target.prototype);
6
+ this.name = this.constructor.name;
7
+ this.code = code;
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ import { EngageError } from "./engage-error";
2
+ export class EngageHttpError extends EngageError {
3
+ status;
4
+ statusText;
5
+ response;
6
+ headers;
7
+ constructor(status, statusText, response, headers) {
8
+ super(`HTTP ${status}: ${statusText}`, statusText);
9
+ Object.setPrototypeOf(this, new.target.prototype);
10
+ this.name = this.constructor.name;
11
+ this.status = status;
12
+ this.statusText = statusText;
13
+ this.response = response;
14
+ this.headers = headers;
15
+ }
16
+ }
@@ -0,0 +1,22 @@
1
+ export function parseApplicationTags(tags) {
2
+ const parsedTags = {};
3
+ if (!tags) {
4
+ return parsedTags;
5
+ }
6
+ tags.map(tag => {
7
+ const [key, value] = tag.split('=');
8
+ parsedTags[key] = value;
9
+ });
10
+ return parsedTags;
11
+ }
12
+ export function checkApplicationTagsForUserLikes(applicationTags) {
13
+ const appTags = parseApplicationTags(applicationTags);
14
+ if (appTags.userLikes === 'true') {
15
+ return true;
16
+ } else {
17
+ return false;
18
+ }
19
+ }
20
+ export function getCredentialIdFromApplicationTags(applicationTags) {
21
+ return applicationTags.find(appTag => appTag.startsWith('connectionsCredential=') || appTag.startsWith('connectionscredential='))?.substring(22);
22
+ }
@@ -0,0 +1,8 @@
1
+ export default {
2
+ get: varName => {
3
+ const value = process.env[varName];
4
+ if (value === 'true') return true;
5
+ if (value === 'false') return false;
6
+ return value;
7
+ }
8
+ };
@@ -0,0 +1,6 @@
1
+ export default {
2
+ MARK_AS_TODO: 'MARK_AS_TODO',
3
+ MARK_AS_COMPLETE: 'MARK_AS_COMPLETE',
4
+ USER_STARTED_RESPONDING: 'USER_STARTED_RESPONDING',
5
+ USER_STOPPED_RESPONDING: 'USER_STOPPED_RESPONDING'
6
+ };
@@ -0,0 +1,12 @@
1
+ export function removePrefix(document) {
2
+ return document && document.replace(/id\:[a-zA-Z]+\.com:/g, '');
3
+ }
4
+ export function twitterPrefixCheck(socialOriginType, value) {
5
+ let result = value;
6
+ if (socialOriginType === 'twitter') {
7
+ if (!value.includes('id:twitter.com:')) {
8
+ result = 'id:twitter.com:' + value;
9
+ }
10
+ }
11
+ return result;
12
+ }
@@ -0,0 +1,6 @@
1
+ export function socialTypesThatCanBeHidden() {
2
+ return ['instagram', 'facebook', 'tiktok'];
3
+ }
4
+ export function isThisHiddenEligible(document) {
5
+ return socialTypesThatCanBeHidden().includes(document.metaData.source.socialOriginType);
6
+ }
@@ -0,0 +1,112 @@
1
+ import logger from '../lib/logger.js';
2
+ import { IRClient } from '../data-access/http/ir.clien.jst';
3
+ import XRunes from '@meltwater/xrunes';
4
+ import xRunesCore from '@meltwater/xrunes-core';
5
+ import { MeltwaterAttributes } from '../lib/logger.helpers.js';
6
+ class HiddenCommentHelper {
7
+ constructor(_ref) {
8
+ let {
9
+ company,
10
+ user,
11
+ traceId
12
+ } = _ref;
13
+ this.irClient = new IRClient({
14
+ company,
15
+ user,
16
+ traceId
17
+ });
18
+ this.xRunes = new XRunes();
19
+ this.xRunes.registerLibrary(xRunesCore);
20
+ }
21
+ shouldHandle(message) {
22
+ return message.metaData.discussionType === 'qt';
23
+ }
24
+ async hideChildren(message, markHidden) {
25
+ let {
26
+ body: {
27
+ publishDate: {
28
+ date: publishDate
29
+ } = {}
30
+ } = {},
31
+ metaData: {
32
+ externalId,
33
+ source: {
34
+ socialOriginType
35
+ } = {}
36
+ } = {},
37
+ systemData: {
38
+ connectionsCredential: credentialId,
39
+ policies: {
40
+ storage: {
41
+ privateTo: companyId
42
+ } = {}
43
+ } = {}
44
+ } = {}
45
+ } = message;
46
+ let operation;
47
+ let query = {
48
+ type: 'x:match',
49
+ matchQuery: {
50
+ type: 'all',
51
+ allQueries: [{
52
+ type: 'x:dateRange',
53
+ field: 'body.publishDate.date',
54
+ from: publishDate
55
+ }, {
56
+ type: 'term',
57
+ field: 'metaData.inReplyTo.externalId',
58
+ value: externalId
59
+ }]
60
+ }
61
+ };
62
+ if (markHidden) {
63
+ operation = 'addToSet';
64
+ query.notMatchQuery = {
65
+ type: 'term',
66
+ field: 'metaData.applicationTags',
67
+ value: 'parentHidden'
68
+ };
69
+ } else {
70
+ operation = 'removeFromSet';
71
+ query.matchQuery.allQueries.push({
72
+ type: 'term',
73
+ field: 'metaData.applicationTags',
74
+ value: 'parentHidden'
75
+ });
76
+ }
77
+ let runes = {
78
+ query,
79
+ transformers: [{
80
+ type: 'idml',
81
+ script: `action = "update" target = "revision" revisionGroup = "${companyId}" documentId = id operations = [{"operation": "${operation}", "value": ["parentHidden"], "fieldPath": "metaData.applicationTags"}]`
82
+ }],
83
+ overlayGroups: [companyId],
84
+ fields: ['id'],
85
+ outputConfiguration: {
86
+ type: 's3',
87
+ region: 'eu-west-1',
88
+ roleArn: process.env.EXPORT_API_ROLE_ARN,
89
+ externalId: process.env.EXPORT_API_EXTERNAL_ID,
90
+ s3BucketName: process.env.EXPORT_API_S3_BUCKET,
91
+ s3KeyPrefix: process.env.EXPORT_API_S3_PREFIX,
92
+ // the property is optional, the trailing / isn't
93
+ batchSize: 1000 // the property is optional, must be >= 100 and <= 20000. Default is 20000
94
+ },
95
+ metaData: {
96
+ companyId
97
+ }
98
+ };
99
+ runes.query = await this.xRunes.render(runes.query);
100
+ logger.debug(`export api query: ${JSON.stringify(runes.query)}`, {
101
+ [MeltwaterAttributes.COMPANYID]: companyId,
102
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
103
+ });
104
+ let results = await this.irClient.export(runes);
105
+ logger.debug(`export api result: ${JSON.stringify(results)}`, {
106
+ [MeltwaterAttributes.COMPANYID]: companyId,
107
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
108
+ });
109
+ return results;
110
+ }
111
+ }
112
+ export default HiddenCommentHelper;