Merge pull request #11 from HWTechClub/newChanges

New changes
This commit is contained in:
ashab272000
2020-08-07 09:20:39 +04:00
committed by GitHub
8 changed files with 215 additions and 67 deletions

View File

@@ -334,6 +334,11 @@
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
} }
}, },
"common-tags": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
"integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw=="
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",

View File

@@ -11,6 +11,7 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"common-tags": "^1.8.0",
"request": "^2.88.2", "request": "^2.88.2",
"whatsapp-web.js": "^1.7.0" "whatsapp-web.js": "^1.7.0"
}, },

View File

@@ -2,7 +2,9 @@ const { Website } = require("../models/website");
const { data } = require("../models/data"); const { data } = require("../models/data");
const { Product } = require('../models/product'); const { Product } = require('../models/product');
const { User } = require('../models/user'); const { User } = require('../models/user');
const fs = require('fs');
const request = require('request'); const request = require('request');
const {stripIndents} = require('common-tags');
/** /**
* user to be sent the message to * user to be sent the message to
@@ -16,6 +18,22 @@ let user = null;
*/ */
let input = null; let input = null;
const base64_decode = async (base64str, file) => {
var bitmap = await Buffer.from(base64str, 'base64');
await fs.writeFileSync(file, bitmap);
console.log('****** File created from base64 encoded string ******');
}
const saveImage = async (messageMedia, fileName) => {
let file = `../website-generator/public/images/${fileName}.jpg`;
await base64_decode(messageMedia.data, file);
return file;
}
const addProduct = (id) => { const addProduct = (id) => {
// Create a product and select it. // Create a product and select it.
@@ -24,6 +42,8 @@ const addProduct = (id) => {
// Add a product to the selected website. // Add a product to the selected website.
user.getSelectedWebsite().addProduct(product); user.getSelectedWebsite().addProduct(product);
} }
const check = ({checkFunction, callback}) => { const check = ({checkFunction, callback}) => {
let checkValue = checkFunction(); let checkValue = checkFunction();
@@ -36,15 +56,25 @@ const check = ({checkFunction, callback}) => {
return checkValue; return checkValue;
} }
const checkMediaExist = () => {
if(input['media'] == undefined){
return [
`A media should be attached with the message`,
`Please attach an image or file with the caption being the command`
];
}
return '';
}
const checkSelectedWebsiteExist= () => { const checkSelectedWebsiteExist= () => {
if(user.getSelectedWebsite() == null) if(user.getSelectedWebsite() == null)
{ {
return [ return [
`A website should be selected or created `A website should be selected or created `,
To create website, please use the following command : `, `To create website, please use the following command : `,
`*wg create <company-name>*`, `*wg create <company-name>*`,
]; ];
} }
@@ -97,14 +127,15 @@ module.exports.onCreateProduct = () => {
//mesage to be sent to the user //mesage to be sent to the user
let message = [ let message = [
`The product has been created with the id : ${selectedId}` , `The product has been created with the id : ${selectedId}` ,
` //use stripIndents to strip the indentation
stripIndents`
This product has been selected. This product has been selected.
Now you can make change to the product with the following commands : Now you can make change to the product with the following commands :
1. wg product info 1. wg product info
2. wg product name <product-name> 2. wg product name <product-name>
3. wg product cost <product-cost> 3. wg product cost <product-cost>
4. wg product desc <product-desc> 4. wg product desc <product-desc>
5. wg product image <product-image> 5. wg product image *with an image attached*
` `
]; ];
@@ -152,14 +183,14 @@ module.exports.onSelectProduct = () => {
return [ return [
`The product has been selected with the id : ${user.getSelectedWebsite().getSelectedProduct().id}` , `The product has been selected with the id : ${user.getSelectedWebsite().getSelectedProduct().id}` ,
` stripIndents`
This product has been selected. This product has been selected.
Now you can make change to the product with the following commands : Now you can make change to the product with the following commands :
1. wg product info 1. wg product info
2. wg product name <product-name> 2. wg product name <product-name>
3. wg product cost <product-cost> 3. wg product cost <product-cost>
4. wg product desc <product-desc> 4. wg product desc <product-desc>
5. wg product image <product-image> 5. wg product image *with an image attached*
` `
]; ];
@@ -178,8 +209,9 @@ module.exports.onGetAllProducts = () => {
for(let p of user.getSelectedWebsite().getAllProduct()) for(let p of user.getSelectedWebsite().getAllProduct())
{ {
let m = 'Product id: ' + p.id + '\nProduct Name : ' + p.name + '\nProduct description : '+ p.desc + '\nProduct Cost: ' + p.cost + '\nProduct Image : '+ p.image; let m = 'Product id: ' + p.id + '\nProduct Name : ' + p.name + '\nProduct description : '+ p.desc + '\nProduct Cost: ' + p.cost + '\nProduct Image : ';
message.push(m); message.push(m);
message.push(p.image);
} }
return message; return message;
@@ -195,13 +227,13 @@ module.exports.onGetProductInfo = () => {
callback : () => { callback : () => {
let selected_product = user.getSelectedWebsite().getSelectedProduct(); let selected_product = user.getSelectedWebsite().getSelectedProduct();
return [ return [
` stripIndents`
Product id: ${selected_product.id} Product id: ${selected_product.id}
Product Name : ${selected_product.name} Product Name : ${selected_product.name}
Product description : ${selected_product.desc } Product description : ${selected_product.desc }
Product Cost: ${selected_product.cost} Product Cost: ${selected_product.cost}
Product Image : ${selected_product.image} Product Image :`,
` selected_product.image
]; ];
} }
}); });
@@ -244,7 +276,7 @@ module.exports.onSetProductDesc = () => {
let selected_product = user.getSelectedWebsite().getSelectedProduct(); let selected_product = user.getSelectedWebsite().getSelectedProduct();
selected_product.setDesc(input['product-desc']); selected_product.setDesc(input['product-desc']);
let message = [ let message = [
'The product cost has been set to '+ selected_product.desc 'The product desc has been set to '+ selected_product.desc
]; ];
return message; return message;
} }
@@ -256,12 +288,27 @@ module.exports.onSetProductImage = () => {
return check({ return check({
checkFunction : checkSelectedProductExist, checkFunction : checkSelectedProductExist,
callback : () => { callback : () => {
let selected_product = user.getSelectedWebsite().getSelectedProduct();
selected_product.setImage(input['product-image']); return check({
let message = [ checkFunction : checkMediaExist,
'The product cost has been set to '+ selected_product.image callback : async () => {
];
return message; let selected_product = user.getSelectedWebsite().getSelectedProduct();
selected_product.setImage(input['media']);
//filename to be set
let filename = `${user.id.slice(3,10)}${user.getSelectedWebsite().companyName}${selected_product.id}`;
//url for the image that are saved
selected_product.imageUrl = await saveImage(input['media'], filename);
let message = [
'The product image has been set to the following image',
selected_product.image
];
return message;
}
});
} }
}); });
} }
@@ -306,16 +353,17 @@ module.exports.onCreateWebsite = () =>
user.addWebsite(new Website(input['company_name'])); user.addWebsite(new Website(input['company_name']));
return [ return [
`welcome to building your own website!`, stripIndents`
`We would like you add the following details:`, welcome to building your own website!
`wg website firstname *<First_Name>*`, We would like you add the following details:
`wg website lastname *<Last_Name>*`, wg website firstname *<First_Name>*
`wg website companyname *<Company_name>*`, wg website lastname *<Last_Name>*
`wg website logo *<Logo_URL>*`, wg website companyname *<Company_name>*
`wg website banner *<Banner_URL>*`, wg website logo *<Logo_URL>*
`wg website description *<Description>*`, wg website banner *<Banner_URL>*
`wg website email *<Email>*`, wg website description *<Description>*
`For adding information use *wg website <firstname>*`, wg website email *<Email>*
For adding information use *wg website <firstname>*`
]; ];
} }
@@ -330,15 +378,16 @@ module.exports.onGetInfo = () => {
let website = user.getSelectedWebsite(); let website = user.getSelectedWebsite();
return [ return [
` stripIndents`
First Name : ${website.firstName} First Name : ${website.firstName}
Last Name : ${website.lastName} Last Name : ${website.lastName}
Company Name (id) : ${website.companyName } Company Name (id) : ${website.companyName }
Logo : ${website.logo}
Banner : ${website.bannerUrl}
Description : ${website.desc} Description : ${website.desc}
Email : ${website.email} Email : ${website.email}
` Banner :`,
website.banner,
`Logo :`,
website.logo
]; ];
} }
}); });
@@ -357,7 +406,7 @@ module.exports.onSetFirstName = () =>
callback : () => { callback : () => {
user.getSelectedWebsite().firstName = input['firstName']; user.getSelectedWebsite().firstName = input['firstName'];
return [`First name has been set to ${user.getSelectedWebsite().firstName}`]; return [`First name has been set to ${user.getSelectedWebsite().firstName}`];
} }
}); });
@@ -392,12 +441,26 @@ module.exports.onSetLastName = () =>
module.exports.onSetLogo = () => module.exports.onSetLogo = () =>
{ {
check({ return check({
//check if website exist
checkFunction : checkSelectedWebsiteExist, checkFunction : checkSelectedWebsiteExist,
callback: () => { callback: () => {
user.getSelectedWebsite().logoUrl = input['url'];
return check({
return [`Logo has been set to ${user.getSelectedWebsite().logoUrl}`]; //check if media exist
checkFunction: checkMediaExist,
callback : async () => {
user.getSelectedWebsite().logo = input['media'];
user.getSelectedWebsite().logoUrl = await saveImage(input['media'], `${user.id.slice(3,10)}${user.getSelectedWebsite().companyName}logo`);
return [
`Logo has been set to the following logo`,
user.getSelectedWebsite().logo
];
}
});
} }
}) })
@@ -412,11 +475,23 @@ module.exports.onSetLogo = () =>
module.exports.onSetBanner = () => module.exports.onSetBanner = () =>
{ {
return check({ return check({
//check if website exist
checkFunction : checkSelectedWebsiteExist, checkFunction : checkSelectedWebsiteExist,
callback : () => { callback : () => {
//check if media exist
return check({
checkFunction : checkMediaExist,
callback : async () => {
user.getSelectedWebsite().bannerUrl = input['bannerURL']; user.getSelectedWebsite().banner = input['media'];
return [`Banner has been set to ${user.getSelectedWebsite().bannerUrl}`]; user.getSelectedWebsite().bannerUrl = await saveImage(input['media'], `${user.id.slice(3,10)}${user.getSelectedWebsite().companyName}banner`);
return [
`Banner has been set to the following banner`,
user.getSelectedWebsite().banner
];
}
})
} }
}); });
} }
@@ -535,3 +610,5 @@ module.exports.onDeployWebsite = () => {
} }
}); });
} }

View File

@@ -1,12 +1,15 @@
const fs = require('fs');
class Command{ class Command{
/** /**
* *
* @param {{string, function()}} param0 * @param {{string, function(),boolean}} param0
*/ */
constructor({command,callback}){ constructor({command,callback, requireMedia = false}){
this.command = command; this.command = command;
this.callback = callback; this.callback = callback;
this.requireMedia = requireMedia;
this.requireInput = false; this.requireInput = false;
this.inputPos = []; this.inputPos = [];
this._requireInput(); this._requireInput();
@@ -30,7 +33,7 @@ class Command{
let splitCommand = this.command.split(' '); let splitCommand = this.command.split(' ');
let splitMsg = this._getInputMessage(message); let splitMsg = this._getSplitMessage(message);
//check the number of words both has //check the number of words both has
@@ -70,6 +73,12 @@ class Command{
* then the command requires input * then the command requires input
*/ */
_requireInput(){ _requireInput(){
if(this.requireMedia)
{
this.requireInput = true;
return;
}
let msg = this.command; let msg = this.command;
let matched = msg.match(/[<>]/g); let matched = msg.match(/[<>]/g);
@@ -79,14 +88,28 @@ class Command{
/** /**
* returns an array of string representing the inputs of the command * returns an array of string representing the inputs of the command
* @param {string} message * @param {import("whatsapp-web.js").Message} message
*/ */
getInput(message){ async getInput(message){
if(this.requireMedia){
return await this._getInputMedia(message);
}else{
return this._getInputMessage(message.body);
}
}
/**
*
* @param {string} msgString
*/
_getInputMessage(msgString){
let splitMsg = this._getInputMessage(message);
let splitCommand = this.command.split(' ');
let input = {}; let input = {};
let debug = ''; let splitMsg = this._getSplitMessage(msgString);
let splitCommand = this.command.split(' ');
for(let i = 0; i < splitMsg.length; i++){ for(let i = 0; i < splitMsg.length; i++){
if(splitCommand[i].startsWith('<')){ if(splitCommand[i].startsWith('<')){
let key = splitCommand[i].slice(1, splitCommand[i].length-1); let key = splitCommand[i].slice(1, splitCommand[i].length-1);
@@ -94,9 +117,14 @@ class Command{
} }
} }
return input; return input;
} }
_getInputMessage(msg){ /**
*
* @param {string} msg
*/
_getSplitMessage(msg){
let split = msg.split(/['"]/g); let split = msg.split(/['"]/g);
if(split.length > 1) if(split.length > 1)
{ {
@@ -109,6 +137,19 @@ class Command{
return msg.split(' '); return msg.split(' ');
} }
/**
*
* @param {import("whatsapp-web.js").Message} message
*/
async _getInputMedia(message){
let input = {};
if(message.hasMedia){
let media = await message.downloadMedia();
input['media'] = media;
}
return input;
}
} }
module.exports.Command = Command; module.exports.Command = Command;

View File

@@ -7,6 +7,7 @@ class Product {
this.desc = desc; this.desc = desc;
this.cost = cost; this.cost = cost;
this.image = image; this.image = image;
this.imageUrl = '';
} }
/** /**

View File

@@ -10,6 +10,8 @@ class Website {
this.firstName = ''; this.firstName = '';
this.lastName = ''; this.lastName = '';
this.companyName = companyName; this.companyName = companyName;
this.logo = '';
this.banner = '';
this.logoUrl = ''; this.logoUrl = '';
this.bannerUrl = ''; this.bannerUrl = '';
this.desc = ''; this.desc = '';
@@ -66,6 +68,27 @@ class Website {
return this.getProduct(this.products.selectedData); return this.getProduct(this.products.selectedData);
} }
toJson(){
let j = {};
j["firstName"] = this.firstName;
j["lastName"] = this.lastName;
j["companyName"] = this.companyName;
j["logoUrl"] = this.logoUrl;
j["bannerUrl"] = this.bannerUrl;
j["email"] = this.email;
j["description"] = this.desc;
let csv = '';
for (let prod of this.products.getAllData().values())
{
let m = [prod.id, prod.name, prod.desc, prod.cost, prod.imageUrl].join(',');
csv += `${m}\n`;
}
j['csv'] = csv;
return JSON.stringify(j);
}
} }

View File

@@ -87,11 +87,11 @@ const commands = [
//inputs the logo of the company to website using url of logo //inputs the logo of the company to website using url of logo
new Command({ new Command({
//User command //User command
command: 'wg website logo',
command: 'wg website logo <url>',
//function to be executed //function to be executed
callback : logic.onSetLogo callback : logic.onSetLogo,
requireMedia : true
}), }),
@@ -180,15 +180,16 @@ const commands = [
}), }),
new Command({ new Command({
//User command //User command
command: 'wg product image <product-image>', command: 'wg product image',
//function to be executed //function to be executed
callback : logic.onSetProductImage callback : logic.onSetProductImage,
requireMedia: true
}), }),
]; ];
module.exports= onMessage = async (message, client) => { module.exports= onMessage = async (message, client) => {
let command = null; let command = null;
@@ -213,13 +214,12 @@ module.exports= onMessage = async (message, client) => {
let input = {}; let input = {};
//check if the command requires input //check if the command requires input
if(command.requireInput){ if(command.requireInput){
input = command.getInput(message.body); input = await command.getInput(message);
} }
//determine the user //determine the user
logic.setUser(message.id.remote); logic.setUser(message.id.remote);
//determine the input //determine the input
logic.setInput(input); logic.setInput(input);
//call callback function in the command //call callback function in the command
//await is used, so that if a command is an async function //await is used, so that if a command is an async function
//the program will wait until it is finished //the program will wait until it is finished

View File

@@ -135,7 +135,7 @@ describe('Command', () => {
expect(a.equals(message)).to.false; expect(a.equals(message)).to.false;
}); });
it('Test : getInput() with 1 input', () => { it('Test : _getInputMessage() with 1 input', () => {
let message = 'wg create p12' let message = 'wg create p12'
@@ -146,10 +146,10 @@ describe('Command', () => {
} }
}); });
expect(a.getInput(message)['id']).to.equal('p12'); expect(a._getInputMessage(message)['id']).to.equal('p12');
}); });
it('Test : getInput() with 2 input', () => { it('Test : _getInputMessage() with 2 input', () => {
let message = 'wg create p12 pikachu' let message = 'wg create p12 pikachu'
@@ -160,31 +160,31 @@ describe('Command', () => {
} }
}); });
expect(a.getInput(message)['id']).to.equal('p12'); expect(a._getInputMessage(message)['id']).to.equal('p12');
expect(a.getInput(message)['name']).to.equal('pikachu'); expect(a._getInputMessage(message)['name']).to.equal('pikachu');
}); });
it('Test : _getInputMessage() with a sentence', () => { it('Test : _getSplitMessage() with a sentence', () => {
let a = new Command({command : 'wg website desc <desc>'}); let a = new Command({command : 'wg website desc <desc>'});
let b = a._getInputMessage(`wg website desc "Hello everynyan, how are you"`); let b = a._getSplitMessage(`wg website desc "Hello everynyan, how are you"`);
expect(b[0]).to.equal('wg'); expect(b[0]).to.equal('wg');
expect(b[1]).to.equal('website'); expect(b[1]).to.equal('website');
expect(b[2]).to.equal('desc'); expect(b[2]).to.equal('desc');
expect(b[3]).to.equal('Hello everynyan, how are you'); expect(b[3]).to.equal('Hello everynyan, how are you');
}) })
it('Test : _getInputMessage() with multiple sentence input', () => { it('Test : _getSplitMessage() with multiple sentence input', () => {
let a = new Command({command : 'wg website desc <desc>'}); let a = new Command({command : 'wg website desc <desc>'});
let b = a._getInputMessage(`wg website desc "Hello everynyan, how are you" "I am fine thank you"`); let b = a._getSplitMessage(`wg website desc "Hello everynyan, how are you" "I am fine thank you"`);
expect(b[0]).to.equal('wg'); expect(b[0]).to.equal('wg');
expect(b[1]).to.equal('website'); expect(b[1]).to.equal('website');
expect(b[2]).to.equal('desc'); expect(b[2]).to.equal('desc');
expect(b[3]).to.equal('Hello everynyan, how are you'); expect(b[3]).to.equal('Hello everynyan, how are you');
expect(b[4]).to.equal('I am fine thank you'); expect(b[4]).to.equal('I am fine thank you');
}) })
it('Test : _getInputMessage() with single word', () => { it('Test : _getSplitMessage() with single word', () => {
let a = new Command({command : 'wg website desc <desc>'}); let a = new Command({command : 'wg website desc <desc>'});
let b = a._getInputMessage(`wg website desc Hello`); let b = a._getSplitMessage(`wg website desc Hello`);
expect(b[0]).to.equal('wg'); expect(b[0]).to.equal('wg');
expect(b[1]).to.equal('website'); expect(b[1]).to.equal('website');
expect(b[2]).to.equal('desc'); expect(b[2]).to.equal('desc');