webtor

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2026 License: MIT Imports: 15 Imported by: 0

README

webtor api-sdk-go

Go SDK for the webtor.io JSON API: store torrents, list their content, resolve streaming/download URLs, manage the account library and Vault — over any of the three API deployments with one client.

import webtor "github.com/webtor-io/api-sdk-go"

backend, _ := webtor.WebUI(os.Getenv("WEBTOR_API_KEY"))
c, _ := webtor.New(backend)

res, _ := c.AddResource(ctx, webtor.Magnet("magnet:?xt=urn:btih:..."))
resp, _ := c.Export(ctx, res.ID, res.File.ID, webtor.ExportOptions{
    Types: []webtor.ExportType{webtor.ExportTypeDownload},
})
url, _ := resp.DownloadURL() // short-lived, self-authorizing — use immediately

Backends

Constructor Deployment Auth Surface
WebUI(apiKey) https://api.webtor.io/v1 (paid plans) Authorization: Bearer resources + library, vault, profile, device flow
RapidAPI(key) https://webtor.p.rapidapi.com X-RapidAPI-Key resources
Direct(baseURL) your own self-hosted rest-api optional pass-through resources

The paths, parameters and response types are identical across all three — only auth and the error dialect differ, and the SDK normalizes both. Client.Supports(webtor.CapLibrary) tells you what the configured backend offers; unsupported calls fail fast with a *CapabilityError.

Highlights

  • Normalized errors — every non-2xx becomes *webtor.Error with a stable Code (not_found, payment_required, rate_limited, …) regardless of the backend's wire dialect. Predicates: webtor.IsNotFound(err) etc.
  • Device-flow loginStartDeviceAuth + WaitDeviceToken implement the RFC 8628 polling protocol; the person confirms a short code on webtor.io and the SDK returns a fresh per-device API key. See examples/device-login.
  • Resumable downloadsOpenDownload returns an io.ReadCloser that transparently re-resolves the expiring export URL and resumes with a Range request on mid-stream failures.
  • Rate-limit aware — automatic Retry-After-honoring backoff on 429.
  • Zero dependencies — the SDK's go.mod has no third-party requirements.

More runnable examples in examples/. The wire types are pinned to the upstream services by the conformance/ test module.

License

MIT

Documentation

Index

Constants

View Source
const (
	// DefaultWebUIBaseURL is the public JSON API of webtor.io. The same
	// routes are also mounted at https://webtor.io/api/v1.
	DefaultWebUIBaseURL = "https://api.webtor.io/v1"
	// DefaultRapidAPIBaseURL is the RapidAPI marketplace endpoint.
	DefaultRapidAPIBaseURL = "https://webtor.p.rapidapi.com"
)

Default endpoints.

View Source
const (
	CodeBadRequest           = "bad_request"
	CodeUnauthorized         = "unauthorized"
	CodeForbidden            = "forbidden"
	CodePaymentRequired      = "payment_required"
	CodeNotFound             = "not_found"
	CodeConflict             = "conflict"
	CodeMethodNotAllowed     = "method_not_allowed"
	CodeRateLimited          = "rate_limited"
	CodeAuthorizationPending = "authorization_pending"
	CodeSlowDown             = "slow_down"
	CodeExpiredToken         = "expired_token"
	CodeUnavailable          = "unavailable"
	CodeInternal             = "internal_error"
	CodeUpstream             = "upstream_error"
	CodeUpstreamTimeout      = "upstream_timeout"
)

Error codes. The web-ui backend sends them verbatim; for the other dialects (rest-api's bare string, RapidAPI's {"message"} and empty bodies) the code is synthesized from the HTTP status, so callers can always branch on Code regardless of the backend.

View Source
const (
	// PledgeStatusWaiting: the pledge exists but the resource is not funded
	// yet, so no transfer has been asked for.
	PledgeStatusWaiting = "waiting"
	// PledgeStatusQueued: funded and handed to storage, transfer not started.
	PledgeStatusQueued = "queued"
	// PledgeStatusStoring: the transfer is running; Progress applies.
	PledgeStatusStoring = "storing"
	// PledgeStatusFailed: the last transfer attempt failed. Terminal for the
	// attempt, not for the resource — storage retries on its own schedule, so
	// keep polling instead of re-pledging.
	PledgeStatusFailed = "failed"
	// PledgeStatusVaulted: the content is stored. Terminal.
	PledgeStatusVaulted = "vaulted"
	// PledgeStatusExpired: the resource lost its funding. Terminal.
	PledgeStatusExpired = "expired"
)

PledgeStatus values for PledgeStatusResponse.Status.

View Source
const DefaultListLimit = 100

DefaultListLimit is the page size used when ListOptions.Limit is zero.

View Source
const MaxTorrentSize = 8 << 20

MaxTorrentSize is the largest .torrent body the API accepts (web-ui enforces it server-side; the SDK enforces it client-side for every backend so oversized uploads fail fast and identically).

View Source
const Version = "0.1.0"

Version of the SDK, used in the default User-Agent.

Variables

View Source
var ErrDeviceAuthExpired = errors.New("webtor: device authorization expired, start over")

ErrDeviceAuthExpired is returned by WaitDeviceToken when the code expired (or was already consumed) before the person confirmed — start over with StartDeviceAuth.

Functions

func IsConflict

func IsConflict(err error) bool

IsConflict reports whether err is an API error with code conflict.

func IsForbidden

func IsForbidden(err error) bool

IsForbidden reports whether err is an API error with code forbidden.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is an API error with code not_found.

func IsPaymentRequired

func IsPaymentRequired(err error) bool

IsPaymentRequired reports whether err is an API error with code payment_required (free tier hitting a paid-only API).

func IsRateLimited

func IsRateLimited(err error) bool

IsRateLimited reports whether err is an API error with code rate_limited.

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized reports whether err is an API error with code unauthorized.

Types

type ArchiveFormat

type ArchiveFormat string

ArchiveFormat selects the container for directory downloads.

const (
	ArchiveFormatZip ArchiveFormat = "zip"
	ArchiveFormatTar ArchiveFormat = "tar"
)

type Backend

type Backend interface {
	BaseURL() *url.URL
	// Authorize sets the backend's auth headers on req. It must not read the
	// body and must be safe to call on retried requests.
	Authorize(req *http.Request)
	Capabilities() Capabilities
	Kind() BackendKind
}

Backend carries everything that differs between the three supported API deployments: where to send requests, how to authorize them, and which API surfaces exist there.

func Direct

func Direct(baseURL string, opts ...DirectOption) (Backend, error)

Direct returns the backend for a self-hosted or in-cluster rest-api instance at baseURL (e.g. "http://localhost:8080"). rest-api itself is unauthenticated; the optional credentials are baked into generated export URLs and checked further down the chain.

func RapidAPI

func RapidAPI(key string, opts ...RapidAPIOption) (Backend, error)

RapidAPI returns the backend for the RapidAPI marketplace. key is the consumer's X-RapidAPI-Key. Only the resource surface is available.

func WebUI

func WebUI(apiKey string, opts ...WebUIOption) (Backend, error)

WebUI returns the backend for webtor.io's account-scoped JSON API. apiKey is the account's API key (issued from the profile page or via the device flow). An empty apiKey yields an unauthenticated client that can only drive the device flow — every other call fails with unauthorized.

type BackendKind

type BackendKind string

BackendKind identifies which of the three supported backends a client talks to.

const (
	// KindWebUI is webtor.io's account-scoped JSON API (default backend).
	KindWebUI BackendKind = "webui"
	// KindRapidAPI is the RapidAPI marketplace gateway.
	KindRapidAPI BackendKind = "rapidapi"
	// KindDirect is a self-hosted / in-cluster rest-api instance.
	KindDirect BackendKind = "direct"
)

type Capabilities

type Capabilities uint32

Capabilities is a bitset of API surfaces a backend supports. The resource surface (add/get/list/export) is universal and has no bit — every backend serves it.

const (
	// CapLibrary: the account library (/library).
	CapLibrary Capabilities = 1 << iota
	// CapVault: long-term storage pledges (/vault).
	CapVault
	// CapProfile: account profile (/profile).
	CapProfile
	// CapDeviceFlow: device authorization (/device/code, /device/token).
	CapDeviceFlow
)

func (Capabilities) String

func (c Capabilities) String() string

type CapabilityError

type CapabilityError struct {
	Backend    BackendKind
	Capability Capabilities
}

CapabilityError is returned — before any HTTP round-trip — when a method needs a capability the configured backend does not have.

func (*CapabilityError) Error

func (e *CapabilityError) Error() string

type Client

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

Client talks to a webtor API backend. Construct with New; the zero value is not usable. All methods are safe for concurrent use.

func New

func New(b Backend, opts ...Option) (*Client, error)

New returns a Client for the given backend.

func (*Client) AddResource

func (c *Client) AddResource(ctx context.Context, src ResourceSource) (*ResourceResponse, error)

AddResource stores a torrent (magnet or .torrent bytes) and returns its descriptor. Adding is content-addressed and idempotent: re-adding the same torrent returns the same resource. A cold magnet blocks until the metadata is resolved from the swarm — up to ~3 minutes; the call is bounded at 4 minutes and is deliberately not retried on timeout (the server-side add keeps running; re-calling AddResource with the same magnet is the way to poll).

func (*Client) Backend

func (c *Client) Backend() Backend

Backend returns the backend the client was constructed with.

func (*Client) Export

func (c *Client) Export(ctx context.Context, resourceID, contentID string, o ExportOptions) (*ExportResponse, error)

Export resolves the short-lived, self-authorizing URLs for one file (or directory) of a resource. contentID is a ListItem.ID, a file's index in the torrent's natural order (ListItem.Index) as a decimal string, or a directory's ID for archive downloads. Every entry of the result map is optional — an export that does not apply to the file is silently absent. The URLs expire: resolve immediately before use and never persist them.

func (*Client) LibraryAdd

func (c *Client) LibraryAdd(ctx context.Context, resourceID string) (*LibraryItem, error)

LibraryAdd adds a stored resource to the account's library. Idempotent: adding an already-present resource succeeds and returns the existing entry.

func (*Client) LibraryGet

func (c *Client) LibraryGet(ctx context.Context, resourceID string) (*LibraryItem, error)

LibraryGet returns the library entry for a resource; a not_found error means the resource is not in the library (the membership check).

func (*Client) LibraryList

LibraryList returns one page of the account's library. Web-ui backend only.

func (*Client) LibraryRemove

func (c *Client) LibraryRemove(ctx context.Context, resourceID string) error

LibraryRemove removes a resource from the library. Not idempotent: removing an absent entry returns a not_found error.

func (*Client) LibraryRename

func (c *Client) LibraryRename(ctx context.Context, resourceID, name string) (*LibraryItem, error)

LibraryRename renames a library entry (the name shown in the library UI, WebDAV and S3 views alike).

func (*Client) List

func (c *Client) List(ctx context.Context, resourceID string, o ListOptions) (*ListResponse, error)

List returns one page of a resource's content listing.

func (*Client) ListAll

func (c *Client) ListAll(ctx context.Context, resourceID string, o ListOptions) func(yield func(ListItem, error) bool)

ListAll iterates every item of a listing, paging transparently. Iteration stops at the first error, yielded with a zero ListItem.

func (*Client) OpenArchive

func (c *Client) OpenArchive(ctx context.Context, resourceID, contentID string, format ArchiveFormat, paths []string) (io.ReadCloser, string, error)

OpenArchive opens a directory (or a selection of paths inside it) as a single archive stream. Unlike OpenDownload it cannot resume: the archive is packed on the fly and a re-request is not guaranteed byte-identical. contentID addresses the directory ("" or the root ID for the whole torrent).

func (*Client) OpenDownload

func (c *Client) OpenDownload(ctx context.Context, resourceID, contentID string, opts ...DownloadOption) (*Download, error)

OpenDownload opens the content of one file for reading. contentID is a ListItem.ID or a file index as a decimal string. The export URL is resolved immediately before the GET and re-resolved on resume — the URLs are short-lived and must never be persisted.

func (*Client) Profile

func (c *Client) Profile(ctx context.Context) (*ProfileResponse, error)

Profile returns the authenticated account. Web-ui backend only.

func (*Client) Resource

func (c *Client) Resource(ctx context.Context, resourceID string) (*ResourceResponse, error)

Resource returns the descriptor of a stored torrent. Single-file torrents carry File, so no List round-trip is needed to address their content.

func (*Client) StartDeviceAuth

func (c *Client) StartDeviceAuth(ctx context.Context, deviceName string) (*DeviceAuth, error)

StartDeviceAuth begins the device authorization flow (RFC 8628 shaped). deviceName labels the resulting key on the account's "connected devices" list — use something recognizable like "webtor-cli @ hostname". The call needs no API key. Web-ui backend only.

func (*Client) Supports

func (c *Client) Supports(caps Capabilities) bool

Supports reports whether the configured backend has every given capability.

func (*Client) TorrentFile

func (c *Client) TorrentFile(ctx context.Context, resourceID string) ([]byte, error)

TorrentFile returns the raw .torrent bytes of a stored resource.

func (*Client) UpdateProfile

func (c *Client) UpdateProfile(ctx context.Context, u ProfileUpdate) (*ProfileResponse, error)

UpdateProfile patches account settings and returns the updated profile.

func (*Client) Vault

func (c *Client) Vault(ctx context.Context) (*VaultResponse, error)

Vault returns the account's Vault state: point balance, content counters and all pledges. Web-ui backend only.

func (*Client) VaultPledge

func (c *Client) VaultPledge(ctx context.Context, resourceID string) (*Pledge, error)

VaultPledge pledges Vault points to keep a resource stored long-term (1 point per GB). A payment_required/forbidden error means insufficient points; a conflict error means a pledge already exists.

func (*Client) VaultPledgeStatus

func (c *Client) VaultPledgeStatus(ctx context.Context, resourceID string) (*PledgeStatusResponse, error)

VaultPledgeStatus returns a pledge and where its transfer stands. Poll it every 10–30 seconds while waiting for a transfer; a failed status is terminal for the attempt, not the resource — storage retries on its own schedule, so keep polling instead of re-pledging.

func (*Client) VaultUnpledge

func (c *Client) VaultUnpledge(ctx context.Context, resourceID string) error

VaultUnpledge withdraws a pledge and claims its points back. A conflict error means the pledge is frozen and cannot be withdrawn yet.

func (*Client) WaitDeviceToken

func (c *Client) WaitDeviceToken(ctx context.Context, da *DeviceAuth, onTick func()) (string, error)

WaitDeviceToken polls until the person confirms the device on the website and returns the freshly issued API key. The key is delivered exactly once — persist it before doing anything else. onTick, when non-nil, is called before each poll (drive a spinner with it). Polling paces itself by the server-announced interval, backs off on slow_down, and stops on context cancellation or code expiry.

type DeviceAuth

type DeviceAuth struct {
	UserCode                string
	VerificationURI         string
	VerificationURIComplete string
	ExpiresAt               time.Time
	// contains filtered or unexported fields
}

DeviceAuth is an in-flight device authorization. Show UserCode and VerificationURI to the person (or open VerificationURIComplete in a browser / render it as a QR code), then call WaitDeviceToken.

type DeviceCodeResponse

type DeviceCodeResponse struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURI         string `json:"verification_uri"`
	VerificationURIComplete string `json:"verification_uri_complete"`
	ExpiresIn               int    `json:"expires_in"`
	Interval                int    `json:"interval"`
}

DeviceCodeResponse starts a device authorization (RFC 8628).

type DeviceTokenResponse

type DeviceTokenResponse struct {
	Key string `json:"key"`
}

DeviceTokenResponse delivers the API key. It is delivered exactly once — persist it before doing anything else.

type DirectOption

type DirectOption func(*directConfig)

DirectOption configures the Direct backend.

func WithDirectAPIKey

func WithDirectAPIKey(k string) DirectOption

WithDirectAPIKey sets the pass-through api-key that rest-api embeds into the export URLs it generates (validated downstream, not by rest-api).

func WithDirectToken

func WithDirectToken(t string) DirectOption

WithDirectToken sets the pass-through JWT that rest-api embeds into the export URLs it generates.

type Download

type Download struct {
	// Name is the file's name, Size its total length in bytes.
	Name string
	Size int64
	// contains filtered or unexported fields
}

Download is a resumable byte stream of one file. It implements io.ReadCloser; on a mid-stream failure (or expiry of the short-lived export URL) it transparently re-resolves a fresh URL and resumes with a Range request, up to 5 times. The context passed to OpenDownload governs the whole stream.

func (*Download) BytesRead

func (d *Download) BytesRead() int64

BytesRead returns how many bytes have been delivered so far (not counting the starting offset). Safe to call concurrently with Read for progress reporting.

func (*Download) Close

func (d *Download) Close() error

Close releases the underlying connection.

func (*Download) Read

func (d *Download) Read(p []byte) (int, error)

Read implements io.Reader with transparent resume.

type DownloadOption

type DownloadOption func(*downloadConfig)

DownloadOption configures OpenDownload.

func WithOffset

func WithOffset(n int64) DownloadOption

WithOffset starts the download at byte n (resume of a partial file).

type Error

type Error struct {
	// HTTPStatus is the response status code.
	HTTPStatus int
	// Code is a stable machine-readable code (see the Code* constants).
	// Always populated: synthesized from HTTPStatus when the backend's error
	// dialect does not carry one.
	Code string
	// Message is the human-readable message, when the backend sent one.
	Message string
	// RetryAfter is the server-requested pause before retrying; non-zero only
	// on rate-limited responses that carried a Retry-After header.
	RetryAfter time.Duration
}

Error is an API error normalized across the three backend dialects.

func (*Error) Error

func (e *Error) Error() string

type ExportItem

type ExportItem struct {
	URL  string      `json:"url,omitempty"`
	Tag  *ExportTag  `json:"html_tag,omitempty"`
	Meta *ExportMeta `json:"meta,omitempty"`
}

ExportItem is one export of a file: a short-lived, self-authorizing URL plus optional presentation metadata. Never persist the URL — resolve a fresh one right before use.

type ExportMeta

type ExportMeta struct {
	Transcode      bool `json:"transcode,omitempty"`
	Multibitrate   bool `json:"multibitrate,omitempty"`
	Cache          bool `json:"cache,omitempty"`
	TranscodeCache bool `json:"transcode_cache,omitempty"`
}

ExportMeta carries flags about how the export will be served.

type ExportOptions

type ExportOptions struct {
	// Types filters which exports to produce; empty means all. The SDK uses
	// the `types` parameter, which every backend understands (web-ui's
	// `output` parameter is deliberately not exposed — it does not exist on
	// the other backends).
	Types []ExportType
	// ArchiveFormat picks the archive container for directory downloads:
	// "zip" (default server-side) or "tar".
	ArchiveFormat string
	// Paths restricts a directory archive to the given paths.
	Paths []string
	// IMDBID improves subtitle lookup for the subtitles export.
	IMDBID string
}

ExportOptions parameterize Export.

type ExportResponse

type ExportResponse struct {
	Source  ListItem                  `json:"source"`
	Exports map[ExportType]ExportItem `json:"exports"`
}

ExportResponse is the answer to an export request.

func (*ExportResponse) Cached

func (r *ExportResponse) Cached() bool

Cached reports whether the content is already fully cached server-side, so a download starts instantly instead of waiting on the swarm. Absence of the torrent_client_stat export means the same thing.

func (*ExportResponse) DownloadURL

func (r *ExportResponse) DownloadURL() (string, bool)

DownloadURL returns the plain-bytes URL, if the download export is present.

func (*ExportResponse) StreamURL

func (r *ExportResponse) StreamURL() (string, bool)

StreamURL returns the streaming (HLS) URL, if the stream export is present.

type ExportSource

type ExportSource struct {
	Src  string `json:"src"`
	Type string `json:"type"`
}

ExportSource is one playable source of an ExportTag.

type ExportTag

type ExportTag struct {
	Name    string         `json:"tag,omitempty"`
	Preload string         `json:"preload,omitempty"`
	Sources []ExportSource `json:"sources,omitempty"`
	Tracks  []ExportTrack  `json:"tracks,omitempty"`
	Src     string         `json:"src,omitempty"`
	Alt     string         `json:"alt,omitempty"`
	Poster  string         `json:"poster,omitempty"`
}

ExportTag is a ready-to-render HTML media tag descriptor.

type ExportTrack

type ExportTrack struct {
	Src     string `json:"src"`
	Kind    string `json:"kind"`
	SrcLang string `json:"srclang,omitempty"`
	Label   string `json:"label,omitempty"`
}

ExportTrack is a side-car track (subtitles) of an ExportTag.

type ExportType

type ExportType string

ExportType names an export flavor in ExportResponse.Exports. Every entry is optional: an export that does not apply to the file is silently absent.

const (
	ExportTypeDownload          ExportType = "download"
	ExportTypeStream            ExportType = "stream"
	ExportTypeTorrentClientStat ExportType = "torrent_client_stat"
	ExportTypeSubtitles         ExportType = "subtitles"
	ExportTypeMediaProbe        ExportType = "media_probe"
)

type LibraryItem

type LibraryItem struct {
	ResourceID string    `json:"resource_id"`
	Name       string    `json:"name"`
	Size       int64     `json:"size"`
	FilesCount int       `json:"files_count"`
	AddedAt    time.Time `json:"added_at"`
}

LibraryItem is a torrent saved to the account's library (web-ui only).

type LibraryListOptions

type LibraryListOptions struct {
	Type LibraryType // default all
	Sort LibrarySort // default recent
	// Limit is the page size; 0 keeps the server default (100, max 1000).
	Limit  int
	Offset int
}

LibraryListOptions parameterize LibraryList.

type LibraryListResponse

type LibraryListResponse struct {
	Items  []LibraryItem `json:"items"`
	Count  int           `json:"items_count"`
	Limit  int           `json:"limit"`
	Offset int           `json:"offset"`
	Type   string        `json:"type"`
	Sort   string        `json:"sort"`
}

LibraryListResponse is one page of the account's library.

type LibrarySort

type LibrarySort string

LibrarySort orders a library listing.

const (
	LibrarySortRecent LibrarySort = "recent"
	LibrarySortName   LibrarySort = "name"
)

type LibraryType

type LibraryType string

LibraryType filters a library listing by content kind.

const (
	LibraryTypeAll    LibraryType = "all"
	LibraryTypeMovies LibraryType = "movies"
	LibraryTypeSeries LibraryType = "series"
)

type ListItem

type ListItem struct {
	ID          string      `json:"id"`
	Name        string      `json:"name,omitempty"`
	Path        string      `json:"path"`
	Type        ListType    `json:"type"`
	Size        int64       `json:"size"`
	MediaFormat MediaFormat `json:"media_format,omitempty"`
	MimeType    string      `json:"mime_type,omitempty"`
	Ext         string      `json:"ext,omitempty"`
	// Index is the file's position in the torrent's natural file order, i.e.
	// the content_id accepted by /resource/<hash>/export/<idx>. Valid only
	// for Type == file items; directory items leave it zero.
	Index int `json:"index"`
}

ListItem is a single entry (file or directory) of a torrent listing.

type ListOptions

type ListOptions struct {
	// Path scopes a tree listing to a directory ("" = root).
	Path string
	// Limit is the page size. 0 means DefaultListLimit. The SDK always sends
	// it explicitly: the backends' server-side defaults disagree (10 on
	// web-ui vs 1000 on rest-api).
	Limit  int
	Offset int
	// Output defaults to ListOutputFlat.
	Output ListOutput
	// Sort defaults to the torrent's natural file order.
	Sort ListSort
}

ListOptions parameterize List.

type ListOutput

type ListOutput string

ListOutput selects the shape of a listing.

const (
	// ListOutputFlat is the flat file list (directories omitted).
	ListOutputFlat ListOutput = "list"
	// ListOutputTree lists one directory level at Path.
	ListOutputTree ListOutput = "tree"
)

type ListResponse

type ListResponse struct {
	ListItem
	Items []ListItem `json:"items"`
	Count int        `json:"items_count"`
}

ListResponse is the answer to a listing request. The embedded ListItem describes the listed node itself (the root or the directory at Path).

type ListSort

type ListSort string

ListSort orders a listing. The zero value keeps the torrent's natural file order.

const (
	ListSortName ListSort = "name"
	ListSortSize ListSort = "size"
)

type ListType

type ListType string

ListType discriminates entries of a torrent listing.

const (
	ListTypeFile      ListType = "file"
	ListTypeDirectory ListType = "directory"
)

type MediaFormat

type MediaFormat string

MediaFormat is the coarse media class of a file as detected by the backend.

const (
	MediaFormatAudio    MediaFormat = "audio"
	MediaFormatVideo    MediaFormat = "video"
	MediaFormatImage    MediaFormat = "image"
	MediaFormatSubtitle MediaFormat = "subtitle"
)

type Option

type Option func(*Client)

Option configures a Client.

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient replaces the underlying *http.Client. The client's Timeout is left untouched; per-call deadlines come from the context and from the SDK's own long-call overrides (AddResource).

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger enables debug logging of requests and retries.

func WithRetry

func WithRetry(p RetryPolicy) Option

WithRetry replaces the default retry policy.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent replaces the default User-Agent header.

type Pledge

type Pledge struct {
	PledgeID   string    `json:"pledge_id"`
	ResourceID string    `json:"resource_id"`
	Name       string    `json:"name,omitempty"`
	Amount     float64   `json:"amount"`
	Frozen     bool      `json:"frozen"`
	Funded     bool      `json:"funded"`
	Vaulted    bool      `json:"vaulted"`
	Expired    bool      `json:"expired"`
	RequiredVP float64   `json:"required_vp"`
	FundedVP   float64   `json:"funded_vp"`
	CreatedAt  time.Time `json:"created_at"`
}

Pledge is a commitment of Vault points to keep a torrent stored.

type PledgeStatusResponse

type PledgeStatusResponse struct {
	Pledge
	Status     string   `json:"status"`
	Progress   *float64 `json:"progress,omitempty"`
	StoredSize *int64   `json:"stored_size,omitempty"`
	TotalSize  *int64   `json:"total_size,omitempty"`
}

PledgeStatusResponse is a pledge plus where its transfer stands. Progress and the sizes are nil when there is no transfer to measure (waiting, expired) — 0 would read as "started".

type ProfileResponse

type ProfileResponse struct {
	UserID   string          `json:"user_id"`
	Email    string          `json:"email,omitempty"`
	Tier     ProfileTier     `json:"tier"`
	Settings ProfileSettings `json:"settings"`
	Scopes   []string        `json:"scopes"`
}

ProfileResponse describes the authenticated account.

type ProfileSettings

type ProfileSettings struct {
	ShowAdult bool `json:"show_adult"`
}

ProfileSettings are the account settings exposed over the API.

type ProfileTier

type ProfileTier struct {
	ID   uint32 `json:"id"`
	Name string `json:"name,omitempty"`
}

ProfileTier is the account's subscription tier.

type ProfileUpdate

type ProfileUpdate struct {
	ShowAdult *bool `json:"show_adult,omitempty"`
}

ProfileUpdate carries the updatable account settings. Nil fields are left untouched.

type RapidAPIOption

type RapidAPIOption func(*rapidAPIConfig)

RapidAPIOption configures the RapidAPI backend.

func WithRapidAPIBaseURL

func WithRapidAPIBaseURL(u string) RapidAPIOption

WithRapidAPIBaseURL overrides the marketplace endpoint (tests, mocks). The X-RapidAPI-Host header keeps naming the real marketplace host.

type ResourceResponse

type ResourceResponse struct {
	ID        string `json:"id"`
	Name      string `json:"name,omitempty"`
	MagnetURI string `json:"magnet_uri,omitempty"`
	// MultiFile is false for single-file-mode torrents (one file sitting at
	// the torrent root).
	MultiFile bool `json:"multi_file"`
	// File is the single file of a single-file torrent (nil when MultiFile).
	// Lets clients skip List for the common single-file case.
	File *ListItem `json:"file,omitempty"`
	// Size is the torrent's total size in bytes (sum of all files).
	Size int64 `json:"size"`
	// FilesCount is the number of files in the torrent.
	FilesCount int `json:"files_count"`
}

ResourceResponse describes a stored torrent.

type ResourceSource

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

ResourceSource is the payload of AddResource: a magnet link or the raw bytes of a .torrent file. Construct with Magnet, TorrentBytes or TorrentReader.

func Magnet

func Magnet(uri string) ResourceSource

Magnet turns a magnet URI — or a bare 40-hex infohash — into a ResourceSource.

func TorrentBytes

func TorrentBytes(b []byte) ResourceSource

TorrentBytes wraps the raw bytes of a .torrent file.

func TorrentReader

func TorrentReader(r io.Reader) ResourceSource

TorrentReader reads a .torrent from r (e.g. stdin), enforcing the size limit while reading.

type RetryPolicy

type RetryPolicy struct {
	// MaxAttempts is the total number of attempts (1 = no retries).
	MaxAttempts int
	// BaseWait is the first backoff wait; it doubles per retry with jitter.
	BaseWait time.Duration
	// MaxWait caps a single wait, including server-requested Retry-After.
	MaxWait time.Duration
}

RetryPolicy controls automatic retries. Retries apply to rate limiting (429, honoring Retry-After) on every method, and additionally to transient upstream failures (upstream_error, unavailable, upstream_timeout, network errors) on idempotent methods (GET/HEAD). POST /resource is never retried on a timeout: the server-side add keeps running, and re-POSTing the same magnet is the caller's naturally idempotent way to poll.

func DefaultRetryPolicy

func DefaultRetryPolicy() RetryPolicy

DefaultRetryPolicy returns the policy used when none is configured: 3 attempts, 500ms base backoff, 30s cap.

type VaultContent

type VaultContent struct {
	Vaulted  int `json:"vaulted"`
	Loading  int `json:"loading"`
	Expiring int `json:"expiring"`
}

VaultContent counts the account's vaulted content by state.

type VaultPoints

type VaultPoints struct {
	Total     *float64 `json:"total"`
	Available *float64 `json:"available"`
	Funded    float64  `json:"funded"`
	Frozen    float64  `json:"frozen"`
	Claimable float64  `json:"claimable"`
}

VaultPoints is the account's Vault point balance. Total and Available are nil on unlimited plans.

type VaultResponse

type VaultResponse struct {
	Points  VaultPoints  `json:"points"`
	Content VaultContent `json:"content"`
	Pledges []Pledge     `json:"pledges"`
}

VaultResponse is the account's full Vault state.

type WebUIOption

type WebUIOption func(*webUIConfig)

WebUIOption configures the WebUI backend.

func WithWebUIBaseURL

func WithWebUIBaseURL(u string) WebUIOption

WithWebUIBaseURL points the backend at a staging or self-hosted web-ui (e.g. "https://example.com/api/v1"). The URL must include the /v1 mount.

Directories

Path Synopsis
examples
add-and-download command
Command add-and-download stores a magnet and downloads its largest file.
Command add-and-download stores a magnet and downloads its largest file.
device-login command
Command device-login obtains an API key via the device authorization flow and prints it.
Command device-login obtains an API key via the device authorization flow and prints it.
vault-wait command
Command vault-wait pledges a resource to the Vault and waits until the transfer completes.
Command vault-wait pledges a resource to the Vault and waits until the transfer completes.

Jump to

Keyboard shortcuts

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