n8n-nodes-quepasa-api-yurisilva_pro 2.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/LICENSE +21 -0
- package/README.md +599 -0
- package/dist/QuePasa/quepasa.svg +4 -0
- package/dist/credentials/QuePasaApi.credentials.d.ts +9 -0
- package/dist/credentials/QuePasaApi.credentials.js +90 -0
- package/dist/nodes/QuePasa/QuePasa.node.d.ts +5 -0
- package/dist/nodes/QuePasa/QuePasa.node.js +501 -0
- package/dist/nodes/QuePasa/descriptions/ChatDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/ChatDescription.js +90 -0
- package/dist/nodes/QuePasa/descriptions/ContactDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/ContactDescription.js +103 -0
- package/dist/nodes/QuePasa/descriptions/GroupDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/GroupDescription.js +250 -0
- package/dist/nodes/QuePasa/descriptions/MediaDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/MediaDescription.js +60 -0
- package/dist/nodes/QuePasa/descriptions/MessageDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/MessageDescription.js +286 -0
- package/dist/nodes/QuePasa/descriptions/SessionDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/SessionDescription.js +103 -0
- package/dist/nodes/QuePasa/descriptions/StatusDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/StatusDescription.js +87 -0
- package/dist/nodes/QuePasa/descriptions/WebhookDescription.d.ts +3 -0
- package/dist/nodes/QuePasa/descriptions/WebhookDescription.js +89 -0
- package/dist/tests/GenericFunctions.spec.d.ts +1 -0
- package/dist/tests/GenericFunctions.spec.js +38 -0
- package/dist/utils/GenericFunctions.d.ts +21 -0
- package/dist/utils/GenericFunctions.js +77 -0
- package/dist/utils/Validators.d.ts +34 -0
- package/dist/utils/Validators.js +75 -0
- package/package.json +72 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.quePasaApiRequest = quePasaApiRequest;
|
|
4
|
+
exports.formatPhoneNumber = formatPhoneNumber;
|
|
5
|
+
exports.validateChatId = validateChatId;
|
|
6
|
+
exports.getBinaryData = getBinaryData;
|
|
7
|
+
exports.bufferToBase64 = bufferToBase64;
|
|
8
|
+
const axios_1 = require("axios");
|
|
9
|
+
/**
|
|
10
|
+
* Faz requisição HTTP para API QuePasa
|
|
11
|
+
*/
|
|
12
|
+
async function quePasaApiRequest(method, endpoint, body = {}, qs = {}, option = {}) {
|
|
13
|
+
const credentials = await this.getCredentials('quePasaApi');
|
|
14
|
+
const options = {
|
|
15
|
+
method,
|
|
16
|
+
body,
|
|
17
|
+
qs,
|
|
18
|
+
url: `${credentials.serverUrl}${endpoint}`,
|
|
19
|
+
json: true,
|
|
20
|
+
...option,
|
|
21
|
+
};
|
|
22
|
+
// Adicionar token do header
|
|
23
|
+
const accounts = credentials.accounts;
|
|
24
|
+
if (accounts?.account?.[0]?.token) {
|
|
25
|
+
options.headers = {
|
|
26
|
+
...options.headers,
|
|
27
|
+
'X-QUEPASA-TOKEN': accounts.account[0].token,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
return await this.helpers.httpRequest(options);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof axios_1.AxiosError) {
|
|
35
|
+
throw new Error(`QuePasa API Error [${error.response?.status}]: ${error.response?.data?.message || error.message}`);
|
|
36
|
+
}
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Formata número de telefone para formato WhatsApp
|
|
42
|
+
*/
|
|
43
|
+
function formatPhoneNumber(phone, isGroup = false) {
|
|
44
|
+
// Remove caracteres não numéricos
|
|
45
|
+
const cleaned = phone.replace(/\D/g, '');
|
|
46
|
+
// Adiciona sufixo apropriado
|
|
47
|
+
const suffix = isGroup ? '@g.us' : '@s.whatsapp.net';
|
|
48
|
+
// Se já tem sufixo, retorna como está
|
|
49
|
+
if (phone.includes('@')) {
|
|
50
|
+
return phone;
|
|
51
|
+
}
|
|
52
|
+
return `${cleaned}${suffix}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Valida formato de Chat ID
|
|
56
|
+
*/
|
|
57
|
+
function validateChatId(chatId) {
|
|
58
|
+
if (!chatId || chatId.trim().length === 0) {
|
|
59
|
+
throw new Error('Chat ID is required');
|
|
60
|
+
}
|
|
61
|
+
if (!chatId.includes('@')) {
|
|
62
|
+
throw new Error('Invalid Chat ID format. Should be like: 5511999999999@s.whatsapp.net or 123456@g.us');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extrai dados binários do n8n
|
|
67
|
+
*/
|
|
68
|
+
async function getBinaryData(itemIndex, propertyName) {
|
|
69
|
+
this.helpers.assertBinaryData(itemIndex, propertyName);
|
|
70
|
+
return await this.helpers.getBinaryDataBuffer(itemIndex, propertyName);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Converte Buffer para base64
|
|
74
|
+
*/
|
|
75
|
+
function bufferToBase64(buffer, mimetype) {
|
|
76
|
+
return `data:${mimetype};base64,${buffer.toString('base64')}`;
|
|
77
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validadores para o QuePasa Node
|
|
3
|
+
*/
|
|
4
|
+
export declare class MessageValidator {
|
|
5
|
+
static validateText(text: string): void;
|
|
6
|
+
static validateChatId(chatId: string): string;
|
|
7
|
+
}
|
|
8
|
+
export declare class MediaValidator {
|
|
9
|
+
static readonly LIMITS: {
|
|
10
|
+
image: {
|
|
11
|
+
maxSize: number;
|
|
12
|
+
types: string[];
|
|
13
|
+
};
|
|
14
|
+
video: {
|
|
15
|
+
maxSize: number;
|
|
16
|
+
types: string[];
|
|
17
|
+
};
|
|
18
|
+
audio: {
|
|
19
|
+
maxSize: number;
|
|
20
|
+
types: string[];
|
|
21
|
+
};
|
|
22
|
+
document: {
|
|
23
|
+
maxSize: number;
|
|
24
|
+
types: string[];
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
static validateMedia(type: string, mimetype: string, size: number): void;
|
|
28
|
+
static formatBytes(bytes: number): string;
|
|
29
|
+
}
|
|
30
|
+
export declare class GroupValidator {
|
|
31
|
+
static validateGroupName(name: string): void;
|
|
32
|
+
static validateParticipants(participants: string[]): void;
|
|
33
|
+
static validateGroupId(groupId: string): string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Validadores para o QuePasa Node
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GroupValidator = exports.MediaValidator = exports.MessageValidator = void 0;
|
|
7
|
+
class MessageValidator {
|
|
8
|
+
static validateText(text) {
|
|
9
|
+
if (!text || text.trim().length === 0) {
|
|
10
|
+
throw new Error('Message text is required');
|
|
11
|
+
}
|
|
12
|
+
if (text.length > 4096) {
|
|
13
|
+
throw new Error('Message too long (max 4096 characters)');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
static validateChatId(chatId) {
|
|
17
|
+
let cleaned = chatId.replace(/[^\d@.]/g, '');
|
|
18
|
+
if (!cleaned.includes('@')) {
|
|
19
|
+
cleaned = `${cleaned}@s.whatsapp.net`;
|
|
20
|
+
}
|
|
21
|
+
return cleaned;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.MessageValidator = MessageValidator;
|
|
25
|
+
class MediaValidator {
|
|
26
|
+
static LIMITS = {
|
|
27
|
+
image: { maxSize: 5 * 1024 * 1024, types: ['image/jpeg', 'image/png', 'image/gif'] },
|
|
28
|
+
video: { maxSize: 16 * 1024 * 1024, types: ['video/mp4', 'video/3gpp'] },
|
|
29
|
+
audio: { maxSize: 16 * 1024 * 1024, types: ['audio/mpeg', 'audio/ogg'] },
|
|
30
|
+
document: { maxSize: 100 * 1024 * 1024, types: ['application/pdf'] },
|
|
31
|
+
};
|
|
32
|
+
static validateMedia(type, mimetype, size) {
|
|
33
|
+
const limit = this.LIMITS[type];
|
|
34
|
+
if (!limit) {
|
|
35
|
+
throw new Error(`Invalid media type: ${type}`);
|
|
36
|
+
}
|
|
37
|
+
if (size > limit.maxSize) {
|
|
38
|
+
throw new Error(`File too large. Max size for ${type}: ${this.formatBytes(limit.maxSize)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
static formatBytes(bytes) {
|
|
42
|
+
if (bytes === 0)
|
|
43
|
+
return '0 Bytes';
|
|
44
|
+
const k = 1024;
|
|
45
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
46
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
47
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.MediaValidator = MediaValidator;
|
|
51
|
+
class GroupValidator {
|
|
52
|
+
static validateGroupName(name) {
|
|
53
|
+
if (!name || name.trim().length === 0) {
|
|
54
|
+
throw new Error('Group name is required');
|
|
55
|
+
}
|
|
56
|
+
if (name.length > 100) {
|
|
57
|
+
throw new Error('Group name too long (max 100 characters)');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
static validateParticipants(participants) {
|
|
61
|
+
if (!participants || participants.length === 0) {
|
|
62
|
+
throw new Error('At least one participant is required');
|
|
63
|
+
}
|
|
64
|
+
if (participants.length > 256) {
|
|
65
|
+
throw new Error('Too many participants (max 256)');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
static validateGroupId(groupId) {
|
|
69
|
+
if (!groupId.endsWith('@g.us')) {
|
|
70
|
+
return `${groupId}@g.us`;
|
|
71
|
+
}
|
|
72
|
+
return groupId;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.GroupValidator = GroupValidator;
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-quepasa-api-yurisilva_pro",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Complete n8n integration for QuePasa WhatsApp API - 48 operations, multi-account support, 100% API v4 coverage",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"n8n",
|
|
8
|
+
"whatsapp",
|
|
9
|
+
"quepasa",
|
|
10
|
+
"whatsapp-api",
|
|
11
|
+
"automation",
|
|
12
|
+
"workflow",
|
|
13
|
+
"typescript",
|
|
14
|
+
"multi-account"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"homepage": "https://github.com/yurisilvapro/n8n-nodes-quepasa-api-yurisilva_pro",
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "Yuri Silva",
|
|
20
|
+
"email": "yuri@yurisilva.pro"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/yurisilvapro/n8n-nodes-quepasa-api-yurisilva_pro.git"
|
|
25
|
+
},
|
|
26
|
+
"main": "index.js",
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc && npm run copy:assets",
|
|
29
|
+
"copy:assets": "copyfiles -u 1 \"nodes/**/*.{png,svg,json}\" dist/",
|
|
30
|
+
"dev": "tsc --watch",
|
|
31
|
+
"format": "prettier --write \"**/*.{ts,json,md}\"",
|
|
32
|
+
"lint": "eslint . --ext .ts",
|
|
33
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
34
|
+
"test": "jest",
|
|
35
|
+
"test:watch": "jest --watch",
|
|
36
|
+
"test:coverage": "jest --coverage"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"n8n": {
|
|
42
|
+
"n8nNodesApiVersion": 1,
|
|
43
|
+
"credentials": [
|
|
44
|
+
"dist/credentials/QuePasaApi.credentials.js"
|
|
45
|
+
],
|
|
46
|
+
"nodes": [
|
|
47
|
+
"dist/nodes/QuePasa/QuePasa.node.js"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/jest": "^29.5.11",
|
|
52
|
+
"@types/node": "^20.10.6",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
|
54
|
+
"@typescript-eslint/parser": "^6.17.0",
|
|
55
|
+
"copyfiles": "^2.4.1",
|
|
56
|
+
"eslint": "^8.56.0",
|
|
57
|
+
"eslint-config-prettier": "^9.1.0",
|
|
58
|
+
"eslint-plugin-n8n-nodes-base": "^1.16.1",
|
|
59
|
+
"jest": "^29.7.0",
|
|
60
|
+
"n8n-workflow": "^1.24.0",
|
|
61
|
+
"prettier": "^3.1.1",
|
|
62
|
+
"ts-jest": "^29.1.1",
|
|
63
|
+
"typescript": "^5.3.3"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"axios": "^1.6.5",
|
|
67
|
+
"form-data": "^4.0.0"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"n8n-workflow": "*"
|
|
71
|
+
}
|
|
72
|
+
}
|