@memberjunction/actions-bizapps-social 2.112.0 → 2.113.1
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 +13 -0
- package/dist/base/base-social.action.d.ts.map +1 -1
- package/dist/base/base-social.action.js +24 -18
- 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 +34 -35
- 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 +36 -34
- 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 +27 -25
- 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 +23 -19
- 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 +32 -28
- 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 +44 -42
- 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 +39 -37
- 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 +59 -44
- 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 +31 -33
- 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 +32 -28
- 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 +26 -24
- 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 +34 -32
- 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 +52 -43
- 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 +28 -30
- 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 +20 -18
- 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 +26 -27
- 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 +59 -38
- 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 +25 -23
- 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 +60 -56
- 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 +27 -25
- 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 +45 -55
- 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 +29 -31
- 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 +23 -25
- 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 +30 -32
- 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 +30 -28
- 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 +38 -33
- 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 +26 -25
- 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 +29 -25
- 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 +47 -40
- 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 +31 -30
- 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 +58 -56
- 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 +68 -58
- 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 +25 -22
- package/dist/providers/youtube/youtube-base.action.js.map +1 -1
- package/package.json +6 -5
- package/src/base/base-social.action.ts +224 -217
- package/src/providers/buffer/buffer-base.action.ts +441 -435
- package/src/providers/facebook/actions/boost-post.action.ts +386 -350
- package/src/providers/facebook/actions/create-album.action.ts +307 -291
- package/src/providers/facebook/actions/create-post.action.ts +227 -224
- package/src/providers/facebook/actions/get-page-insights.action.ts +403 -383
- package/src/providers/facebook/actions/get-page-posts.action.ts +225 -214
- package/src/providers/facebook/actions/get-post-insights.action.ts +316 -300
- package/src/providers/facebook/actions/respond-to-comments.action.ts +336 -319
- package/src/providers/facebook/actions/schedule-post.action.ts +292 -289
- package/src/providers/facebook/actions/search-posts.action.ts +413 -399
- package/src/providers/facebook/facebook-base.action.ts +670 -653
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +189 -184
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +161 -160
- package/src/providers/hootsuite/actions/get-analytics.action.ts +254 -249
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +207 -206
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +205 -206
- package/src/providers/hootsuite/actions/search-posts.action.ts +369 -351
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +209 -211
- package/src/providers/hootsuite/hootsuite-base.action.ts +307 -301
- package/src/providers/instagram/actions/create-post.action.ts +296 -276
- package/src/providers/instagram/actions/create-story.action.ts +394 -378
- package/src/providers/instagram/actions/get-account-insights.action.ts +420 -384
- package/src/providers/instagram/actions/get-business-posts.action.ts +242 -233
- package/src/providers/instagram/actions/get-comments.action.ts +377 -365
- package/src/providers/instagram/actions/get-post-insights.action.ts +273 -265
- package/src/providers/instagram/actions/schedule-post.action.ts +235 -233
- package/src/providers/instagram/actions/search-posts.action.ts +538 -512
- package/src/providers/instagram/instagram-base.action.ts +393 -368
- package/src/providers/linkedin/actions/create-article.action.ts +266 -275
- package/src/providers/linkedin/actions/create-post.action.ts +177 -179
- package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +147 -146
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +139 -138
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +189 -190
- package/src/providers/linkedin/actions/schedule-post.action.ts +189 -191
- package/src/providers/linkedin/actions/search-posts.action.ts +283 -275
- package/src/providers/linkedin/linkedin-base.action.ts +421 -407
- package/src/providers/tiktok/tiktok-base.action.ts +320 -305
- package/src/providers/twitter/actions/create-thread.action.ts +207 -203
- package/src/providers/twitter/actions/create-tweet.action.ts +188 -187
- package/src/providers/twitter/actions/delete-tweet.action.ts +129 -128
- package/src/providers/twitter/actions/get-analytics.action.ts +411 -402
- package/src/providers/twitter/actions/get-mentions.action.ts +219 -218
- package/src/providers/twitter/actions/get-timeline.action.ts +233 -232
- package/src/providers/twitter/actions/schedule-tweet.action.ts +222 -221
- package/src/providers/twitter/actions/search-tweets.action.ts +543 -540
- package/src/providers/twitter/twitter-base.action.ts +560 -541
- package/src/providers/youtube/youtube-base.action.ts +333 -320
|
@@ -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/
|
|
4
|
+
import { LogStatus, LogError } from '@memberjunction/core';
|
|
5
5
|
import { MediaFile } from '../../../base/base-social.action';
|
|
6
6
|
import { BaseAction } from '@memberjunction/actions';
|
|
7
7
|
|
|
@@ -12,248 +12,249 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
12
12
|
*/
|
|
13
13
|
@RegisterClass(BaseAction, 'TwitterScheduleTweetAction')
|
|
14
14
|
export class TwitterScheduleTweetAction extends TwitterBaseAction {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Schedule a tweet for future posting
|
|
17
|
+
*/
|
|
18
|
+
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
19
|
+
const { Params, ContextUser } = params;
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
// Initialize OAuth
|
|
23
|
+
const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
|
|
24
|
+
if (!await this.initializeOAuth(companyIntegrationId)) {
|
|
25
|
+
throw new Error('Failed to initialize OAuth connection');
|
|
26
|
+
}
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
// Extract parameters
|
|
29
|
+
const content = this.getParamValue(Params, 'Content');
|
|
30
|
+
const scheduledTime = this.getParamValue(Params, 'ScheduledTime');
|
|
31
|
+
const mediaFiles = this.getParamValue(Params, 'MediaFiles');
|
|
32
|
+
const replyToTweetId = this.getParamValue(Params, 'ReplyToTweetID');
|
|
33
|
+
const quoteTweetId = this.getParamValue(Params, 'QuoteTweetID');
|
|
34
|
+
const pollOptions = this.getParamValue(Params, 'PollOptions');
|
|
35
|
+
const pollDurationMinutes = this.getParamValue(Params, 'PollDurationMinutes') || 1440; // Default 24 hours
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const replyToTweetId = this.getParamValue(Params, 'ReplyToTweetID');
|
|
33
|
-
const quoteTweetId = this.getParamValue(Params, 'QuoteTweetID');
|
|
34
|
-
const pollOptions = this.getParamValue(Params, 'PollOptions');
|
|
35
|
-
const pollDurationMinutes = this.getParamValue(Params, 'PollDurationMinutes') || 1440; // Default 24 hours
|
|
37
|
+
// Validate required parameters
|
|
38
|
+
if (!content) {
|
|
39
|
+
throw new Error('Content is required');
|
|
40
|
+
}
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
42
|
+
if (!scheduledTime) {
|
|
43
|
+
throw new Error('ScheduledTime is required');
|
|
44
|
+
}
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
// Validate scheduled time is in the future
|
|
47
|
+
const scheduleDate = new Date(scheduledTime);
|
|
48
|
+
const now = new Date();
|
|
49
|
+
|
|
50
|
+
if (scheduleDate <= now) {
|
|
51
|
+
throw new Error('ScheduledTime must be in the future');
|
|
52
|
+
}
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
// Validate scheduled time is not too far in the future (e.g., 1 year)
|
|
55
|
+
const maxFutureDate = new Date();
|
|
56
|
+
maxFutureDate.setFullYear(maxFutureDate.getFullYear() + 1);
|
|
57
|
+
|
|
58
|
+
if (scheduleDate > maxFutureDate) {
|
|
59
|
+
throw new Error('ScheduledTime cannot be more than 1 year in the future');
|
|
60
|
+
}
|
|
49
61
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
// Validate content length
|
|
63
|
+
if (content.length > 280) {
|
|
64
|
+
throw new Error(`Content exceeds Twitter's 280 character limit (current: ${content.length} characters)`);
|
|
65
|
+
}
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
// Build tweet data structure
|
|
68
|
+
const tweetData: CreateTweetData = {
|
|
69
|
+
text: content
|
|
70
|
+
};
|
|
57
71
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
72
|
+
// Add reply if specified
|
|
73
|
+
if (replyToTweetId) {
|
|
74
|
+
tweetData.reply = {
|
|
75
|
+
in_reply_to_tweet_id: replyToTweetId
|
|
76
|
+
};
|
|
77
|
+
}
|
|
61
78
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
// Add quote tweet if specified
|
|
80
|
+
if (quoteTweetId) {
|
|
81
|
+
tweetData.quote_tweet_id = quoteTweetId;
|
|
82
|
+
}
|
|
66
83
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
// Add poll if specified
|
|
85
|
+
if (pollOptions && Array.isArray(pollOptions) && pollOptions.length >= 2) {
|
|
86
|
+
if (pollOptions.length > 4) {
|
|
87
|
+
throw new Error('Twitter polls support a maximum of 4 options');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Validate poll option lengths
|
|
91
|
+
for (const option of pollOptions) {
|
|
92
|
+
if (option.length > 25) {
|
|
93
|
+
throw new Error(`Poll option "${option}" exceeds 25 character limit`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
71
96
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
97
|
+
tweetData.poll = {
|
|
98
|
+
options: pollOptions,
|
|
99
|
+
duration_minutes: Math.min(Math.max(pollDurationMinutes, 5), 10080)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
78
102
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
103
|
+
// Handle media files
|
|
104
|
+
let uploadedMediaIds: string[] = [];
|
|
105
|
+
if (mediaFiles && Array.isArray(mediaFiles) && mediaFiles.length > 0) {
|
|
106
|
+
if (mediaFiles.length > 4) {
|
|
107
|
+
throw new Error('Twitter supports a maximum of 4 media items per tweet');
|
|
108
|
+
}
|
|
83
109
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Handle media files
|
|
104
|
-
let uploadedMediaIds: string[] = [];
|
|
105
|
-
if (mediaFiles && Array.isArray(mediaFiles) && mediaFiles.length > 0) {
|
|
106
|
-
if (mediaFiles.length > 4) {
|
|
107
|
-
throw new Error('Twitter supports a maximum of 4 media items per tweet');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// For scheduling, we'll upload the media now and store the IDs
|
|
111
|
-
// Note: Twitter media IDs expire after 24 hours if not used
|
|
112
|
-
const hoursUntilScheduled = (scheduleDate.getTime() - now.getTime()) / (1000 * 60 * 60);
|
|
110
|
+
// For scheduling, we'll upload the media now and store the IDs
|
|
111
|
+
// Note: Twitter media IDs expire after 24 hours if not used
|
|
112
|
+
const hoursUntilScheduled = (scheduleDate.getTime() - now.getTime()) / (1000 * 60 * 60);
|
|
113
|
+
|
|
114
|
+
if (hoursUntilScheduled <= 24) {
|
|
115
|
+
// Upload now if scheduling within 24 hours
|
|
116
|
+
LogStatus(`Uploading ${mediaFiles.length} media files...`);
|
|
117
|
+
uploadedMediaIds = await this.uploadMedia(mediaFiles as MediaFile[]);
|
|
118
|
+
tweetData.media = {
|
|
119
|
+
media_ids: uploadedMediaIds
|
|
120
|
+
};
|
|
121
|
+
} else {
|
|
122
|
+
// For tweets scheduled beyond 24 hours, we'll need to store media
|
|
123
|
+
// data and upload closer to the scheduled time
|
|
124
|
+
LogStatus('Media will be uploaded closer to scheduled time due to Twitter\'s 24-hour media expiration');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
113
127
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Create scheduled tweet record
|
|
129
|
-
// In a real implementation, this would save to a database or queue service
|
|
130
|
-
const scheduledTweet = {
|
|
131
|
-
id: this.generateScheduledTweetId(),
|
|
132
|
-
scheduledFor: scheduleDate.toISOString(),
|
|
133
|
-
tweetData: tweetData,
|
|
134
|
-
mediaFiles: mediaFiles, // Store for later upload if needed
|
|
135
|
-
companyIntegrationId: companyIntegrationId,
|
|
136
|
-
createdAt: new Date().toISOString(),
|
|
137
|
-
status: 'scheduled',
|
|
138
|
-
};
|
|
128
|
+
// Create scheduled tweet record
|
|
129
|
+
// In a real implementation, this would save to a database or queue service
|
|
130
|
+
const scheduledTweet = {
|
|
131
|
+
id: this.generateScheduledTweetId(),
|
|
132
|
+
scheduledFor: scheduleDate.toISOString(),
|
|
133
|
+
tweetData: tweetData,
|
|
134
|
+
mediaFiles: mediaFiles, // Store for later upload if needed
|
|
135
|
+
companyIntegrationId: companyIntegrationId,
|
|
136
|
+
createdAt: new Date().toISOString(),
|
|
137
|
+
status: 'scheduled'
|
|
138
|
+
};
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
// Simulate saving to a scheduling service
|
|
141
|
+
LogStatus(`Tweet scheduled for ${scheduleDate.toLocaleString()}`);
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
// Get user info for context
|
|
144
|
+
const user = await this.getCurrentUser();
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
146
|
+
// Update output parameters
|
|
147
|
+
const outputParams = [...Params];
|
|
148
|
+
const scheduledIdParam = outputParams.find(p => p.Name === 'ScheduledTweetID');
|
|
149
|
+
if (scheduledIdParam) scheduledIdParam.Value = scheduledTweet.id;
|
|
150
|
+
const scheduledDataParam = outputParams.find(p => p.Name === 'ScheduledTweetData');
|
|
151
|
+
if (scheduledDataParam) scheduledDataParam.Value = scheduledTweet;
|
|
152
|
+
const estimatedUrlParam = outputParams.find(p => p.Name === 'EstimatedURL');
|
|
153
|
+
if (estimatedUrlParam) estimatedUrlParam.Value = `https://twitter.com/${user.username}/status/[pending]`;
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
} catch (error) {
|
|
162
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
155
|
+
return {
|
|
156
|
+
Success: true,
|
|
157
|
+
ResultCode: 'SUCCESS',
|
|
158
|
+
Message: `Successfully scheduled tweet for ${scheduleDate.toLocaleString()}`,
|
|
159
|
+
Params: outputParams
|
|
160
|
+
};
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
162
|
+
} catch (error) {
|
|
163
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
Success: false,
|
|
167
|
+
ResultCode: this.getErrorCode(error),
|
|
168
|
+
Message: `Failed to schedule tweet: ${errorMessage}`,
|
|
169
|
+
Params
|
|
170
|
+
};
|
|
171
|
+
}
|
|
170
172
|
}
|
|
171
|
-
}
|
|
172
173
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Generate a unique ID for scheduled tweet
|
|
176
|
+
*/
|
|
177
|
+
private generateScheduledTweetId(): string {
|
|
178
|
+
return `scheduled_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
179
|
+
}
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
181
|
+
/**
|
|
182
|
+
* Get error code based on error type
|
|
183
|
+
*/
|
|
184
|
+
private getErrorCode(error: any): string {
|
|
185
|
+
if (error instanceof Error) {
|
|
186
|
+
if (error.message.includes('Rate Limit')) return 'RATE_LIMIT';
|
|
187
|
+
if (error.message.includes('Unauthorized')) return 'INVALID_TOKEN';
|
|
188
|
+
if (error.message.includes('character limit')) return 'CONTENT_TOO_LONG';
|
|
189
|
+
if (error.message.includes('media')) return 'INVALID_MEDIA';
|
|
190
|
+
if (error.message.includes('future')) return 'INVALID_SCHEDULE_TIME';
|
|
191
|
+
}
|
|
192
|
+
return 'ERROR';
|
|
190
193
|
}
|
|
191
|
-
return 'ERROR';
|
|
192
|
-
}
|
|
193
194
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Define the parameters this action expects
|
|
197
|
+
*/
|
|
198
|
+
public get Params(): ActionParam[] {
|
|
199
|
+
return [
|
|
200
|
+
...this.commonSocialParams,
|
|
201
|
+
{
|
|
202
|
+
Name: 'Content',
|
|
203
|
+
Type: 'Input',
|
|
204
|
+
Value: null
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
Name: 'ScheduledTime',
|
|
208
|
+
Type: 'Input',
|
|
209
|
+
Value: null
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
Name: 'MediaFiles',
|
|
213
|
+
Type: 'Input',
|
|
214
|
+
Value: null
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
Name: 'ReplyToTweetID',
|
|
218
|
+
Type: 'Input',
|
|
219
|
+
Value: null
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
Name: 'QuoteTweetID',
|
|
223
|
+
Type: 'Input',
|
|
224
|
+
Value: null
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
Name: 'PollOptions',
|
|
228
|
+
Type: 'Input',
|
|
229
|
+
Value: null
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
Name: 'PollDurationMinutes',
|
|
233
|
+
Type: 'Input',
|
|
234
|
+
Value: 1440 // Default 24 hours
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
Name: 'ScheduledTweetID',
|
|
238
|
+
Type: 'Output',
|
|
239
|
+
Value: null
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
Name: 'ScheduledTweetData',
|
|
243
|
+
Type: 'Output',
|
|
244
|
+
Value: null
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
Name: 'EstimatedURL',
|
|
248
|
+
Type: 'Output',
|
|
249
|
+
Value: null
|
|
250
|
+
}
|
|
251
|
+
];
|
|
252
|
+
}
|
|
252
253
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
254
|
+
/**
|
|
255
|
+
* Get action description
|
|
256
|
+
*/
|
|
257
|
+
public get Description(): string {
|
|
258
|
+
return 'Schedules a tweet for future posting on Twitter/X with optional media attachments, polls, replies, or quote tweets';
|
|
259
|
+
}
|
|
260
|
+
}
|