@memberjunction/actions-bizapps-social 2.111.0 → 2.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +6 -6
  3. package/dist/base/base-social.action.d.ts.map +1 -1
  4. package/dist/base/base-social.action.js +18 -24
  5. package/dist/base/base-social.action.js.map +1 -1
  6. package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -1
  7. package/dist/providers/buffer/buffer-base.action.js +35 -34
  8. package/dist/providers/buffer/buffer-base.action.js.map +1 -1
  9. package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -1
  10. package/dist/providers/facebook/actions/boost-post.action.js +33 -33
  11. package/dist/providers/facebook/actions/boost-post.action.js.map +1 -1
  12. package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -1
  13. package/dist/providers/facebook/actions/create-album.action.js +34 -36
  14. package/dist/providers/facebook/actions/create-album.action.js.map +1 -1
  15. package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -1
  16. package/dist/providers/facebook/actions/create-post.action.js +20 -20
  17. package/dist/providers/facebook/actions/create-post.action.js.map +1 -1
  18. package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -1
  19. package/dist/providers/facebook/actions/get-page-insights.action.js +25 -27
  20. package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -1
  21. package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -1
  22. package/dist/providers/facebook/actions/get-page-posts.action.js +19 -23
  23. package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -1
  24. package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -1
  25. package/dist/providers/facebook/actions/get-post-insights.action.js +28 -32
  26. package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -1
  27. package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -1
  28. package/dist/providers/facebook/actions/respond-to-comments.action.js +42 -44
  29. package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -1
  30. package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -1
  31. package/dist/providers/facebook/actions/schedule-post.action.js +29 -29
  32. package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -1
  33. package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -1
  34. package/dist/providers/facebook/actions/search-posts.action.js +37 -39
  35. package/dist/providers/facebook/actions/search-posts.action.js.map +1 -1
  36. package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -1
  37. package/dist/providers/facebook/facebook-base.action.js +44 -59
  38. package/dist/providers/facebook/facebook-base.action.js.map +1 -1
  39. package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -1
  40. package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +33 -31
  41. package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -1
  42. package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -1
  43. package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +28 -32
  44. package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -1
  45. package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -1
  46. package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +19 -19
  47. package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -1
  48. package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -1
  49. package/dist/providers/hootsuite/actions/get-analytics.action.js +24 -26
  50. package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -1
  51. package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -1
  52. package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +22 -22
  53. package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -1
  54. package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -1
  55. package/dist/providers/hootsuite/actions/get-social-profiles.action.js +32 -34
  56. package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -1
  57. package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -1
  58. package/dist/providers/hootsuite/actions/search-posts.action.js +43 -52
  59. package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -1
  60. package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -1
  61. package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +30 -28
  62. package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -1
  63. package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -1
  64. package/dist/providers/hootsuite/hootsuite-base.action.js +18 -20
  65. package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -1
  66. package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -1
  67. package/dist/providers/instagram/actions/create-post.action.js +27 -26
  68. package/dist/providers/instagram/actions/create-post.action.js.map +1 -1
  69. package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -1
  70. package/dist/providers/instagram/actions/create-story.action.js +35 -35
  71. package/dist/providers/instagram/actions/create-story.action.js.map +1 -1
  72. package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -1
  73. package/dist/providers/instagram/actions/get-account-insights.action.js +38 -59
  74. package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -1
  75. package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -1
  76. package/dist/providers/instagram/actions/get-business-posts.action.js +29 -29
  77. package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -1
  78. package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -1
  79. package/dist/providers/instagram/actions/get-comments.action.js +36 -36
  80. package/dist/providers/instagram/actions/get-comments.action.js.map +1 -1
  81. package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -1
  82. package/dist/providers/instagram/actions/get-post-insights.action.js +23 -25
  83. package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -1
  84. package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -1
  85. package/dist/providers/instagram/actions/schedule-post.action.js +25 -25
  86. package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -1
  87. package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -1
  88. package/dist/providers/instagram/actions/search-posts.action.js +56 -60
  89. package/dist/providers/instagram/actions/search-posts.action.js.map +1 -1
  90. package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -1
  91. package/dist/providers/instagram/instagram-base.action.js +25 -27
  92. package/dist/providers/instagram/instagram-base.action.js.map +1 -1
  93. package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -1
  94. package/dist/providers/linkedin/actions/create-article.action.js +55 -45
  95. package/dist/providers/linkedin/actions/create-article.action.js.map +1 -1
  96. package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -1
  97. package/dist/providers/linkedin/actions/create-post.action.js +31 -29
  98. package/dist/providers/linkedin/actions/create-post.action.js.map +1 -1
  99. package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -1
  100. package/dist/providers/linkedin/actions/get-followers.action.js +28 -28
  101. package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -1
  102. package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -1
  103. package/dist/providers/linkedin/actions/get-organization-posts.action.js +20 -20
  104. package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -1
  105. package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -1
  106. package/dist/providers/linkedin/actions/get-personal-posts.action.js +19 -19
  107. package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -1
  108. package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -1
  109. package/dist/providers/linkedin/actions/get-post-analytics.action.js +25 -23
  110. package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -1
  111. package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -1
  112. package/dist/providers/linkedin/actions/schedule-post.action.js +32 -30
  113. package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -1
  114. package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -1
  115. package/dist/providers/linkedin/actions/search-posts.action.js +28 -30
  116. package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -1
  117. package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -1
  118. package/dist/providers/linkedin/linkedin-base.action.js +33 -38
  119. package/dist/providers/linkedin/linkedin-base.action.js.map +1 -1
  120. package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -1
  121. package/dist/providers/tiktok/tiktok-base.action.js +25 -26
  122. package/dist/providers/tiktok/tiktok-base.action.js.map +1 -1
  123. package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -1
  124. package/dist/providers/twitter/actions/create-thread.action.js +25 -29
  125. package/dist/providers/twitter/actions/create-thread.action.js.map +1 -1
  126. package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -1
  127. package/dist/providers/twitter/actions/create-tweet.action.js +23 -23
  128. package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -1
  129. package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -1
  130. package/dist/providers/twitter/actions/delete-tweet.action.js +19 -19
  131. package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -1
  132. package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -1
  133. package/dist/providers/twitter/actions/get-analytics.action.js +40 -47
  134. package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -1
  135. package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -1
  136. package/dist/providers/twitter/actions/get-mentions.action.js +30 -31
  137. package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -1
  138. package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -1
  139. package/dist/providers/twitter/actions/get-timeline.action.js +29 -29
  140. package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -1
  141. package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -1
  142. package/dist/providers/twitter/actions/schedule-tweet.action.js +26 -26
  143. package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -1
  144. package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -1
  145. package/dist/providers/twitter/actions/search-tweets.action.js +56 -58
  146. package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -1
  147. package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -1
  148. package/dist/providers/twitter/twitter-base.action.js +58 -68
  149. package/dist/providers/twitter/twitter-base.action.js.map +1 -1
  150. package/dist/providers/youtube/youtube-base.action.d.ts +1 -1
  151. package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -1
  152. package/dist/providers/youtube/youtube-base.action.js +22 -25
  153. package/dist/providers/youtube/youtube-base.action.js.map +1 -1
  154. package/package.json +5 -6
  155. package/src/base/base-social.action.ts +217 -224
  156. package/src/providers/buffer/buffer-base.action.ts +435 -441
  157. package/src/providers/facebook/actions/boost-post.action.ts +350 -386
  158. package/src/providers/facebook/actions/create-album.action.ts +291 -307
  159. package/src/providers/facebook/actions/create-post.action.ts +224 -227
  160. package/src/providers/facebook/actions/get-page-insights.action.ts +383 -403
  161. package/src/providers/facebook/actions/get-page-posts.action.ts +214 -225
  162. package/src/providers/facebook/actions/get-post-insights.action.ts +300 -316
  163. package/src/providers/facebook/actions/respond-to-comments.action.ts +319 -336
  164. package/src/providers/facebook/actions/schedule-post.action.ts +289 -292
  165. package/src/providers/facebook/actions/search-posts.action.ts +399 -413
  166. package/src/providers/facebook/facebook-base.action.ts +653 -670
  167. package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
  168. package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +184 -189
  169. package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +160 -161
  170. package/src/providers/hootsuite/actions/get-analytics.action.ts +249 -254
  171. package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +206 -207
  172. package/src/providers/hootsuite/actions/get-social-profiles.action.ts +206 -205
  173. package/src/providers/hootsuite/actions/search-posts.action.ts +351 -369
  174. package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +211 -209
  175. package/src/providers/hootsuite/hootsuite-base.action.ts +301 -307
  176. package/src/providers/instagram/actions/create-post.action.ts +276 -296
  177. package/src/providers/instagram/actions/create-story.action.ts +378 -394
  178. package/src/providers/instagram/actions/get-account-insights.action.ts +384 -420
  179. package/src/providers/instagram/actions/get-business-posts.action.ts +233 -242
  180. package/src/providers/instagram/actions/get-comments.action.ts +365 -377
  181. package/src/providers/instagram/actions/get-post-insights.action.ts +265 -273
  182. package/src/providers/instagram/actions/schedule-post.action.ts +233 -235
  183. package/src/providers/instagram/actions/search-posts.action.ts +512 -538
  184. package/src/providers/instagram/instagram-base.action.ts +368 -393
  185. package/src/providers/linkedin/actions/create-article.action.ts +275 -266
  186. package/src/providers/linkedin/actions/create-post.action.ts +179 -177
  187. package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
  188. package/src/providers/linkedin/actions/get-organization-posts.action.ts +146 -147
  189. package/src/providers/linkedin/actions/get-personal-posts.action.ts +138 -139
  190. package/src/providers/linkedin/actions/get-post-analytics.action.ts +190 -189
  191. package/src/providers/linkedin/actions/schedule-post.action.ts +191 -189
  192. package/src/providers/linkedin/actions/search-posts.action.ts +275 -283
  193. package/src/providers/linkedin/linkedin-base.action.ts +407 -421
  194. package/src/providers/tiktok/tiktok-base.action.ts +305 -320
  195. package/src/providers/twitter/actions/create-thread.action.ts +203 -207
  196. package/src/providers/twitter/actions/create-tweet.action.ts +187 -188
  197. package/src/providers/twitter/actions/delete-tweet.action.ts +128 -129
  198. package/src/providers/twitter/actions/get-analytics.action.ts +402 -411
  199. package/src/providers/twitter/actions/get-mentions.action.ts +218 -219
  200. package/src/providers/twitter/actions/get-timeline.action.ts +232 -233
  201. package/src/providers/twitter/actions/schedule-tweet.action.ts +221 -222
  202. package/src/providers/twitter/actions/search-tweets.action.ts +540 -543
  203. package/src/providers/twitter/twitter-base.action.ts +541 -560
  204. package/src/providers/youtube/youtube-base.action.ts +320 -333
@@ -1,7 +1,7 @@
1
1
  import { RegisterClass } from '@memberjunction/global';
2
2
  import { LinkedInBaseAction, LinkedInShare } from '../linkedin-base.action';
3
3
  import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
4
- import { LogStatus, LogError } from '@memberjunction/core';
4
+ import { LogStatus, LogError } from '@memberjunction/global';
5
5
  import { SocialPost, SearchParams } from '../../../base/base-social.action';
6
6
  import { BaseAction } from '@memberjunction/actions';
7
7
 
@@ -10,315 +10,307 @@ import { BaseAction } from '@memberjunction/actions';
10
10
  */
11
11
  @RegisterClass(BaseAction, 'LinkedInSearchPostsAction')
12
12
  export class LinkedInSearchPostsAction extends LinkedInBaseAction {
13
- /**
14
- * Search for posts on LinkedIn with various filters
15
- */
16
- protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
17
- const { Params, ContextUser } = params;
18
-
19
- try {
20
- // Initialize OAuth
21
- const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
22
- if (!await this.initializeOAuth(companyIntegrationId)) {
23
- throw new Error('Failed to initialize OAuth connection');
24
- }
13
+ /**
14
+ * Search for posts on LinkedIn with various filters
15
+ */
16
+ protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
17
+ const { Params, ContextUser } = params;
25
18
 
26
- // Extract parameters
27
- const query = this.getParamValue(Params, 'Query');
28
- const hashtags = this.getParamValue(Params, 'Hashtags');
29
- const startDate = this.getParamValue(Params, 'StartDate');
30
- const endDate = this.getParamValue(Params, 'EndDate');
31
- const authorType = this.getParamValue(Params, 'AuthorType') || 'all'; // 'personal', 'organization', 'all'
32
- const organizationId = this.getParamValue(Params, 'OrganizationID');
33
- const limit = this.getParamValue(Params, 'Limit') || 100;
34
- const offset = this.getParamValue(Params, 'Offset') || 0;
35
- const includeAnalytics = this.getParamValue(Params, 'IncludeAnalytics') === true;
36
-
37
- // Build search parameters
38
- const searchParams: SearchParams = {
39
- query: query,
40
- hashtags: hashtags,
41
- startDate: startDate ? new Date(startDate) : undefined,
42
- endDate: endDate ? new Date(endDate) : undefined,
43
- limit: limit,
44
- offset: offset
45
- };
46
-
47
- // Perform the search
48
- const posts = await this.searchPostsImplementation(
49
- searchParams,
50
- authorType,
51
- organizationId,
52
- includeAnalytics
53
- );
54
-
55
- LogStatus(`Found ${posts.length} posts matching search criteria`);
56
-
57
- // Update output parameters
58
- const outputParams = [...Params];
59
- const postsParam = outputParams.find(p => p.Name === 'Posts');
60
- if (postsParam) postsParam.Value = posts;
61
- const totalCountParam = outputParams.find(p => p.Name === 'TotalCount');
62
- if (totalCountParam) totalCountParam.Value = posts.length;
63
-
64
- return {
65
- Success: true,
66
- ResultCode: 'SUCCESS',
67
- Message: `Successfully found ${posts.length} posts`,
68
- Params: outputParams
69
- };
70
-
71
- } catch (error) {
72
- const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
73
-
74
- return {
75
- Success: false,
76
- ResultCode: 'ERROR',
77
- Message: `Failed to search posts: ${errorMessage}`,
78
- Params
79
- };
80
- }
81
- }
19
+ try {
20
+ // Initialize OAuth
21
+ const companyIntegrationId = this.getParamValue(Params, 'CompanyIntegrationID');
22
+ if (!(await this.initializeOAuth(companyIntegrationId))) {
23
+ throw new Error('Failed to initialize OAuth connection');
24
+ }
82
25
 
83
- /**
84
- * Implementation of post search
85
- */
86
- private async searchPostsImplementation(
87
- params: SearchParams,
88
- authorType: string,
89
- organizationId?: string,
90
- includeAnalytics: boolean = false
91
- ): Promise<SocialPost[]> {
92
- const allPosts: SocialPost[] = [];
93
- const authorsToSearch: string[] = [];
94
-
95
- // Determine which authors to search
96
- if (authorType === 'personal' || authorType === 'all') {
97
- const userUrn = await this.getCurrentUserUrn();
98
- authorsToSearch.push(userUrn);
99
- }
26
+ // Extract parameters
27
+ const query = this.getParamValue(Params, 'Query');
28
+ const hashtags = this.getParamValue(Params, 'Hashtags');
29
+ const startDate = this.getParamValue(Params, 'StartDate');
30
+ const endDate = this.getParamValue(Params, 'EndDate');
31
+ const authorType = this.getParamValue(Params, 'AuthorType') || 'all'; // 'personal', 'organization', 'all'
32
+ const organizationId = this.getParamValue(Params, 'OrganizationID');
33
+ const limit = this.getParamValue(Params, 'Limit') || 100;
34
+ const offset = this.getParamValue(Params, 'Offset') || 0;
35
+ const includeAnalytics = this.getParamValue(Params, 'IncludeAnalytics') === true;
100
36
 
101
- if (authorType === 'organization' || authorType === 'all') {
102
- if (organizationId) {
103
- authorsToSearch.push(`urn:li:organization:${organizationId}`);
104
- } else {
105
- // Get all admin organizations
106
- const orgs = await this.getAdminOrganizations();
107
- authorsToSearch.push(...orgs.map(org => org.urn));
108
- }
109
- }
37
+ // Build search parameters
38
+ const searchParams: SearchParams = {
39
+ query: query,
40
+ hashtags: hashtags,
41
+ startDate: startDate ? new Date(startDate) : undefined,
42
+ endDate: endDate ? new Date(endDate) : undefined,
43
+ limit: limit,
44
+ offset: offset,
45
+ };
110
46
 
111
- // Search posts for each author
112
- for (const authorUrn of authorsToSearch) {
113
- LogStatus(`Searching posts for author: ${authorUrn}`);
114
-
115
- // Get all posts for the author (LinkedIn doesn't support direct content search)
116
- const shares = await this.getAllSharesForAuthor(authorUrn, params.limit || 100);
117
-
118
- // Filter posts based on search criteria
119
- for (const share of shares) {
120
- if (this.matchesSearchCriteria(share, params)) {
121
- const post = this.normalizePost(share);
122
-
123
- // Optionally fetch analytics
124
- if (includeAnalytics && authorUrn.includes('organization')) {
125
- try {
126
- const analytics = await this.getPostAnalyticsForSearch(share.id, authorUrn);
127
- if (analytics) {
128
- post.analytics = this.normalizeAnalytics(analytics);
129
- }
130
- } catch (error) {
131
- LogError(`Failed to get analytics for post ${share.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
132
- }
133
- }
134
-
135
- allPosts.push(post);
136
- }
137
- }
138
- }
47
+ // Perform the search
48
+ const posts = await this.searchPostsImplementation(searchParams, authorType, organizationId, includeAnalytics);
49
+
50
+ LogStatus(`Found ${posts.length} posts matching search criteria`);
51
+
52
+ // Update output parameters
53
+ const outputParams = [...Params];
54
+ const postsParam = outputParams.find((p) => p.Name === 'Posts');
55
+ if (postsParam) postsParam.Value = posts;
56
+ const totalCountParam = outputParams.find((p) => p.Name === 'TotalCount');
57
+ if (totalCountParam) totalCountParam.Value = posts.length;
139
58
 
140
- // Sort by date (newest first)
141
- allPosts.sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime());
59
+ return {
60
+ Success: true,
61
+ ResultCode: 'SUCCESS',
62
+ Message: `Successfully found ${posts.length} posts`,
63
+ Params: outputParams,
64
+ };
65
+ } catch (error) {
66
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
142
67
 
143
- // Apply offset and limit
144
- const startIndex = params.offset || 0;
145
- const endIndex = startIndex + (params.limit || 100);
146
-
147
- return allPosts.slice(startIndex, endIndex);
68
+ return {
69
+ Success: false,
70
+ ResultCode: 'ERROR',
71
+ Message: `Failed to search posts: ${errorMessage}`,
72
+ Params,
73
+ };
148
74
  }
75
+ }
149
76
 
150
- /**
151
- * Get all shares for an author with pagination
152
- */
153
- private async getAllSharesForAuthor(authorUrn: string, maxResults: number): Promise<LinkedInShare[]> {
154
- const allShares: LinkedInShare[] = [];
155
- let start = 0;
156
- const count = 50; // LinkedIn's typical page size
77
+ /**
78
+ * Implementation of post search
79
+ */
80
+ private async searchPostsImplementation(
81
+ params: SearchParams,
82
+ authorType: string,
83
+ organizationId?: string,
84
+ includeAnalytics: boolean = false
85
+ ): Promise<SocialPost[]> {
86
+ const allPosts: SocialPost[] = [];
87
+ const authorsToSearch: string[] = [];
157
88
 
158
- while (allShares.length < maxResults) {
89
+ // Determine which authors to search
90
+ if (authorType === 'personal' || authorType === 'all') {
91
+ const userUrn = await this.getCurrentUserUrn();
92
+ authorsToSearch.push(userUrn);
93
+ }
94
+
95
+ if (authorType === 'organization' || authorType === 'all') {
96
+ if (organizationId) {
97
+ authorsToSearch.push(`urn:li:organization:${organizationId}`);
98
+ } else {
99
+ // Get all admin organizations
100
+ const orgs = await this.getAdminOrganizations();
101
+ authorsToSearch.push(...orgs.map((org) => org.urn));
102
+ }
103
+ }
104
+
105
+ // Search posts for each author
106
+ for (const authorUrn of authorsToSearch) {
107
+ LogStatus(`Searching posts for author: ${authorUrn}`);
108
+
109
+ // Get all posts for the author (LinkedIn doesn't support direct content search)
110
+ const shares = await this.getAllSharesForAuthor(authorUrn, params.limit || 100);
111
+
112
+ // Filter posts based on search criteria
113
+ for (const share of shares) {
114
+ if (this.matchesSearchCriteria(share, params)) {
115
+ const post = this.normalizePost(share);
116
+
117
+ // Optionally fetch analytics
118
+ if (includeAnalytics && authorUrn.includes('organization')) {
159
119
  try {
160
- const shares = await this.getShares(authorUrn, count, start);
161
-
162
- if (shares.length === 0) {
163
- break; // No more results
164
- }
165
-
166
- allShares.push(...shares);
167
- start += count;
168
-
169
- // Check if we've hit the API limit
170
- if (shares.length < count) {
171
- break; // Last page
172
- }
120
+ const analytics = await this.getPostAnalyticsForSearch(share.id, authorUrn);
121
+ if (analytics) {
122
+ post.analytics = this.normalizeAnalytics(analytics);
123
+ }
173
124
  } catch (error) {
174
- LogError(`Error fetching shares at offset ${start}: ${error instanceof Error ? error.message : 'Unknown error'}`);
175
- break;
125
+ LogError(`Failed to get analytics for post ${share.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
176
126
  }
177
- }
127
+ }
178
128
 
179
- return allShares.slice(0, maxResults);
129
+ allPosts.push(post);
130
+ }
131
+ }
180
132
  }
181
133
 
182
- /**
183
- * Check if a share matches the search criteria
184
- */
185
- private matchesSearchCriteria(share: LinkedInShare, params: SearchParams): boolean {
186
- const content = share.specificContent?.['com.linkedin.ugc.ShareContent']?.shareCommentary?.text || '';
187
- const publishedDate = new Date(share.firstPublishedAt || share.created.time);
134
+ // Sort by date (newest first)
135
+ allPosts.sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime());
188
136
 
189
- // Check date range
190
- if (params.startDate && publishedDate < params.startDate) {
191
- return false;
192
- }
193
- if (params.endDate && publishedDate > params.endDate) {
194
- return false;
195
- }
137
+ // Apply offset and limit
138
+ const startIndex = params.offset || 0;
139
+ const endIndex = startIndex + (params.limit || 100);
196
140
 
197
- // Check query (case-insensitive)
198
- if (params.query) {
199
- const query = params.query.toLowerCase();
200
- if (!content.toLowerCase().includes(query)) {
201
- return false;
202
- }
203
- }
141
+ return allPosts.slice(startIndex, endIndex);
142
+ }
204
143
 
205
- // Check hashtags
206
- if (params.hashtags && params.hashtags.length > 0) {
207
- const contentLower = content.toLowerCase();
208
- const hasAllHashtags = params.hashtags.every(hashtag => {
209
- const normalizedHashtag = hashtag.toLowerCase().startsWith('#')
210
- ? hashtag.toLowerCase()
211
- : `#${hashtag.toLowerCase()}`;
212
- return contentLower.includes(normalizedHashtag);
213
- });
214
-
215
- if (!hasAllHashtags) {
216
- return false;
217
- }
144
+ /**
145
+ * Get all shares for an author with pagination
146
+ */
147
+ private async getAllSharesForAuthor(authorUrn: string, maxResults: number): Promise<LinkedInShare[]> {
148
+ const allShares: LinkedInShare[] = [];
149
+ let start = 0;
150
+ const count = 50; // LinkedIn's typical page size
151
+
152
+ while (allShares.length < maxResults) {
153
+ try {
154
+ const shares = await this.getShares(authorUrn, count, start);
155
+
156
+ if (shares.length === 0) {
157
+ break; // No more results
218
158
  }
219
159
 
220
- return true;
160
+ allShares.push(...shares);
161
+ start += count;
162
+
163
+ // Check if we've hit the API limit
164
+ if (shares.length < count) {
165
+ break; // Last page
166
+ }
167
+ } catch (error) {
168
+ LogError(`Error fetching shares at offset ${start}: ${error instanceof Error ? error.message : 'Unknown error'}`);
169
+ break;
170
+ }
221
171
  }
222
172
 
223
- /**
224
- * Get analytics for a post during search
225
- */
226
- private async getPostAnalyticsForSearch(shareId: string, organizationUrn: string): Promise<any> {
227
- try {
228
- const response = await this.axiosInstance.get('/organizationalEntityShareStatistics', {
229
- params: {
230
- q: 'organizationalEntity',
231
- organizationalEntity: organizationUrn,
232
- shares: `List(${shareId})`
233
- }
234
- });
235
-
236
- if (response.data.elements && response.data.elements.length > 0) {
237
- return response.data.elements[0];
238
- }
173
+ return allShares.slice(0, maxResults);
174
+ }
239
175
 
240
- return null;
241
- } catch (error) {
242
- // Silently fail for individual analytics requests during search
243
- return null;
244
- }
176
+ /**
177
+ * Check if a share matches the search criteria
178
+ */
179
+ private matchesSearchCriteria(share: LinkedInShare, params: SearchParams): boolean {
180
+ const content = share.specificContent?.['com.linkedin.ugc.ShareContent']?.shareCommentary?.text || '';
181
+ const publishedDate = new Date(share.firstPublishedAt || share.created.time);
182
+
183
+ // Check date range
184
+ if (params.startDate && publishedDate < params.startDate) {
185
+ return false;
186
+ }
187
+ if (params.endDate && publishedDate > params.endDate) {
188
+ return false;
245
189
  }
246
190
 
247
- /**
248
- * Override base searchPosts method
249
- */
250
- protected async searchPosts(params: SearchParams): Promise<SocialPost[]> {
251
- return this.searchPostsImplementation(params, 'all');
191
+ // Check query (case-insensitive)
192
+ if (params.query) {
193
+ const query = params.query.toLowerCase();
194
+ if (!content.toLowerCase().includes(query)) {
195
+ return false;
196
+ }
252
197
  }
253
198
 
254
- /**
255
- * Define the parameters this action expects
256
- */
257
- public get Params(): ActionParam[] {
258
- return [
259
- ...this.commonSocialParams,
260
- {
261
- Name: 'Query',
262
- Type: 'Input',
263
- Value: null
264
- },
265
- {
266
- Name: 'Hashtags',
267
- Type: 'Input',
268
- Value: null // Array of hashtags
269
- },
270
- {
271
- Name: 'StartDate',
272
- Type: 'Input',
273
- Value: null
274
- },
275
- {
276
- Name: 'EndDate',
277
- Type: 'Input',
278
- Value: null
279
- },
280
- {
281
- Name: 'AuthorType',
282
- Type: 'Input',
283
- Value: 'all' // 'personal', 'organization', 'all'
284
- },
285
- {
286
- Name: 'OrganizationID',
287
- Type: 'Input',
288
- Value: null
289
- },
290
- {
291
- Name: 'Limit',
292
- Type: 'Input',
293
- Value: 100
294
- },
295
- {
296
- Name: 'Offset',
297
- Type: 'Input',
298
- Value: 0
299
- },
300
- {
301
- Name: 'IncludeAnalytics',
302
- Type: 'Input',
303
- Value: false
304
- },
305
- {
306
- Name: 'Posts',
307
- Type: 'Output',
308
- Value: null
309
- },
310
- {
311
- Name: 'TotalCount',
312
- Type: 'Output',
313
- Value: null
314
- }
315
- ];
199
+ // Check hashtags
200
+ if (params.hashtags && params.hashtags.length > 0) {
201
+ const contentLower = content.toLowerCase();
202
+ const hasAllHashtags = params.hashtags.every((hashtag) => {
203
+ const normalizedHashtag = hashtag.toLowerCase().startsWith('#') ? hashtag.toLowerCase() : `#${hashtag.toLowerCase()}`;
204
+ return contentLower.includes(normalizedHashtag);
205
+ });
206
+
207
+ if (!hasAllHashtags) {
208
+ return false;
209
+ }
316
210
  }
317
211
 
318
- /**
319
- * Get action description
320
- */
321
- public get Description(): string {
322
- return 'Searches for historical LinkedIn posts with support for content search, hashtags, date ranges, and author filtering. Retrieves posts from personal profiles and organization pages.';
212
+ return true;
213
+ }
214
+
215
+ /**
216
+ * Get analytics for a post during search
217
+ */
218
+ private async getPostAnalyticsForSearch(shareId: string, organizationUrn: string): Promise<any> {
219
+ try {
220
+ const response = await this.axiosInstance.get('/organizationalEntityShareStatistics', {
221
+ params: {
222
+ q: 'organizationalEntity',
223
+ organizationalEntity: organizationUrn,
224
+ shares: `List(${shareId})`,
225
+ },
226
+ });
227
+
228
+ if (response.data.elements && response.data.elements.length > 0) {
229
+ return response.data.elements[0];
230
+ }
231
+
232
+ return null;
233
+ } catch (error) {
234
+ // Silently fail for individual analytics requests during search
235
+ return null;
323
236
  }
324
- }
237
+ }
238
+
239
+ /**
240
+ * Override base searchPosts method
241
+ */
242
+ protected async searchPosts(params: SearchParams): Promise<SocialPost[]> {
243
+ return this.searchPostsImplementation(params, 'all');
244
+ }
245
+
246
+ /**
247
+ * Define the parameters this action expects
248
+ */
249
+ public get Params(): ActionParam[] {
250
+ return [
251
+ ...this.commonSocialParams,
252
+ {
253
+ Name: 'Query',
254
+ Type: 'Input',
255
+ Value: null,
256
+ },
257
+ {
258
+ Name: 'Hashtags',
259
+ Type: 'Input',
260
+ Value: null, // Array of hashtags
261
+ },
262
+ {
263
+ Name: 'StartDate',
264
+ Type: 'Input',
265
+ Value: null,
266
+ },
267
+ {
268
+ Name: 'EndDate',
269
+ Type: 'Input',
270
+ Value: null,
271
+ },
272
+ {
273
+ Name: 'AuthorType',
274
+ Type: 'Input',
275
+ Value: 'all', // 'personal', 'organization', 'all'
276
+ },
277
+ {
278
+ Name: 'OrganizationID',
279
+ Type: 'Input',
280
+ Value: null,
281
+ },
282
+ {
283
+ Name: 'Limit',
284
+ Type: 'Input',
285
+ Value: 100,
286
+ },
287
+ {
288
+ Name: 'Offset',
289
+ Type: 'Input',
290
+ Value: 0,
291
+ },
292
+ {
293
+ Name: 'IncludeAnalytics',
294
+ Type: 'Input',
295
+ Value: false,
296
+ },
297
+ {
298
+ Name: 'Posts',
299
+ Type: 'Output',
300
+ Value: null,
301
+ },
302
+ {
303
+ Name: 'TotalCount',
304
+ Type: 'Output',
305
+ Value: null,
306
+ },
307
+ ];
308
+ }
309
+
310
+ /**
311
+ * Get action description
312
+ */
313
+ public get Description(): string {
314
+ return 'Searches for historical LinkedIn posts with support for content search, hashtags, date ranges, and author filtering. Retrieves posts from personal profiles and organization pages.';
315
+ }
316
+ }