Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
{
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
"env": {
"node": true,
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 2019,
"sourceType": "module"
},
"rules": {
"indent": [
"error",
2
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}
35 changes: 15 additions & 20 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
const express = require('express');
const app = express();
const lookup = require('country-code-lookup');
const morgan = require('morgan');
const stripAnsi = require('strip-ansi');

const port = process.env.PORT || 3001;

const { getCountryTable, getJSONData, getJSONDataForCountry } = require('./lib/byCountry');
const { getCompleteTable } = require('./lib/corona');
const { lookupCountry } = require('./lib/helpers');
const { getLiveUpdates } = require('./lib/reddit.js');

const app = express();
const port = process.env.PORT || 3001;

function errorHandler(error, res) {
console.error(error);
Expand All @@ -26,13 +23,11 @@ app.use((req, res, next) => {
next();
});



app.get('/', (req, res) => {
const isCurl = req.headers['user-agent'].match(/\bcurl\b/gmi) !== null;
const isCurl = req.headers['user-agent'].match(/\bcurl\b/gim) !== null;
const format = req.query.format ? req.query.format : '';
const minimal = req.query.minimal === 'true' ? true : false;
const emojis = req.query.emojis === 'true' ? true : false;
const minimal = req.query.minimal === 'true';
const emojis = req.query.emojis === 'true';
const top = req.query.top ? Number(req.query.top) : 1000;

if (format.toLowerCase() === 'json') {
Expand All @@ -49,24 +44,25 @@ app.get('/', (req, res) => {

app.get('/updates', (req, res) => {
const format = req.query.format ? req.query.format : '';
const isCurl = req.headers['user-agent'].match(/\bcurl\b/gmi) !== null;
const isCurl = req.headers['user-agent'].match(/\bcurl\b/gim) !== null;
if (format.toLowerCase() === 'json') {
return getLiveUpdates({ json: true, isCurl }).then(result => {
return res.json(result);
}).catch(error => errorHandler(error, res));
}

return getLiveUpdates({ json: false, isCurl }).then(result => {
return res.send(result);
}).catch(error => errorHandler(error, res));
});

app.get('/:country', (req, res) => {
const { country } = req.params;
const isCurl = req.headers['user-agent'].match(/\bcurl\b/gmi) !== null;
const isCurl = req.headers['user-agent'].match(/\bcurl\b/gim) !== null;
const format = req.query.format ? req.query.format : '';
const minimal = req.query.minimal === 'true' ? true : false;
const emojis = req.query.emojis === 'true' ? true : false;
if (!country || 'ALL' === country.toUpperCase()) {
const minimal = req.query.minimal === 'true';
const emojis = req.query.emojis === 'true';
if (!country || country.toUpperCase() === 'ALL') {
if (format.toLowerCase() === 'json') {
return getJSONData().then(result => {
return res.json(result);
Expand All @@ -79,13 +75,13 @@ app.get('/:country', (req, res) => {
}).catch(error => errorHandler(error, res));
}

let lookupObj = lookupCountry(country);
const lookupObj = lookupCountry(country);

if (!lookupObj) {
return res.send(`
Country not found.
Try full country name or country code.
Ex:
Try the full country name or country code.
Example:
- /UK: for United Kingdom
- /US: for United States of America.
- /Italy: for Italy.
Expand All @@ -106,5 +102,4 @@ app.get('/:country', (req, res) => {
}).catch(error => errorHandler(error, res));
});


app.listen(port, () => console.log(`Running on ${port}`));
app.listen(port, () => console.log(`Running on ${port}`));
11 changes: 7 additions & 4 deletions bin/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env node

// eslint-disable-next-line no-unused-vars
const yargonaut = require('yargonaut').style('green');
const yargs = require('yargs');
const chalk = require('chalk');
Expand All @@ -7,12 +9,13 @@ const { getCountryTable } = require('../lib/byCountry');
const { lookupCountry } = require('../lib/helpers');

const { argv } = yargs
.command('$0 [country]','Tool to track COVID-19 statistics from terminal', yargs =>
.command('$0 [country]', 'Tool to track COVID-19 statistics from terminal', yargs =>
yargs.positional('country', {
coerce(arg) {
if ('ALL' === arg.toUpperCase()) {
if (arg.toUpperCase() === 'ALL') {
return 'ALL';
}

const country = lookupCountry(arg);
if (!country) {
let error = `Country '${arg}' not found.\n`;
Expand All @@ -23,6 +26,7 @@ const { argv } = yargs
error += '- Italy: for Italy.\n';
throw new Error(chalk.red.bold(error));
}

return country.iso2;
},
describe: 'Filter table by country',
Expand Down Expand Up @@ -57,12 +61,11 @@ const { argv } = yargs
.strict()
.help('help');


const { emojis, country, minimal, top } = argv;
(
country === 'ALL'
? getCompleteTable({ emojis, minimal, top })
: getCountryTable({ countryCode: country, emojis, minimal })
)
.then(console.log)
.catch(console.error);
.catch(console.error);
12 changes: 9 additions & 3 deletions lib/api.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
const NodeCache = require('node-cache');
const axios = require('axios');
const myCache = new NodeCache( { stdTTL: 100, checkperiod: 600 } );

const myCache = new NodeCache({ stdTTL: 100, checkperiod: 600 });
const CORONA_ALL_KEY = 'coronaAll';

exports.getCoronaData = async () => {
const coronaCache = myCache.get(CORONA_ALL_KEY);

if (coronaCache) {
return coronaCache;
}

const result = await axios('https://coronavirus-tracker-api.herokuapp.com/all');

if (!result || !result.data) {
throw new Error(`Source API faliure.`);
throw new Error('Source API failure.');
}

myCache.set(CORONA_ALL_KEY, result.data, 60 * 15);

return result.data;
}
};
50 changes: 23 additions & 27 deletions lib/byCountry.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
const Table = require('cli-table3');
const axios = require('axios');
const _ = require('lodash');
const chalk = require('chalk');
const helpers = require('./helpers');
const api = require('./api');
const stripAnsi = require('strip-ansi');
const {
getCountry,
getConfirmed,
getActive,
getDeaths,
Expand All @@ -19,7 +16,6 @@ const {
calRecoveredPer,
getOneDayChange,
getOneWeekChange,
getRateOfGrowth,
getTotalStats,
footer,
} = require('./helpers');
Expand Down Expand Up @@ -52,35 +48,35 @@ function getDataByState(confirmed, deaths, recovered) {
const countryArr = extraStats(
Object.keys(countryMap).map(key => countryMap[key])
);
return _.sortBy(countryArr, (o) => -o.confirmed)
return _.sortBy(countryArr, (o) => -o.confirmed);
}

function extraStats(dataArr) {
return dataArr.map(obj => Object.assign({}, obj,
{
active: calActive(obj),
mortalityPer: calMortalityPer(obj),
recoveredPer: calRecoveredPer(obj),
})
return dataArr.map(obj => ({
...obj,
active: calActive(obj),
mortalityPer: calMortalityPer(obj),
recoveredPer: calRecoveredPer(obj),
})
);
}

exports.getJSONData = async () => {
const data = await api.getCoronaData();
const { latest, confirmed, deaths, recovered } = data;
const { confirmed, deaths, recovered } = data;
const countryData = getDataByState(confirmed, deaths, recovered);
const totalStats = getTotalStats(countryData);
totalStats.country = 'World';
return countryData.concat(totalStats);
}
};

exports.getJSONDataForCountry = async (countryCode) => {
const data = await api.getCoronaData();
const { latest, confirmed, deaths, recovered } = data;
const countryData = getDataByState(confirmed, deaths, recovered, countryCode)
const { confirmed, deaths, recovered } = data;
const countryData = getDataByState(confirmed, deaths, recovered)
.filter(obj => obj.countryCode === countryCode);
return countryData;
}
};

exports.getCountryTable = async ({
countryCode,
Expand All @@ -94,11 +90,11 @@ exports.getCountryTable = async ({
style: helpers.getTableStyles(minimal),
});
const data = await api.getCoronaData();
const { latest, confirmed, deaths, recovered } = data;
const { confirmed, deaths, recovered } = data;
const countryData = getDataByState(confirmed, deaths, recovered)
.filter(obj => obj.countryCode === countryCode);

if(countryData.length === 0) {
if (countryData.length === 0) {
throw new Error(`Country code ${countryCode} does not match anything in the database.`);
}

Expand All @@ -114,10 +110,9 @@ exports.getCountryTable = async ({
getRecoveredPer(totalStats.recoveredPer),
getOneDayChange(totalStats),
getOneWeekChange(totalStats),
// '',
// getEmoji(countryData[0].countryCode),
]
})
});

if (countryData.length > 1) {
let rank = 1;
countryData.forEach(cd => {
Expand All @@ -132,13 +127,13 @@ exports.getCountryTable = async ({
getRecoveredPer(cd.recoveredPer),
getOneDayChange(cd),
getOneWeekChange(cd),
// getRateOfGrowth(cd),
... (emojis ? [countryEmoji] : [])
]
table.push({ [rank++]: values })
...(emojis ? [countryEmoji] : [])
];
table.push({ [rank++]: values });
});
}
const lastUpdated = countryData[0].lastUpdated;

const { lastUpdated } = countryData[0];
if (!isCurl) {
const template = `<!DOCTYPE html>
<html lang="en">
Expand All @@ -164,5 +159,6 @@ exports.getCountryTable = async ({
</html>`;
return stripAnsi(template);
}

return table.toString() + footer(lastUpdated);
}
};
Loading