@pakoor/n8n-nodes-instagram 0.1.2 → 0.1.3
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/dist/credentials/InstagramOAuth2Api.credentials.d.ts +11 -10
- package/dist/credentials/InstagramOAuth2Api.credentials.d.ts.map +1 -1
- package/dist/credentials/InstagramOAuth2Api.credentials.js +108 -74
- package/dist/credentials/InstagramOAuth2Api.credentials.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ICredentialDataDecryptedObject, ICredentialTestRequest, ICredentialType, IDataObject, IHttpRequestHelper, INodeProperties } from 'n8n-workflow';
|
|
2
2
|
export declare class InstagramOAuth2Api implements ICredentialType {
|
|
3
3
|
name: string;
|
|
4
|
+
extends: string[];
|
|
4
5
|
displayName: string;
|
|
5
6
|
documentationUrl: string;
|
|
6
|
-
extends: string[];
|
|
7
7
|
properties: INodeProperties[];
|
|
8
|
-
authenticate: IAuthenticateGeneric;
|
|
9
|
-
test: ICredentialTestRequest;
|
|
10
8
|
/**
|
|
11
|
-
* Pre-authentication hook
|
|
12
|
-
* and
|
|
9
|
+
* Pre-authentication hook that exchanges short-lived OAuth token for a long-lived token
|
|
10
|
+
* and refreshes it when near expiration. n8n automatically persists the returned values.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* - 1.6: Auto-discover Instagram Business Account ID
|
|
12
|
+
* This is called by n8n before each API request when the credential has an expirable field.
|
|
13
|
+
* If this function returns new credential data, n8n will persist it to the database.
|
|
17
14
|
*/
|
|
18
|
-
preAuthentication(this: IHttpRequestHelper, credentials: ICredentialDataDecryptedObject): Promise<
|
|
15
|
+
preAuthentication(this: IHttpRequestHelper, credentials: ICredentialDataDecryptedObject): Promise<IDataObject>;
|
|
16
|
+
/**
|
|
17
|
+
* Test the credentials to ensure they work
|
|
18
|
+
*/
|
|
19
|
+
test: ICredentialTestRequest;
|
|
19
20
|
}
|
|
20
21
|
//# sourceMappingURL=InstagramOAuth2Api.credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstagramOAuth2Api.credentials.d.ts","sourceRoot":"","sources":["../../src/credentials/InstagramOAuth2Api.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"InstagramOAuth2Api.credentials.d.ts","sourceRoot":"","sources":["../../src/credentials/InstagramOAuth2Api.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,sBAAsB,EACtB,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,eAAe,EAChB,MAAM,cAAc,CAAC;AAEtB,qBAAa,kBAAmB,YAAW,eAAe;IACxD,IAAI,SAAwB;IAC5B,OAAO,WAAiB;IACxB,WAAW,SAA0B;IACrC,gBAAgB,SAAwE;IAExF,UAAU,EAAE,eAAe,EAAE,CAgG3B;IAEF;;;;;;OAMG;IACG,iBAAiB,CACrB,IAAI,EAAE,kBAAkB,EACxB,WAAW,EAAE,8BAA8B,GAC1C,OAAO,CAAC,WAAW,CAAC;IA6EvB;;OAEG;IACH,IAAI,EAAE,sBAAsB,CAS1B;CACH"}
|
|
@@ -4,9 +4,9 @@ exports.InstagramOAuth2Api = void 0;
|
|
|
4
4
|
class InstagramOAuth2Api {
|
|
5
5
|
constructor() {
|
|
6
6
|
this.name = 'instagramOAuth2Api';
|
|
7
|
-
this.displayName = 'Instagram OAuth2 API';
|
|
8
|
-
this.documentationUrl = 'https://developers.facebook.com/docs/instagram-api/';
|
|
9
7
|
this.extends = ['oAuth2Api'];
|
|
8
|
+
this.displayName = 'Instagram OAuth2 API';
|
|
9
|
+
this.documentationUrl = 'https://developers.facebook.com/docs/instagram-api/getting-started';
|
|
10
10
|
this.properties = [
|
|
11
11
|
{
|
|
12
12
|
displayName: 'Grant Type',
|
|
@@ -18,19 +18,19 @@ class InstagramOAuth2Api {
|
|
|
18
18
|
displayName: 'Authorization URL',
|
|
19
19
|
name: 'authUrl',
|
|
20
20
|
type: 'hidden',
|
|
21
|
-
default: 'https://
|
|
21
|
+
default: 'https://api.instagram.com/oauth/authorize',
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
displayName: 'Access Token URL',
|
|
25
25
|
name: 'accessTokenUrl',
|
|
26
26
|
type: 'hidden',
|
|
27
|
-
default: 'https://
|
|
27
|
+
default: 'https://api.instagram.com/oauth/access_token',
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
displayName: 'Scope',
|
|
31
31
|
name: 'scope',
|
|
32
32
|
type: 'hidden',
|
|
33
|
-
default: '
|
|
33
|
+
default: 'instagram_business_basic,instagram_business_manage_messages,instagram_business_manage_comments,instagram_business_content_publish',
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
displayName: 'Auth URI Query Parameters',
|
|
@@ -45,114 +45,148 @@ class InstagramOAuth2Api {
|
|
|
45
45
|
default: 'body',
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
|
-
displayName: '
|
|
49
|
-
name: '
|
|
48
|
+
displayName: 'Account Information',
|
|
49
|
+
name: 'accountInfoNotice',
|
|
50
|
+
type: 'notice',
|
|
51
|
+
default: '',
|
|
52
|
+
description: 'After connecting your account, your Instagram Business Account details (username, ID, profile) will be automatically available. You can access this information in your workflow nodes. The system will automatically exchange your OAuth token for a long-lived token (60 days) and persist it, ensuring it survives n8n restarts.',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Client ID',
|
|
56
|
+
name: 'clientId',
|
|
50
57
|
type: 'string',
|
|
51
58
|
default: '',
|
|
52
|
-
|
|
59
|
+
required: true,
|
|
60
|
+
description: 'The Instagram App ID from your Meta Developer Console. <a href="https://developers.facebook.com/apps/" target="_blank">Get it here</a>.',
|
|
61
|
+
placeholder: '1234567890123456',
|
|
53
62
|
},
|
|
54
63
|
{
|
|
55
|
-
displayName: '
|
|
56
|
-
name: '
|
|
57
|
-
type: '
|
|
64
|
+
displayName: 'Client Secret',
|
|
65
|
+
name: 'clientSecret',
|
|
66
|
+
type: 'string',
|
|
58
67
|
typeOptions: {
|
|
59
68
|
password: true,
|
|
60
69
|
},
|
|
61
70
|
default: '',
|
|
71
|
+
required: true,
|
|
72
|
+
description: 'The Instagram App Secret from your Meta Developer Console',
|
|
73
|
+
placeholder: 'abc123def456...',
|
|
62
74
|
},
|
|
63
75
|
{
|
|
64
|
-
displayName: '
|
|
65
|
-
name: '
|
|
76
|
+
displayName: 'Webhook Verify Token',
|
|
77
|
+
name: 'webhookVerifyToken',
|
|
78
|
+
type: 'string',
|
|
79
|
+
typeOptions: { password: true },
|
|
80
|
+
default: '',
|
|
81
|
+
required: false,
|
|
82
|
+
description: 'Optional: Custom verification token for webhook setup (minimum 20 characters). Only needed if using Instagram Trigger node.',
|
|
83
|
+
placeholder: 'my_custom_verify_token_2024',
|
|
84
|
+
},
|
|
85
|
+
// Hidden field for long-lived token with expirable typeOption
|
|
86
|
+
// This enables n8n's preAuthentication system to persist the token
|
|
87
|
+
{
|
|
88
|
+
displayName: 'Long-Lived Token',
|
|
89
|
+
name: 'longLivedToken',
|
|
66
90
|
type: 'hidden',
|
|
67
|
-
|
|
91
|
+
typeOptions: {
|
|
92
|
+
expirable: true,
|
|
93
|
+
},
|
|
94
|
+
default: '',
|
|
68
95
|
},
|
|
69
96
|
{
|
|
70
|
-
displayName: '
|
|
71
|
-
name: '
|
|
97
|
+
displayName: 'Token Expires At',
|
|
98
|
+
name: 'tokenExpiresAt',
|
|
72
99
|
type: 'hidden',
|
|
73
100
|
default: 0,
|
|
74
101
|
},
|
|
75
102
|
];
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
qs: {
|
|
80
|
-
access_token: '={{$credentials.longLivedToken || $credentials.accessToken}}',
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
};
|
|
103
|
+
/**
|
|
104
|
+
* Test the credentials to ensure they work
|
|
105
|
+
*/
|
|
84
106
|
this.test = {
|
|
85
107
|
request: {
|
|
86
|
-
baseURL: 'https://graph.
|
|
108
|
+
baseURL: 'https://graph.instagram.com/v23.0',
|
|
87
109
|
url: '/me',
|
|
110
|
+
method: 'GET',
|
|
88
111
|
qs: {
|
|
89
|
-
fields: 'id,
|
|
112
|
+
fields: 'id,username',
|
|
90
113
|
},
|
|
91
114
|
},
|
|
92
115
|
};
|
|
93
116
|
}
|
|
94
117
|
/**
|
|
95
|
-
* Pre-authentication hook
|
|
96
|
-
* and
|
|
118
|
+
* Pre-authentication hook that exchanges short-lived OAuth token for a long-lived token
|
|
119
|
+
* and refreshes it when near expiration. n8n automatically persists the returned values.
|
|
97
120
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* - 1.6: Auto-discover Instagram Business Account ID
|
|
121
|
+
* This is called by n8n before each API request when the credential has an expirable field.
|
|
122
|
+
* If this function returns new credential data, n8n will persist it to the database.
|
|
101
123
|
*/
|
|
102
124
|
async preAuthentication(credentials) {
|
|
103
|
-
const
|
|
125
|
+
const now = Math.floor(Date.now() / 1000);
|
|
126
|
+
const longLivedToken = credentials.longLivedToken;
|
|
127
|
+
const tokenExpiresAt = credentials.tokenExpiresAt || 0;
|
|
104
128
|
const clientSecret = credentials.clientSecret;
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
129
|
+
const oauthTokenData = credentials.oauthTokenData;
|
|
130
|
+
const shortLivedToken = oauthTokenData?.access_token;
|
|
131
|
+
// If we have a valid long-lived token that's not near expiration, no action needed
|
|
132
|
+
if (longLivedToken && tokenExpiresAt > 0) {
|
|
133
|
+
// Token is still valid with more than 7 days remaining
|
|
134
|
+
const sevenDaysInSeconds = 7 * 24 * 60 * 60;
|
|
135
|
+
if (tokenExpiresAt > now + sevenDaysInSeconds) {
|
|
136
|
+
return {}; // No update needed
|
|
137
|
+
}
|
|
138
|
+
// Token is valid but near expiration (< 7 days), try to refresh it
|
|
139
|
+
// Instagram allows refresh only if token is at least 24 hours old
|
|
140
|
+
const totalLifetime = 60 * 24 * 60 * 60; // 60 days
|
|
141
|
+
const tokenAge = now - (tokenExpiresAt - totalLifetime);
|
|
142
|
+
if (tokenAge >= 24 * 60 * 60) {
|
|
143
|
+
try {
|
|
144
|
+
const refreshed = (await this.helpers.httpRequest({
|
|
145
|
+
method: 'GET',
|
|
146
|
+
url: 'https://graph.instagram.com/refresh_access_token',
|
|
147
|
+
qs: {
|
|
148
|
+
grant_type: 'ig_refresh_token',
|
|
149
|
+
access_token: longLivedToken,
|
|
150
|
+
},
|
|
151
|
+
}));
|
|
152
|
+
return {
|
|
153
|
+
longLivedToken: refreshed.access_token,
|
|
154
|
+
tokenExpiresAt: now + refreshed.expires_in,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
// Refresh failed, but token is still valid - continue using it
|
|
159
|
+
console.warn('Instagram: Failed to refresh long-lived token, continuing with current token', error);
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return {}; // Token too new to refresh
|
|
164
|
+
}
|
|
165
|
+
// No long-lived token yet - exchange short-lived OAuth token for long-lived
|
|
166
|
+
if (!shortLivedToken) {
|
|
167
|
+
// No token available at all
|
|
168
|
+
return {};
|
|
108
169
|
}
|
|
109
|
-
const updatedCredentials = { ...credentials };
|
|
110
170
|
try {
|
|
111
|
-
|
|
112
|
-
const longLivedTokenResponse = await this.helpers.httpRequest({
|
|
171
|
+
const exchanged = (await this.helpers.httpRequest({
|
|
113
172
|
method: 'GET',
|
|
114
|
-
url: 'https://graph.
|
|
173
|
+
url: 'https://graph.instagram.com/access_token',
|
|
115
174
|
qs: {
|
|
116
|
-
grant_type: '
|
|
117
|
-
client_id: clientId,
|
|
175
|
+
grant_type: 'ig_exchange_token',
|
|
118
176
|
client_secret: clientSecret,
|
|
119
|
-
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
if (longLivedTokenResponse.access_token) {
|
|
123
|
-
const now = Date.now();
|
|
124
|
-
const expiresIn = longLivedTokenResponse.expires_in ?? 5184000; // Default 60 days
|
|
125
|
-
updatedCredentials.longLivedToken = longLivedTokenResponse.access_token;
|
|
126
|
-
updatedCredentials.longLivedTokenExpiresAt = now + expiresIn * 1000;
|
|
127
|
-
updatedCredentials.longLivedTokenCreatedAt = now;
|
|
128
|
-
}
|
|
129
|
-
// Step 2: Auto-discover Instagram Business Account ID (Requirement 1.6)
|
|
130
|
-
const tokenToUse = updatedCredentials.longLivedToken || accessToken;
|
|
131
|
-
// Get pages connected to the user
|
|
132
|
-
const pagesResponse = await this.helpers.httpRequest({
|
|
133
|
-
method: 'GET',
|
|
134
|
-
url: 'https://graph.facebook.com/v18.0/me/accounts',
|
|
135
|
-
qs: {
|
|
136
|
-
fields: 'instagram_business_account,id,name',
|
|
137
|
-
access_token: tokenToUse,
|
|
177
|
+
access_token: shortLivedToken,
|
|
138
178
|
},
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
updatedCredentials.instagramAccountId = page.instagram_business_account.id;
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
179
|
+
}));
|
|
180
|
+
return {
|
|
181
|
+
longLivedToken: exchanged.access_token,
|
|
182
|
+
tokenExpiresAt: now + exchanged.expires_in,
|
|
183
|
+
};
|
|
149
184
|
}
|
|
150
185
|
catch (error) {
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
186
|
+
// Exchange failed - the short-lived token may be expired
|
|
187
|
+
console.error('Instagram: Failed to exchange OAuth token for long-lived token', error);
|
|
188
|
+
return {};
|
|
154
189
|
}
|
|
155
|
-
return updatedCredentials;
|
|
156
190
|
}
|
|
157
191
|
}
|
|
158
192
|
exports.InstagramOAuth2Api = InstagramOAuth2Api;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstagramOAuth2Api.credentials.js","sourceRoot":"","sources":["../../src/credentials/InstagramOAuth2Api.credentials.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"InstagramOAuth2Api.credentials.js","sourceRoot":"","sources":["../../src/credentials/InstagramOAuth2Api.credentials.ts"],"names":[],"mappings":"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"}
|