@memberjunction/actions-bizapps-social 2.61.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 +4 -0
- package/CHANGELOG.md +16 -0
- package/README.md +375 -0
- package/dist/base/base-social.action.d.ts +137 -0
- package/dist/base/base-social.action.d.ts.map +1 -0
- package/dist/base/base-social.action.js +176 -0
- package/dist/base/base-social.action.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/buffer/actions/create-post.action.d.ts +20 -0
- package/dist/providers/buffer/actions/create-post.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/create-post.action.js +195 -0
- package/dist/providers/buffer/actions/create-post.action.js.map +1 -0
- package/dist/providers/buffer/actions/delete-post.action.d.ts +20 -0
- package/dist/providers/buffer/actions/delete-post.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/delete-post.action.js +119 -0
- package/dist/providers/buffer/actions/delete-post.action.js.map +1 -0
- package/dist/providers/buffer/actions/get-analytics.action.d.ts +28 -0
- package/dist/providers/buffer/actions/get-analytics.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/get-analytics.action.js +143 -0
- package/dist/providers/buffer/actions/get-analytics.action.js.map +1 -0
- package/dist/providers/buffer/actions/get-pending-posts.action.d.ts +24 -0
- package/dist/providers/buffer/actions/get-pending-posts.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/get-pending-posts.action.js +161 -0
- package/dist/providers/buffer/actions/get-pending-posts.action.js.map +1 -0
- package/dist/providers/buffer/actions/get-profiles.action.d.ts +24 -0
- package/dist/providers/buffer/actions/get-profiles.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/get-profiles.action.js +128 -0
- package/dist/providers/buffer/actions/get-profiles.action.js.map +1 -0
- package/dist/providers/buffer/actions/get-sent-posts.action.d.ts +32 -0
- package/dist/providers/buffer/actions/get-sent-posts.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/get-sent-posts.action.js +187 -0
- package/dist/providers/buffer/actions/get-sent-posts.action.js.map +1 -0
- package/dist/providers/buffer/actions/index.d.ts +9 -0
- package/dist/providers/buffer/actions/index.d.ts.map +1 -0
- package/dist/providers/buffer/actions/index.js +25 -0
- package/dist/providers/buffer/actions/index.js.map +1 -0
- package/dist/providers/buffer/actions/reorder-queue.action.d.ts +20 -0
- package/dist/providers/buffer/actions/reorder-queue.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/reorder-queue.action.js +138 -0
- package/dist/providers/buffer/actions/reorder-queue.action.js.map +1 -0
- package/dist/providers/buffer/actions/search-posts.action.d.ts +28 -0
- package/dist/providers/buffer/actions/search-posts.action.d.ts.map +1 -0
- package/dist/providers/buffer/actions/search-posts.action.js +249 -0
- package/dist/providers/buffer/actions/search-posts.action.js.map +1 -0
- package/dist/providers/buffer/buffer-base.action.d.ts +95 -0
- package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -0
- package/dist/providers/buffer/buffer-base.action.js +419 -0
- package/dist/providers/buffer/buffer-base.action.js.map +1 -0
- package/dist/providers/buffer/index.d.ts +3 -0
- package/dist/providers/buffer/index.d.ts.map +1 -0
- package/dist/providers/buffer/index.js +19 -0
- package/dist/providers/buffer/index.js.map +1 -0
- package/dist/providers/facebook/actions/boost-post.action.d.ts +45 -0
- package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/boost-post.action.js +340 -0
- package/dist/providers/facebook/actions/boost-post.action.js.map +1 -0
- package/dist/providers/facebook/actions/create-album.action.d.ts +33 -0
- package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/create-album.action.js +285 -0
- package/dist/providers/facebook/actions/create-album.action.js.map +1 -0
- package/dist/providers/facebook/actions/create-post.action.d.ts +21 -0
- package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/create-post.action.js +223 -0
- package/dist/providers/facebook/actions/create-post.action.js.map +1 -0
- package/dist/providers/facebook/actions/get-page-insights.action.d.ts +37 -0
- package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/get-page-insights.action.js +359 -0
- package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -0
- package/dist/providers/facebook/actions/get-page-posts.action.d.ts +29 -0
- package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/get-page-posts.action.js +216 -0
- package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -0
- package/dist/providers/facebook/actions/get-post-insights.action.d.ts +33 -0
- package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/get-post-insights.action.js +287 -0
- package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -0
- package/dist/providers/facebook/actions/index.d.ts +10 -0
- package/dist/providers/facebook/actions/index.d.ts.map +1 -0
- package/dist/providers/facebook/actions/index.js +26 -0
- package/dist/providers/facebook/actions/index.js.map +1 -0
- package/dist/providers/facebook/actions/respond-to-comments.action.d.ts +41 -0
- package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/respond-to-comments.action.js +328 -0
- package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -0
- package/dist/providers/facebook/actions/schedule-post.action.d.ts +29 -0
- package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/schedule-post.action.js +289 -0
- package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -0
- package/dist/providers/facebook/actions/search-posts.action.d.ts +54 -0
- package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -0
- package/dist/providers/facebook/actions/search-posts.action.js +396 -0
- package/dist/providers/facebook/actions/search-posts.action.js.map +1 -0
- package/dist/providers/facebook/facebook-base.action.d.ts +230 -0
- package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -0
- package/dist/providers/facebook/facebook-base.action.js +566 -0
- package/dist/providers/facebook/facebook-base.action.js.map +1 -0
- package/dist/providers/facebook/index.d.ts +3 -0
- package/dist/providers/facebook/index.d.ts.map +1 -0
- package/dist/providers/facebook/index.js +19 -0
- package/dist/providers/facebook/index.js.map +1 -0
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts +24 -0
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +266 -0
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts +25 -0
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +202 -0
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts +20 -0
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +172 -0
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/get-analytics.action.d.ts +52 -0
- package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/get-analytics.action.js +265 -0
- package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts +37 -0
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +208 -0
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts +36 -0
- package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js +212 -0
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/search-posts.action.d.ts +53 -0
- package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/search-posts.action.js +353 -0
- package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -0
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts +20 -0
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +217 -0
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -0
- package/dist/providers/hootsuite/hootsuite-base.action.d.ts +101 -0
- package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -0
- package/dist/providers/hootsuite/hootsuite-base.action.js +274 -0
- package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -0
- package/dist/providers/hootsuite/index.d.ts +10 -0
- package/dist/providers/hootsuite/index.d.ts.map +1 -0
- package/dist/providers/hootsuite/index.js +28 -0
- package/dist/providers/hootsuite/index.js.map +1 -0
- package/dist/providers/instagram/actions/create-post.action.d.ts +30 -0
- package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/create-post.action.js +269 -0
- package/dist/providers/instagram/actions/create-post.action.js.map +1 -0
- package/dist/providers/instagram/actions/create-story.action.d.ts +43 -0
- package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/create-story.action.js +365 -0
- package/dist/providers/instagram/actions/create-story.action.js.map +1 -0
- package/dist/providers/instagram/actions/get-account-insights.action.d.ts +50 -0
- package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/get-account-insights.action.js +390 -0
- package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -0
- package/dist/providers/instagram/actions/get-business-posts.action.d.ts +30 -0
- package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/get-business-posts.action.js +246 -0
- package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -0
- package/dist/providers/instagram/actions/get-comments.action.d.ts +41 -0
- package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/get-comments.action.js +337 -0
- package/dist/providers/instagram/actions/get-comments.action.js.map +1 -0
- package/dist/providers/instagram/actions/get-post-insights.action.d.ts +42 -0
- package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/get-post-insights.action.js +271 -0
- package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -0
- package/dist/providers/instagram/actions/index.d.ts +9 -0
- package/dist/providers/instagram/actions/index.d.ts.map +1 -0
- package/dist/providers/instagram/actions/index.js +26 -0
- package/dist/providers/instagram/actions/index.js.map +1 -0
- package/dist/providers/instagram/actions/schedule-post.action.d.ts +34 -0
- package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/schedule-post.action.js +234 -0
- package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -0
- package/dist/providers/instagram/actions/search-posts.action.d.ts +56 -0
- package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -0
- package/dist/providers/instagram/actions/search-posts.action.js +479 -0
- package/dist/providers/instagram/actions/search-posts.action.js.map +1 -0
- package/dist/providers/instagram/index.d.ts +3 -0
- package/dist/providers/instagram/index.d.ts.map +1 -0
- package/dist/providers/instagram/index.js +20 -0
- package/dist/providers/instagram/index.js.map +1 -0
- package/dist/providers/instagram/instagram-base.action.d.ts +76 -0
- package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -0
- package/dist/providers/instagram/instagram-base.action.js +362 -0
- package/dist/providers/instagram/instagram-base.action.js.map +1 -0
- package/dist/providers/linkedin/actions/create-article.action.d.ts +28 -0
- package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/create-article.action.js +275 -0
- package/dist/providers/linkedin/actions/create-article.action.js.map +1 -0
- package/dist/providers/linkedin/actions/create-post.action.d.ts +20 -0
- package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/create-post.action.js +188 -0
- package/dist/providers/linkedin/actions/create-post.action.js.map +1 -0
- package/dist/providers/linkedin/actions/get-followers.action.d.ts +29 -0
- package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/get-followers.action.js +222 -0
- package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -0
- package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts +24 -0
- package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/get-organization-posts.action.js +163 -0
- package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -0
- package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts +25 -0
- package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/get-personal-posts.action.js +156 -0
- package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -0
- package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts +28 -0
- package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/get-post-analytics.action.js +200 -0
- package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -0
- package/dist/providers/linkedin/actions/index.d.ts +9 -0
- package/dist/providers/linkedin/actions/index.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/index.js +25 -0
- package/dist/providers/linkedin/actions/index.js.map +1 -0
- package/dist/providers/linkedin/actions/schedule-post.action.d.ts +22 -0
- package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/schedule-post.action.js +205 -0
- package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -0
- package/dist/providers/linkedin/actions/search-posts.action.d.ts +41 -0
- package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -0
- package/dist/providers/linkedin/actions/search-posts.action.js +292 -0
- package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -0
- package/dist/providers/linkedin/index.d.ts +3 -0
- package/dist/providers/linkedin/index.d.ts.map +1 -0
- package/dist/providers/linkedin/index.js +19 -0
- package/dist/providers/linkedin/index.js.map +1 -0
- package/dist/providers/linkedin/linkedin-base.action.d.ts +166 -0
- package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -0
- package/dist/providers/linkedin/linkedin-base.action.js +346 -0
- package/dist/providers/linkedin/linkedin-base.action.js.map +1 -0
- package/dist/providers/tiktok/actions/create-video-post.action.d.ts +21 -0
- package/dist/providers/tiktok/actions/create-video-post.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/create-video-post.action.js +226 -0
- package/dist/providers/tiktok/actions/create-video-post.action.js.map +1 -0
- package/dist/providers/tiktok/actions/get-account-analytics.action.d.ts +32 -0
- package/dist/providers/tiktok/actions/get-account-analytics.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/get-account-analytics.action.js +242 -0
- package/dist/providers/tiktok/actions/get-account-analytics.action.js.map +1 -0
- package/dist/providers/tiktok/actions/get-comments.action.d.ts +44 -0
- package/dist/providers/tiktok/actions/get-comments.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/get-comments.action.js +290 -0
- package/dist/providers/tiktok/actions/get-comments.action.js.map +1 -0
- package/dist/providers/tiktok/actions/get-trending-hashtags.action.d.ts +48 -0
- package/dist/providers/tiktok/actions/get-trending-hashtags.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/get-trending-hashtags.action.js +309 -0
- package/dist/providers/tiktok/actions/get-trending-hashtags.action.js.map +1 -0
- package/dist/providers/tiktok/actions/get-user-videos.action.d.ts +20 -0
- package/dist/providers/tiktok/actions/get-user-videos.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/get-user-videos.action.js +131 -0
- package/dist/providers/tiktok/actions/get-user-videos.action.js.map +1 -0
- package/dist/providers/tiktok/actions/get-video-analytics.action.d.ts +28 -0
- package/dist/providers/tiktok/actions/get-video-analytics.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/get-video-analytics.action.js +198 -0
- package/dist/providers/tiktok/actions/get-video-analytics.action.js.map +1 -0
- package/dist/providers/tiktok/actions/index.d.ts +8 -0
- package/dist/providers/tiktok/actions/index.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/index.js +25 -0
- package/dist/providers/tiktok/actions/index.js.map +1 -0
- package/dist/providers/tiktok/actions/search-videos.action.d.ts +89 -0
- package/dist/providers/tiktok/actions/search-videos.action.d.ts.map +1 -0
- package/dist/providers/tiktok/actions/search-videos.action.js +653 -0
- package/dist/providers/tiktok/actions/search-videos.action.js.map +1 -0
- package/dist/providers/tiktok/index.d.ts +3 -0
- package/dist/providers/tiktok/index.d.ts.map +1 -0
- package/dist/providers/tiktok/index.js +20 -0
- package/dist/providers/tiktok/index.js.map +1 -0
- package/dist/providers/tiktok/tiktok-base.action.d.ts +87 -0
- package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -0
- package/dist/providers/tiktok/tiktok-base.action.js +294 -0
- package/dist/providers/tiktok/tiktok-base.action.js.map +1 -0
- package/dist/providers/twitter/actions/create-thread.action.d.ts +28 -0
- package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/create-thread.action.js +217 -0
- package/dist/providers/twitter/actions/create-thread.action.js.map +1 -0
- package/dist/providers/twitter/actions/create-tweet.action.d.ts +24 -0
- package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/create-tweet.action.js +199 -0
- package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -0
- package/dist/providers/twitter/actions/delete-tweet.action.d.ts +24 -0
- package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/delete-tweet.action.js +158 -0
- package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -0
- package/dist/providers/twitter/actions/get-analytics.action.d.ts +44 -0
- package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/get-analytics.action.js +399 -0
- package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -0
- package/dist/providers/twitter/actions/get-mentions.action.d.ts +24 -0
- package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/get-mentions.action.js +229 -0
- package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -0
- package/dist/providers/twitter/actions/get-timeline.action.d.ts +24 -0
- package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/get-timeline.action.js +249 -0
- package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -0
- package/dist/providers/twitter/actions/index.d.ts +14 -0
- package/dist/providers/twitter/actions/index.d.ts.map +1 -0
- package/dist/providers/twitter/actions/index.js +30 -0
- package/dist/providers/twitter/actions/index.js.map +1 -0
- package/dist/providers/twitter/actions/schedule-tweet.action.d.ts +30 -0
- package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/schedule-tweet.action.js +250 -0
- package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -0
- package/dist/providers/twitter/actions/search-tweets.action.d.ts +41 -0
- package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -0
- package/dist/providers/twitter/actions/search-tweets.action.js +559 -0
- package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -0
- package/dist/providers/twitter/index.d.ts +8 -0
- package/dist/providers/twitter/index.d.ts.map +1 -0
- package/dist/providers/twitter/index.js +24 -0
- package/dist/providers/twitter/index.js.map +1 -0
- package/dist/providers/twitter/twitter-base.action.d.ts +185 -0
- package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -0
- package/dist/providers/twitter/twitter-base.action.js +484 -0
- package/dist/providers/twitter/twitter-base.action.js.map +1 -0
- package/dist/providers/youtube/actions/create-playlist.action.d.ts +28 -0
- package/dist/providers/youtube/actions/create-playlist.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/create-playlist.action.js +235 -0
- package/dist/providers/youtube/actions/create-playlist.action.js.map +1 -0
- package/dist/providers/youtube/actions/get-channel-analytics.action.d.ts +60 -0
- package/dist/providers/youtube/actions/get-channel-analytics.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/get-channel-analytics.action.js +429 -0
- package/dist/providers/youtube/actions/get-channel-analytics.action.js.map +1 -0
- package/dist/providers/youtube/actions/get-channel-videos.action.d.ts +28 -0
- package/dist/providers/youtube/actions/get-channel-videos.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/get-channel-videos.action.js +263 -0
- package/dist/providers/youtube/actions/get-channel-videos.action.js.map +1 -0
- package/dist/providers/youtube/actions/get-comments.action.d.ts +40 -0
- package/dist/providers/youtube/actions/get-comments.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/get-comments.action.js +381 -0
- package/dist/providers/youtube/actions/get-comments.action.js.map +1 -0
- package/dist/providers/youtube/actions/get-video-analytics.action.d.ts +48 -0
- package/dist/providers/youtube/actions/get-video-analytics.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/get-video-analytics.action.js +280 -0
- package/dist/providers/youtube/actions/get-video-analytics.action.js.map +1 -0
- package/dist/providers/youtube/actions/index.d.ts +10 -0
- package/dist/providers/youtube/actions/index.d.ts.map +1 -0
- package/dist/providers/youtube/actions/index.js +26 -0
- package/dist/providers/youtube/actions/index.js.map +1 -0
- package/dist/providers/youtube/actions/schedule-video.action.d.ts +24 -0
- package/dist/providers/youtube/actions/schedule-video.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/schedule-video.action.js +225 -0
- package/dist/providers/youtube/actions/schedule-video.action.js.map +1 -0
- package/dist/providers/youtube/actions/search-videos.action.d.ts +40 -0
- package/dist/providers/youtube/actions/search-videos.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/search-videos.action.js +483 -0
- package/dist/providers/youtube/actions/search-videos.action.js.map +1 -0
- package/dist/providers/youtube/actions/update-video-metadata.action.d.ts +32 -0
- package/dist/providers/youtube/actions/update-video-metadata.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/update-video-metadata.action.js +298 -0
- package/dist/providers/youtube/actions/update-video-metadata.action.js.map +1 -0
- package/dist/providers/youtube/actions/upload-video.action.d.ts +28 -0
- package/dist/providers/youtube/actions/upload-video.action.d.ts.map +1 -0
- package/dist/providers/youtube/actions/upload-video.action.js +266 -0
- package/dist/providers/youtube/actions/upload-video.action.js.map +1 -0
- package/dist/providers/youtube/index.d.ts +3 -0
- package/dist/providers/youtube/index.d.ts.map +1 -0
- package/dist/providers/youtube/index.js +19 -0
- package/dist/providers/youtube/index.js.map +1 -0
- package/dist/providers/youtube/youtube-base.action.d.ts +83 -0
- package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -0
- package/dist/providers/youtube/youtube-base.action.js +319 -0
- package/dist/providers/youtube/youtube-base.action.js.map +1 -0
- package/package.json +42 -0
- package/social_actions_summary.md +439 -0
- package/src/base/base-social.action.ts +270 -0
- package/src/index.ts +26 -0
- package/src/providers/buffer/actions/create-post.action.ts +205 -0
- package/src/providers/buffer/actions/delete-post.action.ts +116 -0
- package/src/providers/buffer/actions/get-analytics.action.ts +146 -0
- package/src/providers/buffer/actions/get-pending-posts.action.ts +161 -0
- package/src/providers/buffer/actions/get-profiles.action.ts +126 -0
- package/src/providers/buffer/actions/get-sent-posts.action.ts +189 -0
- package/src/providers/buffer/actions/index.ts +8 -0
- package/src/providers/buffer/actions/reorder-queue.action.ts +141 -0
- package/src/providers/buffer/actions/search-posts.action.ts +262 -0
- package/src/providers/buffer/buffer-base.action.ts +490 -0
- package/src/providers/buffer/index.ts +2 -0
- package/src/providers/facebook/actions/boost-post.action.ts +412 -0
- package/src/providers/facebook/actions/create-album.action.ts +335 -0
- package/src/providers/facebook/actions/create-post.action.ts +243 -0
- package/src/providers/facebook/actions/get-page-insights.action.ts +427 -0
- package/src/providers/facebook/actions/get-page-posts.action.ts +241 -0
- package/src/providers/facebook/actions/get-post-insights.action.ts +338 -0
- package/src/providers/facebook/actions/index.ts +9 -0
- package/src/providers/facebook/actions/respond-to-comments.action.ts +372 -0
- package/src/providers/facebook/actions/schedule-post.action.ts +310 -0
- package/src/providers/facebook/actions/search-posts.action.ts +449 -0
- package/src/providers/facebook/facebook-base.action.ts +750 -0
- package/src/providers/facebook/index.ts +2 -0
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +293 -0
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +206 -0
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +173 -0
- package/src/providers/hootsuite/actions/get-analytics.action.ts +281 -0
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +220 -0
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +220 -0
- package/src/providers/hootsuite/actions/search-posts.action.ts +395 -0
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +222 -0
- package/src/providers/hootsuite/hootsuite-base.action.ts +346 -0
- package/src/providers/hootsuite/index.ts +12 -0
- package/src/providers/instagram/README.md +129 -0
- package/src/providers/instagram/actions/create-post.action.ts +329 -0
- package/src/providers/instagram/actions/create-story.action.ts +415 -0
- package/src/providers/instagram/actions/get-account-insights.action.ts +449 -0
- package/src/providers/instagram/actions/get-business-posts.action.ts +281 -0
- package/src/providers/instagram/actions/get-comments.action.ts +395 -0
- package/src/providers/instagram/actions/get-post-insights.action.ts +302 -0
- package/src/providers/instagram/actions/index.ts +9 -0
- package/src/providers/instagram/actions/schedule-post.action.ts +248 -0
- package/src/providers/instagram/actions/search-posts.action.ts +569 -0
- package/src/providers/instagram/index.ts +3 -0
- package/src/providers/instagram/instagram-base.action.ts +430 -0
- package/src/providers/linkedin/actions/create-article.action.ts +301 -0
- package/src/providers/linkedin/actions/create-post.action.ts +190 -0
- package/src/providers/linkedin/actions/get-followers.action.ts +226 -0
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +164 -0
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +158 -0
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +205 -0
- package/src/providers/linkedin/actions/index.ts +8 -0
- package/src/providers/linkedin/actions/schedule-post.action.ts +206 -0
- package/src/providers/linkedin/actions/search-posts.action.ts +323 -0
- package/src/providers/linkedin/index.ts +2 -0
- package/src/providers/linkedin/linkedin-base.action.ts +481 -0
- package/src/providers/tiktok/actions/create-video-post.action.ts +234 -0
- package/src/providers/tiktok/actions/get-account-analytics.action.ts +255 -0
- package/src/providers/tiktok/actions/get-comments.action.ts +332 -0
- package/src/providers/tiktok/actions/get-trending-hashtags.action.ts +341 -0
- package/src/providers/tiktok/actions/get-user-videos.action.ts +136 -0
- package/src/providers/tiktok/actions/get-video-analytics.action.ts +218 -0
- package/src/providers/tiktok/actions/index.ts +8 -0
- package/src/providers/tiktok/actions/search-videos.action.ts +717 -0
- package/src/providers/tiktok/index.ts +3 -0
- package/src/providers/tiktok/tiktok-base.action.ts +356 -0
- package/src/providers/twitter/README.md +207 -0
- package/src/providers/twitter/actions/create-thread.action.ts +227 -0
- package/src/providers/twitter/actions/create-tweet.action.ts +204 -0
- package/src/providers/twitter/actions/delete-tweet.action.ts +153 -0
- package/src/providers/twitter/actions/get-analytics.action.ts +440 -0
- package/src/providers/twitter/actions/get-mentions.action.ts +233 -0
- package/src/providers/twitter/actions/get-timeline.action.ts +248 -0
- package/src/providers/twitter/actions/index.ts +14 -0
- package/src/providers/twitter/actions/schedule-tweet.action.ts +259 -0
- package/src/providers/twitter/actions/search-tweets.action.ts +588 -0
- package/src/providers/twitter/index.ts +8 -0
- package/src/providers/twitter/twitter-base.action.ts +629 -0
- package/src/providers/youtube/actions/create-playlist.action.ts +256 -0
- package/src/providers/youtube/actions/get-channel-analytics.action.ts +502 -0
- package/src/providers/youtube/actions/get-channel-videos.action.ts +286 -0
- package/src/providers/youtube/actions/get-comments.action.ts +411 -0
- package/src/providers/youtube/actions/get-video-analytics.action.ts +298 -0
- package/src/providers/youtube/actions/index.ts +9 -0
- package/src/providers/youtube/actions/schedule-video.action.ts +246 -0
- package/src/providers/youtube/actions/search-videos.action.ts +530 -0
- package/src/providers/youtube/actions/update-video-metadata.action.ts +321 -0
- package/src/providers/youtube/actions/upload-video.action.ts +288 -0
- package/src/providers/youtube/index.ts +2 -0
- package/src/providers/youtube/youtube-base.action.ts +373 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
2
|
+
import { BaseSocialMediaAction, MediaFile, SocialPost, SearchParams, SocialAnalytics } from '../../base/base-social.action';
|
|
3
|
+
import axios, { AxiosInstance, AxiosError } from 'axios';
|
|
4
|
+
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
|
|
5
|
+
import { LogStatus, LogError } from '@memberjunction/core';
|
|
6
|
+
import FormData from 'form-data';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Base class for all Facebook actions.
|
|
10
|
+
* Handles Facebook-specific authentication, API interactions, and rate limiting.
|
|
11
|
+
* Uses Facebook Graph API v18.0 with OAuth 2.0.
|
|
12
|
+
*/
|
|
13
|
+
@RegisterClass(BaseSocialMediaAction, 'FacebookBaseAction')
|
|
14
|
+
export abstract class FacebookBaseAction extends BaseSocialMediaAction {
|
|
15
|
+
/**
|
|
16
|
+
* Internal method that must be implemented by derived action classes
|
|
17
|
+
*/
|
|
18
|
+
protected abstract InternalRunAction(params: RunActionParams): Promise<ActionResultSimple>;
|
|
19
|
+
protected get platformName(): string {
|
|
20
|
+
return 'Facebook';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
protected get apiBaseUrl(): string {
|
|
24
|
+
return 'https://graph.facebook.com/v18.0';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* API version for cleaner URL building
|
|
29
|
+
*/
|
|
30
|
+
protected get apiVersion(): string {
|
|
31
|
+
return 'v18.0';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Axios instance for making HTTP requests
|
|
36
|
+
*/
|
|
37
|
+
private _axiosInstance: AxiosInstance | null = null;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get or create axios instance with interceptors
|
|
41
|
+
*/
|
|
42
|
+
protected get axiosInstance(): AxiosInstance {
|
|
43
|
+
if (!this._axiosInstance) {
|
|
44
|
+
this._axiosInstance = axios.create({
|
|
45
|
+
baseURL: this.apiBaseUrl,
|
|
46
|
+
timeout: 30000,
|
|
47
|
+
headers: {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
'Accept': 'application/json'
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Add request interceptor for auth
|
|
54
|
+
this._axiosInstance.interceptors.request.use(
|
|
55
|
+
(config) => {
|
|
56
|
+
const token = this.getAccessToken();
|
|
57
|
+
if (token) {
|
|
58
|
+
// Facebook uses access_token as query parameter
|
|
59
|
+
config.params = {
|
|
60
|
+
...config.params,
|
|
61
|
+
access_token: token
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return config;
|
|
65
|
+
},
|
|
66
|
+
(error) => Promise.reject(error)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Add response interceptor for rate limit handling
|
|
70
|
+
this._axiosInstance.interceptors.response.use(
|
|
71
|
+
(response) => {
|
|
72
|
+
// Log rate limit info if available
|
|
73
|
+
const rateLimitInfo = this.parseRateLimitHeaders(response.headers);
|
|
74
|
+
if (rateLimitInfo) {
|
|
75
|
+
LogStatus(`Facebook Rate Limit - Remaining: ${rateLimitInfo.remaining}/${rateLimitInfo.limit}`);
|
|
76
|
+
}
|
|
77
|
+
return response;
|
|
78
|
+
},
|
|
79
|
+
async (error: AxiosError) => {
|
|
80
|
+
if (error.response?.status === 429 || this.isFacebookRateLimitError(error)) {
|
|
81
|
+
// Rate limit exceeded - Facebook returns various codes
|
|
82
|
+
const waitTime = this.extractRateLimitWaitTime(error) || 60;
|
|
83
|
+
await this.handleRateLimit(waitTime);
|
|
84
|
+
|
|
85
|
+
// Retry the request
|
|
86
|
+
return this._axiosInstance!.request(error.config!);
|
|
87
|
+
}
|
|
88
|
+
return Promise.reject(error);
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return this._axiosInstance;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Check if error is a Facebook rate limit error
|
|
97
|
+
*/
|
|
98
|
+
private isFacebookRateLimitError(error: AxiosError): boolean {
|
|
99
|
+
const errorData = error.response?.data as any;
|
|
100
|
+
const errorCode = errorData?.error?.code;
|
|
101
|
+
const errorSubcode = errorData?.error?.error_subcode;
|
|
102
|
+
|
|
103
|
+
// Facebook rate limit error codes
|
|
104
|
+
return errorCode === 4 || // Application request limit reached
|
|
105
|
+
errorCode === 17 || // User request limit reached
|
|
106
|
+
errorCode === 32 || // Page request limit reached
|
|
107
|
+
errorCode === 613 || // Calls to stream have exceeded the rate limit
|
|
108
|
+
errorSubcode === 2446079; // Reduce the amount of data you're asking for
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Extract wait time from Facebook rate limit error
|
|
113
|
+
*/
|
|
114
|
+
private extractRateLimitWaitTime(error: AxiosError): number | null {
|
|
115
|
+
const errorData = error.response?.data as any;
|
|
116
|
+
const headers = error.response?.headers;
|
|
117
|
+
|
|
118
|
+
// Check headers first
|
|
119
|
+
if (headers?.['x-app-usage'] || headers?.['x-page-usage'] || headers?.['x-ad-account-usage']) {
|
|
120
|
+
// Parse usage headers to determine wait time
|
|
121
|
+
const usage = JSON.parse(headers['x-app-usage'] || headers['x-page-usage'] || headers['x-ad-account-usage']);
|
|
122
|
+
if (usage.call_count > 90) {
|
|
123
|
+
return 300; // Wait 5 minutes if over 90% usage
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check error message for wait time
|
|
128
|
+
const message = errorData?.error?.message;
|
|
129
|
+
if (message && message.includes('Please retry your request later')) {
|
|
130
|
+
return 300; // Default to 5 minutes
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Refresh the access token using the refresh token
|
|
138
|
+
* Note: Facebook uses long-lived tokens that last 60 days
|
|
139
|
+
*/
|
|
140
|
+
protected async refreshAccessToken(): Promise<void> {
|
|
141
|
+
try {
|
|
142
|
+
const currentToken = this.getAccessToken();
|
|
143
|
+
if (!currentToken) {
|
|
144
|
+
throw new Error('No access token available for Facebook');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const clientId = this.getCustomAttribute(2) || ''; // App ID stored in CustomAttribute2
|
|
148
|
+
const clientSecret = this.getCustomAttribute(3) || ''; // App Secret stored in CustomAttribute3
|
|
149
|
+
|
|
150
|
+
// Exchange short-lived token for long-lived token
|
|
151
|
+
const response = await axios.get(`${this.apiBaseUrl}/oauth/access_token`, {
|
|
152
|
+
params: {
|
|
153
|
+
grant_type: 'fb_exchange_token',
|
|
154
|
+
client_id: clientId,
|
|
155
|
+
client_secret: clientSecret,
|
|
156
|
+
fb_exchange_token: currentToken
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const { access_token, expires_in } = response.data;
|
|
161
|
+
|
|
162
|
+
// Update stored tokens
|
|
163
|
+
await this.updateStoredTokens(
|
|
164
|
+
access_token,
|
|
165
|
+
undefined, // Facebook doesn't use refresh tokens
|
|
166
|
+
expires_in || 5184000 // Default to 60 days if not specified
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
LogStatus('Facebook access token refreshed successfully');
|
|
170
|
+
} catch (error) {
|
|
171
|
+
LogError(`Failed to refresh Facebook access token: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get the authenticated user's pages
|
|
178
|
+
*/
|
|
179
|
+
protected async getUserPages(): Promise<FacebookPage[]> {
|
|
180
|
+
try {
|
|
181
|
+
const response = await this.axiosInstance.get('/me/accounts', {
|
|
182
|
+
params: {
|
|
183
|
+
fields: 'id,name,access_token,category,picture'
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
return response.data.data || [];
|
|
187
|
+
} catch (error) {
|
|
188
|
+
LogError(`Failed to get user pages: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get page access token for a specific page
|
|
195
|
+
*/
|
|
196
|
+
protected async getPageAccessToken(pageId: string): Promise<string> {
|
|
197
|
+
const pages = await this.getUserPages();
|
|
198
|
+
const page = pages.find(p => p.id === pageId);
|
|
199
|
+
|
|
200
|
+
if (!page) {
|
|
201
|
+
throw new Error(`Page ${pageId} not found or user doesn't have access`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return page.access_token;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Upload media to Facebook
|
|
209
|
+
*/
|
|
210
|
+
protected async uploadSingleMedia(file: MediaFile): Promise<string> {
|
|
211
|
+
try {
|
|
212
|
+
const fileData = typeof file.data === 'string'
|
|
213
|
+
? Buffer.from(file.data, 'base64')
|
|
214
|
+
: file.data;
|
|
215
|
+
|
|
216
|
+
const formData = new FormData();
|
|
217
|
+
formData.append('source', fileData, {
|
|
218
|
+
filename: file.filename,
|
|
219
|
+
contentType: file.mimeType
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const isVideo = file.mimeType.startsWith('video/');
|
|
223
|
+
const endpoint = isVideo ? '/me/videos' : '/me/photos';
|
|
224
|
+
|
|
225
|
+
const response = await this.axiosInstance.post(endpoint, formData, {
|
|
226
|
+
headers: formData.getHeaders(),
|
|
227
|
+
params: {
|
|
228
|
+
published: 'false' // Upload as unpublished for later use
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
return response.data.id;
|
|
233
|
+
} catch (error) {
|
|
234
|
+
LogError(`Failed to upload media to Facebook: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Upload media to a specific page
|
|
241
|
+
*/
|
|
242
|
+
protected async uploadMediaToPage(pageId: string, file: MediaFile): Promise<string> {
|
|
243
|
+
try {
|
|
244
|
+
const fileData = typeof file.data === 'string'
|
|
245
|
+
? Buffer.from(file.data, 'base64')
|
|
246
|
+
: file.data;
|
|
247
|
+
|
|
248
|
+
const pageToken = await this.getPageAccessToken(pageId);
|
|
249
|
+
const formData = new FormData();
|
|
250
|
+
formData.append('source', fileData, {
|
|
251
|
+
filename: file.filename,
|
|
252
|
+
contentType: file.mimeType
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const isVideo = file.mimeType.startsWith('video/');
|
|
256
|
+
const endpoint = `/${pageId}/${isVideo ? 'videos' : 'photos'}`;
|
|
257
|
+
|
|
258
|
+
const response = await axios.post(`${this.apiBaseUrl}${endpoint}`, formData, {
|
|
259
|
+
headers: formData.getHeaders(),
|
|
260
|
+
params: {
|
|
261
|
+
access_token: pageToken,
|
|
262
|
+
published: 'false' // Upload as unpublished for later use
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
return response.data.id;
|
|
267
|
+
} catch (error) {
|
|
268
|
+
LogError(`Failed to upload media to Facebook page: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Validate media file meets Facebook requirements
|
|
275
|
+
*/
|
|
276
|
+
protected validateMediaFile(file: MediaFile): void {
|
|
277
|
+
const supportedImageTypes = [
|
|
278
|
+
'image/jpeg',
|
|
279
|
+
'image/png',
|
|
280
|
+
'image/gif',
|
|
281
|
+
'image/bmp',
|
|
282
|
+
'image/tiff'
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
const supportedVideoTypes = [
|
|
286
|
+
'video/mp4',
|
|
287
|
+
'video/quicktime',
|
|
288
|
+
'video/x-matroska',
|
|
289
|
+
'video/webm'
|
|
290
|
+
];
|
|
291
|
+
|
|
292
|
+
const supportedTypes = [...supportedImageTypes, ...supportedVideoTypes];
|
|
293
|
+
|
|
294
|
+
if (!supportedTypes.includes(file.mimeType)) {
|
|
295
|
+
throw new Error(`Unsupported media type: ${file.mimeType}. Supported types: ${supportedTypes.join(', ')}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Facebook media size limits
|
|
299
|
+
let maxSize: number;
|
|
300
|
+
if (supportedImageTypes.includes(file.mimeType)) {
|
|
301
|
+
maxSize = 4 * 1024 * 1024; // 4MB for images
|
|
302
|
+
} else if (supportedVideoTypes.includes(file.mimeType)) {
|
|
303
|
+
maxSize = 10 * 1024 * 1024 * 1024; // 10GB for videos
|
|
304
|
+
} else {
|
|
305
|
+
maxSize = 4 * 1024 * 1024; // Default 4MB
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (file.size > maxSize) {
|
|
309
|
+
throw new Error(`File size exceeds limit. Max: ${maxSize / 1024 / 1024}MB, Got: ${file.size / 1024 / 1024}MB`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Create a post on Facebook
|
|
315
|
+
*/
|
|
316
|
+
protected async createPost(pageId: string, postData: CreatePostData): Promise<FacebookPost> {
|
|
317
|
+
try {
|
|
318
|
+
const pageToken = await this.getPageAccessToken(pageId);
|
|
319
|
+
|
|
320
|
+
const response = await axios.post(
|
|
321
|
+
`${this.apiBaseUrl}/${pageId}/feed`,
|
|
322
|
+
postData,
|
|
323
|
+
{
|
|
324
|
+
params: {
|
|
325
|
+
access_token: pageToken
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
// Get the full post data
|
|
331
|
+
return await this.getPost(response.data.id);
|
|
332
|
+
} catch (error) {
|
|
333
|
+
this.handleFacebookError(error as AxiosError);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Get a specific post
|
|
339
|
+
*/
|
|
340
|
+
protected async getPost(postId: string): Promise<FacebookPost> {
|
|
341
|
+
try {
|
|
342
|
+
const response = await this.axiosInstance.get(`/${postId}`, {
|
|
343
|
+
params: {
|
|
344
|
+
fields: this.getPostFields()
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
return response.data;
|
|
348
|
+
} catch (error) {
|
|
349
|
+
LogError(`Failed to get post: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Get posts from a page
|
|
356
|
+
*/
|
|
357
|
+
protected async getPagePosts(pageId: string, params: GetPagePostsParams = {}): Promise<FacebookPost[]> {
|
|
358
|
+
try {
|
|
359
|
+
const pageToken = await this.getPageAccessToken(pageId);
|
|
360
|
+
|
|
361
|
+
const response = await axios.get(`${this.apiBaseUrl}/${pageId}/posts`, {
|
|
362
|
+
params: {
|
|
363
|
+
access_token: pageToken,
|
|
364
|
+
fields: this.getPostFields(),
|
|
365
|
+
limit: params.limit || 100,
|
|
366
|
+
since: params.since ? Math.floor(params.since.getTime() / 1000) : undefined,
|
|
367
|
+
until: params.until ? Math.floor(params.until.getTime() / 1000) : undefined,
|
|
368
|
+
...params
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return response.data.data || [];
|
|
373
|
+
} catch (error) {
|
|
374
|
+
LogError(`Failed to get page posts: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
375
|
+
throw error;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Get paginated results from Facebook
|
|
381
|
+
*/
|
|
382
|
+
protected async getPaginatedResults<T>(url: string, params: Record<string, any> = {}, maxResults?: number): Promise<T[]> {
|
|
383
|
+
const results: T[] = [];
|
|
384
|
+
let nextUrl: string | null = url;
|
|
385
|
+
const limit = params.limit || 100;
|
|
386
|
+
|
|
387
|
+
while (nextUrl) {
|
|
388
|
+
const response = await axios.get(nextUrl, {
|
|
389
|
+
params: nextUrl === url ? { ...params, limit } : {}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
if (response.data.data && Array.isArray(response.data.data)) {
|
|
393
|
+
results.push(...response.data.data);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Check if we've reached max results
|
|
397
|
+
if (maxResults && results.length >= maxResults) {
|
|
398
|
+
return results.slice(0, maxResults);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Get next page URL
|
|
402
|
+
nextUrl = response.data.paging?.next || null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return results;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Get default fields for post queries
|
|
410
|
+
*/
|
|
411
|
+
protected getPostFields(): string {
|
|
412
|
+
return 'id,message,created_time,updated_time,from,story,permalink_url,attachments,shares,reactions.summary(true),comments.summary(true),insights.metric(post_impressions,post_impressions_unique,post_engaged_users,post_clicks,post_reactions_by_type_total)';
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Convert Facebook post to common format
|
|
417
|
+
*/
|
|
418
|
+
protected normalizePost(fbPost: FacebookPost): SocialPost {
|
|
419
|
+
const mediaUrls: string[] = [];
|
|
420
|
+
|
|
421
|
+
// Extract media URLs from attachments
|
|
422
|
+
if (fbPost.attachments?.data) {
|
|
423
|
+
for (const attachment of fbPost.attachments.data) {
|
|
424
|
+
if (attachment.media?.image?.src) {
|
|
425
|
+
mediaUrls.push(attachment.media.image.src);
|
|
426
|
+
} else if (attachment.media?.source) {
|
|
427
|
+
mediaUrls.push(attachment.media.source);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
id: fbPost.id,
|
|
434
|
+
platform: 'Facebook',
|
|
435
|
+
profileId: fbPost.from?.id || '',
|
|
436
|
+
content: fbPost.message || fbPost.story || '',
|
|
437
|
+
mediaUrls,
|
|
438
|
+
publishedAt: new Date(fbPost.created_time),
|
|
439
|
+
analytics: this.extractPostAnalytics(fbPost),
|
|
440
|
+
platformSpecificData: {
|
|
441
|
+
permalinkUrl: fbPost.permalink_url,
|
|
442
|
+
story: fbPost.story,
|
|
443
|
+
attachments: fbPost.attachments,
|
|
444
|
+
postType: fbPost.attachments?.data?.[0]?.type || 'status'
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Extract analytics from Facebook post
|
|
451
|
+
*/
|
|
452
|
+
private extractPostAnalytics(fbPost: FacebookPost): SocialAnalytics | undefined {
|
|
453
|
+
const insights = fbPost.insights?.data;
|
|
454
|
+
const reactions = fbPost.reactions?.summary?.total_count || 0;
|
|
455
|
+
const comments = fbPost.comments?.summary?.total_count || 0;
|
|
456
|
+
const shares = fbPost.shares?.count || 0;
|
|
457
|
+
|
|
458
|
+
// Extract metrics from insights
|
|
459
|
+
let impressions = 0;
|
|
460
|
+
let reach = 0;
|
|
461
|
+
let engagements = 0;
|
|
462
|
+
let clicks = 0;
|
|
463
|
+
|
|
464
|
+
if (insights) {
|
|
465
|
+
for (const insight of insights) {
|
|
466
|
+
switch (insight.name) {
|
|
467
|
+
case 'post_impressions':
|
|
468
|
+
impressions = insight.values?.[0]?.value || 0;
|
|
469
|
+
break;
|
|
470
|
+
case 'post_impressions_unique':
|
|
471
|
+
reach = insight.values?.[0]?.value || 0;
|
|
472
|
+
break;
|
|
473
|
+
case 'post_engaged_users':
|
|
474
|
+
engagements = insight.values?.[0]?.value || 0;
|
|
475
|
+
break;
|
|
476
|
+
case 'post_clicks':
|
|
477
|
+
clicks = insight.values?.[0]?.value || 0;
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return {
|
|
484
|
+
impressions,
|
|
485
|
+
reach,
|
|
486
|
+
engagements: engagements || (reactions + comments + shares),
|
|
487
|
+
clicks,
|
|
488
|
+
shares,
|
|
489
|
+
comments,
|
|
490
|
+
likes: reactions,
|
|
491
|
+
platformMetrics: {
|
|
492
|
+
reactions,
|
|
493
|
+
comments,
|
|
494
|
+
shares,
|
|
495
|
+
insights
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Normalize Facebook analytics to common format
|
|
502
|
+
*/
|
|
503
|
+
protected normalizeAnalytics(fbMetrics: any): SocialAnalytics {
|
|
504
|
+
return {
|
|
505
|
+
impressions: fbMetrics.impressions || 0,
|
|
506
|
+
engagements: fbMetrics.engaged_users || 0,
|
|
507
|
+
clicks: fbMetrics.clicks || 0,
|
|
508
|
+
shares: fbMetrics.shares || 0,
|
|
509
|
+
comments: fbMetrics.comments || 0,
|
|
510
|
+
likes: fbMetrics.reactions || fbMetrics.likes || 0,
|
|
511
|
+
reach: fbMetrics.reach || 0,
|
|
512
|
+
saves: fbMetrics.saves,
|
|
513
|
+
videoViews: fbMetrics.video_views,
|
|
514
|
+
platformMetrics: fbMetrics
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Search for posts - implemented in search action
|
|
520
|
+
*/
|
|
521
|
+
protected async searchPosts(params: SearchParams): Promise<SocialPost[]> {
|
|
522
|
+
// This is implemented in the search-posts.action.ts
|
|
523
|
+
throw new Error('Search posts is implemented in FacebookSearchPostsAction');
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Handle Facebook-specific errors
|
|
528
|
+
*/
|
|
529
|
+
protected handleFacebookError(error: AxiosError): never {
|
|
530
|
+
if (error.response) {
|
|
531
|
+
const { status, data } = error.response;
|
|
532
|
+
const errorData = data as any;
|
|
533
|
+
const fbError = errorData?.error;
|
|
534
|
+
|
|
535
|
+
if (fbError) {
|
|
536
|
+
const code = fbError.code;
|
|
537
|
+
const message = fbError.message;
|
|
538
|
+
const type = fbError.type;
|
|
539
|
+
const subcode = fbError.error_subcode;
|
|
540
|
+
|
|
541
|
+
// Map Facebook error codes to user-friendly messages
|
|
542
|
+
switch (code) {
|
|
543
|
+
case 1:
|
|
544
|
+
throw new Error(`API Unknown Error: ${message}`);
|
|
545
|
+
case 2:
|
|
546
|
+
throw new Error(`API Service Error: ${message}`);
|
|
547
|
+
case 4:
|
|
548
|
+
throw new Error('Application request limit reached. Please try again later.');
|
|
549
|
+
case 10:
|
|
550
|
+
throw new Error('Permission denied. Ensure the app has required Facebook permissions.');
|
|
551
|
+
case 17:
|
|
552
|
+
throw new Error('User request limit reached. Please try again later.');
|
|
553
|
+
case 32:
|
|
554
|
+
throw new Error('Page request limit reached. Please try again later.');
|
|
555
|
+
case 100:
|
|
556
|
+
throw new Error(`Invalid Parameter: ${message}`);
|
|
557
|
+
case 190:
|
|
558
|
+
throw new Error('Access token has expired. Please re-authenticate.');
|
|
559
|
+
case 200:
|
|
560
|
+
case 210:
|
|
561
|
+
case 220:
|
|
562
|
+
throw new Error(`Permission Error: ${message}`);
|
|
563
|
+
case 368:
|
|
564
|
+
throw new Error('Temporarily blocked from posting. Please try again later.');
|
|
565
|
+
case 506:
|
|
566
|
+
throw new Error('Duplicate post. This content has already been posted.');
|
|
567
|
+
default:
|
|
568
|
+
throw new Error(`Facebook API Error (${code}): ${message}`);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Generic HTTP errors
|
|
573
|
+
switch (status) {
|
|
574
|
+
case 400:
|
|
575
|
+
throw new Error(`Bad Request: ${errorData.message || 'Invalid request parameters'}`);
|
|
576
|
+
case 401:
|
|
577
|
+
throw new Error('Unauthorized: Invalid or expired access token');
|
|
578
|
+
case 403:
|
|
579
|
+
throw new Error('Forbidden: Insufficient permissions');
|
|
580
|
+
case 404:
|
|
581
|
+
throw new Error('Not Found: Resource does not exist');
|
|
582
|
+
case 500:
|
|
583
|
+
throw new Error('Internal Server Error: Facebook service error');
|
|
584
|
+
case 503:
|
|
585
|
+
throw new Error('Service Unavailable: Facebook service temporarily unavailable');
|
|
586
|
+
default:
|
|
587
|
+
throw new Error(`Facebook API Error (${status}): ${errorData.message || 'Unknown error'}`);
|
|
588
|
+
}
|
|
589
|
+
} else if (error.request) {
|
|
590
|
+
throw new Error('Network Error: No response from Facebook');
|
|
591
|
+
} else {
|
|
592
|
+
throw new Error(`Request Error: ${error.message}`);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Parse Facebook-specific rate limit headers
|
|
598
|
+
*/
|
|
599
|
+
protected parseRateLimitHeaders(headers: any): { remaining: number; reset: Date; limit: number; } | null {
|
|
600
|
+
// Facebook uses different headers for rate limiting
|
|
601
|
+
const appUsage = headers['x-app-usage'];
|
|
602
|
+
const pageUsage = headers['x-page-usage'];
|
|
603
|
+
const adAccountUsage = headers['x-ad-account-usage'];
|
|
604
|
+
|
|
605
|
+
if (appUsage || pageUsage || adAccountUsage) {
|
|
606
|
+
try {
|
|
607
|
+
const usage = JSON.parse(appUsage || pageUsage || adAccountUsage);
|
|
608
|
+
const callCount = usage.call_count || 0;
|
|
609
|
+
const totalTime = usage.total_time || 0;
|
|
610
|
+
const totalCPUTime = usage.total_cputime || 0;
|
|
611
|
+
|
|
612
|
+
// Facebook rate limits are percentage-based
|
|
613
|
+
return {
|
|
614
|
+
remaining: Math.max(0, 100 - callCount),
|
|
615
|
+
reset: new Date(Date.now() + 3600000), // Reset in 1 hour
|
|
616
|
+
limit: 100
|
|
617
|
+
};
|
|
618
|
+
} catch (error) {
|
|
619
|
+
LogError(`Failed to parse Facebook rate limit headers: ${error}`);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Facebook-specific interfaces
|
|
629
|
+
*/
|
|
630
|
+
export interface FacebookPage {
|
|
631
|
+
id: string;
|
|
632
|
+
name: string;
|
|
633
|
+
access_token: string;
|
|
634
|
+
category: string;
|
|
635
|
+
picture?: {
|
|
636
|
+
data: {
|
|
637
|
+
url: string;
|
|
638
|
+
};
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
export interface CreatePostData {
|
|
643
|
+
message?: string;
|
|
644
|
+
link?: string;
|
|
645
|
+
place?: string;
|
|
646
|
+
tags?: string[];
|
|
647
|
+
privacy?: {
|
|
648
|
+
value: 'EVERYONE' | 'ALL_FRIENDS' | 'FRIENDS_OF_FRIENDS' | 'SELF';
|
|
649
|
+
};
|
|
650
|
+
attached_media?: Array<{ media_fbid: string }>;
|
|
651
|
+
scheduled_publish_time?: number; // Unix timestamp
|
|
652
|
+
published?: boolean;
|
|
653
|
+
backdated_time?: number;
|
|
654
|
+
backdated_time_granularity?: 'year' | 'month' | 'day' | 'hour' | 'minute';
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export interface FacebookPost {
|
|
658
|
+
id: string;
|
|
659
|
+
message?: string;
|
|
660
|
+
story?: string;
|
|
661
|
+
created_time: string;
|
|
662
|
+
updated_time: string;
|
|
663
|
+
from?: {
|
|
664
|
+
id: string;
|
|
665
|
+
name: string;
|
|
666
|
+
};
|
|
667
|
+
permalink_url?: string;
|
|
668
|
+
attachments?: {
|
|
669
|
+
data: Array<{
|
|
670
|
+
type: string;
|
|
671
|
+
title?: string;
|
|
672
|
+
description?: string;
|
|
673
|
+
url?: string;
|
|
674
|
+
media?: {
|
|
675
|
+
image?: {
|
|
676
|
+
src: string;
|
|
677
|
+
width: number;
|
|
678
|
+
height: number;
|
|
679
|
+
};
|
|
680
|
+
source?: string;
|
|
681
|
+
};
|
|
682
|
+
}>;
|
|
683
|
+
};
|
|
684
|
+
shares?: {
|
|
685
|
+
count: number;
|
|
686
|
+
};
|
|
687
|
+
reactions?: {
|
|
688
|
+
summary: {
|
|
689
|
+
total_count: number;
|
|
690
|
+
};
|
|
691
|
+
};
|
|
692
|
+
comments?: {
|
|
693
|
+
summary: {
|
|
694
|
+
total_count: number;
|
|
695
|
+
};
|
|
696
|
+
};
|
|
697
|
+
insights?: {
|
|
698
|
+
data: Array<{
|
|
699
|
+
name: string;
|
|
700
|
+
values: Array<{
|
|
701
|
+
value: number;
|
|
702
|
+
}>;
|
|
703
|
+
}>;
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
export interface GetPagePostsParams {
|
|
708
|
+
since?: Date;
|
|
709
|
+
until?: Date;
|
|
710
|
+
limit?: number;
|
|
711
|
+
published?: boolean;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
export interface FacebookInsight {
|
|
715
|
+
name: string;
|
|
716
|
+
period: string;
|
|
717
|
+
values: Array<{
|
|
718
|
+
value: number | Record<string, number>;
|
|
719
|
+
end_time?: string;
|
|
720
|
+
}>;
|
|
721
|
+
title?: string;
|
|
722
|
+
description?: string;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
export interface FacebookComment {
|
|
726
|
+
id: string;
|
|
727
|
+
message: string;
|
|
728
|
+
created_time: string;
|
|
729
|
+
from: {
|
|
730
|
+
id: string;
|
|
731
|
+
name: string;
|
|
732
|
+
};
|
|
733
|
+
like_count: number;
|
|
734
|
+
comment_count?: number;
|
|
735
|
+
parent?: {
|
|
736
|
+
id: string;
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
export interface FacebookAlbum {
|
|
741
|
+
id: string;
|
|
742
|
+
name: string;
|
|
743
|
+
description?: string;
|
|
744
|
+
link: string;
|
|
745
|
+
cover_photo?: {
|
|
746
|
+
id: string;
|
|
747
|
+
};
|
|
748
|
+
count: number;
|
|
749
|
+
created_time: string;
|
|
750
|
+
}
|