This commit is contained in:
Leifer Mendez
2022-08-10 21:07:28 +02:00
commit 980cb3d144
380 changed files with 2080 additions and 0 deletions

11
src/app.ts Normal file
View File

@@ -0,0 +1,11 @@
import "dotenv/config"
import express from "express"
import cors from "cors"
import routes from "./infrastructure/router"
const port = process.env.PORT || 3001
const app = express()
app.use(cors())
app.use(express.json())
app.use(`/`,routes)
app.listen(port, () => console.log(`Ready...${port}`))

View File

@@ -0,0 +1,24 @@
import LeadExternal from "../domain/lead.external";
import LeadRepository from "../domain/lead.repository";
export class LeadCreate {
private leadRepository: LeadRepository;
private leadExternal: LeadExternal;
constructor(respositories: [LeadRepository, LeadExternal]) {
const [leadRepository, leadExternal] = respositories;
this.leadRepository = leadRepository;
this.leadExternal = leadExternal;
}
public async sendMessageAndSave({
message,
phone,
}: {
message: string;
phone: string;
}) {
const responseDbSave = await this.leadRepository.save({ message, phone });//TODO DB
const responseExSave = await this.leadExternal.sendMsg({ message, phone });//TODO enviar a ws
return {responseDbSave, responseExSave};
}
}

View File

@@ -0,0 +1,3 @@
export default interface LeadExternal {
sendMsg({message, phone}:{message:string, phone:string}):Promise<any>
}

View File

@@ -0,0 +1,12 @@
import { Lead } from "./lead";
export default interface LeadRepository {
save({
message,
phone,
}: {
message: string;
phone: string;
}): Promise<Lead | undefined | null>;
getDetail(id:string):Promise<Lead | null | undefined>
}

13
src/domain/lead.ts Normal file
View File

@@ -0,0 +1,13 @@
import { v4 as uuid } from "uuid";
export class Lead {
readonly uuid: string;
readonly message: string;
readonly phone: string;
constructor({ message, phone }: { message: string; phone: string }) {
this.uuid = uuid();
this.message = message;
this.phone = phone;
}
}

View File

@@ -0,0 +1,14 @@
import { Request, Response } from "express";
import { LeadCreate } from "../../application/lead.create";
class LeadCtrl {
constructor(private readonly leadCreator: LeadCreate) {}
public sendCtrl = async ({ body }: Request, res: Response) => {
const { message, phone } = body;
const response = await this.leadCreator.sendMessageAndSave({ message, phone })
res.send(response);
};
}
export default LeadCtrl;

26
src/infrastructure/ioc.ts Normal file
View File

@@ -0,0 +1,26 @@
import { ContainerBuilder } from "node-dependency-injection";
import { LeadCreate } from "../application/lead.create";
import LeadCtrl from "./controller/lead.ctrl";
import MockRepository from "./repositories/mock.repository";
import WsTransporter from "./repositories/ws.external";
const container = new ContainerBuilder();
/**
* Inicamos servicio de WS / Bot / Twilio
*/
container.register("ws.transporter", WsTransporter);
const wsTransporter = container.get("ws.transporter");
container.register("db.repository", MockRepository);
const dbRepository = container.get("db.repository");
container
.register("lead.creator", LeadCreate)
.addArgument([dbRepository, wsTransporter]);
const leadCreator = container.get("lead.creator");
container.register("lead.ctrl", LeadCtrl).addArgument(leadCreator);
export default container;

View File

@@ -0,0 +1,18 @@
import { Lead } from "../../domain/lead";
import LeadRepository from "../../domain/lead.repository";
class MockRepository implements LeadRepository {
getDetail(id: string): Promise<Lead | null | undefined> {
throw new Error("Method not implemented.");
}
save(): Promise<Lead> {
const MOCK_LEAD: Lead = {
uuid: "00---000",
message: "test",
phone: "00000",
};
return Promise.resolve(MOCK_LEAD);
}
}
export default MockRepository

View File

@@ -0,0 +1,8 @@
import LeadExternal from "../../domain/lead.external";
export class TwilioService implements LeadExternal {
sendMsg({ message, phone }: { message: string; phone: string; }): Promise<any> {
return Promise.resolve('SE_ENVIO_CORRECTAMENTE')
}
}

View File

@@ -0,0 +1,63 @@
import { Client, LocalAuth } from "whatsapp-web.js";
import { image as imageQr } from "qr-image";
import LeadExternal from "../../domain/lead.external";
/**
* Extendemos los super poderes de whatsapp-web
*/
class WsTransporter extends Client implements LeadExternal {
private status = false;
constructor() {
super({
authStrategy: new LocalAuth(),
puppeteer: { headless: true },
});
console.log("Iniciando....");
this.initialize();
this.on("ready", () => {
this.status = true;
console.log("LOGIN_SUCCESS");
});
this.on("auth_failure", () => {
this.status = false;
console.log("LOGIN_FAIL");
});
this.on("qr", (qr) => this.generateImage(qr));
}
/**
* Enviar mensaje de WS
* @param lead
* @returns
*/
async sendMsg(lead: { message: string; phone: string }): Promise<any> {
try {
if (!this.status) return Promise.resolve({ error: "WAIT_LOGIN" });
const { message, phone } = lead;
const response = await this.sendMessage(`${phone}@c.us`, message);
return { id: response.id.id };
} catch (e: any) {
return Promise.resolve({ error: e.message });
}
}
getStatus(): boolean {
return this.status;
}
private generateImage = (base64: string) => {
const path = `${process.cwd()}/tmp`;
let qr_svg = imageQr(base64, { type: "svg", margin: 4 });
qr_svg.pipe(require("fs").createWriteStream(`${path}/qr.svg`));
console.log(`⚡ Recuerda que el QR se actualiza cada minuto ⚡'`);
console.log(`⚡ Actualiza F5 el navegador para mantener el mejor QR⚡`);
};
}
export default WsTransporter;

View File

@@ -0,0 +1,28 @@
import { readdirSync } from "fs";
import express, { Router } from "express";
const router: Router = Router();
const PATH_ROUTES = __dirname;
function removeExtension(fileName: string): string {
const cleanFileName = <string>fileName.split(".").shift();
return cleanFileName;
}
/**
*
* @param file tracks.ts
*/
function loadRouter(file: string): void {
const name = removeExtension(file);
if (name !== "index") {
import(`./${file}`).then((routerModule) => {
console.log("cargado", name);
router.use(`/${name}`, routerModule.router);
});
}
}
readdirSync(PATH_ROUTES).filter((file) => loadRouter(file));
export default router;

View File

@@ -0,0 +1,12 @@
import express, { Router } from "express";
import LeadCtrl from "../controller/lead.ctrl";
import container from "../ioc";
const router: Router = Router();
/**
* http://localhost/lead POST
*/
const leadCtrl: LeadCtrl = container.get("lead.ctrl");
router.post("/", leadCtrl.sendCtrl);
export { router };