-
Notifications
You must be signed in to change notification settings - Fork 7
/
goodreads.ts
70 lines (63 loc) · 1.95 KB
/
goodreads.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import xml from 'fast-xml-parser'
import he from 'he'
import got from 'got'
export default class Goodreads {
private request = got.extend({
prefixUrl: 'https://www.goodreads.com',
searchParams: {
v: 2,
key: process.env.GOODREADS_API_KEY,
},
})
public async getBooks(): Promise<Book[]> {
let reviewList: Goodreads.Review[]
try {
reviewList = await this.getReviewList()
} catch (error) {
throw new Error("Error while fetching review list: " + error)
}
const reviews = await Promise.all(
reviewList.map(({ id }) => this.getReviewShow(id))
)
const books = reviews
.map(({ id, book, date_updated, user_statuses }) => {
const latestStatus = Array.isArray(user_statuses?.user_status)
? user_statuses?.user_status[0]
: user_statuses?.user_status
return {
id: id,
title: he.decode(book.title),
percent: latestStatus?.percent || 0,
date: new Date(latestStatus?.updated_at || date_updated),
}
})
.sort((a, b) => {
if (process.env.BOOKS_SORT_BY === 'percent') {
return b.percent - a.percent
}
return b.date.getTime() - a.date.getTime()
})
return books
}
private async getReviewList(
shelf = 'currently-reading'
): Promise<Goodreads.Review[]> {
const res = await this.request
.get('review/list', {
searchParams: {
id: process.env.GOODREADS_USER_ID,
shelf,
},
})
.text()
const reviewList: Goodreads.ReviewList = xml.parse(res)
const reviews = reviewList.GoodreadsResponse.reviews.review
return reviews
}
private async getReviewShow(id: number): Promise<Goodreads.Review> {
const res = await this.request.get('review/show', { searchParams: { id } }).text()
const reviewShow: Goodreads.ReviewShow = xml.parse(res)
const review = reviewShow.GoodreadsResponse.review
return review
}
}