@runnerpro/backend 1.11.6 → 1.12.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.
|
@@ -35,6 +35,12 @@ const index_2 = require("../../locale/index");
|
|
|
35
35
|
const multer_1 = __importDefault(require("multer"));
|
|
36
36
|
const axios_1 = __importDefault(require("axios"));
|
|
37
37
|
const saveResponseTime_1 = require("../saveResponseTime");
|
|
38
|
+
const sendMail_1 = require("../../sendMail");
|
|
39
|
+
const fluent_ffmpeg_1 = __importDefault(require("fluent-ffmpeg"));
|
|
40
|
+
const ffmpeg_static_1 = __importDefault(require("ffmpeg-static"));
|
|
41
|
+
const ffprobe_static_1 = __importDefault(require("ffprobe-static"));
|
|
42
|
+
fluent_ffmpeg_1.default.setFfmpegPath(ffmpeg_static_1.default);
|
|
43
|
+
fluent_ffmpeg_1.default.setFfprobePath(ffprobe_static_1.default.path);
|
|
38
44
|
const conversationRoute = (_a) => {
|
|
39
45
|
var { router } = _a, params = __rest(_a, ["router"]);
|
|
40
46
|
const uploadFile = (0, multer_1.default)({
|
|
@@ -245,10 +251,20 @@ const getPreferredLanguageForChat = ({ text, idCliente, isClient }) => __awaiter
|
|
|
245
251
|
};
|
|
246
252
|
});
|
|
247
253
|
const sendFile = (req, res, { sendNotification, firebaseMessaging, isClient, bucket }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
248
|
-
const { idCliente, type
|
|
254
|
+
const { idCliente, type } = req.body;
|
|
255
|
+
let { duration } = req.body;
|
|
249
256
|
const { userid } = req.session;
|
|
250
|
-
const [{ id: idFile }] = yield (0, index_1.query)('INSERT INTO [CHAT MESSAGE] ([ID CLIENTE], [ID SENDER], [TEXT], [MIMETYPE], [DURATION], [TYPE]) VALUES (?, ?, ?, ?, ?, ?) RETURNING [ID]', [isClient ? userid : idCliente, userid, req.file.originalname, req.file.mimetype, duration || null, type || 2]);
|
|
251
257
|
const filePath = path_1.default.join('./uploads', req.file.filename);
|
|
258
|
+
if (req.file.mimetype.includes('video')) {
|
|
259
|
+
(0, sendMail_1.sendMail)({
|
|
260
|
+
to: ['david.jimenez@runnerpro.app'],
|
|
261
|
+
subject: 'Video',
|
|
262
|
+
body: JSON.stringify(req.file),
|
|
263
|
+
title: '',
|
|
264
|
+
});
|
|
265
|
+
duration = yield getDurationFromVideo(filePath);
|
|
266
|
+
}
|
|
267
|
+
const [{ id: idFile }] = yield (0, index_1.query)('INSERT INTO [CHAT MESSAGE] ([ID CLIENTE], [ID SENDER], [TEXT], [MIMETYPE], [DURATION], [TYPE]) VALUES (?, ?, ?, ?, ?, ?) RETURNING [ID]', [isClient ? userid : idCliente, userid, req.file.originalname, req.file.mimetype, duration || null, type || 2]);
|
|
252
268
|
const fileData = fs_1.default.readFileSync(filePath);
|
|
253
269
|
const files = [];
|
|
254
270
|
if (req.file.mimetype.includes('image')) {
|
|
@@ -262,6 +278,18 @@ const sendFile = (req, res, { sendNotification, firebaseMessaging, isClient, buc
|
|
|
262
278
|
(0, index_1.err)(null, null, error, null);
|
|
263
279
|
}
|
|
264
280
|
}
|
|
281
|
+
else if (req.file.mimetype.includes('video')) {
|
|
282
|
+
// Si es vídeo, se guarda el vídeo original, la duración y un thumbnail
|
|
283
|
+
const thumbnail = yield getThumbnailFromVideo(filePath);
|
|
284
|
+
(0, sendMail_1.sendMail)({
|
|
285
|
+
to: ['david.jimenez@runnerpro.app'],
|
|
286
|
+
subject: 'Video 4',
|
|
287
|
+
body: JSON.stringify(thumbnail),
|
|
288
|
+
title: '',
|
|
289
|
+
});
|
|
290
|
+
files.push({ data: fileData, id: idFile });
|
|
291
|
+
files.push({ data: thumbnail, id: `${idFile}-thumbnail` });
|
|
292
|
+
}
|
|
265
293
|
else {
|
|
266
294
|
files.push({ data: fileData, id: idFile });
|
|
267
295
|
}
|
|
@@ -280,6 +308,47 @@ const sendFile = (req, res, { sendNotification, firebaseMessaging, isClient, buc
|
|
|
280
308
|
}
|
|
281
309
|
res.send({ idFile });
|
|
282
310
|
});
|
|
311
|
+
const getThumbnailFromVideo = (videoPath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
312
|
+
const timestamp = 10;
|
|
313
|
+
const size = '640x480';
|
|
314
|
+
const quality = 2;
|
|
315
|
+
(0, sendMail_1.sendMail)({
|
|
316
|
+
to: ['david.jimenez@runnerpro.app'],
|
|
317
|
+
subject: 'Video 2',
|
|
318
|
+
body: JSON.stringify(videoPath),
|
|
319
|
+
title: '',
|
|
320
|
+
});
|
|
321
|
+
const tempDir = path_1.default.join('./uploads');
|
|
322
|
+
const outputFilename = `thumbnail_${Date.now()}.png`;
|
|
323
|
+
const outputPath = path_1.default.join(tempDir, outputFilename);
|
|
324
|
+
(0, sendMail_1.sendMail)({
|
|
325
|
+
to: ['david.jimenez@runnerpro.app'],
|
|
326
|
+
subject: 'Video 3',
|
|
327
|
+
body: JSON.stringify({ tempDir, outputFilename, outputPath }),
|
|
328
|
+
title: '',
|
|
329
|
+
});
|
|
330
|
+
return new Promise((resolve, reject) => {
|
|
331
|
+
(0, fluent_ffmpeg_1.default)(videoPath)
|
|
332
|
+
.screenshots({
|
|
333
|
+
timestamps: [timestamp],
|
|
334
|
+
filename: outputFilename,
|
|
335
|
+
folder: tempDir,
|
|
336
|
+
size,
|
|
337
|
+
quality,
|
|
338
|
+
})
|
|
339
|
+
.on('end', () => {
|
|
340
|
+
console.log('Thumbnail generado:', outputPath);
|
|
341
|
+
resolve(outputPath);
|
|
342
|
+
})
|
|
343
|
+
.on('error', (err) => {
|
|
344
|
+
console.error('Error generando thumbnail:', err);
|
|
345
|
+
reject(err);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
const getDurationFromVideo = (filePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
350
|
+
return 10;
|
|
351
|
+
});
|
|
283
352
|
const readMessage = (req, res, { isClient }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
284
353
|
const { idCliente } = req.body;
|
|
285
354
|
yield markReadMessage({ isClient, idCliente });
|
|
@@ -140,76 +140,18 @@ const writeSheet = ({ sheetInstance, sheetName, sheetPage, cellValue, cellPositi
|
|
|
140
140
|
}
|
|
141
141
|
});
|
|
142
142
|
exports.writeSheet = writeSheet;
|
|
143
|
-
// Función para detectar si un valor es una fecha en formato DD/MM/YYYY o YYYY/MM/DD
|
|
144
|
-
const isDateString = (value) => {
|
|
145
|
-
if (typeof value !== 'string')
|
|
146
|
-
return false;
|
|
147
|
-
// Patrones para DD/MM/YYYY y YYYY/MM/DD
|
|
148
|
-
const datePatterns = [
|
|
149
|
-
/^\d{1,2}\/\d{1,2}\/\d{4}$/, // DD/MM/YYYY o D/M/YYYY
|
|
150
|
-
/^\d{4}\/\d{1,2}\/\d{1,2}$/, // YYYY/MM/DD o YYYY/M/D
|
|
151
|
-
];
|
|
152
|
-
return datePatterns.some((pattern) => pattern.test(value));
|
|
153
|
-
};
|
|
154
|
-
// Función para convertir string de fecha a objeto Date de JavaScript
|
|
155
|
-
const convertToJSDate = (dateString) => {
|
|
156
|
-
if (!isDateString(dateString))
|
|
157
|
-
return null;
|
|
158
|
-
try {
|
|
159
|
-
let day, month, year;
|
|
160
|
-
const parts = dateString.split('/');
|
|
161
|
-
if (parts[0].length === 4) {
|
|
162
|
-
// Formato YYYY/MM/DD
|
|
163
|
-
year = parseInt(parts[0]);
|
|
164
|
-
month = parseInt(parts[1]);
|
|
165
|
-
day = parseInt(parts[2]);
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
// Formato DD/MM/YYYY
|
|
169
|
-
day = parseInt(parts[0]);
|
|
170
|
-
month = parseInt(parts[1]);
|
|
171
|
-
year = parseInt(parts[2]);
|
|
172
|
-
}
|
|
173
|
-
// Crear objeto Date (mes - 1 porque Date usa 0-11 para meses)
|
|
174
|
-
const date = new Date(year, month - 1, day);
|
|
175
|
-
// Validar que sea una fecha válida
|
|
176
|
-
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
return date;
|
|
180
|
-
}
|
|
181
|
-
catch (error) {
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
143
|
const appendSheet = ({ sheetInstance, sheetName, sheetPage, cellValues, cellPositionAppend }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
144
|
try {
|
|
187
145
|
if (!sheetInstance)
|
|
188
146
|
sheetInstance = yield getSheetInstance();
|
|
189
|
-
// Procesar los valores: mantener fechas como están y usar USER_ENTERED solo para fechas
|
|
190
|
-
const processedValues = cellValues.map((value) => {
|
|
191
|
-
if (typeof value === 'string' && isDateString(value)) {
|
|
192
|
-
// Para fechas, convertir a formato que Google Sheets reconozca mejor
|
|
193
|
-
const jsDate = convertToJSDate(value);
|
|
194
|
-
if (jsDate) {
|
|
195
|
-
// Formatear como YYYY-MM-DD que Google Sheets reconoce mejor
|
|
196
|
-
const year = jsDate.getFullYear();
|
|
197
|
-
const month = (jsDate.getMonth() + 1).toString().padStart(2, '0');
|
|
198
|
-
const day = jsDate.getDate().toString().padStart(2, '0');
|
|
199
|
-
return `${year}-${month}-${day}`;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return value;
|
|
203
|
-
});
|
|
204
|
-
// Insertar los datos procesados
|
|
205
147
|
yield sheetInstance.spreadsheets.values.append({
|
|
206
148
|
auth: googleAuth,
|
|
207
149
|
spreadsheetId: googleSheeIds[sheetName],
|
|
208
150
|
range: `${sheetPage}!${cellPositionAppend}`,
|
|
209
|
-
valueInputOption: '
|
|
151
|
+
valueInputOption: 'RAW',
|
|
210
152
|
insertDataOption: 'INSERT_ROWS',
|
|
211
153
|
resource: {
|
|
212
|
-
values: [
|
|
154
|
+
values: [cellValues],
|
|
213
155
|
},
|
|
214
156
|
});
|
|
215
157
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../../src/chat/api/conversation.ts"],"names":[],"mappings":"AAoBA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SAoBpD,CAAC;AA+WF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/googleSheet/index.ts"],"names":[],"mappings":"AA6BA,iBAAe,SAAS,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,eAAe,EAAE;;;;;;CAAA,gBAgBnG;AAED,QAAA,MAAM,eAAe;;;;;;;;;0BAiCpB,CAAC;AAGF,iBAAS,SAAS,CAAC,MAAM,KAAA,UAaxB;AAED,iBAAS,iBAAiB,CAAC,MAAM,KAAA,UAOhC;AAED,QAAA,MAAM,UAAU;;;;;;mBAkBf,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/googleSheet/index.ts"],"names":[],"mappings":"AA6BA,iBAAe,SAAS,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,eAAe,EAAE;;;;;;CAAA,gBAgBnG;AAED,QAAA,MAAM,eAAe;;;;;;;;;0BAiCpB,CAAC;AAGF,iBAAS,SAAS,CAAC,MAAM,KAAA,UAaxB;AAED,iBAAS,iBAAiB,CAAC,MAAM,KAAA,UAOhC;AAED,QAAA,MAAM,UAAU;;;;;;mBAkBf,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;mBAmBhB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runnerpro/backend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.1",
|
|
4
4
|
"description": "A collection of common backend functions",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./lib/cjs/index.js"
|
|
@@ -66,11 +66,13 @@
|
|
|
66
66
|
"@google-cloud/translate": "^8.3.0",
|
|
67
67
|
"@notionhq/client": "^2.2.15",
|
|
68
68
|
"exifr": "^7.1.3",
|
|
69
|
+
"ffmpeg-static": "^5.2.0",
|
|
70
|
+
"ffprobe-static": "^3.1.0",
|
|
69
71
|
"firebase-admin": "^11.10.1",
|
|
72
|
+
"fluent-ffmpeg": "^2.1.3",
|
|
70
73
|
"googleapis": "^144.0.0",
|
|
71
74
|
"multer": "^1.4.5-lts.1",
|
|
72
75
|
"oauth-signature": "1.5.0",
|
|
73
76
|
"socket.io": "^4.7.2"
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
|
-
|