A lo largo de los años, nuestros servicios en Kinsta siempre se han gestionado manualmente a través del panel de control MyKinsta. Sin embargo, con la introducción de la API de Kinsta y el lanzamiento continuo de nuevos endpoints de la API, puedes mejorar tu juego desarrollando un método personalizado para interactuar con los servicios de Kinsta. Uno de estos medios es desarrollar un Slackbot para supervisar y gestionar actividades como la creación de sitios.

Qué Estás Construyendo

Este tutorial explica cómo construir un Slackbot (o aplicación Slack) que interactúa con la API de Kinsta para recuperar información y entregarla como mensajes en tiempo real a un canal Slack determinado utilizando los Webhooks Entrantes de la API de Slack.

Para conseguirlo, crearás una aplicación Node.js con el framework Express para crear una interfaz de usuario para la creación de sitios WordPress e integrarla con la API de Kinsta. La aplicación utiliza un formulario para recoger los detalles de configuración de tu sitio WordPress y luego envía una actualización en tiempo real sobre la información del sitio y detalles sobre cómo comprobar su estado de funcionamiento al canal Slack especificado.

Gif que muestra la aplicación que se construiría y cómo envía información en tiempo real a Slack.
Gif que muestra la aplicación que se construiría y cómo envía información en tiempo real a Slack.

Requisitos Previos

Para seguir adelante con este proyecto, debes tener lo siguiente:

Configurar el Entorno de Desarrollo

Para empezar, crea un nuevo directorio para tu aplicación e inícialo con npm:

mkdir my-express-app 
cd my-express-app 
npm init -y

Tras ejecutar el comando npm init -y, se creará un nuevo archivo package.json en el directorio de tu proyecto con los valores predeterminados. Este archivo contiene información importante sobre tu proyecto y sus dependencias.

A continuación, instala las dependencias necesarias para tu proyecto. Las siguientes dependencias son esenciales:

  • ejs: EJS (Embedded JavaScript) es un motor de plantillas que te permite generar contenido HTML dinámico con JavaScript.
  • express: Express es un framework de aplicaciones web rápido y minimalista para Node.js. Simplifica la creación de aplicaciones web y API proporcionando funciones esenciales como el enrutamiento, el soporte de middleware y la gestión de solicitudes y respuestas HTTP.
  • express-ejs-layouts: Express EJS layouts es una extensión para Express que permite utilizar layouts o plantillas para mantener una estructura coherente en múltiples vistas.

Para instalar estas dependencias, ejecuta el siguiente comando:

npm install ejs express express-ejs-layouts

Además, necesitarás instalar las siguientes dependencias de desarrollo para facilitar la construcción y prueba de tu proyecto Node.js:

  • nodemon: Una valiosa herramienta que reinicia automáticamente tu aplicación Node.js cada vez que se detectan cambios de archivo en el directorio, garantizando un flujo de trabajo de desarrollo optimizado.
  • dotenv: Este módulo de dependencia cero desempeña un papel crucial en la carga de variables de entorno desde un archivo .env.

Para instalar estas dependencias de desarrollo, ejecuta el siguiente comando:

npm install -D nodemon dotenv

Una vez inicializado tu package.json e instaladas todas las dependencias, crea un nuevo archivo, por ejemplo app.js.

touch app.js

Aquí tienes una configuración por defecto para tu archivo app.js, donde importas los módulos necesarios y lo configuras para que se ejecute en un puerto específico:

// Import required modules
const express = require('express');
const app = express();

// Set up your routes and middleware here
// ...

// Start the server to listen on the specified port
app.listen(process.env.PORT || 3000, () => {
  console.log(`Server is running on port ${process.env.PORT || 3000}`);
});

Para ejecutar tu aplicación Node.js, ejecuta el comando

node app.js

Sin embargo, ejecutar una aplicación como ésta implica reiniciarla manualmente cada vez que hagas cambios en tu proyecto. Para superar este inconveniente, utiliza nodemon, que ya tienes instalado. Configúralo en tu archivo package.json creando un comando script:

  "scripts": {
    "dev": "nodemon app.js"
  },

Ahora, ejecuta tu aplicación Node.js con reinicios automáticos utilizando el siguiente comando:

npm run dev

Primeros Pasos con Express y EJS Templating

En este tutorial, estás construyendo una aplicación Node.js que mostrará contenido en el navegador. Para conseguirlo, se utiliza express.js como tu framework web, y EJS (Embedded JavaScript) como tu motor de plantillas.

Para establecer EJS como tu motor de visualización, añade la siguiente línea a tu archivo app.js. Esto permitirá ejecutar archivos .ejs:

// Use EJS as the view engine 
app.set('view engine', 'ejs');

Ahora que Express está configurado con EJS, define tus rutas. En las aplicaciones web, las rutas determinan cómo responde la aplicación a las distintas peticiones HTTP (como GET o POST) y especifican las acciones que deben realizarse cuando se accede a una URL concreta.

Por ejemplo, crea una ruta que cargue una página específica cuando un usuario navegue a la página index (/). Para ello, utiliza el método de petición GET.

// Define a route for the homepage
app.get('/', (req, res) => {
  // Here, you can specify what to do when someone accesses the homepage
  // For example, render an EJS template or send some HTML content
});

En el código anterior, cuando un usuario acceda al index de tu aplicación, el servidor ejecutará la función callback especificada como segundo parámetro. Dentro de esta función de llamada de retorno, puedes manejar la lógica para renderizar una plantilla EJS o enviar algún contenido HTML para que se muestre en la página de inicio.

Puedes utilizar el método res.render() para renderizar una plantilla EJS o utilizar res.send() para enviar contenido HTML simple.

app.get('/', (req, res) => {
    res.send('Hello World');
});

Cuando ejecutes tu aplicación, se mostrará «Hello Word» en la página index.

Plantillas EJS

Este tutorial se centra en la lógica e incluye archivos de inicio, para que no tengas que preocuparte de crear plantillas desde cero. Sigue estos pasos para empezar:

  1. Accede a la plantilla en GitHub para crear un nuevo repositorio.
  2. Marca la opción Incluir todas las ramas durante la creación del repositorio.
  3. Una vez creado el repositorio, clona el proyecto en tu ordenador utilizando Git.
  4. Para acceder al código de inicio, cambia a la rama starter-files en tu repositorio local.

En el código de inicio, tenemos dos carpetas principales: public y views. La carpeta public contiene todos los activos estáticos (archivos CSS e imágenes). Se añaden a la plantilla como archivos estáticos:

// Static files
app.use(express.static('/public'));
app.use('/css', express.static(__dirname + '/public/css'));
app.use('/images', express.static(__dirname + '/public/images'));

En la carpeta views, tienes el archivo layout.ejs y dos carpetas: pages y partials. El archivo layout.ejs contiene el diseño general de este proyecto, para que no tengas que repetir código recurrente para todas las páginas. Importa la biblioteca express-ejs-layouts en el archivo app.js y, a continuación, configúrala:

// Import
const expressEjsLayouts = require('express-ejs-layouts');

// Configure
app.use(expressEjsLayouts);

La carpeta pages contiene los archivos de ruta (index.ejs y operation.ejs), mientras que la carpeta partials contiene los componentes (header.ejs y footer.ejs). Añádelos al diseño de la siguiente forma

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="icon" href="/images/favicon.ico" />
        <link rel="stylesheet" href="/css/index.css" />
        <title>Site Builder</title>
    </head>
    <body>
        <div class="app-container">
            <%- include('partials/header') %>
            <div class="container"><%- body %></div>
            <%- include('partials/footer') %>
        </div>
    </body>
</html>

Cuando ejecutes tu aplicación Node.js, la interfaz de usuario se cargará, pero tienes que añadir lógica a esta aplicación para enviar los datos del formulario a la API de Kinsta y enviar información sobre el sitio a Slack cuando se inicie la operación.

Primeros Pasos con los Webhooks Entrantes de Slack

Los Webhooks Entrantes de Slack proporcionan una forma sencilla de enviar mensajes desde aplicaciones externas a Slack. Para utilizar los Webhooks Entrantes de Slack, crea y configura una aplicación Slack, y luego copia la URL de tu Webhook para enviar mensajes a Slack mediante programación.

Configurar una Aplicación Slack y Obtener la URL del Webhook

Crea una nueva aplicación Slack siguiendo estos pasos:

  1. Navega hasta el panel de control de la API de Slack.
  2. Haz clic en el botón Crear Nueva App, que abrirá un modal.
  3. Selecciona la opción Desde Cero para empezar a crear tu aplicación desde cero.
  4. Dale un nombre a tu aplicación Slack, por ejemplo, Kinsta Bot.
  5. A continuación, elige el espacio de trabajo donde quieres instalar la aplicación y haz clic en el botón Crear Aplicación.

Una vez creada tu aplicación Slack, puedes habilitar los Webhooks Entrantes navegando hasta Features y seleccionando Incoming Webhooks. Activa el interruptor para habilitar los Webhooks Entrantes para tu aplicación.

Desplázate hacia abajo hasta la sección Webhook URLs for Your Workspace (URL de Webhooks para tu Espacio de Trabajo) y haz clic en Add New Webhook to Wordspace (Añadir Nuevo Webhook al Espacio de Trabajo). Se te pedirá que elijas un canal al que se enviarán los mensajes. Selecciona el canal deseado y haz clic en Permitir.

Tras la autorización, se te proporcionará una URL de Webhook para el canal seleccionado. Esta URL es la que utilizarás para enviar mensajes a Slack mediante programación. Este es el aspecto de una URL Webhook:

https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Este Webhook es específico para un único usuario y un único canal. Mantenlo seguro, ya que actúa como token de autenticación para tu aplicación. Puedes almacenar los códigos únicos después de /services/ en tu archivo .env. También se te pedirá que reinstales la app en tu espacio de trabajo para que los cambios surtan efecto.

Enviar Mensajes a Slack con Node.js y la API Kinsta

Ahora que la interfaz de tu aplicación Node.js está configurada y el Slackbot se ha creado correctamente (junto con tu URL WebHook), es hora de manejar la lógica.

Obtener Datos del Formulario en Node.js

En la página index, tienes un formulario que enviará datos a la API de Kinsta para crear un nuevo sitio de WordPress. Para que esto funcione, necesitas crear una petición POST desde la página index. Asegúrate de que tu formulario tiene un método POST, y los campos de entrada tienen un atributo name, que se utilizará en el archivo app.js.

app.post('/', (req, res) => {
    // Perform the desired operation with the form data
});

Para recuperar datos de un formulario en Node.js, necesitarás utilizar el siguiente middleware:

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

Ahora, puedes acceder a los valores de tu formulario utilizando req.body.[form field name]. Por ejemplo, req.body.displayName te dará el nombre para mostrar enviado a través del formulario. Vamos a registrar los datos generales del formulario:

app.post('/', (req, res) => {
    console.log(req.body);
});

Cuando ejecutes tu código, se mostrarán los datos del formulario después de rellenarlo y pulsar el botón Enviar.

Detalles del formulario recuperados del parámetro req en Node.js
Detalles del formulario recuperados del parámetro req en Node.js.

Creación de un Sitio con la API de Kinsta en Node.js

Para crear un sitio WordPress con la API Kinsta en Node.js, puedes utilizar el método fetch(), que ahora es compatible y funciona eficazmente en las últimas versiones de Node.js.

Para realizar cualquier operación con la API de Kinsta, necesitas crear una clave API. Para generar una clave API:

  1. Ve a tu panel de control MyKinsta.
  2. Ve a la página Claves API (Tu nombre > Configuración de la empresa > Claves API).
  3. Haz clic en Crear Clave API.
  4. Elige una fecha de caducidad o establece una fecha de inicio personalizada y un número de horas para que caduque la clave.
  5. Dale a la clave un nombre único.
  6. Haz clic en Generar.

Asegúrate de copiar la clave API generada y almacenarla de forma segura, ya que sólo será visible en este momento. Para este proyecto, crea un archivo .env en tu directorio root y guarda la clave API como KINSTA_API_KEY.

Además, para crear un sitio WordPress utilizando la API de Kinsta, necesitarás tu ID de empresa (que puedes encontrar en MyKinsta en Empresa > Detalles de facturación > ID de empresa). Almacena también este ID en el archivo .env, para poder acceder a estas variables de entorno a través de process.env. Para habilitar esta funcionalidad, asegúrate de configurar la dependencia dotenv en la parte superior de tu archivo app.js de la siguiente manera:

require('dotenv').config();

Para proceder a la creación de un sitio WordPress a través de la API de Kinsta, envía una solicitud POST al endpoint /sites con los datos necesarios proporcionados en el objeto req.body:

const KinstaAPIUrl = 'https://api.kinsta.com/v2';

app.post('/', (req, res) => {
    const createSite = async () => {
        const resp = await fetch(`${KinstaAPIUrl}/sites`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                Authorization: `Bearer ${process.env.REACT_APP_KINSTA_API_KEY}`,
            },
            body: JSON.stringify({
                company: process.env.REACT_APP_KINSTA_COMPANY_ID,
                display_name: req.body.displayName,
                region: req.body.location,
                install_mode: 'new',
                is_subdomain_multisite: false,
                admin_email: req.body.email,
                admin_password: req.body.password,
                admin_user: req.body.username,
                is_multisite: false,
                site_title: req.body.siteTitle,
                woocommerce: false,
                wordpressseo: false,
                wp_language: 'en_US',
            }),
        });
        const data = await resp.json();
        console.log(data);
    };
    createSite();
});

Al ejecutar el código anterior, crearás un nuevo sitio WordPress con la API de Kinsta. Pero éste no es el objetivo principal. El objetivo es enviar un mensaje a Slack con información sobre el sitio cuando la operación de creación del sitio se realice correctamente.

Enviar un Mensaje a Slack con la URL del Webhook Entrante

Para ello, crea una sentencia If para comprobar el estado de la respuesta a la solicitud de la API. Si es 202, significa que «la creación del sitio ha comenzado» y puedes enviar un mensaje a Slack utilizando la URL entrante de Webhooks. Para ello, puedes utilizar tu biblioteca de peticiones HTTP preferida (por ejemplo, Axios) o un método para enviar una petición POST a Slack. Utilicemos el método fetch():

if (data.status === 202) {
    fetch(
        `https://hooks.slack.com/services/${process.env.SLACK_WEBHOOK_ID}`,
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                text: 'Hello, world.',
            }),
        }
    );
}

Ejecuta el código anterior y rellena el formulario de creación del sitio. Si el proceso tiene éxito, se enviará inmediatamente un mensaje a Slack.

Hello World enviado desde Node.js a Slack con Incoming Webhooks
Hello World enviado desde Node.js a Slack con Incoming Webhooks

Personalizar los Mensajes de Slack

El ejemplo anterior envía un mensaje de texto básico, pero los Webhooks Entrantes de Slack admiten mucho más que un simple texto. Puedes personalizar tus mensajes para incluir adjuntos, enlaces, imágenes, botones y mucho más.

Una forma de personalizar los mensajes de Slack es utilizar el Constructor de Kit de Bloques de Slack. El Kit de bloques es un framework de interfaz de usuario proporcionado por Slack que te permite construir mensajes ricos e interactivos con diversos elementos de contenido.

Para este tutorial, aquí tienes un bloque creado con el constructor de kit de bloques para dar el formato adecuado al mensaje y añadir algunos valores del formulario y de la respuesta de creación del sitio:

const message = {
    blocks: [
        {
            type: 'section',
            text: {
                type: 'mrkdwn',
                text: `Hello, your new site (${req.body.displayName}) has started building. It takes minutes to build. You can check the operation status intermittently via https://site-builder-nodejs-xvsph.kinsta.app/operation/${req.body.displayName}/${data.operation_id}.`,
            },
        },
        {
            type: 'divider',
        },
        {
            type: 'section',
            text: {
                type: 'mrkdwn',
                text: "_Here are your site's details:_",
            },
        },
        {
            type: 'section',
            text: {
                type: 'mrkdwn',
                text: `1. *Site URL:* http://${req.body.displayName}.kinsta.cloud/n2. *WP Admin URL:* http://${req.body.displayName}.kinsta.cloud/wp-admin/`,
            },
        },
    ],
};

En este código, creas un objeto mensaje que contiene un array de bloques. Cada bloque representa una sección específica del mensaje Slack y puede tener diferentes tipos de contenido.

  1. Bloque de Sección: Este tipo de bloque se utiliza para mostrar una sección de texto. Utiliza el type: 'section' para indicar que es un bloque de sección. Dentro del bloque de sección, la propiedad text se utiliza con type: 'mrkdwn' para especificar que el contenido del texto debe interpretarse como formato Markdown. El contenido de texto real se proporciona en la propiedad text, y utilizamos literales de plantilla para incluir valores dinámicos del formulario y de la respuesta de creación del sitio, como req.body.displayName y data.operation_id.
  2. Bloque Divisor: Este tipo de bloque se utiliza para añadir una línea horizontal para separar secciones del mensaje. Utilizamos type: 'divider' para crear el bloque divisor.

Cuando este mensaje se envíe a Slack mediante el Webhook Entrante, generará un mensaje visualmente atractivo e informativo en tu canal de Slack. El mensaje incluirá valores dinámicos del formulario (como el nombre del sitio) e información de la respuesta de creación del sitio, convirtiéndolo en un mensaje altamente personalizado.

Para enviar este mensaje personalizado, sustituye el objeto del cuerpo del fetch() por el contenido de la variable del mensaje:

if (data.status === 202) {
    fetch(
        `https://hooks.slack.com/services/${process.env.SLACK_WEBHOOK_ID}`,
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(message),
        }
    );
}
Mensaje Slack personalizado con Constructor de Kits de bloques de Slack.
Mensaje Slack personalizado con Constructor de Kits de bloques de Slack.

Manejar la Operación de Creación del Sitio con la API de Kinsta

En el mensaje enviado a Slack, se crea un enlace que tiene el ID de la operación y el nombre para mostrar. Puedes crear una nueva ruta para que la página Operaciones utilice estos datos para comprobar el estado de la operación.

En Express, puedes acceder a los parámetros de la URL con el parámetro req. Por ejemplo, para obtener el ID de la operación, utiliza req.params.operationId.

const KinstaAPIUrl = 'https://api.kinsta.com/v2';

app.get('/operation/:displayName/:operationId', (req, res) => {
    const checkOperation = async () => {
        const operationId = req.params.operationId;
        const resp = await fetch(`${KinstaAPIUrl}/operations/${operationId}`, {
            method: 'GET',
            headers: {
                Authorization: `Bearer ${process.env.REACT_APP_KINSTA_API_KEY}`,
            },
        });
        const data = await resp.json();
        res.render('pages/operation', {
            operationID: req.params.operationId,
            displayName: req.params.displayName,
            operationMessage: data.message,
        });
    };
    checkOperation();
});

Con el código anterior, al hacer clic en el enlace de Slack se realizará una solicitud a la API de Kinsta para comprobar el estado de la operación de tu sitio. Actualiza el archivo operation.ejs para añadir datos dinámicos:

<div class="container-title">
    <h1 class="title">Check Site Operation Status</h1>
    <p>
        Check the status of your site tools operation via the id. Feel free to copy
        the ID and check in few seconds.
    </p>
</div>
<div class="form-container">
    <div class="input-div">
        <input class="form-control" value="<%= operationID %>" readOnly />
    </div>
    <button class="btn" type="submit" onclick="window.location.reload()">
        Refresh Operation Status
    </button>
</div>
<div class="services">
    <div class="details">
        <p><%= operationMessage %>..</p>
    </div>
</div>
<div class="services">
    <p class="description">
        If message above indicates that "Operation has successfully finished", use
        the links below to access your WP admin and the site itself.
    </p>
    <div class="details">
        <a
            href="http://<%= displayName %>.kinsta.cloud/wp-admin/"
            target="_blank"
            rel="noreferrer"
            class="detail-link"
        >
            <p>Open WordPress admin</p>
            <FiExternalLink />
        </a>
        <a
            href="http://<%= displayName %>.kinsta.cloud/"
            target="_blank"
            rel="noreferrer"
            class="detail-link"
        >
            <p>Open URL</p>
            <FiExternalLink />
        </a>
    </div>
</div>
Página de operaciones que muestra el ID de la operación y los detalles del sitio.
Página de operaciones que muestra el ID de la operación y los detalles del sitio.

Una última cosa, puedes utilizar el método de redirección para navegar a la página de operaciones cuando se inicie el proceso de creación de un sitio:

if (data.status === 202) {
    fetch(
        `https://hooks.slack.com/services/${process.env.SLACK_WEBHOOK_ID}`,
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(message),
        }
    );
    res.redirect(`/operation/${req.body.displayName}/${data.operation_id}`);
}

El código fuente completo de este proyecto está disponible en la rama principal de este repositorio de GitHub.

Desplegar Tu Aplicación Node.js en Kinsta

Puedes desplegar fácilmente esta aplicación Node.js en la plataforma de Alojamiento de Aplicaciones de Kinsta. Todo lo que tienes que hacer es enviar tu código a tu proveedor Git preferido (Bitbucket, GitHub o GitLab). A continuación, sigue estos pasos:

  1. Accede a tu cuenta Kinsta en el panel MyKinsta.
  2. Haz clic en Añadir servicio.
  3. Selecciona Aplicación en el menú desplegable.
  4. En el modal que aparece, elige el repositorio que quieres desplegar. Si tienes varias ramas, puedes seleccionar la rama deseada y dar un nombre a tu aplicación.
  5. Selecciona una de las ubicaciones de centros de datos disponibles. Kinsta detectará e instalará las dependencias de tu aplicación desde package.json y, a continuación, la construirá y desplegará.

Por último, no es seguro enviar claves API a alojamientos públicos como tu proveedor de Git. Cuando alojes, puedes añadirlas como variables de entorno utilizando el mismo nombre de variable y valor especificados en el archivo .env.

Establece variables de entorno en DevKinsta al desplegar.
Establece variables de entorno en DevKinsta al desplegar.

Una vez que inicies el despliegue de tu aplicación, normalmente se creará y desplegará en unos minutos. Se proporcionará un enlace a tu nueva aplicación, con el siguiente aspecto: https://site-builder-nodejs-xvsph.kinsta.app.

Resumen

En este tutorial, has aprendido cómo enviar mensajes a Slack desde una aplicación Node.js utilizando Webhooks Entrantes y cómo personalizar los mensajes de Slack con el Kit de Construcción de Bloques.

Las posibilidades con Slack y la API Kinsta son enormes, y este tutorial es sólo el principio. Integrando estas herramientas, puedes crear un flujo de trabajo fluido que mantenga a tu equipo bien informado y aumente la productividad.

¿Cómo utilizas la API Kinsta? ¿Qué funciones te gustaría que se añadieran/expusieran próximamente?

Joel Olawanle Kinsta

Joel is a Frontend developer working at Kinsta as a Technical Editor. He is a passionate teacher with love for open source and has written over 200 technical articles majorly around JavaScript and it's frameworks.