read

package
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package read implements the X read surfaces: timelines, search, threads, bookmarks and lists.

Index

Constants

View Source
const (
	DefaultLimit = 8
	MaxLimit     = 50
)

Limits on how much a single call may ask for.

Variables

This section is empty.

Functions

func ClampLimit

func ClampLimit(n int) int

ClampLimit brings a caller-supplied limit into range.

Types

type InvalidError added in v0.0.8

type InvalidError struct{ Reason string }

InvalidError marks a request the caller got wrong -- a missing handle, a URL this cannot read. It is not a server fault and repeating it will not help.

func (*InvalidError) Error added in v0.0.8

func (e *InvalidError) Error() string

type Lease added in v0.0.5

type Lease func(ctx context.Context) (*browser.Session, func(), error)

Lease borrows a browser session and returns a function that hands it back.

Reads borrow rather than open so a warm browser can be shared between them: launching and quitting Chrome costs about 1.8s per read on its own, before the slower cold page loads.

type NotFoundError added in v0.0.8

type NotFoundError struct{ Reason string }

NotFoundError marks a surface X had nothing on. A list id that does not exist is the caller asking for something absent, not the server failing.

func (*NotFoundError) Error added in v0.0.8

func (e *NotFoundError) Error() string

type NotificationResult added in v0.0.9

type NotificationResult struct {
	Notifications []model.Notification `json:"notifications"`
	FetchedAt     time.Time            `json:"fetched_at"`
	Cached        bool                 `json:"cached"`
}

NotificationResult is a page of notifications.

There is no Contributors here as there is for posts: a notification names its own actors, and several of them for an aggregated cell, so ranking accounts across the page would be counting the same like twice.

type Options

type Options struct {
	Lease    Lease
	Auth     *auth.Manager
	Budget   *limit.Budget
	CacheFor time.Duration
	Timeout  time.Duration
}

Options configures a Reader.

type Query

type Query struct {
	Text  string
	Mode  xui.SearchMode
	Limit int
}

Query describes a search request.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader reads X through a browser.

func New

func New(opts Options) *Reader

New builds a Reader.

func (*Reader) Bookmarks

func (r *Reader) Bookmarks(ctx context.Context, n int) (Result, error)

Bookmarks reads the signed-in account's saved posts.

func (*Reader) FromURL added in v0.0.2

func (r *Reader) FromURL(ctx context.Context, raw string, n int) (Resolved, error)

FromURL reads whatever an x.com URL points at.

Callers paste links rather than assembling handle/id pairs, so this is the entry point that matches how the tools are actually used. A post URL yields a thread; a profile, list, bookmarks or search URL yields that timeline.

func (*Reader) Home

func (r *Reader) Home(ctx context.Context, n int) (Result, error)

func (*Reader) Invalidate added in v0.0.5

func (r *Reader) Invalidate()

Home reads the signed-in home timeline. Invalidate drops every cached result.

A write changes what the next read should return -- a new post belongs in the timeline, a like belongs on the post -- and serving the pre-write copy for the rest of the TTL makes the write look like it did not happen.

func (*Reader) List

func (r *Reader) List(ctx context.Context, listID string, n int) (Result, error)

List reads a curated list's timeline.

func (*Reader) Mentions added in v0.0.9

func (r *Reader) Mentions(ctx context.Context, n int) (Result, error)

Mentions reads the notifications tab that holds posts.

Mentions are ordinary posts, so this is the ordinary post path pointed at a different URL. Notifications are not, and take their own.

func (*Reader) Notifications added in v0.0.9

func (r *Reader) Notifications(ctx context.Context, n int) (NotificationResult, error)

Notifications reads the "All" tab: likes, follows, reposts and X's own recommendations.

Almost none of these are posts. On a real account, seventeen of eighteen cells held no post at all, so reading this page with the post extractor would return the one and quietly present it as the lot.

func (*Reader) Search

func (r *Reader) Search(ctx context.Context, q Query) (Result, error)

Search reads recent posts matching a query.

func (*Reader) Thread

func (r *Reader) Thread(ctx context.Context, handle, postID string, n int) (model.Thread, error)

Thread reads a post together with the replies shown beneath it.

X renders the root and its replies as the same kind of article, so the first post on the page is the root and the rest are replies.

func (*Reader) UserPosts

func (r *Reader) UserPosts(ctx context.Context, handle string, n int) (Result, error)

UserPosts reads an account's own timeline.

type Resolved added in v0.0.9

type Resolved struct {
	Kind          xui.TargetKind      `json:"kind"`
	Posts         *Result             `json:"posts,omitempty"`
	Thread        *model.Thread       `json:"thread,omitempty"`
	Notifications *NotificationResult `json:"notifications,omitempty"`
}

Resolved is what a URL turned out to point at.

The kind is returned rather than inferred. The caller used to work it out by checking whether a thread had a root, which is indistinguishable from a thread that failed to render -- and there is now a third shape, since a notification is neither a post nor a thread.

type Result

type Result struct {
	Posts        []model.Post        `json:"posts"`
	Contributors []model.Contributor `json:"contributors"`
	FetchedAt    time.Time           `json:"fetched_at"`
	Cached       bool                `json:"cached"`
}

Result is a set of posts plus the accounts that produced them.

Jump to

Keyboard shortcuts

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