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:
Tom
2025-02-28 00:19:26 +00:00
parent 64ebdfd6f4
commit 969829da20
29 changed files with 1121 additions and 239 deletions

View File

@ -5,13 +5,10 @@ import { In, InsertResult, Repository } from 'typeorm';
import { BookOriginEntity } from './entities/book-origin.entity';
import { BookStatusEntity } from './entities/book-status.entity';
import { UUID } from 'crypto';
import { PinoLogger } from 'nestjs-pino';
import { BookSearchResultDto } from 'src/providers/dto/book-search-result.dto';
import { BookOriginType } from 'src/shared/enums/book_origin_type';
import { CreateBookDto } from './dto/create-book.dto';
import { CreateBookOriginDto } from './dto/create-book-origin.dto';
import { CreateBookStatusDto as BookStatusDto } from './dto/book-status.dto';
import { SeriesService } from 'src/series/series.service';
import { CreateBookStatusDto } from './dto/create-book-status.dto';
import { DeleteBookStatusDto } from './dto/delete-book-status.dto';
@Injectable()
export class BooksService {
@ -22,82 +19,10 @@ export class BooksService {
private bookOriginRepository: Repository<BookOriginEntity>,
@InjectRepository(BookStatusEntity)
private bookStatusRepository: Repository<BookStatusEntity>,
private series: SeriesService,
private logger: PinoLogger,
) { }
async createBook(book: BookSearchResultDto) {
this.logger.debug({
class: BooksService.name,
method: this.createBook.name,
book: book,
msg: 'Saving book to database...',
});
if (book.providerSeriesId) {
await this.series.updateSeries({
providerSeriesId: book.providerSeriesId,
title: book.title,
provider: book.provider,
});
this.logger.debug({
class: BooksService.name,
method: this.createBook.name,
series: book.providerSeriesId,
msg: 'Series saved to database.',
});
}
const createBook: CreateBookDto = {
title: book.title,
desc: book.desc,
providerSeriesId: book.providerSeriesId,
providerBookId: book.providerBookId,
volume: book.volume,
provider: book.provider,
publishedAt: book.publishedAt,
};
const data = await this.createBookInternal(createBook);
const bookId = data.identifiers[0]['bookId'];
const tasks = [];
tasks.push(book.authors.map(author => this.addBookOrigin(bookId, BookOriginType.AUTHOR, author)));
tasks.push(book.categories.map(category => this.addBookOrigin(bookId, BookOriginType.CATEGORY, category)));
tasks.push(this.addBookOrigin(bookId, BookOriginType.LANGUAGE, book.language));
if (book.maturityRating) {
tasks.push(this.addBookOrigin(bookId, BookOriginType.MATURITY_RATING, book.maturityRating));
}
if (book.thumbnail) {
tasks.push(this.addBookOrigin(bookId, BookOriginType.PROVIDER_THUMBNAIL, book.thumbnail));
}
if (book.url) {
tasks.push(this.addBookOrigin(bookId, BookOriginType.PROVIDER_URL, book.url));
}
if ('ISBN_10' in book.industryIdentifiers) {
tasks.push(this.addBookOrigin(bookId, BookOriginType.ISBN_10, book.industryIdentifiers['ISBN_10']));
}
if ('ISBN_13' in book.industryIdentifiers) {
tasks.push(this.addBookOrigin(bookId, BookOriginType.ISBN_10, book.industryIdentifiers['ISBN_13']));
}
await Promise.all(tasks);
this.logger.info({
class: BooksService.name,
method: this.createBook.name,
book: book,
msg: 'Book saved to database.',
});
return bookId;
}
private async createBookInternal(book: CreateBookDto): Promise<InsertResult> {
async createBook(book: CreateBookDto): Promise<InsertResult> {
const entity = this.bookRepository.create(book);
return await this.bookRepository.createQueryBuilder()
.insert()
@ -107,12 +32,26 @@ export class BooksService {
.execute();
}
async addBookOrigin(bookId: UUID, type: BookOriginType, value: string): Promise<InsertResult> {
return await this.bookOriginRepository.insert({
bookId,
type,
value,
});
async addBookOrigin(origin: CreateBookOriginDto): Promise<InsertResult> {
return await this.bookOriginRepository.insert(origin);
}
async deleteBookOrigin(origin: CreateBookOriginDto) {
return await this.bookOriginRepository.createQueryBuilder()
.delete()
.where({
whereFactory: origin,
})
.execute();
}
async deleteBookStatus(status: DeleteBookStatusDto) {
return await this.bookStatusRepository.createQueryBuilder()
.delete()
.where({
whereFactory: status,
})
.execute();
}
async findBooksByIds(bookIds: UUID[]) {
@ -120,7 +59,7 @@ export class BooksService {
where: {
bookId: In(bookIds)
}
})
});
}
async findBookStatusesTrackedBy(userId: UUID): Promise<BookStatusEntity[]> {
@ -157,13 +96,12 @@ export class BooksService {
}, update);
}
async updateBookStatus(status: BookStatusDto) {
async updateBookStatus(status: CreateBookStatusDto) {
status.modifiedAt = new Date();
await this.bookStatusRepository.createQueryBuilder()
.insert()
.values(status)
.orUpdate(['user_id', 'book_id'], ['state', 'modified_at'], { skipUpdateIfNoValuesChanged: true })
.execute();
return await this.bookStatusRepository.upsert(status, ['book_id']);
}
}