From 00a71914e1c1c6bfeff2822c36cdacc8c08250de Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Mon, 23 Mar 2020 20:04:40 +0800 Subject: [PATCH 1/7] Add .circleci/config.yml --- .circleci/config.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..4a8a9e2 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,17 @@ +version: 2.1 +orbs: + node: circleci/node@1.1.6 +jobs: + build-and-test: + executor: + name: node/default + steps: + - checkout + - node/with-cache: + steps: + - run: npm install + - run: npm test +workflows: + build-and-test: + jobs: + - build-and-test \ No newline at end of file From acafc4a922f809ef3574ade1a85f616d0d517e6d Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Mon, 23 Mar 2020 20:13:11 +0800 Subject: [PATCH 2/7] Update config.yml --- .circleci/config.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4a8a9e2..4d4fc43 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,8 +10,7 @@ jobs: - node/with-cache: steps: - run: npm install - - run: npm test workflows: build-and-test: jobs: - - build-and-test \ No newline at end of file + - build-and-test From 68b1c69bc6f27e5731dd026ad01642b9ef042b54 Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Tue, 24 Mar 2020 04:21:15 +0800 Subject: [PATCH 3/7] Add Windows CMD support --- app.js | 35 ++++++++++++++++ lib/cli/index.js | 102 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 121 insertions(+), 16 deletions(-) diff --git a/app.js b/app.js index eb160ae..d622fa4 100644 --- a/app.js +++ b/app.js @@ -30,6 +30,21 @@ app.get('/', async (req, res, next) => { return next(); }); +// for cmd and powershell +app.get(['/plain','/cmd','/basic'], async (req, res, next) => { + const userAgent = req.headers['user-agent'], + api = await axios.get(`${apiBaseURL}/all`), + data = api.data; + if (util.isCommandline(userAgent)) { + await res.send(covid19.plainglobaltracker( + data.cases, data.deaths, + data.recovered, data.updated + )); + return null; + } + return next(); +}); + // by country route for covid19 tracker app.get('/:country', async (req, res, next) => { const userAgent = req.headers['user-agent'], @@ -50,6 +65,26 @@ app.get('/:country', async (req, res, next) => { return next(); }); +// by country route for covid19 tracker +app.get(['/plain/:country','/cmd/:country','/basic/:country'], async (req, res, next) => { + const userAgent = req.headers['user-agent'], + countryData = req.params.country, + api = await axios.get(`${apiBaseURL}/countries/${countryData}`), + all = await axios.get(`${apiBaseURL}/all`), + u = all.data, + d = api.data; + if (util.isCommandline(userAgent)) { + await res.send(covid19.plaincountrytracker( + d.country, d.cases, d.todayCases, + d.deaths, d.todayDeaths, d.recovered, + d.active, d.critical, d.casesPerOneMillion, + u.updated + )); + return null; + } + return next(); +}); + app.get('*', (req, res) => res.send(` Sorry, CLI version is only available at the moment... \n diff --git a/lib/cli/index.js b/lib/cli/index.js index 9a8d5d0..308bfe8 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -1,36 +1,38 @@ /* eslint-disable no-await-in-loop */ -const style = require('ansi-styles'), +const color = require('ansi-styles'), fs = require('fs'), table3 = require('cli-table3'); -// ansi style and colors +// ansi colors const // table color tblclr = (border) => {return cyan(border);}, // normal ansi colors - white = (txt) => {return style.white.open+txt+style.white.close;}, - black = (txt) => {return style.black.open+txt+style.black.close;}, - green = (txt) => {return style.green.open+txt+style.green.close;}, - cyan = (txt) => {return style.cyan.open+txt+style.cyan.close;}, - magenta = (txt) => {return style.magenta.open+txt+style.magenta.close;}, - yellow = (txt) => {return style.yellow.open+txt+style.yellow.close;}, - red = (txt) => {return style.red.open+txt+style.red.close;}, + white = (txt) => {return color.white.open+txt+color.white.close;}, + black = (txt) => {return color.black.open+txt+color.black.close;}, + green = (txt) => {return color.green.open+txt+color.green.close;}, + cyan = (txt) => {return color.cyan.open+txt+color.cyan.close;}, + magenta = (txt) => {return color.magenta.open+txt+color.magenta.close;}, + yellow = (txt) => {return color.yellow.open+txt+color.yellow.close;}, + red = (txt) => {return color.red.open+txt+color.red.close;}, // bright ansi colors - cyanBright = (txt) => {return style.cyanBright.open+txt+style.cyanBright.close;}, - magentaBright = (txt) => {return style.magentaBright.open+txt+style.magentaBright.close;}, - redBright = (txt) => {return style.redBright.open+txt+style.redBright.close;}, + cyanBright = (txt) => {return color.cyanBright.open+txt+color.cyanBright.close;}, + magentaBright = (txt) => {return color.magentaBright.open+txt+color.magentaBright.close;}, + redBright = (txt) => {return color.redBright.open+txt+color.redBright.close;}, // background ansi color - cyanBG = (txt) => {return style.bgCyan.open+txt+style.bgCyan.close;}; + cyanBG = (txt) => {return color.bgCyan.open+txt+color.bgCyan.close;}, + // horizontal line + line = '-'.repeat(60); // package.json information const pkg = JSON.parse(fs.readFileSync('package.json')); // format data -const formatNumber = (num) => { - return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); +const formatNumber = (value) => { + return value.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); }; // time data @@ -96,7 +98,7 @@ exports.covid19countrytracker = (n, c, tC, d, tD, r, a, cl, cPOM, u) => { }); table.push( [{colSpan:5,content:yellow('As of '+asof.toLocaleString()+' [Date:'+currentdate+']')}], - [magenta('Cases'), red('Deaths'), green('Recovered'), cyan('Active'), cyanBright('Cases Per Million')], + [magenta('Cases'), red('Deaths'), green('Recovered'), cyan('Active'), cyanBright('Cases/Million')], [formatNumber(cases), formatNumber(deaths), formatNumber(recovered), formatNumber(active), formatNumber(casesPerOneMillion)], [magentaBright('Today Cases'), redBright('Today Deaths'), redBright('Critical'), red('Mortality %'), green('Recovered %')], [formatNumber(todayCases), formatNumber(todayDeaths), formatNumber(critical), mortalityPercentage.toFixed(2), recoveredPercentage.toFixed(2)], @@ -105,6 +107,62 @@ exports.covid19countrytracker = (n, c, tC, d, tD, r, a, cl, cPOM, u) => { return table.toString()+'\n'+footer; }; +exports.plainglobaltracker = (c, d, r, u) => { + const cases = c, deaths = d, recovered = r, asof = new Date(u), + mortalityPercentage = (d/c)*100, recoveredPercentage = (r/c)*100; + + const visual = ` + ${line} + COVID-19 Tracker CLI v${pkg.version} - Global Update + ${line} + As of ${asof.toLocaleString()} [Date: ${currentdate}] + ${line} + Cases | ${formatNumber(cases)} + Deaths | ${formatNumber(deaths)} + Mortality % | ${mortalityPercentage.toFixed(2)} + Recovered | ${formatNumber(recovered)} + Recovery % | ${recoveredPercentage.toFixed(2)} + ${line} + ${source} + ${line} + ${repo} + ${line} + `; + return visual+plainfooter; +}; + +exports.plaincountrytracker = (n, c, tC, d, tD, r, a, cl, cPOM, u) => { + const name = n, cases = c, todayCases = tC, + deaths = d, todayDeaths = tD, recovered = r, + active = a, critical = cl, casesPerOneMillion = cPOM, + mortalityPercentage = (d/c)*100, recoveredPercentage = (r/c)*100, + asof = new Date(u); + + const visual = ` + ${line} + COVID-19 Tracker CLI v${pkg.version} - ${name} Update + ${line} + As of ${asof.toLocaleString()} [Date: ${currentdate}] + ${line} + Cases | ${formatNumber(cases)} + Today Cases | ${formatNumber(todayCases)} + Deaths | ${formatNumber(deaths)} + Today Deaths | ${formatNumber(todayDeaths)} + Critical | ${formatNumber(critical)} + Mortality % | ${mortalityPercentage.toFixed(2)} + Recovered | ${formatNumber(recovered)} + Recovery % | ${recoveredPercentage.toFixed(2)} + Active | ${formatNumber(active)} + Cases/Million | ${formatNumber(casesPerOneMillion)} + ${line} + ${source} + ${line} + ${repo} + ${line} + `; + return visual+plainfooter; +}; + // cli footer const footer = ` Always wash your hands, stay safe... @@ -116,3 +174,15 @@ const footer = ` --- Follow ${cyanBG(black('@warengonzaga'))} for more updates! \n`; + +// cli plain footer +const plainfooter = ` + Always wash your hands, stay safe... + + --- + Love this project? Please consider buying me a cup of coffee! + [ warengonzaga.com/buymeacoffee ] + + --- + Follow [ @warengonzaga ] for more updates! +\n`; From 6cc4c6b4690c512c266fda6a07d3f9b5bb957e7d Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Tue, 24 Mar 2020 04:21:39 +0800 Subject: [PATCH 4/7] Update version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8118158..21e442d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "covid19-tracker-cli", - "version": "1.0.0", + "version": "2.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 07e3b7c..7906177 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "covid19-tracker-cli", - "version": "2.1.0", + "version": "2.5.0", "description": "Track COVID-19 cases from command line interface", "main": "app.js", "scripts": { From 9c5fd1e42c836a998c3831d8a43fc1f4ee68398c Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Tue, 24 Mar 2020 04:21:55 +0800 Subject: [PATCH 5/7] Update readme file --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9ef1385..3f0e605 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,12 @@ This simple application offers you the following features... * Optimized application. * Fast response time (~< 100ms). * Simple layout and easy to understand. -* By country query (```/country```). +* By country query. + * e.g. (```/country```). +* Windows CMD support. + * e.g. (```/cmd``` or ```/cmd/country```). +* Plain or Basic version. + * e.g. (```/plain``` or ```/plain/country```) or (```/basic```, ```/basic/country```). _More features coming soon..._ @@ -87,10 +92,8 @@ If you're facing a problem in using COVID-19 Tracker CLI please let me know by c ## To Do -* CI (CircleCI) * Local Version * Add Static Version -* Official Logo * Sample Usage (gif) * Add HTTP Headers (currently F) * More Code Refactor! (I guess I know what I'm doing now... for sure) @@ -155,7 +158,6 @@ COVID-19 Tracker CLI is licensed under MIT - -* ## Resources From dce7c02f599ae11082b4735e60a694012a7eab69 Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Tue, 24 Mar 2020 06:33:29 +0800 Subject: [PATCH 6/7] Add random health saying --- app.js | 10 +++++++++ lib/cli/index.js | 46 +++++++++++++++++++++++++++++++++------- lib/sayings/threads.json | 22 +++++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 lib/sayings/threads.json diff --git a/app.js b/app.js index d622fa4..dae7040 100644 --- a/app.js +++ b/app.js @@ -45,6 +45,16 @@ app.get(['/plain','/cmd','/basic'], async (req, res, next) => { return next(); }); +// help options +app.get(['/help','/manual'], async (req, res, next) => { + const userAgent = req.headers['user-agent']; + if (util.isCommandline(userAgent)) { + await res.send(covid19.help()); + return null; + } + return next(); +}); + // by country route for covid19 tracker app.get('/:country', async (req, res, next) => { const userAgent = req.headers['user-agent'], diff --git a/lib/cli/index.js b/lib/cli/index.js index 308bfe8..e11c5f7 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -21,6 +21,7 @@ const cyanBright = (txt) => {return color.cyanBright.open+txt+color.cyanBright.close;}, magentaBright = (txt) => {return color.magentaBright.open+txt+color.magentaBright.close;}, redBright = (txt) => {return color.redBright.open+txt+color.redBright.close;}, + greenBright = (txt) => {return color.greenBright.open+txt+color.greenBright.close;}, // background ansi color cyanBG = (txt) => {return color.bgCyan.open+txt+color.bgCyan.close;}, // horizontal line @@ -29,6 +30,13 @@ const // package.json information const pkg = JSON.parse(fs.readFileSync('package.json')); +const say = JSON.parse(fs.readFileSync('./lib/sayings/threads.json')); + +// random sayings +const randomSay = () => { + let random = Math.floor(Math.random() * say.length); + return say[random]; +}; // format data const formatNumber = (value) => { @@ -68,6 +76,27 @@ const source = 'Source: https://www.worldometers.info/coronavirus/', sourceCountry = {colSpan:5,content:source}, repoCountry = {colSpan:5,content:repo}; +// help menu +exports.help = () => { + const manual = ` + ${line} + COVID-19 Tracker CLI v${pkg.version} by Waren Gonzaga + ${line} + + /country or /code ......... by country query + ex. /philippines or /ph + + /cmd ...................... if using CMD + + /plain or /basic .......... if your cli does not support ansi encoding + + ${line} + + "${randomSay()}" + `; + return manual+plainfooter; +}; + // covid19 global tracker exports.covid19globaltracker = (c, d, r, u) => { const cases = c, deaths = d, recovered = r, asof = new Date(u), @@ -82,7 +111,7 @@ exports.covid19globaltracker = (c, d, r, u) => { [formatNumber(cases), formatNumber(deaths), formatNumber(recovered), mortalityPercentage.toFixed(2), recoveredPercentage.toFixed(2)], [sourceGlobal],[repoGlobal] ); - return table.toString()+'\n'+footer; + return table.toString()+'\n\n'+' '+'"'+green(randomSay())+'"'+footer; }; // covid19 country tracker @@ -90,7 +119,7 @@ exports.covid19countrytracker = (n, c, tC, d, tD, r, a, cl, cPOM, u) => { const name = n, cases = c, todayCases = tC, deaths = d, todayDeaths = tD, recovered = r, active = a, critical = cl, casesPerOneMillion = cPOM, - mortalityPercentage = (d/c)*100, recoveredPercentage = (r/c)*100, + mortalityPercentage = (d/c)*100, recoveryPercentage = (r/c)*100, asof = new Date(u); table = new table3({ head: [{colSpan:5,content:white('COVID-19 Tracker CLI v'+pkg.version+' - '+name+' Update')}], @@ -100,11 +129,11 @@ exports.covid19countrytracker = (n, c, tC, d, tD, r, a, cl, cPOM, u) => { [{colSpan:5,content:yellow('As of '+asof.toLocaleString()+' [Date:'+currentdate+']')}], [magenta('Cases'), red('Deaths'), green('Recovered'), cyan('Active'), cyanBright('Cases/Million')], [formatNumber(cases), formatNumber(deaths), formatNumber(recovered), formatNumber(active), formatNumber(casesPerOneMillion)], - [magentaBright('Today Cases'), redBright('Today Deaths'), redBright('Critical'), red('Mortality %'), green('Recovered %')], - [formatNumber(todayCases), formatNumber(todayDeaths), formatNumber(critical), mortalityPercentage.toFixed(2), recoveredPercentage.toFixed(2)], + [magentaBright('Today Cases'), redBright('Today Deaths'), redBright('Critical'), red('Mortality %'), greenBright('Recovery %')], + [formatNumber(todayCases), formatNumber(todayDeaths), formatNumber(critical), mortalityPercentage.toFixed(2), recoveryPercentage.toFixed(2)], [sourceCountry],[repoCountry] ); - return table.toString()+'\n'+footer; + return table.toString()+'\n\n'+' '+'"'+green(randomSay())+'"'+footer; }; exports.plainglobaltracker = (c, d, r, u) => { @@ -127,6 +156,8 @@ exports.plainglobaltracker = (c, d, r, u) => { ${line} ${repo} ${line} + + "${randomSay()}" `; return visual+plainfooter; }; @@ -159,13 +190,14 @@ exports.plaincountrytracker = (n, c, tC, d, tD, r, a, cl, cPOM, u) => { ${line} ${repo} ${line} + + "${randomSay()}" `; return visual+plainfooter; }; // cli footer const footer = ` - Always wash your hands, stay safe... --- Love this project? Please consider buying me a cup of coffee! @@ -177,8 +209,6 @@ const footer = ` // cli plain footer const plainfooter = ` - Always wash your hands, stay safe... - --- Love this project? Please consider buying me a cup of coffee! [ warengonzaga.com/buymeacoffee ] diff --git a/lib/sayings/threads.json b/lib/sayings/threads.json new file mode 100644 index 0000000..a00c7d3 --- /dev/null +++ b/lib/sayings/threads.json @@ -0,0 +1,22 @@ +[ + "Alays wash your hands, stay safe!", + "Stay healthy, stay at home...", + "Play online games with your friends", + "Stay on your home!", + "Avoid fake news...", + "Eat healthy foods, sleep on time", + "We will survive!", + "Code with Love by Waren", + "COVID-19 is a serious matter", + "Don't touch your face! wash your hands", + "Social distancing is real...", + "Developer from Philippines", + "Support open-source!", + "A cup of coffee will keep this project updated", + "Can you send some coffee to the developer?", + "Stay at home, play games instead...", + "Uninstall 2020, virus detected!", + "Always wear a mask when you go outside", + "Watch news to keep updated!", + "Support the developer, buy him a coffee!" +] \ No newline at end of file From fc8aa283baaefeb1a68afb91163c1b60d6b251f9 Mon Sep 17 00:00:00 2001 From: Waren Gonzaga Date: Tue, 24 Mar 2020 07:00:51 +0800 Subject: [PATCH 7/7] Fix typo --- lib/sayings/threads.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/sayings/threads.json b/lib/sayings/threads.json index a00c7d3..eedf230 100644 --- a/lib/sayings/threads.json +++ b/lib/sayings/threads.json @@ -1,5 +1,5 @@ [ - "Alays wash your hands, stay safe!", + "Always wash your hands, stay safe!", "Stay healthy, stay at home...", "Play online games with your friends", "Stay on your home!",