From 9220b50e22352bda6fa8a55806891eae6226775f Mon Sep 17 00:00:00 2001 From: Felipe M Date: Sat, 2 Jul 2022 16:27:52 +0200 Subject: [PATCH] feat: added gtm-store.com support --- cmd/server/main.go | 2 + pkg/models/product.go | 1 + pkg/shop/gtmstore/gtmstore.go | 71 +++++++++++++++++++++++++++++++++++ pkg/utils/price.go | 9 +++++ 4 files changed, 83 insertions(+) create mode 100644 pkg/shop/gtmstore/gtmstore.go diff --git a/cmd/server/main.go b/cmd/server/main.go index 839ee09..06c0fa9 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -9,6 +9,7 @@ import ( "github.com/fmartingr/bazaar/pkg/manager" "github.com/fmartingr/bazaar/pkg/shop/akiracomics" "github.com/fmartingr/bazaar/pkg/shop/amazon" + "github.com/fmartingr/bazaar/pkg/shop/gtmstore" "github.com/fmartingr/bazaar/pkg/shop/heroesdepapel" "github.com/fmartingr/bazaar/pkg/shop/steam" ) @@ -19,6 +20,7 @@ func main() { m.Register(steam.Domains, steam.NewSteamShopFactory()) m.Register(heroesdepapel.Domains, heroesdepapel.NewHeroesDePapelShopFactory()) m.Register(amazon.Domains, amazon.NewAmazonShopFactory()) + m.Register(gtmstore.Domains, gtmstore.NewGTMStoreShopFactory()) http.HandleFunc("/item", func(rw http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { diff --git a/pkg/models/product.go b/pkg/models/product.go index a186958..61e049c 100644 --- a/pkg/models/product.go +++ b/pkg/models/product.go @@ -4,6 +4,7 @@ import "time" type Product struct { Name string `json:"name"` + Description string `json:"description"` URL string `json:"url"` ImageURL string `json:"image_url"` InStock bool `json:"in_stock"` diff --git a/pkg/shop/gtmstore/gtmstore.go b/pkg/shop/gtmstore/gtmstore.go new file mode 100644 index 0000000..48f0c5c --- /dev/null +++ b/pkg/shop/gtmstore/gtmstore.go @@ -0,0 +1,71 @@ +package gtmstore + +import ( + "fmt" + "log" + "net/http" + "strconv" + "strings" + + "github.com/PuerkitoBio/goquery" + "github.com/fmartingr/bazaar/pkg/models" + "github.com/fmartingr/bazaar/pkg/utils" +) + +var Domains = []string{"www.gtm-store.com"} + +type GTMStoreShop struct { + domains []string +} + +func (s *GTMStoreShop) Get(url string) (*models.Product, error) { + res, err := http.Get(url) + if err != nil { + return nil, fmt.Errorf("error retrieving url: %s", err) + } + defer res.Body.Close() + if res.StatusCode != 200 { + return nil, fmt.Errorf("error retrieving url: %d %s", res.StatusCode, res.Status) + } + + doc, err := goquery.NewDocumentFromReader(res.Body) + if err != nil { + return nil, fmt.Errorf("error parsing body: %s", err) + } + + product := models.Product{ + URL: url, + } + + doc.Find(`div.primary_block`).Each(func(i int, s *goquery.Selection) { + priceText := utils.StripLastCharacter(s.Find(".woocommerce-Price-amount.amount").Text()) + priceNum, _ := strconv.ParseFloat(strings.ReplaceAll(priceText, ",", "."), 64) + + var imageURLs []string + s.Find(".woocommerce-product-gallery__wrapper div").Each(func(i int, s *goquery.Selection) { + imageURL, exists := s.Find("a").Attr("href") + if exists { + log.Println(imageURL) + imageURLs = append(imageURLs, imageURL) + } + }) + + product.Name = s.Find(".product_title.entry-title").Text() + product.InStock = s.Find("p.stock").HasClass("in-stock") + product.ImageURL = imageURLs[0] + product.PriceText = priceText + product.Description = s.Find(".woocommerce-product-details__short-description").Text() + product.Price = priceNum + }) + + return &product, nil +} + +func NewGTMStoreShopFactory() models.ShopFactory { + return func() models.Shop { + shop := GTMStoreShop{ + domains: Domains, + } + return &shop + } +} diff --git a/pkg/utils/price.go b/pkg/utils/price.go index f561341..f2b2bb7 100644 --- a/pkg/utils/price.go +++ b/pkg/utils/price.go @@ -3,9 +3,18 @@ package utils import ( "regexp" "strings" + "unicode/utf8" ) func ExtractPrice(raw string) string { re := regexp.MustCompile("[^0-9,.]+") return strings.Replace(re.ReplaceAllString(raw, ""), ",", ".", 1) } + +func StripLastCharacter(s string) string { + r, size := utf8.DecodeLastRuneInString(s) + if r == utf8.RuneError && (size == 0 || size == 1) { + size = 0 + } + return s[:len(s)-size] +}