@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.
Files changed (204) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +6 -6
  3. package/dist/base/base-social.action.d.ts.map +1 -1
  4. package/dist/base/base-social.action.js +18 -24
  5. package/dist/base/base-social.action.js.map +1 -1
  6. package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -1
  7. package/dist/providers/buffer/buffer-base.action.js +35 -34
  8. package/dist/providers/buffer/buffer-base.action.js.map +1 -1
  9. package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -1
  10. package/dist/providers/facebook/actions/boost-post.action.js +33 -33
  11. package/dist/providers/facebook/actions/boost-post.action.js.map +1 -1
  12. package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -1
  13. package/dist/providers/facebook/actions/create-album.action.js +34 -36
  14. package/dist/providers/facebook/actions/create-album.action.js.map +1 -1
  15. package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -1
  16. package/dist/providers/facebook/actions/create-post.action.js +20 -20
  17. package/dist/providers/facebook/actions/create-post.action.js.map +1 -1
  18. package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -1
  19. package/dist/providers/facebook/actions/get-page-insights.action.js +25 -27
  20. package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -1
  21. package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -1
  22. package/dist/providers/facebook/actions/get-page-posts.action.js +19 -23
  23. package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -1
  24. package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -1
  25. package/dist/providers/facebook/actions/get-post-insights.action.js +28 -32
  26. package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -1
  27. package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -1
  28. package/dist/providers/facebook/actions/respond-to-comments.action.js +42 -44
  29. package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -1
  30. package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -1
  31. package/dist/providers/facebook/actions/schedule-post.action.js +29 -29
  32. package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -1
  33. package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -1
  34. package/dist/providers/facebook/actions/search-posts.action.js +37 -39
  35. package/dist/providers/facebook/actions/search-posts.action.js.map +1 -1
  36. package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -1
  37. package/dist/providers/facebook/facebook-base.action.js +44 -59
  38. package/dist/providers/facebook/facebook-base.action.js.map +1 -1
  39. package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -1
  40. package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +33 -31
  41. package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -1
  42. package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -1
  43. package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +28 -32
  44. package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -1
  45. package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -1
  46. package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +19 -19
  47. package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -1
  48. package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -1
  49. package/dist/providers/hootsuite/actions/get-analytics.action.js +24 -26
  50. package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -1
  51. package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -1
  52. package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +22 -22
  53. package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -1
  54. package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -1
  55. package/dist/providers/hootsuite/actions/get-social-profiles.action.js +32 -34
  56. package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -1
  57. package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -1
  58. package/dist/providers/hootsuite/actions/search-posts.action.js +43 -52
  59. package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -1
  60. package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -1
  61. package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +30 -28
  62. package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -1
  63. package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -1
  64. package/dist/providers/hootsuite/hootsuite-base.action.js +18 -20
  65. package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -1
  66. package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -1
  67. package/dist/providers/instagram/actions/create-post.action.js +27 -26
  68. package/dist/providers/instagram/actions/create-post.action.js.map +1 -1
  69. package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -1
  70. package/dist/providers/instagram/actions/create-story.action.js +35 -35
  71. package/dist/providers/instagram/actions/create-story.action.js.map +1 -1
  72. package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -1
  73. package/dist/providers/instagram/actions/get-account-insights.action.js +38 -59
  74. package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -1
  75. package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -1
  76. package/dist/providers/instagram/actions/get-business-posts.action.js +29 -29
  77. package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -1
  78. package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -1
  79. package/dist/providers/instagram/actions/get-comments.action.js +36 -36
  80. package/dist/providers/instagram/actions/get-comments.action.js.map +1 -1
  81. package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -1
  82. package/dist/providers/instagram/actions/get-post-insights.action.js +23 -25
  83. package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -1
  84. package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -1
  85. package/dist/providers/instagram/actions/schedule-post.action.js +25 -25
  86. package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -1
  87. package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -1
  88. package/dist/providers/instagram/actions/search-posts.action.js +56 -60
  89. package/dist/providers/instagram/actions/search-posts.action.js.map +1 -1
  90. package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -1
  91. package/dist/providers/instagram/instagram-base.action.js +25 -27
  92. package/dist/providers/instagram/instagram-base.action.js.map +1 -1
  93. package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -1
  94. package/dist/providers/linkedin/actions/create-article.action.js +55 -45
  95. package/dist/providers/linkedin/actions/create-article.action.js.map +1 -1
  96. package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -1
  97. package/dist/providers/linkedin/actions/create-post.action.js +31 -29
  98. package/dist/providers/linkedin/actions/create-post.action.js.map +1 -1
  99. package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -1
  100. package/dist/providers/linkedin/actions/get-followers.action.js +28 -28
  101. package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -1
  102. package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -1
  103. package/dist/providers/linkedin/actions/get-organization-posts.action.js +20 -20
  104. package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -1
  105. package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -1
  106. package/dist/providers/linkedin/actions/get-personal-posts.action.js +19 -19
  107. package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -1
  108. package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -1
  109. package/dist/providers/linkedin/actions/get-post-analytics.action.js +25 -23
  110. package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -1
  111. package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -1
  112. package/dist/providers/linkedin/actions/schedule-post.action.js +32 -30
  113. package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -1
  114. package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -1
  115. package/dist/providers/linkedin/actions/search-posts.action.js +28 -30
  116. package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -1
  117. package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -1
  118. package/dist/providers/linkedin/linkedin-base.action.js +33 -38
  119. package/dist/providers/linkedin/linkedin-base.action.js.map +1 -1
  120. package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -1
  121. package/dist/providers/tiktok/tiktok-base.action.js +25 -26
  122. package/dist/providers/tiktok/tiktok-base.action.js.map +1 -1
  123. package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -1
  124. package/dist/providers/twitter/actions/create-thread.action.js +25 -29
  125. package/dist/providers/twitter/actions/create-thread.action.js.map +1 -1
  126. package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -1
  127. package/dist/providers/twitter/actions/create-tweet.action.js +23 -23
  128. package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -1
  129. package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -1
  130. package/dist/providers/twitter/actions/delete-tweet.action.js +19 -19
  131. package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -1
  132. package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -1
  133. package/dist/providers/twitter/actions/get-analytics.action.js +40 -47
  134. package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -1
  135. package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -1
  136. package/dist/providers/twitter/actions/get-mentions.action.js +30 -31
  137. package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -1
  138. package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -1
  139. package/dist/providers/twitter/actions/get-timeline.action.js +29 -29
  140. package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -1
  141. package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -1
  142. package/dist/providers/twitter/actions/schedule-tweet.action.js +26 -26
  143. package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -1
  144. package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -1
  145. package/dist/providers/twitter/actions/search-tweets.action.js +56 -58
  146. package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -1
  147. package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -1
  148. package/dist/providers/twitter/twitter-base.action.js +58 -68
  149. package/dist/providers/twitter/twitter-base.action.js.map +1 -1
  150. package/dist/providers/youtube/youtube-base.action.d.ts +1 -1
  151. package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -1
  152. package/dist/providers/youtube/youtube-base.action.js +22 -25
  153. package/dist/providers/youtube/youtube-base.action.js.map +1 -1
  154. package/package.json +5 -6
  155. package/src/base/base-social.action.ts +217 -224
  156. package/src/providers/buffer/buffer-base.action.ts +435 -441
  157. package/src/providers/facebook/actions/boost-post.action.ts +350 -386
  158. package/src/providers/facebook/actions/create-album.action.ts +291 -307
  159. package/src/providers/facebook/actions/create-post.action.ts +224 -227
  160. package/src/providers/facebook/actions/get-page-insights.action.ts +383 -403
  161. package/src/providers/facebook/actions/get-page-posts.action.ts +214 -225
  162. package/src/providers/facebook/actions/get-post-insights.action.ts +300 -316
  163. package/src/providers/facebook/actions/respond-to-comments.action.ts +319 -336
  164. package/src/providers/facebook/actions/schedule-post.action.ts +289 -292
  165. package/src/providers/facebook/actions/search-posts.action.ts +399 -413
  166. package/src/providers/facebook/facebook-base.action.ts +653 -670
  167. package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
  168. package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +184 -189
  169. package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +160 -161
  170. package/src/providers/hootsuite/actions/get-analytics.action.ts +249 -254
  171. package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +206 -207
  172. package/src/providers/hootsuite/actions/get-social-profiles.action.ts +206 -205
  173. package/src/providers/hootsuite/actions/search-posts.action.ts +351 -369
  174. package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +211 -209
  175. package/src/providers/hootsuite/hootsuite-base.action.ts +301 -307
  176. package/src/providers/instagram/actions/create-post.action.ts +276 -296
  177. package/src/providers/instagram/actions/create-story.action.ts +378 -394
  178. package/src/providers/instagram/actions/get-account-insights.action.ts +384 -420
  179. package/src/providers/instagram/actions/get-business-posts.action.ts +233 -242
  180. package/src/providers/instagram/actions/get-comments.action.ts +365 -377
  181. package/src/providers/instagram/actions/get-post-insights.action.ts +265 -273
  182. package/src/providers/instagram/actions/schedule-post.action.ts +233 -235
  183. package/src/providers/instagram/actions/search-posts.action.ts +512 -538
  184. package/src/providers/instagram/instagram-base.action.ts +368 -393
  185. package/src/providers/linkedin/actions/create-article.action.ts +275 -266
  186. package/src/providers/linkedin/actions/create-post.action.ts +179 -177
  187. package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
  188. package/src/providers/linkedin/actions/get-organization-posts.action.ts +146 -147
  189. package/src/providers/linkedin/actions/get-personal-posts.action.ts +138 -139
  190. package/src/providers/linkedin/actions/get-post-analytics.action.ts +190 -189
  191. package/src/providers/linkedin/actions/schedule-post.action.ts +191 -189
  192. package/src/providers/linkedin/actions/search-posts.action.ts +275 -283
  193. package/src/providers/linkedin/linkedin-base.action.ts +407 -421
  194. package/src/providers/tiktok/tiktok-base.action.ts +305 -320
  195. package/src/providers/twitter/actions/create-thread.action.ts +203 -207
  196. package/src/providers/twitter/actions/create-tweet.action.ts +187 -188
  197. package/src/providers/twitter/actions/delete-tweet.action.ts +128 -129
  198. package/src/providers/twitter/actions/get-analytics.action.ts +402 -411
  199. package/src/providers/twitter/actions/get-mentions.action.ts +218 -219
  200. package/src/providers/twitter/actions/get-timeline.action.ts +232 -233
  201. package/src/providers/twitter/actions/schedule-tweet.action.ts +221 -222
  202. package/src/providers/twitter/actions/search-tweets.action.ts +540 -543
  203. package/src/providers/twitter/twitter-base.action.ts +541 -560
  204. 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/core';
4
+ import { LogError } from '@memberjunction/global';
5
5
  import { MediaFile } from '../../../base/base-social.action';
6
6
  import { BaseAction } from '@memberjunction/actions';
7
7
 
@@ -12,405 +12,389 @@ import { BaseAction } from '@memberjunction/actions';
12
12
  */
13
13
  @RegisterClass(BaseAction, 'Instagram - Create Story')
14
14
  export class InstagramCreateStoryAction extends InstagramBaseAction {
15
-
16
- protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
17
- try {
18
- const companyIntegrationId = this.getParamValue(params.Params, 'CompanyIntegrationID');
19
- const mediaFile = this.getParamValue(params.Params, 'MediaFile') as MediaFile;
20
- const stickerType = this.getParamValue(params.Params, 'StickerType');
21
- const stickerData = this.getParamValue(params.Params, 'StickerData');
22
- const linkUrl = this.getParamValue(params.Params, 'LinkUrl');
23
- const linkText = this.getParamValue(params.Params, 'LinkText');
24
- const mentionedUsers = this.getParamValue(params.Params, 'MentionedUsers') as string[];
25
- const hashtags = this.getParamValue(params.Params, 'Hashtags') as string[];
26
-
27
- // Initialize OAuth
28
- if (!await this.initializeOAuth(companyIntegrationId)) {
29
- return {
30
- Success: false,
31
- Message: 'Failed to initialize Instagram authentication',
32
- ResultCode: 'AUTH_FAILED'
33
- };
34
- }
35
-
36
- // Validate inputs
37
- if (!mediaFile) {
38
- return {
39
- Success: false,
40
- Message: 'MediaFile is required for stories',
41
- ResultCode: 'MISSING_MEDIA'
42
- };
43
- }
44
-
45
- // Validate media type and duration
46
- const validation = this.validateStoryMedia(mediaFile);
47
- if (!validation.isValid) {
48
- return {
49
- Success: false,
50
- Message: validation.message,
51
- ResultCode: 'INVALID_MEDIA'
52
- };
53
- }
54
-
55
- // Check if account can add links (requires 10k+ followers or verified)
56
- let canAddLink = false;
57
- if (linkUrl) {
58
- canAddLink = await this.checkLinkEligibility();
59
- if (!canAddLink) {
60
- LogError('Account not eligible for story links. Requires 10k+ followers or verification.');
61
- }
62
- }
63
-
64
- // Create story media container
65
- const storyParams: any = {
66
- media_type: 'STORIES',
67
- access_token: this.getAccessToken()
68
- };
69
-
70
- // Add media URL
71
- if (mediaFile.mimeType.startsWith('image/')) {
72
- storyParams.image_url = await this.uploadStoryMediaToCDN(mediaFile);
73
- } else if (mediaFile.mimeType.startsWith('video/')) {
74
- storyParams.video_url = await this.uploadStoryMediaToCDN(mediaFile);
75
- }
76
-
77
- // Add stickers if specified
78
- if (stickerType && stickerData) {
79
- storyParams.sticker = this.formatSticker(stickerType, stickerData);
80
- }
81
-
82
- // Add mentions
83
- if (mentionedUsers && mentionedUsers.length > 0) {
84
- storyParams.user_tags = mentionedUsers.map((username, index) => ({
85
- username,
86
- x: 0.5, // Center horizontally
87
- y: 0.1 + (index * 0.1) // Stack vertically
88
- }));
89
- }
90
-
91
- // Add hashtags
92
- if (hashtags && hashtags.length > 0) {
93
- storyParams.hashtags = hashtags.map((tag, index) => ({
94
- hashtag: tag.startsWith('#') ? tag : `#${tag}`,
95
- x: 0.5,
96
- y: 0.8 - (index * 0.1)
97
- }));
98
- }
99
-
100
- // Create the story container
101
- const containerResponse = await this.makeInstagramRequest<{ id: string }>(
102
- `${this.instagramBusinessAccountId}/media`,
103
- 'POST',
104
- storyParams
105
- );
106
-
107
- // Wait for processing
108
- await this.waitForMediaContainer(containerResponse.id);
109
-
110
- // Publish the story
111
- const publishParams: any = {
112
- creation_id: containerResponse.id,
113
- access_token: this.getAccessToken()
114
- };
115
-
116
- // Add link if eligible and provided
117
- if (linkUrl && canAddLink) {
118
- publishParams.link = {
119
- url: linkUrl,
120
- text: linkText || 'See More'
121
- };
122
- }
123
-
124
- const publishResponse = await this.makeInstagramRequest<{ id: string }>(
125
- `${this.instagramBusinessAccountId}/media_publish`,
126
- 'POST',
127
- publishParams
128
- );
129
-
130
- // Get story details
131
- const storyDetails = await this.getStoryDetails(publishResponse.id);
132
-
133
- // Store result in output params
134
- const outputParams = [...params.Params];
135
- outputParams.push({
136
- Name: 'StoryID',
137
- Type: 'Output',
138
- Value: publishResponse.id
139
- });
140
- outputParams.push({
141
- Name: 'MediaType',
142
- Type: 'Output',
143
- Value: mediaFile.mimeType.startsWith('image/') ? 'IMAGE' : 'VIDEO'
144
- });
145
- outputParams.push({
146
- Name: 'ExpiresAt',
147
- Type: 'Output',
148
- Value: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString()
149
- });
150
- outputParams.push({
151
- Name: 'StoryData',
152
- Type: 'Output',
153
- Value: JSON.stringify({
154
- features: {
155
- hasSticker: !!stickerType,
156
- hasLink: linkUrl && canAddLink,
157
- hasMentions: mentionedUsers && mentionedUsers.length > 0,
158
- hasHashtags: hashtags && hashtags.length > 0
159
- },
160
- insights: storyDetails.insights || {}
161
- })
162
- });
163
-
164
- return {
165
- Success: true,
166
- Message: 'Instagram story created successfully',
167
- ResultCode: 'SUCCESS',
168
- Params: outputParams
169
- };
170
-
171
- } catch (error: any) {
172
- LogError('Failed to create Instagram story', error);
173
-
174
- if (error.code === 'RATE_LIMIT') {
175
- return {
176
- Success: false,
177
- Message: 'Instagram API rate limit exceeded. Please try again later.',
178
- ResultCode: 'RATE_LIMIT'
179
- };
180
- }
181
-
182
- if (error.code === 'INVALID_MEDIA') {
183
- return {
184
- Success: false,
185
- Message: error.message,
186
- ResultCode: 'INVALID_MEDIA'
187
- };
188
- }
189
-
190
- return {
191
- Success: false,
192
- Message: `Failed to create story: ${error.message}`,
193
- ResultCode: 'ERROR'
194
- };
15
+ protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
16
+ try {
17
+ const companyIntegrationId = this.getParamValue(params.Params, 'CompanyIntegrationID');
18
+ const mediaFile = this.getParamValue(params.Params, 'MediaFile') as MediaFile;
19
+ const stickerType = this.getParamValue(params.Params, 'StickerType');
20
+ const stickerData = this.getParamValue(params.Params, 'StickerData');
21
+ const linkUrl = this.getParamValue(params.Params, 'LinkUrl');
22
+ const linkText = this.getParamValue(params.Params, 'LinkText');
23
+ const mentionedUsers = this.getParamValue(params.Params, 'MentionedUsers') as string[];
24
+ const hashtags = this.getParamValue(params.Params, 'Hashtags') as string[];
25
+
26
+ // Initialize OAuth
27
+ if (!(await this.initializeOAuth(companyIntegrationId))) {
28
+ return {
29
+ Success: false,
30
+ Message: 'Failed to initialize Instagram authentication',
31
+ ResultCode: 'AUTH_FAILED',
32
+ };
33
+ }
34
+
35
+ // Validate inputs
36
+ if (!mediaFile) {
37
+ return {
38
+ Success: false,
39
+ Message: 'MediaFile is required for stories',
40
+ ResultCode: 'MISSING_MEDIA',
41
+ };
42
+ }
43
+
44
+ // Validate media type and duration
45
+ const validation = this.validateStoryMedia(mediaFile);
46
+ if (!validation.isValid) {
47
+ return {
48
+ Success: false,
49
+ Message: validation.message,
50
+ ResultCode: 'INVALID_MEDIA',
51
+ };
52
+ }
53
+
54
+ // Check if account can add links (requires 10k+ followers or verified)
55
+ let canAddLink = false;
56
+ if (linkUrl) {
57
+ canAddLink = await this.checkLinkEligibility();
58
+ if (!canAddLink) {
59
+ LogError('Account not eligible for story links. Requires 10k+ followers or verification.');
195
60
  }
61
+ }
62
+
63
+ // Create story media container
64
+ const storyParams: any = {
65
+ media_type: 'STORIES',
66
+ access_token: this.getAccessToken(),
67
+ };
68
+
69
+ // Add media URL
70
+ if (mediaFile.mimeType.startsWith('image/')) {
71
+ storyParams.image_url = await this.uploadStoryMediaToCDN(mediaFile);
72
+ } else if (mediaFile.mimeType.startsWith('video/')) {
73
+ storyParams.video_url = await this.uploadStoryMediaToCDN(mediaFile);
74
+ }
75
+
76
+ // Add stickers if specified
77
+ if (stickerType && stickerData) {
78
+ storyParams.sticker = this.formatSticker(stickerType, stickerData);
79
+ }
80
+
81
+ // Add mentions
82
+ if (mentionedUsers && mentionedUsers.length > 0) {
83
+ storyParams.user_tags = mentionedUsers.map((username, index) => ({
84
+ username,
85
+ x: 0.5, // Center horizontally
86
+ y: 0.1 + index * 0.1, // Stack vertically
87
+ }));
88
+ }
89
+
90
+ // Add hashtags
91
+ if (hashtags && hashtags.length > 0) {
92
+ storyParams.hashtags = hashtags.map((tag, index) => ({
93
+ hashtag: tag.startsWith('#') ? tag : `#${tag}`,
94
+ x: 0.5,
95
+ y: 0.8 - index * 0.1,
96
+ }));
97
+ }
98
+
99
+ // Create the story container
100
+ const containerResponse = await this.makeInstagramRequest<{ id: string }>(
101
+ `${this.instagramBusinessAccountId}/media`,
102
+ 'POST',
103
+ storyParams
104
+ );
105
+
106
+ // Wait for processing
107
+ await this.waitForMediaContainer(containerResponse.id);
108
+
109
+ // Publish the story
110
+ const publishParams: any = {
111
+ creation_id: containerResponse.id,
112
+ access_token: this.getAccessToken(),
113
+ };
114
+
115
+ // Add link if eligible and provided
116
+ if (linkUrl && canAddLink) {
117
+ publishParams.link = {
118
+ url: linkUrl,
119
+ text: linkText || 'See More',
120
+ };
121
+ }
122
+
123
+ const publishResponse = await this.makeInstagramRequest<{ id: string }>(
124
+ `${this.instagramBusinessAccountId}/media_publish`,
125
+ 'POST',
126
+ publishParams
127
+ );
128
+
129
+ // Get story details
130
+ const storyDetails = await this.getStoryDetails(publishResponse.id);
131
+
132
+ // Store result in output params
133
+ const outputParams = [...params.Params];
134
+ outputParams.push({
135
+ Name: 'StoryID',
136
+ Type: 'Output',
137
+ Value: publishResponse.id,
138
+ });
139
+ outputParams.push({
140
+ Name: 'MediaType',
141
+ Type: 'Output',
142
+ Value: mediaFile.mimeType.startsWith('image/') ? 'IMAGE' : 'VIDEO',
143
+ });
144
+ outputParams.push({
145
+ Name: 'ExpiresAt',
146
+ Type: 'Output',
147
+ Value: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
148
+ });
149
+ outputParams.push({
150
+ Name: 'StoryData',
151
+ Type: 'Output',
152
+ Value: JSON.stringify({
153
+ features: {
154
+ hasSticker: !!stickerType,
155
+ hasLink: linkUrl && canAddLink,
156
+ hasMentions: mentionedUsers && mentionedUsers.length > 0,
157
+ hasHashtags: hashtags && hashtags.length > 0,
158
+ },
159
+ insights: storyDetails.insights || {},
160
+ }),
161
+ });
162
+
163
+ return {
164
+ Success: true,
165
+ Message: 'Instagram story created successfully',
166
+ ResultCode: 'SUCCESS',
167
+ Params: outputParams,
168
+ };
169
+ } catch (error: any) {
170
+ LogError('Failed to create Instagram story', error);
171
+
172
+ if (error.code === 'RATE_LIMIT') {
173
+ return {
174
+ Success: false,
175
+ Message: 'Instagram API rate limit exceeded. Please try again later.',
176
+ ResultCode: 'RATE_LIMIT',
177
+ };
178
+ }
179
+
180
+ if (error.code === 'INVALID_MEDIA') {
181
+ return {
182
+ Success: false,
183
+ Message: error.message,
184
+ ResultCode: 'INVALID_MEDIA',
185
+ };
186
+ }
187
+
188
+ return {
189
+ Success: false,
190
+ Message: `Failed to create story: ${error.message}`,
191
+ ResultCode: 'ERROR',
192
+ };
196
193
  }
197
-
198
- /**
199
- * Validate story media requirements
200
- */
201
- private validateStoryMedia(mediaFile: MediaFile): { isValid: boolean; message?: string } {
202
- // Check file size (max 30MB for images, 100MB for videos)
203
- const maxSize = mediaFile.mimeType.startsWith('image/') ? 30 * 1024 * 1024 : 100 * 1024 * 1024;
204
- if (mediaFile.size > maxSize) {
205
- return {
206
- isValid: false,
207
- message: `File size exceeds limit. Max ${maxSize / (1024 * 1024)}MB`
208
- };
209
- }
210
-
211
- // Check media type
212
- const supportedTypes = ['image/jpeg', 'image/png', 'video/mp4', 'video/mov'];
213
- if (!supportedTypes.includes(mediaFile.mimeType)) {
214
- return {
215
- isValid: false,
216
- message: `Unsupported media type. Supported: ${supportedTypes.join(', ')}`
217
- };
218
- }
219
-
220
- // For videos, check duration (max 60 seconds for stories)
221
- // In a real implementation, you'd extract video metadata
222
-
223
- return { isValid: true };
224
- }
225
-
226
- /**
227
- * Check if account is eligible for story links
228
- */
229
- private async checkLinkEligibility(): Promise<boolean> {
230
- try {
231
- const accountInfo = await this.makeInstagramRequest<any>(
232
- this.instagramBusinessAccountId,
233
- 'GET',
234
- null,
235
- {
236
- fields: 'followers_count,is_verified',
237
- access_token: this.getAccessToken()
238
- }
239
- );
240
-
241
- return accountInfo.is_verified || accountInfo.followers_count >= 10000;
242
- } catch (error) {
243
- LogError('Failed to check link eligibility', error);
244
- return false;
245
- }
194
+ }
195
+
196
+ /**
197
+ * Validate story media requirements
198
+ */
199
+ private validateStoryMedia(mediaFile: MediaFile): { isValid: boolean; message?: string } {
200
+ // Check file size (max 30MB for images, 100MB for videos)
201
+ const maxSize = mediaFile.mimeType.startsWith('image/') ? 30 * 1024 * 1024 : 100 * 1024 * 1024;
202
+ if (mediaFile.size > maxSize) {
203
+ return {
204
+ isValid: false,
205
+ message: `File size exceeds limit. Max ${maxSize / (1024 * 1024)}MB`,
206
+ };
246
207
  }
247
208
 
248
- /**
249
- * Format sticker data based on type
250
- */
251
- private formatSticker(type: string, data: any): any {
252
- switch (type) {
253
- case 'location':
254
- return {
255
- type: 'location',
256
- location_id: data.locationId,
257
- x: data.x || 0.5,
258
- y: data.y || 0.5,
259
- width: data.width || 0.5,
260
- height: data.height || 0.1,
261
- rotation: data.rotation || 0
262
- };
263
-
264
- case 'poll':
265
- return {
266
- type: 'poll',
267
- question: data.question,
268
- options: data.options || ['Yes', 'No'],
269
- x: data.x || 0.5,
270
- y: data.y || 0.5
271
- };
272
-
273
- case 'question':
274
- return {
275
- type: 'question',
276
- question: data.question,
277
- text_color: data.textColor || '#FFFFFF',
278
- background_color: data.backgroundColor || '#000000',
279
- x: data.x || 0.5,
280
- y: data.y || 0.5
281
- };
282
-
283
- case 'music':
284
- return {
285
- type: 'music',
286
- audio_asset_id: data.audioAssetId,
287
- display_type: data.displayType || 'default',
288
- x: data.x || 0.5,
289
- y: data.y || 0.5
290
- };
291
-
292
- case 'countdown':
293
- return {
294
- type: 'countdown',
295
- end_time: data.endTime,
296
- text: data.text || 'Countdown',
297
- text_color: data.textColor || '#FFFFFF',
298
- x: data.x || 0.5,
299
- y: data.y || 0.5
300
- };
301
-
302
- default:
303
- return null;
304
- }
305
- }
306
-
307
- /**
308
- * Get story details after publishing
309
- */
310
- private async getStoryDetails(storyId: string): Promise<any> {
311
- try {
312
- const response = await this.makeInstagramRequest(
313
- storyId,
314
- 'GET',
315
- null,
316
- {
317
- fields: 'id,media_type,permalink,timestamp',
318
- access_token: this.getAccessToken()
319
- }
320
- );
321
-
322
- // Try to get initial insights (may not be immediately available)
323
- try {
324
- const insights = await this.getInsights(
325
- storyId,
326
- ['impressions', 'reach', 'exits', 'replies'],
327
- 'lifetime'
328
- );
329
- response.insights = this.parseStoryInsights(insights);
330
- } catch (insightError) {
331
- // Insights might not be available immediately
332
- response.insights = null;
333
- }
334
-
335
- return response;
336
- } catch (error) {
337
- LogError('Failed to get story details', error);
338
- return { id: storyId };
339
- }
209
+ // Check media type
210
+ const supportedTypes = ['image/jpeg', 'image/png', 'video/mp4', 'video/mov'];
211
+ if (!supportedTypes.includes(mediaFile.mimeType)) {
212
+ return {
213
+ isValid: false,
214
+ message: `Unsupported media type. Supported: ${supportedTypes.join(', ')}`,
215
+ };
340
216
  }
341
217
 
342
- /**
343
- * Parse story-specific insights
344
- */
345
- private parseStoryInsights(insights: any[]): any {
346
- const parsed: any = {};
347
-
348
- insights.forEach(metric => {
349
- if (metric.values && metric.values.length > 0) {
350
- parsed[metric.name] = metric.values[0].value || 0;
351
- }
352
- });
353
-
354
- return parsed;
218
+ // For videos, check duration (max 60 seconds for stories)
219
+ // In a real implementation, you'd extract video metadata
220
+
221
+ return { isValid: true };
222
+ }
223
+
224
+ /**
225
+ * Check if account is eligible for story links
226
+ */
227
+ private async checkLinkEligibility(): Promise<boolean> {
228
+ try {
229
+ const accountInfo = await this.makeInstagramRequest<any>(this.instagramBusinessAccountId, 'GET', null, {
230
+ fields: 'followers_count,is_verified',
231
+ access_token: this.getAccessToken(),
232
+ });
233
+
234
+ return accountInfo.is_verified || accountInfo.followers_count >= 10000;
235
+ } catch (error) {
236
+ LogError('Failed to check link eligibility', error);
237
+ return false;
355
238
  }
356
-
357
- /**
358
- * Upload story media to CDN (placeholder implementation)
359
- */
360
- private async uploadStoryMediaToCDN(file: MediaFile): Promise<string> {
361
- // In a real implementation, this would upload to a CDN
362
- // For now, throw an error indicating this needs implementation
363
- throw new Error('Media CDN upload not implemented. Instagram requires media to be hosted at a public URL.');
364
- }
365
-
366
- /**
367
- * Define the parameters for this action
368
- */
369
- public get Params(): ActionParam[] {
370
- return [
371
- ...this.commonSocialParams,
372
- {
373
- Name: 'MediaFile',
374
- Type: 'Input',
375
- Value: null,
376
- },
377
- {
378
- Name: 'StickerType',
379
- Type: 'Input',
380
- Value: null,
381
- },
382
- {
383
- Name: 'StickerData',
384
- Type: 'Input',
385
- Value: null,
386
- },
387
- {
388
- Name: 'LinkUrl',
389
- Type: 'Input',
390
- Value: null,
391
- },
392
- {
393
- Name: 'LinkText',
394
- Type: 'Input',
395
- Value: null,
396
- },
397
- {
398
- Name: 'MentionedUsers',
399
- Type: 'Input',
400
- Value: null,
401
- },
402
- {
403
- Name: 'Hashtags',
404
- Type: 'Input',
405
- Value: null,
406
- }
407
- ];
239
+ }
240
+
241
+ /**
242
+ * Format sticker data based on type
243
+ */
244
+ private formatSticker(type: string, data: any): any {
245
+ switch (type) {
246
+ case 'location':
247
+ return {
248
+ type: 'location',
249
+ location_id: data.locationId,
250
+ x: data.x || 0.5,
251
+ y: data.y || 0.5,
252
+ width: data.width || 0.5,
253
+ height: data.height || 0.1,
254
+ rotation: data.rotation || 0,
255
+ };
256
+
257
+ case 'poll':
258
+ return {
259
+ type: 'poll',
260
+ question: data.question,
261
+ options: data.options || ['Yes', 'No'],
262
+ x: data.x || 0.5,
263
+ y: data.y || 0.5,
264
+ };
265
+
266
+ case 'question':
267
+ return {
268
+ type: 'question',
269
+ question: data.question,
270
+ text_color: data.textColor || '#FFFFFF',
271
+ background_color: data.backgroundColor || '#000000',
272
+ x: data.x || 0.5,
273
+ y: data.y || 0.5,
274
+ };
275
+
276
+ case 'music':
277
+ return {
278
+ type: 'music',
279
+ audio_asset_id: data.audioAssetId,
280
+ display_type: data.displayType || 'default',
281
+ x: data.x || 0.5,
282
+ y: data.y || 0.5,
283
+ };
284
+
285
+ case 'countdown':
286
+ return {
287
+ type: 'countdown',
288
+ end_time: data.endTime,
289
+ text: data.text || 'Countdown',
290
+ text_color: data.textColor || '#FFFFFF',
291
+ x: data.x || 0.5,
292
+ y: data.y || 0.5,
293
+ };
294
+
295
+ default:
296
+ return null;
408
297
  }
409
-
410
- /**
411
- * Get the description for this action
412
- */
413
- public get Description(): string {
414
- return 'Creates an Instagram Story with support for stickers, links, mentions, and interactive elements. Stories disappear after 24 hours.';
298
+ }
299
+
300
+ /**
301
+ * Get story details after publishing
302
+ */
303
+ private async getStoryDetails(storyId: string): Promise<any> {
304
+ try {
305
+ const response = await this.makeInstagramRequest(storyId, 'GET', null, {
306
+ fields: 'id,media_type,permalink,timestamp',
307
+ access_token: this.getAccessToken(),
308
+ });
309
+
310
+ // Try to get initial insights (may not be immediately available)
311
+ try {
312
+ const insights = await this.getInsights(storyId, ['impressions', 'reach', 'exits', 'replies'], 'lifetime');
313
+ response.insights = this.parseStoryInsights(insights);
314
+ } catch (insightError) {
315
+ // Insights might not be available immediately
316
+ response.insights = null;
317
+ }
318
+
319
+ return response;
320
+ } catch (error) {
321
+ LogError('Failed to get story details', error);
322
+ return { id: storyId };
415
323
  }
416
- }
324
+ }
325
+
326
+ /**
327
+ * Parse story-specific insights
328
+ */
329
+ private parseStoryInsights(insights: any[]): any {
330
+ const parsed: any = {};
331
+
332
+ insights.forEach((metric) => {
333
+ if (metric.values && metric.values.length > 0) {
334
+ parsed[metric.name] = metric.values[0].value || 0;
335
+ }
336
+ });
337
+
338
+ return parsed;
339
+ }
340
+
341
+ /**
342
+ * Upload story media to CDN (placeholder implementation)
343
+ */
344
+ private async uploadStoryMediaToCDN(file: MediaFile): Promise<string> {
345
+ // In a real implementation, this would upload to a CDN
346
+ // For now, throw an error indicating this needs implementation
347
+ throw new Error('Media CDN upload not implemented. Instagram requires media to be hosted at a public URL.');
348
+ }
349
+
350
+ /**
351
+ * Define the parameters for this action
352
+ */
353
+ public get Params(): ActionParam[] {
354
+ return [
355
+ ...this.commonSocialParams,
356
+ {
357
+ Name: 'MediaFile',
358
+ Type: 'Input',
359
+ Value: null,
360
+ },
361
+ {
362
+ Name: 'StickerType',
363
+ Type: 'Input',
364
+ Value: null,
365
+ },
366
+ {
367
+ Name: 'StickerData',
368
+ Type: 'Input',
369
+ Value: null,
370
+ },
371
+ {
372
+ Name: 'LinkUrl',
373
+ Type: 'Input',
374
+ Value: null,
375
+ },
376
+ {
377
+ Name: 'LinkText',
378
+ Type: 'Input',
379
+ Value: null,
380
+ },
381
+ {
382
+ Name: 'MentionedUsers',
383
+ Type: 'Input',
384
+ Value: null,
385
+ },
386
+ {
387
+ Name: 'Hashtags',
388
+ Type: 'Input',
389
+ Value: null,
390
+ },
391
+ ];
392
+ }
393
+
394
+ /**
395
+ * Get the description for this action
396
+ */
397
+ public get Description(): string {
398
+ return 'Creates an Instagram Story with support for stickers, links, mentions, and interactive elements. Stories disappear after 24 hours.';
399
+ }
400
+ }