library/query/googlebooks.go

159 lines
4.8 KiB
Go

package query
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"git.yetaga.in/alazyreader/library/media"
)
type GoogleBooks struct{}
type googleBookResult struct {
Kind string `json:"kind"`
TotalItems int `json:"totalItems"`
Items []item `json:"items"`
}
type industryIdentifier struct {
Type string `json:"type"`
Identifier string `json:"identifier"`
}
type readingMode struct {
Text bool `json:"text"`
Image bool `json:"image"`
}
type panelizationSummary struct {
ContainsEpubBubbles bool `json:"containsEpubBubbles"`
ContainsImageBubbles bool `json:"containsImageBubbles"`
}
type imageLink struct {
SmallThumbnail string `json:"smallThumbnail"`
Thumbnail string `json:"thumbnail"`
}
type volumeInfo struct {
Title string `json:"title"`
Subtitle string `json:"subtitle"`
Authors []string `json:"authors"`
Publisher string `json:"publisher"`
PublishedDate string `json:"publishedDate"`
Description string `json:"description"`
IndustryIdentifiers []industryIdentifier `json:"industryIdentifiers"`
ReadingModes readingMode `json:"readingModes"`
PageCount int `json:"pageCount"`
PrintType string `json:"printType"`
Categories []string `json:"categories"`
AverageRating float64 `json:"averageRating"`
RatingsCount int `json:"ratingsCount"`
MaturityRating string `json:"maturityRating"`
AllowAnonLogging bool `json:"allowAnonLogging"`
ContentVersion string `json:"contentVersion"`
PanelizationSummary panelizationSummary `json:"panelizationSummary"`
ImageLinks imageLink `json:"imageLinks"`
Language string `json:"language"`
PreviewLink string `json:"previewLink"`
InfoLink string `json:"infoLink"`
CanonicalVolumeLink string `json:"canonicalVolumeLink"`
}
type saleInfo struct {
Country string `json:"country"`
Saleability string `json:"saleability"`
IsEbook bool `json:"isEbook"`
}
type epub struct {
IsAvailable bool `json:"isAvailable"`
}
type pdf struct {
IsAvailable bool `json:"isAvailable"`
}
type accessInfo struct {
Country string `json:"country"`
Viewability string `json:"viewability"`
Embeddable bool `json:"embeddable"`
PublicDomain bool `json:"publicDomain"`
TextToSpeechPermission string `json:"textToSpeechPermission"`
Epub epub `json:"epub"`
Pdf pdf `json:"pdf"`
WebReaderLink string `json:"webReaderLink"`
AccessViewStatus string `json:"accessViewStatus"`
QuoteSharingAllowed bool `json:"quoteSharingAllowed"`
}
type searchInfo struct {
TextSnippet string `json:"textSnippet"`
}
type item struct {
Kind string `json:"kind"`
ID string `json:"id"`
Etag string `json:"etag"`
SelfLink string `json:"selfLink"`
VolumeInfo volumeInfo `json:"volumeInfo"`
SaleInfo saleInfo `json:"saleInfo"`
AccessInfo accessInfo `json:"accessInfo"`
SearchInfo searchInfo `json:"searchInfo"`
}
func (g *GoogleBooks) GetByISBN(isbn string) (*media.Book, error) {
client := &http.Client{}
resp, err := client.Get(fmt.Sprintf("https://www.googleapis.com/books/v1/volumes?q=isbn:%s", isbn))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("received non-200 status code: %d", resp.StatusCode)
}
var result googleBookResult
b, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if err = json.Unmarshal(b, &result); err != nil {
return nil, err
}
if len(result.Items) == 0 {
return nil, fmt.Errorf("no book found")
}
return googleToBook(result.Items[0]), nil
}
func googleToBook(i item) *media.Book {
return &media.Book{
Title: buildTitle(i.VolumeInfo.Title, i.VolumeInfo.Subtitle),
Authors: i.VolumeInfo.Authors,
SortAuthor: strings.ToLower(getLastName(tryGetFirst(i.VolumeInfo.Authors))),
ISBN10: getIdentifierType(i.VolumeInfo.IndustryIdentifiers, "ISBN_10"),
ISBN13: getIdentifierType(i.VolumeInfo.IndustryIdentifiers, "ISBN_13"),
Publisher: i.VolumeInfo.Publisher,
Year: strings.Split(i.VolumeInfo.PublishedDate, "-")[0],
Description: i.VolumeInfo.Description,
Genre: tryGetFirst(i.VolumeInfo.Categories),
}
}
func getIdentifierType(iis []industryIdentifier, typename string) string {
for _, ident := range iis {
if ident.Type == typename {
return ident.Identifier
}
}
return ""
}