import { Router } from "@oak/oak"; import { authMiddleware } from "../middleware/auth.ts"; import { type APIResponse, type Dump, type FollowStatus, type PaginatedData, } from "../model/interfaces.ts"; import { followPlaylist, followUser, getFollowedPlaylistsDumpFeed, getFollowedUsersDumpFeed, getFollowStatus, unfollowPlaylist, unfollowUser, } from "../services/follow-service.ts"; const router = new Router({ prefix: "/api/follows" }); // Static routes first to prevent Oak matching "status"/"feed" as a :param // GET /api/follows/status router.get("/status", authMiddleware, (ctx) => { const status = getFollowStatus(ctx.state.user.userId as string); const body: APIResponse = { success: true, data: status }; ctx.response.body = body; }); // GET /api/follows/feed/users?page=&limit= router.get("/feed/users", authMiddleware, (ctx) => { const page = Math.max( 1, parseInt(ctx.request.url.searchParams.get("page") ?? "1") || 1, ); const limit = Math.min( Math.max( 1, parseInt(ctx.request.url.searchParams.get("limit") ?? "20") || 20, ), 100, ); const { items, total } = getFollowedUsersDumpFeed( ctx.state.user.userId as string, page, limit, ); const data: PaginatedData = { items, total, hasMore: page * limit < total, }; const body: APIResponse> = { success: true, data }; ctx.response.body = body; }); // GET /api/follows/feed/playlists?page=&limit= router.get("/feed/playlists", authMiddleware, (ctx) => { const page = Math.max( 1, parseInt(ctx.request.url.searchParams.get("page") ?? "1") || 1, ); const limit = Math.min( Math.max( 1, parseInt(ctx.request.url.searchParams.get("limit") ?? "20") || 20, ), 100, ); const { items, total } = getFollowedPlaylistsDumpFeed( ctx.state.user.userId as string, page, limit, ); const data: PaginatedData = { items, total, hasMore: page * limit < total, }; const body: APIResponse> = { success: true, data }; ctx.response.body = body; }); // POST /api/follows/users/:userId router.post("/users/:userId", authMiddleware, (ctx) => { followUser(ctx.state.user.userId as string, ctx.params.userId); ctx.response.status = 204; }); // DELETE /api/follows/users/:userId router.delete("/users/:userId", authMiddleware, (ctx) => { unfollowUser(ctx.state.user.userId as string, ctx.params.userId); ctx.response.status = 204; }); // POST /api/follows/playlists/:playlistId router.post("/playlists/:playlistId", authMiddleware, (ctx) => { followPlaylist(ctx.state.user.userId as string, ctx.params.playlistId); ctx.response.status = 204; }); // DELETE /api/follows/playlists/:playlistId router.delete("/playlists/:playlistId", authMiddleware, (ctx) => { unfollowPlaylist(ctx.state.user.userId as string, ctx.params.playlistId); ctx.response.status = 204; }); export default router;