Documentation
¶
Overview ¶
Package twitter adapts the standalone github.com/go-birdsite/twitter best-effort client to the aggregator's source.Provider contract. A public account screen name (with or without a leading "@") as the query channel fetches that account's tweets; the reserved channels "home"/"following" fetch the logged-in user's home timeline through X's private GraphQL endpoint.
This provider is inherently fragile: Twitter/X locks these endpoints and changes their shape without notice. Public timelines do NOT need an auth token — they need a browser-fingerprinting HTTP client, which is what the syndication endpoint checks. The home timeline is different: it needs the logged-in auth_token + ct0 (CSRF) cookies, which the reader imports from the browser, and a GraphQL query id that X rotates. When those are absent or X rejects the read, it is reported as a typed sign-in prompt rather than a crash or a fake feed.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNoChannel = errors.New("twitter: Query.Channel must be a screen name")
ErrNoChannel is returned when Feed is called without a screen name.
Functions ¶
This section is empty.
Types ¶
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider fetches a public account's tweets as normalized items, and — for the reserved "home"/"following" channels — the authenticated home timeline.
func New ¶
func New() *Provider
New returns a provider. Public timelines need no auth token — the reader reads them through the syndication endpoint (see newWith).
func NewWithClient ¶
func NewWithClient(c client) *Provider
NewWithClient wraps a preconfigured client (or a fake in tests).
func NewWithHTTPClient ¶
NewWithHTTPClient returns a provider whose reads go through hc (e.g. the shared, request-logging client so the Network log captures Twitter/X traffic).
func NewWithSession ¶
NewWithSession returns a provider that can additionally read the authenticated home timeline, using session — a full X cookie string ("auth_token=…; ct0=…") from a signed-in browser. Public-timeline reads are unaffected.
func (*Provider) Feed ¶
Feed returns items for the query. The reserved channels "home" and "following" fetch the authenticated home timeline; any other channel is a public account screen name whose recent tweets are returned (the public path is not paginated, so its Result.Cursor is empty).
func (*Provider) MyFollows ¶
MyFollows returns every account the connected X user follows as a ready subscription, so the aggregator's generic "import my subscriptions" action adds them all. It pages the private GraphQL Following query — keyed on the viewer's own id (from the twid cookie of the imported session) — and returns each followed account as its screen name, the channel form Provider.Feed resolves to that account's tweets.
It satisfies source.FollowImporter. The logged-in auth_token + ct0 cookies are required, and X's rotating query id / expired sessions surface as typed source.AuthError prompts (via gotw.ErrNeedsAuth / gotw.ErrQueryIDRotated) rather than raw errors or a fabricated list.