feat: add news sources, 30-day filter, and fix ticker performance
- Fix Al Jazeera RSS URL (feeds.aljazeera.com is dead, moved to www.aljazeera.com) - Add 8 new RSS sources: DW, France 24, Euronews, DW Africa, RFI, Africa News, NYT Africa, NPR — covering Germany, Europe, Africa, Cameroon region, and USA - Filter WHO outbreak news and ticker feed to last 30 days (drops stale alerts like 733-day-old WHO DONs) - Fix ticker causing Chrome to crash: add will-change:transform and contain:layout style for GPU compositing, reduce DOM nodes from 80 to 40 - Add badge styles for new source categories (DW, EU, Africa)
This commit is contained in:
@@ -51,7 +51,11 @@ export async function getOutbreakNews() {
|
|||||||
return db - da;
|
return db - da;
|
||||||
});
|
});
|
||||||
|
|
||||||
return items.map(item => ({
|
// Filter to last 30 days only
|
||||||
|
const cutoff = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
|
||||||
|
const recent = items.filter(item => new Date(item.PublicationDate || 0) >= cutoff);
|
||||||
|
|
||||||
|
return recent.map(item => ({
|
||||||
title: item.Title,
|
title: item.Title,
|
||||||
date: item.PublicationDate,
|
date: item.PublicationDate,
|
||||||
donId: item.DonId || null,
|
donId: item.DonId || null,
|
||||||
|
|||||||
@@ -126,13 +126,26 @@ async function fetchRSS(url, source) {
|
|||||||
|
|
||||||
export async function fetchAllNews() {
|
export async function fetchAllNews() {
|
||||||
const feeds = [
|
const feeds = [
|
||||||
|
// Global
|
||||||
['http://feeds.bbci.co.uk/news/world/rss.xml', 'BBC'],
|
['http://feeds.bbci.co.uk/news/world/rss.xml', 'BBC'],
|
||||||
['https://rss.nytimes.com/services/xml/rss/nyt/World.xml', 'NYT'],
|
['https://rss.nytimes.com/services/xml/rss/nyt/World.xml', 'NYT'],
|
||||||
['https://www.aljazeera.com/xml/rss/all.xml', 'Al Jazeera'],
|
['https://www.aljazeera.com/xml/rss/all.xml', 'Al Jazeera'],
|
||||||
['https://rss.nytimes.com/services/xml/rss/nyt/Americas.xml', 'NYT Americas'],
|
// USA
|
||||||
['https://rss.nytimes.com/services/xml/rss/nyt/AsiaPacific.xml', 'NYT Asia'],
|
['https://feeds.npr.org/1001/rss.xml', 'NPR'],
|
||||||
['https://feeds.bbci.co.uk/news/technology/rss.xml', 'BBC Tech'],
|
['https://feeds.bbci.co.uk/news/technology/rss.xml', 'BBC Tech'],
|
||||||
['http://feeds.bbci.co.uk/news/science_and_environment/rss.xml', 'BBC Science'],
|
['http://feeds.bbci.co.uk/news/science_and_environment/rss.xml', 'BBC Science'],
|
||||||
|
['https://rss.nytimes.com/services/xml/rss/nyt/Americas.xml', 'NYT Americas'],
|
||||||
|
// Europe
|
||||||
|
['https://rss.dw.com/rdf/rss-en-all', 'DW'],
|
||||||
|
['https://www.france24.com/en/rss', 'France 24'],
|
||||||
|
['https://www.euronews.com/rss?format=mrss', 'Euronews'],
|
||||||
|
// Africa & Cameroon region
|
||||||
|
['https://rss.dw.com/rdf/rss-en-africa', 'DW Africa'],
|
||||||
|
['https://www.rfi.fr/en/rss', 'RFI'],
|
||||||
|
['https://www.africanews.com/feed/rss', 'Africa News'],
|
||||||
|
['https://rss.nytimes.com/services/xml/rss/nyt/Africa.xml', 'NYT Africa'],
|
||||||
|
// Asia-Pacific
|
||||||
|
['https://rss.nytimes.com/services/xml/rss/nyt/AsiaPacific.xml', 'NYT Asia'],
|
||||||
];
|
];
|
||||||
|
|
||||||
const results = await Promise.allSettled(
|
const results = await Promise.allSettled(
|
||||||
@@ -164,8 +177,10 @@ export async function fetchAllNews() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geoNews.sort((a, b) => new Date(b.date || 0) - new Date(a.date || 0));
|
const cutoff = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
|
||||||
return geoNews.slice(0, 50);
|
const filtered = geoNews.filter(n => !n.date || new Date(n.date) >= cutoff);
|
||||||
|
filtered.sort((a, b) => new Date(b.date || 0) - new Date(a.date || 0));
|
||||||
|
return filtered.slice(0, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Leverageable Ideas from Signals ===
|
// === Leverageable Ideas from Signals ===
|
||||||
@@ -549,9 +564,11 @@ function buildNewsFeed(rssNews, gdeltData, tgUrgent, tgTop) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by timestamp descending, limit to 50
|
// Filter to last 30 days, sort by timestamp descending, limit to 50
|
||||||
feed.sort((a, b) => new Date(b.timestamp || 0) - new Date(a.timestamp || 0));
|
const cutoff = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
|
||||||
return feed.slice(0, 50);
|
const recent = feed.filter(item => !item.timestamp || new Date(item.timestamp) >= cutoff);
|
||||||
|
recent.sort((a, b) => new Date(b.timestamp || 0) - new Date(a.timestamp || 0));
|
||||||
|
return recent.slice(0, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === CLI Mode: inject into HTML file ===
|
// === CLI Mode: inject into HTML file ===
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ html,body{height:100%;background:var(--bg);color:var(--text);font-family:var(--s
|
|||||||
.ticker-wrap::before,.ticker-wrap::after{content:'';position:absolute;left:0;right:0;height:30px;z-index:2;pointer-events:none}
|
.ticker-wrap::before,.ticker-wrap::after{content:'';position:absolute;left:0;right:0;height:30px;z-index:2;pointer-events:none}
|
||||||
.ticker-wrap::before{top:0;background:linear-gradient(to bottom,rgba(14,17,22,0.95),transparent)}
|
.ticker-wrap::before{top:0;background:linear-gradient(to bottom,rgba(14,17,22,0.95),transparent)}
|
||||||
.ticker-wrap::after{bottom:0;background:linear-gradient(to top,rgba(14,17,22,0.95),transparent)}
|
.ticker-wrap::after{bottom:0;background:linear-gradient(to top,rgba(14,17,22,0.95),transparent)}
|
||||||
.ticker-track{display:flex;flex-direction:column;animation:tickerScroll var(--ticker-duration,30s) linear infinite}
|
.ticker-track{display:flex;flex-direction:column;animation:tickerScroll var(--ticker-duration,30s) linear infinite;will-change:transform;contain:layout style}
|
||||||
.ticker-wrap:hover .ticker-track{animation-play-state:paused}
|
.ticker-wrap:hover .ticker-track{animation-play-state:paused}
|
||||||
@keyframes tickerScroll{0%{transform:translateY(0)}100%{transform:translateY(-50%)}}
|
@keyframes tickerScroll{0%{transform:translateY(0)}100%{transform:translateY(-50%)}}
|
||||||
.tk-card{padding:8px 10px;border-bottom:1px solid rgba(255,255,255,0.03);cursor:default;transition:background 0.2s}
|
.tk-card{padding:8px 10px;border-bottom:1px solid rgba(255,255,255,0.03);cursor:default;transition:background 0.2s}
|
||||||
@@ -229,6 +229,9 @@ html,body{height:100%;background:var(--bg);color:var(--text);font-family:var(--s
|
|||||||
.tk-src.alj{color:#ffd54f;border-color:rgba(255,213,79,0.3)}
|
.tk-src.alj{color:#ffd54f;border-color:rgba(255,213,79,0.3)}
|
||||||
.tk-src.gdelt{color:#4dd0e1;border-color:rgba(77,208,225,0.3)}
|
.tk-src.gdelt{color:#4dd0e1;border-color:rgba(77,208,225,0.3)}
|
||||||
.tk-src.tg{color:#ffb74d;border-color:rgba(255,183,77,0.3)}
|
.tk-src.tg{color:#ffb74d;border-color:rgba(255,183,77,0.3)}
|
||||||
|
.tk-src.dw{color:#ef9a9a;border-color:rgba(239,154,154,0.3)}
|
||||||
|
.tk-src.eu{color:#ce93d8;border-color:rgba(206,147,216,0.3)}
|
||||||
|
.tk-src.af{color:#a5d6a7;border-color:rgba(165,214,167,0.3)}
|
||||||
.tk-src.other{color:#b0bec5;border-color:rgba(176,190,197,0.2)}
|
.tk-src.other{color:#b0bec5;border-color:rgba(176,190,197,0.2)}
|
||||||
.tk-head{font-size:11px;line-height:1.35;color:#c8d8d2;margin-top:3px}
|
.tk-head{font-size:11px;line-height:1.35;color:#c8d8d2;margin-top:3px}
|
||||||
.tk-time{font-family:var(--mono);font-size:8px;color:var(--dim);margin-top:2px}
|
.tk-time{font-family:var(--mono);font-size:8px;color:var(--dim);margin-top:2px}
|
||||||
@@ -1361,7 +1364,7 @@ function renderLower(){
|
|||||||
const srcHtml=D.health.map(s=>`<div class="src-item"><div class="sd ${s.err?'err':'ok'}"></div><span>${s.n}</span></div>`).join('');
|
const srcHtml=D.health.map(s=>`<div class="src-item"><div class="sd ${s.err?'err':'ok'}"></div><span>${s.n}</span></div>`).join('');
|
||||||
|
|
||||||
// NEWS TICKER — merges RSS + GDELT + Telegram into flowing cards (moved from right rail)
|
// NEWS TICKER — merges RSS + GDELT + Telegram into flowing cards (moved from right rail)
|
||||||
const feed = (D.newsFeed || []).slice(0, 40);
|
const feed = (D.newsFeed || []).slice(0, 20);
|
||||||
const srcClass = s => {
|
const srcClass = s => {
|
||||||
if (!s) return 'other';
|
if (!s) return 'other';
|
||||||
const sl = s.toLowerCase();
|
const sl = s.toLowerCase();
|
||||||
@@ -1370,6 +1373,9 @@ function renderLower(){
|
|||||||
if (sl.includes('jazeera') || sl.includes('alj')) return 'alj';
|
if (sl.includes('jazeera') || sl.includes('alj')) return 'alj';
|
||||||
if (sl.includes('gdelt')) return 'gdelt';
|
if (sl.includes('gdelt')) return 'gdelt';
|
||||||
if (sl.includes('telegram')) return 'tg';
|
if (sl.includes('telegram')) return 'tg';
|
||||||
|
if (sl.includes('dw') || sl.includes('deutsche')) return 'dw';
|
||||||
|
if (sl.includes('france') || sl.includes('rfi') || sl.includes('euronews')) return 'eu';
|
||||||
|
if (sl.includes('africa') || sl.includes('npr')) return 'af';
|
||||||
return 'other';
|
return 'other';
|
||||||
};
|
};
|
||||||
const tickerCards = feed.map(n => {
|
const tickerCards = feed.map(n => {
|
||||||
|
|||||||
Reference in New Issue
Block a user