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

@ -3,6 +3,7 @@ import { BookSearchResultDto } from '../dto/book-search-result.dto';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom, map, timeout } from 'rxjs';
import { AxiosResponse } from 'axios';
import { GoogleSearchContext } from '../contexts/google.search.context';
@Injectable()
export class GoogleService {
@ -11,7 +12,7 @@ export class GoogleService {
) { }
async searchRaw(searchQuery: string): Promise<BookSearchResultDto[]> {
const queryParams = 'printType=books&maxResults=10&fields=items(kind,id,volumeInfo(title,description,authors,publisher,publishedDate,industryIdentifiers,language,categories,maturityRating,imageLinks,canonicalVolumeLink,seriesInfo))&q=';
const queryParams = 'langRestrict=en&printType=books&maxResults=10&fields=items(kind,id,volumeInfo(title,description,authors,publisher,publishedDate,industryIdentifiers,language,categories,maturityRating,imageLinks,canonicalVolumeLink,seriesInfo))&q=';
return await firstValueFrom(
this.http.get('https://www.googleapis.com/books/v1/volumes?' + queryParams + searchQuery)
@ -23,14 +24,19 @@ export class GoogleService {
}
async search(context: GoogleSearchContext): Promise<BookSearchResultDto[]> {
const defaultQueryParams = 'printType=books&fields=items(kind,id,volumeInfo(title,description,authors,publisher,publishedDate,industryIdentifiers,language,categories,maturityRating,imageLinks,canonicalVolumeLink,seriesInfo))';
if (!context) {
return null;
}
const defaultQueryParams = 'langRestrict=en&printType=books&fields=items(kind,id,volumeInfo(title,description,authors,publisher,publishedDate,industryIdentifiers,language,categories,maturityRating,imageLinks,canonicalVolumeLink,seriesInfo))';
const customQueryParams = context.generateQueryParams();
console.log(defaultQueryParams, customQueryParams);
return await firstValueFrom(
this.http.get('https://www.googleapis.com/books/v1/volumes?' + defaultQueryParams + '&' + customQueryParams)
.pipe(
timeout({ first: 5000 }),
map(this.transform),
map(value => this.transform(value)),
)
);
}
@ -40,7 +46,9 @@ export class GoogleService {
return [];
}
return response.data.items.map(item => this.extract(item));
return response.data.items
//.filter(item => item.volumeInfo?.canonicalVolumeLink?.startsWith('https://play.google.com/store/books/details'))
.map(item => this.extract(item));
}
private extract(item: any): BookSearchResultDto {
@ -49,12 +57,12 @@ export class GoogleService {
providerSeriesId: item.volumeInfo.seriesInfo?.volumeSeries[0].seriesId,
title: item.volumeInfo.title,
desc: item.volumeInfo.description,
volume: parseInt(item.volumeInfo.seriesInfo?.bookDisplayNumber),
volume: item.volumeInfo.seriesInfo?.bookDisplayNumber ? parseInt(item.volumeInfo.seriesInfo?.bookDisplayNumber, 10) : undefined,
publisher: item.volumeInfo.publisher,
authors: item.volumeInfo.authors,
categories: item.volumeInfo.categories,
maturityRating: item.volumeInfo.maturityRating,
industryIdentifiers: Object.assign({}, ...item.volumeInfo.industryIdentifiers.map(i => ({ [i.type]: i.identifier }))),
industryIdentifiers: item.volumeInfo.industryIdentifiers ? Object.assign({}, ...item.volumeInfo.industryIdentifiers.map(i => ({ [i.type]: i.identifier }))) : [],
publishedAt: new Date(item.volumeInfo.publishedDate),
language: item.volumeInfo.language,
thumbnail: item.volumeInfo.imageLinks?.thumbnail,
@ -62,15 +70,13 @@ export class GoogleService {
provider: 'google'
}
if (result.providerSeriesId) {
let regex = this.getRegexByPublisher(result.publisher);
let regex = this.getRegexByPublisher(result.publisher);
const match = result.title.match(regex);
if (match?.groups) {
result.title = match.groups['title'].trim();
if (!result.volume) {
result.volume = parseInt(match.groups['volume']);
}
const match = result.title.match(regex);
if (match?.groups) {
result.title = match.groups['title'].trim();
if (!result.volume || isNaN(result.volume)) {
result.volume = parseInt(match.groups['volume'], 10);
}
}