2021-03-31 17:48:47 +02:00
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
2021-05-19 17:43:31 +02:00
func NewAmazonParser ( marketplace string , partnerTag string , accessKey string , secretKey string , searches [ ] string , amazonFulfilled bool , amazonMerchant bool , affiliateLinks bool ) * AmazonParser {
2021-03-31 17:48:47 +02:00
return & AmazonParser {
client : NewAmazonServer ( marketplace ) . CreateClient ( partnerTag , accessKey , secretKey ) ,
searches : searches ,
amazonFulfilled : amazonFulfilled ,
amazonMerchant : amazonMerchant ,
affiliateLinks : affiliateLinks ,
2021-05-19 17:43:31 +02:00
}
2021-03-31 17:48:47 +02:00
}
// 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
2021-04-01 17:50:50 +02:00
func ( p * AmazonParser ) ShopName ( ) ( string , error ) {
return strings . ReplaceAll ( p . client . Marketplace ( ) , "www." , "" ) , nil
2021-03-31 17:48:47 +02:00
}