aboutsummaryrefslogblamecommitdiff
path: root/src/Chat.js
blob: b55610c775f1fab42ef4257ac3d861c863c9a1dd (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13

                                                         
                                                                  









                                  
                          

                            

























                                                         





                   

                    
     
                                                                      



                            





                             

                              
           
         









                                                                     







































                                                                       

   











                                                   
                                                                              




                                       
                                  


                             



                                       
                                                                 
                                                                        



                                       


                                 
                                                               
              
                  








                                       
                  
                                                                               

                     
                                                                    
                                       




                                                  
                          



                                                             




                                                     





























                                                                             






                                                               




                    

                     


                                  
                                                             


                                                                      



                                                                              







                                                                







                                                                                        


                                                          




                                                

                   




                                              

               
























                                            









                                                                       





                    
import React, { Component } from "react";
import { w3cwebsocket as W3CWebSocket } from "websocket";
import { Header, List, Input, Checkbox } from "semantic-ui-react";
import Moment from "react-moment";
import "moment/locale/es";

class Chat extends Component {
  constructor(props) {
    super(props);
    this.state = {
      chat: [],
      chatMessage: "",
      chatUserCount: 0,
      isChatOnline: false,
      filterMessages: false,
      isAdministrador: false
    };
    this.client = {};
    this.chatColors = [
      "grey",
      "red",
      "pink",
      "orange",
      "yellow",
      "green",
      "teal",
      "blue",
      "purple",
      "black"
    ];
    this.handleOnChange = this.handleOnChange.bind(this);
    this.sendMessage = this.sendMessage.bind(this);
  }

  handleOnChange(e, data) {
    this.setState({ chatMessage: data.value });
  }

  translateColon(msg) {
    return msg ? msg.replace(/%3A/g, ":") : "";
  }

  addMessage(
    message,
    stream,
    own = false,
    sender = "",
    color = "grey",
    timestamp = "",
    isNotice = false
  ) {
    const ts = timestamp ? new Date(parseInt(timestamp)) : new Date();
    this.setState(
      prevState => ({
        chat: [
          ...prevState.chat,
          {
            content: message,
            stream: stream,
            own,
            timestamp: ts,
            author: sender,
            color: color,
            isNotice: isNotice
          }
        ]
      }),
      () => {
        let chatContainer = document.getElementById("chatContainer");
        if (chatContainer != null) {
          chatContainer.scrollTop = chatContainer.scrollHeight;
        }
      }
    );
  }

  printMessage(message, color, notice = false) {
    this.addMessage(message, "", false, "", color, "", notice);
  }

  processCommand(command) {
    const args = command.split(" ");
    const argCount = args.length;
    switch (args[0]) {
      case "/login":
        if (argCount === 2) {
          this.client.send("LOGIN:" + args[1]);
        }
        break;
      case "/logout":
        this.client.send("LOGOUT");
        break;
      case "/notice":
        if (argCount > 1) {
          this.client.send("NOTICE:0:" + command.replace(args[0], ""));
        }
        break;
      case "/kick":
        if (argCount === 2) {
          this.client.send("KICK:" + args[1]);
        }
        break;
      case "/ban":
        if (argCount === 2) {
          this.client.send("BAN:" + args[1]);
        }
        break;
      case "/title":
        if (argCount > 1) {
          this.client.send("SETTITLE:" + command.replace(args[0], ""));
        }
        break;
      default:
        break;
    }
    this.setState({ chatMessage: "" });
  }

  componentWillMount() {
    this.client = new W3CWebSocket(
      "wss://radio.bienvenidoainternet.org/daemon/"
    );
    this.client.onopen = () => {
      this.setState({ isChatOnline: true });
    };
    this.client.onmessage = message => {
      this.processChatMessage(message.data);
    };
    this.client.onerror = () => {
      this.setState({ isChatOnline: false });
      this.printMessage("Ha ocurrido un error conectándose al chat.", "red");
    };
  }

  sendMessage() {
    const { chatMessage } = this.state;
    const { stream } = this.props;
    if (chatMessage === "") {
      return;
    }
    if (chatMessage.startsWith("/")) {
      this.processCommand(chatMessage);
      return;
    }
    this.client.send(`MSG:${stream.server_name}:${chatMessage}`);
    this.addMessage(chatMessage, stream.server_name, true, "", "black");
    this.setState({ chatMessage: "" });
  }

  processChatMessage(line) {
    const args = line.split(":");
    switch (args[0]) {
      case "MSG":
        this.addMessage(this.translateColon(args[2]), args[1]);
        break;
      case "HMSG":
        this.addMessage(
          this.translateColon(args[3]),
          args[2],
          false,
          "",
          "grey",
          args[1]
        );
        break;
      case "FMSG":
        this.addMessage(this.translateColon(args[3]), args[2], false, args[1]);
        break;
      case "WELCOME":
        this.printMessage("Conectado al chat, " + args[1], "green");
        this.client.send("HISTORY:10");
        break;
      case "COUNT":
        this.setState({ chatUserCount: args[1] });
        break;
      case "FLOOD":
        this.printMessage(
          "Error: Estas enviando mensajes demasido rápido!",
          "red"
        );
        break;
      case "HISTORY_OK":
        /*  Renard: z411: que hago con el HISTORY_OK?
            Renard: me lo meto en la raja?
            z411: bien adentro */
        break;
      case "BADPASS":
        this.printMessage("Error: contraseña incorrecta!", "red");
        break;
      case "LOGIN_OK":
        this.printMessage(
          `Bienvenido ${args[1]}, ahora tienes permisos de administrador.`,
          "blue"
        );
        this.setState({ isAdministrador: true });
        break;
      case "FORBIDDEN":
        this.printMessage(
          "Error: No tienes permisos suficientes para ejecutar esta acción",
          "red"
        );
        break;
      case "KICKED":
        this.printMessage("Has sido expulsado del chat", "red");
        this.client.close();
        break;
      case "TITLE":
        this.printMessage(
          "El streamer ha cambiado el título de la transmisión",
          "orange"
        );
        this.client.close();
        break;
      case "NOTICE":
        this.printMessage(args[2], "yellow", true);
        break;
      default:
        console.error("[Chat] Unsupported command " + args[0]);
        break;
    }
  }

  render() {
    const {
      chat,
      chatMessage,
      chatUserCount,
      isChatOnline,
      filterMessages,
      isAdministrador
    } = this.state;
    const { stream } = this.props;

    const MessageItem = ({ message, index, showAuthor }) => {
      return (
        <List.Item key={index}>
          [<Moment format="HH:mm:ss" date={message.timestamp} />]{" "}
          {message.author !== "" && showAuthor && `(${message.author})`}
          <span
            className={message.isNotice ? "iidx" : `ui text ${message.color}`}
          >
            {`${message.stream && "[" + message.stream + "]"} ${
              message.content
            }`}
          </span>
        </List.Item>
      );
    };

    return (
      <>
        <Header as="h3">
          Chat
          <Header.Subheader>{`Usuarios en el chat: ${chatUserCount}`}</Header.Subheader>
        </Header>
        <div id="chatContainer">
          <List>
            {chat.map((message, i) =>
              filterMessages ? (
                message.stream === stream.server_name && (
                  <MessageItem
                    message={message}
                    index={i}
                    showAuthor={isAdministrador}
                  />
                )
              ) : (
                <MessageItem
                  message={message}
                  index={i}
                  showAuthor={isAdministrador}
                />
              )
            )}
          </List>
        </div>
        <Input
          fluid
          size="mini"
          action={{
            content: "Enviar",
            onClick: () => {
              this.sendMessage();
            },
            disabled: !isChatOnline
          }}
          placeholder=""
          value={chatMessage}
          onChange={this.handleOnChange}
          style={{ marginTop: "0.75em" }}
          maxLength={128}
          onKeyUp={e => {
            let char = e.which || e.keyCode;
            if (char === 13) {
              this.sendMessage();
            }
          }}
          disabled={!isChatOnline}
        />
        <Checkbox
          checked={filterMessages}
          label="Filtrar mensajes de usuarios escuchando stream actual"
          onClick={() => {
            this.setState(prevState => ({
              filterMessages: !prevState.filterMessages
            }));
          }}
          style={{ marginTop: "0.5em" }}
        />
      </>
    );
  }
}

export default Chat;