@memberjunction/actions-bizapps-social 2.111.1 → 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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +6 -6
- package/dist/base/base-social.action.d.ts.map +1 -1
- package/dist/base/base-social.action.js +18 -24
- package/dist/base/base-social.action.js.map +1 -1
- package/dist/providers/buffer/buffer-base.action.d.ts.map +1 -1
- package/dist/providers/buffer/buffer-base.action.js +35 -34
- package/dist/providers/buffer/buffer-base.action.js.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/boost-post.action.js +33 -33
- package/dist/providers/facebook/actions/boost-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-album.action.js +34 -36
- package/dist/providers/facebook/actions/create-album.action.js.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/create-post.action.js +20 -20
- package/dist/providers/facebook/actions/create-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-insights.action.js +25 -27
- package/dist/providers/facebook/actions/get-page-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-page-posts.action.js +19 -23
- package/dist/providers/facebook/actions/get-page-posts.action.js.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/get-post-insights.action.js +28 -32
- package/dist/providers/facebook/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/respond-to-comments.action.js +42 -44
- package/dist/providers/facebook/actions/respond-to-comments.action.js.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/schedule-post.action.js +29 -29
- package/dist/providers/facebook/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/facebook/actions/search-posts.action.js +37 -39
- package/dist/providers/facebook/actions/search-posts.action.js.map +1 -1
- package/dist/providers/facebook/facebook-base.action.d.ts.map +1 -1
- package/dist/providers/facebook/facebook-base.action.js +44 -59
- package/dist/providers/facebook/facebook-base.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js +33 -31
- package/dist/providers/hootsuite/actions/bulk-schedule-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js +28 -32
- package/dist/providers/hootsuite/actions/create-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js +19 -19
- package/dist/providers/hootsuite/actions/delete-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-analytics.action.js +24 -26
- package/dist/providers/hootsuite/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js +22 -22
- package/dist/providers/hootsuite/actions/get-scheduled-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js +32 -34
- package/dist/providers/hootsuite/actions/get-social-profiles.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/search-posts.action.js +43 -52
- package/dist/providers/hootsuite/actions/search-posts.action.js.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js +30 -28
- package/dist/providers/hootsuite/actions/update-scheduled-post.action.js.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.d.ts.map +1 -1
- package/dist/providers/hootsuite/hootsuite-base.action.js +18 -20
- package/dist/providers/hootsuite/hootsuite-base.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-post.action.js +27 -26
- package/dist/providers/instagram/actions/create-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/create-story.action.js +35 -35
- package/dist/providers/instagram/actions/create-story.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-account-insights.action.js +38 -59
- package/dist/providers/instagram/actions/get-account-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-business-posts.action.js +29 -29
- package/dist/providers/instagram/actions/get-business-posts.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-comments.action.js +36 -36
- package/dist/providers/instagram/actions/get-comments.action.js.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/get-post-insights.action.js +23 -25
- package/dist/providers/instagram/actions/get-post-insights.action.js.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/schedule-post.action.js +25 -25
- package/dist/providers/instagram/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/instagram/actions/search-posts.action.js +56 -60
- package/dist/providers/instagram/actions/search-posts.action.js.map +1 -1
- package/dist/providers/instagram/instagram-base.action.d.ts.map +1 -1
- package/dist/providers/instagram/instagram-base.action.js +25 -27
- package/dist/providers/instagram/instagram-base.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-article.action.js +55 -45
- package/dist/providers/linkedin/actions/create-article.action.js.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/create-post.action.js +31 -29
- package/dist/providers/linkedin/actions/create-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-followers.action.js +28 -28
- package/dist/providers/linkedin/actions/get-followers.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-organization-posts.action.js +20 -20
- package/dist/providers/linkedin/actions/get-organization-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-personal-posts.action.js +19 -19
- package/dist/providers/linkedin/actions/get-personal-posts.action.js.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/get-post-analytics.action.js +25 -23
- package/dist/providers/linkedin/actions/get-post-analytics.action.js.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/schedule-post.action.js +32 -30
- package/dist/providers/linkedin/actions/schedule-post.action.js.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.d.ts.map +1 -1
- package/dist/providers/linkedin/actions/search-posts.action.js +28 -30
- package/dist/providers/linkedin/actions/search-posts.action.js.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.d.ts.map +1 -1
- package/dist/providers/linkedin/linkedin-base.action.js +33 -38
- package/dist/providers/linkedin/linkedin-base.action.js.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.d.ts.map +1 -1
- package/dist/providers/tiktok/tiktok-base.action.js +25 -26
- package/dist/providers/tiktok/tiktok-base.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-thread.action.js +25 -29
- package/dist/providers/twitter/actions/create-thread.action.js.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/create-tweet.action.js +23 -23
- package/dist/providers/twitter/actions/create-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/delete-tweet.action.js +19 -19
- package/dist/providers/twitter/actions/delete-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-analytics.action.js +40 -47
- package/dist/providers/twitter/actions/get-analytics.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-mentions.action.js +30 -31
- package/dist/providers/twitter/actions/get-mentions.action.js.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/get-timeline.action.js +29 -29
- package/dist/providers/twitter/actions/get-timeline.action.js.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/schedule-tweet.action.js +26 -26
- package/dist/providers/twitter/actions/schedule-tweet.action.js.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.d.ts.map +1 -1
- package/dist/providers/twitter/actions/search-tweets.action.js +56 -58
- package/dist/providers/twitter/actions/search-tweets.action.js.map +1 -1
- package/dist/providers/twitter/twitter-base.action.d.ts.map +1 -1
- package/dist/providers/twitter/twitter-base.action.js +58 -68
- package/dist/providers/twitter/twitter-base.action.js.map +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts +1 -1
- package/dist/providers/youtube/youtube-base.action.d.ts.map +1 -1
- package/dist/providers/youtube/youtube-base.action.js +22 -25
- package/dist/providers/youtube/youtube-base.action.js.map +1 -1
- package/package.json +5 -6
- package/src/base/base-social.action.ts +217 -224
- package/src/providers/buffer/buffer-base.action.ts +435 -441
- package/src/providers/facebook/actions/boost-post.action.ts +350 -386
- package/src/providers/facebook/actions/create-album.action.ts +291 -307
- package/src/providers/facebook/actions/create-post.action.ts +224 -227
- package/src/providers/facebook/actions/get-page-insights.action.ts +383 -403
- package/src/providers/facebook/actions/get-page-posts.action.ts +214 -225
- package/src/providers/facebook/actions/get-post-insights.action.ts +300 -316
- package/src/providers/facebook/actions/respond-to-comments.action.ts +319 -336
- package/src/providers/facebook/actions/schedule-post.action.ts +289 -292
- package/src/providers/facebook/actions/search-posts.action.ts +399 -413
- package/src/providers/facebook/facebook-base.action.ts +653 -670
- package/src/providers/hootsuite/actions/bulk-schedule-posts.action.ts +257 -257
- package/src/providers/hootsuite/actions/create-scheduled-post.action.ts +184 -189
- package/src/providers/hootsuite/actions/delete-scheduled-post.action.ts +160 -161
- package/src/providers/hootsuite/actions/get-analytics.action.ts +249 -254
- package/src/providers/hootsuite/actions/get-scheduled-posts.action.ts +206 -207
- package/src/providers/hootsuite/actions/get-social-profiles.action.ts +206 -205
- package/src/providers/hootsuite/actions/search-posts.action.ts +351 -369
- package/src/providers/hootsuite/actions/update-scheduled-post.action.ts +211 -209
- package/src/providers/hootsuite/hootsuite-base.action.ts +301 -307
- package/src/providers/instagram/actions/create-post.action.ts +276 -296
- package/src/providers/instagram/actions/create-story.action.ts +378 -394
- package/src/providers/instagram/actions/get-account-insights.action.ts +384 -420
- package/src/providers/instagram/actions/get-business-posts.action.ts +233 -242
- package/src/providers/instagram/actions/get-comments.action.ts +365 -377
- package/src/providers/instagram/actions/get-post-insights.action.ts +265 -273
- package/src/providers/instagram/actions/schedule-post.action.ts +233 -235
- package/src/providers/instagram/actions/search-posts.action.ts +512 -538
- package/src/providers/instagram/instagram-base.action.ts +368 -393
- package/src/providers/linkedin/actions/create-article.action.ts +275 -266
- package/src/providers/linkedin/actions/create-post.action.ts +179 -177
- package/src/providers/linkedin/actions/get-followers.action.ts +211 -211
- package/src/providers/linkedin/actions/get-organization-posts.action.ts +146 -147
- package/src/providers/linkedin/actions/get-personal-posts.action.ts +138 -139
- package/src/providers/linkedin/actions/get-post-analytics.action.ts +190 -189
- package/src/providers/linkedin/actions/schedule-post.action.ts +191 -189
- package/src/providers/linkedin/actions/search-posts.action.ts +275 -283
- package/src/providers/linkedin/linkedin-base.action.ts +407 -421
- package/src/providers/tiktok/tiktok-base.action.ts +305 -320
- package/src/providers/twitter/actions/create-thread.action.ts +203 -207
- package/src/providers/twitter/actions/create-tweet.action.ts +187 -188
- package/src/providers/twitter/actions/delete-tweet.action.ts +128 -129
- package/src/providers/twitter/actions/get-analytics.action.ts +402 -411
- package/src/providers/twitter/actions/get-mentions.action.ts +218 -219
- package/src/providers/twitter/actions/get-timeline.action.ts +232 -233
- package/src/providers/twitter/actions/schedule-tweet.action.ts +221 -222
- package/src/providers/twitter/actions/search-tweets.action.ts +540 -543
- package/src/providers/twitter/twitter-base.action.ts +541 -560
- 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, LinkedInShareData, LinkedInArticle } from '../linkedin-base.action';
|
|
3
3
|
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
|
|
4
|
-
import { LogStatus, LogError } from '@memberjunction/
|
|
4
|
+
import { LogStatus, LogError } from '@memberjunction/global';
|
|
5
5
|
import { MediaFile } from '../../../base/base-social.action';
|
|
6
6
|
import { BaseAction } from '@memberjunction/actions';
|
|
7
7
|
|
|
@@ -10,293 +10,302 @@ import { BaseAction } from '@memberjunction/actions';
|
|
|
10
10
|
*/
|
|
11
11
|
@RegisterClass(BaseAction, 'LinkedInCreateArticleAction')
|
|
12
12
|
export class LinkedInCreateArticleAction extends LinkedInBaseAction {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
+
* Create a LinkedIn article
|
|
15
|
+
*/
|
|
16
|
+
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
|
|
17
|
+
const { Params, ContextUser } = params;
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const organizationId = this.getParamValue(Params, 'OrganizationID');
|
|
33
|
-
const visibility = this.getParamValue(Params, 'Visibility') || 'PUBLIC';
|
|
34
|
-
const publishImmediately = this.getParamValue(Params, 'PublishImmediately') !== false; // Default true
|
|
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
|
+
}
|
|
35
25
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
// Extract parameters
|
|
27
|
+
const title = this.getParamValue(Params, 'Title');
|
|
28
|
+
const content = this.getParamValue(Params, 'Content');
|
|
29
|
+
const description = this.getParamValue(Params, 'Description');
|
|
30
|
+
const coverImage = this.getParamValue(Params, 'CoverImage');
|
|
31
|
+
const authorType = this.getParamValue(Params, 'AuthorType') || 'personal'; // 'personal' or 'organization'
|
|
32
|
+
const organizationId = this.getParamValue(Params, 'OrganizationID');
|
|
33
|
+
const visibility = this.getParamValue(Params, 'Visibility') || 'PUBLIC';
|
|
34
|
+
const publishImmediately = this.getParamValue(Params, 'PublishImmediately') !== false; // Default true
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
36
|
+
// Validate required parameters
|
|
37
|
+
if (!title) {
|
|
38
|
+
throw new Error('Title is required');
|
|
39
|
+
}
|
|
40
|
+
if (!content) {
|
|
41
|
+
throw new Error('Content is required');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Determine author URN
|
|
45
|
+
let authorUrn: string;
|
|
46
|
+
if (authorType === 'organization') {
|
|
47
|
+
if (!organizationId) {
|
|
48
|
+
// Get first admin organization if not specified
|
|
49
|
+
const orgs = await this.getAdminOrganizations();
|
|
50
|
+
if (orgs.length === 0) {
|
|
51
|
+
throw new Error('No organizations found. Please specify OrganizationID.');
|
|
52
|
+
}
|
|
53
|
+
authorUrn = orgs[0].urn;
|
|
54
|
+
LogStatus(`Using organization: ${orgs[0].name}`);
|
|
55
|
+
} else {
|
|
56
|
+
authorUrn = `urn:li:organization:${organizationId}`;
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
// Personal article
|
|
60
|
+
authorUrn = await this.getCurrentUserUrn();
|
|
61
|
+
}
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
// Upload cover image if provided
|
|
64
|
+
let coverImageUrn: string | undefined;
|
|
65
|
+
if (coverImage) {
|
|
66
|
+
LogStatus('Uploading cover image...');
|
|
67
|
+
const coverImageFile = coverImage as MediaFile;
|
|
68
|
+
const uploadedUrns = await this.uploadMedia([coverImageFile]);
|
|
69
|
+
coverImageUrn = uploadedUrns[0];
|
|
70
|
+
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
description: description ? {
|
|
89
|
-
text: description
|
|
90
|
-
} : undefined
|
|
91
|
-
}]
|
|
92
|
-
}
|
|
72
|
+
// Create article share data
|
|
73
|
+
const articleShareData: LinkedInShareData = {
|
|
74
|
+
author: authorUrn,
|
|
75
|
+
lifecycleState: publishImmediately ? 'PUBLISHED' : 'DRAFT',
|
|
76
|
+
specificContent: {
|
|
77
|
+
'com.linkedin.ugc.ShareContent': {
|
|
78
|
+
shareCommentary: {
|
|
79
|
+
text: description || `Check out my new article: ${title}`,
|
|
80
|
+
},
|
|
81
|
+
shareMediaCategory: 'ARTICLE',
|
|
82
|
+
media: [
|
|
83
|
+
{
|
|
84
|
+
status: 'READY' as const,
|
|
85
|
+
media: '', // Article URL will be filled after creation
|
|
86
|
+
title: {
|
|
87
|
+
text: title,
|
|
93
88
|
},
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
89
|
+
description: description
|
|
90
|
+
? {
|
|
91
|
+
text: description,
|
|
92
|
+
}
|
|
93
|
+
: undefined,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
visibility: {
|
|
99
|
+
'com.linkedin.ugc.MemberNetworkVisibility': visibility as any,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
// Format content for LinkedIn article
|
|
104
|
+
const formattedContent = this.formatArticleContent(content);
|
|
101
105
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// Note: LinkedIn's v2 API has limited article creation support
|
|
106
|
-
// Full article creation typically requires using the Publishing Platform API
|
|
107
|
-
// This implementation creates an article-style share with rich content
|
|
108
|
-
|
|
109
|
-
// For now, we'll create a rich media share that looks like an article
|
|
110
|
-
const articlePost = await this.createRichMediaShare(
|
|
111
|
-
authorUrn,
|
|
112
|
-
title,
|
|
113
|
-
formattedContent,
|
|
114
|
-
description,
|
|
115
|
-
coverImageUrn,
|
|
116
|
-
visibility,
|
|
117
|
-
publishImmediately
|
|
118
|
-
);
|
|
106
|
+
// Create the article
|
|
107
|
+
LogStatus('Creating LinkedIn article...');
|
|
119
108
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (articleParam) articleParam.Value = articlePost;
|
|
124
|
-
const articleIdParam = outputParams.find(p => p.Name === 'ArticleID');
|
|
125
|
-
if (articleIdParam) articleIdParam.Value = articlePost.id;
|
|
109
|
+
// Note: LinkedIn's v2 API has limited article creation support
|
|
110
|
+
// Full article creation typically requires using the Publishing Platform API
|
|
111
|
+
// This implementation creates an article-style share with rich content
|
|
126
112
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
113
|
+
// For now, we'll create a rich media share that looks like an article
|
|
114
|
+
const articlePost = await this.createRichMediaShare(
|
|
115
|
+
authorUrn,
|
|
116
|
+
title,
|
|
117
|
+
formattedContent,
|
|
118
|
+
description,
|
|
119
|
+
coverImageUrn,
|
|
120
|
+
visibility,
|
|
121
|
+
publishImmediately
|
|
122
|
+
);
|
|
133
123
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
124
|
+
// Update output parameters
|
|
125
|
+
const outputParams = [...Params];
|
|
126
|
+
const articleParam = outputParams.find((p) => p.Name === 'Article');
|
|
127
|
+
if (articleParam) articleParam.Value = articlePost;
|
|
128
|
+
const articleIdParam = outputParams.find((p) => p.Name === 'ArticleID');
|
|
129
|
+
if (articleIdParam) articleIdParam.Value = articlePost.id;
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
Success: true,
|
|
133
|
+
ResultCode: 'SUCCESS',
|
|
134
|
+
Message: `Successfully created LinkedIn article: ${title}`,
|
|
135
|
+
Params: outputParams,
|
|
136
|
+
};
|
|
137
|
+
} catch (error) {
|
|
138
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
145
139
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
140
|
+
return {
|
|
141
|
+
Success: false,
|
|
142
|
+
ResultCode: 'ERROR',
|
|
143
|
+
Message: `Failed to create LinkedIn article: ${errorMessage}`,
|
|
144
|
+
Params,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
153
148
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Format article content for LinkedIn
|
|
151
|
+
*/
|
|
152
|
+
private formatArticleContent(content: string): string {
|
|
153
|
+
// LinkedIn articles support basic HTML formatting
|
|
154
|
+
// Convert markdown-style formatting to LinkedIn-compatible format
|
|
155
|
+
let formatted = content;
|
|
158
156
|
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
// Convert markdown headers to bold text
|
|
158
|
+
formatted = formatted.replace(/^### (.+)$/gm, '\n**$1**\n');
|
|
159
|
+
formatted = formatted.replace(/^## (.+)$/gm, '\n**$1**\n');
|
|
160
|
+
formatted = formatted.replace(/^# (.+)$/gm, '\n**$1**\n');
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
// Convert markdown bold
|
|
163
|
+
formatted = formatted.replace(/\*\*(.+?)\*\*/g, '**$1**');
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
// Convert markdown italic
|
|
166
|
+
formatted = formatted.replace(/\*(.+?)\*/g, '_$1_');
|
|
167
167
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (formatted.length > maxLength) {
|
|
171
|
-
formatted = formatted.substring(0, maxLength - 3) + '...';
|
|
172
|
-
}
|
|
168
|
+
// Add line breaks for paragraphs
|
|
169
|
+
formatted = formatted.replace(/\n\n/g, '\n\n');
|
|
173
170
|
|
|
174
|
-
|
|
171
|
+
// Truncate if too long (LinkedIn has character limits)
|
|
172
|
+
const maxLength = 3000; // LinkedIn's limit for share commentary
|
|
173
|
+
if (formatted.length > maxLength) {
|
|
174
|
+
formatted = formatted.substring(0, maxLength - 3) + '...';
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
*/
|
|
180
|
-
private async createRichMediaShare(
|
|
181
|
-
authorUrn: string,
|
|
182
|
-
title: string,
|
|
183
|
-
content: string,
|
|
184
|
-
description?: string,
|
|
185
|
-
coverImageUrn?: string,
|
|
186
|
-
visibility: string = 'PUBLIC',
|
|
187
|
-
publishImmediately: boolean = true
|
|
188
|
-
): Promise<any> {
|
|
189
|
-
try {
|
|
190
|
-
// Create a rich share with article-like formatting
|
|
191
|
-
const shareData: LinkedInShareData = {
|
|
192
|
-
author: authorUrn,
|
|
193
|
-
lifecycleState: publishImmediately ? 'PUBLISHED' : 'DRAFT',
|
|
194
|
-
specificContent: {
|
|
195
|
-
'com.linkedin.ugc.ShareContent': {
|
|
196
|
-
shareCommentary: {
|
|
197
|
-
text: `📝 ${title}\n\n${content}`
|
|
198
|
-
},
|
|
199
|
-
shareMediaCategory: coverImageUrn ? 'IMAGE' : 'NONE',
|
|
200
|
-
media: coverImageUrn ? [{
|
|
201
|
-
status: 'READY' as const,
|
|
202
|
-
media: coverImageUrn,
|
|
203
|
-
title: {
|
|
204
|
-
text: title
|
|
205
|
-
},
|
|
206
|
-
description: description ? {
|
|
207
|
-
text: description
|
|
208
|
-
} : undefined
|
|
209
|
-
}] : undefined
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
visibility: {
|
|
213
|
-
'com.linkedin.ugc.MemberNetworkVisibility': visibility as any
|
|
214
|
-
}
|
|
215
|
-
};
|
|
177
|
+
return formatted;
|
|
178
|
+
}
|
|
216
179
|
|
|
217
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Create a rich media share that resembles an article
|
|
182
|
+
*/
|
|
183
|
+
private async createRichMediaShare(
|
|
184
|
+
authorUrn: string,
|
|
185
|
+
title: string,
|
|
186
|
+
content: string,
|
|
187
|
+
description?: string,
|
|
188
|
+
coverImageUrn?: string,
|
|
189
|
+
visibility: string = 'PUBLIC',
|
|
190
|
+
publishImmediately: boolean = true
|
|
191
|
+
): Promise<any> {
|
|
192
|
+
try {
|
|
193
|
+
// Create a rich share with article-like formatting
|
|
194
|
+
const shareData: LinkedInShareData = {
|
|
195
|
+
author: authorUrn,
|
|
196
|
+
lifecycleState: publishImmediately ? 'PUBLISHED' : 'DRAFT',
|
|
197
|
+
specificContent: {
|
|
198
|
+
'com.linkedin.ugc.ShareContent': {
|
|
199
|
+
shareCommentary: {
|
|
200
|
+
text: `📝 ${title}\n\n${content}`,
|
|
201
|
+
},
|
|
202
|
+
shareMediaCategory: coverImageUrn ? 'IMAGE' : 'NONE',
|
|
203
|
+
media: coverImageUrn
|
|
204
|
+
? [
|
|
205
|
+
{
|
|
206
|
+
status: 'READY' as const,
|
|
207
|
+
media: coverImageUrn,
|
|
208
|
+
title: {
|
|
209
|
+
text: title,
|
|
210
|
+
},
|
|
211
|
+
description: description
|
|
212
|
+
? {
|
|
213
|
+
text: description,
|
|
214
|
+
}
|
|
215
|
+
: undefined,
|
|
216
|
+
},
|
|
217
|
+
]
|
|
218
|
+
: undefined,
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
visibility: {
|
|
222
|
+
'com.linkedin.ugc.MemberNetworkVisibility': visibility as any,
|
|
223
|
+
},
|
|
224
|
+
};
|
|
218
225
|
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
id: postId,
|
|
222
|
-
title: title,
|
|
223
|
-
content: content,
|
|
224
|
-
description: description,
|
|
225
|
-
coverImage: coverImageUrn,
|
|
226
|
-
author: authorUrn,
|
|
227
|
-
publishedAt: publishImmediately ? new Date().toISOString() : null,
|
|
228
|
-
visibility: visibility,
|
|
229
|
-
url: `https://www.linkedin.com/feed/update/${postId}/`
|
|
230
|
-
};
|
|
231
|
-
} catch (error) {
|
|
232
|
-
LogError(`Failed to create rich media share: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
233
|
-
throw error;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
226
|
+
const postId = await this.createShare(shareData);
|
|
236
227
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
Name: 'Description',
|
|
255
|
-
Type: 'Input',
|
|
256
|
-
Value: null
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
Name: 'CoverImage',
|
|
260
|
-
Type: 'Input',
|
|
261
|
-
Value: null
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
Name: 'AuthorType',
|
|
265
|
-
Type: 'Input',
|
|
266
|
-
Value: 'personal' // 'personal' or 'organization'
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
Name: 'OrganizationID',
|
|
270
|
-
Type: 'Input',
|
|
271
|
-
Value: null
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
Name: 'Visibility',
|
|
275
|
-
Type: 'Input',
|
|
276
|
-
Value: 'PUBLIC' // 'PUBLIC', 'CONNECTIONS', 'LOGGED_IN', 'CONTAINER'
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
Name: 'PublishImmediately',
|
|
280
|
-
Type: 'Input',
|
|
281
|
-
Value: true
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
Name: 'Article',
|
|
285
|
-
Type: 'Output',
|
|
286
|
-
Value: null
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
Name: 'ArticleID',
|
|
290
|
-
Type: 'Output',
|
|
291
|
-
Value: null
|
|
292
|
-
}
|
|
293
|
-
];
|
|
228
|
+
// Return article-like object
|
|
229
|
+
return {
|
|
230
|
+
id: postId,
|
|
231
|
+
title: title,
|
|
232
|
+
content: content,
|
|
233
|
+
description: description,
|
|
234
|
+
coverImage: coverImageUrn,
|
|
235
|
+
author: authorUrn,
|
|
236
|
+
publishedAt: publishImmediately ? new Date().toISOString() : null,
|
|
237
|
+
visibility: visibility,
|
|
238
|
+
url: `https://www.linkedin.com/feed/update/${postId}/`,
|
|
239
|
+
};
|
|
240
|
+
} catch (error) {
|
|
241
|
+
LogError(`Failed to create rich media share: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
242
|
+
throw error;
|
|
294
243
|
}
|
|
244
|
+
}
|
|
295
245
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Define the parameters this action expects
|
|
248
|
+
*/
|
|
249
|
+
public get Params(): ActionParam[] {
|
|
250
|
+
return [
|
|
251
|
+
...this.commonSocialParams,
|
|
252
|
+
{
|
|
253
|
+
Name: 'Title',
|
|
254
|
+
Type: 'Input',
|
|
255
|
+
Value: null,
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
Name: 'Content',
|
|
259
|
+
Type: 'Input',
|
|
260
|
+
Value: null,
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
Name: 'Description',
|
|
264
|
+
Type: 'Input',
|
|
265
|
+
Value: null,
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
Name: 'CoverImage',
|
|
269
|
+
Type: 'Input',
|
|
270
|
+
Value: null,
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
Name: 'AuthorType',
|
|
274
|
+
Type: 'Input',
|
|
275
|
+
Value: 'personal', // 'personal' or 'organization'
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
Name: 'OrganizationID',
|
|
279
|
+
Type: 'Input',
|
|
280
|
+
Value: null,
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
Name: 'Visibility',
|
|
284
|
+
Type: 'Input',
|
|
285
|
+
Value: 'PUBLIC', // 'PUBLIC', 'CONNECTIONS', 'LOGGED_IN', 'CONTAINER'
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
Name: 'PublishImmediately',
|
|
289
|
+
Type: 'Input',
|
|
290
|
+
Value: true,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
Name: 'Article',
|
|
294
|
+
Type: 'Output',
|
|
295
|
+
Value: null,
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
Name: 'ArticleID',
|
|
299
|
+
Type: 'Output',
|
|
300
|
+
Value: null,
|
|
301
|
+
},
|
|
302
|
+
];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get action description
|
|
307
|
+
*/
|
|
308
|
+
public get Description(): string {
|
|
309
|
+
return 'Creates a LinkedIn article (long-form content) with title, content, and optional cover image. Note: Uses rich media shares to simulate article functionality due to API limitations.';
|
|
310
|
+
}
|
|
311
|
+
}
|