From e83987012621aef47101213a5a7e9622594fb4e1 Mon Sep 17 00:00:00 2001 From: Xen0Xys Date: Sat, 18 May 2024 12:53:37 +0200 Subject: [PATCH] :sparkles: Improve routes naming and roles --- .../models/responses/episode.response.ts | 4 - ....response.ts => light-webtoon-response.ts} | 2 +- ...isodes.response.ts => webtoon-response.ts} | 23 ++-- .../webtoon/webtoon-database.service.ts | 103 ++++++++++-------- .../webtoon/webtoon/webtoon.controller.ts | 34 ++++-- 5 files changed, 92 insertions(+), 74 deletions(-) rename src/modules/webtoon/webtoon/models/responses/{webtoon.response.ts => light-webtoon-response.ts} (93%) rename src/modules/webtoon/webtoon/models/responses/{episodes.response.ts => webtoon-response.ts} (54%) diff --git a/src/modules/webtoon/webtoon/models/responses/episode.response.ts b/src/modules/webtoon/webtoon/models/responses/episode.response.ts index c321fc9..5322735 100644 --- a/src/modules/webtoon/webtoon/models/responses/episode.response.ts +++ b/src/modules/webtoon/webtoon/models/responses/episode.response.ts @@ -3,14 +3,10 @@ import {ApiProperty} from "@nestjs/swagger"; export default class EpisodeResponse{ @ApiProperty() title: string; - @ApiProperty() - images: string[]; constructor( title: string, - images: string[] ){ this.title = title; - this.images = images; } } diff --git a/src/modules/webtoon/webtoon/models/responses/webtoon.response.ts b/src/modules/webtoon/webtoon/models/responses/light-webtoon-response.ts similarity index 93% rename from src/modules/webtoon/webtoon/models/responses/webtoon.response.ts rename to src/modules/webtoon/webtoon/models/responses/light-webtoon-response.ts index c3acf61..20538e8 100644 --- a/src/modules/webtoon/webtoon/models/responses/webtoon.response.ts +++ b/src/modules/webtoon/webtoon/models/responses/light-webtoon-response.ts @@ -1,6 +1,6 @@ import {ApiProperty} from "@nestjs/swagger"; -export default class WebtoonResponse{ +export default class LightWebtoonResponse{ @ApiProperty() id: number; @ApiProperty() diff --git a/src/modules/webtoon/webtoon/models/responses/episodes.response.ts b/src/modules/webtoon/webtoon/models/responses/webtoon-response.ts similarity index 54% rename from src/modules/webtoon/webtoon/models/responses/episodes.response.ts rename to src/modules/webtoon/webtoon/models/responses/webtoon-response.ts index a7b3963..b10efb5 100644 --- a/src/modules/webtoon/webtoon/models/responses/episodes.response.ts +++ b/src/modules/webtoon/webtoon/models/responses/webtoon-response.ts @@ -1,34 +1,27 @@ -import EpisodeLineModel from "../models/episode-line.model"; import {ApiProperty} from "@nestjs/swagger"; +import LightWebtoonResponse from "./light-webtoon-response"; -export default class EpisodesResponse{ - @ApiProperty() - episodes: EpisodeLineModel[]; +export default class WebtoonResponse extends LightWebtoonResponse{ @ApiProperty() backgroundBanner: string; @ApiProperty() topBanner: string; @ApiProperty() mobileBanner: string; - @ApiProperty() - title: string; - @ApiProperty() - author: string; constructor( - episodes: EpisodeLineModel[], + id: number, + title: string, + language: string, + thumbnail: string, + author: string, backgroundBanner: string, topBanner: string, mobileBanner: string, - title: string, - author: string ){ - this.episodes = episodes; + super(id, title, language, thumbnail, author); this.backgroundBanner = backgroundBanner; this.topBanner = topBanner; this.mobileBanner = mobileBanner; - this.title = title; - this.author = author; } - } diff --git a/src/modules/webtoon/webtoon/webtoon-database.service.ts b/src/modules/webtoon/webtoon/webtoon-database.service.ts index 8cd1836..6329815 100644 --- a/src/modules/webtoon/webtoon/webtoon-database.service.ts +++ b/src/modules/webtoon/webtoon/webtoon-database.service.ts @@ -3,20 +3,19 @@ import CachedWebtoonModel from "./models/models/cached-webtoon.model"; import EpisodeModel from "./models/models/episode.model"; import EpisodeDataModel from "./models/models/episode-data.model"; import EpisodeResponse from "./models/responses/episode.response"; -import EpisodesResponse from "./models/responses/episodes.response"; import EpisodeLineModel from "./models/models/episode-line.model"; -import WebtoonResponse from "./models/responses/webtoon.response"; +import LightWebtoonResponse from "./models/responses/light-webtoon-response"; import WebtoonModel from "./models/models/webtoon.model"; import WebtoonDataModel from "./models/models/webtoon-data.model"; import {Injectable, NotFoundException} from "@nestjs/common"; import {PrismaService} from "../../misc/prisma.service"; import {MiscService} from "../../misc/misc.service"; import ImageTypes from "./models/enums/image-types"; +import WebtoonResponse from "./models/responses/webtoon-response"; @Injectable() export class WebtoonDatabaseService{ - constructor( private readonly prismaService: PrismaService, private readonly miscService: MiscService @@ -224,22 +223,22 @@ export class WebtoonDatabaseService{ }); } - async getWebtoons(): Promise{ - const webtoons = await this.prismaService.webtoons.findMany({ + async getWebtoons(): Promise{ + const webtoons: any = await this.prismaService.webtoons.findMany({ include: { thumbnail: true } }); - const response: WebtoonResponse[] = []; + const response: LightWebtoonResponse[] = []; for(const webtoon of webtoons){ const thumbnail: string = this.miscService.bufferToDataURL(this.loadImage(webtoon.thumbnail.sum)); - response.push(new WebtoonResponse(webtoon.id, webtoon.title, webtoon.language, thumbnail, webtoon.author)); + response.push(new LightWebtoonResponse(webtoon.id, webtoon.title, webtoon.language, thumbnail, webtoon.author)); } return response; } - async getEpisodeInfos(webtoonId: number): Promise{ - const dbWebtoon = await this.prismaService.webtoons.findFirst({ + async getWebtoon(webtoonId: number){ + const webtoon: any = await this.prismaService.webtoons.findFirst({ where: { id: webtoonId }, @@ -247,12 +246,36 @@ export class WebtoonDatabaseService{ thumbnail: true, background_banner: true, top_banner: true, - mobile_banner: true, + mobile_banner: true + } + }); + if(!webtoon) + throw new NotFoundException(`Webtoon with id ${webtoonId} not found in database.`); + const thumbnail: string = this.miscService.bufferToDataURL(this.loadImage(webtoon.thumbnail.sum)); + const backgroundBanner: string = this.miscService.bufferToDataURL(this.loadImage(webtoon.background_banner.sum)); + const topBanner: string = this.miscService.bufferToDataURL(this.loadImage(webtoon.top_banner.sum)); + const mobileBanner: string = this.miscService.bufferToDataURL(this.loadImage(webtoon.mobile_banner.sum)); + return new WebtoonResponse( + webtoon.id, + webtoon.title, + webtoon.language, + thumbnail, + webtoon.author, + backgroundBanner, + topBanner, + mobileBanner + ); + } + + async getEpisodes(webtoonId: number): Promise{ + const dbWebtoon: any = await this.prismaService.webtoons.findFirst({ + where: { + id: webtoonId } }); if(!dbWebtoon) throw new NotFoundException(`Webtoon with id ${webtoonId} not found in database.`); - const episodes = await this.prismaService.episodes.findMany({ + const episodes: any[] = await this.prismaService.episodes.findMany({ where: { webtoon_id: webtoonId }, @@ -263,40 +286,36 @@ export class WebtoonDatabaseService{ number: "asc" } }); - const episodeLines: EpisodeLineModel[] = []; - const episodeLinesPromises: Promise[] = []; - for(const episode of episodes) - episodeLinesPromises.push(this.loadEpisodeLine(episode)); - for(const promise of episodeLinesPromises) - episodeLines.push(await promise); - return { - episodes: episodeLines, - backgroundBanner: this.miscService.bufferToDataURL(this.loadImage(dbWebtoon.background_banner.sum)), - topBanner: this.miscService.bufferToDataURL(this.loadImage(dbWebtoon.top_banner.sum)), - mobileBanner: this.miscService.bufferToDataURL(this.loadImage(dbWebtoon.mobile_banner.sum)), - title: dbWebtoon.title, - } as EpisodesResponse; + const response: EpisodeLineModel[] = []; + for(const episode of episodes){ + const thumbnail: string = this.miscService.bufferToDataURL(this.loadImage(episode.thumbnail.sum)); + response.push(new EpisodeLineModel(episode.id, episode.title, episode.number, thumbnail)); + } + return response; } - private async loadEpisodeLine(episode: any): Promise{ - const thumbnailData: Buffer | undefined = this.loadImage(episode.thumbnail.sum); - if(!thumbnailData) - throw new NotFoundException(`Thumbnail not found for episode ${episode.number}`); - const thumbnail: string = this.miscService.bufferToDataURL(thumbnailData); - return new EpisodeLineModel(episode.id, episode.title, episode.number, thumbnail); + async getEpisodeInfos(episodeId: number): Promise{ + const episode: any = await this.prismaService.episodes.findFirst({ + where: { + id: episodeId + } + }); + if(!episode) + throw new NotFoundException(`Episode with id ${episodeId} not found in database.`); + return new EpisodeResponse(episode.title); } - async getEpisodeImages(episodeId: number): Promise{ - const episode = await this.prismaService.episodes.findFirst({ + async getEpisodeImages(episodeId: number): Promise{ + const episode: any = await this.prismaService.episodes.findFirst({ where: { - id: episodeId, + id: episodeId } }); if(!episode) - throw new NotFoundException(`Episode ${episodeId} not found in database.`); - const images = await this.prismaService.episodeImages.findMany({ + throw new NotFoundException(`Episode with id ${episodeId} not found in database.`); + const images: any[] = await this.prismaService.episodeImages.findMany({ where: { - episode_id: episode.id + episode_id: episodeId }, include: { image: true @@ -305,14 +324,10 @@ export class WebtoonDatabaseService{ number: "asc" } }); - const episodeImages: string[] = []; - for(const image of images){ - const imageData: Buffer | undefined = this.loadImage(image.image.sum); - if(!imageData) - throw new NotFoundException(`Image not found for episode ${episodeId}`); - episodeImages.push(this.miscService.bufferToDataURL(imageData)); - } - return new EpisodeResponse(episode.title, episodeImages); + const response: string[] = []; + for(const image of images) + response.push(this.miscService.bufferToDataURL(this.loadImage(image.image.sum))); + return response; } private saveImage(image: Buffer): string{ diff --git a/src/modules/webtoon/webtoon/webtoon.controller.ts b/src/modules/webtoon/webtoon/webtoon.controller.ts index 8d46450..c85f437 100644 --- a/src/modules/webtoon/webtoon/webtoon.controller.ts +++ b/src/modules/webtoon/webtoon/webtoon.controller.ts @@ -3,11 +3,11 @@ import {ApiResponse, ApiTags} from "@nestjs/swagger"; import {WebtoonDatabaseService} from "./webtoon-database.service"; import {WebtoonIdDto} from "./models/dto/webtoon-id.dto"; import {EpisodeIdDto} from "./models/dto/episode-id.dto"; -import EpisodesResponse from "./models/responses/episodes.response"; import EpisodeResponse from "./models/responses/episode.response"; -import WebtoonResponse from "./models/responses/webtoon.response"; +import LightWebtoonResponse from "./models/responses/light-webtoon-response"; import {Throttle} from "@nestjs/throttler"; - +import WebtoonResponse from "./models/responses/webtoon-response"; +import EpisodeLineModel from "./models/models/episode-line.model"; @Controller("webtoons") @ApiTags("Webtoon") @@ -19,20 +19,34 @@ export class WebtoonController{ ){} @Get() - @ApiResponse({status: 200, description: "Returns a list of webtoons", type: WebtoonResponse, isArray: true}) - async getWebtoonList(): Promise{ + @ApiResponse({status: 200, description: "Returns a list of webtoons", type: LightWebtoonResponse, isArray: true}) + async getWebtoonList(): Promise{ return this.webtoonDatabaseService.getWebtoons(); } + @Get(":webtoonId") + @ApiResponse({status: 200, description: "Returns a webtoon", type: WebtoonResponse}) + @ApiResponse({status: 404, description: "Webtoon not found"}) + async getWebtoon(@Param() webtoonIdDto: WebtoonIdDto){ + return this.webtoonDatabaseService.getWebtoon(webtoonIdDto.webtoonId); + } + @Get(":webtoonId/episodes") - @ApiResponse({status: 200, description: "Returns a list of episodes for a webtoon", type: EpisodesResponse}) - async getWebtoonEpisodes(@Param() webtoonIdDto: WebtoonIdDto): Promise{ - return this.webtoonDatabaseService.getEpisodeInfos(webtoonIdDto.webtoonId); + @ApiResponse({status: 200, description: "Returns a list of episodes for a webtoon", type: EpisodeLineModel, isArray: true}) + @ApiResponse({status: 404, description: "Webtoon not found"}) + async getWebtoonEpisodes(@Param() webtoonIdDto: WebtoonIdDto): Promise{ + return this.webtoonDatabaseService.getEpisodes(webtoonIdDto.webtoonId); + } + + @Get("episodes/:episodeId") + @ApiResponse({status: 200, description: "Returns an episode", type: EpisodeResponse}) + async getEpisode(@Param() episodeIdDto: EpisodeIdDto): Promise{ + return this.webtoonDatabaseService.getEpisodeInfos(episodeIdDto.episodeId); } @Get("episodes/:episodeId/images") - @ApiResponse({status: 200, description: "Returns a list of images for an episode", type: EpisodeResponse}) - async getEpisodeImages(@Param() episodeIdDto: EpisodeIdDto): Promise{ + @ApiResponse({status: 200, description: "Returns a list of images for an episode", type: String, isArray: true}) + async getEpisodeImages(@Param() episodeIdDto: EpisodeIdDto): Promise{ return this.webtoonDatabaseService.getEpisodeImages(episodeIdDto.episodeId); } }