diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..4d4fc43 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,16 @@ +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 +workflows: + build-and-test: + jobs: + - build-and-test 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 diff --git a/app.js b/app.js index eb160ae..dae7040 100644 --- a/app.js +++ b/app.js @@ -30,6 +30,31 @@ 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(); +}); + +// 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'], @@ -50,6 +75,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..e11c5f7 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -1,36 +1,46 @@ /* 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;}, + greenBright = (txt) => {return color.greenBright.open+txt+color.greenBright.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')); +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 = (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 @@ -66,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), @@ -80,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 @@ -88,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')}], @@ -96,18 +127,77 @@ 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)], + [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) => { + 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} + + "${randomSay()}" + `; + 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} + + "${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! @@ -116,3 +206,13 @@ const footer = ` --- Follow ${cyanBG(black('@warengonzaga'))} for more updates! \n`; + +// cli plain footer +const plainfooter = ` + --- + Love this project? Please consider buying me a cup of coffee! + [ warengonzaga.com/buymeacoffee ] + + --- + Follow [ @warengonzaga ] for more updates! +\n`; diff --git a/lib/sayings/threads.json b/lib/sayings/threads.json new file mode 100644 index 0000000..eedf230 --- /dev/null +++ b/lib/sayings/threads.json @@ -0,0 +1,22 @@ +[ + "Always 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 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": {