From 05d078e7e97bb1cc2480c0eed9ea1dea3bad2d7f Mon Sep 17 00:00:00 2001 From: Aaron Bieber Date: Sat, 1 Feb 2020 20:45:42 -0700 Subject: [PATCH] working beer plugin, also run tests in plugins dir --- .builds/openbsd.yml | 2 +- plugins/beer.go | 113 ++++++++++++++++++++++++++++++++++--------- plugins/beer_test.go | 19 ++++++++ 3 files changed, 110 insertions(+), 24 deletions(-) create mode 100644 plugins/beer_test.go diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml index d8df91b..d45b658 100644 --- a/.builds/openbsd.yml +++ b/.builds/openbsd.yml @@ -8,4 +8,4 @@ sources: tasks: - test_mcchunkie: | cd mcchunkie - go test + go test ./... diff --git a/plugins/beer.go b/plugins/beer.go index 83c9f0d..e73c5ad 100644 --- a/plugins/beer.go +++ b/plugins/beer.go @@ -5,9 +5,11 @@ import ( "fmt" "io/ioutil" "log" + "math/rand" "net/http" "net/url" "regexp" + "time" "github.com/matrix-org/gomatrix" ) @@ -16,27 +18,61 @@ import ( type Beer struct { } -// BeerRecord is the parent beer type -type BeerRecord struct { - DatasetID string `json:"datasetid"` - RecordID string `json:"recordid"` - Fields BeerFields `json:"fields"` +// BeerResp represents our response from the api +type BeerResp struct { + Nhits int `json:"nhits"` + Parameters Parameters `json:"parameters"` + Records []Records `json:"records"` } -// BeerFields ar the fields we care about for any given beer -type BeerFields struct { - Website string `json:"website"` - City string `json:"city"` - Name string `json:"name"` - Country string `json:"country"` - Descr string `json:"descript"` - Style string `json:"style_name"` - IBU int `json:"ibu"` - BreweryName string `json:"name_breweries"` +// Parameters are the meta information +type Parameters struct { + Dataset []string `json:"dataset"` + Timezone string `json:"timezone"` + Q string `json:"q"` + Rows int `json:"rows"` + Format string `json:"format"` } -// BeerRecords are a collection of responses -type BeerRecords []BeerRecord +// Fields are the bits of info we care about +type Fields struct { + Website string `json:"website"` + City string `json:"city"` + StyleID string `json:"style_id"` + Name string `json:"name"` + Country string `json:"country"` + CatID string `json:"cat_id"` + BreweryID string `json:"brewery_id"` + Descript string `json:"descript"` + Upc int `json:"upc"` + Coordinates []float64 `json:"coordinates"` + Ibu int `json:"ibu"` + CatName string `json:"cat_name"` + LastMod time.Time `json:"last_mod"` + State string `json:"state"` + StyleName string `json:"style_name"` + Abv float64 `json:"abv"` + Address1 string `json:"address1"` + NameBreweries string `json:"name_breweries"` + Srm int `json:"srm"` + ID string `json:"id"` + AddUser string `json:"add_user"` +} + +// Geometry is basically useless +type Geometry struct { + Type string `json:"type"` + Coordinates []float64 `json:"coordinates"` +} + +// Records holds our fileds +type Records struct { + Datasetid string `json:"datasetid"` + Recordid string `json:"recordid"` + Fields Fields `json:"fields"` + Geometry Geometry `json:"geometry"` + RecordTimestamp time.Time `json:"record_timestamp"` +} func (h *Beer) fix(msg string) string { re := regexp.MustCompile(`(?i)^beer: `) @@ -48,10 +84,9 @@ func (h *Beer) match(msg string) bool { return re.MatchString(msg) } -func (h *Beer) get(beer string) (*BeerRecords, error) { +func (h *Beer) get(beer string) (*BeerResp, error) { u := "https://data.opendatasoft.com/api/records/1.0/search?dataset=open-beer-database%40public-us&q=" u = fmt.Sprintf("%s%s", u, url.PathEscape(beer)) - log.Println(u) resp, err := http.Get(u) if err != nil { return nil, err @@ -64,12 +99,36 @@ func (h *Beer) get(beer string) (*BeerRecords, error) { return nil, err } - beers := &BeerRecords{} - _ = json.Unmarshal([]byte(body), beers) + var beers = &BeerResp{} + err = json.Unmarshal([]byte(body), beers) + if err != nil { + return nil, err + } return beers, nil } +func (h *Beer) pretty(b BeerResp, random bool) string { + idx := 0 + + if random { + rand.Seed(time.Now().Unix()) + idx = rand.Intn(len(b.Records)) + } + + return fmt.Sprintf("%s (%s) by %s from %s, %s - IBU: %d, ABV: %.1f %s\n%s", + b.Records[idx].Fields.Name, + b.Records[idx].Fields.StyleName, + b.Records[idx].Fields.NameBreweries, + b.Records[idx].Fields.City, + b.Records[idx].Fields.State, + b.Records[idx].Fields.Ibu, + b.Records[idx].Fields.Abv, + b.Records[idx].Fields.Website, + b.Records[idx].Fields.Descript, + ) +} + // Respond to hi events func (h *Beer) Respond(c *gomatrix.Client, ev *gomatrix.Event, user string) { if mtype, ok := ev.MessageType(); ok { @@ -80,11 +139,19 @@ func (h *Beer) Respond(c *gomatrix.Client, ev *gomatrix.Event, user string) { beer := h.fix(post) if beer != "" { log.Printf("%s: responding to '%s'", h.Name(), ev.Sender) - j, err := h.get(beer) + brr, err := h.get(beer) if err != nil { SendMessage(c, ev.RoomID, fmt.Sprintf("sorry %s, I can't look for beer. (%s)", ev.Sender, err)) } - SendMessage(c, ev.RoomID, fmt.Sprintf("%v", j)) + + switch { + case brr.Nhits == 0: + SendMessage(c, ev.RoomID, "¯\\_(ツ)_/¯") + case brr.Nhits == 1: + SendMessage(c, ev.RoomID, fmt.Sprintf("%s", h.pretty(*brr, false))) + case brr.Nhits > 1: + SendMessage(c, ev.RoomID, fmt.Sprintf("Found %d beers, here is a random one:\n%s", brr.Nhits, h.pretty(*brr, true))) + } } } } diff --git a/plugins/beer_test.go b/plugins/beer_test.go new file mode 100644 index 0000000..30a6c67 --- /dev/null +++ b/plugins/beer_test.go @@ -0,0 +1,19 @@ +package plugins + +import ( + "fmt" + "testing" +) + +func TestBeer(t *testing.T) { + beer := &Beer{} + b, err := beer.get("oskar blues") + if err != nil { + t.Errorf("%+v\n", err) + } + + if b.Nhits == 0 { + t.Errorf("Expected 7 results; got %d\n", b.Nhits) + } + fmt.Printf("%+v", b) +}