259 lines
6.7 KiB
TypeScript
259 lines
6.7 KiB
TypeScript
import { InjectQueue } from '@nestjs/bullmq';
|
|
import { Body, Controller, Delete, Get, Post, Put, Request, Res, UseGuards } from '@nestjs/common';
|
|
import { Response } from 'express';
|
|
import { Queue } from 'bullmq';
|
|
import { PinoLogger } from 'nestjs-pino';
|
|
import { BooksService } from 'src/books/books.service';
|
|
import { BookSearchResultDto } from 'src/providers/dto/book-search-result.dto';
|
|
import { SeriesService } from 'src/series/series.service';
|
|
import { QueryFailedError } from 'typeorm';
|
|
import { UpdateBookDto } from 'src/books/dto/update-book.dto';
|
|
import { UpdateBookOriginDto } from 'src/books/dto/update-book-origin.dto';
|
|
import { LibraryService } from './library.service';
|
|
import { CreateSeriesSubscriptionDto } from 'src/series/dto/create-series-subscription.dto';
|
|
import { JwtAccessGuard } from 'src/auth/guards/jwt-access.guard';
|
|
import { SeriesDto } from 'src/series/dto/series.dto';
|
|
import { CreateBookOriginDto } from 'src/books/dto/create-book-origin.dto';
|
|
import { DeleteBookStatusDto } from 'src/books/dto/delete-book-status.dto';
|
|
|
|
@UseGuards(JwtAccessGuard)
|
|
@Controller('library')
|
|
export class LibraryController {
|
|
constructor(
|
|
private readonly books: BooksService,
|
|
private readonly series: SeriesService,
|
|
private readonly library: LibraryService,
|
|
@InjectQueue('library') private readonly jobs: Queue,
|
|
private readonly logger: PinoLogger,
|
|
) { }
|
|
|
|
@Get('series')
|
|
async getSeries(
|
|
@Request() req,
|
|
@Res({ passthrough: true }) response: Response,
|
|
) {
|
|
return {
|
|
success: true,
|
|
data: await this.series.getAllSeries(),
|
|
};
|
|
}
|
|
|
|
@Post('series')
|
|
async createSeries(
|
|
@Request() req,
|
|
@Body() body: CreateSeriesSubscriptionDto,
|
|
@Res({ passthrough: true }) response: Response,
|
|
) {
|
|
try {
|
|
await this.library.addSeries({
|
|
provider: body.provider,
|
|
providerSeriesId: body.providerSeriesId,
|
|
title: body.title,
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
};
|
|
} catch (err) {
|
|
if (err instanceof QueryFailedError) {
|
|
if (err.driverError.code == '23505') {
|
|
// Subscription already exist.
|
|
response.statusCode = 409;
|
|
return {
|
|
success: false,
|
|
error_message: 'Series subscription already exists.',
|
|
};
|
|
}
|
|
}
|
|
|
|
response.statusCode = 500;
|
|
return {
|
|
success: false,
|
|
error_message: 'Something went wrong.',
|
|
};
|
|
}
|
|
}
|
|
|
|
@Get('series/subscriptions')
|
|
async getSeriesSubscriptions(
|
|
@Request() req,
|
|
@Res({ passthrough: true }) response: Response,
|
|
) {
|
|
return {
|
|
success: true,
|
|
data: await this.series.getSeriesSubscribedBy(req.user.userId),
|
|
};
|
|
}
|
|
|
|
@Post('series/subscribe')
|
|
async subscribe(
|
|
@Request() req,
|
|
@Body() body: SeriesDto,
|
|
@Res({ passthrough: true }) response: Response,
|
|
) {
|
|
try {
|
|
await this.library.addSubscription({
|
|
...body,
|
|
userId: req.user.userId,
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
};
|
|
} catch (err) {
|
|
if (err instanceof QueryFailedError) {
|
|
if (err.driverError.code == '23505') {
|
|
// Subscription already exists.
|
|
response.statusCode = 409;
|
|
return {
|
|
success: false,
|
|
error_message: 'Series subscription already exists.',
|
|
};
|
|
} else if (err.driverError.code == '23503') {
|
|
// Series does not exist.
|
|
response.statusCode = 400;
|
|
return {
|
|
success: false,
|
|
error_message: 'Series does not exist.',
|
|
};
|
|
}
|
|
}
|
|
|
|
response.statusCode = 500;
|
|
return {
|
|
success: false,
|
|
error_message: 'Something went wrong.',
|
|
};
|
|
}
|
|
}
|
|
|
|
@Get('books')
|
|
async getBooksFromUser(
|
|
@Request() req,
|
|
) {
|
|
return {
|
|
success: true,
|
|
data: await this.books.findBookStatusesTrackedBy(req.user.userId),
|
|
};
|
|
}
|
|
|
|
@Post('books')
|
|
async createBook(
|
|
@Request() req,
|
|
@Body() body: BookSearchResultDto,
|
|
@Res({ passthrough: true }) response: Response,
|
|
) {
|
|
if (body.provider && body.providerSeriesId) {
|
|
try {
|
|
await this.series.updateSeries({
|
|
provider: body.provider,
|
|
providerSeriesId: body.providerSeriesId,
|
|
title: body.title,
|
|
});
|
|
} catch (err) {
|
|
if (err instanceof QueryFailedError) {
|
|
// Ignore if the series already exist.
|
|
if (err.driverError.code != '23505') {
|
|
response.statusCode = 500;
|
|
return {
|
|
success: false,
|
|
error_message: 'Something went wrong.',
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
return {
|
|
success: true,
|
|
data: await this.books.createBook(body),
|
|
};
|
|
} catch (err) {
|
|
if (err instanceof QueryFailedError) {
|
|
if (err.driverError.code == '23505') {
|
|
// Book exists already.
|
|
response.statusCode = 409;
|
|
return {
|
|
success: false,
|
|
error_message: 'The book has already been added previously.',
|
|
};
|
|
} else if (err.driverError.code == '23503') {
|
|
// Data dependency is missing.
|
|
response.statusCode = 500;
|
|
return {
|
|
success: false,
|
|
error_message: 'Series has not been added.',
|
|
};
|
|
}
|
|
}
|
|
|
|
this.logger.error({
|
|
class: LibraryController.name,
|
|
method: this.createBook.name,
|
|
user: req.user,
|
|
msg: 'Failed to create book.',
|
|
error: err,
|
|
});
|
|
|
|
response.statusCode = 500;
|
|
return {
|
|
success: false,
|
|
error_message: 'Something went wrong while adding the book.',
|
|
};
|
|
}
|
|
}
|
|
|
|
@Put('books')
|
|
async updateBook(
|
|
@Body() body: UpdateBookDto,
|
|
) {
|
|
const data = { ...body };
|
|
delete data['bookId'];
|
|
|
|
const result = await this.books.updateBook(body.bookId, data);
|
|
return {
|
|
success: result?.affected == 1,
|
|
};
|
|
}
|
|
|
|
@Delete('books/origins')
|
|
async deleteBookOrigin(
|
|
@Body() body: CreateBookOriginDto,
|
|
) {
|
|
const data = { ...body };
|
|
delete data['bookOriginId'];
|
|
|
|
const result = await this.books.deleteBookOrigin(body);
|
|
return {
|
|
success: result?.affected == 1,
|
|
};
|
|
}
|
|
|
|
@Delete('books/status')
|
|
async deleteBookStatus(
|
|
@Body() body: DeleteBookStatusDto,
|
|
) {
|
|
const data = { ...body };
|
|
delete data['bookOriginId'];
|
|
|
|
const result = await this.books.deleteBookStatus(body);
|
|
return {
|
|
success: result?.affected == 1,
|
|
};
|
|
}
|
|
|
|
@Put('books/origins')
|
|
async updateBookOrigin(
|
|
@Body() body: UpdateBookOriginDto,
|
|
) {
|
|
const data = { ...body };
|
|
delete data['bookOriginId'];
|
|
|
|
const result = await this.books.updateBookOrigin(body.bookOriginId, data);
|
|
return {
|
|
success: result?.affected == 1,
|
|
};
|
|
}
|
|
}
|