@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,59 +1,59 @@
|
|
|
1
1
|
import { BaseOAuthAction } from '@memberjunction/actions';
|
|
2
2
|
import { ActionParam } from '@memberjunction/actions-base';
|
|
3
|
-
import { LogStatus, LogError } from '@memberjunction/
|
|
3
|
+
import { LogStatus, LogError } from '@memberjunction/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Common interfaces for social media actions
|
|
7
7
|
*/
|
|
8
8
|
export interface SocialPost {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
id: string;
|
|
10
|
+
platform: string;
|
|
11
|
+
profileId: string;
|
|
12
|
+
content: string;
|
|
13
|
+
mediaUrls: string[];
|
|
14
|
+
publishedAt: Date;
|
|
15
|
+
scheduledFor?: Date;
|
|
16
|
+
analytics?: SocialAnalytics;
|
|
17
|
+
platformSpecificData: Record<string, any>;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface SocialAnalytics {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
impressions: number;
|
|
22
|
+
engagements: number;
|
|
23
|
+
clicks: number;
|
|
24
|
+
shares: number;
|
|
25
|
+
comments: number;
|
|
26
|
+
likes: number;
|
|
27
|
+
reach: number;
|
|
28
|
+
saves?: number;
|
|
29
|
+
videoViews?: number;
|
|
30
|
+
platformMetrics: Record<string, any>;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export interface SearchParams {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
query?: string;
|
|
35
|
+
hashtags?: string[];
|
|
36
|
+
startDate?: Date;
|
|
37
|
+
endDate?: Date;
|
|
38
|
+
limit?: number;
|
|
39
|
+
offset?: number;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export interface MediaFile {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
filename: string;
|
|
44
|
+
mimeType: string;
|
|
45
|
+
data: Buffer | string; // Base64 or buffer
|
|
46
|
+
size: number;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
export enum SocialMediaErrorCode {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
RATE_LIMIT_EXCEEDED = 'RATE_LIMIT',
|
|
51
|
+
INVALID_TOKEN = 'INVALID_TOKEN',
|
|
52
|
+
TOKEN_EXPIRED = 'TOKEN_EXPIRED',
|
|
53
|
+
PLATFORM_ERROR = 'PLATFORM_ERROR',
|
|
54
|
+
INVALID_MEDIA = 'INVALID_MEDIA',
|
|
55
|
+
POST_NOT_FOUND = 'POST_NOT_FOUND',
|
|
56
|
+
INSUFFICIENT_PERMISSIONS = 'INSUFFICIENT_PERMISSIONS'
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
@@ -62,202 +62,209 @@ export enum SocialMediaErrorCode {
|
|
|
62
62
|
* analytics normalization, and rate limiting.
|
|
63
63
|
*/
|
|
64
64
|
export abstract class BaseSocialMediaAction extends BaseOAuthAction {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Get the platform name (e.g., 'Twitter', 'LinkedIn')
|
|
81
|
-
*/
|
|
82
|
-
protected abstract get platformName(): string;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Get the API base URL for the platform
|
|
86
|
-
*/
|
|
87
|
-
protected abstract get apiBaseUrl(): string;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Normalize platform-specific analytics to common format
|
|
91
|
-
*/
|
|
92
|
-
protected normalizeAnalytics(platformData: any): SocialAnalytics {
|
|
93
|
-
// Default implementation - override in platform-specific classes
|
|
94
|
-
return {
|
|
95
|
-
impressions: platformData.impressions || 0,
|
|
96
|
-
engagements: platformData.engagements || 0,
|
|
97
|
-
clicks: platformData.clicks || 0,
|
|
98
|
-
shares: platformData.shares || 0,
|
|
99
|
-
comments: platformData.comments || 0,
|
|
100
|
-
likes: platformData.likes || 0,
|
|
101
|
-
reach: platformData.reach || 0,
|
|
102
|
-
saves: platformData.saves,
|
|
103
|
-
videoViews: platformData.videoViews,
|
|
104
|
-
platformMetrics: platformData,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Upload media files to the platform
|
|
110
|
-
*/
|
|
111
|
-
protected async uploadMedia(files: MediaFile[]): Promise<string[]> {
|
|
112
|
-
const uploadedUrls: string[] = [];
|
|
113
|
-
|
|
114
|
-
for (const file of files) {
|
|
115
|
-
// Validate file
|
|
116
|
-
this.validateMediaFile(file);
|
|
117
|
-
|
|
118
|
-
// Upload file (platform-specific implementation)
|
|
119
|
-
const url = await this.uploadSingleMedia(file);
|
|
120
|
-
uploadedUrls.push(url);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Common parameters for all social media actions
|
|
68
|
+
*/
|
|
69
|
+
protected get commonSocialParams(): ActionParam[] {
|
|
70
|
+
return [
|
|
71
|
+
...this.oauthParams,
|
|
72
|
+
{
|
|
73
|
+
Name: 'ProfileID',
|
|
74
|
+
Type: 'Input',
|
|
75
|
+
Value: null
|
|
76
|
+
}
|
|
77
|
+
];
|
|
121
78
|
}
|
|
122
79
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Get the platform name (e.g., 'Twitter', 'LinkedIn')
|
|
82
|
+
*/
|
|
83
|
+
protected abstract get platformName(): string;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the API base URL for the platform
|
|
87
|
+
*/
|
|
88
|
+
protected abstract get apiBaseUrl(): string;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Normalize platform-specific analytics to common format
|
|
92
|
+
*/
|
|
93
|
+
protected normalizeAnalytics(platformData: any): SocialAnalytics {
|
|
94
|
+
// Default implementation - override in platform-specific classes
|
|
95
|
+
return {
|
|
96
|
+
impressions: platformData.impressions || 0,
|
|
97
|
+
engagements: platformData.engagements || 0,
|
|
98
|
+
clicks: platformData.clicks || 0,
|
|
99
|
+
shares: platformData.shares || 0,
|
|
100
|
+
comments: platformData.comments || 0,
|
|
101
|
+
likes: platformData.likes || 0,
|
|
102
|
+
reach: platformData.reach || 0,
|
|
103
|
+
saves: platformData.saves,
|
|
104
|
+
videoViews: platformData.videoViews,
|
|
105
|
+
platformMetrics: platformData
|
|
106
|
+
};
|
|
145
107
|
}
|
|
146
108
|
|
|
147
|
-
|
|
148
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Upload media files to the platform
|
|
111
|
+
*/
|
|
112
|
+
protected async uploadMedia(files: MediaFile[]): Promise<string[]> {
|
|
113
|
+
const uploadedUrls: string[] = [];
|
|
114
|
+
|
|
115
|
+
for (const file of files) {
|
|
116
|
+
// Validate file
|
|
117
|
+
this.validateMediaFile(file);
|
|
118
|
+
|
|
119
|
+
// Upload file (platform-specific implementation)
|
|
120
|
+
const url = await this.uploadSingleMedia(file);
|
|
121
|
+
uploadedUrls.push(url);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return uploadedUrls;
|
|
149
125
|
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Handle rate limiting with exponential backoff
|
|
154
|
-
*/
|
|
155
|
-
protected async handleRateLimit(retryAfter?: number): Promise<void> {
|
|
156
|
-
const waitTime = retryAfter || 60; // Default to 60 seconds
|
|
157
|
-
LogStatus(`Rate limit hit. Waiting ${waitTime} seconds...`);
|
|
158
|
-
|
|
159
|
-
await new Promise((resolve) => setTimeout(resolve, waitTime * 1000));
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Search for posts on the platform
|
|
164
|
-
*/
|
|
165
|
-
protected abstract searchPosts(params: SearchParams): Promise<SocialPost[]>;
|
|
166
126
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
limit: parseInt(limit),
|
|
192
|
-
};
|
|
127
|
+
/**
|
|
128
|
+
* Platform-specific media upload implementation
|
|
129
|
+
*/
|
|
130
|
+
protected abstract uploadSingleMedia(file: MediaFile): Promise<string>;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Validate media file meets platform requirements
|
|
134
|
+
*/
|
|
135
|
+
protected validateMediaFile(file: MediaFile): void {
|
|
136
|
+
const maxSizes: Record<string, number> = {
|
|
137
|
+
'image/jpeg': 5 * 1024 * 1024, // 5MB
|
|
138
|
+
'image/png': 5 * 1024 * 1024, // 5MB
|
|
139
|
+
'image/gif': 15 * 1024 * 1024, // 15MB
|
|
140
|
+
'video/mp4': 512 * 1024 * 1024 // 512MB
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const maxSize = maxSizes[file.mimeType];
|
|
144
|
+
if (!maxSize) {
|
|
145
|
+
throw new Error(`Unsupported media type: ${file.mimeType}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (file.size > maxSize) {
|
|
149
|
+
throw new Error(`File size exceeds limit. Max ${maxSize} bytes, got ${file.size} bytes`);
|
|
150
|
+
}
|
|
193
151
|
}
|
|
194
152
|
|
|
195
|
-
|
|
196
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Handle rate limiting with exponential backoff
|
|
155
|
+
*/
|
|
156
|
+
protected async handleRateLimit(retryAfter?: number): Promise<void> {
|
|
157
|
+
const waitTime = retryAfter || 60; // Default to 60 seconds
|
|
158
|
+
LogStatus(`Rate limit hit. Waiting ${waitTime} seconds...`);
|
|
159
|
+
|
|
160
|
+
await new Promise(resolve => setTimeout(resolve, waitTime * 1000));
|
|
161
|
+
}
|
|
197
162
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
163
|
+
/**
|
|
164
|
+
* Search for posts on the platform
|
|
165
|
+
*/
|
|
166
|
+
protected abstract searchPosts(params: SearchParams): Promise<SocialPost[]>;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Convert platform-specific post data to common format
|
|
170
|
+
*/
|
|
171
|
+
protected abstract normalizePost(platformPost: any): SocialPost;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Parse rate limit headers from API response
|
|
175
|
+
*/
|
|
176
|
+
protected parseRateLimitHeaders(headers: any): {
|
|
177
|
+
remaining: number;
|
|
178
|
+
reset: Date;
|
|
179
|
+
limit: number;
|
|
180
|
+
} | null {
|
|
181
|
+
// Common header patterns across platforms
|
|
182
|
+
const remaining = headers['x-rate-limit-remaining'] ||
|
|
183
|
+
headers['x-ratelimit-remaining'] ||
|
|
184
|
+
headers['rate-limit-remaining'];
|
|
185
|
+
|
|
186
|
+
const reset = headers['x-rate-limit-reset'] ||
|
|
187
|
+
headers['x-ratelimit-reset'] ||
|
|
188
|
+
headers['rate-limit-reset'];
|
|
189
|
+
|
|
190
|
+
const limit = headers['x-rate-limit-limit'] ||
|
|
191
|
+
headers['x-ratelimit-limit'] ||
|
|
192
|
+
headers['rate-limit-limit'];
|
|
193
|
+
|
|
194
|
+
if (remaining !== undefined && reset && limit) {
|
|
195
|
+
return {
|
|
196
|
+
remaining: parseInt(remaining),
|
|
197
|
+
reset: new Date(parseInt(reset) * 1000), // Usually Unix timestamp
|
|
198
|
+
limit: parseInt(limit)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return null;
|
|
205
203
|
}
|
|
206
204
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Build common API headers including authentication
|
|
207
|
+
*/
|
|
208
|
+
protected buildHeaders(additionalHeaders?: Record<string, string>): Record<string, string> {
|
|
209
|
+
const token = this.getAccessToken();
|
|
210
|
+
if (!token) {
|
|
211
|
+
throw new Error('No access token available');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
'Authorization': `Bearer ${token}`,
|
|
216
|
+
'Content-Type': 'application/json',
|
|
217
|
+
'Accept': 'application/json',
|
|
218
|
+
...additionalHeaders
|
|
219
|
+
};
|
|
220
|
+
}
|
|
214
221
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Format date for API requests (ISO 8601)
|
|
224
|
+
*/
|
|
225
|
+
protected formatDate(date: Date | string): string {
|
|
226
|
+
if (typeof date === 'string') {
|
|
227
|
+
date = new Date(date);
|
|
228
|
+
}
|
|
229
|
+
return date.toISOString();
|
|
221
230
|
}
|
|
222
|
-
return date.toISOString();
|
|
223
|
-
}
|
|
224
231
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Parse date from API response
|
|
234
|
+
*/
|
|
235
|
+
protected parseDate(dateString: string): Date {
|
|
236
|
+
return new Date(dateString);
|
|
237
|
+
}
|
|
231
238
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
/**
|
|
240
|
+
* Get profile ID from parameters or default from integration
|
|
241
|
+
*/
|
|
242
|
+
protected getProfileId(params: any): string {
|
|
243
|
+
return params.ProfileID || this.getCustomAttribute(1) || '';
|
|
244
|
+
}
|
|
238
245
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Log API request for debugging
|
|
248
|
+
*/
|
|
249
|
+
protected logApiRequest(method: string, url: string, data?: any): void {
|
|
250
|
+
LogStatus(`${this.platformName} API Request: ${method} ${url}`);
|
|
251
|
+
if (data) {
|
|
252
|
+
LogStatus(`Request Data: ${JSON.stringify(data, null, 2)}`);
|
|
253
|
+
}
|
|
246
254
|
}
|
|
247
|
-
}
|
|
248
255
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
/**
|
|
257
|
+
* Log API response for debugging
|
|
258
|
+
*/
|
|
259
|
+
protected logApiResponse(response: any): void {
|
|
260
|
+
LogStatus(`${this.platformName} API Response: ${JSON.stringify(response, null, 2)}`);
|
|
261
|
+
}
|
|
255
262
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
263
|
+
/**
|
|
264
|
+
* Helper to get parameter value from params array
|
|
265
|
+
*/
|
|
266
|
+
protected getParamValue(params: ActionParam[], paramName: string): any {
|
|
267
|
+
const param = params.find(p => p.Name === paramName);
|
|
268
|
+
return param?.Value;
|
|
269
|
+
}
|
|
270
|
+
}
|