← back to Allnewsdaily
server.js
95 lines
const express = require('express');
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
const app = express();
const PORT = process.env.PORT || 9788;
const OUTLETS_PATH = path.join(__dirname, 'data', 'outlets.json');
const LIVE_STATUS_PATH = path.join(__dirname, 'data', 'live-status.json');
function loadOutlets() {
try {
return JSON.parse(fs.readFileSync(OUTLETS_PATH, 'utf8'));
} catch (e) {
console.error('[outlets] load failed', e.message);
return [];
}
}
function loadLiveStatus() {
try {
if (!fs.existsSync(LIVE_STATUS_PATH)) return {};
return JSON.parse(fs.readFileSync(LIVE_STATUS_PATH, 'utf8'));
} catch (e) {
return {};
}
}
function mergeOutlets() {
const outlets = loadOutlets();
const status = loadLiveStatus();
return outlets.map(o => {
const s = status[o.id];
return {
...o,
isLive: s ? !!s.isLive : false,
liveVideoId: s && s.videoId ? s.videoId : null,
lastCheck: s ? s.checkedAt : null
};
});
}
app.use(express.json());
app.use('/static', express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.get('/api/outlets', (req, res) => {
res.json({ outlets: mergeOutlets(), updatedAt: new Date().toISOString() });
});
app.get('/api/health', (req, res) => {
const outlets = loadOutlets();
const status = loadLiveStatus();
const liveCount = Object.values(status).filter(s => s && s.isLive).length;
res.json({
ok: true,
outlets: outlets.length,
liveOutlets: liveCount,
lastStatusFile: fs.existsSync(LIVE_STATUS_PATH)
? fs.statSync(LIVE_STATUS_PATH).mtime
: null
});
});
app.get('/api/regions', (req, res) => {
const outlets = loadOutlets();
const regions = [...new Set(outlets.map(o => o.region))].sort();
const countries = [...new Set(outlets.map(o => o.country))].sort();
const langs = [...new Set(outlets.map(o => o.lang))].sort();
const categories = [...new Set(outlets.map(o => o.category))].sort();
res.json({ regions, countries, langs, categories });
});
function runChecker() {
const proc = spawn('node', [path.join(__dirname, 'scripts', 'check-live.js')], {
stdio: ['ignore', 'pipe', 'pipe']
});
proc.stdout.on('data', d => process.stdout.write('[checker] ' + d));
proc.stderr.on('data', d => process.stderr.write('[checker] ' + d));
proc.on('exit', code => console.log('[checker] exit ' + code));
}
const POLL_INTERVAL_MS = parseInt(process.env.POLL_INTERVAL_MS || '90000', 10);
app.listen(PORT, () => {
console.log(`allnewsdaily listening on http://0.0.0.0:${PORT}`);
console.log(`outlets loaded: ${loadOutlets().length}`);
runChecker();
setInterval(runChecker, POLL_INTERVAL_MS);
});