mirror of
https://github.com/caty21/forex-dashboard.git
synced 2026-08-24 09:58:05 +00:00
fix: actualités — tri chronologique cassé + 3 flux RSS morts remplacés
Tri (lib/newsfeed.ts + components/NewsTab.tsx) : Un bonus "+3h pour les catégories prioritaires" (Guerre/Chef d'État/Crise…) était appliqué avant le tri par date. En temps normal ça remonte discrètement une poignée d'articles importants ; mais en période de crise soutenue (conflit Moyen-Orient actuel), la quasi-totalité des articles matche une de ces catégories — le bonus s'applique presque partout et casse l'ordre chronologique au lieu de l'affiner, produisant des blocs par source de plus en plus vieux au lieu d'un flux unique correctement entrelacé. Vérifié en direct : 54 articles avant fix avec des dizaines d'inversions chronologiques, 0 après. Le badge visuel "⚡ Prioritaire" reste pour signaler l'importance sans trahir la fraîcheur réelle. Flux RSS (lib/newsfeed.ts RSS_FEEDS) — 3 des 6 sources ne contribuaient plus rien, vérifié en direct : - ForexLive : /feed/news est une coquille vide (0 <item>) depuis leur migration Nuxt.js vers investinglive.com — déjà couvert par le scraper dédié fetchInvestingLiveNews(), aucune perte réelle en le retirant. - MarketWatch : l'ancien miroir dowjones.io ne sert que des articles vieux de 1+ an (filtrés par le cutoff 8 jours) → remplacé par l'URL RSS actuelle (marketwatch.com/rss/topstories, testée fraîche). - Reuters : feeds.reuters.com n'existe plus (échec DNS, fermé par Reuters il y a plusieurs années) → remplacé par CNBC Markets (testé frais). Bloomberg (403 anti-bot) et FinancialJuice (site restructuré) restent à zéro, déjà connu et accepté (échecs silencieux gérés par try/catch). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
062892c340
commit
7c9b6ac89d
+10
-8
@@ -55,7 +55,7 @@ const HIGH_PRIO = new Set([
|
|||||||
|
|
||||||
const SOURCE_COLORS: Record<string, string> = {
|
const SOURCE_COLORS: Record<string, string> = {
|
||||||
"InvestingLive": "bg-amber-500/20 text-amber-400",
|
"InvestingLive": "bg-amber-500/20 text-amber-400",
|
||||||
"Reuters": "bg-orange-500/20 text-orange-400",
|
"CNBC": "bg-orange-500/20 text-orange-400",
|
||||||
"Bloomberg Economics": "bg-sky-500/20 text-sky-400",
|
"Bloomberg Economics": "bg-sky-500/20 text-sky-400",
|
||||||
"Bloomberg CB": "bg-sky-500/20 text-sky-400",
|
"Bloomberg CB": "bg-sky-500/20 text-sky-400",
|
||||||
"Bloomberg FX": "bg-sky-500/20 text-sky-400",
|
"Bloomberg FX": "bg-sky-500/20 text-sky-400",
|
||||||
@@ -72,14 +72,16 @@ function formatRelativeTime(isoDate: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Tri ───────────────────────────────────────────────────────────────────────
|
// ── Tri ───────────────────────────────────────────────────────────────────────
|
||||||
// Score plus élevé = apparaît en premier.
|
// Strictement chronologique (score = timestamp). Un bonus "+3h prioritaire /
|
||||||
// Récence primaire → haute priorité (+3h) → catégorisé (+1h) → bruit sans catégorie (0)
|
// +1h catégorisé" existait ici, mais en période de crise soutenue la quasi-
|
||||||
|
// totalité des articles matche une catégorie prioritaire (Guerre/Géopolitique/
|
||||||
|
// Chef d'État) : le bonus s'applique alors presque partout et casse l'ordre
|
||||||
|
// chronologique au lieu de l'affiner (des articles plus vieux mais
|
||||||
|
// "prioritaires" passent devant des articles réellement plus récents). Le
|
||||||
|
// badge visuel "⚡ Prioritaire" (NewsCard) signale déjà l'importance sans
|
||||||
|
// trahir la fraîcheur réelle du flux.
|
||||||
function scoreItem(item: NewsItem): number {
|
function scoreItem(item: NewsItem): number {
|
||||||
const t = new Date(item.publishedAt).getTime();
|
return new Date(item.publishedAt).getTime();
|
||||||
const isPrio = item.categories.some(c => HIGH_PRIO.has(c));
|
|
||||||
const hasCat = item.categories.length > 0 || item.impacts.length > 0;
|
|
||||||
return t + (isPrio ? 3 * 3_600_000 : hasCat ? 1 * 3_600_000 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Composant principal ───────────────────────────────────────────────────────
|
// ── Composant principal ───────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"ts":1783520638250,"data":{"current":{},"prev":{},"prevDate":null}}
|
{"ts":1783528251592,"data":{"current":{"NZD":{"currency":"NZD","nextMeetingProbPct":82,"nextMeetingIsHike":true,"nextMeetingIsNoChange":false,"bpsYearEnd":62,"publishedDate":"2026-07-03"},"USD":{"currency":"USD","nextMeetingProbPct":17,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":30,"publishedDate":"2026-07-03"},"EUR":{"currency":"EUR","nextMeetingProbPct":28,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":24,"publishedDate":"2026-07-03"},"JPY":{"currency":"JPY","nextMeetingProbPct":1,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":20,"publishedDate":"2026-07-03"},"GBP":{"currency":"GBP","nextMeetingProbPct":7,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":18,"publishedDate":"2026-07-03"},"AUD":{"currency":"AUD","nextMeetingProbPct":15,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":10,"publishedDate":"2026-07-03"},"CAD":{"currency":"CAD","nextMeetingProbPct":9,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":8,"publishedDate":"2026-07-03"},"CHF":{"currency":"CHF","nextMeetingProbPct":4,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":5,"publishedDate":"2026-07-03"}},"prev":{"NZD":{"currency":"NZD","nextMeetingProbPct":62,"nextMeetingIsHike":true,"nextMeetingIsNoChange":false,"bpsYearEnd":55,"publishedDate":"2026-06-26"},"USD":{"currency":"USD","nextMeetingProbPct":30,"nextMeetingIsHike":true,"nextMeetingIsNoChange":false,"bpsYearEnd":31,"publishedDate":"2026-06-26"},"EUR":{"currency":"EUR","nextMeetingProbPct":31,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":27,"publishedDate":"2026-06-26"},"GBP":{"currency":"GBP","nextMeetingProbPct":14,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":20,"publishedDate":"2026-06-26"},"JPY":{"currency":"JPY","nextMeetingProbPct":3,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":19,"publishedDate":"2026-06-26"},"CAD":{"currency":"CAD","nextMeetingProbPct":4,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":18,"publishedDate":"2026-06-26"},"AUD":{"currency":"AUD","nextMeetingProbPct":13,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":8,"publishedDate":"2026-06-26"},"CHF":{"currency":"CHF","nextMeetingProbPct":6,"nextMeetingIsHike":false,"nextMeetingIsNoChange":true,"bpsYearEnd":5,"publishedDate":"2026-06-26"}},"prevDate":"2026-06-26"}}
|
||||||
+23
-15
@@ -675,13 +675,20 @@ async function fetchInvestingLiveNews(): Promise<NewsItem[]> {
|
|||||||
// ForexLive : commentaires macro en temps réel
|
// ForexLive : commentaires macro en temps réel
|
||||||
// MarketWatch : marchés généraux
|
// MarketWatch : marchés généraux
|
||||||
|
|
||||||
|
// Vérifié en direct (2026-07-08) :
|
||||||
|
// - ForexLive retiré : /feed/news est une coquille vide (0 <item>) depuis leur
|
||||||
|
// migration Nuxt.js vers investinglive.com — déjà couvert par le scraper
|
||||||
|
// dédié fetchInvestingLiveNews() (API réelle), donc pas de perte réelle.
|
||||||
|
// - MarketWatch : l'ancien miroir dowjones.io sert des articles vieux de 1+ an
|
||||||
|
// (tous filtrés par le cutoff 8 jours) → remplacé par l'URL RSS actuelle.
|
||||||
|
// - Reuters : feeds.reuters.com n'existe plus (échec DNS, fermé côté Reuters
|
||||||
|
// il y a plusieurs années) → remplacé par CNBC Markets (flux frais, testé).
|
||||||
const RSS_FEEDS: { url: string; source: string }[] = [
|
const RSS_FEEDS: { url: string; source: string }[] = [
|
||||||
{ url: "https://www.fxstreet.com/rss/news", source: "FXStreet" },
|
{ url: "https://www.fxstreet.com/rss/news", source: "FXStreet" },
|
||||||
{ url: "https://www.forexlive.com/feed/news", source: "ForexLive" },
|
{ url: "https://www.marketwatch.com/rss/topstories", source: "MarketWatch" },
|
||||||
{ url: "https://feeds.content.dowjones.io/public/rss/mw_realtimeheadlines", source: "MarketWatch" },
|
{ url: "https://finance.yahoo.com/rss/topfinstories", source: "Yahoo Finance" },
|
||||||
{ url: "https://finance.yahoo.com/rss/topfinstories", source: "Yahoo Finance" },
|
{ url: "https://www.cnbc.com/id/100003114/device/rss/rss.html", source: "CNBC" },
|
||||||
{ url: "https://feeds.reuters.com/reuters/businessNews", source: "Reuters" },
|
{ url: "https://www.investing.com/rss/news.rss", source: "Investing.com" },
|
||||||
{ url: "https://www.investing.com/rss/news.rss", source: "Investing.com" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
async function fetchRssFeeds(): Promise<NewsItem[]> {
|
async function fetchRssFeeds(): Promise<NewsItem[]> {
|
||||||
@@ -895,15 +902,16 @@ export async function fetchAllNews(): Promise<NewsItem[]> {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const PRIORITY_SET = new Set(["Discours BC", "Décision Taux", "Crise", "Guerre", "Chef d'État", "Probabilités Taux"]);
|
// Tri strictement chronologique (décroissant). Un bonus "+3h pour les
|
||||||
const isPrio = (item: NewsItem) => item.categories.some(c => PRIORITY_SET.has(c));
|
// catégories prioritaires" existait ici auparavant, mais en période de
|
||||||
const PRIO_BONUS_MS = 3 * 60 * 60 * 1000; // +3h boost pour les prioritaires
|
// crise soutenue (ex. conflit Moyen-Orient) la quasi-totalité des articles
|
||||||
|
// matche "Guerre"/"Géopolitique"/"Chef d'État" — le bonus s'appliquait donc
|
||||||
deduped.sort((a, b) => {
|
// presque partout et cassait l'ordre chronologique au lieu de l'affiner
|
||||||
const ta = new Date(a.publishedAt).getTime() + (isPrio(a) ? PRIO_BONUS_MS : 0);
|
// (des articles plus anciens mais "prioritaires" passaient devant des
|
||||||
const tb = new Date(b.publishedAt).getTime() + (isPrio(b) ? PRIO_BONUS_MS : 0);
|
// articles réellement plus récents). Le badge visuel "⚡ Prioritaire"
|
||||||
return tb - ta;
|
// (NewsTab.tsx) reste le bon endroit pour signaler l'importance sans
|
||||||
});
|
// trahir la fraîcheur réelle du flux.
|
||||||
|
deduped.sort((a, b) => new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime());
|
||||||
|
|
||||||
return deduped;
|
return deduped;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user