|
@@ -0,0 +1,162 @@
|
|
|
+const { v4: uuidv4 } = require("uuid")
|
|
|
+const server = require("http").createServer()
|
|
|
+const port = 10010
|
|
|
+const io = require("socket.io")(server, {
|
|
|
+ path: "/im-rtc",
|
|
|
+ serveClient: false,
|
|
|
+ pingInterval: 10000,
|
|
|
+ pingTimeout: 5000,
|
|
|
+ cors: {
|
|
|
+ origin: "*",
|
|
|
+ methods: ["GET", "POST"],
|
|
|
+ },
|
|
|
+})
|
|
|
+
|
|
|
+io.on("connection", socket => new ClientRequest(socket))
|
|
|
+
|
|
|
+server.listen(port)
|
|
|
+
|
|
|
+const __rooms = {}
|
|
|
+class ClientRequest {
|
|
|
+ constructor(socket) {
|
|
|
+ this.socket = socket
|
|
|
+ this.option = socket.handshake.query
|
|
|
+ this.init()
|
|
|
+
|
|
|
+ // 没有roomId时新建
|
|
|
+ if (!this.option.roomId) {
|
|
|
+ this.option.roomId = uuidv4()
|
|
|
+ }
|
|
|
+
|
|
|
+ // 没有角色时默认为主持人
|
|
|
+ if (!this.option.role) {
|
|
|
+ this.option.role = "leader"
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断roomId在房间列表中是否存在
|
|
|
+ if (!__rooms[this.option.roomId]) {
|
|
|
+ // 初始化房间
|
|
|
+ __rooms[this.option.roomId] = []
|
|
|
+ }
|
|
|
+
|
|
|
+ // 没有userId时新建
|
|
|
+ if (!this.option.userId) {
|
|
|
+ // 没有userId就新建
|
|
|
+ this.option.userId = "user-" + (__rooms[this.option.roomId].length + 1)
|
|
|
+ }
|
|
|
+
|
|
|
+ let { role, type, roomId, userId, userName } = this.option
|
|
|
+ let user = { role, type, roomId, userId, userName }
|
|
|
+ let users = __rooms[this.option.roomId]
|
|
|
+
|
|
|
+ users.push(user)
|
|
|
+
|
|
|
+ this.socket.join(this.option.roomId)
|
|
|
+ this.socket.emit("join", {
|
|
|
+ user,
|
|
|
+ users,
|
|
|
+ })
|
|
|
+ this.onUserJoin(user, users)
|
|
|
+ }
|
|
|
+ init() {
|
|
|
+ this.socket.on("disconnect", reason => this.onDisconnect(reason))
|
|
|
+ this.socket.on("reconnect", reason => this.onReconnect(reason))
|
|
|
+
|
|
|
+ // 通用事件
|
|
|
+ this.socket.on("action", data => {
|
|
|
+ this.socket.broadcast.to(this.option.roomId).emit("action", data)
|
|
|
+ })
|
|
|
+
|
|
|
+ // 踢人
|
|
|
+ this.socket.on("getOut", userId => this.onGetOut(userId))
|
|
|
+
|
|
|
+ // 静音
|
|
|
+ this.socket.on("muted", (muted, userId) => this.onMuted(muted, userId))
|
|
|
+ }
|
|
|
+
|
|
|
+ onDisconnect(reason) {
|
|
|
+ let user = null
|
|
|
+ let users = __rooms[this.option.roomId]
|
|
|
+
|
|
|
+ for (let i = 0; i < users.length; i++) {
|
|
|
+ if (this.option.userId == users[i].userId) {
|
|
|
+ let splices = users.splice(i, 1)
|
|
|
+ if (splices.length) {
|
|
|
+ user = splices[0]
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ user && this.onUserLeave(user, users)
|
|
|
+ }
|
|
|
+ onReconnect(reason) {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 踢人
|
|
|
+ */
|
|
|
+ onGetOut(userId) {
|
|
|
+ if (!this.isLeader()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.socket.broadcast.to(this.option.roomId).emit("getOut", userId)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 静音
|
|
|
+ * @param {*} muted 静音状态
|
|
|
+ * @param {*} userId 如果有userId,则设置指定用户静音
|
|
|
+ */
|
|
|
+ onMuted(muted, userId) {
|
|
|
+ // 群体静音只有主持人才能使用
|
|
|
+ if (!this.isLeader()) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let user = null
|
|
|
+ let users = __rooms[this.option.roomId]
|
|
|
+
|
|
|
+ if (userId) {
|
|
|
+ for (let i = 0; i < users.length; i++) {
|
|
|
+ if (users[i].userId == userId) {
|
|
|
+ user = users[i]
|
|
|
+ user.muted = muted
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 没找到指定参与人时不做操作
|
|
|
+ if (!user) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 设置所有参与人除主持人外静音状态
|
|
|
+ users.forEach(item => {
|
|
|
+ if(item.role == 'leader'){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ item.muted = muted
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ this.socket.broadcast.to(this.option.roomId).emit("muted", muted, userId)
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 通知其他用户有人加入房间
|
|
|
+ */
|
|
|
+ onUserJoin(user, users) {
|
|
|
+ this.socket.broadcast.to(this.option.roomId).emit("userJoin", { user, users })
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知其他用户有人离开房间
|
|
|
+ */
|
|
|
+ onUserLeave(user, users) {
|
|
|
+ this.socket.broadcast.to(this.option.roomId).emit("userLeave", { user, users })
|
|
|
+ console.log(`用户[${user.userId}]离开房间`)
|
|
|
+ }
|
|
|
+
|
|
|
+ isLeader() {
|
|
|
+ return this.option.role == "leader"
|
|
|
+ }
|
|
|
+}
|