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 "" }