-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathsocketapi.js
137 lines (113 loc) · 6.45 KB
/
socketapi.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
const io = require("socket.io")()
const crypto = require('crypto')
const socketapi = { io: io }
const NB_ONLINE_INSTRUCTORS = 'NB_ONLINE_INSTRUCTORS'
const NB_ONLINE_STUDENTS = 'NB_ONLINE_STUDENTS'
let dict = {}
let socketUserMapping = {}
io.on('connection', function (socket) {
socket.on('joined', data => handleOnJoin(socket, data))
socket.on("disconnect", data => handleOnDisconnect(socket, data))
socket.on("left", data => handleOnLeft(socket, data))
// socket.on('thread-typing', data => handleOnThreadTyping(socket, data))
// socket.on('thread-stop-typing', data => handleOnThreadStopTyping(socket, data))
})
function handleOnJoin(socket, data) {
console.log(`\n********* IO -> JOINED:\n${data?.username} (${data?.role})\nsource: ${data?.sourceURL}\nclass: ${data?.classId}\n*********`)
socketUserMapping[socket.id] = data
const urlHash = crypto.createHash('md5').update(data.sourceURL).digest('hex')
const globalRoomId = `${urlHash}:${data.classId}`
const classSectionRooms = Array.from(io.sockets.adapter.rooms.keys()).filter(c => c.startsWith(`${globalRoomId}:`))
if (data.sectionId && data.sectionId.length > 0) {
const sectionRoomId = `${urlHash}:${data.classId}:${data.sectionId}`
socket.sectionRoomId = sectionRoomId
socket.join(sectionRoomId)
io.to(sectionRoomId).emit('connections', { online: (io.sockets.adapter.rooms.get(sectionRoomId)?.size || 0) + (io.sockets.adapter.rooms.get(globalRoomId)?.size || 0), users: fetchOnlineUsers([globalRoomId, sectionRoomId]) })
} else {
socket.join(globalRoomId)
classSectionRooms.forEach(sectionRoomId => io.to(sectionRoomId).emit('connections', { online: (io.sockets.adapter.rooms.get(sectionRoomId)?.size || 0) + (io.sockets.adapter.rooms.get(globalRoomId)?.size || 0), users: fetchOnlineUsers([globalRoomId, sectionRoomId]) }))
}
if (data?.role === 'instructor') {
socket.join(NB_ONLINE_INSTRUCTORS)
} else {
socket.join(NB_ONLINE_STUDENTS)
}
socket.nbuser = data
socket.globalRoomId = globalRoomId
const classAllRooms = Array.from(io.sockets.adapter.rooms.keys()).filter(c => c.startsWith(globalRoomId))
io.to(globalRoomId).emit('connections', { online: classAllRooms.reduce((acc, curr) => acc + (io.sockets.adapter.rooms.get(curr)?.size || 0), 0), users: fetchOnlineUsers(classAllRooms) })
}
function handleOnDisconnect(socket, data) {
console.log(`\n********* IO -> DISCONNECT:\n${data?.username} (${data?.role})\nsource: ${data?.sourceURL}\nclass: ${data?.classId}\n*********`)
delete socketUserMapping[socket.id]
if (socket.sectionRoomId) {
io.to(socket.sectionRoomId).emit('connections', { online: (io.sockets.adapter.rooms.get(socket.sectionRoomId)?.size || 0) + (io.sockets.adapter.rooms.get(socket.globalRoomId)?.size || 0), users: fetchOnlineUsers([socket.globalRoomId, socket.sectionRoomId]) })
}
const classAllRooms = Array.from(io.sockets.adapter.rooms.keys()).filter(c => c.startsWith(socket.globalRoomId))
io.to(socket.globalRoomId).emit('connections', { online: classAllRooms.reduce((acc, curr) => acc + io.sockets.adapter.rooms.get(curr).size, 0), users: fetchOnlineUsers(classAllRooms) })
}
function handleOnLeft(socket, data) {
console.log(`\n********* IO -> LEFT:\n${data?.username} (${data?.role})\nsource: ${data?.sourceURL}\nclass: ${data?.classId}\n*********`)
delete socketUserMapping[socket.id]
const urlHash = crypto.createHash('md5').update(data.sourceURL).digest('hex')
const globalRoomId = `${urlHash}:${data.classId}`
const classSectionRooms = Array.from(io.sockets.adapter.rooms.keys()).filter(c => c.startsWith(`${globalRoomId}:`))
if (data.sectionId && data.sectionId.length > 0) {
const sectionRoomId = `${urlHash}:${data.classId}:${data.sectionId}`
socket.sectionRoomId = null
socket.leave(sectionRoomId)
io.to(sectionRoomId).emit('connections', { online: (io.sockets.adapter.rooms.get(sectionRoomId)?.size || 0) + (io.sockets.adapter.rooms.get(globalRoomId)?.size || 0), users: fetchOnlineUsers([globalRoomId, sectionRoomId]) })
} else {
socket.leave(globalRoomId)
classSectionRooms.forEach(sectionRoomId => io.to(sectionRoomId).emit('connections', { online: (io.sockets.adapter.rooms.get(sectionRoomId)?.size || 0) + (io.sockets.adapter.rooms.get(globalRoomId)?.size || 0), users: fetchOnlineUsers([globalRoomId, sectionRoomId]) }))
}
socket.globalRoomId = null
const classAllRooms = Array.from(io.sockets.adapter.rooms.keys()).filter(c => c.startsWith(globalRoomId))
io.to(globalRoomId).emit('connections', { online: classAllRooms.reduce((acc, curr) => acc + (io.sockets.adapter.rooms.get(curr)?.size || 0), 0), users: fetchOnlineUsers(classAllRooms) })
}
// function handleOnThreadTyping(socket, data) {
// if (data.threadId in dict) {
// dict[data.threadId].add(data.username)
// } else {
// dict[data.threadId] = new Set([data.username])
// }
// io.emit('thread-typing', { usersTyping: [...dict[data.threadId]], threadId: data.threadId })
// }
// function handleOnThreadStopTyping(socket, data) {
// if (data.threadId in dict) {
// dict[data.threadId].delete(data.username)
// if (dict[data.threadId].size == 0) {
// io.emit('thread-typing', { usersTyping: [...dict[data.threadId]], threadId: data.threadId })
// }
// }
// }
function fetchOnlineUsers(socketIds) {
let users = {}
users.students = []
users.instructors = []
users.ids = []
try {
socketIds.forEach(socketId => {
// TODO: check here
Array.from(io.sockets.adapter.rooms.get(socketId) || []).forEach(connection => {
if (!users.ids.includes(socketUserMapping[connection]?.id)) {
// TODO: check why it crashed here
try {
users.ids.push(socketUserMapping[connection].id)
if (socketUserMapping[connection].role.toLowerCase() === 'instructor') {
users.instructors.push(socketUserMapping[connection])
} else {
users.students.push(socketUserMapping[connection])
}
} catch (error) {
console.log(error);
}
}
})
})
} catch (error) {
console.error(error);
}
return users
}
module.exports = socketapi