mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
fix(LinkedIn Node): Update the version of the API (#5720)
* 🐛 Change request to follow new API version
* Extract urn from response header
* Change body params for image and media request
* Fix body for Image and Article posts
* remove console log
---------
Co-authored-by: Marcus <marcus@n8n.io>
This commit is contained in:
parent
97b35daf0a
commit
18d2e7cd57
|
@ -8,6 +8,13 @@ import type {
|
|||
JsonObject,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
function resolveHeaderData(fullResponse: any) {
|
||||
if (fullResponse.statusCode === 201) {
|
||||
return { urn: fullResponse.headers['x-restli-id'] };
|
||||
} else {
|
||||
return fullResponse.body;
|
||||
}
|
||||
}
|
||||
|
||||
export async function linkedInApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
|
||||
|
@ -18,17 +25,20 @@ export async function linkedInApiRequest(
|
|||
binary?: boolean,
|
||||
_headers?: object,
|
||||
): Promise<any> {
|
||||
const options: OptionsWithUrl = {
|
||||
let options: OptionsWithUrl = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'X-Restli-Protocol-Version': '2.0.0',
|
||||
'LinkedIn-Version': '202301',
|
||||
},
|
||||
method,
|
||||
body,
|
||||
url: binary ? endpoint : `https://api.linkedin.com/v2${endpoint}`,
|
||||
url: binary ? endpoint : `https://api.linkedin.com/rest${endpoint}`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
options = Object.assign({}, options, {
|
||||
resolveWithFullResponse: true,
|
||||
});
|
||||
// If uploading binary data
|
||||
if (binary) {
|
||||
delete options.json;
|
||||
|
@ -40,9 +50,11 @@ export async function linkedInApiRequest(
|
|||
}
|
||||
|
||||
try {
|
||||
return await this.helpers.requestOAuth2.call(this, 'linkedInOAuth2Api', options, {
|
||||
tokenType: 'Bearer',
|
||||
});
|
||||
return resolveHeaderData(
|
||||
await this.helpers.requestOAuth2.call(this, 'linkedInOAuth2Api', options, {
|
||||
tokenType: 'Bearer',
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
|
|
|
@ -102,6 +102,17 @@ export class LinkedIn implements INodeType {
|
|||
let title = '';
|
||||
let originalUrl = '';
|
||||
|
||||
body = {
|
||||
author: authorUrn,
|
||||
lifecycleState: 'PUBLISHED',
|
||||
distribution: {
|
||||
feedDistribution: 'MAIN_FEED',
|
||||
targetEnties: [],
|
||||
thirdPartyDistributionChannels: [],
|
||||
},
|
||||
visibility,
|
||||
};
|
||||
|
||||
if (shareMediaCategory === 'IMAGE') {
|
||||
if (additionalFields.description) {
|
||||
description = additionalFields.description as string;
|
||||
|
@ -111,66 +122,36 @@ export class LinkedIn implements INodeType {
|
|||
}
|
||||
// Send a REQUEST to prepare a register of a media image file
|
||||
const registerRequest = {
|
||||
registerUploadRequest: {
|
||||
recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
|
||||
initializeUploadRequest: {
|
||||
owner: authorUrn,
|
||||
serviceRelationships: [
|
||||
{
|
||||
relationshipType: 'OWNER',
|
||||
identifier: 'urn:li:userGeneratedContent',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const registerObject = await linkedInApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
'/assets?action=registerUpload',
|
||||
'/images?action=initializeUpload',
|
||||
registerRequest,
|
||||
);
|
||||
|
||||
// Response provides a specific upload URL that is used to upload the binary image file
|
||||
const uploadUrl = registerObject.value.uploadMechanism[
|
||||
'com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'
|
||||
].uploadUrl as string;
|
||||
const asset = registerObject.value.asset as string;
|
||||
|
||||
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
||||
this.helpers.assertBinaryData(i, binaryPropertyName);
|
||||
|
||||
// Buffer binary data
|
||||
const buffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
|
||||
// Upload image
|
||||
await linkedInApiRequest.call(this, 'POST', uploadUrl, buffer, true);
|
||||
const { uploadUrl, image } = registerObject.value;
|
||||
await linkedInApiRequest.call(this, 'POST', uploadUrl as string, buffer, true);
|
||||
|
||||
body = {
|
||||
author: authorUrn,
|
||||
lifecycleState: 'PUBLISHED',
|
||||
specificContent: {
|
||||
'com.linkedin.ugc.ShareContent': {
|
||||
shareCommentary: {
|
||||
text,
|
||||
},
|
||||
shareMediaCategory: 'IMAGE',
|
||||
media: [
|
||||
{
|
||||
status: 'READY',
|
||||
description: {
|
||||
text: description,
|
||||
},
|
||||
media: asset,
|
||||
title: {
|
||||
text: title,
|
||||
},
|
||||
},
|
||||
],
|
||||
const imageBody = {
|
||||
content: {
|
||||
media: {
|
||||
title,
|
||||
id: image,
|
||||
description,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
|
||||
},
|
||||
commentary: text,
|
||||
};
|
||||
Object.assign(body, imageBody);
|
||||
} else if (shareMediaCategory === 'ARTICLE') {
|
||||
if (additionalFields.description) {
|
||||
description = additionalFields.description as string;
|
||||
|
@ -182,60 +163,28 @@ export class LinkedIn implements INodeType {
|
|||
originalUrl = additionalFields.originalUrl as string;
|
||||
}
|
||||
|
||||
body = {
|
||||
author: `${authorUrn}`,
|
||||
lifecycleState: 'PUBLISHED',
|
||||
specificContent: {
|
||||
'com.linkedin.ugc.ShareContent': {
|
||||
shareCommentary: {
|
||||
text,
|
||||
},
|
||||
shareMediaCategory,
|
||||
media: [
|
||||
{
|
||||
status: 'READY',
|
||||
description: {
|
||||
text: description,
|
||||
},
|
||||
originalUrl,
|
||||
title: {
|
||||
text: title,
|
||||
},
|
||||
},
|
||||
],
|
||||
const articleBody = {
|
||||
content: {
|
||||
article: {
|
||||
title,
|
||||
description,
|
||||
source: originalUrl,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
|
||||
},
|
||||
commentary: text,
|
||||
};
|
||||
|
||||
Object.assign(body, articleBody);
|
||||
if (description === '') {
|
||||
delete body.specificContent['com.linkedin.ugc.ShareContent'].media[0].description;
|
||||
delete body.description;
|
||||
}
|
||||
|
||||
if (title === '') {
|
||||
delete body.specificContent['com.linkedin.ugc.ShareContent'].media[0].title;
|
||||
delete body.title;
|
||||
}
|
||||
} else {
|
||||
body = {
|
||||
author: authorUrn,
|
||||
lifecycleState: 'PUBLISHED',
|
||||
specificContent: {
|
||||
'com.linkedin.ugc.ShareContent': {
|
||||
shareCommentary: {
|
||||
text,
|
||||
},
|
||||
shareMediaCategory,
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
'com.linkedin.ugc.MemberNetworkVisibility': visibility,
|
||||
},
|
||||
};
|
||||
Object.assign(body, { commentary: text });
|
||||
}
|
||||
|
||||
const endpoint = '/ugcPosts';
|
||||
const endpoint = '/posts';
|
||||
responseData = await linkedInApiRequest.call(this, 'POST', endpoint, body);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue