UNPKG

cabdriver

Version:

Helps you to fill in your hours with taxi

334 lines (291 loc) 11 kB
'use strict'; var Async = require('async'); var Moment = require('moment-timezone'); var Pad = require('pad'); var _ = require('lodash'); var GoogleAuth = require('../lib/auth/google_auth'); var SlackAuth = require('../lib/auth/slack_auth'); var JiraAuth = require('../lib/auth/jira_auth'); var ZebraAuth = require('../lib/auth/zebra_auth'); var GithubAuth = require('../lib/auth/github_auth'); var GitlabAuth = require('../lib/auth/gitlab_auth'); var NullAuth = require('../lib/auth/null_auth'); var GoogleCalendar = require('../lib/source/calendar'); var GoogleMail = require('../lib/source/mail'); var Slack = require('../lib/source/slack'); var Logbot = require('../lib/source/logbot'); var Jira = require('../lib/source/jira'); var Zebra = require('../lib/source/zebra'); var Git = require('../lib/source/git'); var Github = require('../lib/source/github'); var Gitlab = require('../lib/source/gitlab'); var date = require('../lib/date'); var util = require('../lib/util'); var Cli = require('./cli'); class FetchCli extends Cli { constructor(programOpts, configPath, sources) { super(programOpts, configPath); this.sources = sources || { calendar: { source: GoogleCalendar, auth: GoogleAuth }, mail: { source: GoogleMail, auth: GoogleAuth }, git: { source: Git, auth: NullAuth }, gitlab: { source: Gitlab, auth: GitlabAuth }, github: { source: Github, auth: GithubAuth }, jira: { source: Jira, auth: JiraAuth }, slack: { source: Slack, auth: SlackAuth }, logbot: { source: Logbot, auth: SlackAuth }, zebra: { source: Zebra, auth: ZebraAuth } }; this.updateOptions(this.options); } run() { super.run(); var me = this; me.querySources(function(err, results) { if (err) { console.error('Error occured: ', err); return; } try { results = me.postProcess(results); me.printResults(results); process.exit(0); } catch (e) { console.error('Error occured: ', e); process.exit(1); } }); } postProcess(results) { var me = this; // map results to user-defined projects results = _.map(results, function(msg) { return me.mapProjects(msg); }); // remove `null` entries results = _.filter(results, function(msg) { return !_.isNull(msg); }); return results; } mapProjects(msg) { var me = this; var mapping = me.getMapping(); if (!mapping) { return msg; } _.forEach(mapping, function(patterns, key) { var projectMatch = _.some(patterns, function(pattern) { var re = new RegExp(pattern, 'i'); return re.test(msg.project) || re.test(msg.text); }); if (projectMatch && ['__comment__', '__remove__'].indexOf(key) === -1) { msg.project = key; return false; } }); msg = me.handleComments(msg, mapping); msg = me.handleRemove(msg, mapping); return msg; } handleComments(msg, mapping) { if (mapping['__comment__']) { var commentMatch = _.some(mapping['__comment__'], function(pattern) { var re = new RegExp(pattern, 'i'); return re.test(msg.project) || re.test(msg.text); }); if (commentMatch) { msg.comment = true; } } return msg; } handleRemove(msg, mapping) { var me = this; if (mapping['__remove__']) { var removeMatch = _.some(mapping['__remove__'], function(pattern) { var re = new RegExp(pattern, 'i'); return re.test(msg.project) || re.test(msg.text); }); if (removeMatch && me.options.verbose) { msg.comment = true; msg.text = msg.text + ' [REMOVED]'; } else if (removeMatch) { msg = null; } } return msg; } getMapping() { var me = this; if (me.config.mapping) { return me.config.mapping; } return {}; } getCmdName() { return 'fetch'; } querySources(exitCallback) { var me = this; var sources = me.getSources(); var sourceEntries = me.getSourceEntries(sources); Async.parallel( Async.reflectAll(sourceEntries), function(err, allResults) { if (err) { exitCallback(err); return; } var results = []; _.each(allResults, function(result, key) { if (result.value) { results = results.concat(result.value); } else { console.error(''); console.error(key + ' source failed: ' + result.error); } }); exitCallback(null, results); }); } getSources() { var me = this; var sources = _.mapValues(me.sources, function(config) { return new config.source(me.options, new config.auth()); }); return sources; } getSourceEntries(sources) { var me = this; var sourceEntries = _.mapValues( sources, function(source) { return function(callback) { source.getEntries(me.config) .then(function(entries) { callback(null, entries); }) .catch(callback); }; } ); return sourceEntries; } // eslint-disable-next-line max-lines-per-function updateOptions(options) { var me = this; options = options || {}; var calledWithSources = me.sourcesInOptions(me.programOpts); if (calledWithSources) { _.assignIn(options, me.config.defaults, me.programOpts); } else { _.assignIn(options, me.programOpts, me.config.defaults); } var sourcesInOptions = me.sourcesInOptions(options); if (!sourcesInOptions) { options.calendar = true; } const {startDate, endDate} = me.validateDate(options.date); options['startDate'] = startDate; options['endDate'] = endDate; if (options.verbose) { console.log('Start date: %s', Moment.tz(options['startDate'], 'Europe/Zurich').format('DD.MM.YYYY')); console.log('End date: %s', Moment.tz(options['endDate'], 'Europe/Zurich').format('DD.MM.YYYY')); console.log('Calendar: %s', options.calendar); console.log('Mail: %s', options.mail); console.log('Slack: %s', options.slack); console.log('Logbot: %s', options.logbot); console.log('Jira: %s', options.jira); console.log('Zebra: %s', options.zebra); console.log('Git: %s', options.git); console.log('Github: %s', options.github); console.log('Gitlab: %s', options.gitlab); console.log('Pie chart: %s', options.pie); console.log('Hours: %s', options.hours); console.log('Count: %s', options.number); console.log('Config: %s', options.config); } return options; } validateDate(dateStr) { var dates = date.getStartAndEndDate(dateStr); Moment.suppressDeprecationWarnings = true; if (!Moment(dates['endDate']).isValid() || !Moment(dates['startDate']).isValid()) { console.error('Please enter a valid date range'); process.exit(1); } return dates; } sourcesInOptions(opts) { var me = this; var sourceKeys = _.keys(me.sources); return _.some(opts, function(value, key) { return sourceKeys.indexOf(key) >= 0 && value; }); } printResults(results) { var me = this; var orderedResults = me.groupByAndSort(results); //print a section for each day separated by type _.each(orderedResults, me.printResultDay.bind(me)); } printResultDay(msgs, timestamp) { var me = this; var day = Moment.unix(timestamp).tz('Europe/Zurich'); var allProjects = _.keys(_.groupBy(msgs, 'project')); var maxProjectLength = allProjects.reduce(function (a, b) { return a.length > b.length ? a : b; }).length; var projectPadding = Math.max(5, maxProjectLength + 1); var allTimes = _.keys(_.groupBy(msgs, 'time')); var maxTimeLength = allTimes.reduce(function (a, b) { return a.length > b.length ? a : b; }).length; var timePadding = Math.max(2, maxTimeLength + 1); msgs = _.groupBy(msgs, 'type'); console.log(''); console.log('%s # %s', day.format('DD/MM/YYYY'), day.format('dddd')); _.each(msgs, me.printResultType(projectPadding, timePadding)); } printResultType(projectPadding, timePadding) { return function(msgs, type) { var total = _.reduce(msgs, function(sum, msg) { var time = util.filterFloat(msg.time); if (_.isNaN(time)) { time = date.parseTimeRange(msg.time); } return sum + (_.isNaN(time) ? 0 : time); }, 0); total = total.toFixed(2); console.log(''); process.stdout.write('# ' + type); if (total > 0) { process.stdout.write(' (Total: ' + total + 'h)'); } process.stdout.write('\n'); console.log('#------------------'); _.each(msgs, function(msg) { if (_.has(msg, 'raw') && msg.raw) { console.log(msg.raw); } else { var text = Pad(msg.project, projectPadding); if (msg.time) { text += Pad(msg.time, timePadding); } text += msg.text; if (msg.comment) { text = '# ' + text; } console.log(text); } }); }; } groupByAndSort(results) { //group by and order the result object based on timestamp results = _.groupBy(results, 'timestamp'); var orderedResults = {}; Object.keys(results).sort().forEach(function(key) { orderedResults[key] = results[key]; }); return orderedResults; } } module.exports = FetchCli;