Documentation
¶
Overview ¶
Package steam is the library behind the st command line: the HTTP client, the offline reference layer, and the typed records read from public Steam surfaces.
Steam has one keyless access plane that spans three hosts. The storefront (store.steampowered.com) answers app details, search, reviews, and package details as JSON. The community site (steamcommunity.com) serves public profiles as XML and the community market as JSON. A keyless subset of api.steampowered.com answers the full app catalog, a game's news, its live player count, and its global achievement rates. None of this needs an account or a key, so the Client below is a plain paced, retrying, caching GET client with no auth handshake. It turns a walled or rejected response into a typed error the exit-code mapping understands.
Index ¶
- Constants
- Variables
- func Defaults(c *kit.Config)
- func Identity() kit.Identity
- func URLFor(kind, id string) string
- type Achievement
- type App
- type Client
- func (c *Client) Achievements(ctx context.Context, appid string, limit int) ([]*Achievement, error)
- func (c *Client) App(ctx context.Context, appid string) (*App, error)
- func (c *Client) Featured(ctx context.Context, limit int) ([]*App, error)
- func (c *Client) FeaturedCategory(ctx context.Context, key string, limit int) ([]*App, error)
- func (c *Client) MarketPrice(ctx context.Context, appid, hashName string) (*MarketPrice, error)
- func (c *Client) MarketSearch(ctx context.Context, term string, limit int) ([]*MarketItem, error)
- func (c *Client) News(ctx context.Context, appid string, limit int) ([]*NewsItem, error)
- func (c *Client) Package(ctx context.Context, packageid string) (*Package, error)
- func (c *Client) Players(ctx context.Context, appid string) (*PlayerCount, error)
- func (c *Client) Profile(ctx context.Context, ref string) (*Profile, error)
- func (c *Client) Resolve(ctx context.Context, ref string) (*SteamID, error)
- func (c *Client) Reviews(ctx context.Context, appid string, limit int) ([]*Review, error)
- func (c *Client) Search(ctx context.Context, term string, limit int) ([]*App, error)
- type Config
- type Domain
- type GameLink
- type IDName
- type MarketItem
- type MarketPrice
- type Media
- type NewsItem
- type Package
- type Platforms
- type PlayerCount
- type Price
- type Profile
- type Ref
- type Review
- type SteamID
Constants ¶
const ( // StoreHost is the storefront, the host the URI driver primarily claims. StoreHost = "store.steampowered.com" // CommunityHost serves public profiles (XML) and the community market. CommunityHost = "steamcommunity.com" // APIHost serves the keyless api.steampowered.com endpoints (app list, news, // player count, global achievement percentages). APIHost = "api.steampowered.com" // StoreURL, CommunityURL, and APIURL are the roots each request is built from. StoreURL = "https://" + StoreHost CommunityURL = "https://" + CommunityHost APIURL = "https://" + APIHost // DefaultCacheTTL is how long a cached response stays fresh by default. Store // data changes on a daily cadence, so a few hours is plenty. DefaultCacheTTL = 6 * time.Hour )
const DefaultUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
DefaultUserAgent identifies the client. It names a current browser, because the storefront and the community site serve a leaner response to an obvious script and a few endpoints reject an empty agent. It is honest in that st does not forge a crawler identity it is reverse-DNS-checked against.
Variables ¶
var ( // ErrBlocked is the wall: a 403, or an anti-bot interstitial served with a 200. // Maps to need-auth (exit 4). The remedy is to slow down or try again later; // st does not defeat the wall. ErrBlocked = errors.New("blocked: Steam served an anti-bot wall here. Slow down with --rate or try again later") // ErrNotFound is a missing entity: an appdetails/packagedetails success:false, // a market priceoverview success:false, a player-count result != 1, or a 404. // Maps to exit 6. ErrNotFound = errors.New("not found") // ErrRateLimited is a sustained 429 after retries. Maps to exit 5. ErrRateLimited = errors.New("rate limited by Steam: slow down with --rate or try again later") // ErrNetwork is a transport failure that survives every retry: a connection // refused, a timeout, a DNS error, or a 5xx that never recovered. Maps to exit 8. ErrNetwork = errors.New("network error reaching Steam") // ErrUsage is a bad argument the library catches (an unrecognized reference, a // missing market name). Maps to exit 2. ErrUsage = errors.New("usage") )
Sentinel errors the library returns; domain.go's mapErr turns each into the kit error kind that carries the right exit code (see spec 8031 section 4.5). There is no need-key error, because st reads only keyless surfaces.
Functions ¶
func Defaults ¶ added in v0.2.0
Defaults seeds the framework baseline with steam's own values, so an unset --rate or --timeout uses the steam default rather than the generic kit one.
Types ¶
type Achievement ¶ added in v0.2.0
type Achievement struct {
ID string `json:"id" kit:"id"` // the achievement api name
App string `json:"app,omitempty" table:"-" kit:"link,kind=steam/app"`
Percent float64 `json:"percent"` // global unlock rate
}
Achievement is the global unlock rate of one achievement, emitted by achievements. The keyless percentages endpoint gives only the api name and the percent, so st does not invent a display name or an icon it cannot read.
type App ¶ added in v0.2.0
type App struct {
ID string `json:"id" kit:"id"` // the numeric appid
Name string `json:"name,omitempty" table:",truncate"`
Type string `json:"type,omitempty"` // game, dlc, demo, music, video, ...
IsFree bool `json:"is_free,omitempty"`
ShortDescription string `json:"short_description,omitempty" table:",truncate"`
DetailedDescription string `json:"detailed_description,omitempty" table:"-" kit:"body"`
AboutTheGame string `json:"about_the_game,omitempty" table:"-"`
SupportedLanguages string `json:"supported_languages,omitempty" table:"-"`
Developers []string `json:"developers,omitempty" table:"-"`
Publishers []string `json:"publishers,omitempty" table:"-"`
Price *Price `json:"price,omitempty" table:"-"`
Platforms *Platforms `json:"platforms,omitempty" table:"-"`
Categories []IDName `json:"categories,omitempty" table:"-"`
Genres []IDName `json:"genres,omitempty" table:"-"`
ReleaseDate string `json:"release_date,omitempty"`
ComingSoon bool `json:"coming_soon,omitempty" table:"-"`
RequiredAge int `json:"required_age,omitempty" table:"-"`
ControllerSupport string `json:"controller_support,omitempty" table:"-"`
Metacritic int `json:"metacritic,omitempty" table:"-"`
MetacriticURL string `json:"metacritic_url,omitempty" table:"-"`
Recommendations int `json:"recommendations,omitempty" table:"-"`
AchievementsTotal int `json:"achievements_total,omitempty" table:"-"`
ReviewScore string `json:"review_score,omitempty" table:"-"` // from the store-page island
Website string `json:"website,omitempty" table:"-"`
HeaderImage string `json:"header_image,omitempty" table:"-"`
Background string `json:"background,omitempty" table:"-"`
Screenshots []Media `json:"screenshots,omitempty" table:"-"`
Movies []Media `json:"movies,omitempty" table:"-"`
Tags []string `json:"tags,omitempty" table:"-"` // user tags from the store-page island
ContentDescriptors []string `json:"content_descriptors,omitempty" table:"-"`
SupportURL string `json:"support_url,omitempty" table:"-"`
SupportEmail string `json:"support_email,omitempty" table:"-"`
// Embedded relations the source fills inline.
Fullgame *GameLink `json:"fullgame,omitempty" table:"-"` // set when this app is DLC or a demo
DLC []GameLink `json:"dlc,omitempty" table:"-"`
Packages []int `json:"packages,omitempty" table:"-"`
URL string `json:"url"` // the store page
// Graph edges (one per slice element).
DLCRefs []string `json:"dlc_refs,omitempty" table:"-" kit:"link,kind=steam/app"`
FullgameRef string `json:"fullgame_ref,omitempty" table:"-" kit:"link,kind=steam/app"`
PackageRefs []string `json:"package_refs,omitempty" table:"-" kit:"link,kind=steam/package"`
ReviewsRef string `json:"reviews_ref,omitempty" table:"-" kit:"link,kind=steam/reviews"` // = ID
NewsRef string `json:"news_ref,omitempty" table:"-" kit:"link,kind=steam/news"` // = ID
}
App is the core record: a store entry (a game, DLC, demo, music, video, or software). The id is the numeric appid, the key the store, the reviews, the news, the player count, and the achievements all share.
type Client ¶
Client reads public Steam data over HTTP.
func ClientFromConfig ¶ added in v0.2.0
ClientFromConfig maps the framework config onto a steam.Config and returns a client. There are no credentials to read; the only domain-specific knobs are the storefront locale and the review filters.
func NewClient ¶
NewClient returns a Client configured from cfg, filling unset fields with their defaults.
func (*Client) Achievements ¶ added in v0.2.0
Achievements returns up to limit global achievement rates for appid, ordered as the endpoint returns them (most unlocked first).
func (*Client) App ¶ added in v0.2.0
App fetches one app by appid and returns it as a record. It reads the appdetails JSON, then enriches with the store-page island when the page is reachable.
func (*Client) Featured ¶ added in v0.2.0
Featured returns up to limit promoted apps, de-duplicated by appid, across every featured category the endpoint carries.
func (*Client) FeaturedCategory ¶ added in v0.2.0
FeaturedCategory returns up to limit apps from one named category of the featuredcategories endpoint: top_sellers, new_releases, specials, or coming_soon. A missing category yields no apps and no error.
func (*Client) MarketPrice ¶ added in v0.2.0
MarketPrice returns the price overview for one market item, addressed by its app and its market hash name.
func (*Client) MarketSearch ¶ added in v0.2.0
MarketSearch returns up to limit community market listings for term.
func (*Client) Package ¶ added in v0.2.0
Package fetches one package by packageid and returns it as a record.
func (*Client) Players ¶ added in v0.2.0
Players returns the live concurrent player count for appid.
func (*Client) Profile ¶ added in v0.2.0
Profile fetches a public profile by SteamID64, vanity, or community URL.
func (*Client) Resolve ¶ added in v0.2.0
Resolve turns a vanity name (or any profile reference) into a SteamID record by reading the community XML for its steamID64, then deriving every id form offline.
type Config ¶
type Config struct {
UserAgent string
Delay time.Duration // minimum gap between requests
Retries int // retries on 429/5xx
Timeout time.Duration // per-request timeout
// Storefront locale, shared by the store commands.
CC string // country code, e.g. "us"; sets the price currency and availability
Lang string // language, e.g. "english"; sets the description and name language
Currency int // market currency code, e.g. 1 for USD
// Review filters, used by the reviews command.
ReviewFilter string // recent, updated, all
ReviewLanguage string // all, english, ...
PurchaseType string // all, steam, non_steam_purchase
// Overridable for tests.
StoreURL string
CommunityURL string
APIURL string
CacheDir string
NoCache bool
CacheTTL time.Duration
Refresh bool // refetch and rewrite the cache, ignoring any hit
}
Config is the resolved settings a Client reads.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns the baseline settings. It reads no environment variable: st has no key and no per-flag environment fallback.
type Domain ¶ added in v0.1.1
type Domain struct{}
Domain is the steam driver. It carries no state; the per-run client is built by the factory Register hands kit.
func (Domain) Classify ¶ added in v0.2.0
Classify turns any accepted input into the canonical (type, id), so a host's resolve and url touch no network.
func (Domain) Info ¶ added in v0.1.1
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) Register ¶ added in v0.1.1
Register installs the client factory and every operation onto app. The store group reads the storefront and the keyless web API; the player group reads public community profiles; the market group reads the community market; the ref group is offline and never touches the network.
type GameLink ¶ added in v0.2.0
GameLink is the embedded reference to another app: a base game, a DLC entry, a bundled app, or a most-played game.
type IDName ¶ added in v0.2.0
type IDName struct {
ID string `json:"id,omitempty"`
Description string `json:"description,omitempty"`
}
IDName is a store facet: a category or a genre, with its id and label.
type MarketItem ¶ added in v0.2.0
type MarketItem struct {
ID string `json:"id" kit:"id"` // market hash name
Name string `json:"name,omitempty" table:",truncate"`
App string `json:"app,omitempty" table:"-" kit:"link,kind=steam/app"`
AppName string `json:"app_name,omitempty" table:",truncate"`
SellListings int `json:"sell_listings,omitempty"`
SellPrice int `json:"sell_price,omitempty"` // cents
SellPriceText string `json:"sell_price_text,omitempty"`
Type string `json:"type,omitempty" table:"-"`
Icon string `json:"icon,omitempty" table:"-"`
URL string `json:"url"`
}
MarketItem is one community market listing, emitted by market.
type MarketPrice ¶ added in v0.2.0
type MarketPrice struct {
ID string `json:"id" kit:"id"` // market hash name
App string `json:"app,omitempty" table:"-" kit:"link,kind=steam/app"`
Currency int `json:"currency,omitempty"`
LowestPrice string `json:"lowest_price,omitempty"`
MedianPrice string `json:"median_price,omitempty"`
Volume string `json:"volume,omitempty"`
URL string `json:"url"`
}
MarketPrice is the lowest, median, and volume for one market item, emitted by price.
type Media ¶ added in v0.2.0
type Media struct {
ID string `json:"id,omitempty"`
Type string `json:"type,omitempty"` // screenshot, movie
Thumb string `json:"thumb,omitempty"`
Full string `json:"full,omitempty"` // the full image, or the mp4/webm for a movie
}
Media is one screenshot or movie in an app's gallery.
type NewsItem ¶ added in v0.2.0
type NewsItem struct {
ID string `json:"id" kit:"id"` // gid
App string `json:"app,omitempty" table:"-" kit:"link,kind=steam/app"`
Title string `json:"title,omitempty" table:",truncate"`
URL string `json:"url,omitempty" table:"-"`
Author string `json:"author,omitempty" table:"-"`
Body string `json:"body,omitempty" table:",truncate" kit:"body"`
FeedLabel string `json:"feed_label,omitempty" table:"-"`
FeedName string `json:"feed_name,omitempty" table:"-"`
External bool `json:"external,omitempty" table:"-"`
Date string `json:"date,omitempty"`
}
NewsItem is one news or announcement item for an app, emitted by news.
type Package ¶ added in v0.2.0
type Package struct {
ID string `json:"id" kit:"id"` // packageid
Name string `json:"name,omitempty" table:",truncate"`
Description string `json:"description,omitempty" table:"-" kit:"body"`
Price *Price `json:"price,omitempty" table:"-"`
Platforms *Platforms `json:"platforms,omitempty" table:"-"`
ReleaseDate string `json:"release_date,omitempty"`
ComingSoon bool `json:"coming_soon,omitempty" table:"-"`
HeaderImage string `json:"header_image,omitempty" table:"-"`
Apps []GameLink `json:"apps,omitempty" table:"-"`
URL string `json:"url"`
AppRefs []string `json:"app_refs,omitempty" table:"-" kit:"link,kind=steam/app"`
}
Package is a store package (a sub): a bundle of apps sold as one purchase, emitted by package. AppRefs is the apps it bundles, each a walkable app edge.
type Platforms ¶ added in v0.2.0
type Platforms struct {
Windows bool `json:"windows,omitempty"`
Mac bool `json:"mac,omitempty"`
Linux bool `json:"linux,omitempty"`
}
Platforms is the set of operating systems an app or package supports.
type PlayerCount ¶ added in v0.2.0
type PlayerCount struct {
ID string `json:"id" kit:"id"` // appid
Count int `json:"count"`
URL string `json:"url"`
App string `json:"app,omitempty" table:"-" kit:"link,kind=steam/app"`
}
PlayerCount is the live concurrent player count for an app, emitted by players.
type Price ¶ added in v0.2.0
type Price struct {
Currency string `json:"currency,omitempty"`
Initial int `json:"initial,omitempty"`
Final int `json:"final,omitempty"`
DiscountPct int `json:"discount_pct,omitempty"`
FinalFormatted string `json:"final_formatted,omitempty"`
}
Price is an app or package price. The amounts are in the currency's minor unit (cents for USD).
type Profile ¶ added in v0.2.0
type Profile struct {
ID string `json:"id" kit:"id"` // SteamID64
PersonaName string `json:"persona_name,omitempty" table:",truncate"`
RealName string `json:"real_name,omitempty" table:"-"`
CustomURL string `json:"custom_url,omitempty" table:"-"` // the vanity, if set
Visibility string `json:"visibility,omitempty"` // public, private, friendsonly
OnlineState string `json:"online_state,omitempty"` // online, offline, in-game
StateMessage string `json:"state_message,omitempty" table:"-"`
Location string `json:"location,omitempty" table:"-"`
Summary string `json:"summary,omitempty" table:",truncate" kit:"body"`
MemberSince string `json:"member_since,omitempty" table:"-"`
Avatar string `json:"avatar,omitempty" table:"-"`
AvatarFull string `json:"avatar_full,omitempty" table:"-"`
VACBanned bool `json:"vac_banned,omitempty" table:"-"`
TradeBanState string `json:"trade_ban_state,omitempty" table:"-"`
LimitedAccount bool `json:"limited_account,omitempty" table:"-"`
HoursTwoWeeks float64 `json:"hours_two_weeks,omitempty" table:"-"`
MostPlayed []GameLink `json:"most_played,omitempty" table:"-"`
Groups []string `json:"groups,omitempty" table:"-"` // group ids
URL string `json:"url"`
MostPlayedRefs []string `json:"most_played_refs,omitempty" table:"-" kit:"link,kind=steam/app"`
}
Profile is a public community profile, parsed from the XML, emitted by profile. A private profile carries the public subset and sets Visibility accordingly.
type Ref ¶ added in v0.2.0
type Ref struct {
Input string `json:"input"`
Kind string `json:"kind"`
ID string `json:"id"`
URL string `json:"url"`
}
Ref is the result of `st ref id`/`st ref url`: the canonical (kind, id) a reference resolves to, plus the URL, all without touching the network.
type Review ¶
type Review struct {
ID string `json:"id" kit:"id"` // recommendationid
App string `json:"app,omitempty" table:"-" kit:"link,kind=steam/app"`
Author string `json:"author,omitempty"` // author SteamID64
Language string `json:"language,omitempty" table:"-"`
Body string `json:"body,omitempty" table:",truncate" kit:"body"`
VotedUp bool `json:"voted_up,omitempty"`
VotesUp int `json:"votes_up,omitempty"`
VotesFunny int `json:"votes_funny,omitempty" table:"-"`
WeightedScore float64 `json:"weighted_score,omitempty" table:"-"`
Comments int `json:"comments,omitempty" table:"-"`
SteamPurchase bool `json:"steam_purchase,omitempty" table:"-"`
ReceivedFree bool `json:"received_free,omitempty" table:"-"`
EarlyAccess bool `json:"early_access,omitempty" table:"-"`
PlaytimeAtReview int `json:"playtime_at_review,omitempty" table:"-"` // minutes
PlaytimeForever int `json:"playtime_forever,omitempty" table:"-"` // minutes
Created string `json:"created,omitempty"`
Updated string `json:"updated,omitempty" table:"-"`
AuthorRef string `json:"author_ref,omitempty" table:"-" kit:"link,kind=steam/profile"`
}
Review is one user review of an app, emitted by reviews. App is the edge back to the app; AuthorRef is the edge to the author's public profile.
type SteamID ¶ added in v0.2.0
type SteamID struct {
Input string `json:"input"`
Kind string `json:"kind"` // steamid64, steamid3, steam2, vanity
SteamID64 string `json:"steamid64,omitempty"`
SteamID3 string `json:"steamid3,omitempty"`
Steam2 string `json:"steam2,omitempty"`
AccountID string `json:"account_id,omitempty"`
Vanity string `json:"vanity,omitempty"`
URL string `json:"url,omitempty"`
}
SteamID is the offline conversion result of `st resolve` and `st ref steamid`.