pinterest

package
v0.0.0-...-09e61ba Latest Latest
Warning

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

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

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

View Source
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.

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

BaseURL is the root every request 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 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.

View Source
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

View Source
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

func Defaults(c *kit.Config)

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.

func Identity

func Identity() kit.Identity

Identity is the fixed description of the pinterest 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 Pinterest URL for a (kind, id) pair.

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

func ClientFromConfig(cfg kit.Config) *Client

ClientFromConfig maps the framework config onto a pinterest.Config and returns a client.

func NewClient

func NewClient(cfg Config) *Client

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

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

Board fetches one board's metadata by reference (a full URL, a "user/slug" path, or "user", "slug").

func (*Client) BoardPins

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

BoardPins returns a board's pins, up to limit.

func (*Client) BoardSections

func (c *Client) BoardSections(ctx context.Context, ref string) ([]*Section, error)

BoardSections returns a board's sections. A board with no sections yields an empty slice and no error.

func (*Client) ClearCache

func (c *Client) ClearCache() error

ClearCache removes the on-disk cache. It backs `pin cache clear`.

func (*Client) GetPin

func (c *Client) GetPin(ctx context.Context, pinID string) (*Pin, error)

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

func (c *Client) Related(ctx context.Context, pinID string, limit int) ([]*Pin, error)

Related returns the pins Pinterest recommends under a given pin, up to limit.

func (*Client) Search

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

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

func (c *Client) TopicFeed(ctx context.Context, slug string, limit int) ([]*Pin, error)

TopicFeed returns the pins under an interest slug ("home-decor"), up to limit.

func (*Client) Trending

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

Trending returns the top interest topics, up to limit.

func (*Client) User

func (c *Client) User(ctx context.Context, name string) (*User, error)

User fetches one profile by username (a leading @ or a profile URL are accepted).

func (*Client) UserBoards

func (c *Client) UserBoards(ctx context.Context, name string, limit int) ([]*Board, error)

UserBoards returns a user's public boards, up to limit.

func (*Client) UserPins

func (c *Client) UserPins(ctx context.Context, name string, limit int) ([]*Pin, error)

UserPins returns a user's saved pins, 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

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 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.

func Classify

func Classify(ref string) Ref

Classify reads a reference (a URL, a path, a handle, or a bare id) and reports what it points at. Kind is one of pin, board, user, topic, or unknown.

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.

Jump to

Keyboard shortcuts

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