ebay

package
v0.0.0-...-cef86c9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package ebay is the library behind the ebay command line: an HTTP client for eBay's public web pages and autocomplete host, an optional Browse API backend, and the typed records every command emits.

eBay renders its public pages server-side with schema.org JSON-LD and HTML cards, so this client GETs pages and parses them; the autocomplete host answers plain JSON. eBay fronts its estate with Akamai Bot Manager, which walls the item page (/itm/) and keyword search (/sch/) from datacenter IPs while serving category browse (/b/), seller stores (/str/, /usr/), the deals hub (/deals), and autocomplete from anywhere. So the client is two-layered: a reliable core over the open surfaces, and a best-effort layer over the walled ones that returns ErrBlocked when the wall is up and, if the operator has set Browse API credentials, falls back to that documented backend. Each surface lives in its own file (search.go, item.go, seller.go, category.go, deals.go, suggest.go) with its parsing and record mapping; this file holds the shared web client.

Index

Constants

View Source
const (
	// DefaultDelay is the minimum gap between requests. eBay is touchier than a
	// plain API, so a one-second pace reads steadily without leaning on it.
	DefaultDelay    = 1 * time.Second
	DefaultRetries  = 3
	DefaultTimeout  = 30 * time.Second
	DefaultCacheTTL = 24 * time.Hour
)

Defaults for the polite client.

View Source
const BaseURL = "https://" + Host

BaseURL is the root every item, seller, and category URL is built from.

View Source
const DefaultUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " +
	"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"

DefaultUserAgent is sent with every page request. eBay serves its public pages to a normal browser; a browser User-Agent is what keeps a logged-out reader looking like one. Override it with --user-agent.

View Source
const Host = "www.ebay.com"

Host is the eBay hostname this client builds page URLs from and the host the URI driver in domain.go claims.

Variables

View Source
var (
	// ErrNotFound is a missing entity: an unknown item id, an unknown seller, or
	// a bad category. eBay serves these as a 404 or a not-found shell page.
	// Exit code 6.
	ErrNotFound = errors.New("not found")

	// ErrRateLimited is a sustained HTTP 429 after the client's own retries.
	// Slow down with --rate. Exit code 5.
	ErrRateLimited = errors.New("rate limited")

	// ErrBlocked is the Akamai bot wall: a 403 interstitial, a reset, or an
	// implausibly small body on a page that should be large. eBay walls the item
	// page and keyword search from datacenter IPs, so this is expected there and
	// the message names the two remedies (a residential IP, or Browse API
	// credentials). Exit code 4.
	ErrBlocked = errors.New("blocked by eBay's bot wall (retry from a residential network, " +
		"or set EBAY_CLIENT_ID and EBAY_CLIENT_SECRET to use the Browse API)")
)

The library reports its outcomes as a few sentinel errors. domain.go's mapErr translates each into the kit error kind that carries the matching exit code, so the standalone binary and a host agree on what a wall, a throttle, and a miss mean.

Functions

func Defaults

func Defaults(c *kit.Config)

Defaults seeds the framework baseline with ebay's own values, so an unset --rate or --timeout uses the ebay default rather than the generic kit one. It is passed to kit.New via kit.WithDefaults.

func Identity

func Identity() kit.Identity

Identity is the fixed description of the ebay CLI, shared by the domain and the standalone composition root so help and version read the same everywhere.

func URLFor

func URLFor(kind, id string) string

URLFor builds the canonical eBay URL for a (kind, id) pair.

Types

type Category

type Category struct {
	ID     string   `json:"id" kit:"id"` // numeric leaf category id
	Name   string   `json:"name"`
	Parent string   `json:"parent,omitempty"` // parent category name (from the trail)
	Trail  []string `json:"trail,omitempty"`  // the full ancestor path, eBay first, leaf last
	Node   string   `json:"node,omitempty"`   // bn_<digits> browse-node id when known
	URL    string   `json:"url"`
}

Category is a category node, emitted by category show and category tree.

type Client

type Client struct {
	HTTP      *http.Client
	BaseURL   string
	UserAgent string
	Delay     time.Duration
	Retries   int

	// SuggestURL is the autocomplete endpoint. It defaults to the public
	// autosug host; tests point it at an httptest server.
	SuggestURL string
	// contains filtered or unexported fields
}

Client talks to eBay's public web pages. It paces requests, retries the transient failures, detects the bot wall, and caches response bodies on disk keyed by the request URL.

func ClientFromConfig

func ClientFromConfig(cfg kit.Config) *Client

ClientFromConfig maps the framework config onto an ebay.Config and returns a client. The Browse credentials are read from the environment, not flags, so they never land in shell history.

func NewClient

func NewClient(cfg Config) *Client

NewClient builds a client from cfg.

func (*Client) CategoryBrowse

func (c *Client) CategoryBrowse(ctx context.Context, ref string, limit int) ([]*Listing, error)

CategoryBrowse returns the listings in a category.

func (*Client) CategoryTree

func (c *Client) CategoryTree(ctx context.Context, ref string, limit int) ([]*Category, error)

CategoryTree returns the child categories of a node, read from the left-rail category links the browse page renders.

func (*Client) ClearCache

func (c *Client) ClearCache() error

ClearCache removes the on-disk cache.

func (*Client) Deals

func (c *Client) Deals(ctx context.Context, limit int) ([]*Deal, error)

Deals returns the current deals.

func (*Client) GetCategory

func (c *Client) GetCategory(ctx context.Context, ref string) (*Category, error)

GetCategory returns a category's metadata: its name and its parent, from the breadcrumb trail on the browse page.

func (*Client) GetItem

func (c *Client) GetItem(ctx context.Context, ref string) (*Item, error)

GetItem returns one item by id (or /itm/ URL).

func (*Client) GetSeller

func (c *Client) GetSeller(ctx context.Context, ref string) (*Seller, error)

GetSeller returns a seller's profile.

func (*Client) Search

func (c *Client) Search(ctx context.Context, query string, limit int) ([]*Listing, error)

Search returns listings matching a keyword query.

func (*Client) SellerListings

func (c *Client) SellerListings(ctx context.Context, ref string, limit int) ([]*Listing, error)

SellerListings returns a seller's active listings.

func (*Client) Suggest

func (c *Client) Suggest(ctx context.Context, prefix string, limit int) ([]*Suggestion, error)

Suggest returns search-autocomplete terms for a typed prefix.

type Config

type Config struct {
	UserAgent   string
	Marketplace string

	// ClientID and ClientSecret enable the Browse API fallback for the walled
	// surfaces (item, search). Empty leaves the fallback off; the walled
	// commands then report the bot wall rather than guessing.
	ClientID     string
	ClientSecret string

	// Delay is the minimum gap between requests. Zero means no pacing.
	Delay   time.Duration
	Retries int
	Timeout time.Duration

	// BaseURL is the site root. Empty uses the public site; tests point it at an
	// httptest server.
	BaseURL string

	// CacheDir is where responses are cached. Empty disables the cache, as does
	// NoCache.
	CacheDir string
	CacheTTL time.Duration
	NoCache  bool
	// Refresh fetches fresh copies and rewrites the cache, ignoring any hit.
	Refresh bool
}

Config carries the knobs the client reads. It is built from the kit framework config in ClientFromConfig, so a --rate or --timeout on the command line and the same value resolved by a host both land here.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the baseline configuration: a browser User-Agent, the EBAY_US marketplace, a one-second pace, three retries, a 30s timeout, and a one-day cache.

type Deal

type Deal struct {
	ID           string  `json:"id" kit:"id"`
	Title        string  `json:"title,omitempty" table:",truncate"`
	Price        float64 `json:"price,omitempty"`
	Was          float64 `json:"was,omitempty"` // original price
	Currency     string  `json:"currency,omitempty"`
	Discount     string  `json:"discount,omitempty"` // the badge text, e.g. "20% off"
	FreeShipping bool    `json:"free_shipping,omitempty"`
	Trending     bool    `json:"trending,omitempty"` // the tile carries a hotness badge
	Image        string  `json:"image,omitempty" table:",truncate"`
	URL          string  `json:"url"`
}

Deal is a row on the deals hub, emitted by deals.

type Domain

type Domain struct{}

Domain is the ebay driver. It carries no state; the per-run client is built by the factory Register hands kit.

func (Domain) Classify

func (Domain) Classify(input string) (uriType, id string, err error)

Classify turns any accepted input into the canonical (type, id), so `ant resolve` and `ant url` touch no network.

func (Domain) Info

func (Domain) Info() kit.DomainInfo

Info describes the scheme, the hostnames a pasted link is matched against, and the identity reused for the binary's help and version.

func (Domain) Locate

func (Domain) Locate(uriType, id string) (string, error)

Locate is the inverse: the live https URL for a (type, id).

func (Domain) Register

func (Domain) Register(app *kit.App)

Register installs the client factory and every operation onto app. A resolver op (Single) names its own record type and answers `ant get`; a List op enumerates a parent resource's members and answers `ant ls`.

type Item

type Item struct {
	ID           string   `json:"id" kit:"id"`
	Title        string   `json:"title,omitempty" table:",truncate"`
	Subtitle     string   `json:"subtitle,omitempty" table:",truncate"`
	Price        float64  `json:"price,omitempty"`
	Currency     string   `json:"currency,omitempty"`
	Condition    string   `json:"condition,omitempty"`
	Buying       string   `json:"buying,omitempty"` // fixed, auction
	Bids         int      `json:"bids,omitempty"`   // auctions only
	EndsAt       string   `json:"ends_at,omitempty"`
	Available    int      `json:"available,omitempty"`
	Sold         int      `json:"sold,omitempty"`
	Seller       string   `json:"seller,omitempty"`
	SellerScore  int      `json:"seller_score,omitempty"`
	SellerRating float64  `json:"seller_rating,omitempty"`
	Location     string   `json:"location,omitempty"`
	Shipping     string   `json:"shipping,omitempty"`
	Returns      string   `json:"returns,omitempty"`
	Category     string   `json:"category,omitempty"`
	Image        string   `json:"image,omitempty" table:",truncate"`
	Images       []string `json:"images,omitempty"` // the photo gallery, when the page or API lists more than one
	URL          string   `json:"url"`
}

Item is the full detail for one item, emitted by item. The fields are what the /itm page shows a logged-out visitor, the same fields the Browse API returns on the fallback path.

type Listing

type Listing struct {
	ID        string   `json:"id" kit:"id"`
	Title     string   `json:"title,omitempty" table:",truncate"`
	Price     float64  `json:"price,omitempty"`
	Currency  string   `json:"currency,omitempty"`
	Condition string   `json:"condition,omitempty"`
	Buying    string   `json:"buying,omitempty"` // fixed, auction, best_offer
	Bids      int      `json:"bids,omitempty"`   // auctions only
	Shipping  string   `json:"shipping,omitempty"`
	Seller    string   `json:"seller,omitempty"`
	Rating    float64  `json:"rating,omitempty"`  // aggregate rating (category JSON-LD)
	Reviews   int      `json:"reviews,omitempty"` // review count (category JSON-LD)
	Sold      int      `json:"sold,omitempty"`    // units sold, when the card prints it
	Watching  int      `json:"watching,omitempty"`
	Thumbnail string   `json:"thumbnail,omitempty" table:",truncate"`
	Images    []string `json:"images,omitempty"` // image gallery (category JSON-LD itemOffered)
	URL       string   `json:"url"`
}

Listing is a summary row in a grid, emitted by search, category browse, and seller listings.

type Ref

type Ref struct {
	Input string `json:"input"`
	Kind  string `json:"kind"`
	ID    string `json:"id"`
	URL   string `json:"url"`
}

Ref is the result of `ebay ref id`: the canonical (kind, id) a reference resolves to, plus the live URL, all without touching the network.

func Classify

func Classify(ref string) Ref

Classify reads a reference (a URL, a path, or a bare id) and reports what it points at. Kind is one of item, seller, category, or unknown.

type Seller

type Seller struct {
	Username  string  `json:"username" kit:"id"`
	Store     string  `json:"store,omitempty"`
	Score     int     `json:"score,omitempty"`    // feedback score (count), when shown
	Positive  float64 `json:"positive,omitempty"` // percent positive feedback
	Sold      int     `json:"sold,omitempty"`     // lifetime items sold (storefront)
	Followers int     `json:"followers,omitempty"`
	TopRated  bool    `json:"top_rated,omitempty"` // the Top Rated Seller badge
	Location  string  `json:"location,omitempty"`
	URL       string  `json:"url"`
}

Seller is a seller's public profile, emitted by seller show.

type Suggestion

type Suggestion struct {
	Query string `json:"query"`         // the prefix that was queried
	Term  string `json:"term" kit:"id"` // a suggested completion
}

Suggestion is one autocomplete term, emitted by suggest.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL