@memberjunction/actions-bizapps-social 2.111.0 → 2.112.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +6 -6
- package/dist/base/base-social.action.d.ts.map +1 -1
- package/dist/base/base-social.action.js +18 -24
- package/dist/base/base-social.action.js.map +1 -1
- package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -1
- package/dist/providers/buffer/buffer-base.action.js +35 -34
- package/dist/providers/buffer/buffer-base.action.js.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.js +33 -33
- package/dist/providers/facebook/actions/boost-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.js +34 -36
- package/dist/providers/facebook/actions/create-album.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.js +20 -20
- package/dist/providers/facebook/actions/create-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.js +25 -27
- package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.js +19 -23
- package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.js +28 -32
- package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.js +42 -44
- package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.js +29 -29
- package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.js +37 -39
- package/dist/providers/facebook/actions/search-posts.action.js.map +1 -1
- package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -1
- package/dist/providers/facebook/facebook-base.action.js +44 -59
- package/dist/providers/facebook/facebook-base.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +33 -31
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +28 -32
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +19 -19
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.js +24 -26
- package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +22 -22
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js +32 -34
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.js +43 -52
- package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +30 -28
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.js +18 -20
- package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.js +27 -26
- package/dist/providers/instagram/actions/create-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.js +35 -35
- package/dist/providers/instagram/actions/create-story.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.js +38 -59
- package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.js +29 -29
- package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.js +36 -36
- package/dist/providers/instagram/actions/get-comments.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.js +23 -25
- package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.js +25 -25
- package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.js +56 -60
- package/dist/providers/instagram/actions/search-posts.action.js.map +1 -1
- package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -1
- package/dist/providers/instagram/instagram-base.action.js +25 -27
- package/dist/providers/instagram/instagram-base.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.js +55 -45
- package/dist/providers/linkedin/actions/create-article.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.js +31 -29
- package/dist/providers/linkedin/actions/create-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.js +28 -28
- package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.js +20 -20
- package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.js +19 -19
- package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.js +25 -23
- package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.js +32 -30
- package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.js +28 -30
- package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.js +33 -38
- package/dist/providers/linkedin/linkedin-base.action.js.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.js +25 -26
- package/dist/providers/tiktok/tiktok-base.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.js +25 -29
- package/dist/providers/twitter/actions/create-thread.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.js +23 -23
- package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.js +19 -19
- package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.js +40 -47
- package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.js +30 -31
- package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.js +29 -29
- package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.js +26 -26
- package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.js +56 -58
- package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -1
- package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -1
- package/dist/providers/twitter/twitter-base.action.js +58 -68
- package/dist/providers/twitter/twitter-base.action.js.map +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -1
- package/dist/providers/youtube/youtube-base.action.js +22 -25
- package/dist/providers/youtube/youtube-base.action.js.map +1 -1
- package/package.json +5 -6
- package/src/base/base-social.action.ts +217 -224
- package/src/providers/buffer/buffer-base.action.ts +435 -441
- package/src/providers/facebook/actions/boost-post.action.ts +350 -386
- package/src/providers/facebook/actions/create-album.action.ts +291 -307
- package/src/providers/facebook/actions/create-post.action.ts +224 -227
- package/src/providers/facebook/actions/get-page-insights.action.ts +383 -403
- package/src/providers/facebook/actions/get-page-posts.action.ts +214 -225
- package/src/providers/facebook/actions/get-post-insights.action.ts +300 -316
- package/src/providers/facebook/actions/respond-to-comments.action.ts +319 -336
- package/src/providers/facebook/actions/schedule-post.action.ts +289 -292
- package/src/providers/facebook/actions/search-posts.action.ts +399 -413
- package/src/providers/facebook/facebook-base.action.ts +653 -670
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +184 -189
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +160 -161
- package/src/providers/hootsuite/actions/get-analytics.action.ts +249 -254
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +206 -207
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +206 -205
- package/src/providers/hootsuite/actions/search-posts.action.ts +351 -369
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +211 -209
- package/src/providers/hootsuite/hootsuite-base.action.ts +301 -307
- package/src/providers/instagram/actions/create-post.action.ts +276 -296
- package/src/providers/instagram/actions/create-story.action.ts +378 -394
- package/src/providers/instagram/actions/get-account-insights.action.ts +384 -420
- package/src/providers/instagram/actions/get-business-posts.action.ts +233 -242
- package/src/providers/instagram/actions/get-comments.action.ts +365 -377
- package/src/providers/instagram/actions/get-post-insights.action.ts +265 -273
- package/src/providers/instagram/actions/schedule-post.action.ts +233 -235
- package/src/providers/instagram/actions/search-posts.action.ts +512 -538
- package/src/providers/instagram/instagram-base.action.ts +368 -393
- package/src/providers/linkedin/actions/create-article.action.ts +275 -266
- package/src/providers/linkedin/actions/create-post.action.ts +179 -177
- package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +146 -147
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +138 -139
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +190 -189
- package/src/providers/linkedin/actions/schedule-post.action.ts +191 -189
- package/src/providers/linkedin/actions/search-posts.action.ts +275 -283
- package/src/providers/linkedin/linkedin-base.action.ts +407 -421
- package/src/providers/tiktok/tiktok-base.action.ts +305 -320
- package/src/providers/twitter/actions/create-thread.action.ts +203 -207
- package/src/providers/twitter/actions/create-tweet.action.ts +187 -188
- package/src/providers/twitter/actions/delete-tweet.action.ts +128 -129
- package/src/providers/twitter/actions/get-analytics.action.ts +402 -411
- package/src/providers/twitter/actions/get-mentions.action.ts +218 -219
- package/src/providers/twitter/actions/get-timeline.action.ts +232 -233
- package/src/providers/twitter/actions/schedule-tweet.action.ts +221 -222
- package/src/providers/twitter/actions/search-tweets.action.ts +540 -543
- package/src/providers/twitter/twitter-base.action.ts +541 -560
- package/src/providers/youtube/youtube-base.action.ts +320 -333
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RegisterClass } from '@memberjunction/global';
|
|
2
2
|
import { TwitterBaseAction, CreateTweetData, Tweet } from '../twitter-base.action';
|
|
3
3
|
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
|
|
4
|
-
import { LogStatus, LogError } from '@memberjunction/
|
|
4
|
+
import { LogStatus, LogError } from '@memberjunction/global';
|
|
5
5
|
import { MediaFile, SocialPost } from '../../../base/base-social.action';
|
|
6
6
|
import { BaseAction } from '@memberjunction/actions';
|
|
7
7
|
|
|
@@ -10,219 +10,215 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
10
10
|
*/
|
|
11
11
|
@RegisterClass(BaseAction, 'TwitterCreateThreadAction')
|
|
12
12
|
export class TwitterCreateThreadAction extends TwitterBaseAction {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Create a thread 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 tweets = this.getParamValue(Params, 'Tweets');
|
|
28
|
+
const mediaFilesByTweet = this.getParamValue(Params, 'MediaFilesByTweet');
|
|
29
|
+
const includeNumbers = this.getParamValue(Params, 'IncludeNumbers') !== false; // Default true
|
|
30
|
+
const numberFormat = this.getParamValue(Params, 'NumberFormat') || '{n}/{total}'; // Default format
|
|
31
|
+
|
|
32
|
+
// Validate required parameters
|
|
33
|
+
if (!tweets || !Array.isArray(tweets) || tweets.length === 0) {
|
|
34
|
+
throw new Error('Tweets array is required and must not be empty');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (tweets.length < 2) {
|
|
38
|
+
throw new Error('A thread must contain at least 2 tweets');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (tweets.length > 25) {
|
|
42
|
+
throw new Error('Twitter threads are limited to 25 tweets');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Prepare tweets with numbering if requested
|
|
46
|
+
const preparedTweets = includeNumbers ? this.addThreadNumbers(tweets, numberFormat) : tweets;
|
|
47
|
+
|
|
48
|
+
// Validate all tweet lengths
|
|
49
|
+
for (let i = 0; i < preparedTweets.length; i++) {
|
|
50
|
+
if (preparedTweets[i].length > 280) {
|
|
51
|
+
throw new Error(`Tweet ${i + 1} exceeds Twitter's 280 character limit (current: ${preparedTweets[i].length} characters)`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
const createdTweets: Tweet[] = [];
|
|
56
|
+
const createdPosts: SocialPost[] = [];
|
|
57
|
+
let previousTweetId: string | undefined;
|
|
44
58
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
try {
|
|
60
|
+
// Create tweets in sequence
|
|
61
|
+
for (let i = 0; i < preparedTweets.length; i++) {
|
|
62
|
+
LogStatus(`Creating tweet ${i + 1} of ${preparedTweets.length}...`);
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
throw new Error(`Tweet ${i + 1} exceeds Twitter's 280 character limit (current: ${preparedTweets[i].length} characters)`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
64
|
+
const tweetData: CreateTweetData = {
|
|
65
|
+
text: preparedTweets[i],
|
|
66
|
+
};
|
|
56
67
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
// Create tweets in sequence
|
|
63
|
-
for (let i = 0; i < preparedTweets.length; i++) {
|
|
64
|
-
LogStatus(`Creating tweet ${i + 1} of ${preparedTweets.length}...`);
|
|
65
|
-
|
|
66
|
-
const tweetData: CreateTweetData = {
|
|
67
|
-
text: preparedTweets[i]
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// Reply to previous tweet in thread
|
|
71
|
-
if (previousTweetId) {
|
|
72
|
-
tweetData.reply = {
|
|
73
|
-
in_reply_to_tweet_id: previousTweetId
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Add media if provided for this tweet
|
|
78
|
-
if (mediaFilesByTweet && mediaFilesByTweet[i]) {
|
|
79
|
-
const mediaFiles = mediaFilesByTweet[i];
|
|
80
|
-
if (Array.isArray(mediaFiles) && mediaFiles.length > 0) {
|
|
81
|
-
if (mediaFiles.length > 4) {
|
|
82
|
-
throw new Error(`Tweet ${i + 1}: Twitter supports a maximum of 4 media items per tweet`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
LogStatus(`Uploading ${mediaFiles.length} media files for tweet ${i + 1}...`);
|
|
86
|
-
const mediaIds = await this.uploadMedia(mediaFiles as MediaFile[]);
|
|
87
|
-
|
|
88
|
-
tweetData.media = {
|
|
89
|
-
media_ids: mediaIds
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Create the tweet
|
|
95
|
-
const tweet = await this.createTweet(tweetData);
|
|
96
|
-
createdTweets.push(tweet);
|
|
97
|
-
createdPosts.push(this.normalizePost(tweet));
|
|
98
|
-
previousTweetId = tweet.id;
|
|
99
|
-
|
|
100
|
-
// Small delay between tweets to avoid rate limiting
|
|
101
|
-
if (i < preparedTweets.length - 1) {
|
|
102
|
-
await new Promise(resolve => setTimeout(resolve, 1000)); // 1 second delay
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Get user info for URLs
|
|
107
|
-
const user = await this.getCurrentUser();
|
|
108
|
-
|
|
109
|
-
// Build thread URL (link to first tweet)
|
|
110
|
-
const threadUrl = `https://twitter.com/${user.username}/status/${createdTweets[0].id}`;
|
|
111
|
-
|
|
112
|
-
// Update output parameters
|
|
113
|
-
const outputParams = [...Params];
|
|
114
|
-
const postsParam = outputParams.find(p => p.Name === 'CreatedPosts');
|
|
115
|
-
if (postsParam) postsParam.Value = createdPosts;
|
|
116
|
-
const tweetIdsParam = outputParams.find(p => p.Name === 'TweetIDs');
|
|
117
|
-
if (tweetIdsParam) tweetIdsParam.Value = createdTweets.map(t => t.id);
|
|
118
|
-
const threadUrlParam = outputParams.find(p => p.Name === 'ThreadURL');
|
|
119
|
-
if (threadUrlParam) threadUrlParam.Value = threadUrl;
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
Success: true,
|
|
123
|
-
ResultCode: 'SUCCESS',
|
|
124
|
-
Message: `Successfully created thread with ${createdTweets.length} tweets`,
|
|
125
|
-
Params: outputParams
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
} catch (error) {
|
|
129
|
-
// If thread creation fails partway through, note which tweets were created
|
|
130
|
-
if (createdTweets.length > 0) {
|
|
131
|
-
LogError(`Thread creation failed after creating ${createdTweets.length} tweets. Tweet IDs: ${createdTweets.map(t => t.id).join(', ')}`);
|
|
132
|
-
}
|
|
133
|
-
throw error;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
} catch (error) {
|
|
137
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
138
|
-
|
|
139
|
-
return {
|
|
140
|
-
Success: false,
|
|
141
|
-
ResultCode: this.getErrorCode(error),
|
|
142
|
-
Message: `Failed to create thread: ${errorMessage}`,
|
|
143
|
-
Params
|
|
68
|
+
// Reply to previous tweet in thread
|
|
69
|
+
if (previousTweetId) {
|
|
70
|
+
tweetData.reply = {
|
|
71
|
+
in_reply_to_tweet_id: previousTweetId,
|
|
144
72
|
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Add media if provided for this tweet
|
|
76
|
+
if (mediaFilesByTweet && mediaFilesByTweet[i]) {
|
|
77
|
+
const mediaFiles = mediaFilesByTweet[i];
|
|
78
|
+
if (Array.isArray(mediaFiles) && mediaFiles.length > 0) {
|
|
79
|
+
if (mediaFiles.length > 4) {
|
|
80
|
+
throw new Error(`Tweet ${i + 1}: Twitter supports a maximum of 4 media items per tweet`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
LogStatus(`Uploading ${mediaFiles.length} media files for tweet ${i + 1}...`);
|
|
84
|
+
const mediaIds = await this.uploadMedia(mediaFiles as MediaFile[]);
|
|
85
|
+
|
|
86
|
+
tweetData.media = {
|
|
87
|
+
media_ids: mediaIds,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Create the tweet
|
|
93
|
+
const tweet = await this.createTweet(tweetData);
|
|
94
|
+
createdTweets.push(tweet);
|
|
95
|
+
createdPosts.push(this.normalizePost(tweet));
|
|
96
|
+
previousTweetId = tweet.id;
|
|
97
|
+
|
|
98
|
+
// Small delay between tweets to avoid rate limiting
|
|
99
|
+
if (i < preparedTweets.length - 1) {
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // 1 second delay
|
|
101
|
+
}
|
|
145
102
|
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Add thread numbers to tweets
|
|
150
|
-
*/
|
|
151
|
-
private addThreadNumbers(tweets: string[], format: string): string[] {
|
|
152
|
-
const total = tweets.length;
|
|
153
|
-
|
|
154
|
-
return tweets.map((tweet, index) => {
|
|
155
|
-
const number = index + 1;
|
|
156
|
-
const threadNumber = format
|
|
157
|
-
.replace('{n}', number.toString())
|
|
158
|
-
.replace('{total}', total.toString());
|
|
159
|
-
|
|
160
|
-
// Add number to beginning of tweet with a space
|
|
161
|
-
return `${threadNumber} ${tweet}`;
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
103
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
104
|
+
// Get user info for URLs
|
|
105
|
+
const user = await this.getCurrentUser();
|
|
106
|
+
|
|
107
|
+
// Build thread URL (link to first tweet)
|
|
108
|
+
const threadUrl = `https://twitter.com/${user.username}/status/${createdTweets[0].id}`;
|
|
109
|
+
|
|
110
|
+
// Update output parameters
|
|
111
|
+
const outputParams = [...Params];
|
|
112
|
+
const postsParam = outputParams.find((p) => p.Name === 'CreatedPosts');
|
|
113
|
+
if (postsParam) postsParam.Value = createdPosts;
|
|
114
|
+
const tweetIdsParam = outputParams.find((p) => p.Name === 'TweetIDs');
|
|
115
|
+
if (tweetIdsParam) tweetIdsParam.Value = createdTweets.map((t) => t.id);
|
|
116
|
+
const threadUrlParam = outputParams.find((p) => p.Name === 'ThreadURL');
|
|
117
|
+
if (threadUrlParam) threadUrlParam.Value = threadUrl;
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
Success: true,
|
|
121
|
+
ResultCode: 'SUCCESS',
|
|
122
|
+
Message: `Successfully created thread with ${createdTweets.length} tweets`,
|
|
123
|
+
Params: outputParams,
|
|
124
|
+
};
|
|
125
|
+
} catch (error) {
|
|
126
|
+
// If thread creation fails partway through, note which tweets were created
|
|
127
|
+
if (createdTweets.length > 0) {
|
|
128
|
+
LogError(
|
|
129
|
+
`Thread creation failed after creating ${createdTweets.length} tweets. Tweet IDs: ${createdTweets.map((t) => t.id).join(', ')}`
|
|
130
|
+
);
|
|
174
131
|
}
|
|
175
|
-
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
Success: false,
|
|
139
|
+
ResultCode: this.getErrorCode(error),
|
|
140
|
+
Message: `Failed to create thread: ${errorMessage}`,
|
|
141
|
+
Params,
|
|
142
|
+
};
|
|
176
143
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
Name: 'CreatedPosts',
|
|
206
|
-
Type: 'Output',
|
|
207
|
-
Value: null
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
Name: 'TweetIDs',
|
|
211
|
-
Type: 'Output',
|
|
212
|
-
Value: null
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
Name: 'ThreadURL',
|
|
216
|
-
Type: 'Output',
|
|
217
|
-
Value: null
|
|
218
|
-
}
|
|
219
|
-
];
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Get action description
|
|
224
|
-
*/
|
|
225
|
-
public get Description(): string {
|
|
226
|
-
return 'Creates a thread (series of connected tweets) on Twitter/X with optional media attachments and automatic numbering';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Add thread numbers to tweets
|
|
148
|
+
*/
|
|
149
|
+
private addThreadNumbers(tweets: string[], format: string): string[] {
|
|
150
|
+
const total = tweets.length;
|
|
151
|
+
|
|
152
|
+
return tweets.map((tweet, index) => {
|
|
153
|
+
const number = index + 1;
|
|
154
|
+
const threadNumber = format.replace('{n}', number.toString()).replace('{total}', total.toString());
|
|
155
|
+
|
|
156
|
+
// Add number to beginning of tweet with a space
|
|
157
|
+
return `${threadNumber} ${tweet}`;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get error code based on error type
|
|
163
|
+
*/
|
|
164
|
+
private getErrorCode(error: any): string {
|
|
165
|
+
if (error instanceof Error) {
|
|
166
|
+
if (error.message.includes('Rate Limit')) return 'RATE_LIMIT';
|
|
167
|
+
if (error.message.includes('Unauthorized')) return 'INVALID_TOKEN';
|
|
168
|
+
if (error.message.includes('character limit')) return 'CONTENT_TOO_LONG';
|
|
169
|
+
if (error.message.includes('media')) return 'INVALID_MEDIA';
|
|
227
170
|
}
|
|
228
|
-
|
|
171
|
+
return 'ERROR';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Define the parameters this action expects
|
|
176
|
+
*/
|
|
177
|
+
public get Params(): ActionParam[] {
|
|
178
|
+
return [
|
|
179
|
+
...this.commonSocialParams,
|
|
180
|
+
{
|
|
181
|
+
Name: 'Tweets',
|
|
182
|
+
Type: 'Input',
|
|
183
|
+
Value: null,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
Name: 'MediaFilesByTweet',
|
|
187
|
+
Type: 'Input',
|
|
188
|
+
Value: null,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
Name: 'IncludeNumbers',
|
|
192
|
+
Type: 'Input',
|
|
193
|
+
Value: true,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
Name: 'NumberFormat',
|
|
197
|
+
Type: 'Input',
|
|
198
|
+
Value: '{n}/{total}',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
Name: 'CreatedPosts',
|
|
202
|
+
Type: 'Output',
|
|
203
|
+
Value: null,
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
Name: 'TweetIDs',
|
|
207
|
+
Type: 'Output',
|
|
208
|
+
Value: null,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
Name: 'ThreadURL',
|
|
212
|
+
Type: 'Output',
|
|
213
|
+
Value: null,
|
|
214
|
+
},
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get action description
|
|
220
|
+
*/
|
|
221
|
+
public get Description(): string {
|
|
222
|
+
return 'Creates a thread (series of connected tweets) on Twitter/X with optional media attachments and automatic numbering';
|
|
223
|
+
}
|
|
224
|
+
}
|