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:
93
backend/nestjs-seshat-api/src/library/library.consumer.ts
Normal file
93
backend/nestjs-seshat-api/src/library/library.consumer.ts
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
import { Processor, WorkerHost } from '@nestjs/bullmq';
|
||||
import { Job } from 'bullmq';
|
||||
import { PinoLogger } from 'nestjs-pino';
|
||||
import { GoogleSearchContext } from 'src/providers/contexts/google.search.context';
|
||||
import { BookSearchResultDto } from 'src/providers/dto/book-search-result.dto';
|
||||
import { ProvidersService } from 'src/providers/providers.service';
|
||||
import { CreateSeriesSubscriptionJobDto } from 'src/series/dto/create-series-subscription-job.dto';
|
||||
import { LibraryService } from './library.service';
|
||||
|
||||
@Processor('library')
|
||||
export class LibraryConsumer extends WorkerHost {
|
||||
constructor(
|
||||
private readonly library: LibraryService,
|
||||
private readonly provider: ProvidersService,
|
||||
private readonly logger: PinoLogger,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async process(job: Job, token?: string): Promise<any> {
|
||||
console.log('job started:', job.name, job.data, job.id);
|
||||
const series: CreateSeriesSubscriptionJobDto = job.data;
|
||||
|
||||
let context = this.provider.generateSearchContext(series.provider, series.title) as GoogleSearchContext;
|
||||
//context.intitle = series.title;
|
||||
context.maxResults = '40';
|
||||
context.subject = 'Fiction';
|
||||
|
||||
// Search for the book(s) via the provider.
|
||||
// Up until end of results or after 3 unhelpful pages of results.
|
||||
let results = [];
|
||||
let related = [];
|
||||
let pageSearchedCount = 0;
|
||||
let unhelpfulResultsCount = 0;
|
||||
do {
|
||||
pageSearchedCount += 1;
|
||||
results = await this.provider.search(context);
|
||||
const potential = results.filter(r => r.providerSeriesId == series.providerSeriesId || r.title == series.title);
|
||||
if (potential.length > 0) {
|
||||
related.push.apply(related, potential);
|
||||
} else {
|
||||
unhelpfulResultsCount += 1;
|
||||
}
|
||||
context = context.next();
|
||||
job.updateProgress(pageSearchedCount * 5);
|
||||
} while (results.length >= 40 && unhelpfulResultsCount < 3);
|
||||
|
||||
// Sort & de-duplicate the entries received.
|
||||
const books = related.map(book => this.toScore(book, series))
|
||||
.sort((a, b) => a.result.volume - b.result.volume || b.score - a.score)
|
||||
.filter((_, index, arr) => index == 0 || arr[index - 1].result.volume != arr[index].result.volume);
|
||||
job.updateProgress(25);
|
||||
|
||||
let counter = 0;
|
||||
for (let book of books) {
|
||||
try {
|
||||
book.result.providerSeriesId = series.providerSeriesId;
|
||||
await this.library.addBook(book.result);
|
||||
} catch (err) {
|
||||
this.logger.error({
|
||||
class: LibraryConsumer.name,
|
||||
method: this.process.name,
|
||||
book: book.result,
|
||||
score: book.score,
|
||||
msg: 'Failed to add book in background.',
|
||||
error: err,
|
||||
});
|
||||
} finally {
|
||||
counter++;
|
||||
job.updateProgress(25 + 75 * counter / books.length);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('job completed:', job.name, job.data, job.id);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private toScore(book: BookSearchResultDto, series: CreateSeriesSubscriptionJobDto): ({ result: BookSearchResultDto, score: number }) {
|
||||
if (!book) {
|
||||
return {
|
||||
result: null,
|
||||
score: -1,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
result: book,
|
||||
score: (!!book.providerSeriesId ? 50 : 0) + (book.title == series.title ? 25 : 0) + (book.url.startsWith('https://play.google.com/store/books/details?') ? 10 : 0),
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user