domingo, 19 de febrero de 2017

Chat con Websockets - Aurelia y Express (Parte 4 - Enviando y recibiendo mensajes)

Hola de nuevo, ya que el backend y el frontend están conectados, es hora de enviar y recibir mensajes de las personas con las que nos encontramos chateando. Para esto descargaremos el frontend y el backend con los siguientes comandos (puedes seguir todo el proceso para llegar hasta acá en posts anteriores):
Para el backend:

$ git clone https://github.com/feardarkness/chat-backend.git
$ git checkout tags/connect-be-fe

Para iniciar ingresamos a la carpeta chat-backend y ejecutamos:

$ npm start

Para el frontend:

$ git clone https://github.com/feardarkness/chat-frontend.git
$ git checkout tags/connect-be-fe

Para iniciar ingresamos a la carpeta chat-frontend y ejecutamos:

$ NODE_ENV=dev au run --watch

Ahora modifiquemos el código para mandar mensajes, es necesario modificar tanto el backend como el frontend, así que dividiremos los cambios en dos.

FRONTEND

Es necesario cambiar (src/resources/elements/chat-windows.html) el textarea por un div para ir agregando los mensajes que se nos envien, además se agrega un input text para anotar nuestro alias en el chat y se agrega un tag form para que cuando presionemos la tecla enter el formulario se envie (cuando presionamos enter, el primer botón submit que está en el formulario se presiona).

<template>
  <div class="row" id="chat">
    <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
        <div id="chat-content" ref="messages"></div>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
      <div class="form-group">
        <div class="col-sm-2">
          <input type="text" class="form-control"
                 placeholder="Usuario"
                 value.bind="username">
        </div>
        <form submit.delegate="sendMessage()">
          <div class="col-sm-5">
            <input type="text" class="form-control"
               id="mensaje" placeholder="Escriba el mensaje"
               value.bind="message" autofocus>
          </div>
          <div class="col-sm-2">
            <button type="submit" class="btn btn-primary">Enviar Mensaje</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</template>

Modificaremos los estilos (src/assets/main.scss) para que el div de los mensajes tenga un alto de 200 píxeles y lo marcaremos con un borde sólido de 2 píxeles con las esquinas redondeadas.

@import "../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

#chat{
  #chat-content {
    border: 2px solid #000000;
    border-radius: 5px;
    height:200px;
    overflow: auto;
    padding: 4px;
    margin: 5px 0px;

    .chat-message {

      .username {
        font-style: italic;
      }
    }
  }
}

Por último para el frontend, modificaremos el viewModel (src/resources/elements/chat-window.js) para que en el momento en que nos llegue un mensaje del backend lo agreguemos al div donde mostraremos los mensajes del chat.

this.socket.on('be-message', (data) => {
      this.logger.debug('Event with data', data);
      $(this.messages).append(
        this.createMessageDiv(
          data.message,
          data.username
        )
      );

    });

Además, agregaremos al viewModel (src/resources/elements/chat-window.js) la opción de generar una cadena aleatoria para establecer el nombre de usuario y agregar el mensaje con jquery al div, el archivo completo quedaría así:

import io from 'socket.io';
import {LogManager} from 'aurelia-framework';
import $ from 'bootstrap';

export class ChatWindow {
  message = '';
  username = '';

  constructor() {
    this.logger = LogManager.getLogger('chat-window-element');
    this.username = this.randomString();
  }

  attached() {
    this.logger.debug('Attached...');
    this.socket = io('http://127.0.0.1:8081');

    this.socket.on('connect', () =>{
      this.logger.debug('Socket connected...');
    });

    this.socket.on('be-message', (data) => {
      this.logger.debug('Event with data', data);
      $(this.messages).append(
        this.createMessageDiv(
          data.message,
          data.username
        )
      );

    });

    this.socket.on('disconnect', () =>{
      this.logger.debug('Socket disconnected...');
    });
  }

  createMessageDiv(message, username) {
    return $('<div class="chat-message"><span class="username">'
                    + username + ':</span> ' + message + '</div>');
  }

  sendMessage() {
    this.socket.emit('fe-message', {
      message: this.message,
      username: this.username
    });
  }

  randomString() {
    const letrasDisponibles = `ABCDEFGHIJKLMNOPQRSTUVWXYZ
                      abcdefghijklmnopqrstuvwxyzÑñ0123456789`;
    let cadena = '';
    '1234567'.split('').forEach(() => {
      const pos = Math.floor(Math.random() * letrasDisponibles.length);
      cadena += letrasDisponibles.charAt(pos);
    });
    return cadena;
  }
}

BACKEND

En el backend se implementará el envió de mensajes a todos los clientes conectados, en caso de recibir un mensaje del frontend (fe-message), emitimos ese mensaje a todos los clientes (be-message). Por ahora no realizamos ninguna validación, eso se implementara en un post posterior pero es necesario saber que las validaciones son MUY IMPORTANTES, y en ningún caso se debe confiar en los datos enviados por el cliente.

import express from 'express';
import http from 'http';
import debugModule from 'debug';
import socketIO from 'socket.io';

const app = express();
const server = http.Server(app);
const io = socketIO(server);
const debug = debugModule('chat-backend');

server.listen(8081, () => {
  debug('Servidor escuchando en el puerto 8081');
});

io.on('connection', (socket) => {
  debug('Alguien esta conectado!!!');

  socket.emit('be-message', {
    message: 'Bienvenido usuario!!!',
    username: 'Servidor',
  });

  socket.on('fe-message', (data) => {
    debug('Usuario conectado', data);
    io.emit('be-message', data);
  });
});

Ahora veamos un ejemplo de como debería quedarnos el chat:

Ejemplo de comunicación entre usuarios
Antes de realizar las pruebas en nuestros equipos es necesario deshabilitar browsersync que esta habilitado por defecto en Aurelia. Ingresar a 127.0.0.1:3001, sync options -> disable all -> habilitar code sync. Esto hará que los cambios que realicemos en una ventana no se repitan en otra (si no deshabilitamos estas opciones, las acciones que realicemos se repetirán en todos los navegadores donde tengamos abierta la aplicación).

Y eso es todo por ahora, para descargar la aplicación es necesario realizar los siguientes pasos:

BACKEND
$ git clone https://github.com/feardarkness/chat-backend.git
$ git checkout tags/send-receive-messages

FRONTEND
$ git clone https://github.com/feardarkness/chat-frontend.git
$ git checkout tags/send-receive-messages

Keep coding >_<


No hay comentarios:

Publicar un comentario