@neoworks-dev/otter-sdk
v0.1.0
Published
Shared TypeScript library for building Otter plugins. Provides all media types, the stdin/stdout JSON protocol handler (`runPlugin`), and HTTP utilities with browser-compatible headers.
Readme
@neoworks-dev/otter-sdk
Shared TypeScript library for building Otter plugins. Provides all media types, the stdin/stdout JSON protocol handler (runPlugin), and HTTP utilities with browser-compatible headers.
Overview
All Otter plugins communicate with the Go backend over a stdin/stdout JSON protocol. This SDK handles that protocol so plugin authors only need to implement their capability logic. It also exports all shared media types and a set of HTTP helpers with browser-compatible headers.
Exports
| Export | Description |
| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| runPlugin(handlers) | Reads one JSON invocation from stdin, dispatches to the correct handler, writes the result to stdout, and exits |
| Types (Movie, Series, Episode, ScrapeResult, etc.) | All media types mirrored from internal/plugins/types.go in the Go backend |
| fetchHtml(url, headers?) | fetch wrapper with browser UA and Accept headers |
| followRedirect(url) | Follows redirects and returns the final URL |
| resolveUrl(base, path) | Resolves a relative or protocol-relative path against a base URL |
| domainOf(url) | Extracts the hostname without www. prefix |
Protocol
Otter invokes a plugin by running bun run <main> and writing a single JSON object to stdin:
{ "capability": "scrape", "args": { "url": "https://example.com/movie/123" } }runPlugin dispatches to the registered handler and writes the result to stdout:
{ "result": { ... } }On error:
{ "error": "message" }Scrape is the exception — it emits one ScrapeResult per line (NDJSON), root item first, then children (seasons → episodes):
{"type":"series","series":{...}}
{"type":"season","season":{...}}
{"type":"episode","episode":{...}}Usage
import { runPlugin } from "@shutterly/sdk";
runPlugin({
meta: {
name: "my-plugin",
version: "0.1.0",
capabilities: ["scrape"],
},
scrape: async (url) => {
// return ScrapeResult[]
},
});Media type hierarchy
MediaBase
├── Movie — year, duration_minutes, trailer_urls
├── Series — year, status
│ └── Season — series_external_id, number
│ └── Episode — season_number, number, duration_minutes, air_date
├── Gallery — year
├── AdultMovie — acts, series_name, series_number
├── Scene — number, acts
├── AdultGallery — acts
└── AdultPerson — full performer profileInstallation
This package is a local dependency — installed by referencing the path:
{ "@shutterly/sdk": "file:../sdk" }bun installLicense
MIT
