Skip to content

Commit

Permalink
feat(api-clients): Create api client for pinball map API to fetch loc…
Browse files Browse the repository at this point in the history
…ations
  • Loading branch information
alexstojda committed Jul 26, 2023
1 parent 41bb0bc commit 49c14d7
Show file tree
Hide file tree
Showing 11 changed files with 474 additions and 6 deletions.
9 changes: 9 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
inpackage: true
keeptree: true
dir: "{{.InterfaceDir}}"
with-expecter: false
packages:
pinman/internal/utils:
interfaces:
# select the interfaces you want mocked
HttpDoer: {}
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ COPY --chown=golang:root go.mod go.sum Makefile ./

RUN make mod

COPY --chown=golang:root cmd ./cmd
COPY --chown=golang:root main.go ./
COPY --chown=golang:root internal ./internal
COPY --from=go-gen /out/ internal/app/generated/
RUN go build -v -o pinman ./cmd/pinman/
RUN go build -v -o pinman main.go

ENTRYPOINT ["make"]
CMD ["test"]
Expand Down
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ build: build-backend build-frontend

build-backend:
@mkdir -p ./build
@go build -v -o ./build/pinman ./cmd/pinman/
@go build -v -o ./build/pinman main.go

build-frontend:
@cd $(FRONTEND_DIR) && yarn build

run: clean generate build-frontend
@SPA_PATH=./web/app/build go run cmd/pinman/main.go
@SPA_PATH=./web/app/build go run main.go

run-backend:
@go run cmd/pinman/main.go
@go run main.go

run-database:
@docker compose up -d postgres
Expand All @@ -57,6 +57,8 @@ test: test-backend test-frontend

test-setup:
@go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo
@go install -mod=mod github.com/vektra/mockery/[email protected]
@mockery

test-frontend:
@cd $(FRONTEND_DIR) && yarn test
Expand Down
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ require (
github.com/onsi/gomega v1.24.2
github.com/rs/zerolog v1.20.0
github.com/spf13/viper v1.14.0
github.com/stretchr/testify v1.8.3
golang.org/x/crypto v0.9.0
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
gorm.io/driver/postgres v1.4.5
gorm.io/gorm v1.24.1
)
Expand Down Expand Up @@ -54,6 +56,7 @@ require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
Expand All @@ -68,6 +71,8 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
Expand Down
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
Expand Down Expand Up @@ -180,6 +182,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
Expand Down Expand Up @@ -349,6 +353,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand Down Expand Up @@ -436,6 +441,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down Expand Up @@ -645,6 +652,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.9.2 h1:UXbndbirwCAx6TULftIfie/ygDNCwxEie+IiNP1IcNc=
golang.org/x/tools v0.9.2/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
142 changes: 142 additions & 0 deletions internal/clients/pinballmap/pinballmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package pinballmap

import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"pinman/internal/utils"
)

type Client struct {
apiHost string
apiScheme string
client utils.HttpDoer
}

type ClientInterface interface {
GetLocations(nameFilter string) ([]Location, error)
GetLocation(id int) (*Location, error)
}

func NewClient() *Client {
return &Client{
apiScheme: "https",
apiHost: "pinballmap.com",
client: http.DefaultClient,
}
}

func NewClientWithHttpClient(client utils.HttpDoer) *Client {
return &Client{
apiScheme: "https",
apiHost: "pinballmap.com",
client: client,
}
}

func (c *Client) NewUrl(path string, params url.Values) *url.URL {
urrl := &url.URL{
Scheme: c.apiScheme,
Host: c.apiHost,
Path: path,
}

if params != nil {
urrl.RawQuery = params.Encode()
}

return urrl
}

type Location struct {
ID int `json:"id"`
Name string `json:"name"`
Street string `json:"street"`
City string `json:"city"`
State string `json:"state"`
Country string `json:"country"`
NumMachines int `json:"num_machines"`
}

type LocationResponse struct {
Locations []Location `json:"locations"`
}

type ErrorResponse struct {
Errors string `json:"errors"`
}

// GetLocations retrieves all locations from the Pinball Map API matching the given name filter.
// https://pinballmap.com/api/v1/docs/1.0/locations/index.html
func (c *Client) GetLocations(nameFilter string) ([]Location, error) {
params := url.Values{}
params.Add("by_location_name", nameFilter)
params.Add("no_details", "true")

req, err := http.NewRequest("GET", c.NewUrl("/api/v1/locations.json", params).String(), nil)
if err != nil {
return nil, err
}

req.Header.Set("Accept", "application/json")

resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("doing request: %w", err)
}

if resp.StatusCode != http.StatusOK {
errResp := ErrorResponse{}
err := json.NewDecoder(resp.Body).Decode(&errResp)
if err != nil {
return nil, fmt.Errorf("decoding error response: %w", err)
}

return nil, fmt.Errorf("unexpected response: %s", errResp.Errors)
}

//goland:noinspection GoUnhandledErrorResult
defer resp.Body.Close()

var locations LocationResponse
if err := json.NewDecoder(resp.Body).Decode(&locations); err != nil {
return nil, fmt.Errorf("retrieving locations: %w", err)
}

return locations.Locations, nil
}

func (c *Client) GetLocation(id int) (*Location, error) {
req, err := http.NewRequest("GET", c.NewUrl(fmt.Sprintf("/api/v1/locations/%d.json", id), nil).String(), nil)
if err != nil {
return nil, fmt.Errorf("creating request: %w", err)
}

req.Header.Set("Accept", "application/json")

resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("doing request: %w", err)
}

if resp.StatusCode != http.StatusOK {
errResp := ErrorResponse{}
err := json.NewDecoder(resp.Body).Decode(&errResp)
if err != nil {
return nil, fmt.Errorf("decoding error response: %w", err)
}

return nil, fmt.Errorf("unexpected response: %s", errResp.Errors)
}

//goland:noinspection GoUnhandledErrorResult
defer resp.Body.Close()

var location Location
if err := json.NewDecoder(resp.Body).Decode(&location); err != nil {
return nil, fmt.Errorf("decoding response: %w", err)
}

return &location, nil
}
Loading

0 comments on commit 49c14d7

Please sign in to comment.