import { BadRequestException , UnprocessableEntityException , ForbiddenException , ConflictException , NotFoundException } from '@nestjs/common' ; import { Repository , EntityRepository } from 'typeorm' ; import { EntriesEntity } from '../Entities/entries.entity' ; import { CreateEntryDto } from 'src/v1/Entry/Dto/create-entry.dto' ; import { Role } from '../Enums/Roles' ; @ EntityRepository ( EntriesEntity ) export class EntriesRepository extends Repository < EntriesEntity > { async getEntry ( entryId ) { try { const entry = await this . findOneOrFail ( entryId ) ; return entry ; } catch ( err ) { throw new NotFoundException ( 'Entry could not found by given id' ) ; } } async getVotedEntriesByUsername ( { username , query } ) { const [ entries , total ] = await this . findAndCount ( { where : { ... query . voteType !== 'down' && { 'votes.up_voted' : { $in : [ username ] } } , ... query . voteType === 'down' && { 'votes.down_voted' : { $in : [ username ] } } , } , order : { created_at : 'DESC' , } , take : 10 , skip : Number ( query . skip ) || 0 , } ) ; return { entries , count : total } ; } async getEntriesByTitleId ( { titleId , query } ) { const [ entries , total ] = await this . findAndCount ( { where : { title_id : titleId } , order : { ... query . sortBy === 'newest' && { created_at : 'DESC' , } , ... query . sortBy === 'top' && { votes : 'DESC' , } } , take : 10 , skip : Number ( query . skip ) || 0 , } ) ; return { entries , count : total } ; } async getEntriesByAuthorOfIt ( { username , query } ) { const [ entries , total ] = await this . findAndCount ( { where : { written_by : username } , order : { created_at : 'DESC' , } , take : 10 , skip : Number ( query . skip ) || 0 , } ) ; return { entries , count : total } ; } async getLatestEntries ( ) { const [ entries , total ] = await this . findAndCount ( { order : { created_at : 'DESC' , } , skip : 0 , take : 250 , } ) ; return { entries , count : total } ; } async getFeaturedEntryByTitleId ( { titleId } ) { try { const entries = await this . findOneOrFail ( { where : { title_id : titleId } , order : { votes : 'DESC' , } } ) ; return entries ; } catch ( err ) { throw new NotFoundException ( 'Entry could not found by given id' ) ; } } async createEntry ( writtenBy , dto ) { const newTitle = new EntriesEntity ( { text : dto . text , title_id : dto . titleId , written_by : writtenBy , } ) ; try { return await this . save ( newTitle ) ; } catch ( err ) { throw new UnprocessableEntityException ( err . errmsg ) ; } } async updateEntry ( username , entryId , text ) { let entry ; try { entry = await this . findOneOrFail ( entryId ) ; } catch { throw new NotFoundException ( 'Entry could not found by given id' ) ; } if ( entry . written_by !== username ) throw new BadRequestException ( 'Only author of the entry can update its entry' ) ; if ( entry . text === text ) throw new BadRequestException ( 'Text must be different than the current entry to update it' ) ; try { entry . text = text ; await this . save ( entry ) ; return entry ; } catch ( err ) { throw new BadRequestException ( err . errmsg ) ; } } async voteEntry ( { entryId , isUpVoted , username } ) { const entry = await this . findOneOrFail ( entryId ) ; if ( isUpVoted ) { if ( entry . votes . up_voted . includes ( username ) ) throw new ConflictException ( 'The entry is already up voted' ) ; if ( entry . votes . down_voted . includes ( username ) ) { entry . votes . value ++ ; entry . votes . down_voted = entry . votes . down_voted . filter ( item => item !== username ) ; } entry . votes . value ++ ; entry . votes . up_voted . push ( username ) ; } else { if ( entry . votes . down_voted . includes ( username ) ) throw new ConflictException ( 'The entry is already down voted' ) ; if ( entry . votes . up_voted . includes ( username ) ) { entry . votes . value -- ; entry . votes . up_voted = entry . votes . up_voted . filter ( item => item !== username ) ; } entry . votes . value -- ; entry . votes . down_voted . push ( username ) ; } this . save ( entry ) ; } async undoVoteOfEntry ( { entryId , isUpVoted , username } ) { const entry = await this . findOneOrFail ( entryId ) ; if ( isUpVoted ) { if ( ! entry . votes . up_voted . includes ( username ) ) throw new BadRequestException ( 'Entry has not up voted yet' ) ; entry . votes . value -- ; entry . votes . up_voted = entry . votes . up_voted . filter ( item => item !== username ) ; } else { if ( ! entry . votes . down_voted . includes ( username ) ) throw new BadRequestException ( 'Entry has not down voted yet' ) ; entry . votes . value ++ ; entry . votes . down_voted = entry . votes . down_voted . filter ( item => item !== username ) ; } this . save ( entry ) ; } async deleteEntry ( username , role , entryId ) { let entry ; try { entry = await this . findOneOrFail ( entryId ) ; } catch ( err ) { throw new NotFoundException ( 'Entry could not found by given id' ) ; } if ( role < Role . Admin && entry . written_by !== username ) { throw new ForbiddenException ( 'Operation not permitted' ) ; } await this . delete ( entry ) ; return entry ; } async deleteEntriesBelongsToTitle ( title_id ) { const entries = await this . find ( { title_id } ) ; await this . remove ( entries ) ; } async deleteEntriesBelongsToUsername ( username ) { const entries = await this . find ( { written_by : username } ) ; await this . remove ( entries ) ; return entries ; } }