nicer flow for disconnections, adding socket initialization and such
This commit is contained in:
+8
-118
@@ -1,7 +1,9 @@
|
||||
import express, { Application, Request, Response } from "express";
|
||||
|
||||
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
|
||||
import InitializeWs from "./sockets";
|
||||
import { NextFunction } from "express";
|
||||
import NirvanaResponse from "@nirvana/core/responses/nirvanaResponse";
|
||||
import ReceiveSignal from "../core/sockets/receiveSignal";
|
||||
import SendSignal from "@nirvana/core/sockets/sendSignal";
|
||||
import SocketChannels from "@nirvana/core/sockets/channels";
|
||||
@@ -26,14 +28,16 @@ app.get("/", (req: Request, res: Response) => {
|
||||
res.send("hello world.");
|
||||
});
|
||||
|
||||
app.use("/api", (req: Request, res: Response) => {
|
||||
res.json(new NirvanaResponse("wohoo, server is healthy"));
|
||||
});
|
||||
|
||||
app.use("/api/user", getUserRoutes());
|
||||
app.use("/api/search", getSearchRoutes());
|
||||
app.use("/api/lines", getLineRoutes());
|
||||
|
||||
const PORT = 5000;
|
||||
var server = app.listen(PORT, () => console.log("express running"));
|
||||
|
||||
// socket IO stuff
|
||||
const server = app.listen(PORT, () => console.log("express running"));
|
||||
|
||||
const io = require("socket.io")(server, {
|
||||
// todo: add authentication
|
||||
@@ -42,118 +46,4 @@ const io = require("socket.io")(server, {
|
||||
},
|
||||
});
|
||||
|
||||
io.on("connection", function (socket: any) {
|
||||
// add to map between between googleUserIds and socketId
|
||||
|
||||
console.log("a user connected");
|
||||
|
||||
// ===== JOIN ====
|
||||
/** User wants to subscribe to live emissions of a conversation */
|
||||
socket.on(SocketChannels.JOIN_ROOM, (relationshipId: string) => {
|
||||
// add this user to the room
|
||||
|
||||
console.log(
|
||||
`${socket.id} user joined room for relationship ${relationshipId}`
|
||||
);
|
||||
|
||||
socket.join(relationshipId);
|
||||
|
||||
console.log(`${socket.id} now in rooms ${socket.rooms}`);
|
||||
});
|
||||
|
||||
// ==== UPDATES ====
|
||||
// can be a change of:
|
||||
// 1. status...later...do short polling for this instead
|
||||
// 2. new content: audio clip or link
|
||||
// 3. someone is starting to speak
|
||||
// send message to everyone in room except sender...
|
||||
|
||||
/** User wants to send some update to a particular room */
|
||||
socket.on(
|
||||
SocketChannels.SEND_AUDIO_CLIP,
|
||||
(relationshipId: string, audioChunks: any) => {
|
||||
console.log(`new audio chunks received..routing to appropriate room!`);
|
||||
console.log(relationshipId);
|
||||
console.log(audioChunks);
|
||||
|
||||
io.in(relationshipId).emit(
|
||||
SocketChannels.SEND_AUDIO_CLIP,
|
||||
relationshipId,
|
||||
audioChunks
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// tell everyone in a room when someone is starting to speak
|
||||
socket.on(SocketChannels.SEND_STARTED_SPEAKING, (relationshipId: string) => {
|
||||
console.log(`started speaking in ${relationshipId}`);
|
||||
io.in(relationshipId).emit(
|
||||
SocketChannels.SEND_STARTED_SPEAKING,
|
||||
relationshipId
|
||||
);
|
||||
});
|
||||
|
||||
// tell everyone in a room when someone is stopping to speak
|
||||
socket.on(SocketChannels.SEND_STOPPED_SPEAKING, (relationshipId: string) => {
|
||||
console.log(`stopped speaking in ${relationshipId}`);
|
||||
io.in(relationshipId).emit(
|
||||
SocketChannels.SEND_STOPPED_SPEAKING,
|
||||
relationshipId
|
||||
);
|
||||
});
|
||||
|
||||
// change of user status to all of users' rooms and db update
|
||||
socket.on(
|
||||
SocketChannels.SEND_USER_STATUS_UPDATE,
|
||||
async (userGoogleId: string, newStatus: UserStatus) => {
|
||||
console.log("new status for user");
|
||||
|
||||
const resultUpdate = await UserService.updateUserStatus(
|
||||
userGoogleId,
|
||||
newStatus
|
||||
);
|
||||
|
||||
// tell all rooms that the user is part of
|
||||
// that this user has updated their status
|
||||
if (resultUpdate?.modifiedCount) {
|
||||
socket.rooms.forEach((roomId: string) => {
|
||||
io.in(roomId).emit(
|
||||
SocketChannels.SEND_USER_STATUS_UPDATE,
|
||||
userGoogleId,
|
||||
newStatus
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => {
|
||||
// TODO: only get the socket ids of the relevant rooms for this user
|
||||
// return all Socket instances
|
||||
const allConnectedSockets = Array.from(await io.of("/").sockets.keys());
|
||||
|
||||
io.to(socket.id).emit(SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, {
|
||||
socketIds: allConnectedSockets,
|
||||
} as GetAllSocketClients);
|
||||
});
|
||||
|
||||
socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => {
|
||||
console.log(payload);
|
||||
|
||||
const sendingBackData: ReceiveSignal = {
|
||||
simplePeerSignal: payload.simplePeerSignal,
|
||||
senderUserSocketId: socket.id,
|
||||
isGoingBackToInitiator: payload.isAnswerer ? true : false,
|
||||
};
|
||||
|
||||
io.to(payload.userSocketIdToSignal).emit(
|
||||
SocketChannels.RECEIVE_SIGNAL,
|
||||
sendingBackData
|
||||
);
|
||||
});
|
||||
|
||||
// ==== DISCONNECT ====
|
||||
socket.on("disconnect", () => {
|
||||
console.log("user disconnected");
|
||||
});
|
||||
});
|
||||
InitializeWs(io);
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
|
||||
import { JwtClaims } from "../middleware/auth";
|
||||
import ReceiveSignal from "@nirvana/core/sockets/receiveSignal";
|
||||
import SendSignal from "@nirvana/core/sockets/sendSignal";
|
||||
import SocketChannels from "@nirvana/core/sockets/channels";
|
||||
import { UserService } from "../services/user.service";
|
||||
import { UserStatus } from "@nirvana/core/models/user.model";
|
||||
import { loadConfig } from "../config";
|
||||
|
||||
const jwt = require("jsonwebtoken");
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
export default function InitializeWs(io: any) {
|
||||
console.log("initializing web sockets");
|
||||
|
||||
return io
|
||||
.use(function (socket: any, next: any) {
|
||||
console.log("authenticating user...");
|
||||
|
||||
try {
|
||||
const { token } = socket.handshake.query;
|
||||
|
||||
// verify jwt token with our api secret
|
||||
var decoded: JwtClaims = jwt.verify(token, config.JWT_TOKEN_SECRET);
|
||||
|
||||
socket.userInfo = decoded;
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(new Error("WS Authentication Error"));
|
||||
}
|
||||
})
|
||||
.on("connection", function (socket: any) {
|
||||
const userInfo: JwtClaims = socket.userInfo;
|
||||
|
||||
console.log(
|
||||
`a user connected | user Id: ${userInfo.userId} and name: ${userInfo.name}`
|
||||
);
|
||||
|
||||
socket.on("test", () => {
|
||||
console.log("asdf");
|
||||
});
|
||||
|
||||
// ?verification that user is in a particular line to be tuned into it or just generally in it?
|
||||
|
||||
// regular socket rooms for information for all clients in a specific line
|
||||
|
||||
// another namespace or so for clients tuned into certain lines
|
||||
|
||||
// ===== JOIN ====
|
||||
/** User wants to subscribe to live emissions of a conversation */
|
||||
socket.on(SocketChannels.JOIN_ROOM, (relationshipId: string) => {
|
||||
// add this user to the room
|
||||
|
||||
console.log(
|
||||
`${socket.id} user joined room for relationship ${relationshipId}`
|
||||
);
|
||||
|
||||
socket.join(relationshipId);
|
||||
|
||||
console.log(`${socket.id} now in rooms ${socket.rooms}`);
|
||||
});
|
||||
|
||||
// ==== UPDATES ====
|
||||
// can be a change of:
|
||||
// 1. status...later...do short polling for this instead
|
||||
// 2. new content: audio clip or link
|
||||
// 3. someone is starting to speak
|
||||
// send message to everyone in room except sender...
|
||||
|
||||
/** User wants to send some update to a particular room */
|
||||
socket.on(
|
||||
SocketChannels.SEND_AUDIO_CLIP,
|
||||
(relationshipId: string, audioChunks: any) => {
|
||||
console.log(
|
||||
`new audio chunks received..routing to appropriate room!`
|
||||
);
|
||||
console.log(relationshipId);
|
||||
console.log(audioChunks);
|
||||
|
||||
io.in(relationshipId).emit(
|
||||
SocketChannels.SEND_AUDIO_CLIP,
|
||||
relationshipId,
|
||||
audioChunks
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// tell everyone in a room when someone is starting to speak
|
||||
socket.on(
|
||||
SocketChannels.SEND_STARTED_SPEAKING,
|
||||
(relationshipId: string) => {
|
||||
console.log(`started speaking in ${relationshipId}`);
|
||||
io.in(relationshipId).emit(
|
||||
SocketChannels.SEND_STARTED_SPEAKING,
|
||||
relationshipId
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// tell everyone in a room when someone is stopping to speak
|
||||
socket.on(
|
||||
SocketChannels.SEND_STOPPED_SPEAKING,
|
||||
(relationshipId: string) => {
|
||||
console.log(`stopped speaking in ${relationshipId}`);
|
||||
io.in(relationshipId).emit(
|
||||
SocketChannels.SEND_STOPPED_SPEAKING,
|
||||
relationshipId
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// change of user status to all of users' rooms and db update
|
||||
socket.on(
|
||||
SocketChannels.SEND_USER_STATUS_UPDATE,
|
||||
async (userGoogleId: string, newStatus: UserStatus) => {
|
||||
console.log("new status for user");
|
||||
|
||||
const resultUpdate = await UserService.updateUserStatus(
|
||||
userGoogleId,
|
||||
newStatus
|
||||
);
|
||||
|
||||
// tell all rooms that the user is part of
|
||||
// that this user has updated their status
|
||||
if (resultUpdate?.modifiedCount) {
|
||||
socket.rooms.forEach((roomId: string) => {
|
||||
io.in(roomId).emit(
|
||||
SocketChannels.SEND_USER_STATUS_UPDATE,
|
||||
userGoogleId,
|
||||
newStatus
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => {
|
||||
// TODO: only get the socket ids of the relevant rooms for this user
|
||||
// return all Socket instances
|
||||
const allConnectedSockets = Array.from(await io.of("/").sockets.keys());
|
||||
|
||||
io.to(socket.id).emit(SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, {
|
||||
socketIds: allConnectedSockets,
|
||||
} as GetAllSocketClients);
|
||||
});
|
||||
|
||||
socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => {
|
||||
console.log(payload);
|
||||
|
||||
const sendingBackData: ReceiveSignal = {
|
||||
simplePeerSignal: payload.simplePeerSignal,
|
||||
senderUserSocketId: socket.id,
|
||||
isGoingBackToInitiator: payload.isAnswerer ? true : false,
|
||||
};
|
||||
|
||||
io.to(payload.userSocketIdToSignal).emit(
|
||||
SocketChannels.RECEIVE_SIGNAL,
|
||||
sendingBackData
|
||||
);
|
||||
});
|
||||
|
||||
// ==== DISCONNECT ====
|
||||
socket.on("disconnect", () => {
|
||||
console.log("user disconnected");
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user