LoginSignup
0
0

More than 1 year has passed since last update.

replit + Node.jsで簡易オンラインチャット

Last updated at Posted at 2022-12-03

replitで簡易的なオンラインチャットを作成できたのでメモ。

ここで実際の動作を見れます。

ruiwenge2氏のガイドを参照して作成。より単純なオンラインの例が載ってある。

15:36追記:最新チャットが上になるように変更。
16:28追記:repl再起動後、それ以前にチャットに参加した人の名前がundefinedになる不具合アリ。
再起動前に参加したか確認し、その場合は自動でリロードするよう修正。
19:36追記:開発者ツールを用いれば改行が使えるらしい。要修正
21:05追記
・改行を無効化。
・なぜか日本時間じゃなかったので修正。

index.js (サーバー)

index.js
const express = require("express"); // use express
const app = express(); // create instance of express
const server = require("http").Server(app); // create server
const io = require("socket.io")(server); // create instance of socketio

app.use(express.static("public")); // use "public" directory for static files
const users = {};
const textlog = [];

io.on("connection", socket => {
  socket.on("setup", () => {
    if (textlog.length>0){
      io.emit("updatelog",textlog);
    }
  });
  socket.on("joined", (name) => { // when server recieves the "joined" message
    username = name.split('\n').join(" ")
    users[socket.id] = username; // add user to dictionary
    updatetextlog(getnowtime() + " " + username + " joined")
    console.log(users);
    io.emit("updatelog",textlog);
  });
  socket.on("sendmes", (text) => {
    if (socket.id in users){
      username = users[socket.id];
      updatetextlog(getnowtime() + " " + username + " : "+text.split('\n').join(" "));
      io.emit("updatelog",textlog);
    }else{
      io.to(socket.id).emit("reload")
    }
  });
  socket.on("disconnect", () => { // when someone closes the tab
    if (socket.id in users){
      username = users[socket.id]
      delete users[socket.id]; // remove user from dictionary
      console.log(users);
      updatetextlog(getnowtime() + " " + username + " leaved")
      io.emit("updatelog",textlog);
    }
  });
});

function updatetextlog(newtext){
  textlog.unshift(newtext)
  if (textlog.length>100){
    N=textlog.length-100
    for (let i=0;i<N;i++){
      textlog.pop();
    }
  }
}

function getnowtime(){
  date = new Date();
  text = "";
  textlist = [(date.getHours()+9)%24,date.getMinutes(),date.getSeconds()];
  for (let i=0;i<3;i++){
    if (textlist[i]<10){
      text += "0" + textlist[i]
    }else{
      text += textlist[i]
    }if (i<2){
      text+=":"
    }
  }
  return text
}

server.listen(3000); // run server

io.emit("関数名", 変数)でクライアント側のsocket.on("関数名",処理)を実行する。
・クライアント側のsocket.emit("関数名", 変数)が実行された際、こちらのsocket.on("関数名",処理)が実行される。

index.html / script.js (クライアント)

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>chat test</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script> <!-- use the library -->
<script src="/script.js"></script> <!-- use "script.js" file -->
<div id="chatbox"><input type="text" id="textbox" placeholder="type your name"><input type="button" value="join the chat" onclick="join()"></div>
<div id="logbox">chat log</div>
</body>
</html>
script.js
const socket = io(); // create new instance

socket.emit("setup");

socket.on("updatelog", (textlog) => {
  log=document.getElementById("logbox");
  log.innerHTML = ""
  for (let i=0;i<textlog.length;i++){
    log.innerText += textlog[i]+"\n"
  }
});

socket.on("reload",()=>{location.reload();})

function join(){
  text=document.getElementById("textbox");
  if (text.value!==""){
    socket.emit("joined",text.value);
    chat=document.getElementById("chatbox");
    chat.innerHTML = '<input type="text" id="textbox" size="600"><input type="button" value="send" onclick="send()">';
  }
}

function send(){
  text=document.getElementById("textbox");
  if (text.value!==""){
    socket.emit("sendmes",text.value);
    text.value="";
  }
}

socket.emit("関数名", 変数)でサーバー側のsocket.on("関数名",処理)を実行する。
・サーバー側のio.emit("関数名", 変数)が実行された際、こちらのsocket.on("関数名",処理)が実行される。

追記

Replit Databaseを用いれば、repl再起動後もチャットを保存できる。

以下の例では、テキスト中の\n(≠\\n)に反応してログが崩れる可能性がある。

index.js
const express = require("express"); // use express
const app = express(); // create instance of express
const server = require("http").Server(app); // create server
const io = require("socket.io")(server); // create instance of socketio
+ const Database = require("@replit/database")
+ const db = new Database()

app.use(express.static("public")); // use "public" directory for static files
const users = {};
const textlog = [];
+ db.get("textlog").then(value => {Array.prototype.push.apply(textlog, value.split("\n"))});

io.on("connection", socket => {
  socket.on("setup", () => {
    if (textlog.length>0){
      io.emit("updatelog",textlog);
    }
  });
  socket.on("joined", (name) => { // when server recieves the "joined" message
    username = name.split('\n').join(" ")
    users[socket.id] = username; // add user to dictionary
    updatetextlog(getnowtime() + " " + username + " joined")
    console.log(users);
    io.emit("updatelog",textlog);
  });
  socket.on("sendmes", (text) => {
    if (socket.id in users){
      username = users[socket.id];
      updatetextlog(getnowtime() + " " + username + " : "+text.split('\n').join(" "));
      io.emit("updatelog",textlog);
    }else{
      io.to(socket.id).emit("reload")
    }
  });
  socket.on("disconnect", () => { // when someone closes the tab
    if (socket.id in users){
      username = users[socket.id]
      delete users[socket.id]; // remove user from dictionary
      console.log(users);
      updatetextlog(getnowtime() + " " + username + " leaved")
      io.emit("updatelog",textlog);
    }
  });
});

function updatetextlog(newtext){
  textlog.unshift(newtext)
  if (textlog.length>100){
    N=textlog.length-100
    for (let i=0;i<N;i++){
      textlog.pop();
    }
  }
+ db.set("textlog", textlog.join("\n")).then(() => {});
}

function getnowtime(){
  date = new Date();
  text = "";
  textlist = [(date.getHours()+9)%24,date.getMinutes(),date.getSeconds()];
  for (let i=0;i<3;i++){
    if (textlist[i]<10){
      text += "0" + textlist[i]
    }else{
      text += textlist[i]
    }if (i<2){
      text+=":"
    }
  }
  return text
}

server.listen(3000); // run server
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0