@skillful-ai/piece-skai-instagram-business 0.0.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 +7 -0
- package/package.json +34 -0
- package/src/index.d.ts +8 -0
- package/src/index.js +44 -0
- package/src/index.js.map +1 -0
- package/src/lib/actions/send-message.d.ts +15 -0
- package/src/lib/actions/send-message.js +113 -0
- package/src/lib/actions/send-message.js.map +1 -0
- package/src/lib/actions/upload-photo.d.ts +11 -0
- package/src/lib/actions/upload-photo.js +83 -0
- package/src/lib/actions/upload-photo.js.map +1 -0
- package/src/lib/actions/upload-reel.d.ts +11 -0
- package/src/lib/actions/upload-reel.js +116 -0
- package/src/lib/actions/upload-reel.js.map +1 -0
- package/src/lib/auth/instagram-business.auth.d.ts +16 -0
- package/src/lib/auth/instagram-business.auth.js +68 -0
- package/src/lib/auth/instagram-business.auth.js.map +1 -0
- package/src/lib/common/index.d.ts +72 -0
- package/src/lib/common/index.js +144 -0
- package/src/lib/common/index.js.map +1 -0
- package/src/lib/common/token-service.d.ts +44 -0
- package/src/lib/common/token-service.js +150 -0
- package/src/lib/common/token-service.js.map +1 -0
- package/src/lib/triggers/new-message.d.ts +23 -0
- package/src/lib/triggers/new-message.js +88 -0
- package/src/lib/triggers/new-message.js.map +1 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skillful-ai/piece-skai-instagram-business",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@activepieces/pieces-framework": "^0.20.1",
|
|
9
|
+
"@sinclair/typebox": "0.34.11",
|
|
10
|
+
"axios": "1.8.3",
|
|
11
|
+
"axios-retry": "4.4.1",
|
|
12
|
+
"deepmerge-ts": "7.1.0",
|
|
13
|
+
"mime-types": "2.1.35",
|
|
14
|
+
"nanoid": "3.3.8",
|
|
15
|
+
"semver": "7.6.0",
|
|
16
|
+
"tslib": "^2.3.0",
|
|
17
|
+
"zod": "3.25.76",
|
|
18
|
+
"@activepieces/pieces-common": "0.7.0",
|
|
19
|
+
"@activepieces/shared": "0.22.0"
|
|
20
|
+
},
|
|
21
|
+
"overrides": {
|
|
22
|
+
"@tryfabric/martian": {
|
|
23
|
+
"@notionhq/client": "$@notionhq/client"
|
|
24
|
+
},
|
|
25
|
+
"vite": {
|
|
26
|
+
"rollup": "npm:@rollup/wasm-node"
|
|
27
|
+
},
|
|
28
|
+
"undici": "6.19.8"
|
|
29
|
+
},
|
|
30
|
+
"resolutions": {
|
|
31
|
+
"rollup": "npm:@rollup/wasm-node",
|
|
32
|
+
"undici": "6.19.8"
|
|
33
|
+
}
|
|
34
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const skaiInstagramBusiness: import("@activepieces/pieces-framework").Piece<import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
2
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
3
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
6
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
7
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
8
|
+
}>>;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.skaiInstagramBusiness = void 0;
|
|
4
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
5
|
+
const shared_1 = require("@activepieces/shared");
|
|
6
|
+
const instagram_business_auth_1 = require("./lib/auth/instagram-business.auth");
|
|
7
|
+
// Actions
|
|
8
|
+
const send_message_1 = require("./lib/actions/send-message");
|
|
9
|
+
const upload_photo_1 = require("./lib/actions/upload-photo");
|
|
10
|
+
const upload_reel_1 = require("./lib/actions/upload-reel");
|
|
11
|
+
// Triggers
|
|
12
|
+
const new_message_1 = require("./lib/triggers/new-message");
|
|
13
|
+
exports.skaiInstagramBusiness = (0, pieces_framework_1.createPiece)({
|
|
14
|
+
displayName: 'Instagram Business',
|
|
15
|
+
description: 'Send and receive messages on Instagram Business accounts with SKAI Adapters support',
|
|
16
|
+
auth: instagram_business_auth_1.instagramBusinessAuth,
|
|
17
|
+
minimumSupportedRelease: '0.36.1',
|
|
18
|
+
logoUrl: 'https://cdn.activepieces.com/pieces/instagram.png',
|
|
19
|
+
authors: ['Haider Shabbir Hamid', 'Skillful AI'],
|
|
20
|
+
categories: [shared_1.PieceCategory.COMMUNICATION, shared_1.PieceCategory.MARKETING],
|
|
21
|
+
events: {
|
|
22
|
+
parseAndReply: ({ payload }) => {
|
|
23
|
+
var _a, _b, _c;
|
|
24
|
+
const body = payload.body;
|
|
25
|
+
const recipientId = ((_a = body === null || body === void 0 ? void 0 : body.recipient) === null || _a === void 0 ? void 0 : _a.id) || ((_c = (_b = body === null || body === void 0 ? void 0 : body.entry) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.id);
|
|
26
|
+
return {
|
|
27
|
+
event: 'new_instagram_message',
|
|
28
|
+
identifierValue: recipientId,
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
verify: () => {
|
|
32
|
+
return true;
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
actions: [
|
|
36
|
+
send_message_1.sendMessage,
|
|
37
|
+
upload_photo_1.uploadPhoto,
|
|
38
|
+
upload_reel_1.uploadReel,
|
|
39
|
+
],
|
|
40
|
+
triggers: [
|
|
41
|
+
new_message_1.newInstagramMessage,
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/pieces/custom/skai-instagram-business/src/index.ts"],"names":[],"mappings":";;;AAAA,qEAA6D;AAC7D,iDAAqD;AACrD,gFAA2E;AAE3E,UAAU;AACV,6DAAyD;AACzD,6DAAyD;AACzD,2DAAuD;AAEvD,WAAW;AACX,4DAAiE;AAEpD,QAAA,qBAAqB,GAAG,IAAA,8BAAW,EAAC;IAC7C,WAAW,EAAE,oBAAoB;IACjC,WAAW,EAAE,qFAAqF;IAClG,IAAI,EAAE,+CAAqB;IAC3B,uBAAuB,EAAE,QAAQ;IACjC,OAAO,EAAE,mDAAmD;IAC5D,OAAO,EAAE,CAAC,sBAAsB,EAAE,aAAa,CAAC;IAChD,UAAU,EAAE,CAAC,sBAAa,CAAC,aAAa,EAAE,sBAAa,CAAC,SAAS,CAAC;IAClE,MAAM,EAAE;QACJ,aAAa,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;;YAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAW,CAAC;YACjC,MAAM,WAAW,GAAG,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,SAAS,0CAAE,EAAE,MAAI,MAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,0CAAG,CAAC,CAAC,0CAAE,EAAE,CAAA,CAAC;YAChE,OAAO;gBACH,KAAK,EAAE,uBAAuB;gBAC9B,eAAe,EAAE,WAAW;aAC/B,CAAC;QACN,CAAC;QACD,MAAM,EAAE,GAAG,EAAE;YACT,OAAO,IAAI,CAAC;QAChB,CAAC;KACJ;IACD,OAAO,EAAE;QACL,0BAAW;QACX,0BAAW;QACX,wBAAU;KACb;IACD,QAAQ,EAAE;QACN,iCAAmB;KACtB;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const sendMessage: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
2
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
3
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
6
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
7
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
8
|
+
}>, {
|
|
9
|
+
recipientId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
10
|
+
text: import("@activepieces/pieces-framework").LongTextProperty<false>;
|
|
11
|
+
mediaUrl: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
12
|
+
mediaType: import("@activepieces/pieces-framework").StaticDropdownProperty<"image" | "video" | "audio" | "file", false>;
|
|
13
|
+
replyToMessageId: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
14
|
+
reactionEmoji: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendMessage = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const instagram_business_auth_1 = require("../auth/instagram-business.auth");
|
|
7
|
+
const common_1 = require("../common");
|
|
8
|
+
exports.sendMessage = (0, pieces_framework_1.createAction)({
|
|
9
|
+
auth: instagram_business_auth_1.instagramBusinessAuth,
|
|
10
|
+
name: 'sendMessage',
|
|
11
|
+
displayName: 'Send Message',
|
|
12
|
+
description: 'Send a text message, media, or reaction through Instagram',
|
|
13
|
+
props: {
|
|
14
|
+
recipientId: pieces_framework_1.Property.ShortText({
|
|
15
|
+
displayName: 'Recipient ID',
|
|
16
|
+
description: 'The Instagram-scoped ID (IGSID) of the message recipient',
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
text: pieces_framework_1.Property.LongText({
|
|
20
|
+
displayName: 'Message / Caption',
|
|
21
|
+
description: 'The text message to send (or caption if media is provided)',
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
mediaUrl: pieces_framework_1.Property.ShortText({
|
|
25
|
+
displayName: 'Media URL',
|
|
26
|
+
description: 'URL of the media file to send (image, video, audio, file). If provided with text, text will be sent separately.',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
29
|
+
mediaType: pieces_framework_1.Property.StaticDropdown({
|
|
30
|
+
displayName: 'Media Type',
|
|
31
|
+
description: 'Type of media to send (required when Media URL is provided)',
|
|
32
|
+
required: false,
|
|
33
|
+
options: {
|
|
34
|
+
disabled: false,
|
|
35
|
+
options: common_1.supportedMediaTypes.map((type) => ({
|
|
36
|
+
label: type.charAt(0).toUpperCase() + type.slice(1),
|
|
37
|
+
value: type,
|
|
38
|
+
})),
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
replyToMessageId: pieces_framework_1.Property.ShortText({
|
|
42
|
+
displayName: 'Reply To Message ID',
|
|
43
|
+
description: 'Message ID to reply to (optional)',
|
|
44
|
+
required: false,
|
|
45
|
+
defaultValue: '',
|
|
46
|
+
}),
|
|
47
|
+
reactionEmoji: pieces_framework_1.Property.ShortText({
|
|
48
|
+
displayName: 'Reaction Emoji',
|
|
49
|
+
description: 'Emoji reaction to add to a message (leave empty to remove reaction). Requires Reply To Message ID.',
|
|
50
|
+
required: false,
|
|
51
|
+
})
|
|
52
|
+
},
|
|
53
|
+
run(context) {
|
|
54
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
var _a;
|
|
56
|
+
const { recipientId, text, mediaUrl, mediaType, replyToMessageId, reactionEmoji } = context.propsValue;
|
|
57
|
+
const auth = context.auth;
|
|
58
|
+
// Get valid token (may refresh if needed)
|
|
59
|
+
const { accessToken } = yield common_1.instagramTokenService.getValidToken({
|
|
60
|
+
auth,
|
|
61
|
+
server: context.server,
|
|
62
|
+
project: context.project,
|
|
63
|
+
});
|
|
64
|
+
// Normalize inputs
|
|
65
|
+
const normalizedText = (text === null || text === void 0 ? void 0 : text.trim()) || '';
|
|
66
|
+
const normalizedMediaUrl = (mediaUrl === null || mediaUrl === void 0 ? void 0 : mediaUrl.trim()) || '';
|
|
67
|
+
const normalizedReaction = (_a = reactionEmoji === null || reactionEmoji === void 0 ? void 0 : reactionEmoji.trim()) !== null && _a !== void 0 ? _a : '';
|
|
68
|
+
const normalizedReplyTo = (replyToMessageId === null || replyToMessageId === void 0 ? void 0 : replyToMessageId.trim()) || '';
|
|
69
|
+
// Handle reaction messages first
|
|
70
|
+
const hasTextOrMedia = normalizedText || normalizedMediaUrl;
|
|
71
|
+
const isReactionRequest = normalizedReaction || (normalizedReplyTo && !hasTextOrMedia);
|
|
72
|
+
if (isReactionRequest) {
|
|
73
|
+
if (!normalizedReplyTo) {
|
|
74
|
+
throw new Error('Reply To Message ID is required when sending a reaction');
|
|
75
|
+
}
|
|
76
|
+
const response = yield common_1.instagramApi.sendReaction(auth.instagramAccountId, accessToken, recipientId, normalizedReplyTo, normalizedReaction);
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
reaction: normalizedReaction || '(removed)',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Validate that either text or media is provided
|
|
83
|
+
if (!normalizedText && !normalizedMediaUrl) {
|
|
84
|
+
throw new Error('Either message text or media URL must be provided');
|
|
85
|
+
}
|
|
86
|
+
if (normalizedText && normalizedMediaUrl) {
|
|
87
|
+
throw new Error('Either message text or media URL must be provided, not both');
|
|
88
|
+
}
|
|
89
|
+
let result = null;
|
|
90
|
+
// Send media message if media URL is provided
|
|
91
|
+
if (normalizedMediaUrl) {
|
|
92
|
+
const normalizedMediaType = ((mediaType === null || mediaType === void 0 ? void 0 : mediaType.trim()) || '');
|
|
93
|
+
if (!normalizedMediaType) {
|
|
94
|
+
throw new Error('Media Type is required when Media URL is provided');
|
|
95
|
+
}
|
|
96
|
+
if (!common_1.supportedMediaTypes.includes(normalizedMediaType)) {
|
|
97
|
+
throw new Error(`Invalid media type: ${mediaType}. Valid types are: ${common_1.supportedMediaTypes.join(', ')}`);
|
|
98
|
+
}
|
|
99
|
+
result = yield common_1.instagramApi.sendMediaMessage(auth.instagramAccountId, accessToken, recipientId, normalizedMediaType, normalizedMediaUrl);
|
|
100
|
+
}
|
|
101
|
+
else if (normalizedText) {
|
|
102
|
+
// Send text-only message
|
|
103
|
+
result = yield common_1.instagramApi.sendTextMessage(auth.instagramAccountId, accessToken, recipientId, normalizedText);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
success: true,
|
|
107
|
+
messageId: (result === null || result === void 0 ? void 0 : result.message_id) || null,
|
|
108
|
+
recipientId: recipientId,
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
//# sourceMappingURL=send-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"send-message.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/actions/send-message.ts"],"names":[],"mappings":";;;;AAAA,qEAAwE;AACxE,6EAAoG;AACpG,sCAKmB;AAGN,QAAA,WAAW,GAAG,IAAA,+BAAY,EAAC;IACpC,IAAI,EAAE,+CAAqB;IAC3B,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,2DAA2D;IACxE,KAAK,EAAE;QACH,WAAW,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC5B,WAAW,EAAE,cAAc;YAC3B,WAAW,EAAE,0DAA0D;YACvE,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,IAAI,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YACpB,WAAW,EAAE,mBAAmB;YAChC,WAAW,EAAE,4DAA4D;YACzE,QAAQ,EAAE,KAAK;SAClB,CAAC;QACF,QAAQ,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACzB,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,iHAAiH;YAC9H,QAAQ,EAAE,KAAK;SAClB,CAAC;QACF,SAAS,EAAE,2BAAQ,CAAC,cAAc,CAAC;YAC/B,WAAW,EAAE,YAAY;YACzB,WAAW,EAAE,6DAA6D;YAC1E,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE;gBACL,QAAQ,EAAE,KAAK;gBACf,OAAO,EAAE,4BAAmB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACxC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;oBACnD,KAAK,EAAE,IAAI;iBACd,CAAC,CAAC;aACN;SACJ,CAAC;QACF,gBAAgB,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACjC,WAAW,EAAE,qBAAqB;YAClC,WAAW,EAAE,mCAAmC;YAChD,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,EAAE;SACnB,CAAC;QACF,aAAa,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC9B,WAAW,EAAE,gBAAgB;YAC7B,WAAW,EAAE,oGAAoG;YACjH,QAAQ,EAAE,KAAK;SAClB,CAAC;KACL;IACK,GAAG,CAAC,OAAO;;;YACb,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YACvG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAkC,CAAC;YAExD,0CAA0C;YAC1C,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,8BAAqB,CAAC,aAAa,CAAC;gBAC9D,IAAI;gBACJ,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;aAC3B,CAAC,CAAC;YAEH,mBAAmB;YACnB,MAAM,cAAc,GAAG,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,EAAE,KAAI,EAAE,CAAC;YAC1C,MAAM,kBAAkB,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,EAAE,KAAI,EAAE,CAAC;YAClD,MAAM,kBAAkB,GAAG,MAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,IAAI,EAAE,mCAAI,EAAE,CAAC;YACvD,MAAM,iBAAiB,GAAG,CAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,IAAI,EAAE,KAAI,EAAE,CAAC;YAEzD,iCAAiC;YACjC,MAAM,cAAc,GAAG,cAAc,IAAI,kBAAkB,CAAC;YAC5D,MAAM,iBAAiB,GAAG,kBAAkB,IAAI,CAAC,iBAAiB,IAAI,CAAC,cAAc,CAAC,CAAC;YAEvF,IAAI,iBAAiB,EAAE,CAAC;gBACpB,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBACrB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;gBAC/E,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,qBAAY,CAAC,YAAY,CAC5C,IAAI,CAAC,kBAAkB,EACvB,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,kBAAkB,CACrB,CAAC;gBAEF,OAAO;oBACH,OAAO,EAAE,IAAI;oBACb,QAAQ,EAAE,kBAAkB,IAAI,WAAW;iBAC9C,CAAC;YACN,CAAC;YAED,iDAAiD;YACjD,IAAI,CAAC,cAAc,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACzE,CAAC;YAED,IAAI,cAAc,IAAI,kBAAkB,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;YACnF,CAAC;YAED,IAAI,MAAM,GAAQ,IAAI,CAAC;YAEvB,8CAA8C;YAC9C,IAAI,kBAAkB,EAAE,CAAC;gBACrB,MAAM,mBAAmB,GAAG,CAAC,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,IAAI,EAAE,KAAI,EAAE,CAAc,CAAC;gBACnE,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBACvB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;gBACzE,CAAC;gBACD,IAAI,CAAC,4BAAmB,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;oBACrD,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,sBAAsB,4BAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAC5G,CAAC;gBACD,MAAM,GAAG,MAAM,qBAAY,CAAC,gBAAgB,CACxC,IAAI,CAAC,kBAAkB,EACvB,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,kBAAkB,CACrB,CAAC;YACN,CAAC;iBAAM,IAAI,cAAc,EAAE,CAAC;gBACxB,yBAAyB;gBACzB,MAAM,GAAG,MAAM,qBAAY,CAAC,eAAe,CACvC,IAAI,CAAC,kBAAkB,EACvB,WAAW,EACX,WAAW,EACX,cAAc,CACjB,CAAC;YACN,CAAC;YAED,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,UAAU,KAAI,IAAI;gBACrC,WAAW,EAAE,WAAW;aAC3B,CAAC;QACN,CAAC;KAAA;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const uploadPhoto: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
2
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
3
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
6
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
7
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
8
|
+
}>, {
|
|
9
|
+
photo: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
10
|
+
caption: import("@activepieces/pieces-framework").LongTextProperty<false>;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadPhoto = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const instagram_business_auth_1 = require("../auth/instagram-business.auth");
|
|
8
|
+
const common_1 = require("../common");
|
|
9
|
+
const description = `
|
|
10
|
+
## Upload Photo
|
|
11
|
+
|
|
12
|
+
Upload a photo to your Instagram Business Account as a feed post.
|
|
13
|
+
|
|
14
|
+
### Input Parameters
|
|
15
|
+
- **Photo URL** (required): A publicly accessible URL to the image (JPG/PNG)
|
|
16
|
+
- **Caption**: Optional caption for the post
|
|
17
|
+
|
|
18
|
+
### Requirements
|
|
19
|
+
- The image URL must be publicly accessible
|
|
20
|
+
- Your Instagram account must be connected to a Facebook Page
|
|
21
|
+
- Requires \`instagram_business_content_publish\` permission
|
|
22
|
+
|
|
23
|
+
### Output
|
|
24
|
+
Returns the created media ID on success.
|
|
25
|
+
`;
|
|
26
|
+
exports.uploadPhoto = (0, pieces_framework_1.createAction)({
|
|
27
|
+
auth: instagram_business_auth_1.instagramBusinessAuth,
|
|
28
|
+
name: 'upload_photo',
|
|
29
|
+
displayName: 'Upload Photo',
|
|
30
|
+
description: 'Upload a photo to your Instagram Business Account',
|
|
31
|
+
props: {
|
|
32
|
+
photo: pieces_framework_1.Property.ShortText({
|
|
33
|
+
displayName: 'Photo URL',
|
|
34
|
+
description: 'A publicly accessible URL to the image (JPG/PNG)',
|
|
35
|
+
required: true,
|
|
36
|
+
}),
|
|
37
|
+
caption: pieces_framework_1.Property.LongText({
|
|
38
|
+
displayName: 'Caption',
|
|
39
|
+
description: 'Caption for the post',
|
|
40
|
+
required: false,
|
|
41
|
+
}),
|
|
42
|
+
},
|
|
43
|
+
run(context) {
|
|
44
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const auth = context.auth;
|
|
46
|
+
const { photo, caption } = context.propsValue;
|
|
47
|
+
const { accessToken } = yield common_1.instagramTokenService.getValidToken({
|
|
48
|
+
auth,
|
|
49
|
+
server: context.server,
|
|
50
|
+
project: context.project,
|
|
51
|
+
});
|
|
52
|
+
// Step 1: Create media container
|
|
53
|
+
const createContainerResponse = yield pieces_common_1.httpClient.sendRequest({
|
|
54
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
55
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${auth.instagramAccountId}/media`,
|
|
56
|
+
queryParams: {
|
|
57
|
+
access_token: accessToken,
|
|
58
|
+
image_url: photo,
|
|
59
|
+
caption: caption || '',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
if (!createContainerResponse.body.id) {
|
|
63
|
+
throw new Error(`Failed to create media container: ${JSON.stringify(createContainerResponse.body)}`);
|
|
64
|
+
}
|
|
65
|
+
const containerId = createContainerResponse.body.id;
|
|
66
|
+
// Step 2: Publish the container
|
|
67
|
+
const publishResponse = yield pieces_common_1.httpClient.sendRequest({
|
|
68
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
69
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${auth.instagramAccountId}/media_publish`,
|
|
70
|
+
queryParams: {
|
|
71
|
+
access_token: accessToken,
|
|
72
|
+
creation_id: containerId,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
mediaId: publishResponse.body.id,
|
|
78
|
+
containerId,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
//# sourceMappingURL=upload-photo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-photo.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/actions/upload-photo.ts"],"names":[],"mappings":";;;;AAAA,qEAAwE;AACxE,+DAAqE;AACrE,6EAAoG;AACpG,sCAA4E;AAE5E,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;CAgBnB,CAAC;AAEW,QAAA,WAAW,GAAG,IAAA,+BAAY,EAAC;IACpC,IAAI,EAAE,+CAAqB;IAC3B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,mDAAmD;IAChE,KAAK,EAAE;QACH,KAAK,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACtB,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,kDAAkD;YAC/D,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,OAAO,EAAE,2BAAQ,CAAC,QAAQ,CAAC;YACvB,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,sBAAsB;YACnC,QAAQ,EAAE,KAAK;SAClB,CAAC;KACL;IACK,GAAG,CAAC,OAAO;;YACb,MAAM,IAAI,GAAG,OAAO,CAAC,IAAkC,CAAC;YACxD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;YAE9C,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,8BAAqB,CAAC,aAAa,CAAC;gBAC9D,IAAI;gBACJ,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;aAC3B,CAAC,CAAC;YAGH,iCAAiC;YACjC,MAAM,uBAAuB,GAAG,MAAM,0BAAU,CAAC,WAAW,CAAC;gBACzD,MAAM,EAAE,0BAAU,CAAC,IAAI;gBACvB,GAAG,EAAE,GAAG,iCAAwB,IAAI,IAAI,CAAC,kBAAkB,QAAQ;gBACnE,WAAW,EAAE;oBACT,YAAY,EAAE,WAAW;oBACzB,SAAS,EAAE,KAAK;oBAChB,OAAO,EAAE,OAAO,IAAI,EAAE;iBACzB;aACJ,CAAC,CAAC;YAEH,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzG,CAAC;YAED,MAAM,WAAW,GAAG,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC;YAEpD,gCAAgC;YAChC,MAAM,eAAe,GAAG,MAAM,0BAAU,CAAC,WAAW,CAAC;gBACjD,MAAM,EAAE,0BAAU,CAAC,IAAI;gBACvB,GAAG,EAAE,GAAG,iCAAwB,IAAI,IAAI,CAAC,kBAAkB,gBAAgB;gBAC3E,WAAW,EAAE;oBACT,YAAY,EAAE,WAAW;oBACzB,WAAW,EAAE,WAAW;iBAC3B;aACJ,CAAC,CAAC;YAEH,OAAO;gBACH,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE;gBAChC,WAAW;aACd,CAAC;QACN,CAAC;KAAA;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const uploadReel: import("@activepieces/pieces-framework").IAction<import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
2
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
3
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
6
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
7
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
8
|
+
}>, {
|
|
9
|
+
video: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
10
|
+
caption: import("@activepieces/pieces-framework").LongTextProperty<false>;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadReel = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const instagram_business_auth_1 = require("../auth/instagram-business.auth");
|
|
8
|
+
const common_1 = require("../common");
|
|
9
|
+
const description = `
|
|
10
|
+
## Upload Reel
|
|
11
|
+
|
|
12
|
+
Upload a video reel to your Instagram Business Account.
|
|
13
|
+
|
|
14
|
+
### Input Parameters
|
|
15
|
+
- **Video URL** (required): A publicly accessible URL to the video
|
|
16
|
+
- **Caption**: Optional caption for the reel
|
|
17
|
+
|
|
18
|
+
### Requirements
|
|
19
|
+
- The video URL must be publicly accessible
|
|
20
|
+
- Video must be between 3-90 seconds
|
|
21
|
+
- Maximum file size: 1GB
|
|
22
|
+
- Your Instagram account must be connected to a Facebook Page
|
|
23
|
+
- Requires \`instagram_business_content_publish\` permission
|
|
24
|
+
|
|
25
|
+
### Output
|
|
26
|
+
Returns the created media ID on success.
|
|
27
|
+
`;
|
|
28
|
+
// Helper to wait for video processing
|
|
29
|
+
function waitForVideoProcessing(instagramAccountId_1, containerId_1, accessToken_1) {
|
|
30
|
+
return tslib_1.__awaiter(this, arguments, void 0, function* (instagramAccountId, containerId, accessToken, maxRetries = 30, delayMs = 5000) {
|
|
31
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
32
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
33
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
34
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${containerId}`,
|
|
35
|
+
queryParams: {
|
|
36
|
+
access_token: accessToken,
|
|
37
|
+
fields: 'status_code',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const status = response.body.status_code;
|
|
41
|
+
if (status === 'FINISHED') {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (status === 'ERROR') {
|
|
45
|
+
throw new Error('Video processing failed');
|
|
46
|
+
}
|
|
47
|
+
// Wait before checking again
|
|
48
|
+
yield new Promise(resolve => setTimeout(resolve, delayMs));
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
exports.uploadReel = (0, pieces_framework_1.createAction)({
|
|
54
|
+
auth: instagram_business_auth_1.instagramBusinessAuth,
|
|
55
|
+
name: 'upload_reel',
|
|
56
|
+
displayName: 'Upload Reel',
|
|
57
|
+
description: 'Upload a video reel to your Instagram Business Account',
|
|
58
|
+
props: {
|
|
59
|
+
video: pieces_framework_1.Property.ShortText({
|
|
60
|
+
displayName: 'Video URL',
|
|
61
|
+
description: 'A publicly accessible URL to the video (3-90 seconds, max 1GB)',
|
|
62
|
+
required: true,
|
|
63
|
+
}),
|
|
64
|
+
caption: pieces_framework_1.Property.LongText({
|
|
65
|
+
displayName: 'Caption',
|
|
66
|
+
description: 'Caption for the reel',
|
|
67
|
+
required: false,
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
70
|
+
run(context) {
|
|
71
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
const auth = context.auth;
|
|
73
|
+
const { video, caption } = context.propsValue;
|
|
74
|
+
const { accessToken } = yield common_1.instagramTokenService.getValidToken({
|
|
75
|
+
auth,
|
|
76
|
+
server: context.server,
|
|
77
|
+
project: context.project,
|
|
78
|
+
});
|
|
79
|
+
// Step 1: Create media container for reel
|
|
80
|
+
const createContainerResponse = yield pieces_common_1.httpClient.sendRequest({
|
|
81
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
82
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${auth.instagramAccountId}/media`,
|
|
83
|
+
queryParams: {
|
|
84
|
+
access_token: accessToken,
|
|
85
|
+
video_url: video,
|
|
86
|
+
caption: caption || '',
|
|
87
|
+
media_type: 'REELS',
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
if (!createContainerResponse.body.id) {
|
|
91
|
+
throw new Error(`Failed to create media container: ${JSON.stringify(createContainerResponse.body)}`);
|
|
92
|
+
}
|
|
93
|
+
const containerId = createContainerResponse.body.id;
|
|
94
|
+
// Step 2: Wait for video processing
|
|
95
|
+
const isProcessed = yield waitForVideoProcessing(auth.instagramAccountId, containerId, accessToken);
|
|
96
|
+
if (!isProcessed) {
|
|
97
|
+
throw new Error('Video processing timed out. Please try again with a smaller video.');
|
|
98
|
+
}
|
|
99
|
+
// Step 3: Publish the container
|
|
100
|
+
const publishResponse = yield pieces_common_1.httpClient.sendRequest({
|
|
101
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
102
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${auth.instagramAccountId}/media_publish`,
|
|
103
|
+
queryParams: {
|
|
104
|
+
access_token: accessToken,
|
|
105
|
+
creation_id: containerId,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
success: true,
|
|
110
|
+
mediaId: publishResponse.body.id,
|
|
111
|
+
containerId,
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=upload-reel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-reel.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/actions/upload-reel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const instagramBusinessAuth: import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
2
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
3
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
4
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
6
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
7
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
8
|
+
}>;
|
|
9
|
+
export type InstagramBusinessAuthValue = {
|
|
10
|
+
accessToken: string;
|
|
11
|
+
instagramAccountId: string;
|
|
12
|
+
instagramUsername: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
tokenExpiresAt?: string;
|
|
15
|
+
refreshThresholdDays?: number;
|
|
16
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.instagramBusinessAuth = void 0;
|
|
4
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
5
|
+
const markdown = `
|
|
6
|
+
## Authentication
|
|
7
|
+
|
|
8
|
+
### Embedded Signup (Recommended)
|
|
9
|
+
Click "Connect" to authenticate via Instagram Business Login. This will automatically:
|
|
10
|
+
1. Redirect to Instagram for authorization
|
|
11
|
+
2. Exchange the authorization code for tokens (server-side)
|
|
12
|
+
3. Fetch your Instagram Account ID and username
|
|
13
|
+
4. Set the token expiration date
|
|
14
|
+
|
|
15
|
+
### Manual Setup
|
|
16
|
+
To manually obtain credentials:
|
|
17
|
+
1. Go to https://developers.facebook.com/
|
|
18
|
+
2. Create app → Select **Other** → Choose **Business** type
|
|
19
|
+
3. Add Product → **Instagram**
|
|
20
|
+
4. Configure **Instagram Business Login** settings
|
|
21
|
+
5. Generate User Access Token with scopes:
|
|
22
|
+
- instagram_business_basic
|
|
23
|
+
- instagram_business_manage_messages
|
|
24
|
+
- instagram_business_content_publish
|
|
25
|
+
6. Exchange for long-lived token (60 days)
|
|
26
|
+
7. Get Instagram Account ID from /me endpoint
|
|
27
|
+
|
|
28
|
+
### Token Refresh
|
|
29
|
+
Tokens are automatically refreshed when nearing expiration (within 10 days).
|
|
30
|
+
`;
|
|
31
|
+
exports.instagramBusinessAuth = pieces_framework_1.PieceAuth.CustomAuth({
|
|
32
|
+
required: true,
|
|
33
|
+
description: markdown,
|
|
34
|
+
props: {
|
|
35
|
+
accessToken: pieces_framework_1.PieceAuth.SecretText({
|
|
36
|
+
displayName: 'Access Token',
|
|
37
|
+
description: 'Instagram long-lived access token. Populated automatically via Embedded Signup.',
|
|
38
|
+
required: true,
|
|
39
|
+
}),
|
|
40
|
+
instagramAccountId: pieces_framework_1.Property.ShortText({
|
|
41
|
+
displayName: 'Instagram Account ID',
|
|
42
|
+
description: 'The Instagram Business Account ID. Populated automatically via Embedded Signup.',
|
|
43
|
+
required: true,
|
|
44
|
+
}),
|
|
45
|
+
instagramUsername: pieces_framework_1.Property.ShortText({
|
|
46
|
+
displayName: 'Instagram Username',
|
|
47
|
+
description: 'Your Instagram username (without @). Populated automatically via Embedded Signup.',
|
|
48
|
+
required: true,
|
|
49
|
+
}),
|
|
50
|
+
userId: pieces_framework_1.Property.ShortText({
|
|
51
|
+
displayName: 'User ID',
|
|
52
|
+
description: 'Instagram-scoped User ID (for connection identification). Populated automatically via Embedded Signup.',
|
|
53
|
+
required: true,
|
|
54
|
+
}),
|
|
55
|
+
tokenExpiresAt: pieces_framework_1.Property.ShortText({
|
|
56
|
+
displayName: 'Token Expires At',
|
|
57
|
+
description: 'ISO date string when the token expires. Populated automatically via Embedded Signup.',
|
|
58
|
+
required: false,
|
|
59
|
+
}),
|
|
60
|
+
refreshThresholdDays: pieces_framework_1.Property.Number({
|
|
61
|
+
displayName: 'Refresh Threshold (Days)',
|
|
62
|
+
description: 'Refresh token when this many days remain until expiration. Default: 10 days.',
|
|
63
|
+
required: false,
|
|
64
|
+
defaultValue: 10,
|
|
65
|
+
}),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=instagram-business.auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instagram-business.auth.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/auth/instagram-business.auth.ts"],"names":[],"mappings":";;;AAAA,qEAAqE;AAErE,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBhB,CAAC;AAEW,QAAA,qBAAqB,GAAG,4BAAS,CAAC,UAAU,CAAC;IACtD,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,QAAQ;IACrB,KAAK,EAAE;QACH,WAAW,EAAE,4BAAS,CAAC,UAAU,CAAC;YAC9B,WAAW,EAAE,cAAc;YAC3B,WAAW,EAAE,iFAAiF;YAC9F,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,kBAAkB,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACnC,WAAW,EAAE,sBAAsB;YACnC,WAAW,EAAE,iFAAiF;YAC9F,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,iBAAiB,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAClC,WAAW,EAAE,oBAAoB;YACjC,WAAW,EAAE,mFAAmF;YAChG,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,MAAM,EAAE,2BAAQ,CAAC,SAAS,CAAC;YACvB,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,wGAAwG;YACrH,QAAQ,EAAE,IAAI;SACjB,CAAC;QACF,cAAc,EAAE,2BAAQ,CAAC,SAAS,CAAC;YAC/B,WAAW,EAAE,kBAAkB;YAC/B,WAAW,EAAE,sFAAsF;YACnG,QAAQ,EAAE,KAAK;SAClB,CAAC;QACF,oBAAoB,EAAE,2BAAQ,CAAC,MAAM,CAAC;YAClC,WAAW,EAAE,0BAA0B;YACvC,WAAW,EAAE,8EAA8E;YAC3F,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,EAAE;SACnB,CAAC;KACL;CACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export declare const INSTAGRAM_GRAPH_API_BASE = "https://graph.instagram.com/v24.0";
|
|
2
|
+
export declare const supportedMediaTypes: readonly ["image", "video", "audio", "file"];
|
|
3
|
+
export type MediaType = typeof supportedMediaTypes[number];
|
|
4
|
+
export declare const instagramApi: {
|
|
5
|
+
/**
|
|
6
|
+
* Send a text message
|
|
7
|
+
*/
|
|
8
|
+
sendTextMessage(instagramAccountId: string, accessToken: string, recipientId: string, text: string, replyToMessageId?: string): Promise<any>;
|
|
9
|
+
/**
|
|
10
|
+
* Send a media message (image, video, audio, file)
|
|
11
|
+
*/
|
|
12
|
+
sendMediaMessage(instagramAccountId: string, accessToken: string, recipientId: string, mediaType: MediaType, mediaUrl: string, replyToMessageId?: string): Promise<any>;
|
|
13
|
+
/**
|
|
14
|
+
* Send a reaction to a message
|
|
15
|
+
*/
|
|
16
|
+
sendReaction(instagramAccountId: string, accessToken: string, recipientId: string, messageId: string, emoji: string): Promise<any>;
|
|
17
|
+
/**
|
|
18
|
+
* Get user profile information
|
|
19
|
+
*/
|
|
20
|
+
getUserProfile(accessToken: string, userId: string): Promise<any>;
|
|
21
|
+
/**
|
|
22
|
+
* Download media from Instagram CDN
|
|
23
|
+
*/
|
|
24
|
+
downloadMedia(accessToken: string, mediaId: string): Promise<any>;
|
|
25
|
+
};
|
|
26
|
+
export interface NormalizedInstagramMessage {
|
|
27
|
+
senderId: string;
|
|
28
|
+
recipientId: string;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
type: 'text' | 'media' | 'reaction' | 'unsupported';
|
|
31
|
+
messageId: string;
|
|
32
|
+
text?: string;
|
|
33
|
+
attachments?: Array<{
|
|
34
|
+
type: string;
|
|
35
|
+
url?: string;
|
|
36
|
+
}>;
|
|
37
|
+
reaction?: {
|
|
38
|
+
emoji: string;
|
|
39
|
+
action: 'react' | 'unreact';
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export interface InstagramMessaging {
|
|
43
|
+
sender?: {
|
|
44
|
+
id: string;
|
|
45
|
+
};
|
|
46
|
+
recipient?: {
|
|
47
|
+
id: string;
|
|
48
|
+
};
|
|
49
|
+
timestamp: number;
|
|
50
|
+
message?: InstagramMessage;
|
|
51
|
+
reaction?: InstagramReaction;
|
|
52
|
+
}
|
|
53
|
+
export interface InstagramMessage {
|
|
54
|
+
mid: string;
|
|
55
|
+
text?: string;
|
|
56
|
+
attachments?: InstagramAttachment[];
|
|
57
|
+
}
|
|
58
|
+
export interface InstagramAttachment {
|
|
59
|
+
type: string;
|
|
60
|
+
payload: {
|
|
61
|
+
url?: string;
|
|
62
|
+
reel_url?: string;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface InstagramReaction {
|
|
66
|
+
mid: string;
|
|
67
|
+
action: 'react' | 'unreact';
|
|
68
|
+
emoji?: string;
|
|
69
|
+
reaction?: string;
|
|
70
|
+
}
|
|
71
|
+
export declare function normalizeMessagingEvent(messaging: InstagramMessaging): NormalizedInstagramMessage | undefined;
|
|
72
|
+
export { instagramTokenService, TokenServiceContext, TokenRefreshResult } from './token-service';
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.instagramTokenService = exports.instagramApi = exports.supportedMediaTypes = exports.INSTAGRAM_GRAPH_API_BASE = void 0;
|
|
4
|
+
exports.normalizeMessagingEvent = normalizeMessagingEvent;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
// Instagram Graph API base URL
|
|
8
|
+
exports.INSTAGRAM_GRAPH_API_BASE = 'https://graph.instagram.com/v24.0';
|
|
9
|
+
// Supported media types for messaging
|
|
10
|
+
exports.supportedMediaTypes = ['image', 'video', 'audio', 'file'];
|
|
11
|
+
// Instagram API helper functions
|
|
12
|
+
exports.instagramApi = {
|
|
13
|
+
/**
|
|
14
|
+
* Send a text message
|
|
15
|
+
*/
|
|
16
|
+
sendTextMessage(instagramAccountId, accessToken, recipientId, text, replyToMessageId) {
|
|
17
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const body = {
|
|
19
|
+
recipient: { id: recipientId },
|
|
20
|
+
message: { text },
|
|
21
|
+
};
|
|
22
|
+
if (replyToMessageId) {
|
|
23
|
+
body.reply_to = { mid: replyToMessageId };
|
|
24
|
+
}
|
|
25
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
26
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
27
|
+
url: `${exports.INSTAGRAM_GRAPH_API_BASE}/${instagramAccountId}/messages`,
|
|
28
|
+
queryParams: { access_token: accessToken },
|
|
29
|
+
body,
|
|
30
|
+
});
|
|
31
|
+
return response.body;
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Send a media message (image, video, audio, file)
|
|
36
|
+
*/
|
|
37
|
+
sendMediaMessage(instagramAccountId, accessToken, recipientId, mediaType, mediaUrl, replyToMessageId) {
|
|
38
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const body = {
|
|
40
|
+
recipient: { id: recipientId },
|
|
41
|
+
message: {
|
|
42
|
+
attachment: {
|
|
43
|
+
type: mediaType,
|
|
44
|
+
payload: { url: mediaUrl },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
if (replyToMessageId) {
|
|
49
|
+
body.reply_to = { mid: replyToMessageId };
|
|
50
|
+
}
|
|
51
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
52
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
53
|
+
url: `${exports.INSTAGRAM_GRAPH_API_BASE}/${instagramAccountId}/messages`,
|
|
54
|
+
queryParams: { access_token: accessToken },
|
|
55
|
+
body,
|
|
56
|
+
});
|
|
57
|
+
return response.body;
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* Send a reaction to a message
|
|
62
|
+
*/
|
|
63
|
+
sendReaction(instagramAccountId, accessToken, recipientId, messageId, emoji // Empty string to remove reaction
|
|
64
|
+
) {
|
|
65
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
const body = {
|
|
67
|
+
recipient: { id: recipientId },
|
|
68
|
+
sender_action: emoji ? 'react' : 'unreact',
|
|
69
|
+
payload: Object.assign({ message_id: messageId }, (emoji ? { reaction: emoji } : {})),
|
|
70
|
+
};
|
|
71
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
72
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
73
|
+
url: `${exports.INSTAGRAM_GRAPH_API_BASE}/${instagramAccountId}/messages`,
|
|
74
|
+
queryParams: { access_token: accessToken },
|
|
75
|
+
body,
|
|
76
|
+
});
|
|
77
|
+
return response.body;
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Get user profile information
|
|
82
|
+
*/
|
|
83
|
+
getUserProfile(accessToken, userId) {
|
|
84
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
85
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
86
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
87
|
+
url: `${exports.INSTAGRAM_GRAPH_API_BASE}/${userId}`,
|
|
88
|
+
queryParams: {
|
|
89
|
+
access_token: accessToken,
|
|
90
|
+
fields: 'id,username,name,profile_picture_url',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
return response.body;
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
/**
|
|
97
|
+
* Download media from Instagram CDN
|
|
98
|
+
*/
|
|
99
|
+
downloadMedia(accessToken, mediaId) {
|
|
100
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
102
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
103
|
+
url: `${exports.INSTAGRAM_GRAPH_API_BASE}/${mediaId}`,
|
|
104
|
+
queryParams: {
|
|
105
|
+
access_token: accessToken,
|
|
106
|
+
fields: 'id,media_type,media_url',
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
return response.body;
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
// Normalize messaging event to consistent format
|
|
114
|
+
function normalizeMessagingEvent(messaging) {
|
|
115
|
+
var _a, _b, _c, _d;
|
|
116
|
+
const base = {
|
|
117
|
+
senderId: ((_a = messaging.sender) === null || _a === void 0 ? void 0 : _a.id) || '',
|
|
118
|
+
recipientId: ((_b = messaging.recipient) === null || _b === void 0 ? void 0 : _b.id) || '',
|
|
119
|
+
timestamp: messaging.timestamp,
|
|
120
|
+
};
|
|
121
|
+
// Handle reaction events
|
|
122
|
+
if (messaging.reaction) {
|
|
123
|
+
return Object.assign(Object.assign({}, base), { type: 'reaction', messageId: messaging.reaction.mid, reaction: {
|
|
124
|
+
emoji: messaging.reaction.emoji || '',
|
|
125
|
+
action: messaging.reaction.action,
|
|
126
|
+
} });
|
|
127
|
+
}
|
|
128
|
+
// Handle media attachments
|
|
129
|
+
if (((_c = messaging.message) === null || _c === void 0 ? void 0 : _c.attachments) && ((_d = messaging.message) === null || _d === void 0 ? void 0 : _d.attachments.length) > 0) {
|
|
130
|
+
return Object.assign(Object.assign({}, base), { type: 'media', messageId: messaging.message.mid, attachments: messaging.message.attachments.map(att => ({
|
|
131
|
+
type: att.type,
|
|
132
|
+
url: att.payload.url || att.payload.reel_url,
|
|
133
|
+
})) });
|
|
134
|
+
}
|
|
135
|
+
// Handle message events
|
|
136
|
+
if (messaging.message) {
|
|
137
|
+
return Object.assign(Object.assign({}, base), { type: 'text', messageId: messaging.message.mid, text: messaging.message.text });
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
// Re-export token service
|
|
142
|
+
var token_service_1 = require("./token-service");
|
|
143
|
+
Object.defineProperty(exports, "instagramTokenService", { enumerable: true, get: function () { return token_service_1.instagramTokenService; } });
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/common/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { InstagramBusinessAuthValue } from '../auth/instagram-business.auth';
|
|
2
|
+
export interface TokenRefreshResult {
|
|
3
|
+
accessToken: string;
|
|
4
|
+
expiresIn: number;
|
|
5
|
+
expiresAt: Date;
|
|
6
|
+
}
|
|
7
|
+
export interface TokenServiceContext {
|
|
8
|
+
auth: InstagramBusinessAuthValue;
|
|
9
|
+
server: {
|
|
10
|
+
apiUrl: string;
|
|
11
|
+
publicUrl: string;
|
|
12
|
+
token: string;
|
|
13
|
+
};
|
|
14
|
+
project: {
|
|
15
|
+
id: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare const instagramTokenService: {
|
|
19
|
+
/**
|
|
20
|
+
* Get valid access token, refreshing if necessary and updating the connection in DB
|
|
21
|
+
* This is the main entry point - call this before every API request
|
|
22
|
+
*/
|
|
23
|
+
getValidToken(context: TokenServiceContext): Promise<{
|
|
24
|
+
accessToken: string;
|
|
25
|
+
wasRefreshed: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Refresh long-lived access token via Instagram API
|
|
29
|
+
* Tokens are valid for 60 days, can refresh when at least 24 hours old
|
|
30
|
+
*/
|
|
31
|
+
refreshToken(currentToken: string): Promise<TokenRefreshResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Fetch the full connection from the database via worker API
|
|
34
|
+
* Returns the complete AppConnection including displayName
|
|
35
|
+
*/
|
|
36
|
+
fetchConnection(server: TokenServiceContext["server"], projectId: string, externalId: string): Promise<{
|
|
37
|
+
displayName: string;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Update the connection in the database via server API
|
|
41
|
+
* Uses upsert endpoint which matches by externalId and updates existing connection
|
|
42
|
+
*/
|
|
43
|
+
updateConnectionInDatabase(context: TokenServiceContext, refreshedToken: TokenRefreshResult): Promise<void>;
|
|
44
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.instagramTokenService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
6
|
+
const shared_1 = require("@activepieces/shared");
|
|
7
|
+
const DEFAULT_REFRESH_THRESHOLD_DAYS = 10;
|
|
8
|
+
const PIECE_NAME = '@skillful-ai/piece-skai-instagram-business';
|
|
9
|
+
exports.instagramTokenService = {
|
|
10
|
+
/**
|
|
11
|
+
* Get valid access token, refreshing if necessary and updating the connection in DB
|
|
12
|
+
* This is the main entry point - call this before every API request
|
|
13
|
+
*/
|
|
14
|
+
getValidToken(context) {
|
|
15
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
var _a;
|
|
17
|
+
const { auth } = context;
|
|
18
|
+
const thresholdDays = (_a = auth.refreshThresholdDays) !== null && _a !== void 0 ? _a : DEFAULT_REFRESH_THRESHOLD_DAYS;
|
|
19
|
+
// Check if token has expiration info
|
|
20
|
+
if (!auth.tokenExpiresAt) {
|
|
21
|
+
console.log('[Instagram Token Service] No token expiration info, using current token');
|
|
22
|
+
return { accessToken: auth.accessToken, wasRefreshed: false };
|
|
23
|
+
}
|
|
24
|
+
const expiresAt = new Date(auth.tokenExpiresAt);
|
|
25
|
+
const daysUntilExpiry = (expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24);
|
|
26
|
+
// Check if expired
|
|
27
|
+
if (daysUntilExpiry <= 0) {
|
|
28
|
+
throw new Error(`Instagram token has expired (expired ${Math.abs(Math.round(daysUntilExpiry))} days ago). ` +
|
|
29
|
+
`Please reconnect your Instagram account.`);
|
|
30
|
+
}
|
|
31
|
+
// Check if refresh needed
|
|
32
|
+
if (daysUntilExpiry > thresholdDays) {
|
|
33
|
+
console.log(`[Instagram Token Service] Token valid, expires in ${Math.round(daysUntilExpiry)} days`);
|
|
34
|
+
return { accessToken: auth.accessToken, wasRefreshed: false };
|
|
35
|
+
}
|
|
36
|
+
// Token needs refresh
|
|
37
|
+
console.log(`[Instagram Token Service] Token expires in ${Math.round(daysUntilExpiry)} days, attempting refresh...`);
|
|
38
|
+
try {
|
|
39
|
+
const refreshed = yield this.refreshToken(auth.accessToken);
|
|
40
|
+
// Update the connection in the database via server API
|
|
41
|
+
yield this.updateConnectionInDatabase(context, refreshed);
|
|
42
|
+
console.log(`[Instagram Token Service] Token refreshed, new expiration: ${refreshed.expiresAt.toISOString()}`);
|
|
43
|
+
return { accessToken: refreshed.accessToken, wasRefreshed: true };
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error('[Instagram Token Service] Failed to refresh token:', error.message);
|
|
47
|
+
// If refresh fails but token not yet expired, continue with current token
|
|
48
|
+
if (daysUntilExpiry > 0) {
|
|
49
|
+
console.log('[Instagram Token Service] Using current token despite refresh failure');
|
|
50
|
+
return { accessToken: auth.accessToken, wasRefreshed: false };
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* Refresh long-lived access token via Instagram API
|
|
58
|
+
* Tokens are valid for 60 days, can refresh when at least 24 hours old
|
|
59
|
+
*/
|
|
60
|
+
refreshToken(currentToken) {
|
|
61
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
64
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
65
|
+
url: 'https://graph.instagram.com/refresh_access_token',
|
|
66
|
+
queryParams: {
|
|
67
|
+
grant_type: 'ig_refresh_token',
|
|
68
|
+
access_token: currentToken,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
if (response.status !== 200) {
|
|
72
|
+
throw new Error(`Failed to refresh token: ${((_b = (_a = response.body) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.message) || 'Unknown error'}`);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
accessToken: response.body.access_token,
|
|
76
|
+
expiresIn: response.body.expires_in, // seconds (5184000 = 60 days)
|
|
77
|
+
expiresAt: new Date(Date.now() + response.body.expires_in * 1000),
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* Fetch the full connection from the database via worker API
|
|
83
|
+
* Returns the complete AppConnection including displayName
|
|
84
|
+
*/
|
|
85
|
+
fetchConnection(server, projectId, externalId) {
|
|
86
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
var _a, _b;
|
|
88
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
89
|
+
method: pieces_common_1.HttpMethod.GET,
|
|
90
|
+
url: `${server.apiUrl}v1/worker/app-connections/${encodeURIComponent(externalId)}`,
|
|
91
|
+
queryParams: {
|
|
92
|
+
projectId,
|
|
93
|
+
},
|
|
94
|
+
authentication: {
|
|
95
|
+
type: pieces_common_1.AuthenticationType.BEARER_TOKEN,
|
|
96
|
+
token: server.token,
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
if (response.status !== 200) {
|
|
100
|
+
throw new Error(`Failed to fetch connection: ${((_b = (_a = response.body) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.message) || response.status}`);
|
|
101
|
+
}
|
|
102
|
+
return response.body;
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
/**
|
|
106
|
+
* Update the connection in the database via server API
|
|
107
|
+
* Uses upsert endpoint which matches by externalId and updates existing connection
|
|
108
|
+
*/
|
|
109
|
+
updateConnectionInDatabase(context, refreshedToken) {
|
|
110
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
var _a, _b, _c;
|
|
112
|
+
const { auth, server, project } = context;
|
|
113
|
+
const externalId = `instagram_user_${auth.userId}`;
|
|
114
|
+
// Fetch the full connection to get displayName
|
|
115
|
+
const existingConnection = yield this.fetchConnection(server, project.id, externalId);
|
|
116
|
+
const requestBody = {
|
|
117
|
+
externalId,
|
|
118
|
+
displayName: existingConnection.displayName,
|
|
119
|
+
pieceName: PIECE_NAME,
|
|
120
|
+
projectId: project.id,
|
|
121
|
+
type: shared_1.AppConnectionType.CUSTOM_AUTH,
|
|
122
|
+
value: {
|
|
123
|
+
type: shared_1.AppConnectionType.CUSTOM_AUTH,
|
|
124
|
+
props: {
|
|
125
|
+
accessToken: refreshedToken.accessToken,
|
|
126
|
+
instagramAccountId: auth.instagramAccountId,
|
|
127
|
+
instagramUsername: auth.instagramUsername,
|
|
128
|
+
userId: auth.userId,
|
|
129
|
+
tokenExpiresAt: refreshedToken.expiresAt.toISOString(),
|
|
130
|
+
refreshThresholdDays: (_a = auth.refreshThresholdDays) !== null && _a !== void 0 ? _a : DEFAULT_REFRESH_THRESHOLD_DAYS,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
const response = yield pieces_common_1.httpClient.sendRequest({
|
|
135
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
136
|
+
url: `${server.apiUrl}v1/app-connections`,
|
|
137
|
+
authentication: {
|
|
138
|
+
type: pieces_common_1.AuthenticationType.BEARER_TOKEN,
|
|
139
|
+
token: server.token,
|
|
140
|
+
},
|
|
141
|
+
body: requestBody,
|
|
142
|
+
});
|
|
143
|
+
if (response.status !== 201 && response.status !== 200) {
|
|
144
|
+
throw new Error(`Failed to update connection in database: ${((_c = (_b = response.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.message) || response.status}`);
|
|
145
|
+
}
|
|
146
|
+
console.log('[Instagram Token Service] Connection updated in database with refreshed token');
|
|
147
|
+
});
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=token-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-service.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/common/token-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TriggerStrategy } from '@activepieces/pieces-framework';
|
|
2
|
+
export declare const newInstagramMessage: import("@activepieces/pieces-framework").ITrigger<TriggerStrategy.WEBHOOK, import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
3
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
4
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
5
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
6
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
7
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
8
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
9
|
+
}>, {}> | import("@activepieces/pieces-framework").ITrigger<TriggerStrategy.POLLING, import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
10
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
11
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
12
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
13
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
14
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
15
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
16
|
+
}>, {}> | import("@activepieces/pieces-framework").ITrigger<TriggerStrategy.APP_WEBHOOK, import("@activepieces/pieces-framework").CustomAuthProperty<{
|
|
17
|
+
accessToken: import("@activepieces/pieces-framework").SecretTextProperty<true>;
|
|
18
|
+
instagramAccountId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
19
|
+
instagramUsername: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
20
|
+
userId: import("@activepieces/pieces-framework").ShortTextProperty<true>;
|
|
21
|
+
tokenExpiresAt: import("@activepieces/pieces-framework").ShortTextProperty<false>;
|
|
22
|
+
refreshThresholdDays: import("@activepieces/pieces-framework").NumberProperty<false>;
|
|
23
|
+
}>, {}>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.newInstagramMessage = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const pieces_framework_1 = require("@activepieces/pieces-framework");
|
|
6
|
+
const pieces_common_1 = require("@activepieces/pieces-common");
|
|
7
|
+
const instagram_business_auth_1 = require("../auth/instagram-business.auth");
|
|
8
|
+
const common_1 = require("../common");
|
|
9
|
+
exports.newInstagramMessage = (0, pieces_framework_1.createTrigger)({
|
|
10
|
+
auth: instagram_business_auth_1.instagramBusinessAuth,
|
|
11
|
+
name: 'new_instagram_message',
|
|
12
|
+
displayName: 'New Message',
|
|
13
|
+
description: 'Triggers on new Instagram messages, reactions, and events',
|
|
14
|
+
type: pieces_framework_1.TriggerStrategy.APP_WEBHOOK,
|
|
15
|
+
props: {},
|
|
16
|
+
sampleData: {
|
|
17
|
+
senderId: '1234567890123456',
|
|
18
|
+
recipientId: '9876543210987654',
|
|
19
|
+
timestamp: 1703865600000,
|
|
20
|
+
type: 'text',
|
|
21
|
+
messageId: 'aWdGZAA...',
|
|
22
|
+
text: 'Hello! This is a sample message.',
|
|
23
|
+
attachments: null,
|
|
24
|
+
reaction: null,
|
|
25
|
+
},
|
|
26
|
+
onEnable(context) {
|
|
27
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
const auth = context.auth;
|
|
29
|
+
// Register this flow to receive events for this Instagram account
|
|
30
|
+
// The server's webhook controller routes events by recipient.id (Instagram Account ID)
|
|
31
|
+
context.app.createListeners({
|
|
32
|
+
events: ['new_instagram_message'],
|
|
33
|
+
identifierValue: auth.instagramAccountId,
|
|
34
|
+
});
|
|
35
|
+
// Subscribe to webhook fields via Instagram API
|
|
36
|
+
// This tells Instagram to send webhooks to your configured URL
|
|
37
|
+
try {
|
|
38
|
+
yield pieces_common_1.httpClient.sendRequest({
|
|
39
|
+
method: pieces_common_1.HttpMethod.POST,
|
|
40
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${auth.instagramAccountId}/subscribed_apps`,
|
|
41
|
+
queryParams: {
|
|
42
|
+
access_token: auth.accessToken,
|
|
43
|
+
subscribed_fields: 'messages,message_reactions',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
console.log(`[Instagram Trigger] Subscribed to webhooks for account ${auth.instagramAccountId}`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error(`[Instagram Trigger] Failed to subscribe to webhooks: ${error.message}`);
|
|
50
|
+
// Don't fail the trigger enable - the subscription might already exist
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
onDisable(context) {
|
|
55
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const auth = context.auth;
|
|
57
|
+
// Unsubscribe from webhook fields
|
|
58
|
+
try {
|
|
59
|
+
yield pieces_common_1.httpClient.sendRequest({
|
|
60
|
+
method: pieces_common_1.HttpMethod.DELETE,
|
|
61
|
+
url: `${common_1.INSTAGRAM_GRAPH_API_BASE}/${auth.instagramAccountId}/subscribed_apps`,
|
|
62
|
+
queryParams: {
|
|
63
|
+
access_token: auth.accessToken,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
console.log(`[Instagram Trigger] Unsubscribed from webhooks for account ${auth.instagramAccountId}`);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error(`[Instagram Trigger] Failed to unsubscribe from webhooks: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
run(context) {
|
|
74
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
const payload = context.payload;
|
|
76
|
+
const messaging = payload === null || payload === void 0 ? void 0 : payload.body;
|
|
77
|
+
if (!messaging) {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const normalizedMessage = (0, common_1.normalizeMessagingEvent)(messaging);
|
|
81
|
+
if (!normalizedMessage) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
return [normalizedMessage];
|
|
85
|
+
});
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=new-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-message.js","sourceRoot":"","sources":["../../../../../../../../packages/pieces/custom/skai-instagram-business/src/lib/triggers/new-message.ts"],"names":[],"mappings":";;;;AAAA,qEAAgF;AAChF,+DAAqE;AACrE,6EAAoG;AACpG,sCAAkG;AAGrF,QAAA,mBAAmB,GAAG,IAAA,gCAAa,EAAC;IAC7C,IAAI,EAAE,+CAAqB;IAC3B,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,2DAA2D;IACxE,IAAI,EAAE,kCAAe,CAAC,WAAW;IACjC,KAAK,EAAE,EAAE;IACT,UAAU,EAAE;QACR,QAAQ,EAAE,kBAAkB;QAC5B,WAAW,EAAE,kBAAkB;QAC/B,SAAS,EAAE,aAAa;QACxB,IAAI,EAAE,MAAM;QACZ,SAAS,EAAE,YAAY;QACvB,IAAI,EAAE,kCAAkC;QACxC,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE,IAAI;KACjB;IACK,QAAQ,CAAC,OAAO;;YAClB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAkC,CAAC;YAExD,kEAAkE;YAClE,uFAAuF;YACvF,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;gBACxB,MAAM,EAAE,CAAC,uBAAuB,CAAC;gBACjC,eAAe,EAAE,IAAI,CAAC,kBAAkB;aAC3C,CAAC,CAAC;YAEH,gDAAgD;YAChD,+DAA+D;YAC/D,IAAI,CAAC;gBACD,MAAM,0BAAU,CAAC,WAAW,CAAC;oBACzB,MAAM,EAAE,0BAAU,CAAC,IAAI;oBACvB,GAAG,EAAE,GAAG,iCAAwB,IAAI,IAAI,CAAC,kBAAkB,kBAAkB;oBAC7E,WAAW,EAAE;wBACT,YAAY,EAAE,IAAI,CAAC,WAAW;wBAC9B,iBAAiB,EAAE,4BAA4B;qBAClD;iBACJ,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,0DAA0D,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;YACrG,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,wDAAwD,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACvF,uEAAuE;YAC3E,CAAC;QACL,CAAC;KAAA;IACK,SAAS,CAAC,OAAO;;YACnB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAkC,CAAC;YAExD,kCAAkC;YAClC,IAAI,CAAC;gBACD,MAAM,0BAAU,CAAC,WAAW,CAAC;oBACzB,MAAM,EAAE,0BAAU,CAAC,MAAM;oBACzB,GAAG,EAAE,GAAG,iCAAwB,IAAI,IAAI,CAAC,kBAAkB,kBAAkB;oBAC7E,WAAW,EAAE;wBACT,YAAY,EAAE,IAAI,CAAC,WAAW;qBACjC;iBACJ,CAAC,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,8DAA8D,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;YACzG,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,4DAA4D,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/F,CAAC;QACL,CAAC;KAAA;IACK,GAAG,CAAC,OAAO;;YACb,MAAM,OAAO,GAAG,OAAO,CAAC,OAAc,CAAC;YACvC,MAAM,SAAS,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAA0B,CAAC;YACtD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACb,OAAO,EAAE,CAAC;YACd,CAAC;YACD,MAAM,iBAAiB,GAAG,IAAA,gCAAuB,EAAC,SAAS,CAAC,CAAC;YAC7D,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACrB,OAAO,EAAE,CAAC;YACd,CAAC;YACD,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC/B,CAAC;KAAA;CACJ,CAAC,CAAC"}
|