pact-coffee-cli
Version:
A CLI for interacting with Pact coffee's API
262 lines (228 loc) • 7.55 kB
JavaScript
const helpers = require('./helpers');
const chalk = require('chalk');
const APIInterface = require('./pactAPIInterface');
const moment = require('moment');
const auth = require('./auth');
const CLI = require('clui');
const Spinner = CLI.Spinner;
// Classes are ES6, precompile or set prototypes.
class CoffeeMaker {
constructor() {
this.authToken;
this.myCoffees;
this.userData;
this.orderID;
this.orderHistory;
}
authenticate = async () => {
try {
const credentials = await auth.getCredentials();
const msg = 'Authenticating you, please wait... ☕';
const authToken = await statusWrapper(
msg,
APIInterface.getAuthToken,
credentials
);
if (!authToken) {
throw new Error('No token recieved');
}
this.authToken = authToken;
//console.log(chalk.green('Authentication successful.'));
} catch (e) {
console.log(
chalk.red(
`We couldn't authenticate you with Pact's servers, try entering your credentials again below`
)
);
await auth.requestCredentials();
await this.authenticate();
}
};
getUserData = async () => {
try {
if (!this.authToken) {
throw new Error(
'Need to be authenticated first, try calling authenticate()'
);
}
this.userData = await APIInterface.getUserData(this.authToken);
if (!this.userData) {
throw new Error('Unable to retrive user data');
}
this.orderID = this.userData['start']['order_ids'][0];
} catch (e) {
console.log(chalk.red(`Error getting user data: ${e}`));
}
};
changeOrderDate = async (date) => {
try {
const requestedDate = helpers.handleDateInput(date);
const newDispatchDate = await APIInterface.changeDispatchDate(
this.authToken,
this.orderID,
requestedDate
);
console.log(
chalk.green(
`Order dispatch date successfully changed to ${newDispatchDate}. 👍`
)
);
} catch (e) {
console.log(chalk.red(`Error changing order date: ${e}`));
}
};
displayRatedCoffees = async () => {
//Use cached coffee ratings if possible
//Need to make sure data not stale when adding a change coffee rating feature
if (!this.myCoffees) {
this.myCoffees = await APIInterface.getMyCoffees(this.authToken);
}
const myCoffeeRatings = generateRatedCoffees(
filterNullCoffees(this.myCoffees)
);
Object.keys(myCoffeeRatings).forEach((coffeeName) => {
if (myCoffeeRatings[coffeeName]) {
console.log(chalk.green(`${coffeeName}: 👍`));
} else {
console.log(chalk.red(`${coffeeName}: 👎`));
}
});
};
displayOrderStatus = async () => {
try {
if (!this.userData) {
throw new Error('No user data found, try calling getUserData()');
}
const coffeeName = this.userData.items[0]['product_name'];
const dispatchDate = this.userData.orders[0]['dispatch_on'];
const daysTo = moment(dispatchDate, 'YYYY-MM-DD').diff(moment(), 'days');
console.log(
chalk.yellow('Your order of'),
chalk.green(coffeeName),
chalk.yellow(`☕ will be dispatched in`),
chalk.red(`${daysTo} days`),
chalk.white(`(${helpers.reverseDate(dispatchDate, '-', '/')})`)
);
} catch (e) {
console.log(chalk.red(`Error displaying order status: ${e}`));
}
};
displayLastDispatched = async () => {
if (!this.orderHistory) await this.getOrderHistory();
const orderHistory = this.orderHistory;
try {
if (orderHistory) {
let order = orderHistory['orders'][0];
let coffeeItem = orderHistory.items.filter(
(item) => item.id === order.item_ids[0]
);
if (coffeeItem) {
coffeeItem = coffeeItem[0];
const orderStatus = order['current_state'];
let outputStr = '';
const daysAgo = moment().diff(
moment(order.dispatch_on, 'YYYY-MM-DD'),
'days'
);
if (orderStatus === 'shipped') {
outputStr += chalk.yellow(
`Your last ${chalk.green(`dispatched`)} order was ${chalk.red(
`${daysAgo} days ago`
)}`
);
outputStr += chalk.white(
` (${moment(order.dispatch_on, 'YYYY-MM-DD').format(
'Do MMM YYYY'
)} - ${coffeeItem.product_name})`
);
} else {
outputStr += chalk.red(`Your last order failed to ship`);
outputStr += chalk.white(
` (${moment(order.dispatch_on, 'YYYY-MM-DD').format(
'Do MMM YYYY'
)} - ${coffeeItem.product_name})`
);
}
console.log(outputStr);
}
}
} catch (e) {
console.log("Couldn't display last dispatched order");
}
};
getOrderHistory = async () => {
try {
if (!this.authToken) {
throw new Error('No auth token found, try calling authenticate()');
}
this.orderHistory = await APIInterface.getOrderHistory(this.authToken);
} catch (e) {
console.log(chalk.red(`Error getting order history: ${e}`));
}
};
displayOrderHistory = async () => {
try {
if (!this.orderHistory) await this.getOrderHistory();
let orderHistory = this.orderHistory;
if (orderHistory) {
let slicedOrderHistory = orderHistory['orders'];
if (slicedOrderHistory.length > 5) {
slicedOrderHistory = orderHistory['orders'].slice(0, 5);
}
console.log(
chalk.white.bold(`Last ${slicedOrderHistory.length} orders:`)
);
for (let order of slicedOrderHistory) {
let coffeeItem = orderHistory.items.filter(
(item) => item.id === order.item_ids[0]
);
if (coffeeItem) {
coffeeItem = coffeeItem[0];
const orderStatus = order['current_state'];
console.log(
chalk.white.bold(
`${moment(order.dispatch_on, 'YYYY-MM-DD').format(
'Do MMM YYYY'
)}: `
),
chalk.yellow(coffeeItem.product_name),
orderStatus === 'shipped'
? chalk.green(`(Status: ${orderStatus.toUpperCase()} ✅)`)
: chalk.red(`(Status: ${orderStatus.toUpperCase()} ❌)`)
);
}
}
}
} catch (e) {
console.log(chalk.red(`Error displaying order history: ${e}`));
}
};
cleanup = async () => {
await APIInterface.deauthenticate(this.authToken);
//console.log(chalk.green('Successfully cleaned up!'));
};
// getFullCoffeeData = async () => {
// //const coffeeData = await APIInterface.getCoffeeData(tokenBASE64)
// //const available = helpers.filterAvailableCoffees(coffeeData)
// };
}
const filterNullCoffees = (coffees) => {
return coffees.filter((coffee) => {
return coffee.rating !== null;
});
};
const generateRatedCoffees = (coffees) => {
const coffeeRatings = {};
coffees.forEach((coffee) => {
coffeeRatings[coffee.name] = coffee.rating;
});
return coffeeRatings;
};
statusWrapper = async (msg = 'Loading, please wait...', func, ...args) => {
const status = new Spinner(msg);
status.start();
const response = await func(...args);
status.stop();
return response;
};
module.exports = CoffeeMaker;