@memberjunction/actions-bizapps-social 2.111.0 → 2.112.0
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +6 -6
- package/dist/base/base-social.action.d.ts.map +1 -1
- package/dist/base/base-social.action.js +18 -24
- package/dist/base/base-social.action.js.map +1 -1
- package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -1
- package/dist/providers/buffer/buffer-base.action.js +35 -34
- package/dist/providers/buffer/buffer-base.action.js.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.js +33 -33
- package/dist/providers/facebook/actions/boost-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.js +34 -36
- package/dist/providers/facebook/actions/create-album.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.js +20 -20
- package/dist/providers/facebook/actions/create-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.js +25 -27
- package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.js +19 -23
- package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.js +28 -32
- package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.js +42 -44
- package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.js +29 -29
- package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.js +37 -39
- package/dist/providers/facebook/actions/search-posts.action.js.map +1 -1
- package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -1
- package/dist/providers/facebook/facebook-base.action.js +44 -59
- package/dist/providers/facebook/facebook-base.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +33 -31
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +28 -32
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +19 -19
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.js +24 -26
- package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +22 -22
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js +32 -34
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.js +43 -52
- package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +30 -28
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.js +18 -20
- package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.js +27 -26
- package/dist/providers/instagram/actions/create-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.js +35 -35
- package/dist/providers/instagram/actions/create-story.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.js +38 -59
- package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.js +29 -29
- package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.js +36 -36
- package/dist/providers/instagram/actions/get-comments.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.js +23 -25
- package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.js +25 -25
- package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.js +56 -60
- package/dist/providers/instagram/actions/search-posts.action.js.map +1 -1
- package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -1
- package/dist/providers/instagram/instagram-base.action.js +25 -27
- package/dist/providers/instagram/instagram-base.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.js +55 -45
- package/dist/providers/linkedin/actions/create-article.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.js +31 -29
- package/dist/providers/linkedin/actions/create-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.js +28 -28
- package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.js +20 -20
- package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.js +19 -19
- package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.js +25 -23
- package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.js +32 -30
- package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.js +28 -30
- package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.js +33 -38
- package/dist/providers/linkedin/linkedin-base.action.js.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.js +25 -26
- package/dist/providers/tiktok/tiktok-base.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.js +25 -29
- package/dist/providers/twitter/actions/create-thread.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.js +23 -23
- package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.js +19 -19
- package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.js +40 -47
- package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.js +30 -31
- package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.js +29 -29
- package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.js +26 -26
- package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.js +56 -58
- package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -1
- package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -1
- package/dist/providers/twitter/twitter-base.action.js +58 -68
- package/dist/providers/twitter/twitter-base.action.js.map +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -1
- package/dist/providers/youtube/youtube-base.action.js +22 -25
- package/dist/providers/youtube/youtube-base.action.js.map +1 -1
- package/package.json +5 -6
- package/src/base/base-social.action.ts +217 -224
- package/src/providers/buffer/buffer-base.action.ts +435 -441
- package/src/providers/facebook/actions/boost-post.action.ts +350 -386
- package/src/providers/facebook/actions/create-album.action.ts +291 -307
- package/src/providers/facebook/actions/create-post.action.ts +224 -227
- package/src/providers/facebook/actions/get-page-insights.action.ts +383 -403
- package/src/providers/facebook/actions/get-page-posts.action.ts +214 -225
- package/src/providers/facebook/actions/get-post-insights.action.ts +300 -316
- package/src/providers/facebook/actions/respond-to-comments.action.ts +319 -336
- package/src/providers/facebook/actions/schedule-post.action.ts +289 -292
- package/src/providers/facebook/actions/search-posts.action.ts +399 -413
- package/src/providers/facebook/facebook-base.action.ts +653 -670
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +184 -189
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +160 -161
- package/src/providers/hootsuite/actions/get-analytics.action.ts +249 -254
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +206 -207
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +206 -205
- package/src/providers/hootsuite/actions/search-posts.action.ts +351 -369
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +211 -209
- package/src/providers/hootsuite/hootsuite-base.action.ts +301 -307
- package/src/providers/instagram/actions/create-post.action.ts +276 -296
- package/src/providers/instagram/actions/create-story.action.ts +378 -394
- package/src/providers/instagram/actions/get-account-insights.action.ts +384 -420
- package/src/providers/instagram/actions/get-business-posts.action.ts +233 -242
- package/src/providers/instagram/actions/get-comments.action.ts +365 -377
- package/src/providers/instagram/actions/get-post-insights.action.ts +265 -273
- package/src/providers/instagram/actions/schedule-post.action.ts +233 -235
- package/src/providers/instagram/actions/search-posts.action.ts +512 -538
- package/src/providers/instagram/instagram-base.action.ts +368 -393
- package/src/providers/linkedin/actions/create-article.action.ts +275 -266
- package/src/providers/linkedin/actions/create-post.action.ts +179 -177
- package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +146 -147
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +138 -139
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +190 -189
- package/src/providers/linkedin/actions/schedule-post.action.ts +191 -189
- package/src/providers/linkedin/actions/search-posts.action.ts +275 -283
- package/src/providers/linkedin/linkedin-base.action.ts +407 -421
- package/src/providers/tiktok/tiktok-base.action.ts +305 -320
- package/src/providers/twitter/actions/create-thread.action.ts +203 -207
- package/src/providers/twitter/actions/create-tweet.action.ts +187 -188
- package/src/providers/twitter/actions/delete-tweet.action.ts +128 -129
- package/src/providers/twitter/actions/get-analytics.action.ts +402 -411
- package/src/providers/twitter/actions/get-mentions.action.ts +218 -219
- package/src/providers/twitter/actions/get-timeline.action.ts +232 -233
- package/src/providers/twitter/actions/schedule-tweet.action.ts +221 -222
- package/src/providers/twitter/actions/search-tweets.action.ts +540 -543
- package/src/providers/twitter/twitter-base.action.ts +541 -560
- package/src/providers/youtube/youtube-base.action.ts +320 -333
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RegisterClass } from '@memberjunction/global';
|
|
2
2
|
import { InstagramBaseAction } from '../instagram-base.action';
|
|
3
3
|
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
|
|
4
|
-
import { LogError } from '@memberjunction/
|
|
4
|
+
import { LogError } from '@memberjunction/global';
|
|
5
5
|
import { BaseAction } from '@memberjunction/actions';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -10,387 +10,375 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
10
10
|
*/
|
|
11
11
|
@RegisterClass(BaseAction, 'Instagram - Get Comments')
|
|
12
12
|
export class InstagramGetCommentsAction extends InstagramBaseAction {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
ResultCode: 'AUTH_FAILED'
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Validate inputs
|
|
33
|
-
if (!postId) {
|
|
34
|
-
return {
|
|
35
|
-
Success: false,
|
|
36
|
-
Message: 'PostID is required',
|
|
37
|
-
ResultCode: 'MISSING_PARAMS'
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Build fields for comment data
|
|
42
|
-
const fields = 'id,text,username,timestamp,like_count,replies{id,text,username,timestamp,like_count}';
|
|
43
|
-
|
|
44
|
-
// Build query parameters
|
|
45
|
-
const queryParams: any = {
|
|
46
|
-
fields,
|
|
47
|
-
access_token: this.getAccessToken(),
|
|
48
|
-
limit: Math.min(limit, 100)
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
if (afterCursor) {
|
|
52
|
-
queryParams.after = afterCursor;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Get comments
|
|
56
|
-
const response = await this.makeInstagramRequest<{
|
|
57
|
-
data: any[];
|
|
58
|
-
paging?: {
|
|
59
|
-
cursors: {
|
|
60
|
-
before: string;
|
|
61
|
-
after: string;
|
|
62
|
-
};
|
|
63
|
-
next?: string;
|
|
64
|
-
};
|
|
65
|
-
}>(
|
|
66
|
-
`${postId}/comments`,
|
|
67
|
-
'GET',
|
|
68
|
-
null,
|
|
69
|
-
queryParams
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const comments = response.data || [];
|
|
73
|
-
|
|
74
|
-
// Process comments
|
|
75
|
-
const processedComments = await this.processComments(comments, includeReplies);
|
|
76
|
-
|
|
77
|
-
// Get hidden comments if requested
|
|
78
|
-
let hiddenComments: any[] = [];
|
|
79
|
-
if (includeHidden) {
|
|
80
|
-
hiddenComments = await this.getHiddenComments(postId);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Calculate engagement metrics
|
|
84
|
-
const metrics = this.calculateCommentMetrics(processedComments);
|
|
85
|
-
|
|
86
|
-
// Analyze sentiment patterns
|
|
87
|
-
const sentimentAnalysis = this.analyzeSentiment(processedComments);
|
|
88
|
-
|
|
89
|
-
// Store result in output params
|
|
90
|
-
const outputParams = [...params.Params];
|
|
91
|
-
outputParams.push({
|
|
92
|
-
Name: 'ResultData',
|
|
93
|
-
Type: 'Output',
|
|
94
|
-
Value: JSON.stringify({
|
|
95
|
-
postId,
|
|
96
|
-
comments: processedComments,
|
|
97
|
-
hiddenComments,
|
|
98
|
-
metrics,
|
|
99
|
-
sentimentAnalysis,
|
|
100
|
-
paging: {
|
|
101
|
-
hasNext: !!response.paging?.next,
|
|
102
|
-
afterCursor: response.paging?.cursors?.after
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
Success: true,
|
|
109
|
-
Message: `Retrieved ${processedComments.length} comments`,
|
|
110
|
-
ResultCode: 'SUCCESS',
|
|
111
|
-
Params: outputParams
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
} catch (error: any) {
|
|
115
|
-
LogError('Failed to retrieve Instagram comments', error);
|
|
116
|
-
|
|
117
|
-
if (error.code === 'RATE_LIMIT') {
|
|
118
|
-
return {
|
|
119
|
-
Success: false,
|
|
120
|
-
Message: 'Instagram API rate limit exceeded. Please try again later.',
|
|
121
|
-
ResultCode: 'RATE_LIMIT'
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (error.code === 'POST_NOT_FOUND') {
|
|
126
|
-
return {
|
|
127
|
-
Success: false,
|
|
128
|
-
Message: 'Instagram post not found or access denied',
|
|
129
|
-
ResultCode: 'POST_NOT_FOUND'
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
Success: false,
|
|
135
|
-
Message: `Failed to retrieve comments: ${error.message}`,
|
|
136
|
-
ResultCode: 'ERROR'
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Process comments and fetch replies if needed
|
|
143
|
-
*/
|
|
144
|
-
private async processComments(comments: any[], includeReplies: boolean): Promise<any[]> {
|
|
145
|
-
const processed: any[] = [];
|
|
146
|
-
|
|
147
|
-
for (const comment of comments) {
|
|
148
|
-
const processedComment: any = {
|
|
149
|
-
id: comment.id,
|
|
150
|
-
text: comment.text,
|
|
151
|
-
username: comment.username,
|
|
152
|
-
timestamp: comment.timestamp,
|
|
153
|
-
likeCount: comment.like_count || 0,
|
|
154
|
-
replies: [],
|
|
155
|
-
metrics: {
|
|
156
|
-
wordCount: this.countWords(comment.text),
|
|
157
|
-
hasEmojis: this.containsEmojis(comment.text),
|
|
158
|
-
hasMentions: this.containsMentions(comment.text),
|
|
159
|
-
hasHashtags: this.containsHashtags(comment.text)
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
// Process replies if they exist and are requested
|
|
164
|
-
if (includeReplies && comment.replies?.data) {
|
|
165
|
-
processedComment.replies = comment.replies.data.map((reply: any) => ({
|
|
166
|
-
id: reply.id,
|
|
167
|
-
text: reply.text,
|
|
168
|
-
username: reply.username,
|
|
169
|
-
timestamp: reply.timestamp,
|
|
170
|
-
likeCount: reply.like_count || 0,
|
|
171
|
-
metrics: {
|
|
172
|
-
wordCount: this.countWords(reply.text),
|
|
173
|
-
hasEmojis: this.containsEmojis(reply.text),
|
|
174
|
-
hasMentions: this.containsMentions(reply.text),
|
|
175
|
-
hasHashtags: this.containsHashtags(reply.text)
|
|
176
|
-
}
|
|
177
|
-
}));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
processed.push(processedComment);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return processed;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Get hidden comments (comments hidden by the account)
|
|
188
|
-
*/
|
|
189
|
-
private async getHiddenComments(postId: string): Promise<any[]> {
|
|
190
|
-
try {
|
|
191
|
-
const response = await this.makeInstagramRequest<{ data: any[] }>(
|
|
192
|
-
`${postId}/comments`,
|
|
193
|
-
'GET',
|
|
194
|
-
null,
|
|
195
|
-
{
|
|
196
|
-
fields: 'id,text,username,timestamp,hidden',
|
|
197
|
-
access_token: this.getAccessToken(),
|
|
198
|
-
filter: 'hidden'
|
|
199
|
-
}
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
return response.data || [];
|
|
203
|
-
} catch (error) {
|
|
204
|
-
LogError('Failed to get hidden comments', error);
|
|
205
|
-
return [];
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Calculate comment metrics
|
|
211
|
-
*/
|
|
212
|
-
private calculateCommentMetrics(comments: any[]): any {
|
|
213
|
-
const metrics = {
|
|
214
|
-
totalComments: comments.length,
|
|
215
|
-
totalReplies: 0,
|
|
216
|
-
avgCommentLength: 0,
|
|
217
|
-
avgLikesPerComment: 0,
|
|
218
|
-
topCommenters: [] as any[],
|
|
219
|
-
engagementRate: 0,
|
|
220
|
-
responseRate: 0
|
|
13
|
+
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
14
|
+
try {
|
|
15
|
+
const companyIntegrationId = this.getParamValue(params.Params, 'CompanyIntegrationID');
|
|
16
|
+
const postId = this.getParamValue(params.Params, 'PostID');
|
|
17
|
+
const includeReplies = this.getParamValue(params.Params, 'IncludeReplies') !== false;
|
|
18
|
+
const includeHidden = this.getParamValue(params.Params, 'IncludeHidden') || false;
|
|
19
|
+
const limit = this.getParamValue(params.Params, 'Limit') || 50;
|
|
20
|
+
const afterCursor = this.getParamValue(params.Params, 'AfterCursor');
|
|
21
|
+
|
|
22
|
+
// Initialize OAuth
|
|
23
|
+
if (!(await this.initializeOAuth(companyIntegrationId))) {
|
|
24
|
+
return {
|
|
25
|
+
Success: false,
|
|
26
|
+
Message: 'Failed to initialize Instagram authentication',
|
|
27
|
+
ResultCode: 'AUTH_FAILED',
|
|
221
28
|
};
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
totalLength += comment.metrics.wordCount;
|
|
231
|
-
totalLikes += comment.likeCount;
|
|
232
|
-
|
|
233
|
-
// Count commenters
|
|
234
|
-
commenterCounts[comment.username] = (commenterCounts[comment.username] || 0) + 1;
|
|
235
|
-
|
|
236
|
-
// Count replies
|
|
237
|
-
metrics.totalReplies += comment.replies.length;
|
|
238
|
-
|
|
239
|
-
// Add reply stats
|
|
240
|
-
comment.replies.forEach((reply: any) => {
|
|
241
|
-
totalLength += reply.metrics.wordCount;
|
|
242
|
-
totalLikes += reply.likeCount;
|
|
243
|
-
commenterCounts[reply.username] = (commenterCounts[reply.username] || 0) + 1;
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
const totalInteractions = comments.length + metrics.totalReplies;
|
|
248
|
-
metrics.avgCommentLength = Math.round(totalLength / totalInteractions);
|
|
249
|
-
metrics.avgLikesPerComment = Math.round(totalLikes / totalInteractions);
|
|
250
|
-
|
|
251
|
-
// Get top commenters
|
|
252
|
-
metrics.topCommenters = Object.entries(commenterCounts)
|
|
253
|
-
.sort(([, a], [, b]) => b - a)
|
|
254
|
-
.slice(0, 10)
|
|
255
|
-
.map(([username, count]) => ({ username, count }));
|
|
256
|
-
|
|
257
|
-
// Calculate response rate (comments with replies)
|
|
258
|
-
const commentsWithReplies = comments.filter(c => c.replies.length > 0).length;
|
|
259
|
-
metrics.responseRate = (commentsWithReplies / comments.length) * 100;
|
|
260
|
-
|
|
261
|
-
return metrics;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Analyze sentiment patterns in comments
|
|
266
|
-
*/
|
|
267
|
-
private analyzeSentiment(comments: any[]): any {
|
|
268
|
-
const analysis = {
|
|
269
|
-
positive: 0,
|
|
270
|
-
negative: 0,
|
|
271
|
-
neutral: 0,
|
|
272
|
-
questions: 0,
|
|
273
|
-
keywords: [] as any[],
|
|
274
|
-
emojis: [] as any[]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Validate inputs
|
|
32
|
+
if (!postId) {
|
|
33
|
+
return {
|
|
34
|
+
Success: false,
|
|
35
|
+
Message: 'PostID is required',
|
|
36
|
+
ResultCode: 'MISSING_PARAMS',
|
|
275
37
|
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Build fields for comment data
|
|
41
|
+
const fields = 'id,text,username,timestamp,like_count,replies{id,text,username,timestamp,like_count}';
|
|
42
|
+
|
|
43
|
+
// Build query parameters
|
|
44
|
+
const queryParams: any = {
|
|
45
|
+
fields,
|
|
46
|
+
access_token: this.getAccessToken(),
|
|
47
|
+
limit: Math.min(limit, 100),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (afterCursor) {
|
|
51
|
+
queryParams.after = afterCursor;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Get comments
|
|
55
|
+
const response = await this.makeInstagramRequest<{
|
|
56
|
+
data: any[];
|
|
57
|
+
paging?: {
|
|
58
|
+
cursors: {
|
|
59
|
+
before: string;
|
|
60
|
+
after: string;
|
|
61
|
+
};
|
|
62
|
+
next?: string;
|
|
63
|
+
};
|
|
64
|
+
}>(`${postId}/comments`, 'GET', null, queryParams);
|
|
65
|
+
|
|
66
|
+
const comments = response.data || [];
|
|
67
|
+
|
|
68
|
+
// Process comments
|
|
69
|
+
const processedComments = await this.processComments(comments, includeReplies);
|
|
70
|
+
|
|
71
|
+
// Get hidden comments if requested
|
|
72
|
+
let hiddenComments: any[] = [];
|
|
73
|
+
if (includeHidden) {
|
|
74
|
+
hiddenComments = await this.getHiddenComments(postId);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Calculate engagement metrics
|
|
78
|
+
const metrics = this.calculateCommentMetrics(processedComments);
|
|
79
|
+
|
|
80
|
+
// Analyze sentiment patterns
|
|
81
|
+
const sentimentAnalysis = this.analyzeSentiment(processedComments);
|
|
82
|
+
|
|
83
|
+
// Store result in output params
|
|
84
|
+
const outputParams = [...params.Params];
|
|
85
|
+
outputParams.push({
|
|
86
|
+
Name: 'ResultData',
|
|
87
|
+
Type: 'Output',
|
|
88
|
+
Value: JSON.stringify({
|
|
89
|
+
postId,
|
|
90
|
+
comments: processedComments,
|
|
91
|
+
hiddenComments,
|
|
92
|
+
metrics,
|
|
93
|
+
sentimentAnalysis,
|
|
94
|
+
paging: {
|
|
95
|
+
hasNext: !!response.paging?.next,
|
|
96
|
+
afterCursor: response.paging?.cursors?.after,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
Success: true,
|
|
103
|
+
Message: `Retrieved ${processedComments.length} comments`,
|
|
104
|
+
ResultCode: 'SUCCESS',
|
|
105
|
+
Params: outputParams,
|
|
106
|
+
};
|
|
107
|
+
} catch (error: any) {
|
|
108
|
+
LogError('Failed to retrieve Instagram comments', error);
|
|
109
|
+
|
|
110
|
+
if (error.code === 'RATE_LIMIT') {
|
|
111
|
+
return {
|
|
112
|
+
Success: false,
|
|
113
|
+
Message: 'Instagram API rate limit exceeded. Please try again later.',
|
|
114
|
+
ResultCode: 'RATE_LIMIT',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
276
117
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
comments.forEach(comment => {
|
|
286
|
-
const text = comment.text.toLowerCase();
|
|
287
|
-
|
|
288
|
-
// Check sentiment
|
|
289
|
-
const hasPositive = positiveWords.some(word => text.includes(word));
|
|
290
|
-
const hasNegative = negativeWords.some(word => text.includes(word));
|
|
291
|
-
const hasQuestion = questionWords.some(word => text.includes(word));
|
|
292
|
-
|
|
293
|
-
if (hasQuestion) {
|
|
294
|
-
analysis.questions++;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (hasPositive && !hasNegative) {
|
|
298
|
-
analysis.positive++;
|
|
299
|
-
} else if (hasNegative && !hasPositive) {
|
|
300
|
-
analysis.negative++;
|
|
301
|
-
} else {
|
|
302
|
-
analysis.neutral++;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Extract keywords (simple word frequency)
|
|
306
|
-
const words = text.split(/\s+/).filter(word => word.length > 3);
|
|
307
|
-
words.forEach(word => {
|
|
308
|
-
keywordCounts[word] = (keywordCounts[word] || 0) + 1;
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
// Extract emojis
|
|
312
|
-
const emojis = text.match(/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]/gu) || [];
|
|
313
|
-
emojis.forEach(emoji => {
|
|
314
|
-
emojiCounts[emoji] = (emojiCounts[emoji] || 0) + 1;
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
// Analyze replies too
|
|
318
|
-
comment.replies.forEach((reply: any) => {
|
|
319
|
-
// Similar analysis for replies...
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
// Get top keywords and emojis
|
|
324
|
-
analysis.keywords = Object.entries(keywordCounts)
|
|
325
|
-
.sort(([, a], [, b]) => b - a)
|
|
326
|
-
.slice(0, 20)
|
|
327
|
-
.map(([keyword, count]) => ({ keyword, count }));
|
|
328
|
-
|
|
329
|
-
analysis.emojis = Object.entries(emojiCounts)
|
|
330
|
-
.sort(([, a], [, b]) => b - a)
|
|
331
|
-
.slice(0, 10)
|
|
332
|
-
.map(([emoji, count]) => ({ emoji, count }));
|
|
333
|
-
|
|
334
|
-
return analysis;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Helper methods for text analysis
|
|
339
|
-
*/
|
|
340
|
-
private countWords(text: string): number {
|
|
341
|
-
return text.trim().split(/\s+/).length;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
private containsEmojis(text: string): boolean {
|
|
345
|
-
return /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]/u.test(text);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
private containsMentions(text: string): boolean {
|
|
349
|
-
return /@\w+/.test(text);
|
|
350
|
-
}
|
|
118
|
+
if (error.code === 'POST_NOT_FOUND') {
|
|
119
|
+
return {
|
|
120
|
+
Success: false,
|
|
121
|
+
Message: 'Instagram post not found or access denied',
|
|
122
|
+
ResultCode: 'POST_NOT_FOUND',
|
|
123
|
+
};
|
|
124
|
+
}
|
|
351
125
|
|
|
352
|
-
|
|
353
|
-
|
|
126
|
+
return {
|
|
127
|
+
Success: false,
|
|
128
|
+
Message: `Failed to retrieve comments: ${error.message}`,
|
|
129
|
+
ResultCode: 'ERROR',
|
|
130
|
+
};
|
|
354
131
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Process comments and fetch replies if needed
|
|
136
|
+
*/
|
|
137
|
+
private async processComments(comments: any[], includeReplies: boolean): Promise<any[]> {
|
|
138
|
+
const processed: any[] = [];
|
|
139
|
+
|
|
140
|
+
for (const comment of comments) {
|
|
141
|
+
const processedComment: any = {
|
|
142
|
+
id: comment.id,
|
|
143
|
+
text: comment.text,
|
|
144
|
+
username: comment.username,
|
|
145
|
+
timestamp: comment.timestamp,
|
|
146
|
+
likeCount: comment.like_count || 0,
|
|
147
|
+
replies: [],
|
|
148
|
+
metrics: {
|
|
149
|
+
wordCount: this.countWords(comment.text),
|
|
150
|
+
hasEmojis: this.containsEmojis(comment.text),
|
|
151
|
+
hasMentions: this.containsMentions(comment.text),
|
|
152
|
+
hasHashtags: this.containsHashtags(comment.text),
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Process replies if they exist and are requested
|
|
157
|
+
if (includeReplies && comment.replies?.data) {
|
|
158
|
+
processedComment.replies = comment.replies.data.map((reply: any) => ({
|
|
159
|
+
id: reply.id,
|
|
160
|
+
text: reply.text,
|
|
161
|
+
username: reply.username,
|
|
162
|
+
timestamp: reply.timestamp,
|
|
163
|
+
likeCount: reply.like_count || 0,
|
|
164
|
+
metrics: {
|
|
165
|
+
wordCount: this.countWords(reply.text),
|
|
166
|
+
hasEmojis: this.containsEmojis(reply.text),
|
|
167
|
+
hasMentions: this.containsMentions(reply.text),
|
|
168
|
+
hasHashtags: this.containsHashtags(reply.text),
|
|
169
|
+
},
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
processed.push(processedComment);
|
|
388
174
|
}
|
|
389
175
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
176
|
+
return processed;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get hidden comments (comments hidden by the account)
|
|
181
|
+
*/
|
|
182
|
+
private async getHiddenComments(postId: string): Promise<any[]> {
|
|
183
|
+
try {
|
|
184
|
+
const response = await this.makeInstagramRequest<{ data: any[] }>(`${postId}/comments`, 'GET', null, {
|
|
185
|
+
fields: 'id,text,username,timestamp,hidden',
|
|
186
|
+
access_token: this.getAccessToken(),
|
|
187
|
+
filter: 'hidden',
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
return response.data || [];
|
|
191
|
+
} catch (error) {
|
|
192
|
+
LogError('Failed to get hidden comments', error);
|
|
193
|
+
return [];
|
|
395
194
|
}
|
|
396
|
-
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Calculate comment metrics
|
|
199
|
+
*/
|
|
200
|
+
private calculateCommentMetrics(comments: any[]): any {
|
|
201
|
+
const metrics = {
|
|
202
|
+
totalComments: comments.length,
|
|
203
|
+
totalReplies: 0,
|
|
204
|
+
avgCommentLength: 0,
|
|
205
|
+
avgLikesPerComment: 0,
|
|
206
|
+
topCommenters: [] as any[],
|
|
207
|
+
engagementRate: 0,
|
|
208
|
+
responseRate: 0,
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
if (comments.length === 0) return metrics;
|
|
212
|
+
|
|
213
|
+
let totalLength = 0;
|
|
214
|
+
let totalLikes = 0;
|
|
215
|
+
const commenterCounts: Record<string, number> = {};
|
|
216
|
+
|
|
217
|
+
comments.forEach((comment) => {
|
|
218
|
+
totalLength += comment.metrics.wordCount;
|
|
219
|
+
totalLikes += comment.likeCount;
|
|
220
|
+
|
|
221
|
+
// Count commenters
|
|
222
|
+
commenterCounts[comment.username] = (commenterCounts[comment.username] || 0) + 1;
|
|
223
|
+
|
|
224
|
+
// Count replies
|
|
225
|
+
metrics.totalReplies += comment.replies.length;
|
|
226
|
+
|
|
227
|
+
// Add reply stats
|
|
228
|
+
comment.replies.forEach((reply: any) => {
|
|
229
|
+
totalLength += reply.metrics.wordCount;
|
|
230
|
+
totalLikes += reply.likeCount;
|
|
231
|
+
commenterCounts[reply.username] = (commenterCounts[reply.username] || 0) + 1;
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const totalInteractions = comments.length + metrics.totalReplies;
|
|
236
|
+
metrics.avgCommentLength = Math.round(totalLength / totalInteractions);
|
|
237
|
+
metrics.avgLikesPerComment = Math.round(totalLikes / totalInteractions);
|
|
238
|
+
|
|
239
|
+
// Get top commenters
|
|
240
|
+
metrics.topCommenters = Object.entries(commenterCounts)
|
|
241
|
+
.sort(([, a], [, b]) => b - a)
|
|
242
|
+
.slice(0, 10)
|
|
243
|
+
.map(([username, count]) => ({ username, count }));
|
|
244
|
+
|
|
245
|
+
// Calculate response rate (comments with replies)
|
|
246
|
+
const commentsWithReplies = comments.filter((c) => c.replies.length > 0).length;
|
|
247
|
+
metrics.responseRate = (commentsWithReplies / comments.length) * 100;
|
|
248
|
+
|
|
249
|
+
return metrics;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Analyze sentiment patterns in comments
|
|
254
|
+
*/
|
|
255
|
+
private analyzeSentiment(comments: any[]): any {
|
|
256
|
+
const analysis = {
|
|
257
|
+
positive: 0,
|
|
258
|
+
negative: 0,
|
|
259
|
+
neutral: 0,
|
|
260
|
+
questions: 0,
|
|
261
|
+
keywords: [] as any[],
|
|
262
|
+
emojis: [] as any[],
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const keywordCounts: Record<string, number> = {};
|
|
266
|
+
const emojiCounts: Record<string, number> = {};
|
|
267
|
+
|
|
268
|
+
// Simple sentiment analysis based on keywords and patterns
|
|
269
|
+
const positiveWords = ['love', 'amazing', 'beautiful', 'great', 'awesome', 'perfect', 'excellent', 'wonderful', '❤️', '😍', '🔥', '💯'];
|
|
270
|
+
const negativeWords = ['hate', 'awful', 'terrible', 'bad', 'worst', 'ugly', 'disgusting', '😠', '😡', '👎'];
|
|
271
|
+
const questionWords = ['?', 'what', 'where', 'when', 'how', 'why', 'who'];
|
|
272
|
+
|
|
273
|
+
comments.forEach((comment) => {
|
|
274
|
+
const text = comment.text.toLowerCase();
|
|
275
|
+
|
|
276
|
+
// Check sentiment
|
|
277
|
+
const hasPositive = positiveWords.some((word) => text.includes(word));
|
|
278
|
+
const hasNegative = negativeWords.some((word) => text.includes(word));
|
|
279
|
+
const hasQuestion = questionWords.some((word) => text.includes(word));
|
|
280
|
+
|
|
281
|
+
if (hasQuestion) {
|
|
282
|
+
analysis.questions++;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (hasPositive && !hasNegative) {
|
|
286
|
+
analysis.positive++;
|
|
287
|
+
} else if (hasNegative && !hasPositive) {
|
|
288
|
+
analysis.negative++;
|
|
289
|
+
} else {
|
|
290
|
+
analysis.neutral++;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Extract keywords (simple word frequency)
|
|
294
|
+
const words = text.split(/\s+/).filter((word) => word.length > 3);
|
|
295
|
+
words.forEach((word) => {
|
|
296
|
+
keywordCounts[word] = (keywordCounts[word] || 0) + 1;
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Extract emojis
|
|
300
|
+
const emojis = text.match(/[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]/gu) || [];
|
|
301
|
+
emojis.forEach((emoji) => {
|
|
302
|
+
emojiCounts[emoji] = (emojiCounts[emoji] || 0) + 1;
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// Analyze replies too
|
|
306
|
+
comment.replies.forEach((reply: any) => {
|
|
307
|
+
// Similar analysis for replies...
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Get top keywords and emojis
|
|
312
|
+
analysis.keywords = Object.entries(keywordCounts)
|
|
313
|
+
.sort(([, a], [, b]) => b - a)
|
|
314
|
+
.slice(0, 20)
|
|
315
|
+
.map(([keyword, count]) => ({ keyword, count }));
|
|
316
|
+
|
|
317
|
+
analysis.emojis = Object.entries(emojiCounts)
|
|
318
|
+
.sort(([, a], [, b]) => b - a)
|
|
319
|
+
.slice(0, 10)
|
|
320
|
+
.map(([emoji, count]) => ({ emoji, count }));
|
|
321
|
+
|
|
322
|
+
return analysis;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Helper methods for text analysis
|
|
327
|
+
*/
|
|
328
|
+
private countWords(text: string): number {
|
|
329
|
+
return text.trim().split(/\s+/).length;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
private containsEmojis(text: string): boolean {
|
|
333
|
+
return /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]/u.test(text);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
private containsMentions(text: string): boolean {
|
|
337
|
+
return /@\w+/.test(text);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private containsHashtags(text: string): boolean {
|
|
341
|
+
return /#\w+/.test(text);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Define the parameters for this action
|
|
346
|
+
*/
|
|
347
|
+
public get Params(): ActionParam[] {
|
|
348
|
+
return [
|
|
349
|
+
...this.commonSocialParams,
|
|
350
|
+
{
|
|
351
|
+
Name: 'PostID',
|
|
352
|
+
Type: 'Input',
|
|
353
|
+
Value: null,
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
Name: 'IncludeReplies',
|
|
357
|
+
Type: 'Input',
|
|
358
|
+
Value: true,
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
Name: 'IncludeHidden',
|
|
362
|
+
Type: 'Input',
|
|
363
|
+
Value: false,
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
Name: 'Limit',
|
|
367
|
+
Type: 'Input',
|
|
368
|
+
Value: 50,
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
Name: 'AfterCursor',
|
|
372
|
+
Type: 'Input',
|
|
373
|
+
Value: null,
|
|
374
|
+
},
|
|
375
|
+
];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Get the description for this action
|
|
380
|
+
*/
|
|
381
|
+
public get Description(): string {
|
|
382
|
+
return 'Retrieves comments for an Instagram post including replies, metrics, and sentiment analysis.';
|
|
383
|
+
}
|
|
384
|
+
}
|