@peopl-health/nexus 1.3.1 → 1.3.2
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.
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
let downloadFileFromS3, s3;
|
|
3
|
-
try {
|
|
4
|
-
downloadFileFromS3 = require('../config/awsConfig')?.downloadFileFromS3;
|
|
5
|
-
s3 = require('../config/awsConfig')?.s3;
|
|
6
|
-
} catch (e) {
|
|
7
|
-
// AWS config not available
|
|
8
|
-
}
|
|
1
|
+
const { s3, downloadFileFromS3 } = require('../config/awsConfig');
|
|
9
2
|
const bucketName = process.env.AWS_S3_BUCKET_NAME;
|
|
10
3
|
|
|
11
4
|
|
|
@@ -24,6 +17,14 @@ const getMediaController = async (req, res) => {
|
|
|
24
17
|
});
|
|
25
18
|
}
|
|
26
19
|
|
|
20
|
+
// Validate configuration
|
|
21
|
+
if (!downloadFileFromS3 || typeof downloadFileFromS3 !== 'function') {
|
|
22
|
+
return res.status(500).json({ success: false, error: 'downloadFileFromS3 not configured. Call configureMediaController() to inject it.' });
|
|
23
|
+
}
|
|
24
|
+
if (!bucketName) {
|
|
25
|
+
return res.status(500).json({ success: false, error: 'AWS_S3_BUCKET_NAME not configured. Pass bucketName to configureMediaController() or set env.' });
|
|
26
|
+
}
|
|
27
|
+
|
|
27
28
|
let mediaKey = key;
|
|
28
29
|
|
|
29
30
|
console.log(`[MediaController] Final S3 key to fetch: ${mediaKey}`);
|
|
@@ -32,36 +33,37 @@ const getMediaController = async (req, res) => {
|
|
|
32
33
|
|
|
33
34
|
if (!fileData || !fileData.Body) {
|
|
34
35
|
console.error(`[MediaController] Media not found in S3: ${key}`);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
36
|
+
|
|
37
|
+
if (s3) {
|
|
38
|
+
try {
|
|
39
|
+
const prefix = key.split('/') [0];
|
|
40
|
+
console.log(`[MediaController] Checking S3 for objects with prefix: ${prefix}/`);
|
|
41
|
+
s3.listObjectsV2({
|
|
42
|
+
Bucket: bucketName,
|
|
43
|
+
Prefix: prefix + '/',
|
|
44
|
+
MaxKeys: 10
|
|
45
|
+
}).promise()
|
|
46
|
+
.then(listData => {
|
|
47
|
+
if (listData.Contents && listData.Contents.length > 0) {
|
|
48
|
+
console.log(`[MediaController] Found ${listData.Contents.length} objects with similar prefix:`);
|
|
49
|
+
listData.Contents.forEach(item => {
|
|
50
|
+
console.log(`[MediaController] - ${item.Key} (${item.Size} bytes)`);
|
|
51
|
+
if (item.Key.includes(key.split('/').pop().substring(0, 10))) {
|
|
52
|
+
console.log(`[MediaController] !!! POTENTIAL MATCH: ${item.Key}`);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
console.log(`[MediaController] No objects found with prefix: ${prefix}/`);
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
.catch(listErr => {
|
|
60
|
+
console.error(`[MediaController] Error listing objects: ${listErr.message}`);
|
|
61
|
+
});
|
|
62
|
+
} catch (listErr) {
|
|
63
|
+
console.error(`[MediaController] Error setting up bucket listing: ${listErr.message}`);
|
|
64
|
+
}
|
|
63
65
|
}
|
|
64
|
-
|
|
66
|
+
|
|
65
67
|
return res.status(404).json({
|
|
66
68
|
success: false,
|
|
67
69
|
error: 'Media not found in S3',
|
|
@@ -102,4 +104,4 @@ const getMediaController = async (req, res) => {
|
|
|
102
104
|
|
|
103
105
|
module.exports = {
|
|
104
106
|
getMediaController
|
|
105
|
-
};
|
|
107
|
+
};
|
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
const { Message } = require('../models/messageModel.js');
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const { sendMessage } = require('../core/NexusMessaging');
|
|
5
|
-
|
|
6
|
-
// Injectable dependencies with safe defaults
|
|
7
|
-
let injected = {
|
|
8
|
-
ScheduledMessage: null,
|
|
9
|
-
getRecordByFilter: null,
|
|
10
|
-
sendScheduledMessage: null
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
// Allow consumers to inject their model and services
|
|
14
|
-
const configureMessageController = ({ ScheduledMessage, getRecordByFilter, sendScheduledMessage } = {}) => {
|
|
15
|
-
if (ScheduledMessage) injected.ScheduledMessage = ScheduledMessage;
|
|
16
|
-
if (getRecordByFilter) injected.getRecordByFilter = getRecordByFilter;
|
|
17
|
-
if (sendScheduledMessage) injected.sendScheduledMessage = sendScheduledMessage;
|
|
18
|
-
};
|
|
2
|
+
const { ScheduledMessage } = require('../models/agendaMessageModel.js');
|
|
3
|
+
const { getRecordByFilter } = require('../services/airtableService.js');
|
|
4
|
+
const { sendMessage, sendScheduledMessage } = require('../core/NexusMessaging');
|
|
19
5
|
|
|
20
6
|
const moment = require('moment-timezone');
|
|
21
7
|
|
|
8
|
+
|
|
22
9
|
const sendMessageController = async (req, res) => {
|
|
23
10
|
const {
|
|
24
11
|
fileUrl,
|
|
@@ -31,13 +18,10 @@ const sendMessageController = async (req, res) => {
|
|
|
31
18
|
contentSid = null,
|
|
32
19
|
variables = null
|
|
33
20
|
} = req.body || {};
|
|
34
|
-
const author =
|
|
21
|
+
const author = (require('../config/runtimeConfig').get('USER_DB_MONGO'));
|
|
35
22
|
const sendMoment = sendTime ? moment.tz(sendTime, timeZone) + 2500 : new Date();
|
|
36
23
|
|
|
37
24
|
try {
|
|
38
|
-
if (!injected.ScheduledMessage || typeof injected.ScheduledMessage.create !== 'function') {
|
|
39
|
-
return res.status(500).json({ success: false, error: 'ScheduledMessage model not configured. Call configureMessageController() to inject it.' });
|
|
40
|
-
}
|
|
41
25
|
const messageData = {
|
|
42
26
|
fileUrl,
|
|
43
27
|
message,
|
|
@@ -51,7 +35,7 @@ const sendMessageController = async (req, res) => {
|
|
|
51
35
|
extraDelay: 0,
|
|
52
36
|
variables
|
|
53
37
|
};
|
|
54
|
-
await
|
|
38
|
+
await ScheduledMessage.create(messageData);
|
|
55
39
|
console.log('Sending message with data:', messageData);
|
|
56
40
|
|
|
57
41
|
const result = await sendMessage(messageData);
|
|
@@ -79,22 +63,16 @@ const sendBulkMessageController = async (req, res) => {
|
|
|
79
63
|
contentSid = null,
|
|
80
64
|
variables = null
|
|
81
65
|
} = req.body || {};
|
|
82
|
-
const author =
|
|
66
|
+
const author = (require('../config/runtimeConfig').get('USER_DB_MONGO'));
|
|
83
67
|
const sendMoment = sendTime ? moment.tz(sendTime, timeZone) + 20*1000 : new Date();
|
|
84
68
|
|
|
85
69
|
try {
|
|
86
|
-
if (!injected.ScheduledMessage || typeof injected.ScheduledMessage.create !== 'function') {
|
|
87
|
-
return res.status(500).json({ success: false, error: 'ScheduledMessage model not configured. Call configureMessageController() to inject it.' });
|
|
88
|
-
}
|
|
89
|
-
if (!injected.sendScheduledMessage || typeof injected.sendScheduledMessage !== 'function') {
|
|
90
|
-
return res.status(500).json({ success: false, error: 'sendScheduledMessage not configured. Call configureMessageController() to inject it.' });
|
|
91
|
-
}
|
|
92
70
|
let numSend = 0;
|
|
93
71
|
let extraDelay = 0;
|
|
94
72
|
let curMessage = message;
|
|
95
73
|
const scheduledMessages = [];
|
|
96
74
|
for (const code of codes) {
|
|
97
|
-
const scheduledMessage = new
|
|
75
|
+
const scheduledMessage = new ScheduledMessage({
|
|
98
76
|
fileUrl,
|
|
99
77
|
message: curMessage,
|
|
100
78
|
fileType,
|
|
@@ -119,8 +97,8 @@ const sendBulkMessageController = async (req, res) => {
|
|
|
119
97
|
// Schedule all messages with Agenda in parallel
|
|
120
98
|
const sentMessages = await Promise.all(
|
|
121
99
|
scheduledMessages.map(async (message) => {
|
|
122
|
-
const savedMessage = await
|
|
123
|
-
return
|
|
100
|
+
const savedMessage = await ScheduledMessage.create(message);
|
|
101
|
+
return sendScheduledMessage(savedMessage);
|
|
124
102
|
})
|
|
125
103
|
);
|
|
126
104
|
|
|
@@ -155,7 +133,7 @@ const sendBulkMessageAirtableController = async (req, res) => {
|
|
|
155
133
|
condition = '1',
|
|
156
134
|
variables = null
|
|
157
135
|
} = req.body || {};
|
|
158
|
-
const author =
|
|
136
|
+
const author = (require('../config/runtimeConfig').get('USER_DB_MONGO'));
|
|
159
137
|
const sendMoment = sendTime ? moment.tz(sendTime, timeZone) + 20*1000 : new Date();
|
|
160
138
|
|
|
161
139
|
const regex = /\[(.*?)\]/g;
|
|
@@ -166,16 +144,7 @@ const sendBulkMessageAirtableController = async (req, res) => {
|
|
|
166
144
|
}
|
|
167
145
|
|
|
168
146
|
try {
|
|
169
|
-
|
|
170
|
-
return res.status(500).json({ success: false, error: 'Airtable getRecordByFilter not configured. Call configureMessageController() to inject it.' });
|
|
171
|
-
}
|
|
172
|
-
if (!injected.ScheduledMessage || typeof injected.ScheduledMessage.create !== 'function') {
|
|
173
|
-
return res.status(500).json({ success: false, error: 'ScheduledMessage model not configured. Call configureMessageController() to inject it.' });
|
|
174
|
-
}
|
|
175
|
-
if (!injected.sendScheduledMessage || typeof injected.sendScheduledMessage !== 'function') {
|
|
176
|
-
return res.status(500).json({ success: false, error: 'sendScheduledMessage not configured. Call configureMessageController() to inject it.' });
|
|
177
|
-
}
|
|
178
|
-
const rows = await injected.getRecordByFilter(baseId, tableName, condition);
|
|
147
|
+
const rows = await getRecordByFilter(baseId, tableName, condition);
|
|
179
148
|
let extraDelay = 0;
|
|
180
149
|
let curMessage = message;
|
|
181
150
|
const sentPhones = new Set();
|
|
@@ -220,8 +189,8 @@ const sendBulkMessageAirtableController = async (req, res) => {
|
|
|
220
189
|
|
|
221
190
|
const sentMessages = await Promise.all(
|
|
222
191
|
scheduledMessages.map(async (message) => {
|
|
223
|
-
const savedMessage = await
|
|
224
|
-
return
|
|
192
|
+
const savedMessage = await ScheduledMessage.create(message);
|
|
193
|
+
return sendScheduledMessage(savedMessage);
|
|
225
194
|
})
|
|
226
195
|
);
|
|
227
196
|
|
|
@@ -272,6 +241,5 @@ module.exports = {
|
|
|
272
241
|
sendMessageController,
|
|
273
242
|
sendBulkMessageController,
|
|
274
243
|
sendBulkMessageAirtableController,
|
|
275
|
-
getLastInteractionController
|
|
276
|
-
configureMessageController
|
|
244
|
+
getLastInteractionController
|
|
277
245
|
};
|