@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.
- package/.github/workflows/release.yml +2 -0
- package/babel.config.js +18 -0
- package/dist/cjs/data-access/http/InstagramVideoClient.js +42 -0
- package/dist/cjs/data-access/http/WarpZoneApi.client.js +32 -0
- package/dist/cjs/data-access/http/amazonS3.js +44 -0
- package/dist/cjs/data-access/http/asset-manager-tvm.client.js +35 -0
- package/dist/cjs/data-access/http/companiesApi.client.js +38 -0
- package/dist/cjs/data-access/http/credentialsApi.client.js +102 -0
- package/dist/cjs/data-access/http/entitlementsApi.client.js +40 -0
- package/dist/cjs/data-access/http/facebook.native.js +344 -0
- package/dist/cjs/data-access/http/facebookApi.client.js +631 -0
- package/dist/cjs/data-access/http/featureToggleApi.client.js +31 -0
- package/dist/cjs/data-access/http/identityServices.client.js +97 -0
- package/dist/cjs/data-access/http/instagramApi.client.js +428 -0
- package/dist/cjs/data-access/http/ir.client.js +242 -0
- package/dist/cjs/data-access/http/linkedInApi.client.js +491 -0
- package/dist/cjs/data-access/http/masf.client.js +101 -0
- package/dist/cjs/data-access/http/tiktok.native.js +162 -0
- package/dist/cjs/data-access/http/tiktokApi.client.js +441 -0
- package/dist/cjs/data-access/index.js +132 -0
- package/dist/cjs/errors/engage-error.js +16 -0
- package/dist/cjs/errors/http-error.js +23 -0
- package/dist/cjs/lib/applicationTags.helpers.js +30 -0
- package/dist/cjs/lib/configuration.js +14 -0
- package/dist/cjs/lib/document-action-events.js +12 -0
- package/dist/cjs/lib/externalId.helpers.js +19 -0
- package/dist/cjs/lib/hidden.helpers.js +13 -0
- package/dist/cjs/lib/hiddenComment.helper.js +119 -0
- package/dist/cjs/lib/logger.helpers.js +68 -0
- package/dist/cjs/lib/logger.js +23 -0
- package/dist/cjs/lib/message.helpers.js +58 -0
- package/dist/cjs/lib/metrics.helper.js +97 -0
- package/dist/esm/data-access/http/InstagramVideoClient.js +34 -0
- package/dist/esm/data-access/http/WarpZoneApi.client.js +24 -0
- package/dist/esm/data-access/http/amazonS3.js +37 -0
- package/dist/esm/data-access/http/asset-manager-tvm.client.js +28 -0
- package/dist/esm/data-access/http/companiesApi.client.js +30 -0
- package/dist/esm/data-access/http/credentialsApi.client.js +92 -0
- package/dist/esm/data-access/http/entitlementsApi.client.js +32 -0
- package/dist/esm/data-access/http/facebook.native.js +325 -0
- package/dist/esm/data-access/http/facebookApi.client.js +621 -0
- package/dist/esm/data-access/http/featureToggleApi.client.js +23 -0
- package/dist/esm/data-access/http/identityServices.client.js +89 -0
- package/dist/esm/data-access/http/instagramApi.client.js +420 -0
- package/dist/esm/data-access/http/ir.client.js +234 -0
- package/dist/esm/data-access/http/linkedInApi.client.js +481 -0
- package/dist/esm/data-access/http/masf.client.js +93 -0
- package/dist/esm/data-access/http/tiktok.native.js +146 -0
- package/dist/esm/data-access/http/tiktokApi.client.js +433 -0
- package/dist/esm/data-access/index.js +30 -0
- package/dist/esm/errors/engage-error.js +9 -0
- package/dist/esm/errors/http-error.js +16 -0
- package/dist/esm/lib/applicationTags.helpers.js +22 -0
- package/dist/esm/lib/configuration.js +8 -0
- package/dist/esm/lib/document-action-events.js +6 -0
- package/dist/esm/lib/externalId.helpers.js +12 -0
- package/dist/esm/lib/hidden.helpers.js +6 -0
- package/dist/esm/lib/hiddenComment.helper.js +112 -0
- package/dist/esm/lib/logger.helpers.js +60 -0
- package/dist/esm/lib/logger.js +16 -0
- package/dist/esm/lib/message.helpers.js +52 -0
- package/dist/esm/lib/metrics.helper.js +90 -0
- package/package.json +14 -4
- package/src/data-access/http/facebook.native.js +542 -0
- package/src/data-access/http/tiktok.native.js +248 -0
- package/src/data-access/index.js +4 -0
- package/src/errors/engage-error.js +11 -0
- package/src/errors/http-error.js +19 -0
- package/src/lib/logger.helpers.js +15 -0
- package/src/lib/message.helpers.js +7 -1
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import superagent from 'superagent';
|
|
2
|
+
import { removePrefix } from '../../lib/externalId.helpers.js';
|
|
3
|
+
import { loggerDebug, loggerError, loggerInfo } from '../../lib/logger.helpers.js';
|
|
4
|
+
import { EngageHttpError } from '../../errors/http-error.js';
|
|
5
|
+
import { EngageError } from '../../errors/engage-error.js';
|
|
6
|
+
const FACEBOOK_URL = 'https://graph.facebook.com';
|
|
7
|
+
export async function shareCount(token, externalId, logger) {
|
|
8
|
+
try {
|
|
9
|
+
const response = await getApi(`${FACEBOOK_URL}/${removePrefix(externalId)}/?fields=shares`, token);
|
|
10
|
+
return response.body.shares && response.body.shares.count;
|
|
11
|
+
} catch (err) {
|
|
12
|
+
loggerError(logger, `Facebook shareCount error recieved - ${error.code}`, error);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function reactions(token, externalIds, logger) {
|
|
16
|
+
try {
|
|
17
|
+
const response = await getApi(`${FACEBOOK_URL}?ids=${externalIds.map(externalId => removePrefix(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);
|
|
18
|
+
return response.body;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
loggerError(logger, `Facebook reactions error recieved - ${error.code}`, error);
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function comment(token, _ref) {
|
|
25
|
+
let {
|
|
26
|
+
inReplyToExternalId,
|
|
27
|
+
text,
|
|
28
|
+
attachment = undefined
|
|
29
|
+
} = _ref;
|
|
30
|
+
let logger = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
|
|
31
|
+
let response;
|
|
32
|
+
const isGif = attachment && attachment.mimeType === 'image/gif';
|
|
33
|
+
loggerDebug(logger, `Starting to call facebook comment api inReplyToExternalId ${inReplyToExternalId}`, {
|
|
34
|
+
text,
|
|
35
|
+
attachment
|
|
36
|
+
});
|
|
37
|
+
response = await postApi(`${FACEBOOK_URL}/${removePrefix(inReplyToExternalId)}/comments`, token, {
|
|
38
|
+
...(text && text.length && {
|
|
39
|
+
message: text
|
|
40
|
+
}),
|
|
41
|
+
...(attachment && !isGif && {
|
|
42
|
+
attachment_url: attachment.link
|
|
43
|
+
}),
|
|
44
|
+
...(attachment && isGif && {
|
|
45
|
+
attachment_share_url: attachment.link
|
|
46
|
+
})
|
|
47
|
+
}, logger);
|
|
48
|
+
loggerInfo(logger, `Native Facebook API Publish Comment Response to externalId ${inReplyToExternalId}`, {
|
|
49
|
+
responseBody: JSON.stringify(response.body)
|
|
50
|
+
});
|
|
51
|
+
return response.body;
|
|
52
|
+
}
|
|
53
|
+
export async function privateMessage(token, _ref2, logger) {
|
|
54
|
+
let {
|
|
55
|
+
recipientId,
|
|
56
|
+
text,
|
|
57
|
+
attachment = undefined
|
|
58
|
+
} = _ref2;
|
|
59
|
+
let response;
|
|
60
|
+
const isGif = attachment && attachment.mimeType === 'image/gif';
|
|
61
|
+
loggerDebug(logger, `Starting to call facebook PM api to recipientId ${recipientId}`, {
|
|
62
|
+
payload: JSON.stringify({
|
|
63
|
+
text,
|
|
64
|
+
attachment
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
response = await postApi(`${FACEBOOK_URL}/me/messages`, token, {
|
|
68
|
+
recipient: {
|
|
69
|
+
id: removePrefix(recipientId)
|
|
70
|
+
},
|
|
71
|
+
message: {
|
|
72
|
+
text: text,
|
|
73
|
+
...(attachment && {
|
|
74
|
+
attachment: {
|
|
75
|
+
type: isGif ? 'video' : attachment.mimeType.split('/')[0],
|
|
76
|
+
payload: {
|
|
77
|
+
url: attachment.link,
|
|
78
|
+
is_reusable: true
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
},
|
|
83
|
+
tag: 'HUMAN_AGENT'
|
|
84
|
+
}, logger);
|
|
85
|
+
loggerInfo(logger, `Native Facebook API Publish Private Message Response for documentId ${documentId}`, {
|
|
86
|
+
responseBody: JSON.stringify(response.body)
|
|
87
|
+
});
|
|
88
|
+
return response.body;
|
|
89
|
+
}
|
|
90
|
+
export async function hide(token, externalId, logger) {
|
|
91
|
+
loggerDebug(logger, `Starting to call facebook hide api`);
|
|
92
|
+
const response = await postApi(`${FACEBOOK_URL}/${removePrefix(externalId)}`, token, {
|
|
93
|
+
is_hidden: true
|
|
94
|
+
}, logger);
|
|
95
|
+
loggerInfo(logger`Native Facebook API Hide Response`, {
|
|
96
|
+
responseBody: JSON.stringify(response.body)
|
|
97
|
+
});
|
|
98
|
+
return response.body;
|
|
99
|
+
}
|
|
100
|
+
export async function unhide(token, externalId, logger) {
|
|
101
|
+
loggerDebug(logger, `Starting to call facebook unhide api`);
|
|
102
|
+
const response = await postApi(`${FACEBOOK_URL}/${removePrefix(externalId)}`, token, {
|
|
103
|
+
is_hidden: false
|
|
104
|
+
}, logger);
|
|
105
|
+
loggerChild.info(`Native Facebook API Unhide Response`, {
|
|
106
|
+
responseBody: JSON.stringify(response.body)
|
|
107
|
+
});
|
|
108
|
+
return response.body;
|
|
109
|
+
}
|
|
110
|
+
export async function like(token, externalId, logger) {
|
|
111
|
+
loggerDebug(logger, `Starting to call facebook like api`);
|
|
112
|
+
const response = await postApi(`${FACEBOOK_URL}/${removePrefix(externalId)}/likes`, token, undefined, logger);
|
|
113
|
+
loggerInfo(logger, `Native Facebook API Like Response`, {
|
|
114
|
+
responseBody: JSON.stringify(response.body)
|
|
115
|
+
});
|
|
116
|
+
return response.body;
|
|
117
|
+
}
|
|
118
|
+
export async function unlike(token, externalId, logger) {
|
|
119
|
+
loggerDebug(logger, `Starting to call facebook unlike api`);
|
|
120
|
+
const response = await deleteApi(`${FACEBOOK_URL}/${removePrefix(externalId)}/likes`, token, undefined, logger);
|
|
121
|
+
loggerInfo(logger, `Native Facebook API Unlike Response`, {
|
|
122
|
+
responseBody: JSON.stringify(response.body)
|
|
123
|
+
});
|
|
124
|
+
return response.body;
|
|
125
|
+
}
|
|
126
|
+
export async function isUserBanned(token, authorId, pageId, logger) {
|
|
127
|
+
if (!pageId) {
|
|
128
|
+
// if no pageId to check this call will fail
|
|
129
|
+
// should only happen with temp edge docs
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const response = await getApi(`${FACEBOOK_URL}/${pageId}/blocked`, token, undefined,
|
|
133
|
+
// payload
|
|
134
|
+
{
|
|
135
|
+
user: removePrefix(authorId)
|
|
136
|
+
}, logger);
|
|
137
|
+
if (response && response.body && response.body.data) {
|
|
138
|
+
const userNoPrefix = removePrefix(authorId);
|
|
139
|
+
const user = response.body.data.find(user => {
|
|
140
|
+
if (user.id == userNoPrefix) {
|
|
141
|
+
return user;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
if (user) {
|
|
145
|
+
return true;
|
|
146
|
+
} else {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
loggerInfo(logger, `Native Facebook API is User Banned Response was invalid`, {
|
|
151
|
+
responseBody: JSON.stringify(response.body)
|
|
152
|
+
});
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
export async function getProfile(token, authorId, logger) {
|
|
156
|
+
if (!authorId) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
let response = {};
|
|
160
|
+
const userNoPrefix = removePrefix(authorId);
|
|
161
|
+
try {
|
|
162
|
+
response = await superagent.get(`${FACEBOOK_URL}/${userNoPrefix}`).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
|
|
163
|
+
access_token: token
|
|
164
|
+
}).send();
|
|
165
|
+
} catch (err) {
|
|
166
|
+
if (err?.response?.body?.error) {
|
|
167
|
+
loggerError(logger, `Failed to call facebook api for userId ${userNoPrefix}: ${err.response.body.error.message}`);
|
|
168
|
+
} else {
|
|
169
|
+
loggerError(logger, `Failed to call facebook api for userId ${userNoPrefix}`, err);
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
if (response.status !== 200) {
|
|
174
|
+
loggerError(logger, `Failed to call facebook api for userId ${userNoPrefix}`, {
|
|
175
|
+
responseBody: JSON.stringify(response.body)
|
|
176
|
+
});
|
|
177
|
+
let error = new Error(`Failed to call facebook api for userId ${userNoPrefix}`);
|
|
178
|
+
error.code = response.status;
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return response;
|
|
182
|
+
}
|
|
183
|
+
export async function ban(token, sourceId, authorId, logger) {
|
|
184
|
+
loggerDebug(logger, `Starting to call facebook ban api for externalAuthorId ${authorId} ${sourceId}`);
|
|
185
|
+
const response = await postApi(`${FACEBOOK_URL}/${removePrefix(sourceId)}/blocked`, token, {
|
|
186
|
+
psid: [removePrefix(authorId)]
|
|
187
|
+
}, logger);
|
|
188
|
+
loggerInfo(logger, `Native Facebook API Hide Response for externalAuthorId ${authorId}`, {
|
|
189
|
+
responseBody: JSON.stringify(response.body)
|
|
190
|
+
});
|
|
191
|
+
return response.body;
|
|
192
|
+
}
|
|
193
|
+
export async function unban(token, sourceId, authorId, logger) {
|
|
194
|
+
loggerDebug(logger, `Starting to call facebook unban api for externalAuthorId ${authorId} ${sourceId}`);
|
|
195
|
+
const response = await deleteApi(`${FACEBOOK_URL}/${removePrefix(sourceId)}/blocked`, token, {
|
|
196
|
+
psid: [removePrefix(authorId)]
|
|
197
|
+
}, logger);
|
|
198
|
+
loggerInfo(logger, `Native Facebook API Unban Response for externalAuthorId ${authorId}`, {
|
|
199
|
+
responseBody: JSON.stringify(response.body)
|
|
200
|
+
});
|
|
201
|
+
return response.body;
|
|
202
|
+
}
|
|
203
|
+
export async function getAttachment(token, externalId, discussionType, logger) {
|
|
204
|
+
let result;
|
|
205
|
+
try {
|
|
206
|
+
switch (discussionType) {
|
|
207
|
+
case 're':
|
|
208
|
+
case 'qt':
|
|
209
|
+
result = await getApi(`${FACEBOOK_URL}/${removePrefix(externalId)}?fields=attachment`, token, undefined, undefined, logger);
|
|
210
|
+
return {
|
|
211
|
+
images: [{
|
|
212
|
+
source: result?.body?.attachment?.media?.source || result?.body?.attachment?.media?.image?.src
|
|
213
|
+
}]
|
|
214
|
+
};
|
|
215
|
+
case 'dm':
|
|
216
|
+
result = await getApi(`${FACEBOOK_URL}/${removePrefix(externalId)}?fields=attachments`, token, undefined, undefined, logger);
|
|
217
|
+
return {
|
|
218
|
+
images: result?.body?.attachments?.data.map(item => {
|
|
219
|
+
return {
|
|
220
|
+
source: item.image_data?.url
|
|
221
|
+
};
|
|
222
|
+
})
|
|
223
|
+
};
|
|
224
|
+
default:
|
|
225
|
+
// og
|
|
226
|
+
result = await getApi(`${FACEBOOK_URL}/${removePrefix(externalId)}/attachments?fields=media,subattachments,file_url`, token, undefined, undefined, logger);
|
|
227
|
+
|
|
228
|
+
// if subattachments exist, use them
|
|
229
|
+
const res = result?.body?.data[0];
|
|
230
|
+
if (res?.subattachments) {
|
|
231
|
+
return {
|
|
232
|
+
images: res?.subattachments.data.map(item => {
|
|
233
|
+
return {
|
|
234
|
+
source: item?.media?.source || item?.media?.image?.src
|
|
235
|
+
};
|
|
236
|
+
})
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
images: [{
|
|
241
|
+
source: res?.media?.source || res?.media?.image?.src
|
|
242
|
+
}]
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
loggerError(logger, `Error getting facebook attachment`, error);
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async function getApi(apiUrl, accessToken, payload) {
|
|
251
|
+
let queryParams = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
252
|
+
let logger = arguments.length > 4 ? arguments[4] : undefined;
|
|
253
|
+
let response = {};
|
|
254
|
+
try {
|
|
255
|
+
response = await superagent.get(apiUrl).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
|
|
256
|
+
access_token: accessToken,
|
|
257
|
+
...queryParams
|
|
258
|
+
}).send(payload);
|
|
259
|
+
} catch (err) {
|
|
260
|
+
if (err && err.response && err.response.body && err.response.body.error) {
|
|
261
|
+
loggerError(logger, `Failed to call facebook getApi ${apiUrl}: ${err.response.body.error.message}`);
|
|
262
|
+
} else {
|
|
263
|
+
loggerError(logger, `Failed to call facebook getApi ${apiUrl}`, err);
|
|
264
|
+
}
|
|
265
|
+
throw err;
|
|
266
|
+
}
|
|
267
|
+
if (response.status !== 200) {
|
|
268
|
+
loggerError(logger, `Failed to call facebook api ${apiUrl}`, {
|
|
269
|
+
responseBody: JSON.stringify(response.body)
|
|
270
|
+
});
|
|
271
|
+
let error = new Error(`Failed to call facebook api ${apiUrl}`);
|
|
272
|
+
error.code = response.status;
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
return response;
|
|
276
|
+
}
|
|
277
|
+
async function postApi(apiUrl, accessToken, payload, logger) {
|
|
278
|
+
let response = {};
|
|
279
|
+
try {
|
|
280
|
+
response = await superagent.post(apiUrl).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
|
|
281
|
+
access_token: accessToken
|
|
282
|
+
}).send(payload);
|
|
283
|
+
} catch (err) {
|
|
284
|
+
if (err && err.response && err.response.body && err.response.body.error) {
|
|
285
|
+
loggerError(logger, `Failed to call facebook api: ${err.response.body.error.message}`);
|
|
286
|
+
} else {
|
|
287
|
+
loggerError(logger, `Failed to call facebook api`, err);
|
|
288
|
+
}
|
|
289
|
+
if (response.status) {
|
|
290
|
+
throw new EngageHttpError(response.status, response.statusText, response.body, response.headers);
|
|
291
|
+
}
|
|
292
|
+
throw err;
|
|
293
|
+
}
|
|
294
|
+
if (response.status !== 200) {
|
|
295
|
+
logger.error(logger, `Failed to call facebook api`, {
|
|
296
|
+
responseBody: JSON.stringify(response.body)
|
|
297
|
+
});
|
|
298
|
+
throw new EngageError(response.status, `Failed to call facebook api ${response.body}`);
|
|
299
|
+
}
|
|
300
|
+
return response;
|
|
301
|
+
}
|
|
302
|
+
async function deleteApi(apiUrl, accessToken, payload, logger) {
|
|
303
|
+
let response = {};
|
|
304
|
+
try {
|
|
305
|
+
response = await superagent.delete(apiUrl).set('Accept', 'application/json').set('Content-Type', 'application/json').query({
|
|
306
|
+
access_token: accessToken
|
|
307
|
+
}).send(payload);
|
|
308
|
+
} catch (err) {
|
|
309
|
+
if (err && err.response && err.response.body && err.response.body.error) {
|
|
310
|
+
loggerError(logger, `Failed to call facebook api delete: ${err.response.body.error.message}`);
|
|
311
|
+
} else {
|
|
312
|
+
loggerError(logger, `Failed to call facebook api delete`, err);
|
|
313
|
+
}
|
|
314
|
+
throw err;
|
|
315
|
+
}
|
|
316
|
+
if (response.status !== 200) {
|
|
317
|
+
loggerError(logger, `Failed to call facebook api delete`, {
|
|
318
|
+
responseBody: JSON.stringify(response.body)
|
|
319
|
+
});
|
|
320
|
+
let error = new Error(`Failed to call facebook api delete`);
|
|
321
|
+
error.code = response.status;
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
return response;
|
|
325
|
+
}
|