"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = require("express"); const asyncHandler_1 = require("../utils/asyncHandler"); const db_1 = require("../db"); const schema_1 = require("../db/schema"); const drizzle_orm_1 = require("drizzle-orm"); const auth_1 = require("../utils/auth"); const auth_2 = require("../utils/auth"); const errorHandler_1 = require("../middleware/errorHandler"); const validation_1 = require("../utils/validation"); const router = (0, express_1.Router)(); router.use(auth_2.authMiddleware); async function findUsernames(ids) { if (ids.length === 0) return new Map(); const rows = await db_1.db.select().from(schema_1.users).where((0, drizzle_orm_1.or)(...ids.map((id) => (0, drizzle_orm_1.eq)(schema_1.users.id, id)))); return new Map(rows.map((u) => [u.id, u.username])); } router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => { const userId = req.user.userId; const outgoingRows = await db_1.db .select() .from(schema_1.friendships) .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.status, 'pending'))); const incomingRows = await db_1.db .select() .from(schema_1.friendships) .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.friendId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.status, 'pending'))); const acceptedRows = await db_1.db .select() .from(schema_1.friendships) .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.or)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, userId)), (0, drizzle_orm_1.eq)(schema_1.friendships.status, 'accepted'))); const friendIds = acceptedRows.map((r) => (r.userId === userId ? r.friendId : r.userId)); const outgoingIds = outgoingRows.map((r) => r.friendId); const incomingIds = incomingRows.map((r) => r.userId); const usernames = await findUsernames([...friendIds, ...outgoingIds, ...incomingIds]); const friends = acceptedRows.map((r) => { const friendId = r.userId === userId ? r.friendId : r.userId; return { id: friendId, username: usernames.get(friendId) ?? '' }; }); const outgoing = outgoingRows.map((r) => ({ id: r.id, username: usernames.get(r.friendId) ?? '', requestId: r.id, status: 'pending', })); const incoming = incomingRows.map((r) => ({ id: r.userId, username: usernames.get(r.userId) ?? '', requestId: r.id, status: 'pending', })); res.json({ friends, incoming, outgoing }); })); router.post('/requests', (0, asyncHandler_1.asyncHandler)(async (req, res) => { const { username } = validation_1.friendRequestSchema.parse(req.body); const userId = req.user.userId; if (username.toLowerCase() === (await meUsername(userId))) { throw new errorHandler_1.AppError('SELF_REQUEST', 'You cannot add yourself', 400); } const target = await db_1.db.select().from(schema_1.users).where((0, drizzle_orm_1.eq)(schema_1.users.username, username)).limit(1); if (target.length === 0) { throw new errorHandler_1.AppError('USER_NOT_FOUND', 'No user with that username found', 404); } const existing = await db_1.db .select() .from(schema_1.friendships) .where((0, drizzle_orm_1.or)((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, target[0].id)), (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, target[0].id), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, userId)))) .limit(1); if (existing.length > 0) { throw new errorHandler_1.AppError('ALREADY_FRIENDS', existing[0].status === 'accepted' ? 'You are already friends' : 'Friend request already pending', 409); } const now = Date.now(); await db_1.db.insert(schema_1.friendships).values({ id: (0, auth_1.generateId)('friend'), userId, friendId: target[0].id, status: 'pending', createdAt: now, updatedAt: now, }); res.status(201).json({ success: true }); })); router.post('/requests/:id/accept', (0, asyncHandler_1.asyncHandler)(async (req, res) => { const userId = req.user.userId; const requestId = req.params.id; const row = await db_1.db.select().from(schema_1.friendships).where((0, drizzle_orm_1.eq)(schema_1.friendships.id, requestId)).limit(1); if (row.length === 0) { throw new errorHandler_1.AppError('NOT_FOUND', 'Request not found', 404); } if (row[0].friendId !== userId) { throw new errorHandler_1.AppError('FORBIDDEN', 'This request was not sent to you', 403); } if (row[0].status !== 'pending') { throw new errorHandler_1.AppError('INVALID_STATE', 'Request is no longer pending', 409); } await db_1.db .update(schema_1.friendships) .set({ status: 'accepted', updatedAt: Date.now() }) .where((0, drizzle_orm_1.eq)(schema_1.friendships.id, requestId)); res.json({ success: true }); })); router.delete('/requests/:id', (0, asyncHandler_1.asyncHandler)(async (req, res) => { const userId = req.user.userId; const requestId = req.params.id; const row = await db_1.db.select().from(schema_1.friendships).where((0, drizzle_orm_1.eq)(schema_1.friendships.id, requestId)).limit(1); if (row.length === 0) { throw new errorHandler_1.AppError('NOT_FOUND', 'Request not found', 404); } if (row[0].userId !== userId && row[0].friendId !== userId) { throw new errorHandler_1.AppError('FORBIDDEN', 'Not allowed', 403); } await db_1.db.delete(schema_1.friendships).where((0, drizzle_orm_1.eq)(schema_1.friendships.id, requestId)); res.json({ success: true }); })); router.delete('/:friendId', (0, asyncHandler_1.asyncHandler)(async (req, res) => { const userId = req.user.userId; const friendId = req.params.friendId; await db_1.db .delete(schema_1.friendships) .where((0, drizzle_orm_1.or)((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, friendId)), (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, friendId), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, userId)))); res.json({ success: true }); })); async function meUsername(userId) { const me = await db_1.db.select().from(schema_1.users).where((0, drizzle_orm_1.eq)(schema_1.users.id, userId)).limit(1); return me.length > 0 ? me[0].username.toLowerCase() : ''; } exports.default = router; //# sourceMappingURL=friends.js.map