no update fechas

Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
This commit is contained in:
Omar Sánchez Pizarro
2026-01-20 12:50:03 +01:00
parent a65bedf24d
commit 421fee1938
3 changed files with 51 additions and 33 deletions

View File

@@ -110,8 +110,8 @@ class MongoDBArticleCache:
article_id = str(article.get_id()) article_id = str(article.get_id())
key = (platform, article_id) key = (platform, article_id)
# Preparar datos del artículo (sin user_info) # Campos base del artículo (sin user_info, sin createdAt/updatedAt)
article_data = { base_fields = {
'platform': platform, 'platform': platform,
'id': article_id, 'id': article_id,
'title': article.get_title(), 'title': article.get_title(),
@@ -124,7 +124,6 @@ class MongoDBArticleCache:
'images': article.get_images(), 'images': article.get_images(),
'modified_at': article.get_modified_at(), 'modified_at': article.get_modified_at(),
'expiresAt': expires_at, 'expiresAt': expires_at,
'updatedAt': now,
} }
# Preparar user_info # Preparar user_info
@@ -175,35 +174,37 @@ class MongoDBArticleCache:
) )
) )
else: else:
# Precio diferente, actualizar artículo completo # Precio diferente, actualizar campos del artículo + user_info
# Mantener updatedAt para saber cuándo cambió el precio # Mantener createdAt/updatedAt originales (no se incluyen en el $set)
# Eliminar notifiedAt/notified_at a nivel de artículo (solo debe estar en user_info) update_data = dict(base_fields)
article_data['user_info'] = existing_user_info update_data['user_info'] = existing_user_info
operations.append( operations.append(
UpdateOne( UpdateOne(
{'platform': platform, 'id': article_id}, {'platform': platform, 'id': article_id},
{ {
'$set': article_data, '$set': update_data,
'$unset': {'notifiedAt': '', 'notified_at': ''} '$unset': {'notifiedAt': '', 'notified_at': ''}
} }
) )
) )
else: else:
# Artículo nuevo # Artículo nuevo
article_data['user_info'] = [{ new_article_data = dict(base_fields)
new_article_data['user_info'] = [{
'username': username, 'username': username,
'worker_name': worker_name, 'worker_name': worker_name,
'notified': True, 'notified': True,
'notified_at': now, 'notified_at': now,
'is_favorite': False, 'is_favorite': False,
}] }]
article_data['createdAt'] = now new_article_data['createdAt'] = now
new_article_data['updatedAt'] = now
operations.append( operations.append(
UpdateOne( UpdateOne(
{'platform': platform, 'id': article_id}, {'platform': platform, 'id': article_id},
{ {
'$set': article_data, '$set': new_article_data,
}, },
upsert=True upsert=True
) )

View File

@@ -39,13 +39,7 @@ router.get('/', basicAuthMiddleware, async (req, res) => {
const limit = parseInt(req.query.limit) || 100; const limit = parseInt(req.query.limit) || 100;
const offset = parseInt(req.query.offset) || 0; const offset = parseInt(req.query.offset) || 0;
// Los artículos ya vienen ordenados de MongoDB, pero asegurémonos const paginated = articles.slice(offset, offset + limit);
const sorted = articles.sort((a, b) => {
const aTime = typeof a.notifiedAt === 'number' ? a.notifiedAt : new Date(a.notifiedAt).getTime();
const bTime = typeof b.notifiedAt === 'number' ? b.notifiedAt : new Date(b.notifiedAt).getTime();
return bTime - aTime;
});
const paginated = sorted.slice(offset, offset + limit);
res.json({ res.json({
articles: paginated, articles: paginated,
@@ -124,16 +118,9 @@ router.get('/search', basicAuthMiddleware, async (req, res) => {
return false; return false;
}); });
// Ordenar por fecha de notificación (más recientes primero)
const sorted = filtered.sort((a, b) => {
const aTime = typeof a.notifiedAt === 'number' ? a.notifiedAt : new Date(a.notifiedAt).getTime();
const bTime = typeof b.notifiedAt === 'number' ? b.notifiedAt : new Date(b.notifiedAt).getTime();
return bTime - aTime;
});
res.json({ res.json({
articles: sorted, articles: filtered,
total: sorted.length, total: filtered.length,
query: query, query: query,
}); });
} catch (error) { } catch (error) {

View File

@@ -281,11 +281,21 @@ export async function getNotifiedArticles(filter = {}) {
}; };
// Si hay un user_info específico, usar sus datos // Si hay un user_info específico, usar sus datos
const fallbackTime =
article.createdAt?.getTime?.() ||
(typeof article.createdAt === 'number' ? article.createdAt : null) ||
article.modified_at?.getTime?.() ||
null;
if (relevantUserInfo) { if (relevantUserInfo) {
result.username = relevantUserInfo.username; result.username = relevantUserInfo.username;
result.worker_name = relevantUserInfo.worker_name; result.worker_name = relevantUserInfo.worker_name;
result.is_favorite = relevantUserInfo.is_favorite || false; result.is_favorite = relevantUserInfo.is_favorite || false;
result.notifiedAt = relevantUserInfo.notified_at?.getTime() || Date.now(); // NO usar Date.now() como fallback, para no mover artículos antiguos
result.notifiedAt =
relevantUserInfo.notified_at?.getTime?.() ||
(typeof relevantUserInfo.notified_at === 'number' ? relevantUserInfo.notified_at : null) ||
fallbackTime;
} else { } else {
// Sin filtro específico, mostrar el primer user_info o datos generales // Sin filtro específico, mostrar el primer user_info o datos generales
const firstUserInfo = (article.user_info || [])[0]; const firstUserInfo = (article.user_info || [])[0];
@@ -293,13 +303,19 @@ export async function getNotifiedArticles(filter = {}) {
result.username = firstUserInfo.username; result.username = firstUserInfo.username;
result.worker_name = firstUserInfo.worker_name; result.worker_name = firstUserInfo.worker_name;
result.is_favorite = firstUserInfo.is_favorite || false; result.is_favorite = firstUserInfo.is_favorite || false;
result.notifiedAt = firstUserInfo.notified_at?.getTime() || Date.now(); result.notifiedAt =
firstUserInfo.notified_at?.getTime?.() ||
(typeof firstUserInfo.notified_at === 'number' ? firstUserInfo.notified_at : null) ||
fallbackTime;
} else { } else {
// Compatibilidad con estructura antigua // Compatibilidad con estructura antigua
result.username = article.username; result.username = article.username;
result.worker_name = article.worker_name; result.worker_name = article.worker_name;
result.is_favorite = article.is_favorite || false; result.is_favorite = article.is_favorite || false;
result.notifiedAt = article.notifiedAt?.getTime() || Date.now(); result.notifiedAt =
article.notifiedAt?.getTime?.() ||
(typeof article.notifiedAt === 'number' ? article.notifiedAt : null) ||
fallbackTime;
} }
} }
@@ -331,7 +347,7 @@ export async function getFavorites(username = null) {
const articles = await articlesCollection const articles = await articlesCollection
.find(query) .find(query)
.sort({ 'user_info.notified_at': -1, createdAt: -1 }) .sort({ createdAt: -1, modified_at: -1 })
.toArray(); .toArray();
// Filtrar y transformar para devolver solo los favoritos relevantes // Filtrar y transformar para devolver solo los favoritos relevantes
@@ -351,7 +367,14 @@ export async function getFavorites(username = null) {
username: userInfo.username, username: userInfo.username,
worker_name: userInfo.worker_name, worker_name: userInfo.worker_name,
is_favorite: true, is_favorite: true,
notifiedAt: userInfo.notified_at?.getTime() || Date.now(), // NOTA: no usar Date.now() como fallback, para no mover favoritos antiguos
notifiedAt:
userInfo.notified_at?.getTime?.() ||
(typeof userInfo.notified_at === 'number' ? userInfo.notified_at : null) ||
article.createdAt?.getTime?.() ||
(typeof article.createdAt === 'number' ? article.createdAt : null) ||
article.modified_at?.getTime?.() ||
null,
expiresAt: article.expiresAt?.getTime() || null, expiresAt: article.expiresAt?.getTime() || null,
}); });
} }
@@ -365,7 +388,14 @@ export async function getFavorites(username = null) {
username: userInfo.username, username: userInfo.username,
worker_name: userInfo.worker_name, worker_name: userInfo.worker_name,
is_favorite: true, is_favorite: true,
notifiedAt: userInfo.notified_at?.getTime() || Date.now(), // NOTA: no usar Date.now() como fallback, para no mover favoritos antiguos
notifiedAt:
userInfo.notified_at?.getTime?.() ||
(typeof userInfo.notified_at === 'number' ? userInfo.notified_at : null) ||
article.createdAt?.getTime?.() ||
(typeof article.createdAt === 'number' ? article.createdAt : null) ||
article.modified_at?.getTime?.() ||
null,
expiresAt: article.expiresAt?.getTime() || null, expiresAt: article.expiresAt?.getTime() || null,
}); });
} }