replitで簡易的なオンラインチャットを作成できたのでメモ。
ここで実際の動作を見れます。
ruiwenge2氏のガイドを参照して作成。より単純なオンラインの例が載ってある。
15:36追記:最新チャットが上になるように変更。
16:28追記:repl再起動後、それ以前にチャットに参加した人の名前がundefined
になる不具合アリ。
再起動前に参加したか確認し、その場合は自動でリロードするよう修正。
19:36追記:開発者ツールを用いれば改行が使えるらしい。要修正
21:05追記
・改行を無効化。
・なぜか日本時間じゃなかったので修正。
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 (クライアント)
<!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>
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
)に反応してログが崩れる可能性がある。
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