Documentation
¶
Overview ¶
Package pinterest is the library behind the pin command line: the HTTP client, the Pinterest resource API, the page bootstrap parser, and the typed records every command emits.
Pinterest serves its public data two ways. Board and user pages embed a JSON blob (__PWS_DATA__) that carries the entity and its first grid of pins, parsed in bootstrap.go. Everything that paginates (search, related pins, a board's feed, a topic's feed) is read from the resource API: GET /resource/<Name>Resource/get/ with the request encoded in a `data` query parameter, handled in resource.go. Both work for a logged-out reader. The client warms up a csrftoken from the public homepage, the handshake a browser makes before its first XHR, not a login.
Index ¶
- Constants
- Variables
- func Defaults(c *kit.Config)
- func Identity() kit.Identity
- func URLFor(kind, id string) string
- type Board
- type Client
- func (c *Client) Board(ctx context.Context, ref string) (*Board, error)
- func (c *Client) BoardPins(ctx context.Context, ref string, limit int) ([]*Pin, error)
- func (c *Client) BoardSections(ctx context.Context, ref string) ([]*Section, error)
- func (c *Client) ClearCache() error
- func (c *Client) GetPin(ctx context.Context, pinID string) (*Pin, error)
- func (c *Client) Related(ctx context.Context, pinID string, limit int) ([]*Pin, error)
- func (c *Client) Search(ctx context.Context, query string, limit int) ([]*Pin, error)
- func (c *Client) TopicFeed(ctx context.Context, slug string, limit int) ([]*Pin, error)
- func (c *Client) Trending(ctx context.Context, limit int) ([]*Topic, error)
- func (c *Client) User(ctx context.Context, name string) (*User, error)
- func (c *Client) UserBoards(ctx context.Context, name string, limit int) ([]*Board, error)
- func (c *Client) UserPins(ctx context.Context, name string, limit int) ([]*Pin, error)
- type Config
- type Domain
- type Pin
- type Ref
- type Section
- type Topic
- type User
Constants ¶
const ( DefaultDelay = time.Second DefaultRetries = 3 DefaultTimeout = 30 * time.Second DefaultCacheTTL = 24 * time.Hour )
Defaults for the polite client. A one second gap between requests is gentle enough for steady reading without tripping the rate limiter.
const BaseURL = "https://" + Host
BaseURL is the root every request is built from.
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 request. Pinterest serves its public pages and its resource endpoints to a normal browser; a browser User-Agent is what keeps a logged-out reader unblocked. Override it with --user-agent.
const Host = "www.pinterest.com"
Host is the Pinterest hostname this client talks to and the host the URI driver in domain.go claims.
Variables ¶
var ( // ErrNotFound is a 404 or an empty resource: the pin, board, or user does // not exist, or is not visible to a logged-out reader. 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 a 403 or a login wall: Pinterest declined to serve the // surface to an anonymous reader, which datacenter and CI addresses see more // often than home networks do. Exit code 4. ErrBlocked = errors.New("blocked") )
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 ¶
Defaults seeds the framework baseline with pinterest's own values, so an unset --rate or --timeout uses the pinterest default rather than the generic kit one. It is passed to kit.New via kit.WithDefaults.
Types ¶
type Board ¶
type Board struct {
ID string `json:"id" kit:"id"`
Name string `json:"name"`
Slug string `json:"slug,omitempty"`
URL string `json:"url"`
Owner string `json:"owner,omitempty"`
Description string `json:"description,omitempty" table:",truncate"`
Pins int `json:"pins,omitempty"`
Followers int64 `json:"followers,omitempty"`
Sections int `json:"sections,omitempty"`
Privacy string `json:"privacy,omitempty"`
Cover string `json:"cover,omitempty" table:",truncate"`
Created string `json:"created,omitempty"`
}
Board is a collection of pins owned by a user.
type Client ¶
type Client struct {
HTTP *http.Client
UserAgent string
Delay time.Duration
Retries int
// contains filtered or unexported fields
}
Client talks to Pinterest over HTTP. It holds a cookie jar so the csrftoken obtained at warmup rides along on every resource call, paces requests, retries the transient failures, and caches response bodies on disk.
func ClientFromConfig ¶
ClientFromConfig maps the framework config onto a pinterest.Config and returns a client.
func NewClient ¶
NewClient builds a client from cfg. The cookie jar is required: the warmup request deposits the csrftoken cookie that later resource calls echo back in the X-CSRFToken header.
func (*Client) Board ¶
Board fetches one board's metadata by reference (a full URL, a "user/slug" path, or "user", "slug").
func (*Client) BoardSections ¶
BoardSections returns a board's sections. A board with no sections yields an empty slice and no error.
func (*Client) ClearCache ¶
ClearCache removes the on-disk cache. It backs `pin cache clear`.
func (*Client) GetPin ¶
GetPin fetches one pin by id. It uses the unauth field set, the same one a logged-out browser requests for a pin page.
func (*Client) Related ¶
Related returns the pins Pinterest recommends under a given pin, up to limit.
func (*Client) Search ¶
Search returns pins matching query, up to limit (0 means as many as the feed yields). scope is fixed to pins: boards and users have their own commands.
func (*Client) TopicFeed ¶
TopicFeed returns the pins under an interest slug ("home-decor"), up to limit.
func (*Client) User ¶
User fetches one profile by username (a leading @ or a profile URL are accepted).
func (*Client) UserBoards ¶
UserBoards returns a user's public boards, up to limit.
type Config ¶
type Config struct {
UserAgent string
// Delay is the minimum gap between requests. Zero means no pacing.
Delay time.Duration
Retries int
Timeout time.Duration
// CacheDir is where fetched pages and resource 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, a one second pace, three retries, a 30s timeout, and a one day cache.
type Domain ¶
type Domain struct{}
Domain is the pinterest driver. It carries no state; the per-run client is built by the factory Register hands kit.
func (Domain) Classify ¶
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.
type Pin ¶
type Pin struct {
ID string `json:"id" kit:"id"`
Type string `json:"type,omitempty"`
Title string `json:"title,omitempty" table:",truncate"`
Description string `json:"description,omitempty" table:",truncate"`
Link string `json:"link,omitempty" table:",truncate"`
URL string `json:"url"`
Image string `json:"image,omitempty" table:",truncate"`
ImageWidth int `json:"image_width,omitempty"`
ImageHeight int `json:"image_height,omitempty"`
DominantColor string `json:"dominant_color,omitempty"`
IsVideo bool `json:"is_video,omitempty"`
Video string `json:"video,omitempty" table:",truncate"`
AltText string `json:"alt_text,omitempty" table:",truncate"`
Pinner string `json:"pinner,omitempty"`
Board string `json:"board,omitempty"`
Saves int64 `json:"saves,omitempty"`
Comments int64 `json:"comments,omitempty"`
Created string `json:"created,omitempty"`
}
Pin is one saved image or video.
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 `pin id`: the canonical (kind, id) a reference resolves to, plus the live URL, all without touching the network.
type Section ¶
type Section struct {
ID string `json:"id" kit:"id"`
Title string `json:"title"`
Slug string `json:"slug,omitempty"`
BoardID string `json:"board_id,omitempty"`
Pins int `json:"pins,omitempty"`
}
Section is a named division within a board.
type Topic ¶
type Topic struct {
ID string `json:"id" kit:"id"`
Name string `json:"name"`
Slug string `json:"slug,omitempty"`
Followers int64 `json:"followers,omitempty"`
URL string `json:"url"`
}
Topic is one trending interest, the seed for `pin topic <slug>`.
type User ¶
type User struct {
ID string `json:"id" kit:"id"`
Username string `json:"username"`
FullName string `json:"full_name,omitempty"`
Bio string `json:"bio,omitempty" table:",truncate"`
Website string `json:"website,omitempty" table:",truncate"`
Location string `json:"location,omitempty"`
Followers int64 `json:"followers,omitempty"`
Following int64 `json:"following,omitempty"`
Boards int `json:"boards,omitempty"`
Pins int64 `json:"pins,omitempty"`
MonthlyViews int64 `json:"monthly_views,omitempty"`
Verified bool `json:"verified,omitempty"`
Avatar string `json:"avatar,omitempty" table:",truncate"`
URL string `json:"url"`
}
User is a public profile.