@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,59 +1,59 @@
1
1
  import { BaseOAuthAction } from '@memberjunction/actions';
2
2
  import { ActionParam } from '@memberjunction/actions-base';
3
- import { LogStatus, LogError } from '@memberjunction/core';
3
+ import { LogStatus, LogError } from '@memberjunction/global';
4
4
 
5
5
  /**
6
6
  * Common interfaces for social media actions
7
7
  */
8
8
  export interface SocialPost {
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>;
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
- 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>;
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
- query?: string;
35
- hashtags?: string[];
36
- startDate?: Date;
37
- endDate?: Date;
38
- limit?: number;
39
- offset?: number;
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
- filename: string;
44
- mimeType: string;
45
- data: Buffer | string; // Base64 or buffer
46
- size: number;
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
- 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'
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,209 +62,202 @@ export enum SocialMediaErrorCode {
62
62
  * analytics normalization, and rate limiting.
63
63
  */
64
64
  export abstract class BaseSocialMediaAction extends BaseOAuthAction {
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
- ];
78
- }
65
+ /**
66
+ * Common parameters for all social media actions
67
+ */
68
+ protected get commonSocialParams(): ActionParam[] {
69
+ return [
70
+ ...this.oauthParams,
71
+ {
72
+ Name: 'ProfileID',
73
+ Type: 'Input',
74
+ Value: null,
75
+ },
76
+ ];
77
+ }
79
78
 
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
- };
107
- }
79
+ /**
80
+ * Get the platform name (e.g., 'Twitter', 'LinkedIn')
81
+ */
82
+ protected abstract get platformName(): string;
108
83
 
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;
125
- }
84
+ /**
85
+ * Get the API base URL for the platform
86
+ */
87
+ protected abstract get apiBaseUrl(): string;
126
88
 
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
- }
151
- }
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
+ }
152
107
 
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
- }
108
+ /**
109
+ * Upload media files to the platform
110
+ */
111
+ protected async uploadMedia(files: MediaFile[]): Promise<string[]> {
112
+ const uploadedUrls: string[] = [];
162
113
 
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;
203
- }
114
+ for (const file of files) {
115
+ // Validate file
116
+ this.validateMediaFile(file);
204
117
 
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
- };
118
+ // Upload file (platform-specific implementation)
119
+ const url = await this.uploadSingleMedia(file);
120
+ uploadedUrls.push(url);
220
121
  }
221
122
 
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();
123
+ return uploadedUrls;
124
+ }
125
+
126
+ /**
127
+ * Platform-specific media upload implementation
128
+ */
129
+ protected abstract uploadSingleMedia(file: MediaFile): Promise<string>;
130
+
131
+ /**
132
+ * Validate media file meets platform requirements
133
+ */
134
+ protected validateMediaFile(file: MediaFile): void {
135
+ const maxSizes: Record<string, number> = {
136
+ 'image/jpeg': 5 * 1024 * 1024, // 5MB
137
+ 'image/png': 5 * 1024 * 1024, // 5MB
138
+ 'image/gif': 15 * 1024 * 1024, // 15MB
139
+ 'video/mp4': 512 * 1024 * 1024, // 512MB
140
+ };
141
+
142
+ const maxSize = maxSizes[file.mimeType];
143
+ if (!maxSize) {
144
+ throw new Error(`Unsupported media type: ${file.mimeType}`);
230
145
  }
231
146
 
232
- /**
233
- * Parse date from API response
234
- */
235
- protected parseDate(dateString: string): Date {
236
- return new Date(dateString);
147
+ if (file.size > maxSize) {
148
+ throw new Error(`File size exceeds limit. Max ${maxSize} bytes, got ${file.size} bytes`);
237
149
  }
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[]>;
238
166
 
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) || '';
167
+ /**
168
+ * Convert platform-specific post data to common format
169
+ */
170
+ protected abstract normalizePost(platformPost: any): SocialPost;
171
+
172
+ /**
173
+ * Parse rate limit headers from API response
174
+ */
175
+ protected parseRateLimitHeaders(headers: any): {
176
+ remaining: number;
177
+ reset: Date;
178
+ limit: number;
179
+ } | null {
180
+ // Common header patterns across platforms
181
+ const remaining = headers['x-rate-limit-remaining'] || headers['x-ratelimit-remaining'] || headers['rate-limit-remaining'];
182
+
183
+ const reset = headers['x-rate-limit-reset'] || headers['x-ratelimit-reset'] || headers['rate-limit-reset'];
184
+
185
+ const limit = headers['x-rate-limit-limit'] || headers['x-ratelimit-limit'] || headers['rate-limit-limit'];
186
+
187
+ if (remaining !== undefined && reset && limit) {
188
+ return {
189
+ remaining: parseInt(remaining),
190
+ reset: new Date(parseInt(reset) * 1000), // Usually Unix timestamp
191
+ limit: parseInt(limit),
192
+ };
244
193
  }
245
194
 
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
- }
195
+ return null;
196
+ }
197
+
198
+ /**
199
+ * Build common API headers including authentication
200
+ */
201
+ protected buildHeaders(additionalHeaders?: Record<string, string>): Record<string, string> {
202
+ const token = this.getAccessToken();
203
+ if (!token) {
204
+ throw new Error('No access token available');
254
205
  }
255
206
 
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)}`);
207
+ return {
208
+ Authorization: `Bearer ${token}`,
209
+ 'Content-Type': 'application/json',
210
+ Accept: 'application/json',
211
+ ...additionalHeaders,
212
+ };
213
+ }
214
+
215
+ /**
216
+ * Format date for API requests (ISO 8601)
217
+ */
218
+ protected formatDate(date: Date | string): string {
219
+ if (typeof date === 'string') {
220
+ date = new Date(date);
261
221
  }
222
+ return date.toISOString();
223
+ }
262
224
 
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;
225
+ /**
226
+ * Parse date from API response
227
+ */
228
+ protected parseDate(dateString: string): Date {
229
+ return new Date(dateString);
230
+ }
231
+
232
+ /**
233
+ * Get profile ID from parameters or default from integration
234
+ */
235
+ protected getProfileId(params: any): string {
236
+ return params.ProfileID || this.getCustomAttribute(1) || '';
237
+ }
238
+
239
+ /**
240
+ * Log API request for debugging
241
+ */
242
+ protected logApiRequest(method: string, url: string, data?: any): void {
243
+ LogStatus(`${this.platformName} API Request: ${method} ${url}`);
244
+ if (data) {
245
+ LogStatus(`Request Data: ${JSON.stringify(data, null, 2)}`);
269
246
  }
270
- }
247
+ }
248
+
249
+ /**
250
+ * Log API response for debugging
251
+ */
252
+ protected logApiResponse(response: any): void {
253
+ LogStatus(`${this.platformName} API Response: ${JSON.stringify(response, null, 2)}`);
254
+ }
255
+
256
+ /**
257
+ * Helper to get parameter value from params array
258
+ */
259
+ protected getParamValue(params: ActionParam[], paramName: string): any {
260
+ const param = params.find((p) => p.Name === paramName);
261
+ return param?.Value;
262
+ }
263
+ }