@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 { MediaFile } from '../../../base/base-social.action';
|
|
6
6
|
import { BaseAction } from '@memberjunction/actions';
|
|
7
7
|
|
|
@@ -11,320 +11,300 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
11
11
|
*/
|
|
12
12
|
@RegisterClass(BaseAction, 'Instagram - Create Post')
|
|
13
13
|
export class InstagramCreatePostAction extends InstagramBaseAction {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
ResultCode: 'AUTH_FAILED'
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Validate inputs
|
|
35
|
-
if (!mediaFiles || mediaFiles.length === 0) {
|
|
36
|
-
return {
|
|
37
|
-
Success: false,
|
|
38
|
-
Message: 'At least one media file is required for Instagram posts',
|
|
39
|
-
ResultCode: 'MISSING_MEDIA'
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Instagram has specific requirements for different post types
|
|
44
|
-
if (postType === 'CAROUSEL' && mediaFiles.length < 2) {
|
|
45
|
-
return {
|
|
46
|
-
Success: false,
|
|
47
|
-
Message: 'Carousel posts require at least 2 media files',
|
|
48
|
-
ResultCode: 'INVALID_CAROUSEL'
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (postType === 'REELS' && (!mediaFiles[0].mimeType.startsWith('video/') || mediaFiles.length > 1)) {
|
|
53
|
-
return {
|
|
54
|
-
Success: false,
|
|
55
|
-
Message: 'Reels require exactly one video file',
|
|
56
|
-
ResultCode: 'INVALID_REEL'
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Handle scheduled posts differently
|
|
61
|
-
if (scheduledTime) {
|
|
62
|
-
const scheduleDate = new Date(scheduledTime);
|
|
63
|
-
if (scheduleDate <= new Date()) {
|
|
64
|
-
return {
|
|
65
|
-
Success: false,
|
|
66
|
-
Message: 'Scheduled time must be in the future',
|
|
67
|
-
ResultCode: 'INVALID_SCHEDULE_TIME'
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Instagram requires Facebook Creator Studio for scheduling
|
|
72
|
-
return {
|
|
73
|
-
Success: false,
|
|
74
|
-
Message: 'Instagram post scheduling requires Facebook Creator Studio integration',
|
|
75
|
-
ResultCode: 'SCHEDULING_NOT_SUPPORTED'
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
let postId: string;
|
|
80
|
-
|
|
81
|
-
if (postType === 'CAROUSEL') {
|
|
82
|
-
postId = await this.createCarouselPost(mediaFiles, content, locationId, taggedUsers);
|
|
83
|
-
} else if (postType === 'REELS') {
|
|
84
|
-
postId = await this.createReelPost(mediaFiles[0], content, locationId, taggedUsers);
|
|
85
|
-
} else {
|
|
86
|
-
postId = await this.createFeedPost(mediaFiles[0], content, locationId, taggedUsers);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Store result in output params
|
|
90
|
-
const outputParams = [...params.Params];
|
|
91
|
-
outputParams.push({
|
|
92
|
-
Name: 'PostID',
|
|
93
|
-
Type: 'Output',
|
|
94
|
-
Value: postId
|
|
95
|
-
});
|
|
96
|
-
outputParams.push({
|
|
97
|
-
Name: 'Permalink',
|
|
98
|
-
Type: 'Output',
|
|
99
|
-
Value: `https://www.instagram.com/p/${postId}/`
|
|
100
|
-
});
|
|
101
|
-
outputParams.push({
|
|
102
|
-
Name: 'PostType',
|
|
103
|
-
Type: 'Output',
|
|
104
|
-
Value: postType
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
Success: true,
|
|
109
|
-
Message: `Instagram ${postType.toLowerCase()} created successfully`,
|
|
110
|
-
ResultCode: 'SUCCESS',
|
|
111
|
-
Params: outputParams
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
} catch (error: any) {
|
|
115
|
-
LogError('Failed to create Instagram post', 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 === 'INVALID_MEDIA') {
|
|
126
|
-
return {
|
|
127
|
-
Success: false,
|
|
128
|
-
Message: error.message,
|
|
129
|
-
ResultCode: 'INVALID_MEDIA'
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
Success: false,
|
|
135
|
-
Message: `Failed to create Instagram post: ${error.message}`,
|
|
136
|
-
ResultCode: 'ERROR'
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Create a standard feed post (single image or video)
|
|
143
|
-
*/
|
|
144
|
-
private async createFeedPost(
|
|
145
|
-
mediaFile: MediaFile,
|
|
146
|
-
caption: string,
|
|
147
|
-
locationId?: string,
|
|
148
|
-
taggedUsers?: string[]
|
|
149
|
-
): Promise<string> {
|
|
150
|
-
// Add metadata to media file
|
|
151
|
-
(mediaFile as any).metadata = { caption };
|
|
152
|
-
|
|
153
|
-
// Upload media and get container ID
|
|
154
|
-
const containerId = await this.uploadSingleMedia(mediaFile);
|
|
155
|
-
|
|
156
|
-
// Wait for media to be processed
|
|
157
|
-
await this.waitForMediaContainer(containerId);
|
|
158
|
-
|
|
159
|
-
// Add additional parameters if provided
|
|
160
|
-
const publishParams: any = {
|
|
161
|
-
creation_id: containerId,
|
|
162
|
-
access_token: this.getAccessToken()
|
|
14
|
+
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
15
|
+
try {
|
|
16
|
+
const companyIntegrationId = this.getParamValue(params.Params, 'CompanyIntegrationID');
|
|
17
|
+
const content = this.getParamValue(params.Params, 'Content');
|
|
18
|
+
const mediaFiles = this.getParamValue(params.Params, 'MediaFiles') as MediaFile[];
|
|
19
|
+
const postType = this.getParamValue(params.Params, 'PostType') || 'FEED';
|
|
20
|
+
const locationId = this.getParamValue(params.Params, 'LocationID');
|
|
21
|
+
const taggedUsers = this.getParamValue(params.Params, 'TaggedUsers') as string[];
|
|
22
|
+
const scheduledTime = this.getParamValue(params.Params, 'ScheduledTime');
|
|
23
|
+
|
|
24
|
+
// Initialize OAuth
|
|
25
|
+
if (!(await this.initializeOAuth(companyIntegrationId))) {
|
|
26
|
+
return {
|
|
27
|
+
Success: false,
|
|
28
|
+
Message: 'Failed to initialize Instagram authentication',
|
|
29
|
+
ResultCode: 'AUTH_FAILED',
|
|
163
30
|
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Validate inputs
|
|
34
|
+
if (!mediaFiles || mediaFiles.length === 0) {
|
|
35
|
+
return {
|
|
36
|
+
Success: false,
|
|
37
|
+
Message: 'At least one media file is required for Instagram posts',
|
|
38
|
+
ResultCode: 'MISSING_MEDIA',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Instagram has specific requirements for different post types
|
|
43
|
+
if (postType === 'CAROUSEL' && mediaFiles.length < 2) {
|
|
44
|
+
return {
|
|
45
|
+
Success: false,
|
|
46
|
+
Message: 'Carousel posts require at least 2 media files',
|
|
47
|
+
ResultCode: 'INVALID_CAROUSEL',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
164
50
|
|
|
165
|
-
|
|
166
|
-
|
|
51
|
+
if (postType === 'REELS' && (!mediaFiles[0].mimeType.startsWith('video/') || mediaFiles.length > 1)) {
|
|
52
|
+
return {
|
|
53
|
+
Success: false,
|
|
54
|
+
Message: 'Reels require exactly one video file',
|
|
55
|
+
ResultCode: 'INVALID_REEL',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Handle scheduled posts differently
|
|
60
|
+
if (scheduledTime) {
|
|
61
|
+
const scheduleDate = new Date(scheduledTime);
|
|
62
|
+
if (scheduleDate <= new Date()) {
|
|
63
|
+
return {
|
|
64
|
+
Success: false,
|
|
65
|
+
Message: 'Scheduled time must be in the future',
|
|
66
|
+
ResultCode: 'INVALID_SCHEDULE_TIME',
|
|
67
|
+
};
|
|
167
68
|
}
|
|
168
69
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
70
|
+
// Instagram requires Facebook Creator Studio for scheduling
|
|
71
|
+
return {
|
|
72
|
+
Success: false,
|
|
73
|
+
Message: 'Instagram post scheduling requires Facebook Creator Studio integration',
|
|
74
|
+
ResultCode: 'SCHEDULING_NOT_SUPPORTED',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let postId: string;
|
|
79
|
+
|
|
80
|
+
if (postType === 'CAROUSEL') {
|
|
81
|
+
postId = await this.createCarouselPost(mediaFiles, content, locationId, taggedUsers);
|
|
82
|
+
} else if (postType === 'REELS') {
|
|
83
|
+
postId = await this.createReelPost(mediaFiles[0], content, locationId, taggedUsers);
|
|
84
|
+
} else {
|
|
85
|
+
postId = await this.createFeedPost(mediaFiles[0], content, locationId, taggedUsers);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Store result in output params
|
|
89
|
+
const outputParams = [...params.Params];
|
|
90
|
+
outputParams.push({
|
|
91
|
+
Name: 'PostID',
|
|
92
|
+
Type: 'Output',
|
|
93
|
+
Value: postId,
|
|
94
|
+
});
|
|
95
|
+
outputParams.push({
|
|
96
|
+
Name: 'Permalink',
|
|
97
|
+
Type: 'Output',
|
|
98
|
+
Value: `https://www.instagram.com/p/${postId}/`,
|
|
99
|
+
});
|
|
100
|
+
outputParams.push({
|
|
101
|
+
Name: 'PostType',
|
|
102
|
+
Type: 'Output',
|
|
103
|
+
Value: postType,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
Success: true,
|
|
108
|
+
Message: `Instagram ${postType.toLowerCase()} created successfully`,
|
|
109
|
+
ResultCode: 'SUCCESS',
|
|
110
|
+
Params: outputParams,
|
|
111
|
+
};
|
|
112
|
+
} catch (error: any) {
|
|
113
|
+
LogError('Failed to create Instagram post', error);
|
|
114
|
+
|
|
115
|
+
if (error.code === 'RATE_LIMIT') {
|
|
116
|
+
return {
|
|
117
|
+
Success: false,
|
|
118
|
+
Message: 'Instagram API rate limit exceeded. Please try again later.',
|
|
119
|
+
ResultCode: 'RATE_LIMIT',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
176
122
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
123
|
+
if (error.code === 'INVALID_MEDIA') {
|
|
124
|
+
return {
|
|
125
|
+
Success: false,
|
|
126
|
+
Message: error.message,
|
|
127
|
+
ResultCode: 'INVALID_MEDIA',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
183
130
|
|
|
184
|
-
|
|
131
|
+
return {
|
|
132
|
+
Success: false,
|
|
133
|
+
Message: `Failed to create Instagram post: ${error.message}`,
|
|
134
|
+
ResultCode: 'ERROR',
|
|
135
|
+
};
|
|
185
136
|
}
|
|
137
|
+
}
|
|
186
138
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
locationId?: string,
|
|
194
|
-
taggedUsers?: string[]
|
|
195
|
-
): Promise<string> {
|
|
196
|
-
// Upload all media items as carousel items
|
|
197
|
-
const containerIds: string[] = [];
|
|
198
|
-
|
|
199
|
-
for (const file of mediaFiles.slice(0, 10)) { // Instagram allows max 10 items
|
|
200
|
-
file.filename = `carousel_${file.filename}`; // Mark as carousel item
|
|
201
|
-
const containerId = await this.uploadSingleMedia(file);
|
|
202
|
-
containerIds.push(containerId);
|
|
203
|
-
}
|
|
139
|
+
/**
|
|
140
|
+
* Create a standard feed post (single image or video)
|
|
141
|
+
*/
|
|
142
|
+
private async createFeedPost(mediaFile: MediaFile, caption: string, locationId?: string, taggedUsers?: string[]): Promise<string> {
|
|
143
|
+
// Add metadata to media file
|
|
144
|
+
(mediaFile as any).metadata = { caption };
|
|
204
145
|
|
|
205
|
-
|
|
206
|
-
|
|
146
|
+
// Upload media and get container ID
|
|
147
|
+
const containerId = await this.uploadSingleMedia(mediaFile);
|
|
207
148
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
media_type: 'CAROUSEL',
|
|
211
|
-
children: containerIds,
|
|
212
|
-
caption: caption,
|
|
213
|
-
access_token: this.getAccessToken()
|
|
214
|
-
};
|
|
149
|
+
// Wait for media to be processed
|
|
150
|
+
await this.waitForMediaContainer(containerId);
|
|
215
151
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
152
|
+
// Add additional parameters if provided
|
|
153
|
+
const publishParams: any = {
|
|
154
|
+
creation_id: containerId,
|
|
155
|
+
access_token: this.getAccessToken(),
|
|
156
|
+
};
|
|
219
157
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
'POST',
|
|
223
|
-
carouselParams
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
// Wait for carousel container to be ready
|
|
227
|
-
await this.waitForMediaContainer(carouselResponse.id);
|
|
228
|
-
|
|
229
|
-
// Publish the carousel
|
|
230
|
-
const publishResponse = await this.makeInstagramRequest<{ id: string }>(
|
|
231
|
-
`${this.instagramBusinessAccountId}/media_publish`,
|
|
232
|
-
'POST',
|
|
233
|
-
{
|
|
234
|
-
creation_id: carouselResponse.id,
|
|
235
|
-
access_token: this.getAccessToken()
|
|
236
|
-
}
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
return publishResponse.id;
|
|
158
|
+
if (locationId) {
|
|
159
|
+
publishParams.location_id = locationId;
|
|
240
160
|
}
|
|
241
161
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
taggedUsers?: string[]
|
|
250
|
-
): Promise<string> {
|
|
251
|
-
// Validate video duration (Reels must be 90 seconds or less)
|
|
252
|
-
// In production, you'd check the actual video duration
|
|
253
|
-
|
|
254
|
-
// Add metadata
|
|
255
|
-
(videoFile as any).metadata = {
|
|
256
|
-
caption,
|
|
257
|
-
media_type: 'REELS'
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
// Upload video
|
|
261
|
-
const containerId = await this.uploadSingleMedia(videoFile);
|
|
262
|
-
|
|
263
|
-
// Wait for video to be processed (videos take longer)
|
|
264
|
-
await this.waitForMediaContainer(containerId, 300000); // 5 minute timeout for videos
|
|
162
|
+
if (taggedUsers && taggedUsers.length > 0) {
|
|
163
|
+
publishParams.user_tags = taggedUsers.map((userId) => ({
|
|
164
|
+
username: userId,
|
|
165
|
+
x: 0.5, // Center of image
|
|
166
|
+
y: 0.5,
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
265
169
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
170
|
+
// Publish the post
|
|
171
|
+
const response = await this.makeInstagramRequest<{ id: string }>(
|
|
172
|
+
`${this.instagramBusinessAccountId}/media_publish`,
|
|
173
|
+
'POST',
|
|
174
|
+
publishParams
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return response.id;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Create a carousel post (multiple images/videos)
|
|
182
|
+
*/
|
|
183
|
+
private async createCarouselPost(mediaFiles: MediaFile[], caption: string, locationId?: string, taggedUsers?: string[]): Promise<string> {
|
|
184
|
+
// Upload all media items as carousel items
|
|
185
|
+
const containerIds: string[] = [];
|
|
186
|
+
|
|
187
|
+
for (const file of mediaFiles.slice(0, 10)) {
|
|
188
|
+
// Instagram allows max 10 items
|
|
189
|
+
file.filename = `carousel_${file.filename}`; // Mark as carousel item
|
|
190
|
+
const containerId = await this.uploadSingleMedia(file);
|
|
191
|
+
containerIds.push(containerId);
|
|
192
|
+
}
|
|
271
193
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
194
|
+
// Wait for all media to be processed
|
|
195
|
+
await Promise.all(containerIds.map((id) => this.waitForMediaContainer(id)));
|
|
275
196
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
197
|
+
// Create carousel container
|
|
198
|
+
const carouselParams: any = {
|
|
199
|
+
media_type: 'CAROUSEL',
|
|
200
|
+
children: containerIds,
|
|
201
|
+
caption: caption,
|
|
202
|
+
access_token: this.getAccessToken(),
|
|
203
|
+
};
|
|
281
204
|
|
|
282
|
-
|
|
205
|
+
if (locationId) {
|
|
206
|
+
carouselParams.location_id = locationId;
|
|
283
207
|
}
|
|
284
208
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
209
|
+
const carouselResponse = await this.makeInstagramRequest<{ id: string }>(
|
|
210
|
+
`${this.instagramBusinessAccountId}/media`,
|
|
211
|
+
'POST',
|
|
212
|
+
carouselParams
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
// Wait for carousel container to be ready
|
|
216
|
+
await this.waitForMediaContainer(carouselResponse.id);
|
|
217
|
+
|
|
218
|
+
// Publish the carousel
|
|
219
|
+
const publishResponse = await this.makeInstagramRequest<{ id: string }>(`${this.instagramBusinessAccountId}/media_publish`, 'POST', {
|
|
220
|
+
creation_id: carouselResponse.id,
|
|
221
|
+
access_token: this.getAccessToken(),
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return publishResponse.id;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Create a Reel post
|
|
229
|
+
*/
|
|
230
|
+
private async createReelPost(videoFile: MediaFile, caption: string, locationId?: string, taggedUsers?: string[]): Promise<string> {
|
|
231
|
+
// Validate video duration (Reels must be 90 seconds or less)
|
|
232
|
+
// In production, you'd check the actual video duration
|
|
233
|
+
|
|
234
|
+
// Add metadata
|
|
235
|
+
(videoFile as any).metadata = {
|
|
236
|
+
caption,
|
|
237
|
+
media_type: 'REELS',
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// Upload video
|
|
241
|
+
const containerId = await this.uploadSingleMedia(videoFile);
|
|
242
|
+
|
|
243
|
+
// Wait for video to be processed (videos take longer)
|
|
244
|
+
await this.waitForMediaContainer(containerId, 300000); // 5 minute timeout for videos
|
|
245
|
+
|
|
246
|
+
// Publish the reel
|
|
247
|
+
const publishParams: any = {
|
|
248
|
+
creation_id: containerId,
|
|
249
|
+
access_token: this.getAccessToken(),
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
if (locationId) {
|
|
253
|
+
publishParams.location_id = locationId;
|
|
322
254
|
}
|
|
323
255
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
256
|
+
const response = await this.makeInstagramRequest<{ id: string }>(
|
|
257
|
+
`${this.instagramBusinessAccountId}/media_publish`,
|
|
258
|
+
'POST',
|
|
259
|
+
publishParams
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
return response.id;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Define the parameters for this action
|
|
267
|
+
*/
|
|
268
|
+
public get Params(): ActionParam[] {
|
|
269
|
+
return [
|
|
270
|
+
...this.commonSocialParams,
|
|
271
|
+
{
|
|
272
|
+
Name: 'Content',
|
|
273
|
+
Type: 'Input',
|
|
274
|
+
Value: null,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
Name: 'MediaFiles',
|
|
278
|
+
Type: 'Input',
|
|
279
|
+
Value: null,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
Name: 'PostType',
|
|
283
|
+
Type: 'Input',
|
|
284
|
+
Value: 'FEED',
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
Name: 'LocationID',
|
|
288
|
+
Type: 'Input',
|
|
289
|
+
Value: null,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
Name: 'TaggedUsers',
|
|
293
|
+
Type: 'Input',
|
|
294
|
+
Value: null,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
Name: 'ScheduledTime',
|
|
298
|
+
Type: 'Input',
|
|
299
|
+
Value: null,
|
|
300
|
+
},
|
|
301
|
+
];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get the description for this action
|
|
306
|
+
*/
|
|
307
|
+
public get Description(): string {
|
|
308
|
+
return 'Creates a new Instagram post with images or videos. Supports feed posts, carousels, and reels.';
|
|
309
|
+
}
|
|
310
|
+
}
|