@peopl-health/nexus 1.0.3 → 1.1.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 +123 -0
- package/examples/basic-usage.js +22 -77
- package/lib/controllers/assistantController.js +168 -0
- package/lib/controllers/conversationController.js +582 -0
- package/lib/controllers/mediaController.js +105 -0
- package/lib/controllers/messageController.js +218 -0
- package/lib/controllers/templateController.js +631 -0
- package/lib/index.js +8 -6
- package/lib/routes/index.js +87 -0
- package/lib/utils/index.js +24 -11
- package/lib/utils/mongoAuthConfig.js +13 -3
- package/lib/utils/twilioHelper.js +0 -2
- package/lib/utils/whatsappHelper.js +0 -8
- package/package.json +14 -9
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const { ScheduledMessage } = require('../models/agendaMessageModel.js');
|
|
2
|
+
|
|
3
|
+
const { getRecordByFilter } = require('../services/airtableService.js');
|
|
4
|
+
const { sendScheduledMessage } = require('../services/whatsappService.js');
|
|
5
|
+
|
|
6
|
+
const moment = require('moment-timezone');
|
|
7
|
+
|
|
8
|
+
const sendMessageController = async (req, res) => {
|
|
9
|
+
const {
|
|
10
|
+
fileUrl,
|
|
11
|
+
message,
|
|
12
|
+
fileType,
|
|
13
|
+
code,
|
|
14
|
+
sendTime = new Date(),
|
|
15
|
+
timeZone = 'Etc/GMT',
|
|
16
|
+
hidePreview = false,
|
|
17
|
+
contentSid = null,
|
|
18
|
+
variables = null
|
|
19
|
+
} = req.body || {};
|
|
20
|
+
const author = process.env.USER_DB_MONGO;
|
|
21
|
+
const sendMoment = sendTime ? moment.tz(sendTime, timeZone) + 2500 : new Date();
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const scheduledMessage = new ScheduledMessage({
|
|
25
|
+
fileUrl,
|
|
26
|
+
message,
|
|
27
|
+
fileType,
|
|
28
|
+
timeZone: timeZone === '' ? null : timeZone,
|
|
29
|
+
sendTime: sendMoment,
|
|
30
|
+
contentSid: contentSid,
|
|
31
|
+
hidePreview,
|
|
32
|
+
code,
|
|
33
|
+
author,
|
|
34
|
+
extraDelay: 0,
|
|
35
|
+
variables
|
|
36
|
+
});
|
|
37
|
+
await scheduledMessage.save();
|
|
38
|
+
console.log(scheduledMessage);
|
|
39
|
+
const sentMessage = await sendScheduledMessage(scheduledMessage);
|
|
40
|
+
res.status(200).json({
|
|
41
|
+
status: 200,
|
|
42
|
+
response: 'Message scheduled to be sent once!',
|
|
43
|
+
messageId: sentMessage ? sentMessage.sid : null
|
|
44
|
+
});
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error('Error scheduling individual message:', err.message);
|
|
47
|
+
res.status(500).json({ status: false, error: err.message });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const sendBulkMessageController = async (req, res) => {
|
|
52
|
+
const {
|
|
53
|
+
fileUrl,
|
|
54
|
+
message,
|
|
55
|
+
fileType,
|
|
56
|
+
codes,
|
|
57
|
+
sendTime = new Date(),
|
|
58
|
+
timeZone = 'Etc/GMT',
|
|
59
|
+
hidePreview = false,
|
|
60
|
+
contentSid = null,
|
|
61
|
+
variables = null
|
|
62
|
+
} = req.body || {};
|
|
63
|
+
const author = process.env.USER_DB_MONGO;
|
|
64
|
+
const sendMoment = sendTime ? moment.tz(sendTime, timeZone) + 20*1000 : new Date();
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
let numSend = 0;
|
|
68
|
+
let extraDelay = 0;
|
|
69
|
+
let curMessage = message;
|
|
70
|
+
const scheduledMessages = [];
|
|
71
|
+
for (const code of codes) {
|
|
72
|
+
const scheduledMessage = new ScheduledMessage({
|
|
73
|
+
fileUrl,
|
|
74
|
+
message: curMessage,
|
|
75
|
+
fileType,
|
|
76
|
+
timeZone: timeZone === '' ? null : timeZone,
|
|
77
|
+
sendTime: new Date(sendMoment + extraDelay),
|
|
78
|
+
contentSid: contentSid,
|
|
79
|
+
hidePreview,
|
|
80
|
+
code,
|
|
81
|
+
author,
|
|
82
|
+
extraDelay,
|
|
83
|
+
variables
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Add to scheduledMessages for both saving and scheduling
|
|
87
|
+
scheduledMessages.push(scheduledMessage);
|
|
88
|
+
|
|
89
|
+
// Increment delay and message counter
|
|
90
|
+
extraDelay += Math.floor(Math.random() * 5001) + 5000;
|
|
91
|
+
numSend += 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Schedule all messages with Agenda in parallel
|
|
95
|
+
const sentMessages = await Promise.all(
|
|
96
|
+
scheduledMessages.map(async (message) => {
|
|
97
|
+
const savedMessage = await ScheduledMessage.create(message);
|
|
98
|
+
return sendScheduledMessage(savedMessage);
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
console.log(`Send bulk of ${numSend} messages`);
|
|
103
|
+
|
|
104
|
+
// Extract message IDs
|
|
105
|
+
const messageIds = sentMessages.map(msg => msg ? msg.sid : null).filter(id => id !== null);
|
|
106
|
+
|
|
107
|
+
res.status(200).json({
|
|
108
|
+
status: true,
|
|
109
|
+
response: 'Bulk message sent',
|
|
110
|
+
messageIds: messageIds
|
|
111
|
+
});
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.log(err.message);
|
|
114
|
+
res.status(500).send(err.message);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const sendBulkMessageAirtableController = async (req, res) => {
|
|
119
|
+
const {
|
|
120
|
+
fileUrl,
|
|
121
|
+
message,
|
|
122
|
+
fileType,
|
|
123
|
+
baseId,
|
|
124
|
+
tableName,
|
|
125
|
+
columnPhone,
|
|
126
|
+
sendTime = new Date(),
|
|
127
|
+
timeZone = 'Etc/GMT',
|
|
128
|
+
hidePreview = false,
|
|
129
|
+
contentSid = null,
|
|
130
|
+
condition = '1',
|
|
131
|
+
variables = null
|
|
132
|
+
} = req.body || {};
|
|
133
|
+
const author = process.env.USER_DB_MONGO;
|
|
134
|
+
const sendMoment = sendTime ? moment.tz(sendTime, timeZone) + 20*1000 : new Date();
|
|
135
|
+
|
|
136
|
+
const regex = /\[(.*?)\]/g;
|
|
137
|
+
const envVariables = [];
|
|
138
|
+
let match;
|
|
139
|
+
while ((match = regex.exec(message)) !== null) {
|
|
140
|
+
envVariables.push(match[1]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const rows = await getRecordByFilter(baseId, tableName, condition);
|
|
145
|
+
let extraDelay = 0;
|
|
146
|
+
let curMessage = message;
|
|
147
|
+
const sentPhones = new Set();
|
|
148
|
+
const scheduledMessages = [];
|
|
149
|
+
|
|
150
|
+
for (const row of rows) {
|
|
151
|
+
let customMessage = curMessage;
|
|
152
|
+
|
|
153
|
+
for (const envVar of envVariables) {
|
|
154
|
+
let value = row[envVar];
|
|
155
|
+
if (Array.isArray(value)) value = value[0];
|
|
156
|
+
if (value !== undefined) {
|
|
157
|
+
customMessage = customMessage.replace(`[${envVar}]`, value);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
let code = row[columnPhone];
|
|
162
|
+
if (Array.isArray(code)) code = code[0];
|
|
163
|
+
if (!code) continue;
|
|
164
|
+
if (!code.includes('@g.us')) code = `${code}@s.whatsapp.net`;
|
|
165
|
+
|
|
166
|
+
if (sentPhones.has(code)) continue;
|
|
167
|
+
sentPhones.add(code);
|
|
168
|
+
|
|
169
|
+
// Prepare message object
|
|
170
|
+
const scheduledMessage = {
|
|
171
|
+
fileUrl,
|
|
172
|
+
message: customMessage,
|
|
173
|
+
fileType,
|
|
174
|
+
timeZone: timeZone === '' ? null : timeZone,
|
|
175
|
+
sendTime: new Date(sendMoment + extraDelay),
|
|
176
|
+
contentSid: contentSid,
|
|
177
|
+
hidePreview,
|
|
178
|
+
code,
|
|
179
|
+
author,
|
|
180
|
+
variables
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Add to scheduledMessages for both saving and scheduling
|
|
184
|
+
scheduledMessages.push(scheduledMessage);
|
|
185
|
+
|
|
186
|
+
// Increment delay and message counter
|
|
187
|
+
extraDelay += Math.floor(Math.random() * 5001) + 5000;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Schedule all messages with Agenda in parallel
|
|
191
|
+
const sentMessages = await Promise.all(
|
|
192
|
+
scheduledMessages.map(async (message) => {
|
|
193
|
+
const savedMessage = await ScheduledMessage.create(message);
|
|
194
|
+
return sendScheduledMessage(savedMessage);
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
// Extract message IDs
|
|
199
|
+
const messageIds = sentMessages.map(msg => msg ? msg.sid : null).filter(id => id !== null);
|
|
200
|
+
|
|
201
|
+
console.log(`Iterate over ${rows.length} rows`);
|
|
202
|
+
|
|
203
|
+
res.status(200).json({
|
|
204
|
+
status: true,
|
|
205
|
+
response: 'Airtable message sent',
|
|
206
|
+
messageIds: messageIds
|
|
207
|
+
});
|
|
208
|
+
} catch (err) {
|
|
209
|
+
console.log(err.message);
|
|
210
|
+
res.status(500).send(err.message);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
module.exports = {
|
|
215
|
+
sendMessageController,
|
|
216
|
+
sendBulkMessageController,
|
|
217
|
+
sendBulkMessageAirtableController
|
|
218
|
+
};
|