|
| 1 | +import { element } from '../parsers/element' |
| 2 | +import cover from '../utils/cover' |
| 3 | +import fetch from '../utils/fetch' |
| 4 | + |
| 5 | +type SearchBooksProps = { |
| 6 | + q: string |
| 7 | + page?: number |
| 8 | + field?: 'title' | 'author' | 'genre' |
| 9 | +} |
| 10 | + |
| 11 | +type SearchBooksResult = { |
| 12 | + page: number |
| 13 | + totalRecords: number |
| 14 | + books: SearchBookItem[] |
| 15 | +} |
| 16 | + |
| 17 | +type SearchBookItem = { |
| 18 | + id: string |
| 19 | + url: string |
| 20 | + title: string |
| 21 | + author: string |
| 22 | + cover: string |
| 23 | + rating: number |
| 24 | + ratingCount: number |
| 25 | + publicationYear: number |
| 26 | +} |
| 27 | + |
| 28 | +export default async function searchBooks({ |
| 29 | + q, |
| 30 | + page, |
| 31 | + field, |
| 32 | +}: SearchBooksProps): Promise<SearchBooksResult> { |
| 33 | + const document = await fetch(`/search`, { q, page, field }) |
| 34 | + |
| 35 | + const resultInfo = element(document).query('.searchSubNavContainer').text() |
| 36 | + |
| 37 | + const [pageInfo, totalInfo] = resultInfo.split('of about') |
| 38 | + |
| 39 | + const trs = document.querySelectorAll('[itemtype^="http://schema.org/Book"]') |
| 40 | + |
| 41 | + const books = Array.from(trs).map((tr) => { |
| 42 | + const el = element(tr) |
| 43 | + const ratingStr = el |
| 44 | + .query('td:nth-child(2) .minirating') |
| 45 | + .text() |
| 46 | + .split('avg rating — ') |
| 47 | + |
| 48 | + return { |
| 49 | + title: el.query('td:first-of-type a')?.attr('title'), |
| 50 | + author: el.query('.authorName__container').text(), |
| 51 | + rating: ratingStr[0].toFloat(), |
| 52 | + ratingCount: ratingStr[1].toInt(), |
| 53 | + cover: cover(el.query('td:first-of-type img').attr('src')), |
| 54 | + publicationYear: el |
| 55 | + .query('.greyText.smallText.uitext') |
| 56 | + .textContent() |
| 57 | + .between('published', '—') |
| 58 | + .toInt(), |
| 59 | + url: 'https://goodreads.com/' + el.query('.bookTitle').attr('href'), |
| 60 | + id: el |
| 61 | + .query('.bookTitle') |
| 62 | + .attr('href') |
| 63 | + .split('&')[0] |
| 64 | + .replace('/book/show/', ''), |
| 65 | + } |
| 66 | + }) |
| 67 | + |
| 68 | + return { |
| 69 | + page: pageInfo.toInt(), |
| 70 | + totalRecords: totalInfo.split('results')[0].toInt(), |
| 71 | + books, |
| 72 | + } |
| 73 | +} |
0 commit comments