Skip to content

Commit bb5bb21

Browse files
committed
Update linting and simplify code
1 parent 3e54d4b commit bb5bb21

File tree

8 files changed

+106
-59
lines changed

8 files changed

+106
-59
lines changed

.golangci.yaml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,32 @@ linters:
88
# Default linters: https://golangci-lint.run/usage/linters#enabled-by-default
99
- gofmt
1010
- goimports
11+
- makezero
12+
- misspell
1113
- revive
1214
- stylecheck
13-
- misspell
1415
- unparam
15-
- makezero
1616

1717
linters-settings:
18+
# https://golangci-lint.run/usage/linters#revive
1819
revive:
19-
# https://golangci-lint.run/usage/linters#revive
20+
enable-all-rules: true
2021
rules:
22+
- name: add-constant
23+
disabled: true
24+
25+
- name: line-length-limit
26+
arguments: [120]
27+
2128
- name: var-naming
2229
arguments:
2330
- ["ID", "JSON", "URL"] # Allow List
2431
- [] # Deny List
2532

33+
# https://golangci-lint.run/usage/linters/#stylecheck
2634
stylecheck:
27-
# https://golangci-lint.run/usage/linters/#stylecheck
28-
checks:
29-
- "*"
30-
- "-ST1003" # Duplicate check of var-naming from revive
35+
checks: ["all", "-ST1003"] # ST1003 is a duplicate check of var-naming from revive
3136

37+
# https://golangci-lint.run/usage/linters/#unparam
3238
unparam:
33-
# https://golangci-lint.run/usage/linters/#unparam
3439
check-exported: true

goodreads/book.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ type Edition struct {
7272
LanguageCode string `xml:"language_code"`
7373
}
7474

75+
// func (e *Edition) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
76+
// type alias Edition
77+
// var unmarshaller alias
78+
// err := d.DecodeElement(&unmarshaller, &start)
79+
// if err != nil {
80+
// return err
81+
// }
82+
// *e = Edition(unmarshaller)
83+
84+
// // Cleanup some fields
85+
// e.Description = html2text.HTML2Text(e.Description)
86+
87+
// return nil
88+
// }
89+
7590
type SeriesBook struct {
7691
Series Series `xml:"series"`
7792
BookPosition *string `xml:"user_position"`

goodreads/book_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ func TestUnmarshalGenres(t *testing.T) {
3434
err := xml.Unmarshal([]byte(xmlString), &genres)
3535
require.NoError(t, err)
3636

37-
expectedGenres := goodreads.Genres{"Fantasy", "Classic", "Fiction", "Adventure", "Young Adult"}
37+
expectedGenres := goodreads.Genres{"Fantasy", "Classic", "Fiction"}
3838
require.Equal(t, expectedGenres, genres)
3939
}

goodreads/client.go

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,19 @@ const (
1717
DefaultAPIKey = "ckvsiSDsuqh7omh74ZZ6Q" // Read only API key kindly provided by LazyLibrarian
1818
)
1919

20-
var DefaultGoodreadsClient = &GoodreadsClient{
20+
var DefaultClient = &Client{
2121
client: http.DefaultClient,
2222
apiRootUrl: DefaultAPIRootUrl,
2323
apiKey: DefaultAPIKey,
2424
}
2525

26-
type GoodreadsClient struct {
26+
type Client struct {
2727
client *http.Client
2828
apiRootUrl string
2929
apiKey string
3030
}
3131

32-
func (c *GoodreadsClient) Get(
32+
func (c *Client) Get(
3333
ctx context.Context,
3434
apiPath string,
3535
queryParams map[string]string,
@@ -82,7 +82,7 @@ func (c *GoodreadsClient) Get(
8282

8383
// GetBookById gets a book by its id.
8484
// https://www.goodreads.com/api/index#book.show
85-
func (c *GoodreadsClient) GetBookById(ctx context.Context, bookId string) (Book, error) {
85+
func (c *Client) GetBookById(ctx context.Context, bookId string) (Book, error) {
8686
queryParams := map[string]string{"id": bookId}
8787

8888
var result struct {
@@ -96,9 +96,36 @@ func (c *GoodreadsClient) GetBookById(ctx context.Context, bookId string) (Book,
9696
return result.Book, nil
9797
}
9898

99+
func (c *Client) GetBooksByIds(ctx context.Context, bookIds []string) ([]Book, error) {
100+
books := make([]Book, len(bookIds))
101+
var errs error
102+
var wg sync.WaitGroup
103+
for idx, bookId := range bookIds {
104+
wg.Add(1)
105+
go func(bookId string, idx int) {
106+
defer wg.Done()
107+
108+
book, err := c.GetBookById(ctx, bookId)
109+
if err != nil {
110+
errs = errors.Join(errs, err)
111+
return
112+
}
113+
books[idx] = book
114+
}(bookId, idx)
115+
}
116+
117+
wg.Wait()
118+
119+
if errs != nil {
120+
return nil, errs
121+
}
122+
123+
return books, nil
124+
}
125+
99126
// GetBookByTitle gets a book by its title and optionally an author (which can give a better match)
100127
// https://www.goodreads.com/api/index#book.title
101-
func (c *GoodreadsClient) GetBookByTitle(ctx context.Context, bookTitle string, bookAuthor *string) (Book, error) {
128+
func (c *Client) GetBookByTitle(ctx context.Context, bookTitle string, bookAuthor *string) (Book, error) {
102129
queryParams := map[string]string{"title": bookTitle}
103130
if bookAuthor != nil && *bookAuthor != "" {
104131
queryParams["author"] = *bookAuthor
@@ -117,40 +144,26 @@ func (c *GoodreadsClient) GetBookByTitle(ctx context.Context, bookTitle string,
117144

118145
// SearchBooks search for a book by its title and optionally an author (which can give better results)
119146
// https://www.goodreads.com/api/index#search.books
120-
func (c *GoodreadsClient) SearchBooks(ctx context.Context, bookTitle string, bookAuthor *string) ([]Book, error) {
147+
func (c *Client) SearchBooks(ctx context.Context, bookTitle string, bookAuthor *string) ([]Book, error) {
121148
query := bookTitle
122149
if bookAuthor != nil && *bookAuthor != "" {
123150
query = fmt.Sprintf("%s %s", query, *bookAuthor)
124151
}
125152
queryParams := map[string]string{"q": query}
126153

127-
var result struct {
154+
// Search for books, getting their ids
155+
var unmarshaller struct {
128156
BookIds []string `xml:"search>results>work>best_book>id"`
129157
}
130-
err := c.Get(ctx, "search/index.xml", queryParams, &result)
158+
err := c.Get(ctx, "search/index.xml", queryParams, &unmarshaller)
131159
if err != nil {
132160
return nil, err
133161
}
134162

135-
books := make([]Book, len(result.BookIds))
136-
var errs error
137-
var wg sync.WaitGroup
138-
for idx, bookId := range result.BookIds {
139-
wg.Add(1)
140-
go func(bookId string, idx int) {
141-
defer wg.Done()
142-
143-
book, err := c.GetBookById(ctx, bookId)
144-
if err != nil {
145-
errs = errors.Join(errs, err)
146-
return
147-
}
148-
books[idx] = book
149-
}(bookId, idx)
150-
}
151-
wg.Wait()
152-
if errs != nil {
153-
return nil, errs
163+
// Get book details using their ids
164+
books, err := c.GetBooksByIds(ctx, unmarshaller.BookIds)
165+
if err != nil {
166+
return nil, err
154167
}
155168

156169
return books, nil

goodreads/error.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func HTTPResponseError(response *http.Response) error {
1515
return fmt.Errorf("got status %s", response.Status)
1616
}
1717

18-
var responseContent interface{}
18+
var responseContent any
1919
err = json.Unmarshal(responseBody, &responseContent)
2020
if err != nil {
2121
responseContent = string(responseBody)

goodreads/genre.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,45 +73,59 @@ var genreShelves = mapset.NewSet(
7373
type Genres []string
7474

7575
func (g *Genres) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
76-
// Shelves is a struct matching the goodread response xml
77-
var shelves struct {
78-
Shelf []struct {
76+
// unmarshaller is a struct matching the goodreads response xml
77+
var unmarshaller struct {
78+
Shelves []struct { // nolint
7979
Name string `xml:"name,attr"`
8080
} `xml:"shelf"`
8181
}
82-
err := d.DecodeElement(&shelves, &start)
82+
err := d.DecodeElement(&unmarshaller, &start)
8383
if err != nil {
8484
return err
8585
}
8686

87-
genres := make(Genres, 0, 3)
88-
seenGenreShelves := mapset.NewSetWithSize[string](3)
89-
for _, shelf := range shelves.Shelf {
90-
// Make shelf name singular for easier comparison
91-
shelfName := inflection.Singular(shelf.Name)
87+
// Get shelf names
88+
shelfNames := make([]string, 0, len(unmarshaller.Shelves))
89+
for _, shelf := range unmarshaller.Shelves {
90+
shelfNames = append(shelfNames, shelf.Name)
91+
}
92+
93+
// Convert shelf names to genres
94+
genres := shelvesToGenres(shelfNames)
95+
96+
// Only use first (up to) three genres
97+
if len(genres) < 3 {
98+
*g = genres
99+
} else {
100+
*g = genres[:3]
101+
}
102+
103+
return nil
104+
}
105+
106+
func shelvesToGenres(shelves []string) []string {
107+
genres := make(Genres, 0, len(shelves))
108+
seenGenreShelves := mapset.NewSetWithSize[string](len(shelves))
109+
for _, shelf := range shelves {
110+
// Make shelf singular for easier comparison
111+
shelf := inflection.Singular(shelf)
92112

93113
// Skip non genre shelves and already seen genre shelves
94-
if !genreShelves.Contains(shelfName) || seenGenreShelves.Contains(shelfName) {
114+
if !genreShelves.Contains(shelf) || seenGenreShelves.Contains(shelf) {
95115
continue
96116
}
97117

98118
// Get genre from shelf name, making it human readable
99-
genre := strings.ReplaceAll(shelfName, "-", " ")
119+
genre := strings.ReplaceAll(shelf, "-", " ")
100120
genreWords := strings.Fields(genre)
101121
for i, word := range genreWords {
102122
genreWords[i] = cases.Title(language.Und).String(word) // Capitalize each word
103123
}
104124
genre = strings.Join(genreWords, " ")
105125

106126
genres = append(genres, genre)
107-
seenGenreShelves.Add(shelfName)
108-
109-
// Only get top 3 genres
110-
if len(genres) == 3 {
111-
break
112-
}
127+
seenGenreShelves.Add(shelf)
113128
}
114-
*g = genres
115129

116-
return nil
130+
return genres
117131
}

goodreads/new.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
// NewClient creates a new goodreads client.
99
// If client is nil, the default http client will be used.
1010
// If api url is nil or uset, the default goodreads api url will be used
11-
func NewClient(client *http.Client, apiURL *string, apiKey *string) *GoodreadsClient {
11+
func NewClient(client *http.Client, apiURL *string, apiKey *string) *Client {
1212
if client == nil {
1313
client = http.DefaultClient
1414
}
@@ -23,7 +23,7 @@ func NewClient(client *http.Client, apiURL *string, apiKey *string) *GoodreadsCl
2323
apiKeyString = strings.TrimSpace(*apiKey)
2424
}
2525

26-
return &GoodreadsClient{
26+
return &Client{
2727
client: client,
2828
apiRootUrl: apiUrlString,
2929
apiKey: apiKeyString,

server/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func NewServer() StrictServerInterface { return &server{} }
1313

1414
func (*server) Search(ctx context.Context, request SearchRequestObject) (SearchResponseObject, error) {
1515
// Search book
16-
goodreadsBooks, err := goodreads.DefaultGoodreadsClient.SearchBooks(ctx, request.Params.Query, request.Params.Author)
16+
goodreadsBooks, err := goodreads.DefaultClient.SearchBooks(ctx, request.Params.Query, request.Params.Author)
1717
if err != nil {
1818
return Search500JSONResponse{Error: utils.ToPointer(err.Error())}, nil
1919
}

0 commit comments

Comments
 (0)