Add eBay Browse API integration with daily call quota
eBay marketplaces are now polled through eBay's official Buy > Browse API (client-credentials OAuth2) instead of an Apify scraper actor; Apify still handles Yahoo JP and Mercari. Browse API calls are tracked per day in a new ebay_api_usage table and capped (default 5000, configurable) on eBay's Pacific-time reset clock, so polling halts before the limit is hit. Credentials live in config.toml [ebay] and are overridable via /settings, which also surfaces the day's running call count. Also carries the server.secure_cookies config plumbing (field, accessor, example) consumed by the following commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
94
internal/ebay/types.go
Normal file
94
internal/ebay/types.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package ebay
|
||||
|
||||
import "strings"
|
||||
|
||||
// SearchParams is the input to a single Browse API item_summary/search call.
|
||||
// It is provider-specific and is carried as the opaque input payload of a
|
||||
// scheduler plan, mirroring how Apify actor inputs are carried.
|
||||
type SearchParams struct {
|
||||
// MarketplaceID is an eBay marketplace identifier such as EBAY_US.
|
||||
MarketplaceID string
|
||||
// Query is the keyword search string. Required; the Browse API rejects
|
||||
// an empty q.
|
||||
Query string
|
||||
// ListingType is Veola's vocabulary ("all", "bin"/"buy_it_now",
|
||||
// "auction"); it is mapped to a buyingOptions filter.
|
||||
ListingType string
|
||||
// Limit caps the number of results requested (Browse API max is 200).
|
||||
Limit int
|
||||
}
|
||||
|
||||
// Listing is one normalized active eBay listing. The scheduler converts these
|
||||
// into the shared apify.UnifiedResult shape so the rest of the pipeline
|
||||
// (dedup, filter, alert) is provider-agnostic.
|
||||
type Listing struct {
|
||||
Title string
|
||||
Price float64
|
||||
Currency string
|
||||
URL string
|
||||
Store string
|
||||
ImageURL string
|
||||
}
|
||||
|
||||
// MarketplaceID maps a Veola marketplace string (e.g. "ebay.com",
|
||||
// "ebay.co.uk") to an eBay Browse API marketplace identifier. Unknown or
|
||||
// bare "ebay" values fall back to EBAY_US.
|
||||
func MarketplaceID(marketplace string) string {
|
||||
m := strings.ToLower(strings.TrimSpace(marketplace))
|
||||
switch {
|
||||
case strings.Contains(m, "ebay.co.uk"):
|
||||
return "EBAY_GB"
|
||||
case strings.Contains(m, "ebay.de"):
|
||||
return "EBAY_DE"
|
||||
case strings.Contains(m, "ebay.com.au"):
|
||||
return "EBAY_AU"
|
||||
case strings.Contains(m, "ebay.ca"):
|
||||
return "EBAY_CA"
|
||||
case strings.Contains(m, "ebay.fr"):
|
||||
return "EBAY_FR"
|
||||
case strings.Contains(m, "ebay.it"):
|
||||
return "EBAY_IT"
|
||||
case strings.Contains(m, "ebay.es"):
|
||||
return "EBAY_ES"
|
||||
case strings.Contains(m, "ebay.at"):
|
||||
return "EBAY_AT"
|
||||
case strings.Contains(m, "ebay.ch"):
|
||||
return "EBAY_CH"
|
||||
case strings.Contains(m, "ebay.ie"):
|
||||
return "EBAY_IE"
|
||||
case strings.Contains(m, "ebay.nl"):
|
||||
return "EBAY_NL"
|
||||
case strings.Contains(m, "ebay.com.hk"):
|
||||
return "EBAY_HK"
|
||||
case strings.Contains(m, "ebay.com.sg"):
|
||||
return "EBAY_SG"
|
||||
case strings.Contains(m, "ebay.com.my"):
|
||||
return "EBAY_MY"
|
||||
case strings.Contains(m, "ebay.ph"):
|
||||
return "EBAY_PH"
|
||||
case strings.Contains(m, "ebay.pl"):
|
||||
return "EBAY_PL"
|
||||
default:
|
||||
// "ebay.com" and any bare/unknown eBay marketplace.
|
||||
return "EBAY_US"
|
||||
}
|
||||
}
|
||||
|
||||
// IsEbayMarketplace reports whether a Veola marketplace string should be
|
||||
// polled through the official eBay Browse API.
|
||||
func IsEbayMarketplace(marketplace string) bool {
|
||||
return strings.Contains(strings.ToLower(marketplace), "ebay")
|
||||
}
|
||||
|
||||
// buyingOptionsFilter maps Veola's listing-type vocabulary to the Browse API
|
||||
// "filter" query parameter. An empty string means no filter ("all").
|
||||
func buyingOptionsFilter(listingType string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(listingType)) {
|
||||
case "bin", "buy_it_now", "fixed_price":
|
||||
return "buyingOptions:{FIXED_PRICE}"
|
||||
case "auction":
|
||||
return "buyingOptions:{AUCTION}"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user