141 lines
7.3 KiB
JavaScript
141 lines
7.3 KiB
JavaScript
"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.get('/search', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
|
const { q } = validation_1.searchQuerySchema.parse(req.query);
|
|
const userId = req.user.userId;
|
|
const results = await db_1.db
|
|
.select({ id: schema_1.users.id, username: schema_1.users.username })
|
|
.from(schema_1.users)
|
|
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.ne)(schema_1.users.id, userId), (0, drizzle_orm_1.ilike)(schema_1.users.username, `%${q}%`)))
|
|
.orderBy((0, drizzle_orm_1.asc)(schema_1.users.username))
|
|
.limit(20);
|
|
res.json(results);
|
|
}));
|
|
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
|