@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.
@@ -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
+ };