import { Router } from 'express'; import type { Request, Response } from 'express'; import { checkSocialEnabled } from './social.middleware'; import { groupService } from './group.service'; import { generateModeratorToken } from '../jitsi/jitsi.utils'; import { prisma } from '../../config/database'; const router = Router(); router.use(checkSocialEnabled); /** GET /api/social/groups — list my groups */ router.get('/', async (req: Request, res: Response) => { try { const userId = req.user!.id; const page = Math.max(1, parseInt(req.query.page as string) || 1); const limit = Math.min(50, Math.max(1, parseInt(req.query.limit as string) || 20)); const result = await groupService.listMyGroups(userId, page, limit); res.json(result); } catch (err: any) { res.status(err.statusCode || 500).json({ error: { message: err.message } }); } }); /** GET /api/social/groups/:id — group detail with members (membership required) */ router.get('/:id', async (req: Request, res: Response) => { try { const groupId = req.params.id as string; const userId = req.user!.id; const result = await groupService.getGroupDetail(groupId); // Verify the requesting user is a member of this group const isMember = result.members.some((m: any) => m.userId === userId); if (!isMember) { res.status(404).json({ error: { message: 'Group not found', code: 'NOT_FOUND' } }); return; } res.json(result); } catch (err: any) { res.status(err.statusCode || 500).json({ error: { message: err.message } }); } }); /** POST /api/social/groups/:id/call/start — start group call */ router.post('/:id/call/start', async (req: Request, res: Response) => { try { // Check enableMeet const settings = await prisma.siteSettings.findFirst({ select: { enableMeet: true } }); if (!settings?.enableMeet) { res.status(404).json({ error: { message: 'Video meetings are not enabled' } }); return; } const groupId = req.params.id as string; const result = await groupService.startGroupCall(groupId, req.user!.id); res.status(201).json(result); } catch (err: any) { res.status(err.statusCode || 500).json({ error: { message: err.message } }); } }); /** POST /api/social/groups/:id/call/end — end group call */ router.post('/:id/call/end', async (req: Request, res: Response) => { try { const groupId = req.params.id as string; const result = await groupService.endGroupCall(groupId, req.user!.id); res.json(result); } catch (err: any) { res.status(err.statusCode || 500).json({ error: { message: err.message } }); } }); /** POST /api/social/groups/:id/call/token — get moderator JWT for group call */ router.post('/:id/call/token', async (req: Request, res: Response) => { try { const groupId = req.params.id as string; const meeting = await groupService.getCallMeeting(groupId, req.user!.id); const user = await prisma.user.findUnique({ where: { id: req.user!.id }, select: { id: true, email: true, name: true }, }); if (!user) { res.status(404).json({ error: { message: 'User not found' } }); return; } const token = generateModeratorToken(user, meeting.jitsiRoom); res.json({ token, room: meeting.jitsiRoom, slug: meeting.slug }); } catch (err: any) { res.status(err.statusCode || 500).json({ error: { message: err.message } }); } }); export { router as groupRouter };