@open-wa/wa-automate 4.25.1 → 4.26.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.
- package/dist/cli/index.js +6 -0
- package/dist/cli/integrations/chatwoot.d.ts +6 -0
- package/dist/cli/integrations/chatwoot.js +234 -0
- package/dist/cli/server.d.ts +1 -0
- package/dist/cli/server.js +7 -1
- package/dist/cli/setup.js +10 -0
- package/dist/config/puppeteer.config.js +5 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
@@ -113,6 +113,12 @@ function start() {
|
|
113
113
|
process.exit();
|
114
114
|
}
|
115
115
|
}));
|
116
|
+
if (cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.chatwootUrl) {
|
117
|
+
spinner.info('Setting Up Chatwoot handler');
|
118
|
+
spinner.info('Make sure to set up the Chatwoot inbox webhook to the following path on this process: /chatwoot');
|
119
|
+
yield server_1.setupChatwoot(cliConfig, client);
|
120
|
+
spinner.succeed('Chatwoot handler set up successfully');
|
121
|
+
}
|
116
122
|
if (cliConfig === null || cliConfig === void 0 ? void 0 : cliConfig.botPressUrl) {
|
117
123
|
spinner.info('Setting Up Botpress handler');
|
118
124
|
server_1.setupBotPressHandler(cliConfig, client);
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { Client } from '../..';
|
2
|
+
import { cliFlags } from '../server';
|
3
|
+
import { Request, Response } from "express";
|
4
|
+
export declare type expressMiddleware = (req: Request, res: Response) => Promise<Response<any, Record<string, any>>>;
|
5
|
+
export declare const chatwootMiddleware: (cliConfig: cliFlags, client: Client) => expressMiddleware;
|
6
|
+
export declare const setupChatwootOutgoingMessageHandler: (cliConfig: cliFlags, client: Client) => Promise<void>;
|
@@ -0,0 +1,234 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
13
|
+
};
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
15
|
+
exports.setupChatwootOutgoingMessageHandler = exports.chatwootMiddleware = void 0;
|
16
|
+
const axios_1 = __importDefault(require("axios"));
|
17
|
+
const chatwootMiddleware = (cliConfig, client) => {
|
18
|
+
return (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
19
|
+
const processMesssage = () => __awaiter(void 0, void 0, void 0, function* () {
|
20
|
+
const promises = [];
|
21
|
+
const { body } = req;
|
22
|
+
const m = body.conversation.messages[0];
|
23
|
+
const contact = (body.conversation.meta.sender.phone_number || "").replace('+', '');
|
24
|
+
if (body.message_type === "incoming" ||
|
25
|
+
body.private ||
|
26
|
+
body.event !== "message_created" ||
|
27
|
+
!m ||
|
28
|
+
!contact)
|
29
|
+
return;
|
30
|
+
const { attachments, content } = m;
|
31
|
+
const to = `${contact}@c.us`;
|
32
|
+
if ((attachments === null || attachments === void 0 ? void 0 : attachments.length) > 0) {
|
33
|
+
//has attachments
|
34
|
+
const [firstAttachment, ...restAttachments] = attachments;
|
35
|
+
const sendAttachment = (attachment, c) => __awaiter(void 0, void 0, void 0, function* () { return client.sendImage(to, attachment.data_url, attachment.data_url.substring(attachment.data_url.lastIndexOf('/') + 1), c || '', null, true); });
|
36
|
+
//send the text as the caption with the first message only
|
37
|
+
promises.push(sendAttachment(firstAttachment, content));
|
38
|
+
restAttachments.map(sendAttachment).map(promises.push);
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
//no attachments
|
42
|
+
if (!content)
|
43
|
+
return;
|
44
|
+
/**
|
45
|
+
* Check if this is a location message
|
46
|
+
*/
|
47
|
+
const locationMatcher = /@(\-*\d*\.*\d*\,\-*\d*\.*\d*)/g;
|
48
|
+
const [possLoc, ...restMessage] = content.split(' ');
|
49
|
+
const locArr = possLoc.match(locationMatcher);
|
50
|
+
if (locArr) {
|
51
|
+
const [lat, lng] = locArr[0].split(',');
|
52
|
+
//grab the location message
|
53
|
+
const loc = restMessage.join(' ') || '';
|
54
|
+
promises.push(client.sendLocation(to, lat, lng, loc));
|
55
|
+
}
|
56
|
+
else {
|
57
|
+
//not a location message
|
58
|
+
promises.push(client.sendText(to, content));
|
59
|
+
}
|
60
|
+
}
|
61
|
+
return yield Promise.all(promises);
|
62
|
+
});
|
63
|
+
try {
|
64
|
+
const processAndSendResult = yield processMesssage();
|
65
|
+
console.log("🚀 ~ file: chatwoot.ts ~ line 58 ~ return ~ processAndSendResult", processAndSendResult);
|
66
|
+
res.status(200).send(processAndSendResult);
|
67
|
+
}
|
68
|
+
catch (error) {
|
69
|
+
console.log("🚀 ~ file: chatwoot.ts ~ line 62 ~ return ~ error", error);
|
70
|
+
res.status(400).send(error);
|
71
|
+
}
|
72
|
+
return;
|
73
|
+
});
|
74
|
+
};
|
75
|
+
exports.chatwootMiddleware = chatwootMiddleware;
|
76
|
+
const setupChatwootOutgoingMessageHandler = (cliConfig, client) => __awaiter(void 0, void 0, void 0, function* () {
|
77
|
+
const u = cliConfig.chatwootUrl; //e.g `"localhost:3000/api/v1/accounts/3"
|
78
|
+
const api_access_token = cliConfig.chatwootApiAccessToken;
|
79
|
+
const _u = new URL(u);
|
80
|
+
const origin = _u.origin;
|
81
|
+
const port = _u.port || 80;
|
82
|
+
const accountId = u.match(/accounts\/\d*/g) && u.match(/accounts\/\d*/g)[0].replace('accounts/', '');
|
83
|
+
const resolvedInbox = u.match(/inboxes\/\d*/g) && u.match(/inboxes\/\d*/g)[0].replace('inboxes/', '');
|
84
|
+
console.log("🚀 ~ file: chatwoot.ts ~ line 136 ~ resolvedInbox", resolvedInbox);
|
85
|
+
const cwReq = (path, method, data) => {
|
86
|
+
console.log(`${origin}/api/v1/accounts/${accountId}/${path}`, method, data);
|
87
|
+
return axios_1.default({
|
88
|
+
method,
|
89
|
+
data,
|
90
|
+
url: `${origin}/api/v1/accounts/${accountId}/${path}`,
|
91
|
+
headers: {
|
92
|
+
api_access_token
|
93
|
+
}
|
94
|
+
});
|
95
|
+
};
|
96
|
+
const contactReg = {
|
97
|
+
//WID : chatwoot contact ID
|
98
|
+
"example@c.us": "1"
|
99
|
+
};
|
100
|
+
const convoReg = {
|
101
|
+
//WID : chatwoot conversation ID
|
102
|
+
"example@c.us": "1"
|
103
|
+
};
|
104
|
+
const { data: get_inbox } = yield cwReq(`inboxes/${resolvedInbox}`, 'get');
|
105
|
+
// const inboxId = `openwa_${sessionId}`
|
106
|
+
/**
|
107
|
+
* Get the inbox and test it.
|
108
|
+
*/
|
109
|
+
if (!((get_inbox === null || get_inbox === void 0 ? void 0 : get_inbox.webhook_url) || "").includes("/chatwoot"))
|
110
|
+
console.log("Please set the chatwoot inbox webhook to this sessions URL with path /chatwoot");
|
111
|
+
/**
|
112
|
+
* Get Contacts and conversations
|
113
|
+
*/
|
114
|
+
const searchContact = (number) => __awaiter(void 0, void 0, void 0, function* () {
|
115
|
+
try {
|
116
|
+
const n = number.replace('@c.us', '');
|
117
|
+
const { data } = yield cwReq(`contacts/search?q=${n}&sort=phone_number`, 'get');
|
118
|
+
if (data.payload.length) {
|
119
|
+
return data.payload.find(x => (x.phone_number || "").includes(n)) || false;
|
120
|
+
}
|
121
|
+
else
|
122
|
+
false;
|
123
|
+
}
|
124
|
+
catch (error) {
|
125
|
+
return;
|
126
|
+
}
|
127
|
+
});
|
128
|
+
const getContactConversation = (number) => __awaiter(void 0, void 0, void 0, function* () {
|
129
|
+
try {
|
130
|
+
const { data } = yield cwReq(`contacts/${contactReg[number]}/conversations`, 'get');
|
131
|
+
return data.payload[0];
|
132
|
+
}
|
133
|
+
catch (error) {
|
134
|
+
return;
|
135
|
+
}
|
136
|
+
});
|
137
|
+
const createConversation = (contact_id) => __awaiter(void 0, void 0, void 0, function* () {
|
138
|
+
try {
|
139
|
+
const { data } = yield cwReq(`conversations`, 'post', {
|
140
|
+
contact_id,
|
141
|
+
"inbox_id": resolvedInbox
|
142
|
+
});
|
143
|
+
return data.payload;
|
144
|
+
}
|
145
|
+
catch (error) {
|
146
|
+
return;
|
147
|
+
}
|
148
|
+
});
|
149
|
+
const createContact = (contact) => __awaiter(void 0, void 0, void 0, function* () {
|
150
|
+
try {
|
151
|
+
const { data } = yield cwReq(`contacts`, 'post', {
|
152
|
+
"identifier": contact.id,
|
153
|
+
"name": contact.formattedName || contact.id,
|
154
|
+
"phone_number": `+${contact.id.replace('@c.us', '')}`,
|
155
|
+
"avatar_url": contact.profilePicThumbObj.eurl
|
156
|
+
});
|
157
|
+
return data.payload.contact;
|
158
|
+
}
|
159
|
+
catch (error) {
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
});
|
163
|
+
const sendConversationMessage = (content, contactId, message) => __awaiter(void 0, void 0, void 0, function* () {
|
164
|
+
try {
|
165
|
+
const { data } = yield cwReq(`conversations/${convoReg[contactId]}/messages`, 'post', {
|
166
|
+
content,
|
167
|
+
"message_type": 0,
|
168
|
+
"private": false
|
169
|
+
});
|
170
|
+
return data;
|
171
|
+
}
|
172
|
+
catch (error) {
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
});
|
176
|
+
// const inboxId = s.match(/conversations\/\d*/g) && s.match(/conversations\/\d*/g)[0].replace('conversations/','')
|
177
|
+
/**
|
178
|
+
* Update the chatwoot contact and conversation registries
|
179
|
+
*/
|
180
|
+
client.onMessage((message) => __awaiter(void 0, void 0, void 0, function* () {
|
181
|
+
if (message.from.includes('g')) {
|
182
|
+
//chatwoot integration does not support group chats
|
183
|
+
return;
|
184
|
+
}
|
185
|
+
/**
|
186
|
+
* Does the contact exist in chatwoot?
|
187
|
+
*/
|
188
|
+
if (!contactReg[message.from]) {
|
189
|
+
const contact = yield searchContact(message.from);
|
190
|
+
if (contact) {
|
191
|
+
contactReg[message.from] = contact.id;
|
192
|
+
}
|
193
|
+
else {
|
194
|
+
//create the contact
|
195
|
+
contactReg[message.from] = (yield createContact(message.sender)).id;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
if (!convoReg[message.from]) {
|
199
|
+
const conversation = yield getContactConversation(message.from);
|
200
|
+
if (conversation) {
|
201
|
+
convoReg[message.from] = conversation.id;
|
202
|
+
}
|
203
|
+
else {
|
204
|
+
//create the conversation
|
205
|
+
convoReg[message.from] = (yield createConversation(contactReg[message.from])).id;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
/**
|
209
|
+
* Does the conversation exist in
|
210
|
+
*/
|
211
|
+
let text = message.body;
|
212
|
+
switch (message.type) {
|
213
|
+
case 'location':
|
214
|
+
text = `${message.lat},${message.lng}`;
|
215
|
+
break;
|
216
|
+
case 'buttons_response':
|
217
|
+
text = message.selectedButtonId;
|
218
|
+
break;
|
219
|
+
case 'document':
|
220
|
+
case 'image':
|
221
|
+
case 'audio':
|
222
|
+
case 'ptt':
|
223
|
+
case 'video':
|
224
|
+
if (message.cloudUrl)
|
225
|
+
text = `FILE:\t${message.cloudUrl}\n\nMESSAGE:\t${message.text}`;
|
226
|
+
break;
|
227
|
+
default:
|
228
|
+
text = message.body || "__UNHANDLED__";
|
229
|
+
break;
|
230
|
+
}
|
231
|
+
yield sendConversationMessage(text, message.from, message);
|
232
|
+
}));
|
233
|
+
});
|
234
|
+
exports.setupChatwootOutgoingMessageHandler = setupChatwootOutgoingMessageHandler;
|
package/dist/cli/server.d.ts
CHANGED
@@ -16,5 +16,6 @@ export declare const getCommands: () => any;
|
|
16
16
|
export declare const listListeners: () => string[];
|
17
17
|
export declare const setupMediaMiddleware: () => void;
|
18
18
|
export declare const setupTwilioCompatibleWebhook: (cliConfig: cliFlags, client: Client) => void;
|
19
|
+
export declare const setupChatwoot: (cliConfig: cliFlags, client: Client) => void;
|
19
20
|
export declare const setupBotPressHandler: (cliConfig: cliFlags, client: Client) => void;
|
20
21
|
export declare const setupSocketServer: (cliConfig: any, client: Client) => Promise<void>;
|
package/dist/cli/server.js
CHANGED
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
31
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
32
32
|
};
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
34
|
-
exports.setupSocketServer = exports.setupBotPressHandler = exports.setupTwilioCompatibleWebhook = exports.setupMediaMiddleware = exports.listListeners = exports.getCommands = exports.setupRefocusDisengageMiddleware = exports.setupSwaggerStatsMiddleware = exports.setupApiDocs = exports.setupAuthenticationLayer = exports.enableCORSRequests = exports.setUpExpressApp = exports.server = exports.app = void 0;
|
34
|
+
exports.setupSocketServer = exports.setupBotPressHandler = exports.setupChatwoot = exports.setupTwilioCompatibleWebhook = exports.setupMediaMiddleware = exports.listListeners = exports.getCommands = exports.setupRefocusDisengageMiddleware = exports.setupSwaggerStatsMiddleware = exports.setupApiDocs = exports.setupAuthenticationLayer = exports.enableCORSRequests = exports.setUpExpressApp = exports.server = exports.app = void 0;
|
35
35
|
//@ts-ignore
|
36
36
|
const express_1 = __importDefault(require("express"));
|
37
37
|
const http_1 = __importDefault(require("http"));
|
@@ -43,6 +43,7 @@ const parse_function_1 = __importDefault(require("parse-function"));
|
|
43
43
|
const __1 = require("..");
|
44
44
|
const qs_1 = __importDefault(require("qs"));
|
45
45
|
const xmlbuilder2_1 = require("xmlbuilder2");
|
46
|
+
const chatwoot_1 = require("./integrations/chatwoot");
|
46
47
|
exports.app = express_1.default();
|
47
48
|
exports.server = http_1.default.createServer(exports.app);
|
48
49
|
const trimChatId = (chatId) => chatId.replace("@c.us", "").replace("@g.us", "");
|
@@ -233,6 +234,11 @@ const setupTwilioCompatibleWebhook = (cliConfig, client) => {
|
|
233
234
|
}));
|
234
235
|
};
|
235
236
|
exports.setupTwilioCompatibleWebhook = setupTwilioCompatibleWebhook;
|
237
|
+
const setupChatwoot = (cliConfig, client) => __awaiter(void 0, void 0, void 0, function* () {
|
238
|
+
exports.app.post('/chatwoot', chatwoot_1.chatwootMiddleware(cliConfig, client));
|
239
|
+
yield chatwoot_1.setupChatwootOutgoingMessageHandler(cliConfig, client);
|
240
|
+
});
|
241
|
+
exports.setupChatwoot = setupChatwoot;
|
236
242
|
const setupBotPressHandler = (cliConfig, client) => {
|
237
243
|
const u = cliConfig.botPressUrl;
|
238
244
|
const sendBotPressMessage = (text, chatId, message) => __awaiter(void 0, void 0, void 0, function* () {
|
package/dist/cli/setup.js
CHANGED
@@ -63,6 +63,16 @@ const optionList = [{
|
|
63
63
|
type: String,
|
64
64
|
typeLabel: '{blue {underline http://localhost:5555/incoming}}',
|
65
65
|
description: "Send twillio payloads to this URL. EASY API will also parse and processes twillio response message payloads."
|
66
|
+
}, {
|
67
|
+
name: 'chatwoot-url',
|
68
|
+
type: String,
|
69
|
+
typeLabel: '{blue {underline http://localhost:3000/api/v1/accounts/3/inboxes/1}}',
|
70
|
+
description: "The URL of the specific Chatwoot inbox you set up for this session"
|
71
|
+
}, {
|
72
|
+
name: 'chatwoot-api-access-token',
|
73
|
+
type: String,
|
74
|
+
typeLabel: '{blue {underline mEEwUGEEML2ZThMm252rLg1M}}',
|
75
|
+
description: "The access token of the specific Chatwoot inbox you set up for this session"
|
66
76
|
},
|
67
77
|
{
|
68
78
|
name: 'port',
|
@@ -48,7 +48,11 @@ const puppeteerConfig = {
|
|
48
48
|
// '--no-zygote',
|
49
49
|
// '--renderer-process-limit=1',
|
50
50
|
// '--no-first-run'
|
51
|
-
'--disable-gl-drawing-for-tests'
|
51
|
+
'--disable-gl-drawing-for-tests',
|
52
|
+
//keep awake in all situations
|
53
|
+
'--disable-background-timer-throttling',
|
54
|
+
'--disable-backgrounding-occluded-windows',
|
55
|
+
'--disable-renderer-backgrounding'
|
52
56
|
]
|
53
57
|
};
|
54
58
|
exports.puppeteerConfig = puppeteerConfig;
|
package/package.json
CHANGED