@meltwater/conversations-api-services 1.0.41 → 1.0.43

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.
@@ -113,11 +113,37 @@ async function publish(token, discussionType, mediaId, inReplyToId, socialAccoun
113
113
  if (mediaId) {
114
114
  mediaId = mediaId.replace('urn:li:image:', 'urn:li:digitalmediaAsset:');
115
115
  }
116
+
117
+ // Extract mentions from the messageText
118
+ // https://learn.microsoft.com/en-us/linkedin/compliance/integrations/shares/ugc-post-api?tabs=http#memberattributedentity
119
+ const mentionRegex = /<span class="highlight-mention" data-mention-id="([^"]+)"[^>]*>([^<]+)<\/span>/g;
120
+ let match;
121
+ const attributes = [];
122
+ let textWithoutMentions = messageText;
123
+ while ((match = mentionRegex.exec(messageText)) !== null) {
124
+ attributes.push({
125
+ "type": "MENTION",
126
+ "entity": match[1],
127
+ "start": match.index,
128
+ "length": match[2].length,
129
+ "value": match[1].includes('urn:li:organization') ? {
130
+ "com.linkedin.common.CompanyAttributedEntity": {
131
+ "company": match[1]
132
+ }
133
+ } : {
134
+ // contains person
135
+ "com.linkedin.common.MemberAttributedEntity": {
136
+ "member": match[1]
137
+ }
138
+ }
139
+ });
140
+ textWithoutMentions = textWithoutMentions.replace(match[0], match[2]);
141
+ }
116
142
  let body = {
117
143
  actor: socialAccountId,
118
144
  message: {
119
- attributes: [],
120
- text: messageText
145
+ attributes: attributes,
146
+ text: textWithoutMentions // Replace mention spans with the mention text
121
147
  }
122
148
  };
123
149
  if (discussionType === 're') {
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.comment = comment;
7
7
  exports.deleteComment = deleteComment;
8
+ exports.directMessage = directMessage;
8
9
  exports.getPostData = getPostData;
9
10
  exports.getProfile = getProfile;
10
11
  exports.getStats = getStats;
@@ -17,7 +18,7 @@ var _superagent = _interopRequireDefault(require("superagent"));
17
18
  var _loggerHelpers = require("../../lib/logger.helpers.js");
18
19
  var _externalIdHelpers = require("../../lib/externalId.helpers.js");
19
20
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
20
- const TIKTOK_API_URL = "https://business-api.tiktok.com/open_api/v1.3/business/";
21
+ const TIKTOK_API_URL = 'https://business-api.tiktok.com/open_api/v1.3/business/';
21
22
  async function comment(token, business_id, video_id, text, logger) {
22
23
  const {
23
24
  body: publishedMessage
@@ -39,6 +40,35 @@ async function reply(token, videoId, sourceId, inReplyToId, text, logger) {
39
40
  }, logger)) || {};
40
41
  return publishedMessage;
41
42
  }
43
+ async function directMessage(_ref) {
44
+ let {
45
+ token,
46
+ business_id,
47
+ recipient_id,
48
+ text,
49
+ message_type,
50
+ recepient_type = 'CONVERSATION',
51
+ media_id,
52
+ logger
53
+ } = _ref;
54
+ let payload = {
55
+ business_id: (0, _externalIdHelpers.removePrefix)(business_id),
56
+ recipient: (0, _externalIdHelpers.removePrefix)(recipient_id),
57
+ recepient_type,
58
+ message_type
59
+ };
60
+ if (message_type === 'TEXT') {
61
+ payload.text = {
62
+ body: text
63
+ };
64
+ } else if (message_type === 'IMAGE') {
65
+ payload.media_id = media_id;
66
+ }
67
+ const {
68
+ body: publishedMessage
69
+ } = (await sendPost(token, 'message/send/', payload, logger)) || {};
70
+ return publishedMessage;
71
+ }
42
72
  async function like(token, externalId, sourceId, logger) {
43
73
  const {
44
74
  body: publishedMessage
@@ -93,11 +93,37 @@ async function publish(token, discussionType, mediaId, inReplyToId, socialAccoun
93
93
  if (mediaId) {
94
94
  mediaId = mediaId.replace('urn:li:image:', 'urn:li:digitalmediaAsset:');
95
95
  }
96
+
97
+ // Extract mentions from the messageText
98
+ // https://learn.microsoft.com/en-us/linkedin/compliance/integrations/shares/ugc-post-api?tabs=http#memberattributedentity
99
+ const mentionRegex = /<span class="highlight-mention" data-mention-id="([^"]+)"[^>]*>([^<]+)<\/span>/g;
100
+ let match;
101
+ const attributes = [];
102
+ let textWithoutMentions = messageText;
103
+ while ((match = mentionRegex.exec(messageText)) !== null) {
104
+ attributes.push({
105
+ "type": "MENTION",
106
+ "entity": match[1],
107
+ "start": match.index,
108
+ "length": match[2].length,
109
+ "value": match[1].includes('urn:li:organization') ? {
110
+ "com.linkedin.common.CompanyAttributedEntity": {
111
+ "company": match[1]
112
+ }
113
+ } : {
114
+ // contains person
115
+ "com.linkedin.common.MemberAttributedEntity": {
116
+ "member": match[1]
117
+ }
118
+ }
119
+ });
120
+ textWithoutMentions = textWithoutMentions.replace(match[0], match[2]);
121
+ }
96
122
  let body = {
97
123
  actor: socialAccountId,
98
124
  message: {
99
- attributes: [],
100
- text: messageText
125
+ attributes: attributes,
126
+ text: textWithoutMentions // Replace mention spans with the mention text
101
127
  }
102
128
  };
103
129
  if (discussionType === 're') {
@@ -1,7 +1,7 @@
1
1
  import superagent from 'superagent';
2
2
  import { loggerError } from '../../lib/logger.helpers.js';
3
3
  import { removePrefix } from '../../lib/externalId.helpers.js';
4
- const TIKTOK_API_URL = "https://business-api.tiktok.com/open_api/v1.3/business/";
4
+ const TIKTOK_API_URL = 'https://business-api.tiktok.com/open_api/v1.3/business/';
5
5
  export async function comment(token, business_id, video_id, text, logger) {
6
6
  const {
7
7
  body: publishedMessage
@@ -23,6 +23,35 @@ export async function reply(token, videoId, sourceId, inReplyToId, text, logger)
23
23
  }, logger)) || {};
24
24
  return publishedMessage;
25
25
  }
26
+ export async function directMessage(_ref) {
27
+ let {
28
+ token,
29
+ business_id,
30
+ recipient_id,
31
+ text,
32
+ message_type,
33
+ recepient_type = 'CONVERSATION',
34
+ media_id,
35
+ logger
36
+ } = _ref;
37
+ let payload = {
38
+ business_id: removePrefix(business_id),
39
+ recipient: removePrefix(recipient_id),
40
+ recepient_type,
41
+ message_type
42
+ };
43
+ if (message_type === 'TEXT') {
44
+ payload.text = {
45
+ body: text
46
+ };
47
+ } else if (message_type === 'IMAGE') {
48
+ payload.media_id = media_id;
49
+ }
50
+ const {
51
+ body: publishedMessage
52
+ } = (await sendPost(token, 'message/send/', payload, logger)) || {};
53
+ return publishedMessage;
54
+ }
26
55
  export async function like(token, externalId, sourceId, logger) {
27
56
  const {
28
57
  body: publishedMessage
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meltwater/conversations-api-services",
3
- "version": "1.0.41",
3
+ "version": "1.0.43",
4
4
  "description": "Repository to contain all conversations api services shared across our services",
5
5
  "main": "dist/cjs/data-access/index.js",
6
6
  "module": "dist/esm/data-access/index.js",
@@ -1,4 +1,3 @@
1
-
2
1
  import superagent from 'superagent';
3
2
  import { loggerDebug, loggerError, loggerInfo } from '../../lib/logger.helpers.js';
4
3
 
@@ -126,12 +125,37 @@ async function publish(token,discussionType, mediaId,inReplyToId,socialAccountId
126
125
  );
127
126
  }
128
127
 
128
+ // Extract mentions from the messageText
129
+ // https://learn.microsoft.com/en-us/linkedin/compliance/integrations/shares/ugc-post-api?tabs=http#memberattributedentity
130
+ const mentionRegex = /<span class="highlight-mention" data-mention-id="([^"]+)"[^>]*>([^<]+)<\/span>/g;
131
+ let match;
132
+ const attributes = [];
133
+ let textWithoutMentions = messageText;
134
+ while ((match = mentionRegex.exec(messageText)) !== null) {
135
+ attributes.push({
136
+ "type": "MENTION",
137
+ "entity": match[1],
138
+ "start": match.index,
139
+ "length": match[2].length,
140
+ "value": match[1].includes('urn:li:organization') ? {
141
+ "com.linkedin.common.CompanyAttributedEntity": {
142
+ "company": match[1]
143
+ }
144
+ } : { // contains person
145
+ "com.linkedin.common.MemberAttributedEntity": {
146
+ "member": match[1]
147
+ }
148
+ },
149
+ });
150
+ textWithoutMentions = textWithoutMentions.replace(match[0], match[2]);
151
+ }
152
+
129
153
  let body = {
130
154
  actor: socialAccountId,
131
155
  message: {
132
- attributes: [],
133
- text: messageText,
134
- },
156
+ attributes: attributes,
157
+ text: textWithoutMentions // Replace mention spans with the mention text
158
+ }
135
159
  };
136
160
  if (discussionType === 're') {
137
161
  body.parentComment = inReplyToId;
@@ -1,27 +1,37 @@
1
1
  import superagent from 'superagent';
2
- import { loggerError } from '../../lib/logger.helpers.js';
2
+ import { loggerError } from '../../lib/logger.helpers.js';
3
3
  import { removePrefix } from '../../lib/externalId.helpers.js';
4
4
 
5
- const TIKTOK_API_URL = "https://business-api.tiktok.com/open_api/v1.3/business/";
5
+ const TIKTOK_API_URL =
6
+ 'https://business-api.tiktok.com/open_api/v1.3/business/';
6
7
 
7
- export async function comment(token,business_id,video_id,text,logger) {
8
+ export async function comment(token, business_id, video_id, text, logger) {
8
9
  const { body: publishedMessage } =
9
10
  (await sendPost(
10
11
  token,
11
12
  'comment/create/',
12
13
  {
13
14
  business_id: business_id,
14
- video_id: removePrefix(video_id.startsWith('tt_')
15
- ? video_id.split('_')[2]
16
- : video_id),
15
+ video_id: removePrefix(
16
+ video_id.startsWith('tt_')
17
+ ? video_id.split('_')[2]
18
+ : video_id
19
+ ),
17
20
  text,
18
21
  },
19
- logger,
22
+ logger
20
23
  )) || {};
21
24
  return publishedMessage;
22
25
  }
23
26
 
24
- export async function reply(token,videoId,sourceId, inReplyToId, text, logger) {
27
+ export async function reply(
28
+ token,
29
+ videoId,
30
+ sourceId,
31
+ inReplyToId,
32
+ text,
33
+ logger
34
+ ) {
25
35
  const { body: publishedMessage } =
26
36
  (await sendPost(
27
37
  token,
@@ -32,13 +42,41 @@ export async function reply(token,videoId,sourceId, inReplyToId, text, logger) {
32
42
  video_id: removePrefix(videoId),
33
43
  text,
34
44
  },
35
- logger,
45
+ logger
36
46
  )) || {};
37
47
 
38
48
  return publishedMessage;
39
49
  }
40
50
 
41
- export async function like(token,externalId,sourceId,logger) {
51
+ export async function directMessage({
52
+ token,
53
+ business_id,
54
+ recipient_id,
55
+ text,
56
+ message_type,
57
+ recepient_type = 'CONVERSATION',
58
+ media_id,
59
+ logger,
60
+ }) {
61
+ let payload = {
62
+ business_id: removePrefix(business_id),
63
+ recipient: removePrefix(recipient_id),
64
+ recepient_type,
65
+ message_type,
66
+ };
67
+
68
+ if (message_type === 'TEXT') {
69
+ payload.text = { body: text };
70
+ } else if (message_type === 'IMAGE') {
71
+ payload.media_id = media_id;
72
+ }
73
+
74
+ const { body: publishedMessage } =
75
+ (await sendPost(token, 'message/send/', payload, logger)) || {};
76
+ return publishedMessage;
77
+ }
78
+
79
+ export async function like(token, externalId, sourceId, logger) {
42
80
  const { body: publishedMessage } =
43
81
  (await sendPost(
44
82
  token,
@@ -48,13 +86,13 @@ export async function like(token,externalId,sourceId,logger) {
48
86
  comment_id: removePrefix(externalId),
49
87
  action: 'LIKE',
50
88
  },
51
- logger,
89
+ logger
52
90
  )) || {};
53
91
  return publishedMessage;
54
92
  }
55
93
 
56
94
  // Conversations says this is only allowed on Native...
57
- export async function unlike(token,inReplyToId,sourceId, logger) {
95
+ export async function unlike(token, inReplyToId, sourceId, logger) {
58
96
  const { body: publishedMessage } =
59
97
  (await sendPost(
60
98
  token,
@@ -64,13 +102,13 @@ export async function unlike(token,inReplyToId,sourceId, logger) {
64
102
  comment_id: removePrefix(inReplyToId),
65
103
  action: 'unlike',
66
104
  },
67
- logger,
105
+ logger
68
106
  )) || {};
69
107
  return publishedMessage;
70
108
  }
71
109
 
72
110
  // Conversations says this is only allowed on Native...
73
- export async function hide(token,externalId,sourceId, video_id, logger) {
111
+ export async function hide(token, externalId, sourceId, video_id, logger) {
74
112
  const { body: publishedMessage } =
75
113
  (await sendPost(
76
114
  token,
@@ -81,13 +119,12 @@ export async function hide(token,externalId,sourceId, video_id, logger) {
81
119
  video_id: removePrefix(video_id),
82
120
  action: 'HIDE',
83
121
  },
84
- logger,
122
+ logger
85
123
  )) || {};
86
124
  return publishedMessage;
87
125
  }
88
126
 
89
- export async function unhide(token,externalId,sourceId,video_id, logger) {
90
-
127
+ export async function unhide(token, externalId, sourceId, video_id, logger) {
91
128
  const { body: publishedMessage } =
92
129
  (await sendPost(
93
130
  token,
@@ -98,12 +135,12 @@ export async function unhide(token,externalId,sourceId,video_id, logger) {
98
135
  video_id: removePrefix(video_id),
99
136
  action: 'UNHIDE',
100
137
  },
101
- logger,
138
+ logger
102
139
  )) || {};
103
140
  return publishedMessage;
104
141
  }
105
142
 
106
- export async function deleteComment(token,inReplyToId, profileId, logger) {
143
+ export async function deleteComment(token, inReplyToId, profileId, logger) {
107
144
  const { body: publishedMessage } =
108
145
  (await sendPost(
109
146
  token,
@@ -112,45 +149,51 @@ export async function deleteComment(token,inReplyToId, profileId, logger) {
112
149
  business_id: profileId,
113
150
  comment_id: inReplyToId,
114
151
  },
115
- logger,
152
+ logger
116
153
  )) || {};
117
154
  return publishedMessage;
118
155
  }
119
156
 
120
157
  export async function getProfile(
121
- token,
122
- business_id,
123
- fields = '["username", "display_name", "profile_image"]',
158
+ token,
159
+ business_id,
160
+ fields = '["username", "display_name", "profile_image"]',
124
161
  logger
125
162
  ) {
126
163
  const profile =
127
164
  (await sendRequest(
128
165
  token,
129
166
  `get/?business_id=${business_id}&fields=${fields}`,
130
- logger,
167
+ logger
131
168
  )) || {};
132
169
  return profile;
133
170
  }
134
171
 
135
- export async function getStats(token, business_id, externalIds, paramString = 'video/list/', logger){
136
-
172
+ export async function getStats(
173
+ token,
174
+ business_id,
175
+ externalIds,
176
+ paramString = 'video/list/',
177
+ logger
178
+ ) {
137
179
  const profile =
138
180
  (await sendRequest(
139
181
  token,
140
- `${
141
- paramString
142
- }?business_id=${business_id}&fields=["item_id","create_time","thumbnail_url","share_url","embed_url","caption","video_views","likes","comments","shares"]&filters=${JSON.stringify(
182
+ `${paramString}?business_id=${business_id}&fields=["item_id","create_time","thumbnail_url","share_url","embed_url","caption","video_views","likes","comments","shares"]&filters=${JSON.stringify(
143
183
  {
144
184
  video_ids: externalIds,
145
185
  }
146
186
  )}`,
147
- logger,
187
+ logger
148
188
  )) || {};
149
189
  return profile;
150
190
  }
151
191
 
152
192
  // This doesn't appear to be used in Conversations either
153
- export async function getPostData(token, business_id, video_id,
193
+ export async function getPostData(
194
+ token,
195
+ business_id,
196
+ video_id,
154
197
  fields = '["item_id", "thumbnail_url", "create_time", "username", "display_name", "profile_image"]',
155
198
  logger
156
199
  ) {
@@ -159,13 +202,13 @@ export async function getPostData(token, business_id, video_id,
159
202
  (await sendRequest(
160
203
  token,
161
204
  `video/list?business_id=${business_id}&fields=${fields}&filters={"video_ids":${video_ids}}`,
162
- logger,
205
+ logger
163
206
  )) || {};
164
207
  return profile;
165
208
  }
166
209
 
167
210
  // assumes batch calls are using the same credential
168
- async function sendRequest(token, paramString = '', logger) {
211
+ async function sendRequest(token, paramString = '', logger) {
169
212
  let response = {};
170
213
  try {
171
214
  response = await superagent
@@ -181,11 +224,13 @@ async function sendRequest(token, paramString = '', logger) {
181
224
  err.response.body &&
182
225
  err.response.body.error
183
226
  ) {
184
- loggerError(logger,
227
+ loggerError(
228
+ logger,
185
229
  `Failed to call tiktok api for paramString ${paramString}: ${err.response.body.error.message}`
186
230
  );
187
231
  } else {
188
- loggerError(logger,
232
+ loggerError(
233
+ logger,
189
234
  `Failed to call tiktok api for paramString ${paramString}`,
190
235
  err
191
236
  );
@@ -195,13 +240,10 @@ async function sendRequest(token, paramString = '', logger) {
195
240
  }
196
241
 
197
242
  if (response.status !== 200) {
198
- loggerError(logger,
199
- `Failed to call tiktok api`,
200
- { responseBody: JSON.stringify(response.body) }
201
- );
202
- let error = new Error(
203
- `Failed to call tiktok api`
204
- );
243
+ loggerError(logger, `Failed to call tiktok api`, {
244
+ responseBody: JSON.stringify(response.body),
245
+ });
246
+ let error = new Error(`Failed to call tiktok api`);
205
247
  error.code = response.status;
206
248
  throw error;
207
249
  }
@@ -209,13 +251,7 @@ async function sendRequest(token, paramString = '', logger) {
209
251
  return response.body;
210
252
  }
211
253
 
212
- async function sendPost(
213
- token,
214
- paramString = '',
215
- postData = undefined,
216
- logger
217
- ) {
218
-
254
+ async function sendPost(token, paramString = '', postData = undefined, logger) {
219
255
  let response = {};
220
256
  try {
221
257
  response = await superagent
@@ -231,11 +267,13 @@ async function sendPost(
231
267
  err.response.body &&
232
268
  err.response.body.error
233
269
  ) {
234
- loggerError(logger,
270
+ loggerError(
271
+ logger,
235
272
  `Failed to call tiktok api for paramString ${paramString}: ${err.response.body.error.message}`
236
273
  );
237
274
  } else {
238
- loggerError(logger,
275
+ loggerError(
276
+ logger,
239
277
  `Failed to call tiktok api for paramString ${paramString}`,
240
278
  err
241
279
  );
@@ -245,4 +283,4 @@ async function sendPost(
245
283
  }
246
284
 
247
285
  return response;
248
- }
286
+ }