chat2/app.js

137 lines
4.5 KiB
JavaScript

import express from "express";
import http from "http";
import log4js from "log4js";
import { Server } from "socket.io";
import { loadHistory, saveToDatabase, queryHistory, getDatabaseState } from "./storage.js";
const PORT = process.env.PORT || 5691;
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
const logger = log4js.getLogger("app");
app.use(express.static("static"))
logger.level = process.env.LOG_LEVEL || "debug";
// 初始化在线列表
let onlineList = [];
let clientMap = new Map();
class Response {
constructor(status, msg) {
this.status = status
this.msg = msg
}
}
app.get("/online", (req, res) => {
res.status(200).send({
online: onlineList.length,
user: onlineList
})
})
app.get("/history", (req, res) => {
if (!getDatabaseState()) {
res.status(500).send({
status: 500,
msg: "database is not ready",
data: null
})
}
if (!req.query.limit || isNaN(req.query.limit) || req.query.limit <= 0 || req.query.limit > 100) {
req.query.limit = 10;
}
loadHistory(req.query.limit).then((data) => {
res.status(200).send({
status: 200,
msg: "success",
data: data
})
}).catch((err) => {
logger.error(`database error: ${err}`)
res.status(500).send({
status: 500,
msg: "database error",
data: null
})
})
})
io.on("connection", (socket) => {
logger.info(`A client connected, id: ${socket.id}`)
socket.on("system", data => {
if (!data) {
socket.emit("system", JSON.stringify(new Response(false, "data payload is empty.")))
return;
}
if (clientMap.has(socket.id)) {
socket.emit("system", JSON.stringify(new Response(false, "you are already online.")))
return;
}
try {
const { opt, args } = JSON.parse(data);
console.log(opt, args)
if (opt == "signin") {
if (!args || !args.username) {
socket.emit("system", JSON.stringify(new Response(false, "username is empty.")))
return;
}
const { username } = args
if (username.length > 20) {
socket.emit("system", JSON.stringify(new Response(false, "username is too long.")))
}
if (onlineList.indexOf(username) != -1) {
socket.emit("system", JSON.stringify(new Response(false, "username is already taken.")))
return;
}
socket.username = username;
onlineList.push(username);
clientMap.set(socket.id, username);
socket.emit("username", socket.username);
socket.emit("system", JSON.stringify(new Response(true, `welcome, ${socket.username}`)))
io.emit("notice", JSON.stringify(new Response(true, `${socket.username} join the chat.`)))
logger.debug(`socket(${socket.id}) -- ${username} signed in.`)
}
} catch (err) {
logger.error(`socket(${socket.id}) -- ${err}.`)
socket.emit("system", JSON.stringify(new Response(false, "data payload is invaild.")))
return;
}
console.log(clientMap)
console.log(onlineList)
})
socket.on("msg", data => {
if (!socket.username) {
socket.emit("system", JSON.stringify(new Response(false, "you are not signed in.")));
return;
}
logger.debug(`socket(${socket.id}) -- ${data}`)
io.emit("msg", JSON.stringify({sender: socket.username, msg: data}))
saveToDatabase(socket.username, data, new Date().getTime())
})
socket.on("disconnect", (reason, description) => {
logger.info(`A client disconnected, id: ${socket.id}`)
logger.trace(`socket(${socket.id}) -- reason: ${reason}, description: ${description}`);
if (clientMap.has(socket.id)) clientMap.delete(socket.id);
// TODO: 这个算法有点不安全
if (onlineList.includes(socket.username)) onlineList.splice(onlineList.indexOf(socket.id));
io.emit("notice", JSON.stringify(new Response(true, `${socket.username} left the chat.`)));
})
});
server.listen(PORT, () => {
logger.info(`Server running on port ${PORT}`);
});