stremio

package module
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Jan 16, 2021 License: AGPL-3.0 Imports: 29 Imported by: 4

README

go-stremio

Stremio addon SDK for Go

Contents

  1. Introduction
  2. About this SDK
  3. Features
  4. Example
  5. Advantages
  6. Related projects

Introduction

Stremio is a modern media center that's a one-stop solution for your video entertainment. You discover, watch and organize video content from easy to install addons.

These addons run remotely as a web service, so they can't do any harm to your computer. This is different from how addons work for Kodi for example, where they run locally on your computer and have dozens of third party dependencies. There have been several security incidents with Kodi addons like this one and even the Kodi developers themselves warn of the dangers of third party Kodi addons.

About this SDK

When developing a Stremio addon, you're essentially developing a web service. But there are some defined routes, expected behavior, JSON structure etc., so instead of having to figure all of this out on your own before you've got even a basic addon running, using an SDK can get you up to speed much faster, as it takes care of all of this automatically.

But the official Stremio addon SDK is for Node.js only.

This SDK is for Go!

It provides the most important parts of the Node.js SDK and depending on the requirements of you, the libary users, it will be extended to provide more in the future.

Features

  • Based on the Express-inspired web framework Fiber
  • All required types for building catalog and stream addons
  • Graceful server shutdown
    • With optional channel to be notified about the shutdown
  • CORS middleware to allow requests from Stremio
  • Health check endpoint
  • Optional profiling endpoints (for go pprof)
  • Optional request logging
    • With optional movie / TV show name in the log (instead of just the IMDb ID)
    • With optional client IP address and user agent logging to create privacy-preserving addons
  • Optional cache control and ETag handling
  • Optional custom middlewares
  • Optional custom endpoints
  • Custom user data (users can have settings for your addon!)
    • Including the handling of Stremio's requests to the "/configure" endpoint to show a webpage for the addon's configuration
    • With optional URL-safe Base64 decoding and JSON unmarshalling
  • Addon installation callback (manifest endpoint)
  • Cinemeta client in the independent cinemeta package
  • Optional stream ID filtering via regex
  • Optional collection and export of basic metrics for Prometheus

Current non-features, as they're usually part of a reverse proxy deployed in front of the service:

  • TLS termination (for using HTTPS)
  • Rate limiting (against DoS attacks)
  • Compression (like gzip)

Example

Full examples can be found in examples. Here's a part of the one for a stream addon:

package main

import (
    "context"

    "github.com/deflix-tv/go-stremio"
)

var (
    manifest = stremio.Manifest{
        ID:          "com.example.blender-streams",
        Name:        "Blender movie streams",
        Description: "Stream addon for free movies that were made with Blender",
        // ...
    }
)

func main() {
    // Let the movieHandler handle the "movie" type
    streamHandlers := map[string]stremio.StreamHandler{"movie": movieHandler}

    addon, err := stremio.NewAddon(manifest, nil, streamHandlers, stremio.DefaultOptions)
    if err != nil {
        panic(err)
    }

    addon.Run(nil)
}

func movieHandler(ctx context.Context, id string, userData interface{}) ([]stremio.StreamItem, error) {
    // We only serve Big Buck Bunny and Sintel
    if id == "tt1254207" {
        return []stremio.StreamItem{
            // Torrent stream
            {
                InfoHash: "dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c",
                // Stremio recommends to set the quality as title, as the streams
                // are shown for a specific movie so the user knows the title.
                Title:     "1080p (torrent)",
                FileIndex: 1,
            },
            // HTTP stream
            {
                URL:   "http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4",
                Title: "1080p (HTTP stream)",
            },
        }, nil
    } else if id == "tt1727587" {
        // ...
    }
    return nil, stremio.NotFound
}

Advantages

Some reasons why you might want to consider developing an addon in Go with this SDK:

Criterium Node.js addon Go addon
Direct SDK dependencies 9 5
Transitive SDK dependencies 90¹ 36²
Size of a runnable addon 27 MB³ 11-15 MB⁴
Number of artifacts to deploy depends⁵ 1
Runtime dependencies Node.js -
Concurrency Single-threaded Multi-threaded

¹) ls -l node_modules | wc -l - 1
²) go list -m all | wc -l - 1 - (number of direct dependencies)
³) du -h --max-depth=0 node_modules
⁴) The smaller binary is easily achieved by compiling with -ldflags "-s -w"
⁵) All your JavaScript files and the package.json if you can install the depencencies with npm on the server, otherwise (like in a Docker container) you also need all the node_modules, which are hundreds to thousands of files.

Looking at the performance it depends a lot on what your addon does. Due to the single-threaded nature of Node.js, the more CPU-bound tasks your addon does, the bigger the performance difference will be (in favor of Go). Here we compare the simplest possible addon to be able to compare just the SDKs and not any additional overhead (like DB access):

On a DigitalOcean "Droplet" of type "Basic" (shared CPU) with 2 cores and 2 GB RAM, which costs $15/month:

Criterium Node.js addon Go addon
Startup time to 1st request¹ 400ms-4s 20-30ms
Max rps² @ 1000 connections Local³: 1,000
Remote⁴: 1,000
Local³: 17,000
Remote⁴: 29,000
Memory usage @ 1000 connections Idle: 42 MB
Load⁵: 73 MB
Idle: 11 MB
Load⁵: 45 MB

On a DigitalOcean "Droplet" of type "CPU-Optimized" (dedicated CPU) with 2 cores and 4 GB RAM, which costs $40/month:

Criterium Node.js addon Go addon
Startup time to 1st request¹ 200-400ms 9-20ms
Max rps² @ 1000 connections Local³: 5,000
Remote⁴: 1,000
Local³: 39,000
Remote⁴: 39,000
Memory usage @ 1000 connections Idle: 42 MB
Load⁵: 90 MB
Idle: 11 MB
Load⁵: 47 MB

¹) Measured using ttfok and the code in benchmark. This metric is relevant in case you want to use a "serverless functions" service (like AWS Lambda or Vercel (former ZEIT Now)) that doesn't keep your service running between requests.
²) Max number of requests per second where the p99 latency is still < 100ms
³) The load testing tool ran on a different server, but in the same datacenter and the requests were sent within a private network. Note that DigitalOcean seems to have performance issues with their local "VPC Network" (which didn't affect the Node.js service as it maxed out the CPU, but the Go service maxed out the network before the CPU).
⁴) The load testing tool ran on a different server in a different datacenter of another cloud provider in another city for more real world-like circumstances
⁵) Resident size (RES in htop) at a request rate half of what we measured as maximum

The load tests were run under the following circumstances:

  • We used the addon code, load testing tool and setup described in benchmark
  • We ran the Node.js and Go service on the same Droplet and conducted the benchmark on the same day, several minutes apart, so that the resource sharing of the VPS is about the same. Note that when you try to reproduce the benchmark results, a different VPS could be subject to more or less resource sharing with other VPS on the virtualization host. Other times of day can also lead to differing benchmark results (e.g. low traffic on a Monday morning, high traffic on a Saturday evening).
  • The load tests ran for 60s (to have a somewhat meaningful p99 value), with previous warmup
  • The client servers (both the one in the same DC and the one in a different DC of another cloud provider in another city) used to run the load testing tool were high-powered (8 dedicated cores, 32 GB RAM)

Additional observations:

  • The Go service's response times were generally lower across all request rates
  • The Go service's response times had a much lower deviation, i.e. they were more stable. With less than 60s of time for the load test the Node.js service fared even worse, because outliers lead to a higher p99 latency.
  • We also tested on a lower-powered server by a cheap cloud provider (also 2 core, 2 GB RAM, but the CPU was generally worse). In this case the difference between the Node.js and the Go service was even higher. The Go service is perfectly fitted for scaling out with multiple cheap servers.
  • We also tested with different amounts of connections. With more connections the difference between the Node.js and the Go service was also higher. In a production deployment you want to be able to serve as many users as possible, so this goes in favor of the Go service as well.

Note:

  • This Go SDK is still young. Some features will be added in the future that might decrease its performance, while others will increase it.
  • The Node.js addon was run as a single instance. You can do more complex deployments with a load balancer like HAProxy and multiple instances of the same Node.js service on a single machine to take advantage of multiple CPU cores. But then you should also activate preforking in the Go addon for using several OS processes in parallel, which we didn't do.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// BadRequest signals that the client sent a bad request.
	// It leads to a "400 Bad Request" response.
	BadRequest = errors.New("Bad request")
	// NotFound signals that the catalog/meta/stream was not found.
	// It leads to a "404 Not Found" response.
	NotFound = errors.New("Not found")
)
View Source
var DefaultOptions = Options{
	BindAddr:        "localhost",
	Port:            8080,
	LoggingLevel:    "info",
	LogEncoding:     "console",
	CinemetaTimeout: 2 * time.Second,
}

DefaultOptions is an Options object with default values. For fields that aren't set here the zero value is the default value.

Functions

func NewLogger added in v0.3.0

func NewLogger(level, encoding string) (*zap.Logger, error)

NewLogger creates a new logger with sane defaults and the passed level. Supported levels are: debug, info, warn, error. Only logs with that level and above are then logged (e.g. with "info" no debug logs will be logged). The encoding parameter is optional and will only be used when non-zero. Valid values: "console" (default) and "json".

It makes sense to get this logger as early as possible and use it in your ManifestCallback, CatalogHandler and StreamHandler, so that all logs behave and are formatted the same way. You should then also set this logger in the options for `NewAddon()`, so that not two loggers are created. Alternatively you can create your own custom *zap.Logger and set it in the options when creating a new addon, leading to the addon using that custom logger.

Types

type Addon

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

Addon represents a remote addon. You can create one with NewAddon() and then run it with Run().

func NewAddon

func NewAddon(manifest Manifest, catalogHandlers map[string]CatalogHandler, streamHandlers map[string]StreamHandler, opts Options) (*Addon, error)

NewAddon creates a new Addon object that can be started with Run(). A proper manifest must be supplied, but manifestCallback and all but one handler can be nil in case you only want to handle specific requests and opts can be the zero value of Options.

func (*Addon) AddEndpoint added in v0.3.0

func (a *Addon) AddEndpoint(method, path string, handler fiber.Handler)

AddEndpoint adds a custom endpoint (a route and its handler). If you want to be able to access custom user data, you can use a path like this: "/:userData/foo" and then either deal with the data yourself by using `c.Params("userData", "")` in the handler, or use the convenience method `DecodeUserData("userData", c)`.

func (*Addon) AddMiddleware added in v0.3.0

func (a *Addon) AddMiddleware(path string, middleware fiber.Handler)

AddMiddleware appends a custom middleware to the chain of existing middlewares. Set path to an empty string or "/" to let the middleware apply to all routes. Don't forget to call c.Next() on the Fiber context!

func (*Addon) DecodeUserData added in v0.3.0

func (a *Addon) DecodeUserData(param string, c *fiber.Ctx) (interface{}, error)

DecodeUserData decodes the request's user data and returns the result. It's useful when you add custom endpoints to the addon that don't have a userData parameter like the ManifestCallback, CatalogHandler and StreamHandler have. The param value must match the URL parameter you used when creating the custom endpoint, for example when using `AddEndpoint("GET", "/:userData/ping", customEndpoint)` you must pass "userData".

func (*Addon) RegisterUserData added in v0.3.0

func (a *Addon) RegisterUserData(userDataObject interface{})

RegisterUserData registers the type of userData, so the addon can automatically unmarshal user data into an object of this type and pass the object into the manifest callback or catalog and stream handlers.

func (*Addon) Run

func (a *Addon) Run(stoppingChan chan bool)

Run starts the remote addon. It sets up an HTTP server that handles requests to "/manifest.json" etc. and gracefully handles shutdowns. The call is *blocking*, so use the stoppingChan param if you want to be notified when the addon is about to shut down because of a system signal like Ctrl+C or `docker stop`. It should be a buffered channel with a capacity of 1.

func (*Addon) SetManifestCallback added in v0.3.0

func (a *Addon) SetManifestCallback(callback ManifestCallback)

SetManifestCallback sets the manifest callback

type BehaviorHints

type BehaviorHints struct {
	// Note: Must include `omitempty`, otherwise it will be included if this struct is used in another one, even if the field of the containing struct is marked as `omitempty`
	Adult        bool `json:"adult,omitempty"`
	P2P          bool `json:"p2p,omitempty"`
	Configurable bool `json:"configurable,omitempty"`
	// If you set this to true, it will be true for the "/manifest.json" endpoint, but false for the "/:userData/manifest.json" endpoint, because otherwise Stremio won't show the "Install" button in its UI.
	ConfigurationRequired bool `json:"configurationRequired,omitempty"`
}

type CatalogHandler

type CatalogHandler func(ctx context.Context, id string, userData interface{}) ([]MetaPreviewItem, error)

CatalogHandler is the callback for catalog requests for a specific type (like "movie"). The id parameter is the catalog ID that you specified yourself in the CatalogItem objects in the Manifest. The userData parameter depends on whether you called `RegisterUserData()` before: If not, a simple string will be passed. It's empty if the user didn't provide user data. If yes, a pointer to an object you registered will be passed. It's nil if the user didn't provide user data.

type CatalogItem

type CatalogItem struct {
	Type string `json:"type"`
	ID   string `json:"id"`
	Name string `json:"name"`

	// Optional
	Extra []ExtraItem `json:"extra,omitempty"`
}

CatalogItem represents a catalog.

type ExtraItem

type ExtraItem struct {
	Name string `json:"name"`

	// Optional
	IsRequired   bool     `json:"isRequired,omitempty"`
	Options      []string `json:"options,omitempty"`
	OptionsLimit int      `json:"optionsLimit,omitempty"`
}

type Manifest

type Manifest struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Version     string `json:"version"`

	// One of the following is required
	// Note: Can only have one in code because of how Go (de-)serialization works
	//Resources     []string       `json:"resources,omitempty"`
	ResourceItems []ResourceItem `json:"resources,omitempty"`

	Types    []string      `json:"types"` // Stremio supports "movie", "series", "channel" and "tv"
	Catalogs []CatalogItem `json:"catalogs"`

	// Optional
	IDprefixes    []string      `json:"idPrefixes,omitempty"`
	Background    string        `json:"background,omitempty"` // URL
	ContactEmail  string        `json:"contactEmail,omitempty"`
	BehaviorHints BehaviorHints `json:"behaviorHints,omitempty"`
}

Manifest describes the capabilities of the addon. See https://github.com/Stremio/stremio-addon-sdk/blob/f6f1f2a8b627b9d4f2c62b003b251d98adadbebe/docs/api/responses/manifest.md

type ManifestCallback added in v0.3.0

type ManifestCallback func(ctx context.Context, manifest *Manifest, userData interface{}) int

ManifestCallback is the callback for manifest requests, so mostly addon installations. You can use the callback for two things:

  1. To *prevent* users from installing your addon in Stremio. The userData parameter depends on whether you called `RegisterUserData()` before: If not, a simple string will be passed. It's empty if the user didn't provide user data. If yes, a pointer to an object you registered will be passed. It's nil if the user didn't provide user data. Return an HTTP status code >= 400 to stop further processing and let the addon return that exact status code. Any status code < 400 will lead to the manifest being returned with a 200 OK status code in the response.
  2. To *alter* the manifest before it's returned. This can be useful for example if you want to return some catalogs depending on the userData. Note that the manifest is only returned if the first return value is < 400 (see point 1.).

type MetaFetcher added in v0.8.0

type MetaFetcher interface {
	GetMovie(ctx context.Context, imdbID string) (cinemeta.Meta, error)
	GetTVShow(ctx context.Context, imdbID string, season int, episode int) (cinemeta.Meta, error)
}

MetaFetcher returns metadata for movies and TV shows. It's used when you configure that the media name should be logged or that metadata should be put into the context.

type MetaItem

type MetaItem struct {
	ID   string `json:"id"`
	Type string `json:"type"`
	Name string `json:"name"`

	// Optional
	Genres      []string       `json:"genres,omitempty"`   // Will be replaced by Links at some point
	Director    []string       `json:"director,omitempty"` // Will be replaced by Links at some point
	Cast        []string       `json:"cast,omitempty"`     // Will be replaced by Links at some point
	Links       []MetaLinkItem `json:"links,omitempty"`    // For genres, director, cast and potentially more. Not fully supported by Stremio yet!
	Poster      string         `json:"poster,omitempty"`   // URL
	PosterShape string         `json:"posterShape,omitempty"`
	Background  string         `json:"background,omitempty"` // URL
	Description string         `json:"description,omitempty"`
	ReleaseInfo string         `json:"releaseInfo,omitempty"` // E.g. "2000" for movies and "2000-2014" or "2000-" for TV shows
	IMDbRating  string         `json:"imdbRating,omitempty"`
	Released    string         `json:"released,omitempty"` // Must be ISO 8601, e.g. "2010-12-06T05:00:00.000Z"
	Videos      []VideoItem    `json:"videos,omitempty"`
	Runtime     string         `json:"runtime,omitempty"`
	Language    string         `json:"language,omitempty"`
	Country     string         `json:"country,omitempty"`
	Awards      string         `json:"awards,omitempty"`
	Website     string         `json:"website,omitempty"` // URL

}

MetaItem represents a meta item and is meant to be used when info for a specific item was requested. See https://github.com/Stremio/stremio-addon-sdk/blob/f6f1f2a8b627b9d4f2c62b003b251d98adadbebe/docs/api/responses/meta.md

type MetaLinkItem

type MetaLinkItem struct {
	Name     string `json:"name"`
	Category string `json:"category"`
	URL      string `json:"url"` //  // URL. Can be "Meta Links" (see https://github.com/Stremio/stremio-addon-sdk/blob/f6f1f2a8b627b9d4f2c62b003b251d98adadbebe/docs/api/responses/meta.links.md)
}

MetaLinkItem links to a page within Stremio. It will at some point replace the usage of `genres`, `director` and `cast`. Note: It's not fully supported by Stremio yet (not fully on PC and not at all on Android)!

type MetaPreviewItem

type MetaPreviewItem struct {
	ID     string `json:"id"`
	Type   string `json:"type"`
	Name   string `json:"name"`
	Poster string `json:"poster"` // URL

	// Optional
	PosterShape string `json:"posterShape,omitempty"`

	// Optional, used for the "Discover" page sidebar
	Genres      []string       `json:"genres,omitempty"`   // Will be replaced by Links at some point
	Director    []string       `json:"director,omitempty"` // Will be replaced by Links at some point
	Cast        []string       `json:"cast,omitempty"`     // Will be replaced by Links at some point
	Links       []MetaLinkItem `json:"links,omitempty"`    // For genres, director, cast and potentially more. Not fully supported by Stremio yet!
	IMDbRating  string         `json:"imdbRating,omitempty"`
	ReleaseInfo string         `json:"releaseInfo,omitempty"` // E.g. "2000" for movies and "2000-2014" or "2000-" for TV shows
	Description string         `json:"description,omitempty"`
}

MetaPreviewItem represents a meta preview item and is meant to be used within catalog responses. See https://github.com/Stremio/stremio-addon-sdk/blob/f6f1f2a8b627b9d4f2c62b003b251d98adadbebe/docs/api/responses/meta.md#meta-preview-object

type Options

type Options struct {
	// The interface to bind to.
	// "0.0.0.0" to bind to all interfaces. "localhost" to *exclude* requests from other machines.
	// Default "localhost".
	BindAddr string
	// The port to listen on.
	// Default 8080.
	Port int
	// You can set a custom logger, or leave this empty to create a new one
	// with sane defaults and the LoggingLevel in these options.
	// If you already called `NewLogger()`, you should set that logger here.
	// Default nil.
	Logger *zap.Logger
	// The logging level.
	// Only logs with the same or a higher log level will be shown.
	// For example when you set it to "info", info, warn and error logs will be shown, but no debug logs.
	// Accepts "debug", "info", "warn" and "error".
	// Only required when not already setting the Logger in the options.
	// Default "info".
	LoggingLevel string
	// Configures zap's log encoding.
	// "console" will format a log line console-friendly.
	// "json" is better suited when using a centralized log solution like ELK, Graylog or Loki.
	// Default "console".
	LogEncoding string
	// Flag for indicating whether requests should be logged.
	// Default false (meaning requests will be logged by default).
	DisableRequestLogging bool
	// Flag for indicating whether IP addresses should be logged.
	// Default false.
	LogIPs bool
	// Flag for indicating whether the user agent header should be logged.
	// Default false.
	LogUserAgent bool
	// URL to redirect to when someone requests the root of the handler instead of the manifest, catalog, stream etc.
	// When no value is set, it will lead to a "404 Not Found" response.
	// Default "".
	RedirectURL string
	// Flag for indicating whether you want to expose URL handlers for the Go profiler.
	// The URLs are be the standard ones: "/debug/pprof/...".
	// Default false.
	Profiling bool
	// Flag for indicating whether you want to collect and expose Prometheus metrics.
	// The URL is the standard one: "/metrics".
	// There's no credentials required for accessing it. If you expose deflix-stremio to the public,
	// you might want to protect the metrics route in your reverse proxy.
	// Default false.
	Metrics bool
	// Duration of client/proxy-side cache for responses from the catalog endpoint.
	// Helps reducing number of requsts and transferred data volume to/from the server.
	// The result is not cached by the SDK on the server side, so if two *separate* users make a reqeust,
	// and no proxy cached the response, your CatalogHandler will be called twice.
	// Default 0.
	CacheAgeCatalogs time.Duration
	// Same as CacheAgeCatalogs, but for streams.
	CacheAgeStreams time.Duration
	// Flag for indicating to proxies whether they are allowed to cache responses from the catalog endpoint.
	// Default false.
	CachePublicCatalogs bool
	// Same as CachePublicCatalogs, but for streams.
	CachePublicStreams bool
	// Flag for indicating whether the "ETag" header should be set and the "If-None-Match" header checked.
	// Helps reducing the transferred data volume from the server even further.
	// Only makes sense when setting a non-zero CacheAgeCatalogs.
	// Leads to a slight computational overhead due to every CatalogHandler result being hashed.
	// Default false.
	HandleEtagCatalogs bool
	// Same as HandleEtagCatalogs, but for streams.
	HandleEtagStreams bool
	// Flag for indicating whether user data is Base64-encoded.
	// As the user data is in the URL it needs to be the URL-safe Base64 encoding described in RFC 4648.
	// When true, go-stremio first decodes the value before passing or unmarshalling it.
	// Default false.
	UserDataIsBase64 bool
	// Flag for indicating whether to look up the movie / TV show name by its IMDb ID and put it into the context.
	// Only works for stream requests.
	// Default false.
	PutMetaInContext bool
	// Flag for indicating whether to include the movie / TV show name (and year) in the request log.
	// Only works for stream requests.
	// Default false.
	LogMediaName bool
	// Meta client for fetching movie and TV show info.
	// Only relevant when using PutMetaInContext or LogMediaName.
	// You can set it if you have already created one to share its in-memory cache for example,
	// or leave it empty to let go-stremio create a client that fetches metadata from Stremio's Cinemeta remote addon.
	MetaClient MetaFetcher
	// Timeout for requests to Cinemeta.
	// Only relevant when using PutMetaInContext or LogMediaName.
	// Only required when not setting a MetaClient in the options already.
	// Note that each response is cached for 30 days, so waiting a bit once per movie / TV show per 30 days is acceptable.
	// Default 2 seconds.
	CinemetaTimeout time.Duration
	// "File system" with HTML files that will be served for the "/configure" endpoint.
	// Typically an `http.Dir`, which you can simply create with `http.Dir("/path/to/html/files")`.
	// No configure endpoint will be created if this is nil, so you can add a custom one.
	// Default nil.
	ConfigureHTMLfs http.FileSystem
	// Regex for accepted stream IDs.
	// Even when setting the "tt" prefix in the manifest to only allow IMDb IDs, some clients still send stream requests for completely different IDs,
	// potentially leading to your handlers being triggered and executing some logic before than failing due to the bad ID.
	// With this regex you can make sure your handlers are only called for valid IDs. An empty value will lead to your handlers being called for any ID.
	// IMDb example: "tt\\d{7,8}" or `tt\d{7,8}`
	// Default "".
	StreamIDregex string
}

Options are the options that can be used to configure the addon.

type ResourceItem

type ResourceItem struct {
	Name  string   `json:"name"`
	Types []string `json:"types"` // Stremio supports "movie", "series", "channel" and "tv"

	// Optional
	IDprefixes []string `json:"idPrefixes,omitempty"`
}

type StreamHandler

type StreamHandler func(ctx context.Context, id string, userData interface{}) ([]StreamItem, error)

StreamHandler is the callback for stream requests for a specific type (like "movie"). The context parameter contains a meta object under the key "meta" if PutMetaInContext was set to true in the addon options. The id parameter can be for example an IMDb ID if your addon handles the "movie" type. The userData parameter depends on whether you called `RegisterUserData()` before: If not, a simple string will be passed. It's empty if the user didn't provide user data. If yes, a pointer to an object you registered will be passed. It's nil if the user didn't provide user data.

type StreamItem

type StreamItem struct {
	// One of the following is required
	URL         string `json:"url,omitempty"` // URL
	YoutubeID   string `json:"ytId,omitempty"`
	InfoHash    string `json:"infoHash,omitempty"`
	ExternalURL string `json:"externalUrl,omitempty"` // URL

	// Optional
	Title     string `json:"title,omitempty"`   // Usually used for stream quality
	FileIndex uint8  `json:"fileIdx,omitempty"` // Only when using InfoHash

}

StreamItem represents a stream for a MetaItem. See https://github.com/Stremio/stremio-addon-sdk/blob/f6f1f2a8b627b9d4f2c62b003b251d98adadbebe/docs/api/responses/stream.md

type VideoItem

type VideoItem struct {
	ID       string `json:"id"`
	Title    string `json:"title"`
	Released string `json:"released"` // Must be ISO 8601, e.g. "2010-12-06T05:00:00.000Z"

	// Optional
	Thumbnail string       `json:"thumbnail,omitempty"` // URL
	Streams   []StreamItem `json:"streams,omitempty"`
	Available bool         `json:"available,omitempty"`
	Episode   string       `json:"episode,omitempty"`
	Season    string       `json:"season,omitempty"`
	Trailer   string       `json:"trailer,omitempty"` // Youtube ID
	Overview  string       `json:"overview,omitempty"`
}

Directories

Path Synopsis
examples
pkg

Jump to

Keyboard shortcuts

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