@memberjunction/actions-bizapps-social 2.112.0 → 2.113.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 +13 -0
  3. package/dist/base/base-social.action.d.ts.map +1 -1
  4. package/dist/base/base-social.action.js +24 -18
  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 +34 -35
  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 +36 -34
  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 +27 -25
  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 +23 -19
  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 +32 -28
  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 +44 -42
  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 +39 -37
  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 +59 -44
  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 +31 -33
  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 +32 -28
  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 +26 -24
  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 +34 -32
  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 +52 -43
  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 +28 -30
  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 +20 -18
  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 +26 -27
  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 +59 -38
  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 +25 -23
  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 +60 -56
  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 +27 -25
  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 +45 -55
  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 +29 -31
  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 +23 -25
  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 +30 -32
  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 +30 -28
  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 +38 -33
  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 +26 -25
  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 +29 -25
  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 +47 -40
  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 +31 -30
  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 +58 -56
  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 +68 -58
  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 +25 -22
  153. package/dist/providers/youtube/youtube-base.action.js.map +1 -1
  154. package/package.json +6 -5
  155. package/src/base/base-social.action.ts +224 -217
  156. package/src/providers/buffer/buffer-base.action.ts +441 -435
  157. package/src/providers/facebook/actions/boost-post.action.ts +386 -350
  158. package/src/providers/facebook/actions/create-album.action.ts +307 -291
  159. package/src/providers/facebook/actions/create-post.action.ts +227 -224
  160. package/src/providers/facebook/actions/get-page-insights.action.ts +403 -383
  161. package/src/providers/facebook/actions/get-page-posts.action.ts +225 -214
  162. package/src/providers/facebook/actions/get-post-insights.action.ts +316 -300
  163. package/src/providers/facebook/actions/respond-to-comments.action.ts +336 -319
  164. package/src/providers/facebook/actions/schedule-post.action.ts +292 -289
  165. package/src/providers/facebook/actions/search-posts.action.ts +413 -399
  166. package/src/providers/facebook/facebook-base.action.ts +670 -653
  167. package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
  168. package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +189 -184
  169. package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +161 -160
  170. package/src/providers/hootsuite/actions/get-analytics.action.ts +254 -249
  171. package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +207 -206
  172. package/src/providers/hootsuite/actions/get-social-profiles.action.ts +205 -206
  173. package/src/providers/hootsuite/actions/search-posts.action.ts +369 -351
  174. package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +209 -211
  175. package/src/providers/hootsuite/hootsuite-base.action.ts +307 -301
  176. package/src/providers/instagram/actions/create-post.action.ts +296 -276
  177. package/src/providers/instagram/actions/create-story.action.ts +394 -378
  178. package/src/providers/instagram/actions/get-account-insights.action.ts +420 -384
  179. package/src/providers/instagram/actions/get-business-posts.action.ts +242 -233
  180. package/src/providers/instagram/actions/get-comments.action.ts +377 -365
  181. package/src/providers/instagram/actions/get-post-insights.action.ts +273 -265
  182. package/src/providers/instagram/actions/schedule-post.action.ts +235 -233
  183. package/src/providers/instagram/actions/search-posts.action.ts +538 -512
  184. package/src/providers/instagram/instagram-base.action.ts +393 -368
  185. package/src/providers/linkedin/actions/create-article.action.ts +266 -275
  186. package/src/providers/linkedin/actions/create-post.action.ts +177 -179
  187. package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
  188. package/src/providers/linkedin/actions/get-organization-posts.action.ts +147 -146
  189. package/src/providers/linkedin/actions/get-personal-posts.action.ts +139 -138
  190. package/src/providers/linkedin/actions/get-post-analytics.action.ts +189 -190
  191. package/src/providers/linkedin/actions/schedule-post.action.ts +189 -191
  192. package/src/providers/linkedin/actions/search-posts.action.ts +283 -275
  193. package/src/providers/linkedin/linkedin-base.action.ts +421 -407
  194. package/src/providers/tiktok/tiktok-base.action.ts +320 -305
  195. package/src/providers/twitter/actions/create-thread.action.ts +207 -203
  196. package/src/providers/twitter/actions/create-tweet.action.ts +188 -187
  197. package/src/providers/twitter/actions/delete-tweet.action.ts +129 -128
  198. package/src/providers/twitter/actions/get-analytics.action.ts +411 -402
  199. package/src/providers/twitter/actions/get-mentions.action.ts +219 -218
  200. package/src/providers/twitter/actions/get-timeline.action.ts +233 -232
  201. package/src/providers/twitter/actions/schedule-tweet.action.ts +222 -221
  202. package/src/providers/twitter/actions/search-tweets.action.ts +543 -540
  203. package/src/providers/twitter/twitter-base.action.ts +560 -541
  204. package/src/providers/youtube/youtube-base.action.ts +333 -320
@@ -2,7 +2,7 @@ import { RegisterClass } from '@memberjunction/global';
2
2
  import { FacebookBaseAction } from '../facebook-base.action';
3
3
  import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
4
4
  import { SocialMediaErrorCode } from '../../../base/base-social.action';
5
- import { LogStatus, LogError } from '@memberjunction/global';
5
+ import { LogStatus, LogError } from '@memberjunction/core';
6
6
  import axios from 'axios';
7
7
  import { BaseAction } from '@memberjunction/actions';
8
8
 
@@ -12,366 +12,402 @@ import { BaseAction } from '@memberjunction/actions';
12
12
  */
13
13
  @RegisterClass(BaseAction, 'FacebookBoostPostAction')
14
14
  export class FacebookBoostPostAction extends FacebookBaseAction {
15
- /**
16
- * Get action description
17
- */
18
- public get Description(): string {
19
- return 'Boosts (promotes) a Facebook post to reach a wider audience through paid advertising';
20
- }
21
-
22
- /**
23
- * Define the parameters for this action
24
- */
25
- public get Params(): ActionParam[] {
26
- return [
27
- ...this.commonSocialParams,
28
- {
29
- Name: 'PostID',
30
- Type: 'Input',
31
- Value: null,
32
- },
33
- {
34
- Name: 'AdAccountID',
35
- Type: 'Input',
36
- Value: null,
37
- },
38
- {
39
- Name: 'Budget',
40
- Type: 'Input',
41
- Value: null,
42
- },
43
- {
44
- Name: 'Duration',
45
- Type: 'Input',
46
- Value: 7,
47
- },
48
- {
49
- Name: 'Objective',
50
- Type: 'Input',
51
- Value: 'POST_ENGAGEMENT',
52
- },
53
- {
54
- Name: 'AudienceType',
55
- Type: 'Input',
56
- Value: 'AUTO',
57
- },
58
- {
59
- Name: 'TargetingSpec',
60
- Type: 'Input',
61
- Value: null,
62
- },
63
- {
64
- Name: 'StartTime',
65
- Type: 'Input',
66
- Value: null,
67
- },
68
- {
69
- Name: 'CallToAction',
70
- Type: 'Input',
71
- Value: null,
72
- },
73
- ];
74
- }
75
-
76
- /**
77
- * Execute the action
78
- */
79
- protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
80
- const { Params, ContextUser } = params;
81
-
82
- try {
83
- // Validate required parameters
84
- const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
85
- const postId = this.getParamValue(Params, 'PostID');
86
- const adAccountId = this.getParamValue(Params, 'AdAccountID');
87
- const budget = this.getParamValue(Params, 'Budget') as number;
88
-
89
- if (!companyIntegrationId) {
90
- return {
91
- Success: false,
92
- Message: 'CompanyIntegrationID is required',
93
- ResultCode: 'INVALID_TOKEN',
94
- };
95
- }
15
+ /**
16
+ * Get action description
17
+ */
18
+ public get Description(): string {
19
+ return 'Boosts (promotes) a Facebook post to reach a wider audience through paid advertising';
20
+ }
96
21
 
97
- if (!postId) {
98
- return {
99
- Success: false,
100
- Message: 'PostID is required',
101
- ResultCode: 'MISSING_REQUIRED_PARAM',
102
- };
103
- }
22
+ /**
23
+ * Define the parameters for this action
24
+ */
25
+ public get Params(): ActionParam[] {
26
+ return [
27
+ ...this.commonSocialParams,
28
+ {
29
+ Name: 'PostID',
30
+ Type: 'Input',
31
+ Value: null,
32
+ },
33
+ {
34
+ Name: 'AdAccountID',
35
+ Type: 'Input',
36
+ Value: null,
37
+ },
38
+ {
39
+ Name: 'Budget',
40
+ Type: 'Input',
41
+ Value: null,
42
+ },
43
+ {
44
+ Name: 'Duration',
45
+ Type: 'Input',
46
+ Value: 7,
47
+ },
48
+ {
49
+ Name: 'Objective',
50
+ Type: 'Input',
51
+ Value: 'POST_ENGAGEMENT',
52
+ },
53
+ {
54
+ Name: 'AudienceType',
55
+ Type: 'Input',
56
+ Value: 'AUTO',
57
+ },
58
+ {
59
+ Name: 'TargetingSpec',
60
+ Type: 'Input',
61
+ Value: null,
62
+ },
63
+ {
64
+ Name: 'StartTime',
65
+ Type: 'Input',
66
+ Value: null,
67
+ },
68
+ {
69
+ Name: 'CallToAction',
70
+ Type: 'Input',
71
+ Value: null,
72
+ }
73
+ ];
74
+ }
104
75
 
105
- if (!adAccountId) {
106
- return {
107
- Success: false,
108
- Message: 'AdAccountID is required',
109
- ResultCode: 'MISSING_REQUIRED_PARAM',
110
- };
111
- }
76
+ /**
77
+ * Execute the action
78
+ */
79
+ protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
80
+ const { Params, ContextUser } = params;
81
+
82
+ try {
83
+ // Validate required parameters
84
+ const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
85
+ const postId = this.getParamValue(Params, 'PostID');
86
+ const adAccountId = this.getParamValue(Params, 'AdAccountID');
87
+ const budget = this.getParamValue(Params, 'Budget') as number;
88
+
89
+ if (!companyIntegrationId) {
90
+ return {
91
+ Success: false,
92
+ Message: 'CompanyIntegrationID is required',
93
+ ResultCode: 'INVALID_TOKEN'
94
+ };
95
+ }
96
+
97
+ if (!postId) {
98
+ return {
99
+ Success: false,
100
+ Message: 'PostID is required',
101
+ ResultCode: 'MISSING_REQUIRED_PARAM'
102
+ };
103
+ }
104
+
105
+ if (!adAccountId) {
106
+ return {
107
+ Success: false,
108
+ Message: 'AdAccountID is required',
109
+ ResultCode: 'MISSING_REQUIRED_PARAM'
110
+ };
111
+ }
112
+
113
+ if (!budget || budget <= 0) {
114
+ return {
115
+ Success: false,
116
+ Message: 'Budget must be a positive number',
117
+ ResultCode: 'INVALID_BUDGET'
118
+ };
119
+ }
120
+
121
+ // Initialize OAuth
122
+ if (!await this.initializeOAuth(companyIntegrationId)) {
123
+ return {
124
+ Success: false,
125
+ Message: 'Failed to initialize Facebook OAuth connection',
126
+ ResultCode: 'INVALID_TOKEN'
127
+ };
128
+ }
129
+
130
+ // Get parameters
131
+ const duration = this.getParamValue(Params, 'Duration') as number || 7;
132
+ const objective = this.getParamValue(Params, 'Objective') as string || 'POST_ENGAGEMENT';
133
+ const audienceType = this.getParamValue(Params, 'AudienceType') as string || 'AUTO';
134
+ const targetingSpec = this.getParamValue(Params, 'TargetingSpec') as any;
135
+ const startTime = this.getParamValue(Params, 'StartTime') as string;
136
+ const callToAction = this.getParamValue(Params, 'CallToAction') as string;
137
+
138
+ // Validate duration
139
+ if (duration < 1 || duration > 30) {
140
+ return {
141
+ Success: false,
142
+ Message: 'Duration must be between 1 and 30 days',
143
+ ResultCode: 'INVALID_DURATION'
144
+ };
145
+ }
146
+
147
+ // Extract page ID from post ID
148
+ const pageId = postId.split('_')[0];
149
+
150
+ // Get page access token
151
+ const pageToken = await this.getPageAccessToken(pageId);
152
+
153
+ LogStatus(`Creating boost campaign for post ${postId}...`);
154
+
155
+ // Step 1: Create campaign
156
+ const campaignName = `Boost Post ${postId} - ${new Date().toISOString()}`;
157
+ const campaign = await this.createCampaign(adAccountId, campaignName, objective);
158
+
159
+ // Step 2: Create ad set with targeting
160
+ const adSetName = `Ad Set for ${postId}`;
161
+ const targeting = this.buildTargeting(audienceType, targetingSpec, pageId);
162
+ const adSet = await this.createAdSet(
163
+ adAccountId,
164
+ campaign.id,
165
+ adSetName,
166
+ budget,
167
+ duration,
168
+ targeting,
169
+ startTime
170
+ );
171
+
172
+ // Step 3: Create ad creative from post
173
+ const creative = await this.createCreativeFromPost(adAccountId, postId, pageToken, callToAction);
174
+
175
+ // Step 4: Create the ad
176
+ const adName = `Boosted Post ${postId}`;
177
+ const ad = await this.createAd(adAccountId, adSet.id, creative.id, adName);
178
+
179
+ // Get boost summary
180
+ const boostSummary = {
181
+ campaignId: campaign.id,
182
+ adSetId: adSet.id,
183
+ adId: ad.id,
184
+ creativeId: creative.id,
185
+ postId,
186
+ budget,
187
+ duration,
188
+ objective,
189
+ audienceType,
190
+ startTime: adSet.start_time,
191
+ endTime: adSet.end_time,
192
+ status: ad.status,
193
+ reviewStatus: ad.review_feedback?.global_review_status || 'PENDING',
194
+ previewUrl: `https://www.facebook.com/ads/manager/account/campaigns?act=${adAccountId}&selected_campaign_ids=${campaign.id}`
195
+ };
196
+
197
+ LogStatus(`Successfully created boost campaign for post ${postId}`);
198
+
199
+ return {
200
+ Success: true,
201
+ Message: 'Post boost created successfully',
202
+ ResultCode: 'SUCCESS',
203
+ Params
204
+ };
205
+
206
+ } catch (error) {
207
+ LogError(`Failed to boost Facebook post: ${error instanceof Error ? error.message : 'Unknown error'}`);
208
+
209
+ if (this.isAuthError(error)) {
210
+ return this.handleOAuthError(error);
211
+ }
212
+
213
+ // Check for specific ad-related errors
214
+ if (error instanceof Error) {
215
+ if (error.message.includes('permissions')) {
216
+ return {
217
+ Success: false,
218
+ Message: 'Insufficient permissions. Ensure the token has ads_management permission.',
219
+ ResultCode: 'INSUFFICIENT_PERMISSIONS'
220
+ };
221
+ }
222
+ if (error.message.includes('budget')) {
223
+ return {
224
+ Success: false,
225
+ Message: 'Invalid budget. Check minimum budget requirements for your currency.',
226
+ ResultCode: 'INVALID_BUDGET'
227
+ };
228
+ }
229
+ }
230
+
231
+ return {
232
+ Success: false,
233
+ Message: error instanceof Error ? error.message : 'Unknown error occurred',
234
+ ResultCode: 'ERROR'
235
+ };
236
+ }
237
+ }
112
238
 
113
- if (!budget || budget <= 0) {
114
- return {
115
- Success: false,
116
- Message: 'Budget must be a positive number',
117
- ResultCode: 'INVALID_BUDGET',
118
- };
119
- }
120
-
121
- // Initialize OAuth
122
- if (!(await this.initializeOAuth(companyIntegrationId))) {
123
- return {
124
- Success: false,
125
- Message: 'Failed to initialize Facebook OAuth connection',
126
- ResultCode: 'INVALID_TOKEN',
127
- };
128
- }
129
-
130
- // Get parameters
131
- const duration = (this.getParamValue(Params, 'Duration') as number) || 7;
132
- const objective = (this.getParamValue(Params, 'Objective') as string) || 'POST_ENGAGEMENT';
133
- const audienceType = (this.getParamValue(Params, 'AudienceType') as string) || 'AUTO';
134
- const targetingSpec = this.getParamValue(Params, 'TargetingSpec') as any;
135
- const startTime = this.getParamValue(Params, 'StartTime') as string;
136
- const callToAction = this.getParamValue(Params, 'CallToAction') as string;
137
-
138
- // Validate duration
139
- if (duration < 1 || duration > 30) {
140
- return {
141
- Success: false,
142
- Message: 'Duration must be between 1 and 30 days',
143
- ResultCode: 'INVALID_DURATION',
239
+ /**
240
+ * Create a campaign
241
+ */
242
+ private async createCampaign(adAccountId: string, name: string, objective: string): Promise<any> {
243
+ const response = await this.axiosInstance.post(
244
+ `/${adAccountId}/campaigns`,
245
+ {
246
+ name,
247
+ objective,
248
+ status: 'PAUSED', // Start paused for safety
249
+ special_ad_categories: [] // Required field
250
+ }
251
+ );
252
+
253
+ return response.data;
254
+ }
255
+
256
+ /**
257
+ * Create an ad set
258
+ */
259
+ private async createAdSet(
260
+ adAccountId: string,
261
+ campaignId: string,
262
+ name: string,
263
+ budget: number,
264
+ durationDays: number,
265
+ targeting: any,
266
+ startTime?: string
267
+ ): Promise<any> {
268
+ const now = new Date();
269
+ const start = startTime ? new Date(startTime) : now;
270
+ const end = new Date(start);
271
+ end.setDate(end.getDate() + durationDays);
272
+
273
+ // Calculate daily budget
274
+ const dailyBudget = Math.ceil((budget * 100) / durationDays); // Convert to cents
275
+
276
+ const response = await this.axiosInstance.post(
277
+ `/${adAccountId}/adsets`,
278
+ {
279
+ name,
280
+ campaign_id: campaignId,
281
+ daily_budget: dailyBudget,
282
+ billing_event: 'IMPRESSIONS',
283
+ optimization_goal: this.getOptimizationGoal(campaignId),
284
+ bid_strategy: 'LOWEST_COST_WITHOUT_CAP',
285
+ targeting,
286
+ start_time: start.toISOString(),
287
+ end_time: end.toISOString(),
288
+ status: 'PAUSED'
289
+ }
290
+ );
291
+
292
+ return response.data;
293
+ }
294
+
295
+ /**
296
+ * Create creative from existing post
297
+ */
298
+ private async createCreativeFromPost(
299
+ adAccountId: string,
300
+ postId: string,
301
+ pageToken: string,
302
+ callToAction?: string
303
+ ): Promise<any> {
304
+ const creativeData: any = {
305
+ name: `Creative for ${postId}`,
306
+ object_story_id: postId
144
307
  };
145
- }
146
-
147
- // Extract page ID from post ID
148
- const pageId = postId.split('_')[0];
149
-
150
- // Get page access token
151
- const pageToken = await this.getPageAccessToken(pageId);
152
-
153
- LogStatus(`Creating boost campaign for post ${postId}...`);
154
-
155
- // Step 1: Create campaign
156
- const campaignName = `Boost Post ${postId} - ${new Date().toISOString()}`;
157
- const campaign = await this.createCampaign(adAccountId, campaignName, objective);
158
-
159
- // Step 2: Create ad set with targeting
160
- const adSetName = `Ad Set for ${postId}`;
161
- const targeting = this.buildTargeting(audienceType, targetingSpec, pageId);
162
- const adSet = await this.createAdSet(adAccountId, campaign.id, adSetName, budget, duration, targeting, startTime);
163
-
164
- // Step 3: Create ad creative from post
165
- const creative = await this.createCreativeFromPost(adAccountId, postId, pageToken, callToAction);
166
-
167
- // Step 4: Create the ad
168
- const adName = `Boosted Post ${postId}`;
169
- const ad = await this.createAd(adAccountId, adSet.id, creative.id, adName);
170
-
171
- // Get boost summary
172
- const boostSummary = {
173
- campaignId: campaign.id,
174
- adSetId: adSet.id,
175
- adId: ad.id,
176
- creativeId: creative.id,
177
- postId,
178
- budget,
179
- duration,
180
- objective,
181
- audienceType,
182
- startTime: adSet.start_time,
183
- endTime: adSet.end_time,
184
- status: ad.status,
185
- reviewStatus: ad.review_feedback?.global_review_status || 'PENDING',
186
- previewUrl: `https://www.facebook.com/ads/manager/account/campaigns?act=${adAccountId}&selected_campaign_ids=${campaign.id}`,
187
- };
188
-
189
- LogStatus(`Successfully created boost campaign for post ${postId}`);
190
-
191
- return {
192
- Success: true,
193
- Message: 'Post boost created successfully',
194
- ResultCode: 'SUCCESS',
195
- Params,
196
- };
197
- } catch (error) {
198
- LogError(`Failed to boost Facebook post: ${error instanceof Error ? error.message : 'Unknown error'}`);
199
-
200
- if (this.isAuthError(error)) {
201
- return this.handleOAuthError(error);
202
- }
203
-
204
- // Check for specific ad-related errors
205
- if (error instanceof Error) {
206
- if (error.message.includes('permissions')) {
207
- return {
208
- Success: false,
209
- Message: 'Insufficient permissions. Ensure the token has ads_management permission.',
210
- ResultCode: 'INSUFFICIENT_PERMISSIONS',
211
- };
212
- }
213
- if (error.message.includes('budget')) {
214
- return {
215
- Success: false,
216
- Message: 'Invalid budget. Check minimum budget requirements for your currency.',
217
- ResultCode: 'INVALID_BUDGET',
218
- };
308
+
309
+ if (callToAction) {
310
+ // Get post details to add CTA
311
+ const postResponse = await axios.get(
312
+ `${this.apiBaseUrl}/${postId}`,
313
+ {
314
+ params: {
315
+ access_token: pageToken,
316
+ fields: 'permalink_url'
317
+ }
318
+ }
319
+ );
320
+
321
+ creativeData.call_to_action = {
322
+ type: callToAction,
323
+ value: {
324
+ link: postResponse.data.permalink_url
325
+ }
326
+ };
219
327
  }
220
- }
221
328
 
222
- return {
223
- Success: false,
224
- Message: error instanceof Error ? error.message : 'Unknown error occurred',
225
- ResultCode: 'ERROR',
226
- };
329
+ const response = await this.axiosInstance.post(
330
+ `/${adAccountId}/adcreatives`,
331
+ creativeData
332
+ );
333
+
334
+ return response.data;
227
335
  }
228
- }
229
-
230
- /**
231
- * Create a campaign
232
- */
233
- private async createCampaign(adAccountId: string, name: string, objective: string): Promise<any> {
234
- const response = await this.axiosInstance.post(`/${adAccountId}/campaigns`, {
235
- name,
236
- objective,
237
- status: 'PAUSED', // Start paused for safety
238
- special_ad_categories: [], // Required field
239
- });
240
-
241
- return response.data;
242
- }
243
-
244
- /**
245
- * Create an ad set
246
- */
247
- private async createAdSet(
248
- adAccountId: string,
249
- campaignId: string,
250
- name: string,
251
- budget: number,
252
- durationDays: number,
253
- targeting: any,
254
- startTime?: string
255
- ): Promise<any> {
256
- const now = new Date();
257
- const start = startTime ? new Date(startTime) : now;
258
- const end = new Date(start);
259
- end.setDate(end.getDate() + durationDays);
260
-
261
- // Calculate daily budget
262
- const dailyBudget = Math.ceil((budget * 100) / durationDays); // Convert to cents
263
-
264
- const response = await this.axiosInstance.post(`/${adAccountId}/adsets`, {
265
- name,
266
- campaign_id: campaignId,
267
- daily_budget: dailyBudget,
268
- billing_event: 'IMPRESSIONS',
269
- optimization_goal: this.getOptimizationGoal(campaignId),
270
- bid_strategy: 'LOWEST_COST_WITHOUT_CAP',
271
- targeting,
272
- start_time: start.toISOString(),
273
- end_time: end.toISOString(),
274
- status: 'PAUSED',
275
- });
276
-
277
- return response.data;
278
- }
279
-
280
- /**
281
- * Create creative from existing post
282
- */
283
- private async createCreativeFromPost(adAccountId: string, postId: string, pageToken: string, callToAction?: string): Promise<any> {
284
- const creativeData: any = {
285
- name: `Creative for ${postId}`,
286
- object_story_id: postId,
287
- };
288
-
289
- if (callToAction) {
290
- // Get post details to add CTA
291
- const postResponse = await axios.get(`${this.apiBaseUrl}/${postId}`, {
292
- params: {
293
- access_token: pageToken,
294
- fields: 'permalink_url',
295
- },
296
- });
297
-
298
- creativeData.call_to_action = {
299
- type: callToAction,
300
- value: {
301
- link: postResponse.data.permalink_url,
302
- },
303
- };
336
+
337
+ /**
338
+ * Create the ad
339
+ */
340
+ private async createAd(
341
+ adAccountId: string,
342
+ adSetId: string,
343
+ creativeId: string,
344
+ name: string
345
+ ): Promise<any> {
346
+ const response = await this.axiosInstance.post(
347
+ `/${adAccountId}/ads`,
348
+ {
349
+ name,
350
+ adset_id: adSetId,
351
+ creative: { creative_id: creativeId },
352
+ status: 'PAUSED'
353
+ }
354
+ );
355
+
356
+ return response.data;
304
357
  }
305
358
 
306
- const response = await this.axiosInstance.post(`/${adAccountId}/adcreatives`, creativeData);
307
-
308
- return response.data;
309
- }
310
-
311
- /**
312
- * Create the ad
313
- */
314
- private async createAd(adAccountId: string, adSetId: string, creativeId: string, name: string): Promise<any> {
315
- const response = await this.axiosInstance.post(`/${adAccountId}/ads`, {
316
- name,
317
- adset_id: adSetId,
318
- creative: { creative_id: creativeId },
319
- status: 'PAUSED',
320
- });
321
-
322
- return response.data;
323
- }
324
-
325
- /**
326
- * Build targeting specification
327
- */
328
- private buildTargeting(audienceType: string, customTargeting: any, pageId: string): any {
329
- const baseTargeting: any = {
330
- geo_locations: {
331
- countries: ['US'], // Default to US, can be overridden
332
- },
333
- };
334
-
335
- switch (audienceType) {
336
- case 'FANS':
337
- baseTargeting.connections = [pageId];
338
- break;
339
- case 'FANS_AND_CONNECTIONS':
340
- baseTargeting.connections = [pageId];
341
- baseTargeting.friends_of_connections = [pageId];
342
- break;
343
- case 'CUSTOM':
344
- if (customTargeting) {
345
- return { ...baseTargeting, ...customTargeting };
359
+ /**
360
+ * Build targeting specification
361
+ */
362
+ private buildTargeting(audienceType: string, customTargeting: any, pageId: string): any {
363
+ const baseTargeting: any = {
364
+ geo_locations: {
365
+ countries: ['US'] // Default to US, can be overridden
366
+ }
367
+ };
368
+
369
+ switch (audienceType) {
370
+ case 'FANS':
371
+ baseTargeting.connections = [pageId];
372
+ break;
373
+ case 'FANS_AND_CONNECTIONS':
374
+ baseTargeting.connections = [pageId];
375
+ baseTargeting.friends_of_connections = [pageId];
376
+ break;
377
+ case 'CUSTOM':
378
+ if (customTargeting) {
379
+ return { ...baseTargeting, ...customTargeting };
380
+ }
381
+ break;
382
+ case 'AUTO':
383
+ default:
384
+ // Facebook will automatically optimize targeting
385
+ break;
346
386
  }
347
- break;
348
- case 'AUTO':
349
- default:
350
- // Facebook will automatically optimize targeting
351
- break;
387
+
388
+ // Add any custom targeting on top
389
+ if (customTargeting && audienceType !== 'CUSTOM') {
390
+ Object.assign(baseTargeting, customTargeting);
391
+ }
392
+
393
+ return baseTargeting;
352
394
  }
353
395
 
354
- // Add any custom targeting on top
355
- if (customTargeting && audienceType !== 'CUSTOM') {
356
- Object.assign(baseTargeting, customTargeting);
396
+ /**
397
+ * Get optimization goal based on objective
398
+ */
399
+ private getOptimizationGoal(objective: string): string {
400
+ const goalMap: Record<string, string> = {
401
+ 'POST_ENGAGEMENT': 'POST_ENGAGEMENT',
402
+ 'REACH': 'REACH',
403
+ 'LINK_CLICKS': 'LINK_CLICKS',
404
+ 'PAGE_LIKES': 'PAGE_LIKES',
405
+ 'BRAND_AWARENESS': 'AD_RECALL_LIFT',
406
+ 'VIDEO_VIEWS': 'VIDEO_VIEWS'
407
+ };
408
+
409
+ return goalMap[objective] || 'POST_ENGAGEMENT';
357
410
  }
358
411
 
359
- return baseTargeting;
360
- }
361
-
362
- /**
363
- * Get optimization goal based on objective
364
- */
365
- private getOptimizationGoal(objective: string): string {
366
- const goalMap: Record<string, string> = {
367
- POST_ENGAGEMENT: 'POST_ENGAGEMENT',
368
- REACH: 'REACH',
369
- LINK_CLICKS: 'LINK_CLICKS',
370
- PAGE_LIKES: 'PAGE_LIKES',
371
- BRAND_AWARENESS: 'AD_RECALL_LIFT',
372
- VIDEO_VIEWS: 'VIDEO_VIEWS',
373
- };
374
-
375
- return goalMap[objective] || 'POST_ENGAGEMENT';
376
- }
377
- }
412
+
413
+ }