import { Controller, Get, Post, Body, Param, ParseIntPipe, UploadedFile, UseGuards, UseInterceptors, Res, StreamableFile, BadRequestException, Redirect } from '@nestjs/common' import { FileInterceptor } from '@nestjs/platform-express' import { diskStorage } from 'multer' import { type User } from "./entity/user.entity"; import { UsersService } from "./users.service"; import { UserDto, AvatarUploadDto } from "./dto/user.dto"; import { PongService } from "src/pong/pong.service"; import { AuthenticatedGuard } from 'src/auth/42-auth.guard' import { Profile42 } from 'src/auth/42.decorator' import { Profile } from 'passport-42' import { ApiBody, ApiConsumes } from '@nestjs/swagger' import { type Request, Response } from 'express' import { createReadStream } from 'fs' import { join } from 'path' @Controller('users') export class UsersController { constructor (private readonly usersService: UsersService) {} @Post('block/:id') @UseGuards(AuthenticatedGuard) @Post("block/:id") async blockUser(@Profile42() profile :Profile, @Param('id') id:number) { const user = await this.usersService.findUser(id) as User user.blocked.push((await this.usersService.findUser(+profile.id)) as User) this.usersService.save(user) } @Post('unblock/:id') @UseGuards(AuthenticatedGuard) @Post("unblock/:id") async unblockUser(@Profile42() profile :Profile, @Param('id') id:number) { const user = await this.usersService.findUser(id) as User user.blocked = user.blocked.filter((usr: User) => { return usr.id !== id }) this.usersService.save(user) } @Get('all') async getAllUsers (): Promise { return await this.usersService.findUsers() } @Get('online') async getOnlineUsers (): Promise { return await this.usersService.findOnlineUsers() } @Get('friends') @UseGuards(AuthenticatedGuard) async getFriends (@Profile42() profile: Profile): Promise { return await this.usersService.getFriends(profile.id) } @Get('invits') @UseGuards(AuthenticatedGuard) async getInvits (@Profile42() profile: Profile): Promise { return await this.usersService.getInvits(profile.id) } @Get('leaderboard') @UseGuards(AuthenticatedGuard) async getLeaderboard (): Promise { return await this.usersService.getLeaderboard() } @Post('avatar') @UseGuards(AuthenticatedGuard) @Redirect('http://localhost') @UseInterceptors( FileInterceptor('avatar', { storage: diskStorage({ destination: 'avatars/' }), fileFilter: (request: Request, file: Express.Multer.File, callback) => { if (!file.mimetype.includes('image')) { callback(null, false) return } callback(null, true) } }) ) @ApiConsumes("multipart/form-data") @ApiBody({ description: "A new avatar for the user", type: AvatarUploadDto, }) async changeAvatar ( @Profile42() profile: Profile, @UploadedFile() file: Express.Multer.File ): Promise { if (file === undefined) return await this.usersService.addAvatar(profile.id, file.filename) } @Get('avatar') @UseGuards(AuthenticatedGuard) async getAvatar ( @Profile42() profile: Profile, @Res({ passthrough: true }) response: Response ): Promise { return await this.getAvatarById(profile.id, response) } @Get(':name/byname') async getUserByName (@Param('name') username: string): Promise { const user = await this.usersService.findUserByName(username) user.socketKey = '' return user } @Get('invit/:username') @UseGuards(AuthenticatedGuard) async invitUser ( @Profile42() profile: Profile, @Param('username') username: string ): Promise { const target: User | null = await this.usersService.findUserByName( username ) if (target === null) { throw new BadRequestException(`User ${username} not found.`) } if (+profile.id === +target.ftId) { throw new BadRequestException("You can't invite yourself.") } const ret: string = await this.usersService.invit(profile.id, target.ftId) if (ret !== 'OK') throw new BadRequestException(ret) } @Get(':id/avatar') async getAvatarById ( @Param('id', ParseIntPipe) ftId: number, @Res({ passthrough: true }) response: Response ): Promise { const user: User | null = await this.usersService.findUser(ftId) if (user === null) throw new BadRequestException('User unknown.') const filename = user.avatar const stream = createReadStream(join(process.cwd(), 'avatars/' + filename)) response.set({ 'Content-Diposition': `inline; filename='${filename}'`, 'Content-Type': 'image/jpg' }) return new StreamableFile(stream) } @Get(':id') async getUserById ( @Param('id', ParseIntPipe) ftId: number ): Promise { const user = await this.usersService.findUser(ftId) if (user == null) throw new BadRequestException('User unknown.') user.socketKey = '' return user } @Post(':id') @UseGuards(AuthenticatedGuard) async createById (@Body() payload: UserDto): Promise { const user = await this.usersService.findUser(payload.ftId) if (user != null) { await this.usersService.update(user, payload) } else { await this.usersService.create(payload) } } @Get() @UseGuards(AuthenticatedGuard) async getUser (@Profile42() profile: Profile): Promise { return await this.usersService.findUser(profile.id) } @Post() @UseGuards(AuthenticatedGuard) async updateUser ( @Body() payload: UserDto, @Profile42() profile: Profile ): Promise { const user = await this.usersService.findUser(profile.id) if (user == null) throw new BadRequestException('User not found.') return await this.usersService.update(user, payload) } }