@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, duration } = req.body;
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: 'USER_ENTERED',
151
+ valueInputOption: 'RAW',
210
152
  insertDataOption: 'INSERT_ROWS',
211
153
  resource: {
212
- values: [processedValues],
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":"AAYA,QAAA,MAAM,iBAAiB,0BAA2B,GAAG,SAoBpD,CAAC;AA2SF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
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;AAkDF,QAAA,MAAM,WAAW;;;;;;mBAoChB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,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.11.6",
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
-