first commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const dotenv_1 = __importDefault(require("dotenv"));
|
||||
const containers_1 = __importDefault(require("./routes/containers"));
|
||||
dotenv_1.default.config();
|
||||
const app = (0, express_1.default)();
|
||||
const PORT = process.env.DEFAULT_ADMIN_PORT || 3000;
|
||||
app.use(express_1.default.json());
|
||||
// Rutas
|
||||
app.use("/containers", containers_1.default);
|
||||
// Iniciar el servidor
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
});
|
||||
@@ -0,0 +1,158 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SERVER_STATE = exports.BOT_STATE = void 0;
|
||||
const express_1 = require("express");
|
||||
const dockerService_1 = require("../services/dockerService");
|
||||
const axios_1 = __importDefault(require("axios"));
|
||||
var BOT_STATE;
|
||||
(function (BOT_STATE) {
|
||||
BOT_STATE["EXISTS"] = "exists";
|
||||
BOT_STATE["NOT_EXISTS"] = "not_exists";
|
||||
})(BOT_STATE = exports.BOT_STATE || (exports.BOT_STATE = {}));
|
||||
var SERVER_STATE;
|
||||
(function (SERVER_STATE) {
|
||||
SERVER_STATE["RUNNING"] = "running";
|
||||
SERVER_STATE["NOT_WORKING"] = "not_working";
|
||||
})(SERVER_STATE = exports.SERVER_STATE || (exports.SERVER_STATE = {}));
|
||||
const router = (0, express_1.Router)();
|
||||
const getContainerApiUrl = (port) => {
|
||||
const baseUrl = process.env.CONTAINER_API_URL ? process.env.CONTAINER_API_URL : "http://localhost";
|
||||
const url = `${baseUrl}:${port}/`;
|
||||
return url;
|
||||
};
|
||||
// Obtener todos los contenedores
|
||||
router.get("/", async (req, res) => {
|
||||
try {
|
||||
const containers = await (0, dockerService_1.listContainers)();
|
||||
res.json(containers);
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
// Iniciar un contenedor por ID
|
||||
router.post("/:id/start", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const containerInfo = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
await (0, dockerService_1.startContainer)(containerInfo.Id);
|
||||
res.json({ message: `El bot ${containerInfo.Id} ha sido iniciado` });
|
||||
}
|
||||
catch (error) {
|
||||
if (error.message.indexOf("already started") >= 0) {
|
||||
res.json({ message: `El bot se encontraba iniciado anteriormente.` });
|
||||
return;
|
||||
}
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
// Obtener el QR de conexion para el bot de una organization.
|
||||
router.get("/:id/qr", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const containerInfo = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
const url = getContainerApiUrl(containerInfo.Ports[0].PublicPort.toString()); // "http://localhost:" + containerInfo.Ports[0].PublicPort + "/";
|
||||
const response = await axios_1.default.get(url, { responseType: "arraybuffer" });
|
||||
res.setHeader("Content-type", "image/png");
|
||||
res.send(response.data);
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
// Detener un contenedor por ID
|
||||
router.post("/:id/stop", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const containerInfo = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
await (0, dockerService_1.stopContainer)(containerInfo.Id);
|
||||
res.json({ message: `El bot de la organizacion ${organizationId} ha sido detenido` });
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error.message);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
// Eliminar un contenedor por ID
|
||||
router.delete("/:id", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const containerInfo = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
await (0, dockerService_1.removeContainer)(containerInfo.Id);
|
||||
res.json({ message: `El bot de la organizacion ${organizationId} removed` });
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
// Crear un nuevo contenedor
|
||||
router.post("/create", async (req, res) => {
|
||||
try {
|
||||
const { organizationId } = req.body;
|
||||
const port = await (0, dockerService_1.getAvailablePort)();
|
||||
if (!port) {
|
||||
res.status(400).json({ error: "Port is required" });
|
||||
return;
|
||||
}
|
||||
if (await (0, dockerService_1.existsContainer)(organizationId)) {
|
||||
res.json({ message: `Ya existe un bot de whatsapp creado para esta organizacion` });
|
||||
return;
|
||||
}
|
||||
const containerName = `${organizationId}_bot_${port}`;
|
||||
const imageName = "txbot";
|
||||
const containerId = await (0, dockerService_1.createContainer)(port, containerName, imageName);
|
||||
console.log(`Se ha creado un nuevo bot en el contenedor ${containerId} para la organizacion ${organizationId}`);
|
||||
res.json({ message: `El bot ha sido creado con exito`, port, organizationId });
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
// Consultar el estado de un contenedor par auna organizationId
|
||||
router.post("/:id/status", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const info = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
res.json({ state: BOT_STATE.EXISTS, status: info.Status, serverState: SERVER_STATE.RUNNING });
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message, code: 404 });
|
||||
}
|
||||
});
|
||||
router.post("/:id/send", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const data = req.body;
|
||||
const info = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
const url = getContainerApiUrl(info.Ports[0].PublicPort.toString());
|
||||
const result = await axios_1.default.post(url + "v1/messages", data);
|
||||
if (result.status !== 200) {
|
||||
throw new Error("Ha ocurrido un error al enviar el mensaje" + result);
|
||||
}
|
||||
res.json({ message: `Mensaje enviado` });
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
router.post("/:id/session", async (req, res) => {
|
||||
try {
|
||||
const organizationId = req.params.id;
|
||||
const data = req.body;
|
||||
const info = await (0, dockerService_1.getContainerByOrganization)(organizationId);
|
||||
const url = getContainerApiUrl(info.Ports[0].PublicPort.toString());
|
||||
const result = await axios_1.default.post(url + "v1/session", data);
|
||||
if (result.status !== 200) {
|
||||
throw new Error("Ha ocurrido un error al enviar el mensaje" + result);
|
||||
}
|
||||
const resultData = result.data;
|
||||
res.json({ message: `${resultData}` });
|
||||
}
|
||||
catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
exports.default = router;
|
||||
@@ -0,0 +1,127 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getContainerByOrganization = exports.removeContainer = exports.createContainer = exports.stopContainer = exports.startContainer = exports.getAvailablePort = exports.getOrganizationBotPort = exports.existsContainer = exports.listContainers = void 0;
|
||||
const dockerode_1 = __importDefault(require("dockerode"));
|
||||
const docker = new dockerode_1.default();
|
||||
/**
|
||||
* Listar todos los contenedores.
|
||||
*/
|
||||
const listContainers = async () => {
|
||||
return docker.listContainers({ all: true });
|
||||
};
|
||||
exports.listContainers = listContainers;
|
||||
const existsContainer = async (organizationId) => {
|
||||
const contenedores = await (0, exports.listContainers)();
|
||||
const contenedoresNombres = Array.from(contenedores, (item) => item.Names[0].split("_bot")[0].substring(1));
|
||||
if (contenedoresNombres.includes(organizationId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
exports.existsContainer = existsContainer;
|
||||
const getOrganizationBotPort = async (organizationId) => {
|
||||
const contenedores = await (0, exports.listContainers)();
|
||||
for (const contenedor of contenedores) {
|
||||
if (contenedor.Names.includes(organizationId)) {
|
||||
const port = contenedor.Ports[0].PublicPort;
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
exports.getOrganizationBotPort = getOrganizationBotPort;
|
||||
const getAvailablePort = async () => {
|
||||
const contenedores = await (0, exports.listContainers)();
|
||||
let defaultPort = process.env.DEFAULT_BOT_START_PORT ? parseInt(process.env.DEFAULT_BOT_START_PORT) : -1;
|
||||
if (contenedores.length == 0) {
|
||||
return defaultPort;
|
||||
}
|
||||
contenedores.sort((a, b) => b.Created - a.Created);
|
||||
//Obtengo el contenedor mas reciente.
|
||||
const lastContainerCreated = contenedores.shift();
|
||||
if (!lastContainerCreated) {
|
||||
return defaultPort;
|
||||
}
|
||||
const lastPort = lastContainerCreated.Ports;
|
||||
if (!lastPort) {
|
||||
return defaultPort;
|
||||
}
|
||||
if (lastPort.length == 0) {
|
||||
return defaultPort;
|
||||
}
|
||||
return lastPort[0].PublicPort + 1;
|
||||
};
|
||||
exports.getAvailablePort = getAvailablePort;
|
||||
/**
|
||||
* Iniciar un contenedor por ID.
|
||||
*/
|
||||
const startContainer = async (containerId) => {
|
||||
const container = docker.getContainer(containerId);
|
||||
await container.start();
|
||||
};
|
||||
exports.startContainer = startContainer;
|
||||
/**
|
||||
* Detener un contenedor por ID.
|
||||
*/
|
||||
const stopContainer = async (containerId) => {
|
||||
const container = docker.getContainer(containerId);
|
||||
await container.stop();
|
||||
};
|
||||
exports.stopContainer = stopContainer;
|
||||
const createContainer = async (port, name, image) => {
|
||||
try {
|
||||
// Crear un contenedor con las configuraciones especificadas
|
||||
const container = await docker.createContainer({
|
||||
Image: image,
|
||||
name,
|
||||
Env: [`PORT=${port}`],
|
||||
ExposedPorts: {
|
||||
[`${port}/tcp`]: {}, // Define el puerto expuesto
|
||||
},
|
||||
HostConfig: {
|
||||
PortBindings: {
|
||||
[`${port}/tcp`]: [{ HostPort: `${port}` }], // Mapea el puerto entre el host y el contenedor
|
||||
},
|
||||
},
|
||||
});
|
||||
// Iniciar el contenedor creado
|
||||
await container.start();
|
||||
// Devolver el ID del contenedor como resultado
|
||||
return container.id;
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`Error al crear el contenedor: ${error.message}`);
|
||||
}
|
||||
};
|
||||
exports.createContainer = createContainer;
|
||||
const removeContainer = async (containerId) => {
|
||||
try {
|
||||
// Obtiene el contenedor por su ID
|
||||
const container = docker.getContainer(containerId);
|
||||
// Verifica si el contenedor existe antes de intentar eliminarlo
|
||||
const containerInfo = await container.inspect();
|
||||
if (containerInfo.State.Running) {
|
||||
// Si el contenedor está corriendo, debe detenerse primero
|
||||
await container.stop();
|
||||
}
|
||||
// Elimina el contenedor
|
||||
await container.remove();
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(`Error al eliminar el contenedor: ${error.message}`);
|
||||
}
|
||||
};
|
||||
exports.removeContainer = removeContainer;
|
||||
const getContainerByOrganization = async (organizationId) => {
|
||||
const contenedores = await (0, exports.listContainers)();
|
||||
for (const contenedor of contenedores) {
|
||||
if (contenedor.Names.some((item) => item.includes(organizationId))) {
|
||||
return contenedor;
|
||||
}
|
||||
}
|
||||
throw new Error("Container not found");
|
||||
};
|
||||
exports.getContainerByOrganization = getContainerByOrganization;
|
||||
Reference in New Issue
Block a user