diff --git a/app.js b/app.js index 7645e75..879df11 100644 --- a/app.js +++ b/app.js @@ -9,7 +9,7 @@ const { getJSONDataForCountry, } = require('./lib/byCountry'); const { getCompleteTable, getGraph } = require('./lib/corona'); -const { lookupCountry, htmlTemplate } = require('./lib/helpers'); +const { lookupCountry, htmlTemplate, footer } = require('./lib/helpers'); const { getLiveUpdates } = require('./lib/reddit.js'); const { getWorldoMetersTable } = require('./lib/worldoMeters.js'); const { helpContent, countryNotFound } = require('./lib/constants'); @@ -18,12 +18,17 @@ const app = express(); const port = process.env.PORT || 3001; const IS_CURL_RE = /\bcurl\b/im; -function errorHandler(error, res) { +function errorHandler(error, req, res) { console.error(error); - return res.status(500).send(htmlTemplate(` + const body = ` I am sorry. Something went wrong. Please report it\n ${error.message} - `)); + ${footer(new Date)} + `; + if (req.isCurl) { + return body; + } + return res.status(500).send(htmlTemplate(body)); } app.set('json escape', true); @@ -47,58 +52,60 @@ app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' })); app.use(morgan(':remote-addr :remote-user :method :url :status :res[content-length] - :response-time ms')); app.use((req, res, next) => { res.setHeader('Cache-Control', 'no-cache'); + req.isCurl = IS_CURL_RE.test(req.headers['user-agent']); next(); }); app.get('/', (req, res) => { - const isCurl = IS_CURL_RE.test(req.headers['user-agent']); + const isCurl = req.isCurl; const format = req.query.format ? req.query.format : ''; const minimal = req.query.minimal === 'true'; const emojis = req.query.emojis === 'true'; const top = req.query.top ? Number(req.query.top) : 1000; - const source = req.query.source ? Number(req.query.source) : 1; + const source = req.query.source ? Number(req.query.source) : 2; + + if (source === 1) { + if (format.toLowerCase() === 'json') { + return getJSONData().then(result => { + return res.json(result); + }).catch(error => errorHandler(error, req, res)); + } - if (source === 2) { - return getWorldoMetersTable({ isCurl, emojis, minimal, top, format}) + return getCompleteTable({ isCurl, emojis, minimal, top }) .then(result => { return res.send(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); } - if (format.toLowerCase() === 'json') { - return getJSONData().then(result => { - return res.json(result); - }).catch(error => errorHandler(error, res)); - } - - return getCompleteTable({ isCurl, emojis, minimal, top }) + return getWorldoMetersTable({ isCurl, emojis, minimal, top, format}) .then(result => { return res.send(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); + }); app.get('/updates', (req, res) => { - const isCurl = IS_CURL_RE.test(req.headers['user-agent']); + const isCurl = req.isCurl; const format = req.query.format ? req.query.format : ''; if (format.toLowerCase() === 'json') { return getLiveUpdates({ json: true, isCurl }).then(result => { return res.json(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); } return getLiveUpdates({ json: false, isCurl }).then(result => { return res.send(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); }); app.get(['/:country/graph', '/graph'], (req, res) => { const { country } = req.params; - const isCurl = IS_CURL_RE.test(req.headers['user-agent']); + const isCurl = req.isCurl; if (!country) { return getGraph({ isCurl }) .then(result => res.send(result)) - .catch(error => errorHandler(error, res)); + .catch(error => errorHandler(error, req, res)); } const lookupObj = lookupCountry(country); @@ -107,11 +114,11 @@ app.get(['/:country/graph', '/graph'], (req, res) => { } return getGraph({countryCode: lookupObj.iso2, isCurl }) .then(result => res.send(result)) - .catch(error => errorHandler(error, res)); + .catch(error => errorHandler(error, req, res)); }); app.get('/help', (req, res) => { - const isCurl = IS_CURL_RE.test(req.headers['user-agent']); + const isCurl = req.isCurl; if (!isCurl) { return res.send(htmlTemplate(helpContent)); } @@ -121,23 +128,41 @@ app.get('/help', (req, res) => { app.get('/:country', (req, res) => { const { country } = req.params; - const isCurl = IS_CURL_RE.test(req.headers['user-agent']); + const isCurl = req.isCurl; const format = req.query.format ? req.query.format : ''; const minimal = req.query.minimal === 'true'; const emojis = req.query.emojis === 'true'; - const source = req.query.source ? Number(req.query.source) : 1; + const source = req.query.source ? Number(req.query.source) : 2; if (!country || country.toUpperCase() === 'ALL') { if (format.toLowerCase() === 'json') { - return getJSONData().then(result => { + return getWorldoMetersTable({ isCurl, emojis, minimal, format }).then(result => { return res.json(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); + } + + return getWorldoMetersTable({ isCurl, emojis, minimal }) + .then(result => { + return res.send(result); + }).catch(error => errorHandler(error, req, res)); + } + if (source === 1) { + const lookupObj = lookupCountry(country); + + if (!lookupObj) { + return res.status(404).send(countryNotFound(isCurl)); } + const { iso2 } = lookupObj; - return getCompleteTable({ isCurl, emojis, minimal }) + if (format.toLowerCase() === 'json') { + return getJSONDataForCountry(iso2).then(result => { + return res.json(result); + }).catch(error => errorHandler(error, req, res)); + } + return getCountryTable({ countryCode: iso2, isCurl, emojis, minimal }) .then(result => { return res.send(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); } const lookupObj = lookupCountry(country); @@ -146,26 +171,12 @@ app.get('/:country', (req, res) => { return res.status(404).send(countryNotFound(isCurl)); } - const { iso2 } = lookupObj; - if (source === 2) { - return getWorldoMetersTable({ countryCode: iso2, isCurl, emojis, minimal, format }) - .then(result => { - return res.send(result); - }).catch(error => errorHandler(error, res)); - } - - if (format.toLowerCase() === 'json') { - return getJSONDataForCountry(iso2).then(result => { - return res.json(result); - }).catch(error => errorHandler(error, res)); - } - - return getCountryTable({ countryCode: iso2, isCurl, emojis, minimal }) + return getWorldoMetersTable({ countryCode: iso2, isCurl, emojis, minimal, format }) .then(result => { return res.send(result); - }).catch(error => errorHandler(error, res)); + }).catch(error => errorHandler(error, req, res)); }); app.listen(port, () => console.log(`Running on ${port}`)); diff --git a/bin/index.js b/bin/index.js index 656aadc..338566b 100755 --- a/bin/index.js +++ b/bin/index.js @@ -38,7 +38,7 @@ const { argv } = yargs s: { alias: 'source', describe: 'fetch data from other source', - default: 1, + default: 2, type: 'int' }, e: { @@ -74,15 +74,15 @@ const { argv } = yargs .help('help'); argv.countryCode = argv.country; -if (argv.source === 2) { - getWorldoMetersTable(argv).then(console.log).catch(console.error); -} -else if (argv.graph === true) { - getGraph(argv.countryCode).then(console.log).catch(console.error); -} else { +if (argv.source === 1) { ( argv.country === 'ALL' ? getCompleteTable(argv) : getCountryTable(argv) ).then(console.log).catch(console.error); } +else if (argv.graph === true) { + getGraph(argv.countryCode).then(console.log).catch(console.error); +} else { + getWorldoMetersTable(argv).then(console.log).catch(console.error); +} diff --git a/changelog.md b/changelog.md index ade177f..9863037 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # Changelog +## Version 0.9.0 + +* Changed default source to worldoMeters. i.e source 2 is now default + ## Version 0.8.0 * Added confirmed cases graphs `corona -g` or `corona italy -g` diff --git a/lib/api.js b/lib/api.js index d064716..3f97265 100644 --- a/lib/api.js +++ b/lib/api.js @@ -73,8 +73,12 @@ exports.getWorldoMetersData = async (countryCode = 'ALL') => { critical: 0, }); - result.data.forEach(obj => obj.countryCode = countryNameMap[obj.country]); + result.data.forEach(obj => { + obj.countryCode = countryNameMap[obj.country]; + obj.confirmed = obj.cases; + }); worldStats.casesPerOneMillion = (worldStats.cases / 7794).toFixed(2); + worldStats.confirmed = worldStats.cases; let finalData = result.data; if (countryCode && countryCode !== 'ALL') { finalData = finalData.filter(obj => obj.countryCode === countryCode); diff --git a/lib/constants.js b/lib/constants.js index 745fd1d..e830fca 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,4 +1,4 @@ -const { htmlTemplate } = require('./helpers'); +const { htmlTemplate, footer } = require('./helpers'); exports.countryNameMap = { China: 'CN', UK: 'GB', @@ -181,6 +181,20 @@ exports.countryNameMap = { 'Dominican Republic': 'DO', 'Burkina Faso': 'BF', Uzbekistan: 'UZ', + 'Madagascar': 'MG', + 'Uganda': 'UG', + 'Zimbabwe': 'ZW', + 'Dominica': 'DM', + 'Laos': 'LA', + 'Myanmar': 'MM', + 'Belize': 'BZ', + 'Eritrea': 'ER', + 'Grenada': 'GD', + 'Mozambique': 'MZ', + 'Papua New Guinea': 'PG', + 'Syria': 'SY', + 'Timor-Leste': 'TL', + 'Turks and Caicos': 'TC' }; exports.helpContent = ` @@ -201,6 +215,7 @@ https://corona-stats.online --------------------------------------------------------------------------------- +(DEFAULT SOURCE) # Source 2 stats - updated every 15 minutes from worldometers.info https://corona-stats.online?source=2 @@ -213,12 +228,14 @@ https://corona-stats.online/[countryCode] https://corona-stats.online/[countryName] ## Example: From source 1 -https://corona-stats.online/Italy -https://corona-stats.online/UK +https://corona-stats.online/Italy?source=1 +https://corona-stats.online/UK?source=1 -## Example: From source 2 +## Example: From source 2 (DEFAULT) +https://corona-stats.online/italy https://corona-stats.online/italy?source=2 https://corona-stats.online/UK?source=2 +https://corona-stats.online/UK --------------------------------------------------------------------------------- @@ -227,7 +244,7 @@ https://corona-stats.online/UK?source=2 ## Example: https://corona-stats.online?minimal=true https://corona-stats.online/Italy?minimal=true (with country filter) -https://corona-stats.online?minimal=true&source=2 (with source) +https://corona-stats.online?minimal=true&source=1 (with source) https://corona-stats.online/uk?source=2&minimal=true (with source and country) --------------------------------------------------------------------------------- @@ -246,7 +263,7 @@ https://corona-stats.online/uk?source=2&json=true (with source and countr ## Example: https://corona-stats.online?top=25 -https://corona-stats.online?source=2&top=10 (with source) +https://corona-stats.online?source=1&top=10 (with source) https://corona-stats.online/uk?minimal=true&top=20 (with minimal) @@ -275,6 +292,8 @@ exports.countryNotFound = (isCurl) => { - /UK: for United Kingdom - /US: for United States of America. - /Italy: for Italy. + + ${footer(new Date)} `; return isCurl ? body : htmlTemplate(body); }; \ No newline at end of file diff --git a/lib/helpers.js b/lib/helpers.js index c6f84ed..e7be25e 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -171,9 +171,9 @@ ${chalk.greenBright('Twitter')}: ${chalk.blueBright('https://twitter.com/ekrysis ${chalk.magentaBright('Last Updated on:')} ${moment(lastUpdated).utc().format('DD-MMM-YYYY HH:MM')} UTC -${chalk.red.bold('NEW REALTIME UPDATES')}: ${chalk.blueBright('https://corona-stats.online?source=2')} +${chalk.red.bold('UPDATE')}: ${chalk.blueBright('Source 2 is now default source')} +${chalk.red.bold('JHU Source 1 table')}: ${chalk.blueBright('https://corona-stats.online?source=1')} ${chalk.red.bold('HELP')}: ${chalk.blueBright('https://corona-stats.online/help')} -${chalk.bgBlueBright.bold('API was down because JHU has removed recovered from their data :( ')}: ${chalk.blueBright('https://github.com/CSSEGISandData/COVID-19/issues/1250')} `; e.getTableBorders = minimal => { @@ -235,9 +235,7 @@ e.extraStats = (dataArr) => { return dataArr.map(obj => { return { ...obj, - active: e.calActive(obj), mortalityPer: e.calMortalityPer(obj), - recoveredPer: e.calRecoveredPer(obj) }; }); }; @@ -250,18 +248,37 @@ e.htmlTemplate = (body) => { Coronavirus Tracker -
${body}
+
+
${body}
+
`; diff --git a/lib/worldoMeters.js b/lib/worldoMeters.js index 2a798b1..82f895c 100644 --- a/lib/worldoMeters.js +++ b/lib/worldoMeters.js @@ -19,7 +19,6 @@ exports.getWorldoMetersTable = async ({ style: helpers.getTableStyles(minimal), }); const { data, worldStats } = await api.getWorldoMetersData(countryCode); - console.log(format); if (format === 'json') { return { data, worldStats }; } @@ -28,7 +27,7 @@ exports.getWorldoMetersTable = async ({ data.some(cd => { const countryEmoji = getEmoji(cd.countryCode) || '🏳️'; const values = [ - cFormatter(cd.country, chalk.cyanBright), + cFormatter(`${cd.country} (${cd.countryCode})` , chalk.cyanBright), cFormatter(cd.cases, chalk.green, 'right', true), cFormatter(cd.todayCases, chalk.cyanBright, 'right', true, ' ▲'), cFormatter(cd.deaths, chalk.whiteBright, 'right', true), diff --git a/package.json b/package.json index 2cfe8cd..d3ad7ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coronavirus-tracker-cli", - "version": "0.8.0", + "version": "0.9.0", "description": "track conronavirus cases from cli", "repository": { "type": "git", diff --git a/readme.md b/readme.md index cb9a441..e2b873a 100644 --- a/readme.md +++ b/readme.md @@ -37,10 +37,10 @@ curl https://corona-stats.online?minimal=true ```sh curl https://corona-stats.online?top=20 ``` -### Get realtime stats (NEW) +### Get JHU data (source 2 is now the default source) ```sh -curl https://corona-stats.online?source=2 +curl https://corona-stats.online?source=1 ``` ### Latest News (Work in Progress) @@ -81,10 +81,10 @@ corona corona italy ``` -### Get realtime stats (NEW) +### Get JHU data (source 2 is now the default source) ```sh -corona --source=2 +corona --source=1 ``` ### Top N countries