stremio

package
v0.3.3 Latest Latest
Warning

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

Go to latest
Published: Nov 4, 2026 License: GPL-3.0 Imports: 27 Imported by: 0

Documentation

Overview

Package stremio is the Stremio add-on protocol, and the only model of it in Ether: manifests, routes and ids, and decoding every resource (streams into releases, catalogs, metas, subtitles, `tv` channels and their guide).

It owns no network client. An Addon reads routes through a Fetcher; in the server that is the plugin manager's remote runtime, which guards, meters, redacts and health-checks every call to an installed add-on (internal/plugins). Ether ships no add-on URLs: the owner pastes the install link of an add-on they chose.

Index

Constants

View Source
const (
	MaxManifestBytes  = 1 << 20
	MaxStreamsBytes   = 8 << 20
	MaxCatalogBytes   = 8 << 20
	MaxMetaBytes      = 4 << 20
	MaxSubtitlesBytes = 2 << 20
	// MaxCatalogItems bounds one catalog read.
	MaxCatalogItems = 2000
)

Response size limits per route.

View Source
const (
	ResourceCatalog      = "catalog"
	ResourceMeta         = "meta"
	ResourceStream       = "stream"
	ResourceSubtitles    = "subtitles"
	ResourceAddonCatalog = "addon_catalog"
)

Resource names: the protocol's routes.

View Source
const (
	TypeMovie  = "movie"
	TypeSeries = "series"
	TypeTV     = "tv"
)

Content types Ether maps.

Variables

View Source
var ErrConfigurationRequired = errors.New("the add-on must be configured first: open its configure page and paste the install link it gives you")

ErrConfigurationRequired is returned for an add-on installed from its unconfigured link.

Functions

func BaseURL

func BaseURL(raw string) (*url.URL, error)

BaseURL returns an addon's base URL from its install URL: a stremio:// link becomes https://, and a trailing /manifest.json or /configure is removed. The path keeps the addon's settings segment, if any.

func DefaultNZBClient added in v0.3.3

func DefaultNZBClient() *http.Client

DefaultNZBClient is the guarded client add-on NZBs are downloaded with.

func FetchNZB added in v0.3.3

func FetchNZB(ctx context.Context, client *http.Client, origin string, r core.Release, reserve func(context.Context, string) error) ([]byte, error)

FetchNZB downloads an add-on Usenet stream's NZB with client, trusting only the add-on's own origin (see Backend.FetchNZB). Installed add-ons (internal/plugins/adapters) fetch their NZBs through it too.

func Fingerprint added in v0.3.3

func Fingerprint(base *url.URL) string

Fingerprint identifies one configured add-on: its normalised link. Two configurations of the same add-on differ; the same link pasted on two pages is the same add-on.

func IMDbID added in v0.3.3

func IMDbID(id string) string

IMDbID normalises an IMDb id to "tt" + digits, or "".

func ManifestURL added in v0.3.3

func ManifestURL(base *url.URL) string

ManifestURL is the manifest address of a normalised base URL.

func NormalizeURL added in v0.3.3

func NormalizeURL(raw string) (*url.URL, error)

NormalizeURL turns an install link into the add-on's base URL: a stremio:// link becomes https://, a trailing /manifest.json or /configure is removed, and the query (some add-ons keep their configuration there) is kept. User info and fragments are dropped.

func Origin added in v0.3.3

func Origin(base *url.URL) string

Origin is the base URL's scheme://host[:port].

func ParseCatalogRef added in v0.3.3

func ParseCatalogRef(id string) (imdb string, tmdb, tvdb int64)

ParseCatalogRef reads an external identity from a catalog id: "tt…" or "imdb:tt…" → IMDb; "tmdb:550", "tmdb:movie:550" → TMDB; "tvdb:N" → TVDB. Series ids may carry ":season:episode"; the show id leads.

func ResourceURL added in v0.3.3

func ResourceURL(base *url.URL, route string) string

ResourceURL joins a route path ("/stream/movie/tt1.json") to a base URL, keeping the base's escaping and query.

func Route added in v0.3.3

func Route(resource, typ, id string, extra map[string]string) string

Route builds a resource route: /{resource}/{type}/{id}[/{extra}].json. Extras are sorted and query-escaped, as the Stremio SDK writes them.

func TitleID added in v0.3.3

func TitleID(t *core.Title) (typ, id string, ok bool)

TitleID is the content id the protocol uses for a catalogue title: IMDb when known, else tmdb:N. Episodes add ":season:episode" to their show's id. ok is false when the title has neither id.

Types

type Addon added in v0.3.3

type Addon struct {
	Manifest Manifest
	Fetcher  Fetcher
}

Addon is one installed add-on: its manifest and how to reach it.

func (Addon) Catalog added in v0.3.3

func (a Addon) Catalog(ctx context.Context, c Catalog, extra map[string]string, maxItems int) ([]MetaPreview, error)

Catalog reads a whole catalog, paging with skip when the catalog declares it, until an empty page, a page of only duplicates (an add-on ignoring skip), hasMore false, a 404 after the first page, or maxItems (clamped to MaxCatalogItems). Duplicate ids keep their first place.

func (Addon) CatalogPage added in v0.3.3

func (a Addon) CatalogPage(ctx context.Context, typ, id string, extra map[string]string) (metas []MetaPreview, hasMore *bool, err error)

CatalogPage reads one catalog page. hasMore is the add-on's own hint (nil when absent).

func (Addon) GuideCatalog added in v0.3.3

func (a Addon) GuideCatalog(ctx context.Context, id, date string) ([]Meta, error)

GuideCatalog reads a `tv` catalog's dated guide pages (the epgProvider extension), which answer detailed metas instead of previews.

func (Addon) Meta added in v0.3.3

func (a Addon) Meta(ctx context.Context, typ, id string) (Meta, error)

Meta reads meta/{type}/{id}.json.

func (Addon) Streams added in v0.3.3

func (a Addon) Streams(ctx context.Context, look Lookup) ([]Stream, error)

Streams reads the streams for a lookup.

func (Addon) StreamsFor added in v0.3.3

func (a Addon) StreamsFor(ctx context.Context, typ, id string) ([]Stream, error)

StreamsFor reads stream/{type}/{id}.json.

func (Addon) Subtitles added in v0.3.3

func (a Addon) Subtitles(ctx context.Context, typ, id string, extra map[string]string) ([]Subtitle, error)

Subtitles lists subtitles/{type}/{id}[/extra].json. Listing only: nothing is downloaded here.

type AnimeIDs added in v0.2.44

type AnimeIDs interface {
	Lookup(ctx context.Context, req core.SearchRequest, db string) (id int64, episode int, ok bool, err error)
}

AnimeIDs maps a TMDB request to an anime database id (Kitsu, MAL, AniList, AniDB) for addons that look anime up only by those ids. Implemented by *animemap.Service.

type Backend

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

Backend is a newznab.Backend for one Stremio addon: the indexer Client keeps budgets, the result cache, rate-limit pauses and events around it.

func (*Backend) FetchNZB

func (b *Backend) FetchNZB(ctx context.Context, r core.Release, reserve func(context.Context, string) error) ([]byte, error)

FetchNZB implements newznab.Backend for an addon's Usenet streams: it downloads the stream's NZB. The addon's own origin is trusted (a self-hosted addon on the LAN); any other host, and every redirect hop, must be public. Errors name the host only. Whatever the server answers is transient (core.ErrSourceUnavailable): a login page or an oversized body today says nothing permanent about the release. Only a release without a usable NZB link is rejected (core.ErrReleaseRejected).

func (*Backend) ResolveTorrent

func (b *Backend) ResolveTorrent(_ context.Context, r core.Release, _ func(context.Context, string) error) (core.Release, error)

ResolveTorrent implements newznab.Backend. Every addon result already carries its info hash and magnet.

func (*Backend) Search

func (b *Backend) Search(ctx context.Context, req core.SearchRequest, reserve func(context.Context, string) error) ([]core.Release, error)

Search implements newznab.Backend. Movies are looked up by id and episodes by id, season and episode (lookupID: IMDb, else TMDB, else a mapped anime database id); a season-level request (Episode 0) asks for the season's first episode and keeps whole-season packs. Titles the addon cannot be asked about, and show-level requests, have no answer.

type BehaviorHints added in v0.3.3

type BehaviorHints struct {
	Adult                 bool   `json:"adult,omitempty"`
	P2P                   bool   `json:"p2p,omitempty"`
	Configurable          bool   `json:"configurable,omitempty"`
	ConfigurationRequired bool   `json:"configurationRequired,omitempty"`
	EpgURL                string `json:"epgUrl,omitempty"`
	EPGProvider           bool   `json:"epgProvider,omitempty"`
}

BehaviorHints is the manifest's behaviorHints. EpgURL (an XMLTV guide) and EPGProvider (dated guide catalogs) are extensions some `tv` add-ons use.

type Catalog added in v0.3.3

type Catalog struct {
	Type   string   `json:"type"`
	ID     string   `json:"id"`
	Name   string   `json:"name,omitempty"`
	Genres []string `json:"genres,omitempty"`
	Extra  []Extra  `json:"extra,omitempty"`
	// ExtraSupported and ExtraRequired are the protocol's older way of
	// declaring extras; Extras reads both forms.
	ExtraSupported []string `json:"extraSupported,omitempty"`
	ExtraRequired  []string `json:"extraRequired,omitempty"`
}

Catalog is one catalog (or add-on catalog) declaration.

func (Catalog) ExtraNamed added in v0.3.3

func (c Catalog) ExtraNamed(name string) (Extra, bool)

ExtraNamed returns the catalog's extra called name.

func (Catalog) Extras added in v0.3.3

func (c Catalog) Extras() []Extra

Extras returns the catalog's extras in the current form, folding in the older extraSupported/extraRequired lists.

func (Catalog) Key added in v0.3.3

func (c Catalog) Key() string

Key is a stable identifier for a catalog within one add-on.

func (Catalog) SupportsSkip added in v0.3.3

func (c Catalog) SupportsSkip() bool

SupportsSkip reports whether the catalog pages with skip. `tv` catalogs page by convention even when they do not declare it.

func (Catalog) ValidateExtras added in v0.3.3

func (c Catalog) ValidateExtras(extra map[string]string) error

ValidateExtras checks catalog extras against the declaration: required extras present, options respected, nothing undeclared. skip is the paging extra the reader adds itself.

type ConvertOptions added in v0.3.3

type ConvertOptions struct {
	// Origin is the add-on's own scheme://host[:port], the one private
	// address its stream URLs may reach.
	Origin string
	// Instance identifies the configured add-on in HTTP and NZB GUIDs.
	Instance string
}

ConvertOptions carry what Convert needs beyond the streams.

type Converted added in v0.3.3

type Converted struct {
	Releases         []core.Release
	Source           []int
	SkippedNoHash    int
	SkippedAmbiguous int
}

Converted is the outcome of Convert. Source[i] is the index of the stream Releases[i] came from.

func Convert added in v0.3.3

func Convert(streams []Stream, req core.SearchRequest, look Lookup, opts ConvertOptions) Converted

Convert turns an add-on's streams into releases exactly as the Stremio indexer does (convertWith).

type Extra added in v0.3.3

type Extra struct {
	Name         string   `json:"name"`
	IsRequired   bool     `json:"isRequired,omitempty"`
	Options      []string `json:"options,omitempty"`
	OptionsLimit int      `json:"optionsLimit,omitempty"`
}

Extra is one extra property a catalog accepts (search, genre, skip…).

type Fetcher added in v0.3.3

type Fetcher interface {
	Fetch(ctx context.Context, route string, limit int64) ([]byte, error)
}

Fetcher reads one route of an add-on ("/stream/movie/tt1.json"). A non-2xx answer is an *HTTPError. limit bounds the body.

type HTTPError added in v0.3.3

type HTTPError struct {
	Status     int
	RetryAfter string
}

HTTPError is a non-2xx add-on answer. It names no URL: add-on links carry the owner's configuration, often a debrid key.

func (*HTTPError) Error added in v0.3.3

func (e *HTTPError) Error() string

func (*HTTPError) RateLimited added in v0.3.3

func (e *HTTPError) RateLimited() bool

RateLimited reports an answer that asks Ether to slow down.

type Lookup added in v0.3.3

type Lookup struct {
	Type         string
	ID           string
	Packs        bool
	EntryEpisode int
}

Lookup is how to ask an add-on's stream route about one search: its content type ("movie" or "series") and id, whether only whole-season packs are wanted, and, for an anime database id, the episode's number inside that entry.

func LookupStreams added in v0.3.3

func LookupStreams(ctx context.Context, m Manifest, req core.SearchRequest, anime AnimeIDs) (Lookup, bool)

LookupStreams chooses how to ask the add-on for req's streams: by IMDb id when it takes them, else TMDB, else TVDB, else (for anime) an anime database id the community mapping knows unambiguously. A season request (Episode 0) asks for the season's first episode and keeps only packs. ok is false when the add-on cannot be asked, which skips it for this title. anime may be nil (no anime lookups).

func (Lookup) Route added in v0.3.3

func (l Lookup) Route() string

Route is the stream route path for the lookup.

type Manifest

type Manifest struct {
	ID            string        `json:"id"`
	Version       string        `json:"version"`
	Name          string        `json:"name"`
	Description   string        `json:"description,omitempty"`
	Background    string        `json:"background,omitempty"`
	Types         []string      `json:"types,omitempty"`
	IDPrefixes    []string      `json:"idPrefixes,omitempty"`
	Resources     Resources     `json:"resources,omitempty"`
	Catalogs      []Catalog     `json:"catalogs,omitempty"`
	AddonCatalogs []Catalog     `json:"addonCatalogs,omitempty"`
	BehaviorHints BehaviorHints `json:"behaviorHints,omitzero"`
}

Manifest is a Stremio add-on manifest: the one model of it in Ether. A plugin manifest (internal/plugins) embeds it and adds the `ether` block, so a plain Stremio add-on and an Ether plugin share every Stremio field and every rule below.

func DecodeManifest added in v0.3.3

func DecodeManifest(body []byte) (Manifest, error)

DecodeManifest parses a manifest document.

func FetchManifest

func FetchManifest(ctx context.Context, client *http.Client, rawURL string) (Manifest, error)

FetchManifest reads and checks the manifest of the addon at rawURL.

func FetchManifestAny added in v0.3.3

func FetchManifestAny(ctx context.Context, client *http.Client, rawURL string) (Manifest, error)

FetchManifestAny reads the manifest without the stream-indexer check, for catalog, tv and subtitle roles.

func (Manifest) CatalogNamed added in v0.3.3

func (m Manifest) CatalogNamed(typ, id string) (Catalog, bool)

CatalogNamed returns the catalog of typ with id.

func (Manifest) CatalogsOfType added in v0.3.3

func (m Manifest) CatalogsOfType(typ string) []Catalog

CatalogsOfType returns the catalogs of one content type.

func (Manifest) CheckStreams added in v0.3.3

func (m Manifest) CheckStreams() error

CheckStreams reports why Ether cannot search the add-on for streams, or nil.

func (Manifest) GuideURL added in v0.3.3

func (m Manifest) GuideURL() string

GuideURL returns the add-on's XMLTV guide URL, if it declares one.

func (Manifest) HasResource added in v0.3.3

func (m Manifest) HasResource(name string) bool

HasResource reports whether the add-on declares the named resource.

func (Manifest) Resource added in v0.3.3

func (m Manifest) Resource(name string) (Resource, bool)

Resource returns the named resource with inherited types and prefixes resolved: a bare name takes the manifest's; an object keeps its own, and an object without idPrefixes accepts every id.

func (Manifest) Serves added in v0.3.3

func (m Manifest) Serves(name, typ string) bool

Serves reports whether the named resource answers content type typ.

func (Manifest) TakesID added in v0.3.3

func (m Manifest) TakesID(name, typ, id string) bool

TakesID reports whether the named resource accepts id: catalog routes match a declared catalog; the rest match the resource's id prefixes (none declared accepts every id).

func (Manifest) Valid added in v0.3.3

func (m Manifest) Valid() bool

Valid reports whether m looks like an add-on manifest at all.

type Meta added in v0.3.3

type Meta struct {
	MetaPreview
	Background string   `json:"background,omitempty"`
	Runtime    string   `json:"runtime,omitempty"`
	Released   string   `json:"released,omitempty"`
	Year       any      `json:"year,omitempty"`
	Cast       []string `json:"cast,omitempty"`
	Director   []string `json:"director,omitempty"`
	Writer     []string `json:"writer,omitempty"`
	Country    string   `json:"country,omitempty"`
	Language   string   `json:"language,omitempty"`
	Website    string   `json:"website,omitempty"`
	Videos     []Video  `json:"videos,omitempty"`
}

Meta is a meta document.

type MetaPreview added in v0.3.3

type MetaPreview struct {
	ID            string   `json:"id"`
	Type          string   `json:"type"`
	Name          string   `json:"name"`
	Poster        string   `json:"poster,omitempty"`
	Description   string   `json:"description,omitempty"`
	Genres        []string `json:"genres,omitempty"`
	ReleaseInfo   string   `json:"releaseInfo,omitempty"`
	IMDBRating    string   `json:"imdbRating,omitempty"`
	IMDbID        string   `json:"imdb_id,omitempty"`
	TMDBID        any      `json:"tmdb_id,omitempty"`
	BehaviorHints struct {
		DefaultVideoID     string `json:"defaultVideoId,omitempty"`
		HasScheduledVideos bool   `json:"hasScheduledVideos,omitempty"`
	} `json:"behaviorHints,omitzero"`
}

MetaPreview is one catalog entry.

func (MetaPreview) Ref added in v0.3.3

func (m MetaPreview) Ref() (imdb string, tmdb, tvdb int64)

Ref reads a catalog entry's identity: its id, else explicit imdb_id or tmdb_id fields some add-ons add.

type Options added in v0.2.44

type Options struct {
	// Client talks to the owner-configured addon (20 s timeout when nil).
	Client *http.Client
	// NZBClient downloads the NZB files of Usenet streams. Its transport
	// must be a safefetch guard: only the addon's own origin may be a
	// private address. Nil builds one.
	NZBClient *http.Client
	// Anime maps TMDB ids to anime database ids; nil loads the community
	// mapping lazily, the first time an addon needs it.
	Anime AnimeIDs
}

Options configure a Service.

type Resource added in v0.3.3

type Resource struct {
	Name       string   `json:"name"`
	Types      []string `json:"types,omitempty"`
	IDPrefixes []string `json:"idPrefixes,omitempty"`
	Short      bool     `json:"-"`
}

Resource is one manifest resource. The protocol allows a bare name, which inherits the manifest's types and id prefixes, or an object with its own; Short remembers which, so the manifest round-trips unchanged.

func (Resource) MarshalJSON added in v0.3.3

func (r Resource) MarshalJSON() ([]byte, error)

MarshalJSON writes the form the manifest used.

func (*Resource) UnmarshalJSON added in v0.3.3

func (r *Resource) UnmarshalJSON(b []byte) error

UnmarshalJSON accepts a bare resource name or a resource object.

type Resources added in v0.3.3

type Resources []Resource

Resources is a manifest's resource list.

func ParseResources added in v0.3.3

func ParseResources(raw string) Resources

ParseResources reads a resources JSON array (tests and fixtures).

func (*Resources) UnmarshalJSON added in v0.3.3

func (rs *Resources) UnmarshalJSON(b []byte) error

UnmarshalJSON skips entries that are neither a name nor an object, so one malformed resource does not hide the rest of an add-on.

type Service

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

Service builds and keeps one Backend per configured addon, so a backend's manifest survives between searches.

func NewService

func NewService(client *http.Client) *Service

NewService returns a Service. client nil uses a default client with a 20 s timeout.

func NewServiceWithOptions added in v0.2.44

func NewServiceWithOptions(o Options) *Service

NewServiceWithOptions returns a Service built from o.

func (*Service) AnimeIDs added in v0.3.3

func (s *Service) AnimeIDs() AnimeIDs

AnimeIDs is the service's anime id mapping, loaded the first time an add-on needs it; installed add-ons share it (internal/plugins/adapters).

func (*Service) Backend

func (s *Service) Backend(cfg config.Indexer) (newznab.Backend, error)

Backend returns the backend for an addon indexer (newznab.Options.Backend).

func (*Service) Test

func (s *Service) Test(ctx context.Context, cfg config.Indexer) error

Test checks that the addon at cfg.URL can be searched.

type Stream added in v0.3.3

type Stream = stream

Stream is one stream object an add-on answers (backend.go's stream, the one decoder of it). Installed add-ons and Ether source plugins (internal/plugins/adapters) convert their answers with the same code as the Stremio indexer.

type StreamHints added in v0.3.3

type StreamHints = behaviorHints

StreamHints is a stream's behaviorHints.

type Subtitle added in v0.3.3

type Subtitle struct {
	ID          string `json:"id,omitempty"`
	URL         string `json:"url"`
	Lang        string `json:"lang"`
	Filename    string `json:"filename,omitempty"`
	SubFileName string `json:"SubFileName,omitempty"`
	HashMatch   bool   `json:"hashMatch,omitempty"`
	Format      string `json:"format,omitempty"`
	Name        string `json:"name,omitempty"`
}

Subtitle is one subtitle an add-on offers.

type Video added in v0.3.3

type Video struct {
	ID        string    `json:"id"`
	Title     string    `json:"title"`
	Name      string    `json:"name,omitempty"`
	Overview  string    `json:"overview,omitempty"`
	Season    int       `json:"season,omitempty"`
	Episode   int       `json:"episode,omitempty"`
	Released  time.Time `json:"released,omitzero"`
	StartTime time.Time `json:"startTime,omitzero"`
	EndTime   time.Time `json:"endTime,omitzero"`
	Thumbnail string    `json:"thumbnail,omitempty"`
}

Video is one entry of a meta's videos list. `tv` add-ons publish their schedule as videos with timestamps.

Jump to

Keyboard shortcuts

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