Documentation
¶
Overview ¶
Package stremio is the Stremio addon-source module: the first official optional Module, built exactly as a third party would build one. It is its own Go module (github.com/mosaic-media/module-stremio-addons) importing only the published SDK (contracts/platform/v1) and the standard library, and it is compiled into the Platform binary and invoked through the capability registry (ADR 0007, ADR 0008).
It consumes the Stremio addon protocol as a client: it points at one or more addon HTTP endpoints and, guided by each addon's manifest, uses whatever resources that addon declares. Metadata (the meta resource) creates the Work and its season/episode tree with an external-id source binding; streams (the stream resource) attach a RemoteLocation Part. The two are independent — a meta-only addon yields metadata with no Parts, so a user can enrich local media through Stremio addons without adopting remote streaming. Streams are opt-in by which addons are configured, not by the module.
It owns no schema (ADR 0012): everything it does to the graph goes through ContentService, acting as the Caller the Platform hands it (ADR 0017). Stream locations are snapshotted at import; resolving or transcoding them at play time is a separate, future concern (the Remote Media module), deliberately not here.
Index ¶
- Constants
- type AddonCatalogEntry
- type AddonInfo
- type AppExtras
- type Capability
- func (c *Capability) CatalogItems(ctx context.Context, req v1.CatalogItemsRequest) (v1.CatalogItemsResponse, error)
- func (c *Capability) Catalogs(ctx context.Context, req v1.CatalogsRequest) (v1.CatalogsResponse, error)
- func (c *Capability) Import(ctx context.Context, svc v1.ContentService, req v1.ImportRequest) (v1.ImportResult, error)
- func (c *Capability) Manifest() v1.Manifest
- func (c *Capability) Metadata(ctx context.Context, req v1.MetadataRequest) (v1.ContentMetadata, error)
- func (c *Capability) Search(ctx context.Context, req v1.SearchRequest) (v1.SearchResponse, error)
- func (c *Capability) SettingsUI(ctx context.Context, req v1.SettingsUIRequest) (v1.SettingsUIResponse, error)
- func (c *Capability) Streams(ctx context.Context, req v1.StreamRequest) (v1.StreamResponse, error)
- func (c *Capability) Subtitles(ctx context.Context, req v1.SubtitlesRequest) (v1.SubtitlesResponse, error)
- type CatalogDecl
- type Client
- func (c *Client) AddonCatalog(ctx context.Context) ([]AddonCatalogEntry, error)
- func (c *Client) CatalogItems(ctx context.Context, typ, id, genre string, skip int) ([]MetaPreview, bool, error)
- func (c *Client) Catalogs(ctx context.Context) ([]CatalogDecl, error)
- func (c *Client) InstalledAddons(ctx context.Context) []AddonInfo
- func (c *Client) Meta(ctx context.Context, typ, id string) (Meta, bool, error)
- func (c *Client) MetaMerged(ctx context.Context, typ, id string) (Meta, MetaProvenance, bool, error)
- func (c *Client) Search(ctx context.Context, query string) ([]MetaPreview, error)
- func (c *Client) Stream(ctx context.Context, typ, id string) (Stream, bool, error)
- func (c *Client) Streams(ctx context.Context, typ, id string) ([]Stream, error)
- func (c *Client) Subtitles(ctx context.Context, typ, id string) ([]Subtitle, bool, error)
- type Credit
- type ExtraDecl
- type Link
- type Manifest
- type Meta
- type MetaPreview
- type MetaProvenance
- type ResourceDecl
- type Stream
- type Subtitle
- type Video
Constants ¶
const ( // CapabilityID is the id the Platform registers this module under and a // caller names to invoke it. CapabilityID = "stremio" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AddonCatalogEntry ¶
type AddonCatalogEntry struct {
TransportURL string `json:"transportUrl"`
Manifest Manifest `json:"manifest"`
}
AddonCatalogEntry is one installable addon a catalog of addons lists (ADR 0038): its transport (manifest) URL and enough of its manifest to name it.
type AddonInfo ¶
AddonInfo is the display detail for one configured addon (ADR 0038): the name, logo and description from its manifest, whether it is configurable, and the normalised base URL that identifies it. An addon whose manifest cannot be fetched still yields an entry (named by its URL) so a user can remove it.
type AppExtras ¶ added in v0.15.0
type AppExtras struct {
Cast []Credit `json:"cast"`
Directors []Credit `json:"directors"`
Writers []Credit `json:"writers"`
}
AppExtras is the richer credit block some addons attach alongside the standard meta fields.
type Capability ¶
type Capability struct {
// contains filtered or unexported fields
}
Capability is the Stremio addon-source module (ADR 0008's capability surface, first populated). It holds only an HTTP client; the addons it sources from are whatever a user adds through its settings, handed in at invocation time (ADR 0021), so one registered module serves whatever each user configures. It owns no schema and imports no Platform internals.
It bundles no addon of its own. It used to bundle Cinemeta so that a fresh install had metadata (ADR 0035); that guarantee now belongs to `module-cinemeta`, a core module that cannot be switched off (ADR 0072), and this module is purely what a user chose.
func New ¶
func New(httpClient *http.Client) *Capability
New builds the capability over an HTTP client (nil for a default). Addon URLs are not supplied here — they arrive as settings on each invocation.
func (*Capability) CatalogItems ¶
func (c *Capability) CatalogItems(ctx context.Context, req v1.CatalogItemsRequest) (v1.CatalogItemsResponse, error)
CatalogItems lists one collection's entries as virtual candidates the admin can select to publish (ADR 0028). It does not touch the object graph.
func (*Capability) Catalogs ¶
func (c *Capability) Catalogs(ctx context.Context, req v1.CatalogsRequest) (v1.CatalogsResponse, error)
Catalogs lists the collections the configured addons expose (RoleCatalog — the addon `catalog` resource), for the admin collection browser.
func (*Capability) Import ¶
func (c *Capability) Import(ctx context.Context, svc v1.ContentService, req v1.ImportRequest) (v1.ImportResult, error)
Import materialises the virtual item named by req.Ref — a result a search or catalog browse produced (ADR 0028) — from the configured addons into the Platform. It fetches metadata (required), searches to avoid duplicating, creates the Work with an external-id binding, builds the tree, and attaches a RemoteLocation Part wherever a stream addon serves one. Metadata alone is a complete import; streams are additive.
func (*Capability) Manifest ¶
func (c *Capability) Manifest() v1.Manifest
Manifest is the module's self-declaration, including the provider roles it fills (ADR 0027). It sources metadata and searches and browses catalogs, and resolves streams — the four Stremio addon resources.
func (*Capability) Metadata ¶
func (c *Capability) Metadata(ctx context.Context, req v1.MetadataRequest) (v1.ContentMetadata, error)
Metadata resolves descriptive detail for a ref (RoleMetadata — the addon `meta` resource). It is the enrichment surface: the descriptive fields, not the containment tree, which Import builds where the source's structure is known (ADR 0027).
func (*Capability) Search ¶
func (c *Capability) Search(ctx context.Context, req v1.SearchRequest) (v1.SearchResponse, error)
Search returns virtual candidates for free text (RoleSearch — the addon `catalog/…/search` resource). No raw id: this is what makes user search in Mosaic work over source content that is not in the library (ADR 0028).
func (*Capability) SettingsUI ¶
func (c *Capability) SettingsUI(ctx context.Context, req v1.SettingsUIRequest) (v1.SettingsUIResponse, error)
SettingsUI renders the module's own settings screen as SDUI (RoleSettingsUI, ADR 0038): add an addon by manifest URL, view the installed addons as cards (name, logo, description) with a way to configure or remove them, and browse a grid of installable addons (the addon_catalog resource) to add without a URL. Every mutating control is an Invoke of the Platform's configureModule command with the complete new settings document, so the Platform stays the one that persists them. The screen is returned as serialised UINode JSON — the SDK stays SDUI-agnostic.
It builds its clients directly rather than through clientFrom, which refuses an empty addon list. That refusal is right for a provider role and wrong here: with no bundled default, no addons configured is what a fresh install looks like, and this screen is the only way out of it.
func (*Capability) Streams ¶
func (c *Capability) Streams(ctx context.Context, req v1.StreamRequest) (v1.StreamResponse, error)
Streams resolves playable locations for a materialised item's ref (RoleStream — the addon `stream` resource). Import snapshots streams at materialise time; this exposes the same resolution as a role other flows can call. It returns an empty response, no error, when no addon serves a stream (the meta-only case).
func (*Capability) Subtitles ¶
func (c *Capability) Subtitles(ctx context.Context, req v1.SubtitlesRequest) (v1.SubtitlesResponse, error)
Subtitles resolves subtitle tracks for a materialised item's ref (RoleSubtitles — the addon `subtitles` resource, ADR 0037). Like Streams it is a source role; the consumer is a player that does not exist yet, so this is built ahead of it. It returns an empty response, no error, when no addon serves subtitles.
type CatalogDecl ¶
type CatalogDecl struct {
Type string `json:"type"`
ID string `json:"id"`
Name string `json:"name"`
// Extra is the modern shape: a list of accepted parameters, each named.
Extra []ExtraDecl `json:"extra"`
// ExtraSupported is the older shape: a bare list of accepted parameter
// names. Both are read so search is detected whichever an addon uses.
ExtraSupported []string `json:"extraSupported"`
}
CatalogDecl is one entry of a manifest's catalogs array — a collection the addon exposes (Popular, Top). A catalog is typed and addressed by its id; the extra declarations say which query parameters it accepts, the one that matters here being "search".
func (CatalogDecl) GenreOptions ¶ added in v0.29.0
func (c CatalogDecl) GenreOptions() []string
GenreOptions returns the values the catalog's `genre` extra accepts, empty when it declares none.
**`genre` is the protocol's one general-purpose narrowing, and addons use it for whatever they like.** Cinemeta puts *years* under it. That is fine here precisely because the values are declared: the options are shown as labels and sent back verbatim, and nothing in Mosaic ever has to decide what they mean.
func (CatalogDecl) RequiresAnArgument ¶ added in v0.29.0
func (c CatalogDecl) RequiresAnArgument() bool
RequiresAnArgument reports whether the catalog declares an extra it cannot be listed without.
func (CatalogDecl) SupportsSearch ¶
func (c CatalogDecl) SupportsSearch() bool
SupportsSearch reports whether the catalog accepts a search query.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a minimal client of the Stremio addon protocol — the HTTP contract documented at stremio.github.io/stremio-addon-sdk. It talks to one or more addons and routes each request to an addon whose manifest declares the needed resource and type. A meta-only addon therefore serves metadata and a stream addon serves streams, and neither resource depends on the other.
func NewClient ¶
NewClient builds a client over the given addon URLs. A nil httpClient gets a default with a sane timeout. Each URL is normalised to the addon's base URL (see normaliseAddonURL) so that either the base URL or the manifest URL a user copies from Stremio works. Manifests are not fetched here; they are fetched on first use so construction stays offline.
func (*Client) AddonCatalog ¶
func (c *Client) AddonCatalog(ctx context.Context) ([]AddonCatalogEntry, error)
AddonCatalog fetches the union of every configured addon's addon catalogs — the installable addons a user can add without pasting a manifest URL. Addons that do not serve the resource contribute nothing; a fetch that errors is skipped rather than failing the whole browse. De-duped by transport URL.
func (*Client) CatalogItems ¶
func (c *Client) CatalogItems(ctx context.Context, typ, id, genre string, skip int) ([]MetaPreview, bool, error)
CatalogItems lists one catalog's entries, from the first addon whose manifest declares a catalog of that type and id. skip pages through a large catalog (0 for the first page), and genre narrows it when non-empty — the caller has already checked the value against what that catalog declared. It returns nil, no error, when no configured addon declares the catalog.
It also reports whether another page exists. That is the **weaker** of the two statements SDK v0.25.0 describes — a full page rather than a reported total — and it is still the provider's to make, because only the provider knows the page size. Its cost is one empty fetch at the end of an exactly-full catalog.
func (*Client) InstalledAddons ¶
InstalledAddons returns display detail for each configured addon, in the client's effective (deduped, default-first) order. Manifests are fetched and cached; an unreachable addon is named by its URL rather than dropped, so it stays removable.
func (*Client) Meta ¶
Meta fetches metadata for a content id from the first configured addon whose manifest serves the meta resource for the type. It returns ok=false, no error, when no configured addon serves meta for it.
func (*Client) MetaMerged ¶ added in v0.13.0
func (c *Client) MetaMerged(ctx context.Context, typ, id string) (Meta, MetaProvenance, bool, error)
MetaMerged asks every addon that serves `meta` and combines their answers by the tiered rule above. It also reports which addon supplied each tier, so an odd-looking detail screen is an answerable question rather than a guess.
func (*Client) Search ¶
Search queries every search-capable catalog across every configured addon and returns the union, de-duplicated by content id. A catalog that errors on the search query is skipped rather than failing the whole search, so one broken addon does not blank the results. It returns nil, no error, when nothing matches or no addon offers search.
func (*Client) Streams ¶ added in v0.10.0
Stream fetches the best stream for a content id (a movie id, or an episode id of the form tt...:season:episode) from the first addon whose manifest serves the stream resource for the type. Stremio ranks streams best-first, so the first entry is taken. It returns ok=false, no error, when no configured addon serves a stream — the metadata-only case. Streams fetches every stream a configured addon offers for a content id.
Import stores all of them (ADR 0049): a candidate never expires, so keeping the set costs nothing to keep correct, and it is what lets a consumer choose a release the calling client can actually play instead of being handed whatever happened to be first. Only the resolved URL is perishable, and that is cached separately.
func (*Client) Subtitles ¶
Subtitles fetches subtitle tracks for a content id (a movie id or an episode id of the form tt...:season:episode) from the first addon whose manifest serves the subtitles resource for the type. It returns ok=false, no error, when no configured addon serves subtitles (ADR 0037).
type Credit ¶ added in v0.15.0
type Credit struct {
Name string `json:"name"`
Character string `json:"character"`
Photo string `json:"photo"`
}
Credit is one person with the two things `links` cannot express: the character they played, and a photograph of them.
type ExtraDecl ¶
type ExtraDecl struct {
Name string `json:"name"`
// Options are the values the parameter accepts, when the addon says. An
// extra with none is a free-text parameter (`search`) or one whose values
// the caller must already hold (`lastVideosIds`); either way it cannot back
// a control built from a declared list, so it is not offered as a filter.
Options []string `json:"options"`
// IsRequired is whether a listing *cannot be fetched* without this
// parameter. It is read so a catalog that needs an argument a browse surface
// cannot invent is skipped rather than rendered as a row that answers
// nothing.
IsRequired bool `json:"isRequired"`
}
ExtraDecl is one accepted catalog parameter.
type Link ¶
type Link struct {
Name string `json:"name"`
Category string `json:"category"`
URL string `json:"url"`
}
Link is one entry of a meta's `links` array — the modern Cinemeta shape that carries cast, directors, writers and genres as categorised references.
type Manifest ¶
type Manifest struct {
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Description string `json:"description"`
Logo string `json:"logo"`
Resources []ResourceDecl `json:"resources"`
Types []string `json:"types"`
Catalogs []CatalogDecl `json:"catalogs"`
// AddonCatalogs are catalogs of *other addons* this addon exposes (the
// `addon_catalog` resource) — how a user discovers installable addons without
// a manifest URL (ADR 0038).
AddonCatalogs []CatalogDecl `json:"addonCatalogs"`
BehaviorHints addonBehaviorHints `json:"behaviorHints"`
}
Manifest is the subset of a Stremio addon manifest this client reads.
type Meta ¶
type Meta struct {
ID string `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Poster string `json:"poster"`
Background string `json:"background"`
Logo string `json:"logo"`
// LandscapePoster is wide key art an addon proxying a real artwork database
// returns beside the portrait poster. It is not part of the base Stremio meta
// shape — Cinemeta has no such field — so it is empty for sources that do not
// carry it, and translated here rather than left for the Platform to learn
// (ADR 0051).
LandscapePoster string `json:"landscapePoster"`
Description string `json:"description"`
ReleaseInfo string `json:"releaseInfo"`
Genres []string `json:"genres"`
// ImdbRating is Cinemeta's rating, a string ("8.0") in its API.
ImdbRating string `json:"imdbRating"`
// Runtime is a display string whose format varies ("120 min").
Runtime string `json:"runtime"`
// Cast is the legacy top-level cast (names). Modern Cinemeta also puts cast
// in Links with category "Cast"; both are read (see castNames).
Cast []string `json:"cast"`
Links []Link `json:"links"`
Videos []Video `json:"videos"`
// AppExtras is where an addon proxying a real metadata database puts credits
// that the base Stremio meta shape has no room for. `links` carries cast as
// a name and a search URL — no character, no photo — so an addon with better
// data has nowhere to put it and puts it here instead.
AppExtras AppExtras `json:"app_extras"`
}
Meta is the subset of a meta response this client reads. For a series, Videos lists the episodes, each carrying its season and episode number. Logo/ImdbRating/Runtime/Cast/Links back the rich detail surface (ADR 0034); Cinemeta provides them all — the module simply decoded none of them before.
type MetaPreview ¶
type MetaPreview struct {
ID string `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Poster string `json:"poster"`
ReleaseInfo string `json:"releaseInfo"`
}
MetaPreview is the subset of a catalog/search meta entry this client reads — the lightweight item shape a catalog returns, distinct from the full Meta a meta lookup returns. ReleaseInfo is a year ("2017") or a range ("2008-2013").
type MetaProvenance ¶ added in v0.14.0
MetaProvenance records which addon supplied each tier of a merged record.
It costs almost nothing and turns "why does this look odd" into something answerable. Metadata assembled from several sources is exactly the kind of thing that is hard to debug after the fact without it.
type ResourceDecl ¶
ResourceDecl is one entry of a manifest's resources array. Stremio allows each entry to be either a bare string ("meta") or an object carrying its own types and id prefixes; this unmarshals both shapes.
func (*ResourceDecl) UnmarshalJSON ¶
func (r *ResourceDecl) UnmarshalJSON(b []byte) error
UnmarshalJSON accepts either a bare string or the object form.
type Stream ¶
type Stream struct {
Name string `json:"name"`
Title string `json:"title"`
Description string `json:"description"`
URL string `json:"url"`
InfoHash string `json:"infoHash"`
FileIdx int `json:"fileIdx"`
BehaviorHints behaviorHints `json:"behaviorHints"`
}
Stream is the subset of a stream object this client reads. A stream is either a direct URL or a torrent identified by InfoHash. Description/ BehaviorHints carry the release detail (quality, size) addons pack into the title, which parseStreamMeta teases back out (ADR 0037).
type Subtitle ¶
Subtitle is the subset of a subtitles response entry this client reads (ADR 0037): a track's language and the file URL.
type Video ¶
type Video struct {
ID string `json:"id"`
Title string `json:"title"`
Name string `json:"name"`
Season int `json:"season"`
Episode int `json:"episode"`
Overview string `json:"overview"`
// Thumbnail is a still image URL for the episode.
Thumbnail string `json:"thumbnail"`
// Released is the episode's air date (an ISO datetime in Cinemeta).
Released string `json:"released"`
}
Video is one episode of a series' meta. Overview/Thumbnail/Released back the episode preview (ADR 0034); Cinemeta provides them on each video entry.
func (Video) EpisodeTitle ¶
EpisodeTitle is the video's title, falling back to its name and then a generated label, so an item always has something to show.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
module-stremio-addons
command
Command module-stremio-addons runs this module as its own process, for a Platform that hosts it out of process (ADR 0064, ADR 0077).
|
Command module-stremio-addons runs this module as its own process, for a Platform that hosts it out of process (ADR 0064, ADR 0077). |