@yaring/n8n-nodes-meta
Version:
N8N node for publishing content to Facebook, Instagram, and Threads with access token authentication. Supports text posts, photos, videos, Reels, carousels, and stories.
382 lines • 18 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FacebookInstagramThreads = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const FacebookInstagramThreadsDescription_1 = require("./FacebookInstagramThreadsDescription");
class FacebookInstagramThreads {
constructor() {
this.description = {
displayName: 'Facebook, Instagram & Threads',
name: 'facebookInstagramThreads',
icon: 'file:facebook-instagram-threads.svg',
group: ['output'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Create and publish content to Facebook, Instagram, and Threads',
defaults: {
name: 'Facebook, Instagram & Threads',
},
inputs: ["main"],
outputs: ["main"],
usableAsTool: true,
credentials: [
{
name: 'facebookInstagramThreadsApi',
required: true,
},
],
requestDefaults: {
baseURL: 'https://graph.facebook.com/v23.0',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Facebook',
value: 'facebook',
description: 'Create content on Facebook',
},
{
name: 'Instagram',
value: 'instagram',
description: 'Create content on Instagram',
},
{
name: 'Thread',
value: 'threads',
description: 'Create content on Threads',
},
],
default: 'facebook',
},
...FacebookInstagramThreadsDescription_1.facebookOperations,
...FacebookInstagramThreadsDescription_1.facebookFields,
...FacebookInstagramThreadsDescription_1.instagramOperations,
...FacebookInstagramThreadsDescription_1.instagramFields,
...FacebookInstagramThreadsDescription_1.threadsOperations,
...FacebookInstagramThreadsDescription_1.threadsFields,
],
};
}
async execute() {
var _a, _b;
const items = this.getInputData();
const returnData = [];
async function handleFacebookOperation(itemIndex, operation) {
const targetId = this.getNodeParameter('targetId', itemIndex);
let endpoint = '';
let body = {};
switch (operation) {
case 'createTextPost':
const message = this.getNodeParameter('message', itemIndex);
endpoint = `/${targetId}/feed`;
body = { message };
break;
case 'createPhotoPost':
const photoUrl = this.getNodeParameter('photoUrl', itemIndex);
const caption = this.getNodeParameter('caption', itemIndex, '');
endpoint = `/${targetId}/photos`;
body = {
url: photoUrl,
...(caption && { caption })
};
break;
case 'createVideoPost':
const videoUrl = this.getNodeParameter('videoUrl', itemIndex);
const videoDescription = this.getNodeParameter('videoDescription', itemIndex, '');
endpoint = `/${targetId}/videos`;
body = {
file_url: videoUrl,
...(videoDescription && { description: videoDescription })
};
break;
case 'createLinkPost':
const linkUrl = this.getNodeParameter('linkUrl', itemIndex);
const linkMessage = this.getNodeParameter('linkMessage', itemIndex, '');
endpoint = `/${targetId}/feed`;
body = {
link: linkUrl,
...(linkMessage && { message: linkMessage })
};
break;
default:
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
}
const requestOptions = {
method: 'POST',
url: endpoint,
body,
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', requestOptions);
}
async function handleInstagramOperation(itemIndex, operation) {
const instagramBusinessAccountId = this.getNodeParameter('instagramBusinessAccountId', itemIndex);
switch (operation) {
case 'createPhotoPost':
return await createInstagramPhoto.call(this, itemIndex, instagramBusinessAccountId);
case 'createVideoPost':
return await createInstagramVideo.call(this, itemIndex, instagramBusinessAccountId);
case 'createReels':
return await createInstagramReels.call(this, itemIndex, instagramBusinessAccountId);
case 'createCarouselPost':
return await createInstagramCarousel.call(this, itemIndex, instagramBusinessAccountId);
case 'createStory':
return await createInstagramStory.call(this, itemIndex, instagramBusinessAccountId);
default:
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
}
}
async function createInstagramPhoto(itemIndex, accountId) {
const imageUrl = this.getNodeParameter('imageUrl', itemIndex);
const caption = this.getNodeParameter('caption', itemIndex, '');
const createRequestOptions = {
method: 'POST',
url: `/${accountId}/media`,
body: {
image_url: imageUrl,
...(caption && { caption }),
},
json: true,
};
const createResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', createRequestOptions);
const publishRequestOptions = {
method: 'POST',
url: `/${accountId}/media_publish`,
body: {
creation_id: createResponse.id,
},
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', publishRequestOptions);
}
async function createInstagramVideo(itemIndex, accountId) {
const videoUrl = this.getNodeParameter('videoUrl', itemIndex);
const videoCaption = this.getNodeParameter('videoCaption', itemIndex, '');
const createRequestOptions = {
method: 'POST',
url: `/${accountId}/media`,
body: {
video_url: videoUrl,
media_type: 'VIDEO',
...(videoCaption && { caption: videoCaption }),
},
json: true,
};
const createResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', createRequestOptions);
const publishRequestOptions = {
method: 'POST',
url: `/${accountId}/media_publish`,
body: {
creation_id: createResponse.id,
},
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', publishRequestOptions);
}
async function createInstagramReels(itemIndex, accountId) {
const reelsVideoUrl = this.getNodeParameter('reelsVideoUrl', itemIndex);
const reelsCaption = this.getNodeParameter('reelsCaption', itemIndex, '');
const coverImageUrl = this.getNodeParameter('coverImageUrl', itemIndex, '');
const createRequestOptions = {
method: 'POST',
url: `/${accountId}/media`,
body: {
video_url: reelsVideoUrl,
media_type: 'REELS',
...(reelsCaption && { caption: reelsCaption }),
...(coverImageUrl && { cover_url: coverImageUrl }),
},
json: true,
};
const createResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', createRequestOptions);
const publishRequestOptions = {
method: 'POST',
url: `/${accountId}/media_publish`,
body: {
creation_id: createResponse.id,
},
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', publishRequestOptions);
}
async function createInstagramCarousel(itemIndex, accountId) {
const mediaItems = this.getNodeParameter('mediaItems.mediaItem', itemIndex, []);
const carouselCaption = this.getNodeParameter('carouselCaption', itemIndex, '');
const mediaContainerIds = [];
for (const mediaItem of mediaItems) {
const createRequestOptions = {
method: 'POST',
url: `/${accountId}/media`,
body: {
...(mediaItem.mediaType === 'IMAGE'
? { image_url: mediaItem.mediaUrl }
: { video_url: mediaItem.mediaUrl, media_type: 'VIDEO' }),
is_carousel_item: true,
},
json: true,
};
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', createRequestOptions);
mediaContainerIds.push(response.id);
}
const carouselRequestOptions = {
method: 'POST',
url: `/${accountId}/media`,
body: {
media_type: 'CAROUSEL',
children: mediaContainerIds.join(','),
...(carouselCaption && { caption: carouselCaption }),
},
json: true,
};
const carouselResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', carouselRequestOptions);
const publishRequestOptions = {
method: 'POST',
url: `/${accountId}/media_publish`,
body: {
creation_id: carouselResponse.id,
},
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', publishRequestOptions);
}
async function createInstagramStory(itemIndex, accountId) {
const storyMediaUrl = this.getNodeParameter('storyMediaUrl', itemIndex);
const storyMediaType = this.getNodeParameter('storyMediaType', itemIndex);
const requestOptions = {
method: 'POST',
url: `/${accountId}/media`,
body: {
...(storyMediaType === 'IMAGE'
? { image_url: storyMediaUrl }
: { video_url: storyMediaUrl }),
media_type: 'STORIES',
},
json: true,
};
const createResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', requestOptions);
const publishRequestOptions = {
method: 'POST',
url: `/${accountId}/media_publish`,
body: {
creation_id: createResponse.id,
},
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', publishRequestOptions);
}
async function handleThreadsOperation(itemIndex, operation) {
const threadsUserId = this.getNodeParameter('threadsUserId', itemIndex);
let endpoint = '';
let body = {};
switch (operation) {
case 'createTextPost':
const text = this.getNodeParameter('text', itemIndex);
endpoint = `/${threadsUserId}/threads`;
body = { text };
break;
case 'createPhotoPost':
const imageUrl = this.getNodeParameter('imageUrl', itemIndex);
const photoText = this.getNodeParameter('photoText', itemIndex, '');
endpoint = `/${threadsUserId}/threads`;
body = {
image_url: imageUrl,
...(photoText && { text: photoText })
};
break;
case 'createVideoPost':
const videoUrl = this.getNodeParameter('videoUrl', itemIndex);
const videoText = this.getNodeParameter('videoText', itemIndex, '');
endpoint = `/${threadsUserId}/threads`;
body = {
video_url: videoUrl,
...(videoText && { text: videoText })
};
break;
default:
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
}
const createRequestOptions = {
method: 'POST',
url: endpoint,
body,
json: true,
};
const createResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', createRequestOptions);
const publishRequestOptions = {
method: 'POST',
url: `/${threadsUserId}/threads_publish`,
body: {
creation_id: createResponse.id,
},
json: true,
};
return await this.helpers.httpRequestWithAuthentication.call(this, 'facebookInstagramThreadsApi', publishRequestOptions);
}
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
try {
const resource = this.getNodeParameter('resource', itemIndex);
const operation = this.getNodeParameter('operation', itemIndex);
let responseData = {};
if (resource === 'facebook') {
responseData = await handleFacebookOperation.call(this, itemIndex, operation);
}
else if (resource === 'instagram') {
responseData = await handleInstagramOperation.call(this, itemIndex, operation);
}
else if (resource === 'threads') {
responseData = await handleThreadsOperation.call(this, itemIndex, operation);
}
returnData.push({
json: responseData,
pairedItem: itemIndex
});
}
catch (error) {
let errorMessage = 'Unknown error occurred';
let errorDetails = {};
if ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) {
const fbError = error.response.data.error;
errorMessage = `${fbError.type}: ${fbError.message}`;
errorDetails = {
code: fbError.code,
type: fbError.type,
message: fbError.message,
fbtrace_id: fbError.fbtrace_id,
};
}
else if (error.message) {
errorMessage = error.message;
}
if (this.continueOnFail()) {
returnData.push({
json: {
...this.getInputData(itemIndex)[0].json,
error: errorMessage,
errorDetails,
},
error,
pairedItem: itemIndex
});
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Facebook/Instagram/Threads API Error: ${errorMessage}`, {
itemIndex,
description: JSON.stringify(errorDetails, null, 2),
});
}
}
}
return [returnData];
}
}
exports.FacebookInstagramThreads = FacebookInstagramThreads;
//# sourceMappingURL=FacebookInstagramThreads.node.js.map