This repository has been archived by the owner on Nov 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser_amazon.go
133 lines (110 loc) · 3.89 KB
/
parser_amazon.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"fmt"
"regexp"
"strings"
log "github.com/sirupsen/logrus"
paapi5 "github.com/spiegel-im-spiegel/pa-api"
"github.com/spiegel-im-spiegel/pa-api/entity"
"github.com/spiegel-im-spiegel/pa-api/query"
)
// NewAmazonServer creates an Amazon Server function based on the Marketplace.
// The paapi5 marketplaceEnum is not exported, so this type cannot be used in simple map.
func NewAmazonServer(marketplace string) *paapi5.Server {
switch marketplace {
case "www.amazon.fr":
return paapi5.New(paapi5.WithMarketplace(paapi5.LocaleFrance))
case "www.amazon.com":
return paapi5.New(paapi5.WithMarketplace(paapi5.LocaleUnitedStates))
default:
return paapi5.New() // default Marketplace
}
}
// Map of messages to detect availability
var availabilityMessages = []string{"En stock."}
// AmazonParser structure to handle Amazon parsing logic
type AmazonParser struct {
client paapi5.Client
searches []string
includeRegex *regexp.Regexp
excludeRegex *regexp.Regexp
amazonFulfilled bool
amazonMerchant bool
affiliateLinks bool
}
// NewAmazonParser to create a new AmazonParser instance
func NewAmazonParser(marketplace string, partnerTag string, accessKey string, secretKey string, searches []string, amazonFulfilled bool, amazonMerchant bool, affiliateLinks bool) *AmazonParser {
return &AmazonParser{
client: NewAmazonServer(marketplace).CreateClient(partnerTag, accessKey, secretKey),
searches: searches,
amazonFulfilled: amazonFulfilled,
amazonMerchant: amazonMerchant,
affiliateLinks: affiliateLinks,
}
}
// Parse Amazon API to return list of products
// Implements Parser interface
func (p *AmazonParser) Parse() ([]*Product, error) {
var products []*Product
for _, search := range p.searches {
log.Debugf("searching for '%s' on %s", search, p.client.Marketplace())
// create search request on API
q := query.NewSearchItems(
p.client.Marketplace(),
p.client.PartnerTag(),
p.client.PartnerType(),
).Search(query.Keywords, search).EnableItemInfo().EnableOffers()
body, err := p.client.Request(q)
if err != nil {
return nil, err
}
// decode response
res, err := entity.DecodeResponse(body)
if err != nil {
return nil, err
}
// decode products
for _, item := range res.SearchResult.Items {
product := &Product{}
if !p.affiliateLinks {
product.URL = fmt.Sprintf("https://%s/dp/%s", p.client.Marketplace(), item.ASIN)
} else {
product.URL = item.DetailPageURL // includes partner tag
}
product.Name = item.ItemInfo.Title.DisplayValue
if item.Offers != nil && *item.Offers.Listings != nil {
for _, offer := range *item.Offers.Listings {
// detect if product is packaged by Amazon
if p.amazonFulfilled && !offer.DeliveryInfo.IsAmazonFulfilled {
log.Debugf("excluding offer by '%s' for product '%s' because not fulfilled by Amazon", offer.MerchantInfo.Name, product.Name)
continue
}
// detect if product is sold by Amazon
if p.amazonMerchant && !strings.HasPrefix(offer.MerchantInfo.Name, "Amazon") {
log.Debugf("excluding offer by '%s' for product '%s' because not sold by Amazon", offer.MerchantInfo.Name, product.Name)
continue
}
// detect price
product.Price = offer.Price.Amount
product.PriceCurrency = offer.Price.Currency
// detect availability
if ContainsString(availabilityMessages, offer.Availability.Message) {
product.Available = true
break
}
}
}
products = append(products, product)
}
}
return products, nil
}
// String to print AmazonParser
// Implements the Parser interface
func (p *AmazonParser) String() string {
return fmt.Sprintf("AmazonParser<%s@%s>", p.client.PartnerTag(), p.client.Marketplace())
}
// ShopName returns shop name from Amazon Marketplace
func (p *AmazonParser) ShopName() (string, error) {
return strings.ReplaceAll(p.client.Marketplace(), "www.", ""), nil
}