Create Library module. Moved book controller to library controller. Added series addition to library while adding all known volumes in background. Fixed Google search context.
This commit is contained in:
258
backend/nestjs-seshat-api/src/library/library.controller.ts
Normal file
258
backend/nestjs-seshat-api/src/library/library.controller.ts
Normal file
@ -0,0 +1,258 @@
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user