@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 { TwitterBaseAction, CreateTweetData } from '../twitter-base.action';
3
3
  import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
4
- import { LogStatus, LogError } from '@memberjunction/core';
4
+ import { LogStatus, LogError } from '@memberjunction/global';
5
5
  import { MediaFile } from '../../../base/base-social.action';
6
6
  import { BaseAction } from '@memberjunction/actions';
7
7
 
@@ -10,196 +10,195 @@ import { BaseAction } from '@memberjunction/actions';
10
10
  */
11
11
  @RegisterClass(BaseAction, 'TwitterCreateTweetAction')
12
12
  export class TwitterCreateTweetAction extends TwitterBaseAction {
13
- /**
14
- * Create a tweet on Twitter
15
- */
16
- protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
17
- const { Params, ContextUser } = params;
18
-
19
- try {
20
- // Initialize OAuth
21
- const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
22
- if (!await this.initializeOAuth(companyIntegrationId)) {
23
- throw new Error('Failed to initialize OAuth connection');
24
- }
25
-
26
- // Extract parameters
27
- const content = this.getParamValue(Params, 'Content');
28
- const mediaFiles = this.getParamValue(Params, 'MediaFiles');
29
- const replyToTweetId = this.getParamValue(Params, 'ReplyToTweetID');
30
- const quoteTweetId = this.getParamValue(Params, 'QuoteTweetID');
31
- const pollOptions = this.getParamValue(Params, 'PollOptions');
32
- const pollDurationMinutes = this.getParamValue(Params, 'PollDurationMinutes') || 1440; // Default 24 hours
33
-
34
- // Validate required parameters
35
- if (!content) {
36
- throw new Error('Content is required');
37
- }
38
-
39
- // Validate content length (Twitter's limit is 280 characters)
40
- if (content.length > 280) {
41
- throw new Error(`Content exceeds Twitter's 280 character limit (current: ${content.length} characters)`);
42
- }
43
-
44
- // Build tweet data
45
- const tweetData: CreateTweetData = {
46
- text: content
47
- };
48
-
49
- // Add reply if specified
50
- if (replyToTweetId) {
51
- tweetData.reply = {
52
- in_reply_to_tweet_id: replyToTweetId
53
- };
54
- }
55
-
56
- // Add quote tweet if specified
57
- if (quoteTweetId) {
58
- tweetData.quote_tweet_id = quoteTweetId;
59
- }
60
-
61
- // Add poll if specified
62
- if (pollOptions && Array.isArray(pollOptions) && pollOptions.length >= 2) {
63
- if (pollOptions.length > 4) {
64
- throw new Error('Twitter polls support a maximum of 4 options');
65
- }
66
-
67
- // Validate poll option lengths (max 25 characters each)
68
- for (const option of pollOptions) {
69
- if (option.length > 25) {
70
- throw new Error(`Poll option "${option}" exceeds 25 character limit`);
71
- }
72
- }
73
-
74
- tweetData.poll = {
75
- options: pollOptions,
76
- duration_minutes: Math.min(Math.max(pollDurationMinutes, 5), 10080) // Min 5 minutes, max 7 days
77
- };
78
- }
79
-
80
- // Upload media if provided
81
- if (mediaFiles && Array.isArray(mediaFiles) && mediaFiles.length > 0) {
82
- if (mediaFiles.length > 4) {
83
- throw new Error('Twitter supports a maximum of 4 media items per tweet');
84
- }
85
-
86
- LogStatus(`Uploading ${mediaFiles.length} media files...`);
87
- const mediaIds = await this.uploadMedia(mediaFiles as MediaFile[]);
88
-
89
- tweetData.media = {
90
- media_ids: mediaIds
91
- };
92
- }
93
-
94
- // Create the tweet
95
- LogStatus('Creating tweet...');
96
- const tweet = await this.createTweet(tweetData);
97
-
98
- // Normalize the created tweet
99
- const normalizedPost = this.normalizePost(tweet);
100
-
101
- // Get user info for additional context
102
- const user = await this.getCurrentUser();
103
-
104
- // Update output parameters
105
- const outputParams = [...Params];
106
- const postParam = outputParams.find(p => p.Name === 'CreatedPost');
107
- if (postParam) postParam.Value = normalizedPost;
108
- const tweetIdParam = outputParams.find(p => p.Name === 'TweetID');
109
- if (tweetIdParam) tweetIdParam.Value = tweet.id;
110
- const tweetUrlParam = outputParams.find(p => p.Name === 'TweetURL');
111
- if (tweetUrlParam) tweetUrlParam.Value = `https://twitter.com/${user.username}/status/${tweet.id}`;
112
-
113
- return {
114
- Success: true,
115
- ResultCode: 'SUCCESS',
116
- Message: `Successfully created tweet (ID: ${tweet.id})`,
117
- Params: outputParams
118
- };
119
-
120
- } catch (error) {
121
- const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
122
-
123
- return {
124
- Success: false,
125
- ResultCode: this.getErrorCode(error),
126
- Message: `Failed to create tweet: ${errorMessage}`,
127
- Params
128
- };
13
+ /**
14
+ * Create a tweet on Twitter
15
+ */
16
+ protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
17
+ const { Params, ContextUser } = params;
18
+
19
+ try {
20
+ // Initialize OAuth
21
+ const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
22
+ if (!(await this.initializeOAuth(companyIntegrationId))) {
23
+ throw new Error('Failed to initialize OAuth connection');
24
+ }
25
+
26
+ // Extract parameters
27
+ const content = this.getParamValue(Params, 'Content');
28
+ const mediaFiles = this.getParamValue(Params, 'MediaFiles');
29
+ const replyToTweetId = this.getParamValue(Params, 'ReplyToTweetID');
30
+ const quoteTweetId = this.getParamValue(Params, 'QuoteTweetID');
31
+ const pollOptions = this.getParamValue(Params, 'PollOptions');
32
+ const pollDurationMinutes = this.getParamValue(Params, 'PollDurationMinutes') || 1440; // Default 24 hours
33
+
34
+ // Validate required parameters
35
+ if (!content) {
36
+ throw new Error('Content is required');
37
+ }
38
+
39
+ // Validate content length (Twitter's limit is 280 characters)
40
+ if (content.length > 280) {
41
+ throw new Error(`Content exceeds Twitter's 280 character limit (current: ${content.length} characters)`);
42
+ }
43
+
44
+ // Build tweet data
45
+ const tweetData: CreateTweetData = {
46
+ text: content,
47
+ };
48
+
49
+ // Add reply if specified
50
+ if (replyToTweetId) {
51
+ tweetData.reply = {
52
+ in_reply_to_tweet_id: replyToTweetId,
53
+ };
54
+ }
55
+
56
+ // Add quote tweet if specified
57
+ if (quoteTweetId) {
58
+ tweetData.quote_tweet_id = quoteTweetId;
59
+ }
60
+
61
+ // Add poll if specified
62
+ if (pollOptions && Array.isArray(pollOptions) && pollOptions.length >= 2) {
63
+ if (pollOptions.length > 4) {
64
+ throw new Error('Twitter polls support a maximum of 4 options');
129
65
  }
130
- }
131
66
 
132
- /**
133
- * Get error code based on error type
134
- */
135
- private getErrorCode(error: any): string {
136
- if (error instanceof Error) {
137
- if (error.message.includes('Rate Limit')) return 'RATE_LIMIT';
138
- if (error.message.includes('Unauthorized')) return 'INVALID_TOKEN';
139
- if (error.message.includes('character limit')) return 'CONTENT_TOO_LONG';
140
- if (error.message.includes('media')) return 'INVALID_MEDIA';
67
+ // Validate poll option lengths (max 25 characters each)
68
+ for (const option of pollOptions) {
69
+ if (option.length > 25) {
70
+ throw new Error(`Poll option "${option}" exceeds 25 character limit`);
71
+ }
141
72
  }
142
- return 'ERROR';
143
- }
144
73
 
145
- /**
146
- * Define the parameters this action expects
147
- */
148
- public get Params(): ActionParam[] {
149
- return [
150
- ...this.commonSocialParams,
151
- {
152
- Name: 'Content',
153
- Type: 'Input',
154
- Value: null
155
- },
156
- {
157
- Name: 'MediaFiles',
158
- Type: 'Input',
159
- Value: null
160
- },
161
- {
162
- Name: 'ReplyToTweetID',
163
- Type: 'Input',
164
- Value: null
165
- },
166
- {
167
- Name: 'QuoteTweetID',
168
- Type: 'Input',
169
- Value: null
170
- },
171
- {
172
- Name: 'PollOptions',
173
- Type: 'Input',
174
- Value: null
175
- },
176
- {
177
- Name: 'PollDurationMinutes',
178
- Type: 'Input',
179
- Value: 1440 // Default 24 hours
180
- },
181
- {
182
- Name: 'CreatedPost',
183
- Type: 'Output',
184
- Value: null
185
- },
186
- {
187
- Name: 'TweetID',
188
- Type: 'Output',
189
- Value: null
190
- },
191
- {
192
- Name: 'TweetURL',
193
- Type: 'Output',
194
- Value: null
195
- }
196
- ];
197
- }
74
+ tweetData.poll = {
75
+ options: pollOptions,
76
+ duration_minutes: Math.min(Math.max(pollDurationMinutes, 5), 10080), // Min 5 minutes, max 7 days
77
+ };
78
+ }
198
79
 
199
- /**
200
- * Get action description
201
- */
202
- public get Description(): string {
203
- return 'Creates a tweet on Twitter/X with optional media attachments, polls, replies, or quote tweets';
80
+ // Upload media if provided
81
+ if (mediaFiles && Array.isArray(mediaFiles) && mediaFiles.length > 0) {
82
+ if (mediaFiles.length > 4) {
83
+ throw new Error('Twitter supports a maximum of 4 media items per tweet');
84
+ }
85
+
86
+ LogStatus(`Uploading ${mediaFiles.length} media files...`);
87
+ const mediaIds = await this.uploadMedia(mediaFiles as MediaFile[]);
88
+
89
+ tweetData.media = {
90
+ media_ids: mediaIds,
91
+ };
92
+ }
93
+
94
+ // Create the tweet
95
+ LogStatus('Creating tweet...');
96
+ const tweet = await this.createTweet(tweetData);
97
+
98
+ // Normalize the created tweet
99
+ const normalizedPost = this.normalizePost(tweet);
100
+
101
+ // Get user info for additional context
102
+ const user = await this.getCurrentUser();
103
+
104
+ // Update output parameters
105
+ const outputParams = [...Params];
106
+ const postParam = outputParams.find((p) => p.Name === 'CreatedPost');
107
+ if (postParam) postParam.Value = normalizedPost;
108
+ const tweetIdParam = outputParams.find((p) => p.Name === 'TweetID');
109
+ if (tweetIdParam) tweetIdParam.Value = tweet.id;
110
+ const tweetUrlParam = outputParams.find((p) => p.Name === 'TweetURL');
111
+ if (tweetUrlParam) tweetUrlParam.Value = `https://twitter.com/${user.username}/status/${tweet.id}`;
112
+
113
+ return {
114
+ Success: true,
115
+ ResultCode: 'SUCCESS',
116
+ Message: `Successfully created tweet (ID: ${tweet.id})`,
117
+ Params: outputParams,
118
+ };
119
+ } catch (error) {
120
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
121
+
122
+ return {
123
+ Success: false,
124
+ ResultCode: this.getErrorCode(error),
125
+ Message: `Failed to create tweet: ${errorMessage}`,
126
+ Params,
127
+ };
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Get error code based on error type
133
+ */
134
+ private getErrorCode(error: any): string {
135
+ if (error instanceof Error) {
136
+ if (error.message.includes('Rate Limit')) return 'RATE_LIMIT';
137
+ if (error.message.includes('Unauthorized')) return 'INVALID_TOKEN';
138
+ if (error.message.includes('character limit')) return 'CONTENT_TOO_LONG';
139
+ if (error.message.includes('media')) return 'INVALID_MEDIA';
204
140
  }
205
- }
141
+ return 'ERROR';
142
+ }
143
+
144
+ /**
145
+ * Define the parameters this action expects
146
+ */
147
+ public get Params(): ActionParam[] {
148
+ return [
149
+ ...this.commonSocialParams,
150
+ {
151
+ Name: 'Content',
152
+ Type: 'Input',
153
+ Value: null,
154
+ },
155
+ {
156
+ Name: 'MediaFiles',
157
+ Type: 'Input',
158
+ Value: null,
159
+ },
160
+ {
161
+ Name: 'ReplyToTweetID',
162
+ Type: 'Input',
163
+ Value: null,
164
+ },
165
+ {
166
+ Name: 'QuoteTweetID',
167
+ Type: 'Input',
168
+ Value: null,
169
+ },
170
+ {
171
+ Name: 'PollOptions',
172
+ Type: 'Input',
173
+ Value: null,
174
+ },
175
+ {
176
+ Name: 'PollDurationMinutes',
177
+ Type: 'Input',
178
+ Value: 1440, // Default 24 hours
179
+ },
180
+ {
181
+ Name: 'CreatedPost',
182
+ Type: 'Output',
183
+ Value: null,
184
+ },
185
+ {
186
+ Name: 'TweetID',
187
+ Type: 'Output',
188
+ Value: null,
189
+ },
190
+ {
191
+ Name: 'TweetURL',
192
+ Type: 'Output',
193
+ Value: null,
194
+ },
195
+ ];
196
+ }
197
+
198
+ /**
199
+ * Get action description
200
+ */
201
+ public get Description(): string {
202
+ return 'Creates a tweet on Twitter/X with optional media attachments, polls, replies, or quote tweets';
203
+ }
204
+ }
@@ -1,7 +1,7 @@
1
1
  import { RegisterClass } from '@memberjunction/global';
2
2
  import { TwitterBaseAction } from '../twitter-base.action';
3
3
  import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
4
- import { LogStatus, LogError } from '@memberjunction/core';
4
+ import { LogStatus, LogError } from '@memberjunction/global';
5
5
  import { BaseAction } from '@memberjunction/actions';
6
6
 
7
7
  /**
@@ -9,146 +9,145 @@ import { BaseAction } from '@memberjunction/actions';
9
9
  */
10
10
  @RegisterClass(BaseAction, 'TwitterDeleteTweetAction')
11
11
  export class TwitterDeleteTweetAction extends TwitterBaseAction {
12
- /**
13
- * Delete a tweet from Twitter
14
- */
15
- protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
16
- const { Params, ContextUser } = params;
17
-
18
- try {
19
- // Initialize OAuth
20
- const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
21
- if (!await this.initializeOAuth(companyIntegrationId)) {
22
- throw new Error('Failed to initialize OAuth connection');
23
- }
12
+ /**
13
+ * Delete a tweet from Twitter
14
+ */
15
+ protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
16
+ const { Params, ContextUser } = params;
24
17
 
25
- // Extract parameters
26
- const tweetId = this.getParamValue(Params, 'TweetID');
27
- const confirmDeletion = this.getParamValue(Params, 'ConfirmDeletion') === true;
18
+ try {
19
+ // Initialize OAuth
20
+ const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
21
+ if (!(await this.initializeOAuth(companyIntegrationId))) {
22
+ throw new Error('Failed to initialize OAuth connection');
23
+ }
28
24
 
29
- // Validate required parameters
30
- if (!tweetId) {
31
- throw new Error('TweetID is required');
32
- }
25
+ // Extract parameters
26
+ const tweetId = this.getParamValue(Params, 'TweetID');
27
+ const confirmDeletion = this.getParamValue(Params, 'ConfirmDeletion') === true;
33
28
 
34
- // Safety check - require explicit confirmation
35
- if (!confirmDeletion) {
36
- return {
37
- Success: false,
38
- ResultCode: 'CONFIRMATION_REQUIRED',
39
- Message: 'Tweet deletion requires explicit confirmation. Set ConfirmDeletion to true.',
40
- Params
41
- };
42
- }
29
+ // Validate required parameters
30
+ if (!tweetId) {
31
+ throw new Error('TweetID is required');
32
+ }
43
33
 
44
- // Get the tweet details before deletion (for output)
45
- let tweetDetails: any = null;
46
- try {
47
- LogStatus(`Retrieving tweet details for ID: ${tweetId}...`);
48
- const response = await this.axiosInstance.get(`/tweets/${tweetId}`, {
49
- params: {
50
- 'tweet.fields': 'id,text,created_at,author_id,public_metrics',
51
- 'expansions': 'author_id',
52
- 'user.fields': 'id,username'
53
- }
54
- });
34
+ // Safety check - require explicit confirmation
35
+ if (!confirmDeletion) {
36
+ return {
37
+ Success: false,
38
+ ResultCode: 'CONFIRMATION_REQUIRED',
39
+ Message: 'Tweet deletion requires explicit confirmation. Set ConfirmDeletion to true.',
40
+ Params,
41
+ };
42
+ }
55
43
 
56
- if (response.data.data) {
57
- tweetDetails = {
58
- id: response.data.data.id,
59
- text: response.data.data.text,
60
- createdAt: response.data.data.created_at,
61
- metrics: response.data.data.public_metrics
62
- };
44
+ // Get the tweet details before deletion (for output)
45
+ let tweetDetails: any = null;
46
+ try {
47
+ LogStatus(`Retrieving tweet details for ID: ${tweetId}...`);
48
+ const response = await this.axiosInstance.get(`/tweets/${tweetId}`, {
49
+ params: {
50
+ 'tweet.fields': 'id,text,created_at,author_id,public_metrics',
51
+ expansions: 'author_id',
52
+ 'user.fields': 'id,username',
53
+ },
54
+ });
63
55
 
64
- // Verify ownership
65
- const currentUser = await this.getCurrentUser();
66
- if (response.data.data.author_id !== currentUser.id) {
67
- throw new Error('You can only delete your own tweets');
68
- }
69
- }
70
- } catch (error) {
71
- // If we can't retrieve the tweet, it might already be deleted or we don't have access
72
- LogStatus('Could not retrieve tweet details. It may already be deleted or inaccessible.');
73
- }
56
+ if (response.data.data) {
57
+ tweetDetails = {
58
+ id: response.data.data.id,
59
+ text: response.data.data.text,
60
+ createdAt: response.data.data.created_at,
61
+ metrics: response.data.data.public_metrics,
62
+ };
74
63
 
75
- // Delete the tweet
76
- LogStatus(`Deleting tweet ID: ${tweetId}...`);
77
- await this.deleteTweet(tweetId);
64
+ // Verify ownership
65
+ const currentUser = await this.getCurrentUser();
66
+ if (response.data.data.author_id !== currentUser.id) {
67
+ throw new Error('You can only delete your own tweets');
68
+ }
69
+ }
70
+ } catch (error) {
71
+ // If we can't retrieve the tweet, it might already be deleted or we don't have access
72
+ LogStatus('Could not retrieve tweet details. It may already be deleted or inaccessible.');
73
+ }
78
74
 
79
- // Update output parameters
80
- const outputParams = [...Params];
81
- const deletedDetailsParam = outputParams.find(p => p.Name === 'DeletedTweetDetails');
82
- if (deletedDetailsParam && tweetDetails) deletedDetailsParam.Value = tweetDetails;
83
- const deletionTimeParam = outputParams.find(p => p.Name === 'DeletionTime');
84
- if (deletionTimeParam) deletionTimeParam.Value = new Date().toISOString();
75
+ // Delete the tweet
76
+ LogStatus(`Deleting tweet ID: ${tweetId}...`);
77
+ await this.deleteTweet(tweetId);
85
78
 
86
- return {
87
- Success: true,
88
- ResultCode: 'SUCCESS',
89
- Message: `Successfully deleted tweet (ID: ${tweetId})`,
90
- Params: outputParams
91
- };
79
+ // Update output parameters
80
+ const outputParams = [...Params];
81
+ const deletedDetailsParam = outputParams.find((p) => p.Name === 'DeletedTweetDetails');
82
+ if (deletedDetailsParam && tweetDetails) deletedDetailsParam.Value = tweetDetails;
83
+ const deletionTimeParam = outputParams.find((p) => p.Name === 'DeletionTime');
84
+ if (deletionTimeParam) deletionTimeParam.Value = new Date().toISOString();
92
85
 
93
- } catch (error) {
94
- const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
95
-
96
- return {
97
- Success: false,
98
- ResultCode: this.getErrorCode(error),
99
- Message: `Failed to delete tweet: ${errorMessage}`,
100
- Params
101
- };
102
- }
103
- }
86
+ return {
87
+ Success: true,
88
+ ResultCode: 'SUCCESS',
89
+ Message: `Successfully deleted tweet (ID: ${tweetId})`,
90
+ Params: outputParams,
91
+ };
92
+ } catch (error) {
93
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
104
94
 
105
- /**
106
- * Get error code based on error type
107
- */
108
- private getErrorCode(error: any): string {
109
- if (error instanceof Error) {
110
- if (error.message.includes('Rate Limit')) return 'RATE_LIMIT';
111
- if (error.message.includes('Unauthorized')) return 'INVALID_TOKEN';
112
- if (error.message.includes('Not Found')) return 'TWEET_NOT_FOUND';
113
- if (error.message.includes('Forbidden')) return 'INSUFFICIENT_PERMISSIONS';
114
- if (error.message.includes('own tweets')) return 'NOT_OWNER';
115
- }
116
- return 'ERROR';
95
+ return {
96
+ Success: false,
97
+ ResultCode: this.getErrorCode(error),
98
+ Message: `Failed to delete tweet: ${errorMessage}`,
99
+ Params,
100
+ };
117
101
  }
102
+ }
118
103
 
119
- /**
120
- * Define the parameters this action expects
121
- */
122
- public get Params(): ActionParam[] {
123
- return [
124
- ...this.commonSocialParams,
125
- {
126
- Name: 'TweetID',
127
- Type: 'Input',
128
- Value: null
129
- },
130
- {
131
- Name: 'ConfirmDeletion',
132
- Type: 'Input',
133
- Value: false
134
- },
135
- {
136
- Name: 'DeletedTweetDetails',
137
- Type: 'Output',
138
- Value: null
139
- },
140
- {
141
- Name: 'DeletionTime',
142
- Type: 'Output',
143
- Value: null
144
- }
145
- ];
104
+ /**
105
+ * Get error code based on error type
106
+ */
107
+ private getErrorCode(error: any): string {
108
+ if (error instanceof Error) {
109
+ if (error.message.includes('Rate Limit')) return 'RATE_LIMIT';
110
+ if (error.message.includes('Unauthorized')) return 'INVALID_TOKEN';
111
+ if (error.message.includes('Not Found')) return 'TWEET_NOT_FOUND';
112
+ if (error.message.includes('Forbidden')) return 'INSUFFICIENT_PERMISSIONS';
113
+ if (error.message.includes('own tweets')) return 'NOT_OWNER';
146
114
  }
115
+ return 'ERROR';
116
+ }
147
117
 
148
- /**
149
- * Get action description
150
- */
151
- public get Description(): string {
152
- return 'Deletes a tweet from Twitter/X. Requires explicit confirmation and ownership of the tweet.';
153
- }
154
- }
118
+ /**
119
+ * Define the parameters this action expects
120
+ */
121
+ public get Params(): ActionParam[] {
122
+ return [
123
+ ...this.commonSocialParams,
124
+ {
125
+ Name: 'TweetID',
126
+ Type: 'Input',
127
+ Value: null,
128
+ },
129
+ {
130
+ Name: 'ConfirmDeletion',
131
+ Type: 'Input',
132
+ Value: false,
133
+ },
134
+ {
135
+ Name: 'DeletedTweetDetails',
136
+ Type: 'Output',
137
+ Value: null,
138
+ },
139
+ {
140
+ Name: 'DeletionTime',
141
+ Type: 'Output',
142
+ Value: null,
143
+ },
144
+ ];
145
+ }
146
+
147
+ /**
148
+ * Get action description
149
+ */
150
+ public get Description(): string {
151
+ return 'Deletes a tweet from Twitter/X. Requires explicit confirmation and ownership of the tweet.';
152
+ }
153
+ }