@memberjunction/actions-bizapps-social 2.112.0 → 2.113.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 +13 -0
  3. package/dist/base/base-social.action.d.ts.map +1 -1
  4. package/dist/base/base-social.action.js +24 -18
  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 +34 -35
  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 +36 -34
  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 +27 -25
  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 +23 -19
  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 +32 -28
  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 +44 -42
  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 +39 -37
  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 +59 -44
  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 +31 -33
  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 +32 -28
  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 +26 -24
  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 +34 -32
  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 +52 -43
  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 +28 -30
  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 +20 -18
  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 +26 -27
  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 +59 -38
  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 +25 -23
  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 +60 -56
  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 +27 -25
  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 +45 -55
  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 +29 -31
  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 +23 -25
  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 +30 -32
  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 +30 -28
  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 +38 -33
  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 +26 -25
  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 +29 -25
  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 +47 -40
  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 +31 -30
  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 +58 -56
  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 +68 -58
  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 +25 -22
  153. package/dist/providers/youtube/youtube-base.action.js.map +1 -1
  154. package/package.json +6 -5
  155. package/src/base/base-social.action.ts +224 -217
  156. package/src/providers/buffer/buffer-base.action.ts +441 -435
  157. package/src/providers/facebook/actions/boost-post.action.ts +386 -350
  158. package/src/providers/facebook/actions/create-album.action.ts +307 -291
  159. package/src/providers/facebook/actions/create-post.action.ts +227 -224
  160. package/src/providers/facebook/actions/get-page-insights.action.ts +403 -383
  161. package/src/providers/facebook/actions/get-page-posts.action.ts +225 -214
  162. package/src/providers/facebook/actions/get-post-insights.action.ts +316 -300
  163. package/src/providers/facebook/actions/respond-to-comments.action.ts +336 -319
  164. package/src/providers/facebook/actions/schedule-post.action.ts +292 -289
  165. package/src/providers/facebook/actions/search-posts.action.ts +413 -399
  166. package/src/providers/facebook/facebook-base.action.ts +670 -653
  167. package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
  168. package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +189 -184
  169. package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +161 -160
  170. package/src/providers/hootsuite/actions/get-analytics.action.ts +254 -249
  171. package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +207 -206
  172. package/src/providers/hootsuite/actions/get-social-profiles.action.ts +205 -206
  173. package/src/providers/hootsuite/actions/search-posts.action.ts +369 -351
  174. package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +209 -211
  175. package/src/providers/hootsuite/hootsuite-base.action.ts +307 -301
  176. package/src/providers/instagram/actions/create-post.action.ts +296 -276
  177. package/src/providers/instagram/actions/create-story.action.ts +394 -378
  178. package/src/providers/instagram/actions/get-account-insights.action.ts +420 -384
  179. package/src/providers/instagram/actions/get-business-posts.action.ts +242 -233
  180. package/src/providers/instagram/actions/get-comments.action.ts +377 -365
  181. package/src/providers/instagram/actions/get-post-insights.action.ts +273 -265
  182. package/src/providers/instagram/actions/schedule-post.action.ts +235 -233
  183. package/src/providers/instagram/actions/search-posts.action.ts +538 -512
  184. package/src/providers/instagram/instagram-base.action.ts +393 -368
  185. package/src/providers/linkedin/actions/create-article.action.ts +266 -275
  186. package/src/providers/linkedin/actions/create-post.action.ts +177 -179
  187. package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
  188. package/src/providers/linkedin/actions/get-organization-posts.action.ts +147 -146
  189. package/src/providers/linkedin/actions/get-personal-posts.action.ts +139 -138
  190. package/src/providers/linkedin/actions/get-post-analytics.action.ts +189 -190
  191. package/src/providers/linkedin/actions/schedule-post.action.ts +189 -191
  192. package/src/providers/linkedin/actions/search-posts.action.ts +283 -275
  193. package/src/providers/linkedin/linkedin-base.action.ts +421 -407
  194. package/src/providers/tiktok/tiktok-base.action.ts +320 -305
  195. package/src/providers/twitter/actions/create-thread.action.ts +207 -203
  196. package/src/providers/twitter/actions/create-tweet.action.ts +188 -187
  197. package/src/providers/twitter/actions/delete-tweet.action.ts +129 -128
  198. package/src/providers/twitter/actions/get-analytics.action.ts +411 -402
  199. package/src/providers/twitter/actions/get-mentions.action.ts +219 -218
  200. package/src/providers/twitter/actions/get-timeline.action.ts +233 -232
  201. package/src/providers/twitter/actions/schedule-tweet.action.ts +222 -221
  202. package/src/providers/twitter/actions/search-tweets.action.ts +543 -540
  203. package/src/providers/twitter/twitter-base.action.ts +560 -541
  204. package/src/providers/youtube/youtube-base.action.ts +333 -320
@@ -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/global';
4
+ import { LogError } from '@memberjunction/core';
5
5
  import { MediaFile } from '../../../base/base-social.action';
6
6
  import { BaseAction } from '@memberjunction/actions';
7
7
 
@@ -12,389 +12,405 @@ import { BaseAction } from '@memberjunction/actions';
12
12
  */
13
13
  @RegisterClass(BaseAction, 'Instagram - Create Story')
14
14
  export class InstagramCreateStoryAction extends InstagramBaseAction {
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.');
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
+ };
60
195
  }
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
- };
193
196
  }
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
- };
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
+ }
207
246
  }
208
247
 
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
- };
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
+ }
216
340
  }
217
341
 
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;
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;
238
355
  }
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;
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
+ ];
297
408
  }
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 };
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.';
323
415
  }
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
- }
416
+ }