@meltwater/conversations-api-services 1.0.18 → 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 (68) 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/http/masf.client.js +5 -0
  64. package/src/data-access/index.js +2 -0
  65. package/src/errors/engage-error.js +11 -0
  66. package/src/errors/http-error.js +19 -0
  67. package/src/lib/logger.helpers.js +15 -0
  68. package/src/lib/message.helpers.js +7 -1
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isThisHiddenEligible = isThisHiddenEligible;
7
+ exports.socialTypesThatCanBeHidden = socialTypesThatCanBeHidden;
8
+ function socialTypesThatCanBeHidden() {
9
+ return ['instagram', 'facebook', 'tiktok'];
10
+ }
11
+ function isThisHiddenEligible(document) {
12
+ return socialTypesThatCanBeHidden().includes(document.metaData.source.socialOriginType);
13
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _logger = _interopRequireDefault(require("../lib/logger.js"));
8
+ var _irClien = require("../data-access/http/ir.clien.jst");
9
+ var _xrunes = _interopRequireDefault(require("@meltwater/xrunes"));
10
+ var _xrunesCore = _interopRequireDefault(require("@meltwater/xrunes-core"));
11
+ var _loggerHelpers = require("../lib/logger.helpers.js");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ class HiddenCommentHelper {
14
+ constructor(_ref) {
15
+ let {
16
+ company,
17
+ user,
18
+ traceId
19
+ } = _ref;
20
+ this.irClient = new _irClien.IRClient({
21
+ company,
22
+ user,
23
+ traceId
24
+ });
25
+ this.xRunes = new _xrunes.default();
26
+ this.xRunes.registerLibrary(_xrunesCore.default);
27
+ }
28
+ shouldHandle(message) {
29
+ return message.metaData.discussionType === 'qt';
30
+ }
31
+ async hideChildren(message, markHidden) {
32
+ let {
33
+ body: {
34
+ publishDate: {
35
+ date: publishDate
36
+ } = {}
37
+ } = {},
38
+ metaData: {
39
+ externalId,
40
+ source: {
41
+ socialOriginType
42
+ } = {}
43
+ } = {},
44
+ systemData: {
45
+ connectionsCredential: credentialId,
46
+ policies: {
47
+ storage: {
48
+ privateTo: companyId
49
+ } = {}
50
+ } = {}
51
+ } = {}
52
+ } = message;
53
+ let operation;
54
+ let query = {
55
+ type: 'x:match',
56
+ matchQuery: {
57
+ type: 'all',
58
+ allQueries: [{
59
+ type: 'x:dateRange',
60
+ field: 'body.publishDate.date',
61
+ from: publishDate
62
+ }, {
63
+ type: 'term',
64
+ field: 'metaData.inReplyTo.externalId',
65
+ value: externalId
66
+ }]
67
+ }
68
+ };
69
+ if (markHidden) {
70
+ operation = 'addToSet';
71
+ query.notMatchQuery = {
72
+ type: 'term',
73
+ field: 'metaData.applicationTags',
74
+ value: 'parentHidden'
75
+ };
76
+ } else {
77
+ operation = 'removeFromSet';
78
+ query.matchQuery.allQueries.push({
79
+ type: 'term',
80
+ field: 'metaData.applicationTags',
81
+ value: 'parentHidden'
82
+ });
83
+ }
84
+ let runes = {
85
+ query,
86
+ transformers: [{
87
+ type: 'idml',
88
+ script: `action = "update" target = "revision" revisionGroup = "${companyId}" documentId = id operations = [{"operation": "${operation}", "value": ["parentHidden"], "fieldPath": "metaData.applicationTags"}]`
89
+ }],
90
+ overlayGroups: [companyId],
91
+ fields: ['id'],
92
+ outputConfiguration: {
93
+ type: 's3',
94
+ region: 'eu-west-1',
95
+ roleArn: process.env.EXPORT_API_ROLE_ARN,
96
+ externalId: process.env.EXPORT_API_EXTERNAL_ID,
97
+ s3BucketName: process.env.EXPORT_API_S3_BUCKET,
98
+ s3KeyPrefix: process.env.EXPORT_API_S3_PREFIX,
99
+ // the property is optional, the trailing / isn't
100
+ batchSize: 1000 // the property is optional, must be >= 100 and <= 20000. Default is 20000
101
+ },
102
+ metaData: {
103
+ companyId
104
+ }
105
+ };
106
+ runes.query = await this.xRunes.render(runes.query);
107
+ _logger.default.debug(`export api query: ${JSON.stringify(runes.query)}`, {
108
+ [_loggerHelpers.MeltwaterAttributes.COMPANYID]: companyId,
109
+ [_loggerHelpers.MeltwaterAttributes.CREDENTIALID]: credentialId
110
+ });
111
+ let results = await this.irClient.export(runes);
112
+ _logger.default.debug(`export api result: ${JSON.stringify(results)}`, {
113
+ [_loggerHelpers.MeltwaterAttributes.COMPANYID]: companyId,
114
+ [_loggerHelpers.MeltwaterAttributes.CREDENTIALID]: credentialId
115
+ });
116
+ return results;
117
+ }
118
+ }
119
+ var _default = exports.default = HiddenCommentHelper;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MeltwaterAttributes = void 0;
7
+ exports.loggerDebug = loggerDebug;
8
+ exports.loggerError = loggerError;
9
+ exports.loggerInfo = loggerInfo;
10
+ const MeltwaterAttributes = exports.MeltwaterAttributes = {
11
+ COMPANYID: 'meltwater.company.id',
12
+ // Unique identifier of a company as it applies to meltwater search
13
+ DOCUMENTID: 'meltwater.document.id',
14
+ // Unique identifier of a document indexed into search
15
+ DOCUMENTLANG: 'meltwater.document.lang',
16
+ // Two-letter country code (lower-case) of the original document
17
+ DOCUMENTEXTERNALID: 'meltwater.document.external_id',
18
+ // The external ID of the document
19
+ REQUESTFORMAT: 'meltwater.document.request_format',
20
+ // The document format requested (“gyda”/”quiddity”)
21
+ DOCUMENTIDS: 'meltwater.document_ids',
22
+ // A list of document Ids
23
+ SEARCHIDS: 'meltwater.search_ids',
24
+ // List of IDs of saved searches.
25
+ AUTHORLISTIDS: 'meltwater.authorlist_ids',
26
+ // List of IDs of author lists.
27
+ TAGNAMES: 'meltwater.tag_names',
28
+ // List of tag names
29
+ SEARCHID: 'meltwater.search.id',
30
+ // ID for a saved search
31
+ CREDENTIALID: 'meltwater.social.credential_id',
32
+ // Identifier for Owned and Paid Social Connections.
33
+ CREDENTIALIDS: 'meltwater.social.credential_ids',
34
+ // List of Credential IDs
35
+ SOCIALEXTERNALID: 'meltwater.social.external_id',
36
+ // External ID for Owned and Paid Social Connections.
37
+ ASSETID: 'meltwater.asset.id',
38
+ // Asset ID in the asset library
39
+ ASSETIDS: 'meltwater.asset.ids',
40
+ // List of Asset IDs
41
+ WORKSPACEID: 'meltwater.workspace.id',
42
+ // Workspace ID
43
+ PRODUCTTYPE: 'meltwater.product_type',
44
+ // The name of the product for the search request
45
+ CLIENTNAME: 'meltwater.client_name',
46
+ // The “client_name” identifier used for API calls
47
+ ORIGINALCLIENTNAME: 'meltwater.original_client_name',
48
+ // The originating “client_name” identifier used for API calls
49
+ AUTHKEYID: 'meltwater.auth.kid',
50
+ // The JWT Key ID for the request.
51
+ AUTHEXP: 'meltwater.auth.exp',
52
+ // The expiration of the auth credentials.
53
+ AUTHPERMISSIONS: 'meltwater.auth.permissions',
54
+ // List of auth permermissions.
55
+ USERID: 'user.id' // ID of the user
56
+ };
57
+ function loggerDebug(logger, message) {
58
+ let meta = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
59
+ if (logger) logger.debug(message, meta);
60
+ }
61
+ function loggerInfo(logger, message) {
62
+ let meta = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
63
+ if (logger) logger.info(message, meta);
64
+ }
65
+ function loggerError(logger, message) {
66
+ let meta = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
67
+ if (logger) logger.error(message, meta);
68
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _winston = _interopRequireDefault(require("winston"));
8
+ var _ecsWinstonFormat = require("@elastic/ecs-winston-format");
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ const format = (0, _ecsWinstonFormat.ecsFormat)({
11
+ serviceName: process.env.NODE_ENV ? `conversations-api-services-${process.env.NODE_ENV}` : 'conversations-api-services',
12
+ serviceVersion: process.env.npm_package_version,
13
+ serviceEnvironment: process.env.NODE_ENV
14
+ });
15
+ const logger = _winston.default.createLogger({
16
+ level: process.env.LOG_LEVEL || 'info',
17
+ format,
18
+ defaultMeta: {},
19
+ transports: [new _winston.default.transports.Console({
20
+ format
21
+ })]
22
+ });
23
+ var _default = exports.default = logger;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isMention = isMention;
7
+ function isMention(_ref, credential) {
8
+ let {
9
+ appData: {
10
+ isMention = false
11
+ } = {},
12
+ body: {
13
+ mentions = []
14
+ } = {},
15
+ metaData: {
16
+ authors: [{
17
+ authorInfo: {
18
+ externalId: authorExternalId,
19
+ handle: authorHandle
20
+ } = {}
21
+ } = {}] = [{}],
22
+ inReplyTo: {
23
+ author: {
24
+ externalId: inReplyToExternalId,
25
+ handle: inReplyToHandle
26
+ } = {}
27
+ } = {},
28
+ discussionType = '',
29
+ source: {
30
+ socialOriginType
31
+ } = {}
32
+ } = {},
33
+ providerSpecific
34
+ } = _ref;
35
+ if (socialOriginType == 'twitter' && discussionType != 'og') {
36
+ return false;
37
+ }
38
+ // if inReplyToExternalId is the same as the credential's social_account_id, then it's not a mention
39
+ if (inReplyToExternalId && credential.social_account_id && inReplyToExternalId === credential.social_account_id || inReplyToHandle === credential.username) {
40
+ return false;
41
+ }
42
+ if (authorExternalId && credential.social_account_id && authorExternalId === credential.social_account_id || authorHandle?.length && (authorHandle.toLowerCase() === credential.username?.toLowerCase || authorHandle.toLowerCase() === credential.handle?.toLowerCase())) {
43
+ return false;
44
+ }
45
+ let retIsMention = (['og', 're', 'qt'].includes(discussionType) || discussionType === 'dm' && socialOriginType === 'instagram') && (mentions?.length && mentions.some(mention => mention.toLowerCase() === credential.pageName?.toLowerCase() || mention.toLowerCase() === credential.target_page_name?.toLowerCase() || mention.toLowerCase() === credential.userName?.toLowerCase() || mention.toLowerCase() === credential.username?.toLowerCase()) || isMention && socialOriginType === 'facebook');
46
+ if (providerSpecific) {
47
+ let hasMention = providerSpecific.some(_ref2 => {
48
+ let {
49
+ facebookPostType
50
+ } = _ref2;
51
+ return facebookPostType === 'mention';
52
+ });
53
+ if (hasMention) {
54
+ retIsMention = true;
55
+ }
56
+ }
57
+ return retIsMention;
58
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.metricN = exports.Metrics = void 0;
7
+ var _promClient = _interopRequireDefault(require("prom-client"));
8
+ var _logger = _interopRequireDefault(require("./logger.js"));
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ const podMetricsByName = new Map();
11
+ const metricNames = ['irGetByDocumentId', 'irRatelimited', 'irSearch'];
12
+
13
+ // todo: make this a dynamic process
14
+ const irGetByDocumentIdHistogram = new _promClient.default.Histogram({
15
+ name: 'irGetByDocumentId_Avg_Reponse_Time',
16
+ help: 'metric_help',
17
+ buckets: _promClient.default.linearBuckets(0, 200, 40)
18
+ });
19
+ const irGetByDocumentIdCountHistogram = new _promClient.default.Histogram({
20
+ name: 'irGetByDocumentId_Count',
21
+ help: 'metric_help',
22
+ buckets: _promClient.default.linearBuckets(0, 1, 40)
23
+ });
24
+ metricNames.forEach(metricName => {
25
+ podMetricsByName.set(metricName, new _promClient.default.Counter({
26
+ name: metricName,
27
+ help: `${metricName}_help`
28
+ }));
29
+ });
30
+ class Metrics {
31
+ constructor() {
32
+ this.requestMetricsByName = new Map();
33
+ metricNames.forEach(metricName => {
34
+ this.requestMetricsByName.set(metricName, []);
35
+ });
36
+ this.getMetrics = metricName => {
37
+ return {
38
+ podMetrics: podMetricsByName.get(metricName),
39
+ requestMetrics: this.requestMetricsByName.get(metricName)
40
+ };
41
+ };
42
+ }
43
+ count(metricName) {
44
+ const {
45
+ podMetrics,
46
+ requestMetrics
47
+ } = this.getMetrics(metricName);
48
+ if (podMetrics) {
49
+ podMetrics.inc();
50
+ } else {
51
+ _logger.default.error(`No pod level metric exists for ${metricName}`);
52
+ }
53
+ const metricObject = {
54
+ type: 'count',
55
+ timestamp: Date.now()
56
+ };
57
+ if (requestMetrics) {
58
+ requestMetrics.push(metricObject);
59
+ }
60
+ return metricObject;
61
+ }
62
+ finishOperation(metricName, metricObject) {
63
+ const {
64
+ requestMetrics
65
+ } = this.getMetrics(metricName);
66
+ if (requestMetrics) {
67
+ const matchingMetric = requestMetrics.find(requestMetricExiting => requestMetricExiting.timestamp === metricObject.timestamp);
68
+ matchingMetric.duration = Date.now() - matchingMetric.timestamp;
69
+ }
70
+ }
71
+ async somethingCompleted() {
72
+ let name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'IR.getByDocumentId';
73
+ let start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
74
+ } // duration math
75
+ async finishRequest() {
76
+ const {
77
+ requestMetrics
78
+ } = this.getMetrics('irGetByDocumentId');
79
+ let arrHasDuration = requestMetrics.filter(metric => metric.duration);
80
+ if (arrHasDuration.length) {
81
+ let avgDuration = arrHasDuration.reduce((avg, metric) => avg + metric.duration, 0) / arrHasDuration.length;
82
+ irGetByDocumentIdHistogram.observe(avgDuration);
83
+ }
84
+ if (requestMetrics.length > 0) {
85
+ irGetByDocumentIdCountHistogram.observe(requestMetrics.length);
86
+ }
87
+ }
88
+ }
89
+ exports.Metrics = Metrics;
90
+ function createEnum(values) {
91
+ const enumObject = {};
92
+ for (const val of values) {
93
+ enumObject[val] = val;
94
+ }
95
+ return Object.freeze(enumObject);
96
+ }
97
+ const metricN = exports.metricN = createEnum(metricNames);
@@ -0,0 +1,34 @@
1
+ import superagent from 'superagent';
2
+ import configuration from '../../lib/configuration.js';
3
+ import logger from '../../lib/logger.js';
4
+ export class InstagramVideoClient {
5
+ /**
6
+ * @private
7
+ * @param {string} url
8
+ * @returns {Promise<object>}
9
+ */
10
+ _getDownloadLink = async url => {
11
+ const apiUrl = configuration.get('UGC_MEDIA_API_URL');
12
+ const apiToken = configuration.get('UGC_MEDIA_API_TOKEN');
13
+ try {
14
+ const response = await superagent.get(`${apiUrl}/instagram/video/`).set('x-api-token', apiToken).query({
15
+ url
16
+ });
17
+ return response.body?.data;
18
+ } catch (error) {
19
+ logger.error(`Could not retrieve video link from ${url}`, {
20
+ error
21
+ });
22
+ throw new Error('Could not retrieve video link');
23
+ }
24
+ };
25
+
26
+ /**
27
+ *
28
+ * @param {string} url
29
+ * @returns {Promise<object>}
30
+ */
31
+ getVideoLink = async url => {
32
+ return await this._getDownloadLink(url);
33
+ };
34
+ }
@@ -0,0 +1,24 @@
1
+ import superagent from 'superagent';
2
+ import logger from '../../lib/logger.js';
3
+ import configuration from '../../lib/configuration.js';
4
+ export class WarpZoneApiClient {
5
+ constructor() {
6
+ this.warpzoneURL = configuration.get('WARPZONE_API_URL');
7
+ this.warpzoneAPI = configuration.get('WARPZONE_API_KEY');
8
+ }
9
+ async sendPost() {
10
+ let postData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
11
+ let response = {};
12
+ try {
13
+ response = await superagent.post(this.warpzoneURL + 'event').set('Accept', 'application/json').set('Content-Type', 'application/json').set('X-API-Key', this.warpzoneAPI).send(postData);
14
+ } catch (err) {
15
+ if (err && err.response && err.response.body && err.response.body.error) {
16
+ logger.error(`Failed to call warp zone api: ${err.response.body.error.message}`);
17
+ } else {
18
+ logger.error(`Failed to call warp zone api`, err);
19
+ }
20
+ throw err;
21
+ }
22
+ return response;
23
+ }
24
+ }
@@ -0,0 +1,37 @@
1
+ import AWS from 'aws-sdk';
2
+ import assert from 'assert';
3
+ class AWS_S3 {
4
+ constructor() {}
5
+ async getClient() {
6
+ const {
7
+ Credentials: {
8
+ AccessKeyId,
9
+ SecretAccessKey,
10
+ SessionToken
11
+ } = {}
12
+ } = await assetManagerTvmRepository.get(companyId);
13
+ if (!AccessKeyId || !SecretAccessKey || !SessionToken) {
14
+ // probably a bit extreme, what would you prefer to do
15
+ throw 'No Credentials available';
16
+ }
17
+ return new AWS.S3({
18
+ accessKeyId: AccessKeyId,
19
+ secretAccessKey: SecretAccessKey,
20
+ sessionToken: SessionToken,
21
+ useAccelerateEndpoint: true
22
+ });
23
+ }
24
+ GetS3ObjectQuery(bucket, filename) {
25
+ assert(bucket, 'S3 bucket is required');
26
+ assert(filename, 'filePath is required');
27
+ assert(typeof filename === 'string', 'filePath should be a string.');
28
+ return {
29
+ config: {
30
+ Bucket: bucket,
31
+ Key: filename.replace(`/${bucket}/`, ''),
32
+ GrantRead: 'uri=http://acs.amazonaws.com/groups/global/AllUsers'
33
+ }
34
+ };
35
+ }
36
+ }
37
+ export const awsS3Client = new AWS_S3();
@@ -0,0 +1,28 @@
1
+ import superagent from 'superagent';
2
+ import logger from '../../lib/logger.js';
3
+ import { MeltwaterAttributes } from '../../lib/logger.helpers.js';
4
+ const {
5
+ ASSET_MANAGER_TVM_API_KEY,
6
+ ASSET_MANAGER_TVM_URL
7
+ } = process.env;
8
+ class AssetManagerTVMRepository {
9
+ apiKey;
10
+ constructor() {}
11
+ async get(companyId) {
12
+ let response;
13
+ try {
14
+ response = await superagent.get(`https://${ASSET_MANAGER_TVM_URL}/tvm`).query({
15
+ companyId
16
+ }).timeout(5000).set({
17
+ 'x-api-key': ASSET_MANAGER_TVM_API_KEY
18
+ }).then(result => result.body);
19
+ } catch (error) {
20
+ logger.error("Failed requesting Asset Manager TVM API", error, {
21
+ [MeltwaterAttributes.COMPANYID]: companyId
22
+ });
23
+ throw error;
24
+ }
25
+ return response;
26
+ }
27
+ }
28
+ export const assetManagerTvmRepository = new AssetManagerTVMRepository();
@@ -0,0 +1,30 @@
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 CompanyApiClient {
6
+ constructor(_ref) {
7
+ let {
8
+ services
9
+ } = _ref;
10
+ this.companiesApiUrl = configuration.get('COMPANIES_API_URL');
11
+ this.authService = services.auth;
12
+ }
13
+ async getById(companyId, jwt) {
14
+ let retries = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
15
+ let company;
16
+ try {
17
+ let resignedToken = await this.authService.getResignedToken(jwt);
18
+ company = await superagent.get(`${this.companiesApiUrl}/${companyId}`).set('Authorization', resignedToken).set('x-client-name', configuration.get('CLIENT_NAME_HEADER')).then(result => result.body);
19
+ } catch (error) {
20
+ logger.error(`Failed requesting Companies Api for companyId ${companyId} retry ${retries}`, error, {
21
+ [MeltwaterAttributes.COMPANYID]: companyId
22
+ });
23
+ if (retries <= 3) {
24
+ return this.getById(companyId, jwt, ++retries);
25
+ }
26
+ return;
27
+ }
28
+ return company;
29
+ }
30
+ }
@@ -0,0 +1,92 @@
1
+ import superagent from 'superagent'; // @todo remove 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 CredentialsApiClient {
6
+ constructor() {
7
+ this.credentialsApiUrl = configuration.get('CREDENTIALS_API_URL');
8
+ this.credentialsApiApplicationId = configuration.get('CREDENTIALS_API_APPLICATION_ID');
9
+ }
10
+ async getCredential(_ref, userPermissionsEnabled) {
11
+ let {
12
+ companyId,
13
+ userId,
14
+ accountId,
15
+ productArea
16
+ } = _ref;
17
+ const credentials = await this.getCredentialsByCompany({
18
+ companyId,
19
+ userId,
20
+ productArea
21
+ }, userPermissionsEnabled);
22
+ if (!credentials) {
23
+ throw 'No credentials returned';
24
+ }
25
+ const credential = credentials.find(credential => credential.social_account_id == accountId);
26
+ if (!credential) {
27
+ throw `${sourceId} credential was not found.`;
28
+ }
29
+ return credential;
30
+ }
31
+ async getCredentialsByCompany(_ref2, userPermissionsEnabled) {
32
+ let {
33
+ companyId,
34
+ userId,
35
+ productArea
36
+ } = _ref2;
37
+ const loggerChild = logger.child({
38
+ [MeltwaterAttributes.COMPANYID]: companyId,
39
+ [MeltwaterAttributes.USERID]: userId
40
+ });
41
+ let credentials;
42
+ try {
43
+ if (productArea) {
44
+ loggerChild.info(`Get Credentials for company: ${companyId} and user: ${userId}`);
45
+ credentials = await superagent.get(`${this.credentialsApiUrl}/api/v4.0/CompanyCredentials/${this.credentialsApiApplicationId}/${companyId}/${userId}`).query({
46
+ productArea
47
+ }).then(result => result.body.data);
48
+ } else if (userPermissionsEnabled) {
49
+ credentials = await superagent.get(`${this.credentialsApiUrl}/api/v4.0/CompanyCredentials/${this.credentialsApiApplicationId}/${companyId}/${userId}`).then(result => result.body.data);
50
+ } else {
51
+ credentials = await superagent.get(`${this.credentialsApiUrl}/api/v3.0/CompanyCredentials/${this.credentialsApiApplicationId}/${companyId}/${userId}`).then(result => result.body.data);
52
+ }
53
+ } catch (error) {
54
+ loggerChild.error(`Failed requesting Credentials API for companyId ${companyId} ${userId}`, error);
55
+ return [];
56
+ }
57
+ loggerChild.info(`Finished requesting Credentials API for companyId ${companyId}`);
58
+ return credentials;
59
+ }
60
+
61
+ // todo: will this need to ever use productArea?
62
+ async getToken(credentialId, companyId) {
63
+ const loggerChild = logger.child({
64
+ [MeltwaterAttributes.COMPANYID]: companyId,
65
+ [MeltwaterAttributes.CREDENTIALID]: credentialId
66
+ });
67
+ let token;
68
+ try {
69
+ token = await superagent.get(`${this.credentialsApiUrl}/api/Token/${credentialId}/${companyId}`).then(result => {
70
+ return result.body;
71
+ });
72
+ } catch (error) {
73
+ loggerChild.error(`Failed requesting Credentials API for credentialId ${credentialId} and companyId ${companyId}`, error);
74
+ return;
75
+ }
76
+ loggerChild.info(`Finished requesting Credentials API for credentialId ${credentialId} and companyId ${companyId}`);
77
+ return token;
78
+ }
79
+ async getCredentialIdByAccountId(accountId, channel) {
80
+ let credentialId;
81
+ try {
82
+ credentialId = await superagent.get(`${this.credentialsApiUrl}/api/CompanyCredentials/GetCredential/${channel}/${accountId}`).then(result => {
83
+ return result.body && result.body.data && result.body.data.credentialId;
84
+ });
85
+ } catch (error) {
86
+ logger.error(`Failed requesting Credentials API for credentialId ${accountId} and channel ${channel}`, error);
87
+ return;
88
+ }
89
+ logger.info(`Finished requesting Credentials API for credentialId ${accountId} and channel ${channel}`);
90
+ return credentialId;
91
+ }
92
+ }
@@ -0,0 +1,32 @@
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 EntitlementsApiClient {
6
+ constructor(_ref) {
7
+ let {
8
+ services
9
+ } = _ref;
10
+ this.entitlementsApiUrl = configuration.get('ENTITLEMENTS_API_URL');
11
+ this.authService = services.auth;
12
+ }
13
+ async getById(entitlementId, companyId, jwt) {
14
+ let retries = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
15
+ const loggerChild = logger.child({
16
+ [MeltwaterAttributes.COMPANYID]: companyId
17
+ });
18
+ let entitlement;
19
+ try {
20
+ let resignedToken = await this.authService.getResignedToken(jwt);
21
+ entitlement = await superagent.get(`${this.entitlementsApiUrl}/company/${companyId}/${entitlementId}`).set('Authorization', resignedToken).set('x-client-name', configuration.get('CLIENT_NAME_HEADER')).then(result => result.body);
22
+ } catch (error) {
23
+ loggerChild.error(`Failed requesting entitlement ${entitlementId} for companyId ${companyId} retry ${retries}`, error);
24
+ if (retries <= 3) {
25
+ return this.getById(entitlementId, companyId, jwt, ++retries);
26
+ }
27
+ return;
28
+ }
29
+ loggerChild.info(`Finished requesting entitlement ${entitlementId} for companyId ${companyId}`);
30
+ return entitlement;
31
+ }
32
+ }