n8n-nodes-whaapy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ import { IHookFunctions, IWebhookFunctions, INodeType, INodeTypeDescription, IWebhookResponseData } from 'n8n-workflow';
2
+ export declare class WhaapyTrigger implements INodeType {
3
+ description: INodeTypeDescription;
4
+ webhookMethods: {
5
+ default: {
6
+ checkExists(this: IHookFunctions): Promise<boolean>;
7
+ create(this: IHookFunctions): Promise<boolean>;
8
+ delete(this: IHookFunctions): Promise<boolean>;
9
+ };
10
+ };
11
+ webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
12
+ }
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WhaapyTrigger = void 0;
4
+ class WhaapyTrigger {
5
+ constructor() {
6
+ this.description = {
7
+ displayName: 'Whaapy Trigger',
8
+ name: 'whaapyTrigger',
9
+ icon: 'file:whaapy.svg',
10
+ group: ['trigger'],
11
+ version: 1,
12
+ subtitle: '={{$parameter["event"]}}',
13
+ description: 'Listen for Whaapy webhook events',
14
+ defaults: {
15
+ name: 'Whaapy Trigger',
16
+ },
17
+ inputs: [],
18
+ outputs: ['main'],
19
+ credentials: [
20
+ {
21
+ name: 'whaapyApi',
22
+ required: true,
23
+ },
24
+ ],
25
+ webhooks: [
26
+ {
27
+ name: 'default',
28
+ httpMethod: 'POST',
29
+ responseMode: 'onReceived',
30
+ path: 'webhook',
31
+ },
32
+ ],
33
+ properties: [
34
+ {
35
+ displayName: 'Event',
36
+ name: 'event',
37
+ type: 'options',
38
+ required: true,
39
+ default: 'message.received',
40
+ options: [
41
+ {
42
+ name: 'Message Received',
43
+ value: 'message.received',
44
+ description: 'Triggered when a new message is received',
45
+ },
46
+ {
47
+ name: 'Message Sent',
48
+ value: 'message.sent',
49
+ description: 'Triggered when a message is sent',
50
+ },
51
+ {
52
+ name: 'Message Delivered',
53
+ value: 'message.delivered',
54
+ description: 'Triggered when a message is delivered',
55
+ },
56
+ {
57
+ name: 'Message Read',
58
+ value: 'message.read',
59
+ description: 'Triggered when a message is read',
60
+ },
61
+ {
62
+ name: 'Message Failed',
63
+ value: 'message.failed',
64
+ description: 'Triggered when a message fails to send',
65
+ },
66
+ {
67
+ name: 'Conversation Created',
68
+ value: 'conversation.created',
69
+ description: 'Triggered when a new conversation is created',
70
+ },
71
+ {
72
+ name: 'Conversation Updated',
73
+ value: 'conversation.updated',
74
+ description: 'Triggered when a conversation is updated',
75
+ },
76
+ {
77
+ name: 'Conversation Handoff',
78
+ value: 'conversation.handoff',
79
+ description: 'Triggered when AI hands off to a human',
80
+ },
81
+ {
82
+ name: 'All Events',
83
+ value: '*',
84
+ description: 'Triggered for any event',
85
+ },
86
+ ],
87
+ },
88
+ {
89
+ displayName: 'Options',
90
+ name: 'options',
91
+ type: 'collection',
92
+ placeholder: 'Add Option',
93
+ default: {},
94
+ options: [
95
+ {
96
+ displayName: 'Webhook Secret',
97
+ name: 'webhookSecret',
98
+ type: 'string',
99
+ typeOptions: { password: true },
100
+ default: '',
101
+ description: 'Secret to verify webhook signatures (optional)',
102
+ },
103
+ ],
104
+ },
105
+ ],
106
+ };
107
+ this.webhookMethods = {
108
+ default: {
109
+ async checkExists() {
110
+ const webhookUrl = this.getNodeWebhookUrl('default');
111
+ const event = this.getNodeParameter('event');
112
+ const credentials = await this.getCredentials('whaapyApi');
113
+ try {
114
+ const response = await this.helpers.request({
115
+ method: 'GET',
116
+ url: `${credentials.baseUrl}/webhooks/v1`,
117
+ headers: {
118
+ Authorization: `Bearer ${credentials.apiKey}`,
119
+ },
120
+ json: true,
121
+ });
122
+ const webhooks = response.webhooks || response.data || [];
123
+ return webhooks.some((webhook) => {
124
+ var _a;
125
+ return webhook.url === webhookUrl &&
126
+ ((_a = webhook.events) === null || _a === void 0 ? void 0 : _a.includes(event));
127
+ });
128
+ }
129
+ catch (error) {
130
+ return false;
131
+ }
132
+ },
133
+ async create() {
134
+ var _a;
135
+ const webhookUrl = this.getNodeWebhookUrl('default');
136
+ const event = this.getNodeParameter('event');
137
+ const options = this.getNodeParameter('options');
138
+ const credentials = await this.getCredentials('whaapyApi');
139
+ const body = {
140
+ url: webhookUrl,
141
+ events: event === '*' ? ['*'] : [event],
142
+ };
143
+ if (options.webhookSecret) {
144
+ body.secret = options.webhookSecret;
145
+ }
146
+ try {
147
+ const response = await this.helpers.request({
148
+ method: 'POST',
149
+ url: `${credentials.baseUrl}/webhooks/v1`,
150
+ headers: {
151
+ Authorization: `Bearer ${credentials.apiKey}`,
152
+ 'Content-Type': 'application/json',
153
+ },
154
+ body,
155
+ json: true,
156
+ });
157
+ const webhookData = this.getWorkflowStaticData('node');
158
+ webhookData.webhookId = response.id || ((_a = response.webhook) === null || _a === void 0 ? void 0 : _a.id);
159
+ return true;
160
+ }
161
+ catch (error) {
162
+ return false;
163
+ }
164
+ },
165
+ async delete() {
166
+ const webhookData = this.getWorkflowStaticData('node');
167
+ const credentials = await this.getCredentials('whaapyApi');
168
+ if (!webhookData.webhookId) {
169
+ return true;
170
+ }
171
+ try {
172
+ await this.helpers.request({
173
+ method: 'DELETE',
174
+ url: `${credentials.baseUrl}/webhooks/v1/${webhookData.webhookId}`,
175
+ headers: {
176
+ Authorization: `Bearer ${credentials.apiKey}`,
177
+ },
178
+ });
179
+ delete webhookData.webhookId;
180
+ return true;
181
+ }
182
+ catch (error) {
183
+ return false;
184
+ }
185
+ },
186
+ },
187
+ };
188
+ }
189
+ async webhook() {
190
+ const req = this.getRequestObject();
191
+ const body = this.getBodyData();
192
+ const event = this.getNodeParameter('event');
193
+ // Check if the event matches
194
+ const incomingEvent = body.event || body.type;
195
+ if (event !== '*' && incomingEvent !== event) {
196
+ // Event doesn't match, return empty
197
+ return {
198
+ workflowData: [],
199
+ };
200
+ }
201
+ // Return the webhook data
202
+ return {
203
+ workflowData: [
204
+ this.helpers.returnJsonArray([
205
+ {
206
+ event: incomingEvent,
207
+ timestamp: body.timestamp || new Date().toISOString(),
208
+ data: body.data || body.payload || body,
209
+ headers: req.headers,
210
+ raw: body,
211
+ },
212
+ ]),
213
+ ],
214
+ };
215
+ }
216
+ }
217
+ exports.WhaapyTrigger = WhaapyTrigger;
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
2
+ <rect width="48" height="48" rx="8" fill="#25D366"/>
3
+ <path d="M24 8C15.163 8 8 15.163 8 24C8 27.073 8.962 29.926 10.6 32.275L8.5 39.5L16.025 37.462C18.275 38.962 20.987 39.85 23.9 39.975C32.85 40.312 40.175 33.075 39.988 24.1C39.825 16.288 32.85 8 24 8ZM32.35 29.825C32.025 30.625 30.675 31.35 29.75 31.525C29.075 31.65 28.2 31.75 25.3 30.575C21.65 29.1 19.3 25.4 19.1 25.125C18.9 24.85 17.35 22.825 17.35 20.725C17.35 18.625 18.475 17.6 18.9 17.15C19.25 16.775 19.825 16.6 20.375 16.6C20.55 16.6 20.7 16.612 20.85 16.625C21.275 16.65 21.488 16.675 21.762 17.35C22.1 18.175 22.9 20.275 23 20.475C23.1 20.675 23.175 20.925 23.05 21.2C22.925 21.475 22.838 21.6 22.638 21.825C22.438 22.05 22.25 22.225 22.05 22.475C21.862 22.7 21.65 22.938 21.875 23.363C22.1 23.788 22.888 25.075 24.05 26.1C25.538 27.413 26.75 27.825 27.238 28.025C27.588 28.175 28.013 28.138 28.25 27.875C28.55 27.538 28.913 26.988 29.288 26.45C29.55 26.075 29.888 26.025 30.275 26.175C30.663 26.325 32.75 27.35 33.175 27.563C33.6 27.775 33.875 27.875 33.975 28.05C34.088 28.25 34.088 29.125 33.762 30.125L32.35 29.825Z" fill="white"/>
4
+ </svg>
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "n8n-nodes-whaapy",
3
+ "version": "0.1.0",
4
+ "description": "n8n community node for Whaapy - WhatsApp Business API with AI",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "n8n",
8
+ "whaapy",
9
+ "whatsapp",
10
+ "whatsapp-business",
11
+ "messaging",
12
+ "automation"
13
+ ],
14
+ "license": "MIT",
15
+ "homepage": "https://whaapy.com",
16
+ "author": {
17
+ "name": "Whaapy",
18
+ "email": "support@whaapy.com"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/saymetristan/whaapy-n8n.git"
23
+ },
24
+ "engines": {
25
+ "node": ">=18.10",
26
+ "pnpm": ">=9.1"
27
+ },
28
+ "packageManager": "pnpm@9.1.4",
29
+ "main": "index.js",
30
+ "scripts": {
31
+ "preinstall": "npx only-allow pnpm",
32
+ "build": "tsc && gulp build:icons",
33
+ "dev": "tsc --watch",
34
+ "format": "prettier \"nodes/**/*.ts\" \"credentials/**/*.ts\" --write",
35
+ "lint": "eslint \"nodes/**/*.ts\" \"credentials/**/*.ts\"",
36
+ "lintfix": "eslint \"nodes/**/*.ts\" \"credentials/**/*.ts\" --fix",
37
+ "prepublishOnly": "pnpm build && eslint -c .eslintrc.prepublish.js \"nodes/**/*.ts\" \"credentials/**/*.ts\""
38
+ },
39
+ "files": [
40
+ "dist"
41
+ ],
42
+ "n8n": {
43
+ "n8nNodesApiVersion": 1,
44
+ "credentials": [
45
+ "dist/credentials/WhaapyApi.credentials.js"
46
+ ],
47
+ "nodes": [
48
+ "dist/nodes/Whaapy/Whaapy.node.js",
49
+ "dist/nodes/Whaapy/WhaapyTrigger.node.js"
50
+ ]
51
+ },
52
+ "devDependencies": {
53
+ "@typescript-eslint/parser": "^7.15.0",
54
+ "eslint": "^8.56.0",
55
+ "eslint-plugin-n8n-nodes-base": "^1.16.1",
56
+ "gulp": "^4.0.2",
57
+ "n8n-workflow": "*",
58
+ "prettier": "^3.3.2",
59
+ "typescript": "^5.5.3"
60
+ },
61
+ "peerDependencies": {
62
+ "n8n-workflow": "*"
63
+ }
64
+ }