Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

auto-timesheet

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

auto-timesheet - npm Package Compare versions

Comparing version 0.0.38 to 0.0.39

src/updates.js

5

package.json
{
"name": "auto-timesheet",
"version": "0.0.38",
"version": "0.0.39",
"description": "Add redmine timesheet automatically and periodically.",

@@ -33,2 +33,3 @@ "main": "./src/bin/auto-timesheet.js",

"bluebird": "^3.5.0",
"cat-facts": "^1.0.2",
"cat-me": "^1.0.3",

@@ -49,3 +50,3 @@ "chalk": "^2.0.1",

"serialize-error": "^2.1.0",
"update-available": "^1.0.1",
"update-notifier": "^2.2.0",
"user-home": "^2.0.0"

@@ -52,0 +53,0 @@ },

43

src/bin/auto-timesheet-conf.js

@@ -8,2 +8,3 @@ #!/usr/bin/env node

const fileName = require('../config/internals.json').configFileName;
const chalk = require('chalk');

@@ -13,27 +14,27 @@ const configFile = path.join(home, fileName);

try {
// check if the conf exists or not
require(configFile);
console.log('config file found: opening editor..');
openEditor();
// check if the conf exists or not
require(configFile);
console.log(chalk.gray(' > config file found'));
openEditor();
} catch (err) {
if (err instanceof SyntaxError) {
console.log('syntax err found in the config file > regenerating ...');
}
// make the file with initial values
else {
console.log('Initializing credentials ...');
}
confGen(configFile, openEditor);
if (err instanceof SyntaxError) {
console.log(chalk.red(' > syntax err found in the config file'));
console.log(chalk.cyan(' > regenerating file'));
}
// make the file with initial values
else {
console.log(chalk.gray(' > Initializing credentials ...'));
}
confGen(configFile, openEditor);
}
function openEditor() {
console.log('opening editor');
return editor(configFile, function(code) {
if (code !== 0) throw new Error('something went wrong while saving configuration');
console.log(chalk.gray(' > opening editor..'));
return editor(configFile, function(code) {
if (code !== 0) throw new Error('something went wrong while saving configuration');
console.log('You\'ve edited config successfully!');
console.log('------------------------------------------------');
console.log('run `auto-timesheet start` to start the app');
console.log('------------------------------------------------enjoy');
});
}
console.log(chalk.green(' > You\'ve edited config successfully!'));
console.log(chalk.gray('------------------------------------------------\n'));
console.log('run ' + chalk.yellow('`auto-timesheet start`') + ' to start the app\n');
});
}

@@ -7,11 +7,11 @@ #!/usr/bin/env node

credVerifier()
.then(() => {
lme.d('auto-timesheet starting...');
app();
})
.catch(err => {
lme.e(err);
process.exit(1);
});
.then(() => {
console.log('\n');
app();
})
.catch(err => {
lme.e(err);
console.log('\n');
process.exit(1);
});

@@ -5,7 +5,10 @@ #!/usr/bin/env node

const version = require('../../package.json').version;
const checkUpdates = require('../updates');
checkUpdates();
program
.version(version)
.command('conf', 'configure stuff')
.command('start', 'start application')
.parse(process.argv);
.version(version)
.command('conf', 'configure stuff')
.command('start', 'start application')
.parse(process.argv);

@@ -12,17 +12,17 @@ const userHome = require('user-home');

try {
console.log(chalk.gray('Loading Formation..'));
conf = require(file);
console.log(chalk.gray('Positioning Players..\nDone!'));
console.log(chalk.gray('Loading Formation..'));
conf = require(file);
console.log(chalk.gray('Positioning Players..\nDone!'));
} catch (err) {
if (err instanceof SyntaxError) {
lme.e('Syntax err found in conf file');
console.log(chalk.gray('try running ') + chalk.yellow(`auto-timesheet conf`) + chalk.gray(' again'));
} else {
lme.e('couldnt find config file.')
console.log(chalk.gray('try running ') + chalk.yellow(`auto-timesheet conf`));
}
process.exit(1);
if (err instanceof SyntaxError) {
lme.e('Syntax err found in conf file');
console.log(chalk.gray('try running ') + chalk.yellow('auto-timesheet conf') + chalk.gray(' again'));
} else {
lme.e('couldnt find config file.');
console.log(chalk.gray('try running ') + chalk.yellow('auto-timesheet conf'));
}
process.exit(1);
}
module.exports = conf;
module.exports = conf;

@@ -7,11 +7,11 @@ const jsonfile = require('jsonfile');

jsonfile.writeFile(configFile, template, { spaces: 2 }, err => {
if (err) {
lme.e('Something went wrong while trying to generate credential template!');
console.log(err);
throw err;
}
callback();
})
jsonfile.writeFile(configFile, template, { spaces: 2 }, err => {
if (err) {
lme.e('Something went wrong while trying to generate credential template!');
console.log(err);
throw err;
}
callback();
});
};
};

@@ -17,69 +17,69 @@ const prompt = require('prompt');

const schema = {
properties: {
timesheetPsw: {
description: 'Timesheet password :',
required: true,
hidden: true,
},
gitPsw: {
description: 'Git-service password :',
hidden: true,
required: true
}
}
properties: {
timesheetPsw: {
description: 'Timesheet password :',
required: true,
hidden: true,
},
gitPsw: {
description: 'Git-service password :',
hidden: true,
required: true
}
}
};
module.exports = () => {
return new Promise((resolve, reject) => {
prompt.start();
prompt.get(schema, function(err, result) {
if (err) {
console.log('cancelled');
process.exit(0)
}
return new Promise((resolve, reject) => {
prompt.start();
prompt.get(schema, function(err, result) {
if (err) {
console.log('cancelled');
process.exit(0);
}
// spin your head
spinner = ora(chalk.grey('Checking the pitch..')).start();
// spin your head
spinner = ora(chalk.grey('Checking the pitch..')).start();
// set cred
cache.set('timesheetPsw', result.timesheetPsw);
cache.set('gitPsw', result.gitPsw);
// set cred
cache.set('timesheetPsw', result.timesheetPsw);
cache.set('gitPsw', result.gitPsw);
// verify cred
parallel([validateTimesheetCred, validateGitCred], err => {
if (err) {
spinner.fail(chalk.red('Bad pitch..'))
return reject(err);
}
spinner.succeed(chalk.gray('checked the pitch'));
return resolve();
})
});
// verify cred
parallel([validateTimesheetCred, validateGitCred], err => {
if (err) {
spinner.fail(chalk.red('Bad pitch..'));
return reject(err);
}
spinner.succeed(chalk.gray('alL loOks goOd!'));
return resolve();
});
});
})
}
});
};
function validateTimesheetCred(cb) {
timesheetLogin()
.then(res => {
if (!res) return cb('TIMESHEET: bad credentials');
if (res.statusCode === 302) {
lme.s(' Validated Timesheet');
return cb();
}
timesheetLogin()
.then(res => {
if (!res) return cb('TIMESHEET: bad credentials');
if (res.statusCode === 302) {
lme.s(' Validated Timesheet');
return cb();
}
return cb('TIMESHEET: Something went wrong, may be bad credentials');
})
.catch(err => (cb(err)));
return cb('TIMESHEET: Something went wrong, may be bad credentials');
})
.catch(err => (cb(err)));
}
function validateGitCred(cb) {
getCommits()
.then(data => {
lme.s(' Validated Git-service');
return cb();
})
.catch(err => {
return cb('GIT: ' + err);
});
}
getCommits()
.then(() => {
lme.s(' Validated Git-service');
return cb();
})
.catch(err => {
return cb('GIT: ' + err);
});
}

@@ -14,34 +14,34 @@ const filterCommits = require('./filter-commits');

module.exports = () => {
return new Promise((resolve, reject) => {
loadTimesheetIssues()
.then(data => {
timesheetIssues = data;
return filterCommits();
})
.then(commits => {
let msg = commits.join(', '); // timesheet msg
let issue = tagExtractor(commits); // extracted issue
return new Promise((resolve, reject) => {
loadTimesheetIssues()
.then(data => {
timesheetIssues = data;
return filterCommits();
})
.then(commits => {
let msg = commits.join(', '); // timesheet msg
let issue = tagExtractor(commits); // extracted issue
// if no issues, set the default one
if (!issue) issue = conf.defaultIssue;
// if no issues, set the default one
if (!issue) issue = conf.defaultIssue;
// get closeness of issues
let issueId = getClosestMatchingIssueId(issue, timesheetIssues);
if (issueId !== null) // this check is necessary cz, it can return 0
return resolve({
msg: msg,
issueId: issueId
});
// get closeness of issues
let issueId = getClosestMatchingIssueId(issue, timesheetIssues);
if (issueId !== null) // this check is necessary cz, it can return 0
return resolve({
msg: msg,
issueId: issueId
});
// else return the original issue as the plain text. it'll create a new issue at backend;
return resolve({
msg: msg,
issueId: issue
});
})
.catch(err => {
reject(err);
});
// else return the original issue as the plain text. it'll create a new issue at backend;
return resolve({
msg: msg,
issueId: issue
});
})
.catch(err => {
reject(err);
});
});
};
});
};

@@ -14,34 +14,34 @@ const request = require('request');

const getCommits = () => {
let auth = {
user: cred.username,
pass: cache.get('gitPsw'),
sendImmediately: true
};
return new Promise((resolve, reject) => {
request.get(cred.url, {
'auth': auth,
'headers': {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36'
}
}, (err, res, body) => {
if (res.statusCode !== 200) return reject(JSON.parse(body).message);
let auth = {
user: cred.username,
pass: process.env.NODE_ENV === 'test' ? cred.password : cache.get('gitPsw'),
sendImmediately: true
};
return new Promise((resolve, reject) => {
request.get(cred.url, {
'auth': auth,
'headers': {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36'
}
}, (err, res, body) => {
if (res.statusCode !== 200) return reject(JSON.parse(body).message);
if (err) return reject(err);
let commits = JSON.parse(body);
if (err) return reject(err);
let commits = JSON.parse(body);
// filter last 5 commits of a specific person
let lastCommits = [];
commits.forEach((committed) => {
if (lastCommits.length < 5 && committed.commit.author.email === cred.commitAuthorEmail) {
lastCommits.push(committed);
} else return;
});
// filter last 5 commits of a specific person
let lastCommits = [];
commits.forEach((committed) => {
if (lastCommits.length < 5 && committed.commit.author.email === cred.commitAuthorEmail) {
lastCommits.push(committed);
} else return;
});
return resolve(lastCommits);
return resolve(lastCommits);
});
});
});
});
};
module.exports = getCommits;
module.exports = getCommits;

@@ -10,24 +10,24 @@ const levenshtein = require('fast-levenshtein');

module.exports = (key, pool) => {
// distance store
let distances = [];
// distance store
let distances = [];
// sorted whitespace removed lowercased key text;
key = key.toLowerCase().replace(/ /g, '').split('').sort().join('');
// sorted whitespace removed lowercased key text;
key = key.toLowerCase().replace(/ /g, '').split('').sort().join('');
pool.forEach(issue => {
// sorted whitespace removed lowercased issue text;
let subject = issue.issue.subject.toLowerCase().replace(/ /g, '').split('').sort().join('');
distances.push(levenshtein.get(key, subject));
});
let minDist = Math.min(...distances);
pool.forEach(issue => {
// sorted whitespace removed lowercased issue text;
let subject = issue.issue.subject.toLowerCase().replace(/ /g, '').split('').sort().join('');
distances.push(levenshtein.get(key, subject));
});
let minDist = Math.min(...distances);
// if there is no required matchness return null
if (minDist > +conf.issueMatchingInsensitivity)
return null;
// if there is no required matchness return null
if (minDist > +conf.issueMatchingInsensitivity)
return null;
// else get corresponding issue id;
let idxOfMin = distances.indexOf(minDist);
let issueId = pool[idxOfMin].issue.id;
// else get corresponding issue id;
let idxOfMin = distances.indexOf(minDist);
let issueId = pool[idxOfMin].issue.id;
return issueId;
};
return issueId;
};

@@ -9,46 +9,58 @@ // the periodic invoking function

const config = require('./config/conf-loader'); // not credentials
const catMe = require('cat-me');
const catFact = require('cat-facts');
const chalk = require('chalk');
const {
getDate,
getEndTime,
getStartTime,
initTime
getDate,
getEndTime,
getStartTime,
initTime
} = require('./time-handler');
module.exports = () => {
initTime(); // initialize time
initTime(); // initialize time
setInterval(() => {
// data to send
let params = {
date: getDate(), // '2017-07-06',
projectId: config.projectId,
startTime: getStartTime(), // '10:45:00',
endTime: getEndTime(), // '11:50:00',
issueId: null,
taskDetail: null,
};
console.log(catMe('resting'));
console.log('\n');
console.log(chalk.blue('cat fact: ') + chalk.gray(catFact.random()));
console.log(chalk.blue('\n +----------------------------------------------+'));
console.log(chalk.blue(' | AUTO-TIMESHEET HAS STARTED |'));
console.log(chalk.blue(' +----------------------------------------------+\n'));
console.log(chalk.gray('First activity will be added at around ') + new Date(Date.now() + config.activityInterval) + '\n');
getCommits()
// add to timesheet
.then(data => {
params.taskDetail = data.msg;
params.issueId = data.issueId;
setInterval(() => {
// data to send
let params = {
date: getDate(), // '2017-07-06',
projectId: config.projectId,
startTime: getStartTime(), // '10:45:00',
endTime: getEndTime(), // '11:50:00',
issueId: null,
taskDetail: null,
};
lme.s(params);
return addActivity(params);
})
.then(() => {
lme.s('activity added');
}).catch(() => {
lme.w('couldn\'t add activity. Initialing the alternate process to add it... ;)');
login()
.then(() => (timesheetInit()))
.then(() => (addActivity(params)))
.catch(err => {
throw err;
});
});
getCommits()
// add to timesheet
.then(data => {
params.taskDetail = data.msg;
params.issueId = data.issueId;
}, +config.activityInterval);
};
lme.s(params);
return addActivity(params);
})
.then(() => {
lme.s('activity added');
}).catch(() => {
lme.w('couldn\'t add activity. Initialing the alternate process to add it... ;)');
login()
.then(() => (timesheetInit()))
.then(() => (addActivity(params)))
.catch(err => {
throw err;
});
});
}, +config.activityInterval);
};

@@ -9,27 +9,27 @@ const request = require('request');

module.exports = () => {
return new Promise((resolve, reject) => {
let cookies = getSerializedCookies();
let authenticityToken = getAuthenticityToken();
return new Promise((resolve, reject) => {
let cookies = getSerializedCookies();
let authenticityToken = getAuthenticityToken();
if (!cookies || !authenticityToken)
return reject(new Error('No enough data in cache'));
if (!cookies || !authenticityToken)
return reject(new Error('No enough data in cache'));
// set cookies and token
reqOptions.headers.Cookie = cookies;
reqOptions.headers['X-CSRF-Token'] = authenticityToken;
reqOptions.form = {
project: conf.projectId
};
// set cookies and token
reqOptions.headers.Cookie = cookies;
reqOptions.headers['X-CSRF-Token'] = authenticityToken;
reqOptions.form = {
project: conf.projectId
};
request(reqOptions, (err, res, body) => {
if (err) return reject(err);
if (res.statusCode !== 200) return reject(new Error('status: ' + res.statusCode));
request(reqOptions, (err, res, body) => {
if (err) return reject(err);
if (res.statusCode !== 200) return reject(new Error('status: ' + res.statusCode));
updateCookies(res.headers['set-cookie']);
updateCookies(res.headers['set-cookie']);
body = JSON.parse(body);
body = JSON.parse(body);
resolve(body);
});
});
};
resolve(body);
});
});
};
const loginCore = require('./login');
const getToken = require('./token-extractor');
const { username } = require('../../config/conf-loader').config.timesheet;
const timesheet = require('../../config/conf-loader').config.timesheet;
const cache = require('../../cache');
module.exports = () => {
return getToken().then(token => {
let password = cache.get('timesheetPsw');
return loginCore(username, password, token);
}).catch(() => {
// console.log('--');
// console.log(err);
})
};
return getToken().then(token => {
let password = process.env.NODE_ENV === 'test' ? timesheet.password : cache.get('timesheetPsw');
return loginCore(timesheet.username, password, token);
}).catch(() => {
// console.log('--');
// console.log(err);
});
};

@@ -7,19 +7,19 @@ const request = require('request');

module.exports = (username, password, token) => {
return new Promise((resolve, reject) => {
// set username and password
reqOptions.form.username = username;
reqOptions.form.password = password;
reqOptions.form.authenticity_token = token;
return new Promise((resolve, reject) => {
// set username and password
reqOptions.form.username = username;
reqOptions.form.password = password;
reqOptions.form.authenticity_token = token;
request(reqOptions, (err, res) => {
if (err) return reject(err);
if (res.statusCode !== 302) return reject('ERR occurred: This is most probably due to invalid timesheet username/password');
request(reqOptions, (err, res) => {
if (err) return reject(err);
if (res.statusCode !== 302) return reject('ERR occurred: This is most probably due to invalid timesheet username/password');
updateCookies(res.headers['set-cookie']);
updateCookies(res.headers['set-cookie']);
resolve({
statusCode: res.statusCode
});
});
});
};
resolve({
statusCode: res.statusCode
});
});
});
};

@@ -10,16 +10,16 @@ // module that extracts authenticity_token from the page

module.exports = () => {
return new Promise((resolve, reject) => {
request(reqUrl, (err, res, body) => {
if (err) reject(err);
else {
let page = cheerio.load(body);
let authenticityToken = page('#login-form input')[1].attribs.value;
if (!authenticityToken) reject(new Error('Failed to get authenticity_token. Please rise an issue on github..'));
else {
cache.set('authenticityToken', authenticityToken);
resolve(authenticityToken);
}
}
});
});
};
return new Promise((resolve, reject) => {
request(reqUrl, (err, res, body) => {
if (err) reject(err);
else {
let page = cheerio.load(body);
let authenticityToken = page('#login-form input')[1].attribs.value;
if (!authenticityToken) reject(new Error('Failed to get authenticity_token. Please rise an issue on github..'));
else {
cache.set('authenticityToken', authenticityToken);
resolve(authenticityToken);
}
}
});
});
};

@@ -8,39 +8,39 @@ const request = require('request');

module.exports = (stuffs) => {
return new Promise((resolve, reject) => {
let cookies = getSerializedCookies();
let authenticityToken = getAuthenticityToken();
return new Promise((resolve, reject) => {
let cookies = getSerializedCookies();
let authenticityToken = getAuthenticityToken();
// check if the cache is perfect
if (!cookies || !authenticityToken)
return reject(new Error('No enough data in cache'));
// check if the cache is perfect
if (!cookies || !authenticityToken)
return reject(new Error('No enough data in cache'));
// set cookie and tokens and other stuffs
reqOptions.headers.Cookie = cookies;
reqOptions.headers['X-CSRF-Token'] = authenticityToken;
reqOptions.form = {
'utf8': '✓',
'authenticity_token': authenticityToken,
'date': stuffs.date,
'project_id': stuffs.projectId,
'task[detail]': stuffs.taskDetail,
'start_time': stuffs.startTime,
'end_time': stuffs.endTime,
'issue_id': stuffs.issueId,
'commit': 'Create',
};
// set cookie and tokens and other stuffs
reqOptions.headers.Cookie = cookies;
reqOptions.headers['X-CSRF-Token'] = authenticityToken;
reqOptions.form = {
'utf8': '✓',
'authenticity_token': authenticityToken,
'date': stuffs.date,
'project_id': stuffs.projectId,
'task[detail]': stuffs.taskDetail,
'start_time': stuffs.startTime,
'end_time': stuffs.endTime,
'issue_id': stuffs.issueId,
'commit': 'Create',
};
// issue request
// lme.s(reqOptions);
request(reqOptions, (err, res, body) => {
// issue request
// lme.s(reqOptions);
request(reqOptions, (err, res, body) => {
if (err || res.statusCode !== 200) {
return reject(err ? err : new Error('status:' + res.statusCode));
}
updateCookies(res.headers['set-cookie']);
if (err || res.statusCode !== 200) {
return reject(err ? err : new Error('status:' + res.statusCode));
}
updateCookies(res.headers['set-cookie']);
if (body.includes('Time sheet has been added successfully')) return resolve();
else return reject(new Error('something went wrong while trying to add activity: ' + body));
});
if (body.includes('Time sheet has been added successfully')) return resolve();
else return reject(new Error('something went wrong while trying to add activity: ' + body));
});
});
};
});
};

@@ -8,27 +8,27 @@ const request = require('request');

module.exports = () => {
return new Promise((resolve, reject) => {
let cookies = getSerializedCookies();
if (!cookies) return reject(new Error('No cookies'));
return new Promise((resolve, reject) => {
let cookies = getSerializedCookies();
if (!cookies) return reject(new Error('No cookies'));
// set cookies
reqOptions.headers.Cookie = cookies;
// lme.s(reqOptions);
request(reqOptions, (err, res, body) => {
if (err) return reject(err);
if (res.statusCode !== 200) return reject(new Error('status: ' + res.statusCode));
// set cookies
reqOptions.headers.Cookie = cookies;
// lme.s(reqOptions);
request(reqOptions, (err, res, body) => {
if (err) return reject(err);
if (res.statusCode !== 200) return reject(new Error('status: ' + res.statusCode));
// some silly checks to confirm that it is the intended page.
// (keys gotten from inspecting the intended page)
if (!body.includes('accesskey') ||
!body.includes('<option value=') ||
!body.includes('new_user_activity')) {
throw new Error('Looks like timesheet page can\'t load');
}
// some silly checks to confirm that it is the intended page.
// (keys gotten from inspecting the intended page)
if (!body.includes('accesskey') ||
!body.includes('<option value=') ||
!body.includes('new_user_activity')) {
throw new Error('Looks like timesheet page can\'t load');
}
updateCookies(res.headers['set-cookie']);
updateAuthenticityToken(body);
updateCookies(res.headers['set-cookie']);
updateAuthenticityToken(body);
resolve();
});
});
};
resolve();
});
});
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc