import Conversation, { ConversationMember, ConversationUserMember, MemberRole, } from '@nirvana/core/models/conversation.model'; import { JwtClaims, authCheck } from '../middleware/auth'; import express, { NextFunction, Request, Response, response } from 'express'; import ConversationService from '../services/conversation.service'; import CreateConversationRequest from '@nirvana/core/requests/CreateConversationRequest.request'; import CreateConversationResponse from '@nirvana/core/responses/CreateConversationResponse.response'; import { MemberState } from '@nirvana/core/models/conversation.model'; import NirvanaResponse from '@nirvana/core/responses/nirvanaResponse'; import { ObjectId } from 'mongodb'; import UpdateConversationPriorityRequest from '@nirvana/core/requests/UpdateConversationPriority.request'; import { UserService } from '../services/user.service'; export default function getConversationRoutes() { const router = express.Router(); router.use(express.json()); // get a conversation by id router.get('/:conversationId', authCheck, getConversationById); // get all conversations that I am in // todo: add in pagination for performance, while allowing getting long polling updates? router.get('/', authCheck, getAllConversations); // get a one on one conversation based on other user Id router.get('/check/:otherUserId', authCheck, getOneOnOneConversationIfExists); // get a conversation's content router.get('/:conversationId/content', authCheck); // create a conversation router.post('/', authCheck, createConversation); // change user's categorization of conversation router.post('/:conversationId/priority', authCheck, updatePriorityOfConversation); return router; } const getConversationById = async (req: Request, res: Response, next: NextFunction) => { const { conversationId } = req.params; if (!conversationId) { return next(Error('Must provide a conversation Id')); } const conversationResult = await ConversationService.getConversationById(conversationId); const responseObj = new NirvanaResponse( conversationResult, undefined, conversationResult ? 'here is the conversation' : 'No conversation found', ); return res.json(responseObj); }; const getAllConversations = async (req: Request, res: Response, next: NextFunction) => { const userInfo = res.locals.userInfo as JwtClaims; // todo: use pagination params to get only certain ones try { const resultConversations = await ConversationService.getAllConversationsForUser( userInfo.userId, ); const responseObj = new NirvanaResponse( resultConversations ?? [], undefined, 'here are all of the conversations for user', ); return res.json(responseObj); } catch (error) { return next(Error('unable to get conversations')); } }; const getOneOnOneConversationIfExists = async (req: Request, res: Response, next: NextFunction) => { const userInfo = res.locals.userInfo as JwtClaims; const { otherUserId } = req.params; try { const resultConversation = await ConversationService.getConversationBetweenTwoPeople( new ObjectId(userInfo.userId), new ObjectId(otherUserId), ); return res.json( new NirvanaResponse( resultConversation?._id ?? undefined, undefined, resultConversation ? 'there is a conversation...quick dial them now!' : 'no such conversation exists!', ), ); } catch (error) { return next(Error('unable to get conversations')); } }; const createConversation = async (req: Request, res: Response, next: NextFunction) => { const createRequest = req.body as CreateConversationRequest; const userInfo = res.locals.userInfo as JwtClaims; // todo: do quick check to make sure that we don't already have a conversation // as last resort if client didn't already do this if (!createRequest.otherUsers || createRequest.otherUsers.length === 0) { return next(new Error('must provide who you want to talk to')); } // if it's a one on one, and one already exists then don't allow creating another convo!! if (createRequest.otherUsers.length === 1) { const oneOnOneExists = await ConversationService.getConversationBetweenTwoPeople( new ObjectId(userInfo.userId), new ObjectId(createRequest.otherUsers[0]._id), ); if (oneOnOneExists) { return next(Error('Already have a conversatoin with them! quick dial them!')); } } // process of creating other conversation user members with their user objects // for cached data purposes const conversationUserMembers: ConversationUserMember[] = []; createRequest.otherUsers.forEach((userObject) => { const newConversationMember = new ConversationMember(MemberRole.regular, 'inbox'); // ! hack as json over the wire converts to string for some reason userObject._id = new ObjectId(userObject._id); conversationUserMembers.push({ ...userObject, ...newConversationMember, }); }); // adding in the admin user which is the user who started the conversation const adminMember = new ConversationMember(MemberRole.admin, 'inbox'); const currentUser = await UserService.getUserById(userInfo.userId); if (!currentUser) { return next(new Error('unable to find your user object for caching')); } conversationUserMembers.push({ ...currentUser, ...adminMember, }); // make the insert of the overall conversation document const newConversation = new Conversation( userInfo.userId, conversationUserMembers, createRequest.conversationName, ); const insertResult = await ConversationService.createConversation(newConversation); if (!insertResult) { return next(Error('unable to create a conversation')); } // todo: send updates to other users if they are connected through sockets const responseObj = new NirvanaResponse( new CreateConversationResponse(insertResult.insertedId), undefined, 'created conversation!', ); return res.json(responseObj); }; const updatePriorityOfConversation = async (req: Request, res: Response, next: NextFunction) => { const { conversationId } = req.params; const userInfo = res.locals.userInfo as JwtClaims; const reqObj = req.body as UpdateConversationPriorityRequest; try { const updateRes = await ConversationService.updateUserConversationPriority( new ObjectId(conversationId), new ObjectId(userInfo.userId), reqObj.newState, ); return res.json( new NirvanaResponse( undefined, undefined, updateRes?.ok ? 'updated' : 'failed to update conversation priority', ), ); } catch (error) { next(Error('unable to set conversation as priority')); } };