@pakoor/n8n-nodes-instagram 0.1.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/README.md +271 -0
- package/dist/__tests__/helpers/index.d.ts +2 -0
- package/dist/__tests__/helpers/index.d.ts.map +1 -0
- package/dist/__tests__/helpers/index.js +18 -0
- package/dist/__tests__/helpers/index.js.map +1 -0
- package/dist/__tests__/helpers/testUtils.d.ts +104 -0
- package/dist/__tests__/helpers/testUtils.d.ts.map +1 -0
- package/dist/__tests__/helpers/testUtils.js +175 -0
- package/dist/__tests__/helpers/testUtils.js.map +1 -0
- package/dist/credentials/InstagramAccessTokenApi.credentials.d.ts +19 -0
- package/dist/credentials/InstagramAccessTokenApi.credentials.d.ts.map +1 -0
- package/dist/credentials/InstagramAccessTokenApi.credentials.js +130 -0
- package/dist/credentials/InstagramAccessTokenApi.credentials.js.map +1 -0
- package/dist/credentials/InstagramOAuth2Api.credentials.d.ts +20 -0
- package/dist/credentials/InstagramOAuth2Api.credentials.d.ts.map +1 -0
- package/dist/credentials/InstagramOAuth2Api.credentials.js +177 -0
- package/dist/credentials/InstagramOAuth2Api.credentials.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/Instagram/Instagram.node.d.ts +10 -0
- package/dist/nodes/Instagram/Instagram.node.d.ts.map +1 -0
- package/dist/nodes/Instagram/Instagram.node.js +1152 -0
- package/dist/nodes/Instagram/Instagram.node.js.map +1 -0
- package/dist/nodes/Instagram/InstagramTrigger.node.d.ts +61 -0
- package/dist/nodes/Instagram/InstagramTrigger.node.d.ts.map +1 -0
- package/dist/nodes/Instagram/InstagramTrigger.node.js +315 -0
- package/dist/nodes/Instagram/InstagramTrigger.node.js.map +1 -0
- package/dist/nodes/Instagram/instagram.svg +15 -0
- package/dist/services/InstagramApiClient.d.ts +261 -0
- package/dist/services/InstagramApiClient.d.ts.map +1 -0
- package/dist/services/InstagramApiClient.js +548 -0
- package/dist/services/InstagramApiClient.js.map +1 -0
- package/dist/services/TokenManager.d.ts +73 -0
- package/dist/services/TokenManager.d.ts.map +1 -0
- package/dist/services/TokenManager.js +150 -0
- package/dist/services/TokenManager.js.map +1 -0
- package/dist/services/ValidationUtils.d.ts +44 -0
- package/dist/services/ValidationUtils.d.ts.map +1 -0
- package/dist/services/ValidationUtils.js +203 -0
- package/dist/services/ValidationUtils.js.map +1 -0
- package/dist/services/WebhookHandler.d.ts +206 -0
- package/dist/services/WebhookHandler.d.ts.map +1 -0
- package/dist/services/WebhookHandler.js +261 -0
- package/dist/services/WebhookHandler.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +21 -0
- package/dist/services/index.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,1152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Instagram = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const InstagramApiClient_1 = require("../../services/InstagramApiClient");
|
|
6
|
+
/**
|
|
7
|
+
* Instagram Node
|
|
8
|
+
*
|
|
9
|
+
* Main n8n node for Instagram Messaging and Content API operations.
|
|
10
|
+
* Supports messaging, user profiles, comments, posts, stories, reels, and media management.
|
|
11
|
+
*
|
|
12
|
+
* Requirements: All messaging, user, comment, post, media operations
|
|
13
|
+
*/
|
|
14
|
+
// Resource options
|
|
15
|
+
const resourceOptions = [
|
|
16
|
+
{ name: 'Message', value: 'message', description: 'Send messages to Instagram users' },
|
|
17
|
+
{ name: 'User', value: 'user', description: 'Get user profile information' },
|
|
18
|
+
{ name: 'Comment', value: 'comment', description: 'Manage comments on posts' },
|
|
19
|
+
{ name: 'Post', value: 'post', description: 'Create and publish posts' },
|
|
20
|
+
{ name: 'Story', value: 'story', description: 'Create and publish stories' },
|
|
21
|
+
{ name: 'Reel', value: 'reel', description: 'Create and publish reels' },
|
|
22
|
+
{ name: 'Media', value: 'media', description: 'Manage existing media' },
|
|
23
|
+
];
|
|
24
|
+
// Message operations
|
|
25
|
+
const messageOperations = [
|
|
26
|
+
{ name: 'Send Text', value: 'sendText', description: 'Send a text message' },
|
|
27
|
+
{ name: 'Send Image', value: 'sendImage', description: 'Send an image message' },
|
|
28
|
+
{ name: 'Send Audio', value: 'sendAudio', description: 'Send an audio message' },
|
|
29
|
+
{ name: 'Send Video', value: 'sendVideo', description: 'Send a video message' },
|
|
30
|
+
{ name: 'Send Button Template', value: 'sendButtonTemplate', description: 'Send interactive buttons' },
|
|
31
|
+
{ name: 'Send Generic Template', value: 'sendGenericTemplate', description: 'Send a carousel of cards' },
|
|
32
|
+
{ name: 'Send Quick Replies', value: 'sendQuickReplies', description: 'Send quick reply options' },
|
|
33
|
+
];
|
|
34
|
+
// User operations
|
|
35
|
+
const userOperations = [
|
|
36
|
+
{ name: 'Get Profile', value: 'getProfile', description: 'Get user profile by IGSID' },
|
|
37
|
+
{ name: 'Get My Profile', value: 'getMyProfile', description: 'Get authenticated account profile' },
|
|
38
|
+
];
|
|
39
|
+
// Comment operations
|
|
40
|
+
const commentOperations = [
|
|
41
|
+
{ name: 'Get Comments', value: 'getComments', description: 'Get comments on a media' },
|
|
42
|
+
{ name: 'Get Replies', value: 'getReplies', description: 'Get replies to a comment' },
|
|
43
|
+
{ name: 'Reply', value: 'reply', description: 'Reply to a comment publicly' },
|
|
44
|
+
{ name: 'Send Private Reply', value: 'sendPrivateReply', description: 'Send a private DM reply' },
|
|
45
|
+
{ name: 'Delete', value: 'delete', description: 'Delete a comment' },
|
|
46
|
+
{ name: 'Toggle Visibility', value: 'toggleVisibility', description: 'Hide or unhide a comment' },
|
|
47
|
+
];
|
|
48
|
+
// Post operations
|
|
49
|
+
const postOperations = [
|
|
50
|
+
{ name: 'Create Single', value: 'createSingle', description: 'Create a single image or video post' },
|
|
51
|
+
{ name: 'Create Carousel', value: 'createCarousel', description: 'Create a carousel post' },
|
|
52
|
+
{ name: 'Publish', value: 'publish', description: 'Publish a media container' },
|
|
53
|
+
];
|
|
54
|
+
// Story operations
|
|
55
|
+
const storyOperations = [
|
|
56
|
+
{ name: 'Create', value: 'create', description: 'Create and publish a story' },
|
|
57
|
+
];
|
|
58
|
+
// Reel operations
|
|
59
|
+
const reelOperations = [
|
|
60
|
+
{ name: 'Create', value: 'create', description: 'Create and publish a reel' },
|
|
61
|
+
];
|
|
62
|
+
// Media operations
|
|
63
|
+
const mediaOperations = [
|
|
64
|
+
{ name: 'List', value: 'list', description: 'List all media' },
|
|
65
|
+
{ name: 'Get', value: 'get', description: 'Get media details by ID' },
|
|
66
|
+
{ name: 'Get Children', value: 'getChildren', description: 'Get carousel children' },
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Format error for output
|
|
70
|
+
*/
|
|
71
|
+
function formatError(error) {
|
|
72
|
+
if (error instanceof InstagramApiClient_1.InstagramApiError) {
|
|
73
|
+
return {
|
|
74
|
+
error: true,
|
|
75
|
+
code: error.code,
|
|
76
|
+
message: error.message,
|
|
77
|
+
subcode: error.subcode,
|
|
78
|
+
type: error.type,
|
|
79
|
+
suggestion: error.suggestion,
|
|
80
|
+
retryable: error.retryable,
|
|
81
|
+
retryAfter: error.retryAfter,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
error: true,
|
|
86
|
+
message: error.message,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Execute message operations
|
|
91
|
+
* Requirements: 3.1-3.5, 4.1-4.5, 5.1-5.6
|
|
92
|
+
*/
|
|
93
|
+
async function executeMessageOperation(context, client, operation, itemIndex) {
|
|
94
|
+
const recipientId = context.getNodeParameter('recipientId', itemIndex);
|
|
95
|
+
switch (operation) {
|
|
96
|
+
case 'sendText': {
|
|
97
|
+
const text = context.getNodeParameter('messageText', itemIndex);
|
|
98
|
+
return client.sendTextMessage(recipientId, text);
|
|
99
|
+
}
|
|
100
|
+
case 'sendImage': {
|
|
101
|
+
const mediaUrl = context.getNodeParameter('mediaUrl', itemIndex);
|
|
102
|
+
return client.sendMediaMessage(recipientId, 'image', mediaUrl);
|
|
103
|
+
}
|
|
104
|
+
case 'sendAudio': {
|
|
105
|
+
const mediaUrl = context.getNodeParameter('mediaUrl', itemIndex);
|
|
106
|
+
return client.sendMediaMessage(recipientId, 'audio', mediaUrl);
|
|
107
|
+
}
|
|
108
|
+
case 'sendVideo': {
|
|
109
|
+
const mediaUrl = context.getNodeParameter('mediaUrl', itemIndex);
|
|
110
|
+
return client.sendMediaMessage(recipientId, 'video', mediaUrl);
|
|
111
|
+
}
|
|
112
|
+
case 'sendButtonTemplate': {
|
|
113
|
+
const text = context.getNodeParameter('messageText', itemIndex);
|
|
114
|
+
const buttonsData = context.getNodeParameter('buttons.buttonValues', itemIndex, []);
|
|
115
|
+
const buttons = buttonsData.map((b) => ({
|
|
116
|
+
type: b.type,
|
|
117
|
+
title: b.title,
|
|
118
|
+
url: b.url,
|
|
119
|
+
payload: b.payload,
|
|
120
|
+
}));
|
|
121
|
+
return client.sendButtonTemplate(recipientId, text, buttons);
|
|
122
|
+
}
|
|
123
|
+
case 'sendGenericTemplate': {
|
|
124
|
+
const elementsData = context.getNodeParameter('carouselElements.elementValues', itemIndex, []);
|
|
125
|
+
const elements = elementsData.map((e) => ({
|
|
126
|
+
title: e.title,
|
|
127
|
+
subtitle: e.subtitle,
|
|
128
|
+
image_url: e.image_url,
|
|
129
|
+
}));
|
|
130
|
+
return client.sendGenericTemplate(recipientId, elements);
|
|
131
|
+
}
|
|
132
|
+
case 'sendQuickReplies': {
|
|
133
|
+
const text = context.getNodeParameter('messageText', itemIndex);
|
|
134
|
+
const repliesData = context.getNodeParameter('quickReplies.replyValues', itemIndex, []);
|
|
135
|
+
const quickReplies = repliesData.map((r) => ({
|
|
136
|
+
content_type: 'text',
|
|
137
|
+
title: r.title,
|
|
138
|
+
payload: r.payload,
|
|
139
|
+
image_url: r.image_url,
|
|
140
|
+
}));
|
|
141
|
+
return client.sendQuickReplies(recipientId, text, quickReplies);
|
|
142
|
+
}
|
|
143
|
+
default:
|
|
144
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Unknown message operation: ${operation}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Execute user operations
|
|
149
|
+
* Requirements: 6.1-6.3
|
|
150
|
+
*/
|
|
151
|
+
async function executeUserOperation(context, client, operation, itemIndex) {
|
|
152
|
+
switch (operation) {
|
|
153
|
+
case 'getProfile': {
|
|
154
|
+
const userId = context.getNodeParameter('userId', itemIndex);
|
|
155
|
+
return client.getUserProfile(userId);
|
|
156
|
+
}
|
|
157
|
+
case 'getMyProfile': {
|
|
158
|
+
return client.getMyProfile();
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Unknown user operation: ${operation}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execute comment operations
|
|
166
|
+
* Requirements: 7.1-7.7
|
|
167
|
+
*/
|
|
168
|
+
async function executeCommentOperation(context, client, operation, itemIndex) {
|
|
169
|
+
switch (operation) {
|
|
170
|
+
case 'getComments': {
|
|
171
|
+
const mediaId = context.getNodeParameter('mediaId', itemIndex);
|
|
172
|
+
const options = context.getNodeParameter('commentOptions', itemIndex, {});
|
|
173
|
+
return client.getComments(mediaId, {
|
|
174
|
+
limit: options.limit,
|
|
175
|
+
after: options.after,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
case 'getReplies': {
|
|
179
|
+
const commentId = context.getNodeParameter('commentId', itemIndex);
|
|
180
|
+
return client.getReplies(commentId);
|
|
181
|
+
}
|
|
182
|
+
case 'reply': {
|
|
183
|
+
const commentId = context.getNodeParameter('commentId', itemIndex);
|
|
184
|
+
const message = context.getNodeParameter('replyMessage', itemIndex);
|
|
185
|
+
return client.replyToComment(commentId, message);
|
|
186
|
+
}
|
|
187
|
+
case 'sendPrivateReply': {
|
|
188
|
+
const commentId = context.getNodeParameter('commentId', itemIndex);
|
|
189
|
+
const message = context.getNodeParameter('replyMessage', itemIndex);
|
|
190
|
+
return client.sendPrivateReply(commentId, message);
|
|
191
|
+
}
|
|
192
|
+
case 'delete': {
|
|
193
|
+
const commentId = context.getNodeParameter('commentId', itemIndex);
|
|
194
|
+
return client.deleteComment(commentId);
|
|
195
|
+
}
|
|
196
|
+
case 'toggleVisibility': {
|
|
197
|
+
const commentId = context.getNodeParameter('commentId', itemIndex);
|
|
198
|
+
const hide = context.getNodeParameter('hideComment', itemIndex);
|
|
199
|
+
return client.toggleCommentVisibility(commentId, hide);
|
|
200
|
+
}
|
|
201
|
+
default:
|
|
202
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Unknown comment operation: ${operation}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Execute post operations
|
|
207
|
+
* Requirements: 8.1-8.5, 9.1-9.5
|
|
208
|
+
*/
|
|
209
|
+
async function executePostOperation(context, client, operation, itemIndex) {
|
|
210
|
+
switch (operation) {
|
|
211
|
+
case 'createSingle': {
|
|
212
|
+
const mediaType = context.getNodeParameter('postMediaType', itemIndex);
|
|
213
|
+
const mediaUrl = context.getNodeParameter('postMediaUrl', itemIndex);
|
|
214
|
+
const caption = context.getNodeParameter('caption', itemIndex, '');
|
|
215
|
+
const options = context.getNodeParameter('postOptions', itemIndex, {});
|
|
216
|
+
const userTagsData = context.getNodeParameter('userTags.tagValues', itemIndex, []);
|
|
217
|
+
const userTags = userTagsData.map((t) => ({
|
|
218
|
+
username: t.username,
|
|
219
|
+
x: t.x,
|
|
220
|
+
y: t.y,
|
|
221
|
+
}));
|
|
222
|
+
return client.createMediaContainer(mediaType, mediaUrl, {
|
|
223
|
+
caption: caption || undefined,
|
|
224
|
+
location_id: options.location_id,
|
|
225
|
+
thumb_offset: options.thumb_offset,
|
|
226
|
+
user_tags: userTags.length > 0 ? userTags : undefined,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
case 'createCarousel': {
|
|
230
|
+
const inputMode = context.getNodeParameter('carouselInputMode', itemIndex, 'commaSeparated');
|
|
231
|
+
let childrenIds;
|
|
232
|
+
if (inputMode === 'json') {
|
|
233
|
+
// JSON/Expression mode - parse JSON array
|
|
234
|
+
const jsonInput = context.getNodeParameter('childrenIdsJson', itemIndex);
|
|
235
|
+
if (Array.isArray(jsonInput)) {
|
|
236
|
+
// Already parsed by n8n (from expression)
|
|
237
|
+
childrenIds = jsonInput.map(id => String(id).trim()).filter(Boolean);
|
|
238
|
+
}
|
|
239
|
+
else if (typeof jsonInput === 'string') {
|
|
240
|
+
// Parse JSON string
|
|
241
|
+
try {
|
|
242
|
+
const parsed = JSON.parse(jsonInput);
|
|
243
|
+
if (!Array.isArray(parsed)) {
|
|
244
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Children IDs must be a JSON array');
|
|
245
|
+
}
|
|
246
|
+
childrenIds = parsed.map((id) => String(id).trim()).filter(Boolean);
|
|
247
|
+
}
|
|
248
|
+
catch (parseError) {
|
|
249
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Invalid JSON for carousel children IDs: ${parseError.message}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), 'Invalid input for carousel children IDs');
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// Comma-separated mode
|
|
258
|
+
const childrenIdsStr = context.getNodeParameter('childrenIds', itemIndex);
|
|
259
|
+
childrenIds = childrenIdsStr.split(',').map((id) => id.trim()).filter(Boolean);
|
|
260
|
+
}
|
|
261
|
+
if (childrenIds.length < 2 || childrenIds.length > 10) {
|
|
262
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Carousel must have 2-10 items, got ${childrenIds.length}`);
|
|
263
|
+
}
|
|
264
|
+
const caption = context.getNodeParameter('caption', itemIndex, '');
|
|
265
|
+
return client.createCarouselContainer(childrenIds, caption || undefined);
|
|
266
|
+
}
|
|
267
|
+
case 'publish': {
|
|
268
|
+
const containerId = context.getNodeParameter('containerId', itemIndex);
|
|
269
|
+
return client.publishMedia(containerId);
|
|
270
|
+
}
|
|
271
|
+
default:
|
|
272
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Unknown post operation: ${operation}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Execute story operations
|
|
277
|
+
* Requirements: 10.2
|
|
278
|
+
*/
|
|
279
|
+
async function executeStoryOperation(context, client, itemIndex) {
|
|
280
|
+
const mediaUrl = context.getNodeParameter('storyMediaUrl', itemIndex);
|
|
281
|
+
// Create story container
|
|
282
|
+
const container = await client.createMediaContainer('STORIES', mediaUrl);
|
|
283
|
+
// Auto-publish the story
|
|
284
|
+
return client.publishMedia(container.id);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Execute reel operations
|
|
288
|
+
* Requirements: 10.1, 10.4, 10.5
|
|
289
|
+
*/
|
|
290
|
+
async function executeReelOperation(context, client, itemIndex) {
|
|
291
|
+
const videoUrl = context.getNodeParameter('reelVideoUrl', itemIndex);
|
|
292
|
+
const caption = context.getNodeParameter('reelCaption', itemIndex, '');
|
|
293
|
+
const options = context.getNodeParameter('reelOptions', itemIndex, {});
|
|
294
|
+
// Create reel container
|
|
295
|
+
const container = await client.createMediaContainer('REELS', videoUrl, {
|
|
296
|
+
caption: caption || undefined,
|
|
297
|
+
audio_name: options.audio_name,
|
|
298
|
+
thumb_offset: options.thumb_offset,
|
|
299
|
+
});
|
|
300
|
+
// Auto-publish the reel
|
|
301
|
+
return client.publishMedia(container.id);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Execute media operations
|
|
305
|
+
* Requirements: 11.1-11.3
|
|
306
|
+
*/
|
|
307
|
+
async function executeMediaOperation(context, client, operation, itemIndex) {
|
|
308
|
+
switch (operation) {
|
|
309
|
+
case 'list': {
|
|
310
|
+
const options = context.getNodeParameter('mediaOptions', itemIndex, {});
|
|
311
|
+
return client.listMedia({
|
|
312
|
+
limit: options.limit,
|
|
313
|
+
after: options.after,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
case 'get': {
|
|
317
|
+
const mediaId = context.getNodeParameter('mediaIdForGet', itemIndex);
|
|
318
|
+
return client.getMedia(mediaId);
|
|
319
|
+
}
|
|
320
|
+
case 'getChildren': {
|
|
321
|
+
const mediaId = context.getNodeParameter('mediaIdForGet', itemIndex);
|
|
322
|
+
return client.getMediaChildren(mediaId);
|
|
323
|
+
}
|
|
324
|
+
default:
|
|
325
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Unknown media operation: ${operation}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
class Instagram {
|
|
329
|
+
constructor() {
|
|
330
|
+
this.description = {
|
|
331
|
+
displayName: 'Instagram',
|
|
332
|
+
name: 'instagram',
|
|
333
|
+
icon: 'file:instagram.svg',
|
|
334
|
+
group: ['transform'],
|
|
335
|
+
version: 1,
|
|
336
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
337
|
+
description: 'Instagram Messaging and Content API',
|
|
338
|
+
defaults: {
|
|
339
|
+
name: 'Instagram',
|
|
340
|
+
},
|
|
341
|
+
inputs: ['main'],
|
|
342
|
+
outputs: ['main'],
|
|
343
|
+
credentials: [
|
|
344
|
+
{
|
|
345
|
+
name: 'instagramOAuth2Api',
|
|
346
|
+
required: true,
|
|
347
|
+
displayOptions: {
|
|
348
|
+
show: {
|
|
349
|
+
authentication: ['oAuth2'],
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
name: 'instagramAccessTokenApi',
|
|
355
|
+
required: true,
|
|
356
|
+
displayOptions: {
|
|
357
|
+
show: {
|
|
358
|
+
authentication: ['accessToken'],
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
properties: [
|
|
364
|
+
// Authentication selector
|
|
365
|
+
{
|
|
366
|
+
displayName: 'Authentication',
|
|
367
|
+
name: 'authentication',
|
|
368
|
+
type: 'options',
|
|
369
|
+
options: [
|
|
370
|
+
{ name: 'OAuth2', value: 'oAuth2' },
|
|
371
|
+
{ name: 'Access Token', value: 'accessToken' },
|
|
372
|
+
],
|
|
373
|
+
default: 'oAuth2',
|
|
374
|
+
},
|
|
375
|
+
// Resource selector
|
|
376
|
+
{
|
|
377
|
+
displayName: 'Resource',
|
|
378
|
+
name: 'resource',
|
|
379
|
+
type: 'options',
|
|
380
|
+
noDataExpression: true,
|
|
381
|
+
options: resourceOptions,
|
|
382
|
+
default: 'message',
|
|
383
|
+
},
|
|
384
|
+
// Operation selectors per resource
|
|
385
|
+
{
|
|
386
|
+
displayName: 'Operation',
|
|
387
|
+
name: 'operation',
|
|
388
|
+
type: 'options',
|
|
389
|
+
noDataExpression: true,
|
|
390
|
+
displayOptions: { show: { resource: ['message'] } },
|
|
391
|
+
options: messageOperations,
|
|
392
|
+
default: 'sendText',
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
displayName: 'Operation',
|
|
396
|
+
name: 'operation',
|
|
397
|
+
type: 'options',
|
|
398
|
+
noDataExpression: true,
|
|
399
|
+
displayOptions: { show: { resource: ['user'] } },
|
|
400
|
+
options: userOperations,
|
|
401
|
+
default: 'getProfile',
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
displayName: 'Operation',
|
|
405
|
+
name: 'operation',
|
|
406
|
+
type: 'options',
|
|
407
|
+
noDataExpression: true,
|
|
408
|
+
displayOptions: { show: { resource: ['comment'] } },
|
|
409
|
+
options: commentOperations,
|
|
410
|
+
default: 'getComments',
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
displayName: 'Operation',
|
|
414
|
+
name: 'operation',
|
|
415
|
+
type: 'options',
|
|
416
|
+
noDataExpression: true,
|
|
417
|
+
displayOptions: { show: { resource: ['post'] } },
|
|
418
|
+
options: postOperations,
|
|
419
|
+
default: 'createSingle',
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
displayName: 'Operation',
|
|
423
|
+
name: 'operation',
|
|
424
|
+
type: 'options',
|
|
425
|
+
noDataExpression: true,
|
|
426
|
+
displayOptions: { show: { resource: ['story'] } },
|
|
427
|
+
options: storyOperations,
|
|
428
|
+
default: 'create',
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
displayName: 'Operation',
|
|
432
|
+
name: 'operation',
|
|
433
|
+
type: 'options',
|
|
434
|
+
noDataExpression: true,
|
|
435
|
+
displayOptions: { show: { resource: ['reel'] } },
|
|
436
|
+
options: reelOperations,
|
|
437
|
+
default: 'create',
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
displayName: 'Operation',
|
|
441
|
+
name: 'operation',
|
|
442
|
+
type: 'options',
|
|
443
|
+
noDataExpression: true,
|
|
444
|
+
displayOptions: { show: { resource: ['media'] } },
|
|
445
|
+
options: mediaOperations,
|
|
446
|
+
default: 'list',
|
|
447
|
+
},
|
|
448
|
+
// ============================================
|
|
449
|
+
// MESSAGE RESOURCE FIELDS
|
|
450
|
+
// ============================================
|
|
451
|
+
// Recipient ID - common for all message operations
|
|
452
|
+
{
|
|
453
|
+
displayName: 'Recipient ID',
|
|
454
|
+
name: 'recipientId',
|
|
455
|
+
type: 'string',
|
|
456
|
+
required: true,
|
|
457
|
+
default: '',
|
|
458
|
+
description: 'Instagram-scoped User ID (IGSID) of the recipient',
|
|
459
|
+
displayOptions: {
|
|
460
|
+
show: {
|
|
461
|
+
resource: ['message'],
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
// Text message field
|
|
466
|
+
{
|
|
467
|
+
displayName: 'Message Text',
|
|
468
|
+
name: 'messageText',
|
|
469
|
+
type: 'string',
|
|
470
|
+
typeOptions: { rows: 4 },
|
|
471
|
+
required: true,
|
|
472
|
+
default: '',
|
|
473
|
+
description: 'Text message to send (max 1000 characters)',
|
|
474
|
+
displayOptions: {
|
|
475
|
+
show: {
|
|
476
|
+
resource: ['message'],
|
|
477
|
+
operation: ['sendText', 'sendButtonTemplate', 'sendQuickReplies'],
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
// Media URL for image/audio/video
|
|
482
|
+
{
|
|
483
|
+
displayName: 'Media URL',
|
|
484
|
+
name: 'mediaUrl',
|
|
485
|
+
type: 'string',
|
|
486
|
+
required: true,
|
|
487
|
+
default: '',
|
|
488
|
+
description: 'Public HTTPS URL of the media file',
|
|
489
|
+
displayOptions: {
|
|
490
|
+
show: {
|
|
491
|
+
resource: ['message'],
|
|
492
|
+
operation: ['sendImage', 'sendAudio', 'sendVideo'],
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
// Buttons for button template
|
|
497
|
+
{
|
|
498
|
+
displayName: 'Buttons',
|
|
499
|
+
name: 'buttons',
|
|
500
|
+
type: 'fixedCollection',
|
|
501
|
+
typeOptions: { multipleValues: true },
|
|
502
|
+
default: {},
|
|
503
|
+
description: 'Buttons to include (max 3)',
|
|
504
|
+
displayOptions: {
|
|
505
|
+
show: {
|
|
506
|
+
resource: ['message'],
|
|
507
|
+
operation: ['sendButtonTemplate'],
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
options: [
|
|
511
|
+
{
|
|
512
|
+
name: 'buttonValues',
|
|
513
|
+
displayName: 'Button',
|
|
514
|
+
values: [
|
|
515
|
+
{
|
|
516
|
+
displayName: 'Type',
|
|
517
|
+
name: 'type',
|
|
518
|
+
type: 'options',
|
|
519
|
+
options: [
|
|
520
|
+
{ name: 'Web URL', value: 'web_url' },
|
|
521
|
+
{ name: 'Postback', value: 'postback' },
|
|
522
|
+
],
|
|
523
|
+
default: 'web_url',
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
displayName: 'Title',
|
|
527
|
+
name: 'title',
|
|
528
|
+
type: 'string',
|
|
529
|
+
default: '',
|
|
530
|
+
description: 'Button title (max 20 characters)',
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
displayName: 'URL',
|
|
534
|
+
name: 'url',
|
|
535
|
+
type: 'string',
|
|
536
|
+
default: '',
|
|
537
|
+
description: 'URL to open (for web_url type)',
|
|
538
|
+
displayOptions: { show: { type: ['web_url'] } },
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
displayName: 'Payload',
|
|
542
|
+
name: 'payload',
|
|
543
|
+
type: 'string',
|
|
544
|
+
default: '',
|
|
545
|
+
description: 'Postback payload (for postback type)',
|
|
546
|
+
displayOptions: { show: { type: ['postback'] } },
|
|
547
|
+
},
|
|
548
|
+
],
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
},
|
|
552
|
+
// Carousel elements for generic template
|
|
553
|
+
{
|
|
554
|
+
displayName: 'Carousel Elements',
|
|
555
|
+
name: 'carouselElements',
|
|
556
|
+
type: 'fixedCollection',
|
|
557
|
+
typeOptions: { multipleValues: true },
|
|
558
|
+
default: {},
|
|
559
|
+
description: 'Carousel cards to include',
|
|
560
|
+
displayOptions: {
|
|
561
|
+
show: {
|
|
562
|
+
resource: ['message'],
|
|
563
|
+
operation: ['sendGenericTemplate'],
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
options: [
|
|
567
|
+
{
|
|
568
|
+
name: 'elementValues',
|
|
569
|
+
displayName: 'Element',
|
|
570
|
+
values: [
|
|
571
|
+
{
|
|
572
|
+
displayName: 'Title',
|
|
573
|
+
name: 'title',
|
|
574
|
+
type: 'string',
|
|
575
|
+
default: '',
|
|
576
|
+
required: true,
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
displayName: 'Subtitle',
|
|
580
|
+
name: 'subtitle',
|
|
581
|
+
type: 'string',
|
|
582
|
+
default: '',
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
displayName: 'Image URL',
|
|
586
|
+
name: 'image_url',
|
|
587
|
+
type: 'string',
|
|
588
|
+
default: '',
|
|
589
|
+
description: 'HTTPS URL of the image',
|
|
590
|
+
},
|
|
591
|
+
],
|
|
592
|
+
},
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
// Quick replies
|
|
596
|
+
{
|
|
597
|
+
displayName: 'Quick Replies',
|
|
598
|
+
name: 'quickReplies',
|
|
599
|
+
type: 'fixedCollection',
|
|
600
|
+
typeOptions: { multipleValues: true },
|
|
601
|
+
default: {},
|
|
602
|
+
description: 'Quick reply options (max 13)',
|
|
603
|
+
displayOptions: {
|
|
604
|
+
show: {
|
|
605
|
+
resource: ['message'],
|
|
606
|
+
operation: ['sendQuickReplies'],
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
options: [
|
|
610
|
+
{
|
|
611
|
+
name: 'replyValues',
|
|
612
|
+
displayName: 'Quick Reply',
|
|
613
|
+
values: [
|
|
614
|
+
{
|
|
615
|
+
displayName: 'Title',
|
|
616
|
+
name: 'title',
|
|
617
|
+
type: 'string',
|
|
618
|
+
default: '',
|
|
619
|
+
required: true,
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
displayName: 'Payload',
|
|
623
|
+
name: 'payload',
|
|
624
|
+
type: 'string',
|
|
625
|
+
default: '',
|
|
626
|
+
required: true,
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
displayName: 'Image URL',
|
|
630
|
+
name: 'image_url',
|
|
631
|
+
type: 'string',
|
|
632
|
+
default: '',
|
|
633
|
+
description: 'Optional icon image URL',
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
},
|
|
639
|
+
// ============================================
|
|
640
|
+
// USER RESOURCE FIELDS
|
|
641
|
+
// ============================================
|
|
642
|
+
// User ID for getProfile
|
|
643
|
+
{
|
|
644
|
+
displayName: 'User ID',
|
|
645
|
+
name: 'userId',
|
|
646
|
+
type: 'string',
|
|
647
|
+
required: true,
|
|
648
|
+
default: '',
|
|
649
|
+
description: 'Instagram-scoped User ID (IGSID)',
|
|
650
|
+
displayOptions: {
|
|
651
|
+
show: {
|
|
652
|
+
resource: ['user'],
|
|
653
|
+
operation: ['getProfile'],
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
// ============================================
|
|
658
|
+
// COMMENT RESOURCE FIELDS
|
|
659
|
+
// ============================================
|
|
660
|
+
// Media ID for getComments
|
|
661
|
+
{
|
|
662
|
+
displayName: 'Media ID',
|
|
663
|
+
name: 'mediaId',
|
|
664
|
+
type: 'string',
|
|
665
|
+
required: true,
|
|
666
|
+
default: '',
|
|
667
|
+
description: 'ID of the media to get comments from',
|
|
668
|
+
displayOptions: {
|
|
669
|
+
show: {
|
|
670
|
+
resource: ['comment'],
|
|
671
|
+
operation: ['getComments'],
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
},
|
|
675
|
+
// Comment ID for various operations
|
|
676
|
+
{
|
|
677
|
+
displayName: 'Comment ID',
|
|
678
|
+
name: 'commentId',
|
|
679
|
+
type: 'string',
|
|
680
|
+
required: true,
|
|
681
|
+
default: '',
|
|
682
|
+
description: 'ID of the comment',
|
|
683
|
+
displayOptions: {
|
|
684
|
+
show: {
|
|
685
|
+
resource: ['comment'],
|
|
686
|
+
operation: ['getReplies', 'reply', 'sendPrivateReply', 'delete', 'toggleVisibility'],
|
|
687
|
+
},
|
|
688
|
+
},
|
|
689
|
+
},
|
|
690
|
+
// Reply message
|
|
691
|
+
{
|
|
692
|
+
displayName: 'Reply Message',
|
|
693
|
+
name: 'replyMessage',
|
|
694
|
+
type: 'string',
|
|
695
|
+
typeOptions: { rows: 3 },
|
|
696
|
+
required: true,
|
|
697
|
+
default: '',
|
|
698
|
+
description: 'Message to reply with',
|
|
699
|
+
displayOptions: {
|
|
700
|
+
show: {
|
|
701
|
+
resource: ['comment'],
|
|
702
|
+
operation: ['reply', 'sendPrivateReply'],
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
},
|
|
706
|
+
// Hide/unhide toggle
|
|
707
|
+
{
|
|
708
|
+
displayName: 'Hide Comment',
|
|
709
|
+
name: 'hideComment',
|
|
710
|
+
type: 'boolean',
|
|
711
|
+
default: true,
|
|
712
|
+
description: 'Whether to hide (true) or unhide (false) the comment',
|
|
713
|
+
displayOptions: {
|
|
714
|
+
show: {
|
|
715
|
+
resource: ['comment'],
|
|
716
|
+
operation: ['toggleVisibility'],
|
|
717
|
+
},
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
// Pagination options for comments
|
|
721
|
+
{
|
|
722
|
+
displayName: 'Options',
|
|
723
|
+
name: 'commentOptions',
|
|
724
|
+
type: 'collection',
|
|
725
|
+
placeholder: 'Add Option',
|
|
726
|
+
default: {},
|
|
727
|
+
displayOptions: {
|
|
728
|
+
show: {
|
|
729
|
+
resource: ['comment'],
|
|
730
|
+
operation: ['getComments'],
|
|
731
|
+
},
|
|
732
|
+
},
|
|
733
|
+
options: [
|
|
734
|
+
{
|
|
735
|
+
displayName: 'Limit',
|
|
736
|
+
name: 'limit',
|
|
737
|
+
type: 'number',
|
|
738
|
+
default: 25,
|
|
739
|
+
description: 'Number of comments to return',
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
displayName: 'After Cursor',
|
|
743
|
+
name: 'after',
|
|
744
|
+
type: 'string',
|
|
745
|
+
default: '',
|
|
746
|
+
description: 'Pagination cursor for next page',
|
|
747
|
+
},
|
|
748
|
+
],
|
|
749
|
+
},
|
|
750
|
+
// ============================================
|
|
751
|
+
// POST RESOURCE FIELDS
|
|
752
|
+
// ============================================
|
|
753
|
+
// Media type for single post
|
|
754
|
+
{
|
|
755
|
+
displayName: 'Media Type',
|
|
756
|
+
name: 'postMediaType',
|
|
757
|
+
type: 'options',
|
|
758
|
+
options: [
|
|
759
|
+
{ name: 'Image', value: 'IMAGE' },
|
|
760
|
+
{ name: 'Video', value: 'VIDEO' },
|
|
761
|
+
],
|
|
762
|
+
default: 'IMAGE',
|
|
763
|
+
displayOptions: {
|
|
764
|
+
show: {
|
|
765
|
+
resource: ['post'],
|
|
766
|
+
operation: ['createSingle'],
|
|
767
|
+
},
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
// Media URL for post
|
|
771
|
+
{
|
|
772
|
+
displayName: 'Media URL',
|
|
773
|
+
name: 'postMediaUrl',
|
|
774
|
+
type: 'string',
|
|
775
|
+
required: true,
|
|
776
|
+
default: '',
|
|
777
|
+
description: 'Public HTTPS URL of the image or video',
|
|
778
|
+
displayOptions: {
|
|
779
|
+
show: {
|
|
780
|
+
resource: ['post'],
|
|
781
|
+
operation: ['createSingle'],
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
},
|
|
785
|
+
// Caption for post
|
|
786
|
+
{
|
|
787
|
+
displayName: 'Caption',
|
|
788
|
+
name: 'caption',
|
|
789
|
+
type: 'string',
|
|
790
|
+
typeOptions: { rows: 4 },
|
|
791
|
+
default: '',
|
|
792
|
+
description: 'Post caption',
|
|
793
|
+
displayOptions: {
|
|
794
|
+
show: {
|
|
795
|
+
resource: ['post'],
|
|
796
|
+
operation: ['createSingle', 'createCarousel'],
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
},
|
|
800
|
+
// Carousel children IDs - Input Mode selector
|
|
801
|
+
{
|
|
802
|
+
displayName: 'Input Mode',
|
|
803
|
+
name: 'carouselInputMode',
|
|
804
|
+
type: 'options',
|
|
805
|
+
options: [
|
|
806
|
+
{ name: 'Comma-Separated IDs', value: 'commaSeparated', description: 'Enter container IDs separated by commas' },
|
|
807
|
+
{ name: 'JSON Array / Expression', value: 'json', description: 'Enter JSON array or use expression from previous node' },
|
|
808
|
+
],
|
|
809
|
+
default: 'commaSeparated',
|
|
810
|
+
description: 'How to provide carousel item container IDs',
|
|
811
|
+
displayOptions: {
|
|
812
|
+
show: {
|
|
813
|
+
resource: ['post'],
|
|
814
|
+
operation: ['createCarousel'],
|
|
815
|
+
},
|
|
816
|
+
},
|
|
817
|
+
},
|
|
818
|
+
// Carousel children IDs - Comma-separated mode
|
|
819
|
+
{
|
|
820
|
+
displayName: 'Children Container IDs',
|
|
821
|
+
name: 'childrenIds',
|
|
822
|
+
type: 'string',
|
|
823
|
+
required: true,
|
|
824
|
+
default: '',
|
|
825
|
+
description: 'Comma-separated list of media container IDs (2-10 items)',
|
|
826
|
+
displayOptions: {
|
|
827
|
+
show: {
|
|
828
|
+
resource: ['post'],
|
|
829
|
+
operation: ['createCarousel'],
|
|
830
|
+
carouselInputMode: ['commaSeparated'],
|
|
831
|
+
},
|
|
832
|
+
},
|
|
833
|
+
},
|
|
834
|
+
// Carousel children IDs - JSON/Expression mode
|
|
835
|
+
{
|
|
836
|
+
displayName: 'Children Container IDs (JSON)',
|
|
837
|
+
name: 'childrenIdsJson',
|
|
838
|
+
type: 'json',
|
|
839
|
+
required: true,
|
|
840
|
+
default: '[]',
|
|
841
|
+
description: 'JSON array of container IDs. Supports expressions like {{ $json.containerIds }}. Example: ["123456", "789012"]',
|
|
842
|
+
displayOptions: {
|
|
843
|
+
show: {
|
|
844
|
+
resource: ['post'],
|
|
845
|
+
operation: ['createCarousel'],
|
|
846
|
+
carouselInputMode: ['json'],
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
},
|
|
850
|
+
// Container ID for publish
|
|
851
|
+
{
|
|
852
|
+
displayName: 'Container ID',
|
|
853
|
+
name: 'containerId',
|
|
854
|
+
type: 'string',
|
|
855
|
+
required: true,
|
|
856
|
+
default: '',
|
|
857
|
+
description: 'ID of the media container to publish',
|
|
858
|
+
displayOptions: {
|
|
859
|
+
show: {
|
|
860
|
+
resource: ['post'],
|
|
861
|
+
operation: ['publish'],
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
},
|
|
865
|
+
// Post options
|
|
866
|
+
{
|
|
867
|
+
displayName: 'Options',
|
|
868
|
+
name: 'postOptions',
|
|
869
|
+
type: 'collection',
|
|
870
|
+
placeholder: 'Add Option',
|
|
871
|
+
default: {},
|
|
872
|
+
displayOptions: {
|
|
873
|
+
show: {
|
|
874
|
+
resource: ['post'],
|
|
875
|
+
operation: ['createSingle'],
|
|
876
|
+
},
|
|
877
|
+
},
|
|
878
|
+
options: [
|
|
879
|
+
{
|
|
880
|
+
displayName: 'Location ID',
|
|
881
|
+
name: 'location_id',
|
|
882
|
+
type: 'string',
|
|
883
|
+
default: '',
|
|
884
|
+
description: 'Facebook Page ID of a location',
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
displayName: 'Thumbnail Offset (ms)',
|
|
888
|
+
name: 'thumb_offset',
|
|
889
|
+
type: 'number',
|
|
890
|
+
default: 0,
|
|
891
|
+
description: 'Video thumbnail position in milliseconds',
|
|
892
|
+
},
|
|
893
|
+
],
|
|
894
|
+
},
|
|
895
|
+
// User tags for post
|
|
896
|
+
{
|
|
897
|
+
displayName: 'User Tags',
|
|
898
|
+
name: 'userTags',
|
|
899
|
+
type: 'fixedCollection',
|
|
900
|
+
typeOptions: { multipleValues: true },
|
|
901
|
+
default: {},
|
|
902
|
+
description: 'Tag users in the post (max 20)',
|
|
903
|
+
displayOptions: {
|
|
904
|
+
show: {
|
|
905
|
+
resource: ['post'],
|
|
906
|
+
operation: ['createSingle'],
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
options: [
|
|
910
|
+
{
|
|
911
|
+
name: 'tagValues',
|
|
912
|
+
displayName: 'User Tag',
|
|
913
|
+
values: [
|
|
914
|
+
{
|
|
915
|
+
displayName: 'Username',
|
|
916
|
+
name: 'username',
|
|
917
|
+
type: 'string',
|
|
918
|
+
default: '',
|
|
919
|
+
required: true,
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
displayName: 'X Position',
|
|
923
|
+
name: 'x',
|
|
924
|
+
type: 'number',
|
|
925
|
+
default: 0.5,
|
|
926
|
+
description: 'Horizontal position (0-1)',
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
displayName: 'Y Position',
|
|
930
|
+
name: 'y',
|
|
931
|
+
type: 'number',
|
|
932
|
+
default: 0.5,
|
|
933
|
+
description: 'Vertical position (0-1)',
|
|
934
|
+
},
|
|
935
|
+
],
|
|
936
|
+
},
|
|
937
|
+
],
|
|
938
|
+
},
|
|
939
|
+
// ============================================
|
|
940
|
+
// STORY RESOURCE FIELDS
|
|
941
|
+
// ============================================
|
|
942
|
+
// Media URL for story
|
|
943
|
+
{
|
|
944
|
+
displayName: 'Media URL',
|
|
945
|
+
name: 'storyMediaUrl',
|
|
946
|
+
type: 'string',
|
|
947
|
+
required: true,
|
|
948
|
+
default: '',
|
|
949
|
+
description: 'Public HTTPS URL of the image or video for the story',
|
|
950
|
+
displayOptions: {
|
|
951
|
+
show: {
|
|
952
|
+
resource: ['story'],
|
|
953
|
+
operation: ['create'],
|
|
954
|
+
},
|
|
955
|
+
},
|
|
956
|
+
},
|
|
957
|
+
// ============================================
|
|
958
|
+
// REEL RESOURCE FIELDS
|
|
959
|
+
// ============================================
|
|
960
|
+
// Video URL for reel
|
|
961
|
+
{
|
|
962
|
+
displayName: 'Video URL',
|
|
963
|
+
name: 'reelVideoUrl',
|
|
964
|
+
type: 'string',
|
|
965
|
+
required: true,
|
|
966
|
+
default: '',
|
|
967
|
+
description: 'Public HTTPS URL of the video (max 60 seconds)',
|
|
968
|
+
displayOptions: {
|
|
969
|
+
show: {
|
|
970
|
+
resource: ['reel'],
|
|
971
|
+
operation: ['create'],
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
},
|
|
975
|
+
// Reel caption
|
|
976
|
+
{
|
|
977
|
+
displayName: 'Caption',
|
|
978
|
+
name: 'reelCaption',
|
|
979
|
+
type: 'string',
|
|
980
|
+
typeOptions: { rows: 4 },
|
|
981
|
+
default: '',
|
|
982
|
+
description: 'Reel caption',
|
|
983
|
+
displayOptions: {
|
|
984
|
+
show: {
|
|
985
|
+
resource: ['reel'],
|
|
986
|
+
operation: ['create'],
|
|
987
|
+
},
|
|
988
|
+
},
|
|
989
|
+
},
|
|
990
|
+
// Reel options
|
|
991
|
+
{
|
|
992
|
+
displayName: 'Options',
|
|
993
|
+
name: 'reelOptions',
|
|
994
|
+
type: 'collection',
|
|
995
|
+
placeholder: 'Add Option',
|
|
996
|
+
default: {},
|
|
997
|
+
displayOptions: {
|
|
998
|
+
show: {
|
|
999
|
+
resource: ['reel'],
|
|
1000
|
+
operation: ['create'],
|
|
1001
|
+
},
|
|
1002
|
+
},
|
|
1003
|
+
options: [
|
|
1004
|
+
{
|
|
1005
|
+
displayName: 'Audio Name',
|
|
1006
|
+
name: 'audio_name',
|
|
1007
|
+
type: 'string',
|
|
1008
|
+
default: '',
|
|
1009
|
+
description: 'Name for audio attribution',
|
|
1010
|
+
},
|
|
1011
|
+
{
|
|
1012
|
+
displayName: 'Thumbnail Offset (ms)',
|
|
1013
|
+
name: 'thumb_offset',
|
|
1014
|
+
type: 'number',
|
|
1015
|
+
default: 0,
|
|
1016
|
+
description: 'Video thumbnail position in milliseconds',
|
|
1017
|
+
},
|
|
1018
|
+
],
|
|
1019
|
+
},
|
|
1020
|
+
// ============================================
|
|
1021
|
+
// MEDIA RESOURCE FIELDS
|
|
1022
|
+
// ============================================
|
|
1023
|
+
// Media ID for get/getChildren
|
|
1024
|
+
{
|
|
1025
|
+
displayName: 'Media ID',
|
|
1026
|
+
name: 'mediaIdForGet',
|
|
1027
|
+
type: 'string',
|
|
1028
|
+
required: true,
|
|
1029
|
+
default: '',
|
|
1030
|
+
description: 'ID of the media',
|
|
1031
|
+
displayOptions: {
|
|
1032
|
+
show: {
|
|
1033
|
+
resource: ['media'],
|
|
1034
|
+
operation: ['get', 'getChildren'],
|
|
1035
|
+
},
|
|
1036
|
+
},
|
|
1037
|
+
},
|
|
1038
|
+
// Pagination options for media list
|
|
1039
|
+
{
|
|
1040
|
+
displayName: 'Options',
|
|
1041
|
+
name: 'mediaOptions',
|
|
1042
|
+
type: 'collection',
|
|
1043
|
+
placeholder: 'Add Option',
|
|
1044
|
+
default: {},
|
|
1045
|
+
displayOptions: {
|
|
1046
|
+
show: {
|
|
1047
|
+
resource: ['media'],
|
|
1048
|
+
operation: ['list'],
|
|
1049
|
+
},
|
|
1050
|
+
},
|
|
1051
|
+
options: [
|
|
1052
|
+
{
|
|
1053
|
+
displayName: 'Limit',
|
|
1054
|
+
name: 'limit',
|
|
1055
|
+
type: 'number',
|
|
1056
|
+
default: 25,
|
|
1057
|
+
description: 'Number of media items to return',
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
displayName: 'After Cursor',
|
|
1061
|
+
name: 'after',
|
|
1062
|
+
type: 'string',
|
|
1063
|
+
default: '',
|
|
1064
|
+
description: 'Pagination cursor for next page',
|
|
1065
|
+
},
|
|
1066
|
+
],
|
|
1067
|
+
},
|
|
1068
|
+
],
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Execute method - wires up all operations to InstagramApiClient
|
|
1073
|
+
* Requirements: All node operations, 14.4 (continueOnFail support)
|
|
1074
|
+
*/
|
|
1075
|
+
async execute() {
|
|
1076
|
+
const items = this.getInputData();
|
|
1077
|
+
const returnData = [];
|
|
1078
|
+
// Get credentials
|
|
1079
|
+
const authentication = this.getNodeParameter('authentication', 0);
|
|
1080
|
+
let accessToken;
|
|
1081
|
+
let accountId;
|
|
1082
|
+
if (authentication === 'oAuth2') {
|
|
1083
|
+
const credentials = await this.getCredentials('instagramOAuth2Api');
|
|
1084
|
+
accessToken = credentials.longLivedToken || credentials.accessToken;
|
|
1085
|
+
accountId = credentials.instagramAccountId;
|
|
1086
|
+
}
|
|
1087
|
+
else {
|
|
1088
|
+
const credentials = await this.getCredentials('instagramAccessTokenApi');
|
|
1089
|
+
accessToken = credentials.accessToken;
|
|
1090
|
+
accountId = credentials.instagramAccountId;
|
|
1091
|
+
}
|
|
1092
|
+
if (!accessToken) {
|
|
1093
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No access token available. Please reconnect your credentials.');
|
|
1094
|
+
}
|
|
1095
|
+
if (!accountId) {
|
|
1096
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Instagram Account ID not found. Please reconnect your credentials.');
|
|
1097
|
+
}
|
|
1098
|
+
const client = new InstagramApiClient_1.InstagramApiClient(accessToken, accountId);
|
|
1099
|
+
for (let i = 0; i < items.length; i++) {
|
|
1100
|
+
try {
|
|
1101
|
+
const resource = this.getNodeParameter('resource', i);
|
|
1102
|
+
const operation = this.getNodeParameter('operation', i);
|
|
1103
|
+
let responseData;
|
|
1104
|
+
// Route to appropriate handler
|
|
1105
|
+
switch (resource) {
|
|
1106
|
+
case 'message':
|
|
1107
|
+
responseData = await executeMessageOperation(this, client, operation, i);
|
|
1108
|
+
break;
|
|
1109
|
+
case 'user':
|
|
1110
|
+
responseData = await executeUserOperation(this, client, operation, i);
|
|
1111
|
+
break;
|
|
1112
|
+
case 'comment':
|
|
1113
|
+
responseData = await executeCommentOperation(this, client, operation, i);
|
|
1114
|
+
break;
|
|
1115
|
+
case 'post':
|
|
1116
|
+
responseData = await executePostOperation(this, client, operation, i);
|
|
1117
|
+
break;
|
|
1118
|
+
case 'story':
|
|
1119
|
+
responseData = await executeStoryOperation(this, client, i);
|
|
1120
|
+
break;
|
|
1121
|
+
case 'reel':
|
|
1122
|
+
responseData = await executeReelOperation(this, client, i);
|
|
1123
|
+
break;
|
|
1124
|
+
case 'media':
|
|
1125
|
+
responseData = await executeMediaOperation(this, client, operation, i);
|
|
1126
|
+
break;
|
|
1127
|
+
default:
|
|
1128
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown resource: ${resource}`);
|
|
1129
|
+
}
|
|
1130
|
+
returnData.push({
|
|
1131
|
+
json: responseData,
|
|
1132
|
+
pairedItem: { item: i },
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
catch (error) {
|
|
1136
|
+
// Requirement 14.4: continueOnFail support
|
|
1137
|
+
if (this.continueOnFail()) {
|
|
1138
|
+
const errorData = formatError(error);
|
|
1139
|
+
returnData.push({
|
|
1140
|
+
json: errorData,
|
|
1141
|
+
pairedItem: { item: i },
|
|
1142
|
+
});
|
|
1143
|
+
continue;
|
|
1144
|
+
}
|
|
1145
|
+
throw error;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
return [returnData];
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
exports.Instagram = Instagram;
|
|
1152
|
+
//# sourceMappingURL=Instagram.node.js.map
|