@mookielianhd/n8n-nodes-instagram 2.3.0 → 2.4.1
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 +65 -3
- package/dist/nodes/Instagram/Instagram.node.js +657 -13
- package/dist/nodes/Instagram/Instagram.node.js.map +1 -1
- package/dist/nodes/Instagram/resources/index.js +22 -1
- package/dist/nodes/Instagram/resources/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -38,9 +38,50 @@ class Instagram {
|
|
|
38
38
|
name: 'resource',
|
|
39
39
|
type: 'options',
|
|
40
40
|
noDataExpression: true,
|
|
41
|
-
options: [
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
options: [
|
|
42
|
+
{
|
|
43
|
+
name: 'Auth',
|
|
44
|
+
value: 'auth',
|
|
45
|
+
description: 'Exchange and refresh Instagram access tokens; call /me',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'Comment',
|
|
49
|
+
value: 'comments',
|
|
50
|
+
description: 'Moderate comments on Instagram media',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'IG Hashtag',
|
|
54
|
+
value: 'igHashtag',
|
|
55
|
+
description: 'Search hashtags and fetch top or recent media for a hashtag',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'IG User',
|
|
59
|
+
value: 'igUser',
|
|
60
|
+
description: 'Read profile and media for an Instagram Business or Creator account',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'Image',
|
|
64
|
+
value: 'image',
|
|
65
|
+
description: 'Publish image posts to Instagram',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'Messaging',
|
|
69
|
+
value: 'messaging',
|
|
70
|
+
description: 'Send direct messages via the Instagram Messaging API',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'Reel',
|
|
74
|
+
value: 'reels',
|
|
75
|
+
description: 'Publish Reels videos to Instagram',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'Story',
|
|
79
|
+
value: 'stories',
|
|
80
|
+
description: 'Publish story videos to Instagram',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
default: 'image',
|
|
84
|
+
description: 'Select what you want to do with the Instagram API',
|
|
44
85
|
required: true,
|
|
45
86
|
},
|
|
46
87
|
{
|
|
@@ -121,18 +162,182 @@ class Instagram {
|
|
|
121
162
|
default: 'list',
|
|
122
163
|
required: true,
|
|
123
164
|
},
|
|
165
|
+
{
|
|
166
|
+
displayName: 'Operation',
|
|
167
|
+
name: 'operation',
|
|
168
|
+
type: 'options',
|
|
169
|
+
noDataExpression: true,
|
|
170
|
+
displayOptions: {
|
|
171
|
+
show: {
|
|
172
|
+
resource: ['igUser'],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
options: [
|
|
176
|
+
{
|
|
177
|
+
name: 'Get',
|
|
178
|
+
value: 'get',
|
|
179
|
+
action: 'Get IG user',
|
|
180
|
+
description: 'Get basic profile information for an Instagram Business or Creator account',
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: 'Get Media',
|
|
184
|
+
value: 'getMedia',
|
|
185
|
+
action: 'Get media',
|
|
186
|
+
description: 'List media objects owned by an Instagram Business or Creator account',
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
default: 'get',
|
|
190
|
+
required: true,
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
displayName: 'Operation',
|
|
194
|
+
name: 'operation',
|
|
195
|
+
type: 'options',
|
|
196
|
+
noDataExpression: true,
|
|
197
|
+
displayOptions: {
|
|
198
|
+
show: {
|
|
199
|
+
resource: ['auth'],
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
options: [
|
|
203
|
+
{
|
|
204
|
+
name: 'Exchange Access Token',
|
|
205
|
+
value: 'exchangeAccessToken',
|
|
206
|
+
action: 'Exchange short lived token',
|
|
207
|
+
description: 'Exchange a short-lived Instagram User access token for a long-lived token using the Instagram Platform access token endpoint',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'Get Me',
|
|
211
|
+
value: 'getMe',
|
|
212
|
+
action: 'Get me profile',
|
|
213
|
+
description: 'Call the Graph API /me endpoint using the access token from the Instagram API credential',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: 'Refresh Access Token',
|
|
217
|
+
value: 'refreshAccessToken',
|
|
218
|
+
action: 'Refresh access token',
|
|
219
|
+
description: 'Refresh a long-lived Instagram User access token using the Instagram Platform refresh endpoint',
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
default: 'refreshAccessToken',
|
|
223
|
+
required: true,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
displayName: 'Operation',
|
|
227
|
+
name: 'operation',
|
|
228
|
+
type: 'options',
|
|
229
|
+
noDataExpression: true,
|
|
230
|
+
displayOptions: {
|
|
231
|
+
show: {
|
|
232
|
+
resource: ['igHashtag'],
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
options: [
|
|
236
|
+
{
|
|
237
|
+
name: 'Search',
|
|
238
|
+
value: 'search',
|
|
239
|
+
action: 'Search hashtags',
|
|
240
|
+
description: 'Search for a hashtag by name and return its ID',
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: 'Get Recent Media',
|
|
244
|
+
value: 'getRecentMedia',
|
|
245
|
+
action: 'Get recent media for hashtag',
|
|
246
|
+
description: 'Get the most recent media tagged with a hashtag',
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: 'Get Top Media',
|
|
250
|
+
value: 'getTopMedia',
|
|
251
|
+
action: 'Get top media for hashtag',
|
|
252
|
+
description: 'Get the most popular media tagged with a hashtag',
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
default: 'search',
|
|
256
|
+
required: true,
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
displayName: 'Operation',
|
|
260
|
+
name: 'operation',
|
|
261
|
+
type: 'options',
|
|
262
|
+
noDataExpression: true,
|
|
263
|
+
displayOptions: {
|
|
264
|
+
show: {
|
|
265
|
+
resource: ['messaging'],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
options: [
|
|
269
|
+
{
|
|
270
|
+
name: 'Send Message',
|
|
271
|
+
value: 'sendMessage',
|
|
272
|
+
action: 'Send direct message',
|
|
273
|
+
description: 'Send a text message to an Instagram user via the Messaging API',
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
default: 'sendMessage',
|
|
277
|
+
required: true,
|
|
278
|
+
},
|
|
124
279
|
{
|
|
125
280
|
displayName: 'Node',
|
|
126
281
|
name: 'node',
|
|
127
282
|
type: 'string',
|
|
128
283
|
default: '',
|
|
129
|
-
description: 'The Instagram Business Account ID or User ID on which to publish the media, or the professional account that owns the commented media',
|
|
284
|
+
description: 'The Instagram Business Account ID or User ID on which to publish the media, or the professional account that owns the commented media, or the IG User to read data for, or the IG User performing a hashtag or messaging query',
|
|
130
285
|
placeholder: 'me',
|
|
131
286
|
required: true,
|
|
132
287
|
displayOptions: {
|
|
133
288
|
show: {
|
|
134
|
-
resource: ['image', 'reels', 'stories', 'comments'],
|
|
135
|
-
operation: ['publish', 'sendPrivateReply'],
|
|
289
|
+
resource: ['image', 'reels', 'stories', 'comments', 'igUser', 'igHashtag', 'messaging'],
|
|
290
|
+
operation: ['publish', 'sendPrivateReply', 'get', 'getMedia', 'search', 'getRecentMedia', 'getTopMedia', 'sendMessage'],
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
displayName: 'Access Token',
|
|
296
|
+
name: 'accessToken',
|
|
297
|
+
type: 'string',
|
|
298
|
+
typeOptions: {
|
|
299
|
+
password: true,
|
|
300
|
+
},
|
|
301
|
+
default: '',
|
|
302
|
+
description: 'The long-lived Instagram User access token to refresh. Leave empty to use the access token from the Instagram API credential.',
|
|
303
|
+
displayOptions: {
|
|
304
|
+
show: {
|
|
305
|
+
resource: ['auth'],
|
|
306
|
+
operation: ['refreshAccessToken'],
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
displayName: 'Short-Lived Access Token',
|
|
312
|
+
name: 'shortLivedAccessToken',
|
|
313
|
+
type: 'string',
|
|
314
|
+
typeOptions: {
|
|
315
|
+
password: true,
|
|
316
|
+
},
|
|
317
|
+
default: '',
|
|
318
|
+
description: 'The short-lived Instagram User access token to exchange for a long-lived token. This is usually obtained from the login flow.',
|
|
319
|
+
required: true,
|
|
320
|
+
displayOptions: {
|
|
321
|
+
show: {
|
|
322
|
+
resource: ['auth'],
|
|
323
|
+
operation: ['exchangeAccessToken'],
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
displayName: 'App Secret',
|
|
329
|
+
name: 'appSecret',
|
|
330
|
+
type: 'string',
|
|
331
|
+
typeOptions: {
|
|
332
|
+
password: true,
|
|
333
|
+
},
|
|
334
|
+
default: '',
|
|
335
|
+
description: 'Instagram App Secret from the Meta App Dashboard. Required to securely exchange a short-lived access token for a long-lived token.',
|
|
336
|
+
required: true,
|
|
337
|
+
displayOptions: {
|
|
338
|
+
show: {
|
|
339
|
+
resource: ['auth'],
|
|
340
|
+
operation: ['exchangeAccessToken'],
|
|
136
341
|
},
|
|
137
342
|
},
|
|
138
343
|
},
|
|
@@ -145,7 +350,7 @@ class Instagram {
|
|
|
145
350
|
required: true,
|
|
146
351
|
displayOptions: {
|
|
147
352
|
show: {
|
|
148
|
-
resource: ['image', 'reels', 'stories', 'comments'],
|
|
353
|
+
resource: ['image', 'reels', 'stories', 'comments', 'igUser', 'igHashtag', 'auth', 'messaging'],
|
|
149
354
|
operation: [
|
|
150
355
|
'publish',
|
|
151
356
|
'list',
|
|
@@ -154,11 +359,108 @@ class Instagram {
|
|
|
154
359
|
'deleteComment',
|
|
155
360
|
'disableComments',
|
|
156
361
|
'enableComments',
|
|
362
|
+
'get',
|
|
363
|
+
'getMedia',
|
|
364
|
+
'search',
|
|
365
|
+
'getRecentMedia',
|
|
366
|
+
'getTopMedia',
|
|
367
|
+
'getMe',
|
|
368
|
+
'sendMessage',
|
|
157
369
|
'sendPrivateReply',
|
|
158
370
|
],
|
|
159
371
|
},
|
|
160
372
|
},
|
|
161
373
|
},
|
|
374
|
+
{
|
|
375
|
+
displayName: 'Return All',
|
|
376
|
+
name: 'returnAll',
|
|
377
|
+
type: 'boolean',
|
|
378
|
+
default: false,
|
|
379
|
+
description: 'Whether to return all results or only up to a given limit',
|
|
380
|
+
displayOptions: {
|
|
381
|
+
show: {
|
|
382
|
+
resource: ['igUser', 'igHashtag'],
|
|
383
|
+
operation: ['getMedia', 'getRecentMedia', 'getTopMedia'],
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
displayName: 'Limit',
|
|
389
|
+
name: 'limit',
|
|
390
|
+
type: 'number',
|
|
391
|
+
typeOptions: {
|
|
392
|
+
minValue: 1,
|
|
393
|
+
maxValue: 500,
|
|
394
|
+
},
|
|
395
|
+
default: 50,
|
|
396
|
+
description: 'Max number of results to return',
|
|
397
|
+
displayOptions: {
|
|
398
|
+
show: {
|
|
399
|
+
resource: ['igUser', 'igHashtag'],
|
|
400
|
+
operation: ['getMedia', 'getRecentMedia', 'getTopMedia'],
|
|
401
|
+
returnAll: [false],
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
displayName: 'Recipient IG User ID',
|
|
407
|
+
name: 'recipientId',
|
|
408
|
+
type: 'string',
|
|
409
|
+
default: '',
|
|
410
|
+
description: 'The Instagram-scoped user ID (IGSID) of the recipient. This is provided in webhook events or other Messaging API responses.',
|
|
411
|
+
required: true,
|
|
412
|
+
displayOptions: {
|
|
413
|
+
show: {
|
|
414
|
+
resource: ['messaging'],
|
|
415
|
+
operation: ['sendMessage'],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
displayName: 'Message Text',
|
|
421
|
+
name: 'messageText',
|
|
422
|
+
type: 'string',
|
|
423
|
+
typeOptions: {
|
|
424
|
+
rows: 4,
|
|
425
|
+
},
|
|
426
|
+
default: '',
|
|
427
|
+
description: 'The text content of the direct message to send',
|
|
428
|
+
required: true,
|
|
429
|
+
displayOptions: {
|
|
430
|
+
show: {
|
|
431
|
+
resource: ['messaging'],
|
|
432
|
+
operation: ['sendMessage'],
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
displayName: 'Hashtag Name',
|
|
438
|
+
name: 'hashtagName',
|
|
439
|
+
type: 'string',
|
|
440
|
+
default: '',
|
|
441
|
+
description: 'The hashtag name to search for, without the # symbol',
|
|
442
|
+
required: true,
|
|
443
|
+
displayOptions: {
|
|
444
|
+
show: {
|
|
445
|
+
resource: ['igHashtag'],
|
|
446
|
+
operation: ['search'],
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
displayName: 'Hashtag ID',
|
|
452
|
+
name: 'hashtagId',
|
|
453
|
+
type: 'string',
|
|
454
|
+
default: '',
|
|
455
|
+
description: 'The IG Hashtag ID returned by the hashtag search',
|
|
456
|
+
required: true,
|
|
457
|
+
displayOptions: {
|
|
458
|
+
show: {
|
|
459
|
+
resource: ['igHashtag'],
|
|
460
|
+
operation: ['getRecentMedia', 'getTopMedia'],
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
},
|
|
162
464
|
{
|
|
163
465
|
displayName: 'Media ID',
|
|
164
466
|
name: 'mediaId',
|
|
@@ -354,7 +656,7 @@ class Instagram {
|
|
|
354
656
|
};
|
|
355
657
|
}
|
|
356
658
|
async execute() {
|
|
357
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
659
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
358
660
|
const items = this.getInputData();
|
|
359
661
|
const returnItems = [];
|
|
360
662
|
const hostUrl = 'graph.facebook.com';
|
|
@@ -411,6 +713,348 @@ class Instagram {
|
|
|
411
713
|
try {
|
|
412
714
|
const resource = this.getNodeParameter('resource', itemIndex);
|
|
413
715
|
const operation = this.getNodeParameter('operation', itemIndex);
|
|
716
|
+
if (resource === 'messaging') {
|
|
717
|
+
const graphApiVersion = this.getNodeParameter('graphApiVersion', itemIndex);
|
|
718
|
+
const accountId = this.getNodeParameter('node', itemIndex);
|
|
719
|
+
try {
|
|
720
|
+
if (operation === 'sendMessage') {
|
|
721
|
+
const recipientId = this.getNodeParameter('recipientId', itemIndex);
|
|
722
|
+
const text = this.getNodeParameter('messageText', itemIndex);
|
|
723
|
+
const url = `https://${hostUrl}/${graphApiVersion}/${accountId}/messages`;
|
|
724
|
+
const requestOptions = {
|
|
725
|
+
headers: {
|
|
726
|
+
accept: 'application/json,text/*;q=0.99',
|
|
727
|
+
'Content-Type': 'application/json',
|
|
728
|
+
},
|
|
729
|
+
method: 'POST',
|
|
730
|
+
url,
|
|
731
|
+
body: {
|
|
732
|
+
recipient: {
|
|
733
|
+
id: recipientId,
|
|
734
|
+
},
|
|
735
|
+
message: {
|
|
736
|
+
text,
|
|
737
|
+
},
|
|
738
|
+
},
|
|
739
|
+
json: true,
|
|
740
|
+
};
|
|
741
|
+
const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'instagramApi', requestOptions));
|
|
742
|
+
returnItems.push({ json: response, pairedItem: { item: itemIndex } });
|
|
743
|
+
continue;
|
|
744
|
+
}
|
|
745
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported messaging operation: ${operation}`, { itemIndex });
|
|
746
|
+
}
|
|
747
|
+
catch (error) {
|
|
748
|
+
if (!this.continueOnFail()) {
|
|
749
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
750
|
+
}
|
|
751
|
+
let errorItem;
|
|
752
|
+
const errorWithGraph = error;
|
|
753
|
+
if (errorWithGraph.response !== undefined) {
|
|
754
|
+
const graphApiErrors = (_b = (_a = errorWithGraph.response.body) === null || _a === void 0 ? void 0 : _a.error) !== null && _b !== void 0 ? _b : {};
|
|
755
|
+
errorItem = {
|
|
756
|
+
statusCode: errorWithGraph.statusCode,
|
|
757
|
+
...graphApiErrors,
|
|
758
|
+
headers: errorWithGraph.response.headers,
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
errorItem = error;
|
|
763
|
+
}
|
|
764
|
+
returnItems.push({ json: { ...errorItem }, pairedItem: { item: itemIndex } });
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
if (resource === 'auth') {
|
|
769
|
+
try {
|
|
770
|
+
if (operation === 'refreshAccessToken') {
|
|
771
|
+
let token = (_c = this.getNodeParameter('accessToken', itemIndex, '')) !== null && _c !== void 0 ? _c : '';
|
|
772
|
+
if (!token) {
|
|
773
|
+
const credentials = (await this.getCredentials('instagramApi'));
|
|
774
|
+
token = (_d = credentials === null || credentials === void 0 ? void 0 : credentials.accessToken) !== null && _d !== void 0 ? _d : '';
|
|
775
|
+
}
|
|
776
|
+
if (!token) {
|
|
777
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No access token provided and no access token found in the Instagram API credential.', { itemIndex });
|
|
778
|
+
}
|
|
779
|
+
const url = 'https://graph.instagram.com/refresh_access_token';
|
|
780
|
+
const requestOptions = {
|
|
781
|
+
headers: {
|
|
782
|
+
accept: 'application/json,text/*;q=0.99',
|
|
783
|
+
},
|
|
784
|
+
method: 'GET',
|
|
785
|
+
url,
|
|
786
|
+
qs: {
|
|
787
|
+
grant_type: 'ig_refresh_token',
|
|
788
|
+
access_token: token,
|
|
789
|
+
},
|
|
790
|
+
json: true,
|
|
791
|
+
};
|
|
792
|
+
const response = (await this.helpers.httpRequest.call(this, requestOptions));
|
|
793
|
+
returnItems.push({ json: response, pairedItem: { item: itemIndex } });
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
if (operation === 'exchangeAccessToken') {
|
|
797
|
+
const shortLivedToken = this.getNodeParameter('shortLivedAccessToken', itemIndex);
|
|
798
|
+
const appSecret = this.getNodeParameter('appSecret', itemIndex);
|
|
799
|
+
const url = 'https://graph.instagram.com/access_token';
|
|
800
|
+
const requestOptions = {
|
|
801
|
+
headers: {
|
|
802
|
+
accept: 'application/json,text/*;q=0.99',
|
|
803
|
+
},
|
|
804
|
+
method: 'GET',
|
|
805
|
+
url,
|
|
806
|
+
qs: {
|
|
807
|
+
grant_type: 'ig_exchange_token',
|
|
808
|
+
client_secret: appSecret,
|
|
809
|
+
access_token: shortLivedToken,
|
|
810
|
+
},
|
|
811
|
+
json: true,
|
|
812
|
+
};
|
|
813
|
+
const response = (await this.helpers.httpRequest.call(this, requestOptions));
|
|
814
|
+
returnItems.push({ json: response, pairedItem: { item: itemIndex } });
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
if (operation === 'getMe') {
|
|
818
|
+
const graphApiVersion = this.getNodeParameter('graphApiVersion', itemIndex);
|
|
819
|
+
const url = `https://${hostUrl}/${graphApiVersion}/me`;
|
|
820
|
+
const requestOptions = {
|
|
821
|
+
headers: {
|
|
822
|
+
accept: 'application/json,text/*;q=0.99',
|
|
823
|
+
},
|
|
824
|
+
method: 'GET',
|
|
825
|
+
url,
|
|
826
|
+
json: true,
|
|
827
|
+
};
|
|
828
|
+
const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'instagramApi', requestOptions));
|
|
829
|
+
returnItems.push({ json: response, pairedItem: { item: itemIndex } });
|
|
830
|
+
continue;
|
|
831
|
+
}
|
|
832
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported auth operation: ${operation}`, { itemIndex });
|
|
833
|
+
}
|
|
834
|
+
catch (error) {
|
|
835
|
+
if (!this.continueOnFail()) {
|
|
836
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
837
|
+
}
|
|
838
|
+
let errorItem;
|
|
839
|
+
const errorWithGraph = error;
|
|
840
|
+
if (errorWithGraph.response !== undefined) {
|
|
841
|
+
const graphApiErrors = (_f = (_e = errorWithGraph.response.body) === null || _e === void 0 ? void 0 : _e.error) !== null && _f !== void 0 ? _f : {};
|
|
842
|
+
errorItem = {
|
|
843
|
+
statusCode: errorWithGraph.statusCode,
|
|
844
|
+
...graphApiErrors,
|
|
845
|
+
headers: errorWithGraph.response.headers,
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
errorItem = error;
|
|
850
|
+
}
|
|
851
|
+
returnItems.push({ json: { ...errorItem }, pairedItem: { item: itemIndex } });
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
if (resource === 'igHashtag') {
|
|
856
|
+
const graphApiVersion = this.getNodeParameter('graphApiVersion', itemIndex);
|
|
857
|
+
const accountId = this.getNodeParameter('node', itemIndex);
|
|
858
|
+
try {
|
|
859
|
+
if (operation === 'search') {
|
|
860
|
+
const hashtagName = this.getNodeParameter('hashtagName', itemIndex);
|
|
861
|
+
const url = `https://${hostUrl}/${graphApiVersion}/ig_hashtag_search`;
|
|
862
|
+
const requestOptions = {
|
|
863
|
+
headers: {
|
|
864
|
+
accept: 'application/json,text/*;q=0.99',
|
|
865
|
+
},
|
|
866
|
+
method: 'GET',
|
|
867
|
+
url,
|
|
868
|
+
qs: {
|
|
869
|
+
user_id: accountId,
|
|
870
|
+
q: hashtagName,
|
|
871
|
+
},
|
|
872
|
+
json: true,
|
|
873
|
+
};
|
|
874
|
+
const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'instagramApi', requestOptions));
|
|
875
|
+
returnItems.push({ json: response, pairedItem: { item: itemIndex } });
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
if (operation === 'getRecentMedia' || operation === 'getTopMedia') {
|
|
879
|
+
const hashtagId = this.getNodeParameter('hashtagId', itemIndex);
|
|
880
|
+
const returnAll = this.getNodeParameter('returnAll', itemIndex, false);
|
|
881
|
+
const limit = this.getNodeParameter('limit', itemIndex, 0);
|
|
882
|
+
const edge = operation === 'getRecentMedia' ? 'recent_media' : 'top_media';
|
|
883
|
+
const baseUrl = `https://${hostUrl}/${graphApiVersion}/${hashtagId}/${edge}`;
|
|
884
|
+
const fields = [
|
|
885
|
+
'id',
|
|
886
|
+
'media_type',
|
|
887
|
+
'media_url',
|
|
888
|
+
'caption',
|
|
889
|
+
'permalink',
|
|
890
|
+
'timestamp',
|
|
891
|
+
'comments_count',
|
|
892
|
+
'like_count',
|
|
893
|
+
].join(',');
|
|
894
|
+
const accumulated = [];
|
|
895
|
+
let after;
|
|
896
|
+
const hardCap = returnAll ? 5000 : limit;
|
|
897
|
+
let hasMore = true;
|
|
898
|
+
while (hasMore) {
|
|
899
|
+
const remaining = returnAll ? undefined : hardCap - accumulated.length;
|
|
900
|
+
const pageLimit = remaining !== undefined ? Math.min(remaining, 50) : 50;
|
|
901
|
+
const qs = {
|
|
902
|
+
user_id: accountId,
|
|
903
|
+
fields,
|
|
904
|
+
limit: pageLimit,
|
|
905
|
+
};
|
|
906
|
+
if (after) {
|
|
907
|
+
qs.after = after;
|
|
908
|
+
}
|
|
909
|
+
const requestOptions = {
|
|
910
|
+
headers: {
|
|
911
|
+
accept: 'application/json,text/*;q=0.99',
|
|
912
|
+
},
|
|
913
|
+
method: 'GET',
|
|
914
|
+
url: baseUrl,
|
|
915
|
+
qs,
|
|
916
|
+
json: true,
|
|
917
|
+
};
|
|
918
|
+
const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'instagramApi', requestOptions));
|
|
919
|
+
const pageData = (_g = response.data) !== null && _g !== void 0 ? _g : [];
|
|
920
|
+
accumulated.push(...pageData);
|
|
921
|
+
const paging = response.paging;
|
|
922
|
+
after = (_h = paging === null || paging === void 0 ? void 0 : paging.cursors) === null || _h === void 0 ? void 0 : _h.after;
|
|
923
|
+
if ((!returnAll && accumulated.length >= hardCap) || !after) {
|
|
924
|
+
hasMore = false;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
const finalData = !returnAll && hardCap > 0 ? accumulated.slice(0, hardCap) : accumulated;
|
|
928
|
+
returnItems.push({ json: { data: finalData }, pairedItem: { item: itemIndex } });
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported IG Hashtag operation: ${operation}`, { itemIndex });
|
|
932
|
+
}
|
|
933
|
+
catch (error) {
|
|
934
|
+
if (!this.continueOnFail()) {
|
|
935
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
936
|
+
}
|
|
937
|
+
let errorItem;
|
|
938
|
+
const errorWithGraph = error;
|
|
939
|
+
if (errorWithGraph.response !== undefined) {
|
|
940
|
+
const graphApiErrors = (_k = (_j = errorWithGraph.response.body) === null || _j === void 0 ? void 0 : _j.error) !== null && _k !== void 0 ? _k : {};
|
|
941
|
+
errorItem = {
|
|
942
|
+
statusCode: errorWithGraph.statusCode,
|
|
943
|
+
...graphApiErrors,
|
|
944
|
+
headers: errorWithGraph.response.headers,
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
else {
|
|
948
|
+
errorItem = error;
|
|
949
|
+
}
|
|
950
|
+
returnItems.push({ json: { ...errorItem }, pairedItem: { item: itemIndex } });
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
if (resource === 'igUser') {
|
|
955
|
+
const graphApiVersion = this.getNodeParameter('graphApiVersion', itemIndex);
|
|
956
|
+
const accountId = this.getNodeParameter('node', itemIndex);
|
|
957
|
+
try {
|
|
958
|
+
if (operation === 'get') {
|
|
959
|
+
const url = `https://${hostUrl}/${graphApiVersion}/${accountId}`;
|
|
960
|
+
const requestOptions = {
|
|
961
|
+
headers: {
|
|
962
|
+
accept: 'application/json,text/*;q=0.99',
|
|
963
|
+
},
|
|
964
|
+
method: 'GET',
|
|
965
|
+
url,
|
|
966
|
+
qs: {
|
|
967
|
+
fields: [
|
|
968
|
+
'id',
|
|
969
|
+
'username',
|
|
970
|
+
'name',
|
|
971
|
+
'biography',
|
|
972
|
+
'website',
|
|
973
|
+
'media_count',
|
|
974
|
+
'followers_count',
|
|
975
|
+
'follows_count',
|
|
976
|
+
'profile_picture_url',
|
|
977
|
+
].join(','),
|
|
978
|
+
},
|
|
979
|
+
json: true,
|
|
980
|
+
};
|
|
981
|
+
const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'instagramApi', requestOptions));
|
|
982
|
+
returnItems.push({ json: response, pairedItem: { item: itemIndex } });
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
if (operation === 'getMedia') {
|
|
986
|
+
const returnAll = this.getNodeParameter('returnAll', itemIndex, false);
|
|
987
|
+
const limit = this.getNodeParameter('limit', itemIndex, 0);
|
|
988
|
+
const baseUrl = `https://${hostUrl}/${graphApiVersion}/${accountId}/media`;
|
|
989
|
+
const fields = [
|
|
990
|
+
'id',
|
|
991
|
+
'media_type',
|
|
992
|
+
'media_url',
|
|
993
|
+
'thumbnail_url',
|
|
994
|
+
'caption',
|
|
995
|
+
'permalink',
|
|
996
|
+
'timestamp',
|
|
997
|
+
'username',
|
|
998
|
+
].join(',');
|
|
999
|
+
const accumulated = [];
|
|
1000
|
+
let after;
|
|
1001
|
+
const hardCap = returnAll ? 5000 : limit;
|
|
1002
|
+
let hasMore = true;
|
|
1003
|
+
while (hasMore) {
|
|
1004
|
+
const remaining = returnAll ? undefined : hardCap - accumulated.length;
|
|
1005
|
+
const pageLimit = remaining !== undefined ? Math.min(remaining, 100) : 100;
|
|
1006
|
+
const qs = {
|
|
1007
|
+
fields,
|
|
1008
|
+
limit: pageLimit,
|
|
1009
|
+
};
|
|
1010
|
+
if (after) {
|
|
1011
|
+
qs.after = after;
|
|
1012
|
+
}
|
|
1013
|
+
const requestOptions = {
|
|
1014
|
+
headers: {
|
|
1015
|
+
accept: 'application/json,text/*;q=0.99',
|
|
1016
|
+
},
|
|
1017
|
+
method: 'GET',
|
|
1018
|
+
url: baseUrl,
|
|
1019
|
+
qs,
|
|
1020
|
+
json: true,
|
|
1021
|
+
};
|
|
1022
|
+
const response = (await this.helpers.httpRequestWithAuthentication.call(this, 'instagramApi', requestOptions));
|
|
1023
|
+
const pageData = (_l = response.data) !== null && _l !== void 0 ? _l : [];
|
|
1024
|
+
accumulated.push(...pageData);
|
|
1025
|
+
const paging = response.paging;
|
|
1026
|
+
after = (_m = paging === null || paging === void 0 ? void 0 : paging.cursors) === null || _m === void 0 ? void 0 : _m.after;
|
|
1027
|
+
if ((!returnAll && accumulated.length >= hardCap) || !after) {
|
|
1028
|
+
hasMore = false;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
const finalData = !returnAll && hardCap > 0 ? accumulated.slice(0, hardCap) : accumulated;
|
|
1032
|
+
returnItems.push({ json: { data: finalData }, pairedItem: { item: itemIndex } });
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported IG User operation: ${operation}`, { itemIndex });
|
|
1036
|
+
}
|
|
1037
|
+
catch (error) {
|
|
1038
|
+
if (!this.continueOnFail()) {
|
|
1039
|
+
throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
|
|
1040
|
+
}
|
|
1041
|
+
let errorItem;
|
|
1042
|
+
const errorWithGraph = error;
|
|
1043
|
+
if (errorWithGraph.response !== undefined) {
|
|
1044
|
+
const graphApiErrors = (_p = (_o = errorWithGraph.response.body) === null || _o === void 0 ? void 0 : _o.error) !== null && _p !== void 0 ? _p : {};
|
|
1045
|
+
errorItem = {
|
|
1046
|
+
statusCode: errorWithGraph.statusCode,
|
|
1047
|
+
...graphApiErrors,
|
|
1048
|
+
headers: errorWithGraph.response.headers,
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
else {
|
|
1052
|
+
errorItem = error;
|
|
1053
|
+
}
|
|
1054
|
+
returnItems.push({ json: { ...errorItem }, pairedItem: { item: itemIndex } });
|
|
1055
|
+
continue;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
414
1058
|
if (resource === 'comments') {
|
|
415
1059
|
const graphApiVersion = this.getNodeParameter('graphApiVersion', itemIndex);
|
|
416
1060
|
try {
|
|
@@ -517,7 +1161,7 @@ class Instagram {
|
|
|
517
1161
|
let errorItem;
|
|
518
1162
|
const errorWithGraph = error;
|
|
519
1163
|
if (errorWithGraph.response !== undefined) {
|
|
520
|
-
const graphApiErrors = (
|
|
1164
|
+
const graphApiErrors = (_r = (_q = errorWithGraph.response.body) === null || _q === void 0 ? void 0 : _q.error) !== null && _r !== void 0 ? _r : {};
|
|
521
1165
|
errorItem = {
|
|
522
1166
|
statusCode: errorWithGraph.statusCode,
|
|
523
1167
|
...graphApiErrors,
|
|
@@ -546,7 +1190,7 @@ class Instagram {
|
|
|
546
1190
|
const graphApiVersion = this.getNodeParameter('graphApiVersion', itemIndex);
|
|
547
1191
|
const caption = this.getNodeParameter('caption', itemIndex);
|
|
548
1192
|
const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {});
|
|
549
|
-
const altText = (
|
|
1193
|
+
const altText = (_s = additionalFields.altText) !== null && _s !== void 0 ? _s : '';
|
|
550
1194
|
const rawLocationId = additionalFields.locationId;
|
|
551
1195
|
const userTagsCollection = additionalFields.userTags;
|
|
552
1196
|
const productTagsCollection = additionalFields.productTags;
|
|
@@ -624,7 +1268,7 @@ class Instagram {
|
|
|
624
1268
|
let errorItem;
|
|
625
1269
|
const err = error;
|
|
626
1270
|
if (err.response !== undefined) {
|
|
627
|
-
const graphApiErrors = (
|
|
1271
|
+
const graphApiErrors = (_u = (_t = err.response.body) === null || _t === void 0 ? void 0 : _t.error) !== null && _u !== void 0 ? _u : {};
|
|
628
1272
|
errorItem = {
|
|
629
1273
|
statusCode: err.statusCode,
|
|
630
1274
|
...graphApiErrors,
|
|
@@ -697,7 +1341,7 @@ class Instagram {
|
|
|
697
1341
|
let errorItem;
|
|
698
1342
|
const err = error;
|
|
699
1343
|
if (err.response !== undefined) {
|
|
700
|
-
const graphApiErrors = (
|
|
1344
|
+
const graphApiErrors = (_w = (_v = err.response.body) === null || _v === void 0 ? void 0 : _v.error) !== null && _w !== void 0 ? _w : {};
|
|
701
1345
|
errorItem = {
|
|
702
1346
|
statusCode: err.statusCode,
|
|
703
1347
|
...graphApiErrors,
|
|
@@ -738,7 +1382,7 @@ class Instagram {
|
|
|
738
1382
|
let errorItem;
|
|
739
1383
|
const errorWithGraph = error;
|
|
740
1384
|
if (errorWithGraph.response !== undefined) {
|
|
741
|
-
const graphApiErrors = (
|
|
1385
|
+
const graphApiErrors = (_y = (_x = errorWithGraph.response.body) === null || _x === void 0 ? void 0 : _x.error) !== null && _y !== void 0 ? _y : {};
|
|
742
1386
|
errorItem = {
|
|
743
1387
|
statusCode: errorWithGraph.statusCode,
|
|
744
1388
|
...graphApiErrors,
|