| package bex:plugin@1.0.0; |
|
|
| interface common { |
| record request-context { |
| request-id: string, |
| locale: option<string>, |
| region: option<string>, |
| safe-mode: bool, |
| hints: list<string>, |
| } |
| record attr { key: string, value: string } |
| enum image-layout { portrait, landscape, square, banner, circular, unknown } |
| record image { |
| url: string, |
| layout: image-layout, |
| width: option<u32>, |
| height: option<u32>, |
| blurhash: option<string>, |
| } |
| record image-set { |
| low: option<image>, |
| medium: option<image>, |
| high: option<image>, |
| backdrop: option<image>, |
| logo: option<image>, |
| } |
| record linked-id { source: string, id: string } |
| enum media-kind { movie, series, anime, short, special, documentary, music, podcast, book, live, unknown } |
| enum status { unknown, upcoming, ongoing, completed, cancelled, paused } |
| enum card-layout { carousel, grid, vertical-list, banner, compact } |
| record page-cursor { token: option<string>, limit: option<u32> } |
| record media-card { |
| id: string, |
| title: string, |
| kind: option<media-kind>, |
| images: option<image-set>, |
| original-title: option<string>, |
| tagline: option<string>, |
| year: option<string>, |
| score: option<u32>, |
| genres: list<string>, |
| status: option<status>, |
| content-rating: option<string>, |
| url: option<string>, |
| ids: list<linked-id>, |
| extra: list<attr>, |
| } |
| record category-link { id: string, title: string, subtitle: option<string>, image: option<image> } |
| record home-section { |
| id: string, |
| title: string, |
| subtitle: option<string>, |
| items: list<media-card>, |
| next-page: option<string>, |
| layout: card-layout, |
| show-rank: bool, |
| categories: list<category-link>, |
| extra: list<attr>, |
| } |
| record paged-result { |
| items: list<media-card>, |
| categories: list<category-link>, |
| next-page: option<string>, |
| } |
| record search-filters { kind: option<media-kind>, page: page-cursor, fast-match: bool } |
| record episode { |
| id: string, |
| title: string, |
| number: option<f64>, |
| season: option<f64>, |
| images: option<image-set>, |
| description: option<string>, |
| released: option<string>, |
| score: option<u32>, |
| url: option<string>, |
| tags: list<string>, |
| extra: list<attr>, |
| } |
| record season { id: string, title: string, number: option<f64>, year: option<u32>, episodes: list<episode> } |
| record person { id: string, name: string, image: option<image-set>, role: option<string>, url: option<string> } |
| record media-info { |
| id: string, |
| title: string, |
| kind: media-kind, |
| images: option<image-set>, |
| original-title: option<string>, |
| description: option<string>, |
| score: option<u32>, |
| scored-by: option<u64>, |
| year: option<string>, |
| release-date: option<string>, |
| genres: list<string>, |
| tags: list<string>, |
| status: option<status>, |
| content-rating: option<string>, |
| seasons: list<season>, |
| cast: list<person>, |
| crew: list<person>, |
| runtime-minutes: option<u32>, |
| trailer-url: option<string>, |
| ids: list<linked-id>, |
| studio: option<string>, |
| country: option<string>, |
| language: option<string>, |
| url: option<string>, |
| extra: list<attr>, |
| } |
| record video-resolution { width: u32, height: u32, hdr: bool, label: string } |
| enum stream-format { hls, dash, progressive, unknown } |
| record video-track { |
| resolution: video-resolution, |
| url: string, |
| mime-type: option<string>, |
| bitrate: option<u64>, |
| codecs: option<string>, |
| } |
| record subtitle-track { label: string, url: string, language: option<string>, format: option<string> } |
| record server { id: string, label: string, url: string, priority: u8, extra: list<attr> } |
| record stream-source { |
| id: string, |
| label: string, |
| format: stream-format, |
| manifest-url: option<string>, |
| videos: list<video-track>, |
| subtitles: list<subtitle-track>, |
| headers: list<attr>, |
| extra: list<attr>, |
| } |
| record subtitle-query { |
| title: option<string>, |
| year: option<u32>, |
| season: option<u32>, |
| episode: option<u32>, |
| language: option<string>, |
| fps: option<f32>, |
| file-hash: option<string>, |
| file-size: option<u64>, |
| identifiers: list<linked-id>, |
| } |
| record subtitle-entry { |
| id: string, |
| title: string, |
| language: string, |
| format: string, |
| url: option<string>, |
| release: option<string>, |
| fps: option<f32>, |
| downloads: option<u64>, |
| score: option<u32>, |
| hearing-impaired: bool, |
| machine-translated: bool, |
| file-hash: option<string>, |
| extra: list<attr>, |
| } |
| record subtitle-file { format: string, content: list<u8> } |
| record article { |
| id: string, |
| title: string, |
| summary: option<string>, |
| url: string, |
| published: option<string>, |
| author: option<string>, |
| thumbnail: option<image-set>, |
| tags: list<string>, |
| extra: list<attr>, |
| } |
| record article-section { id: string, title: string, items: list<article>, next-page: option<string> } |
| variant plugin-error { |
| network(string), |
| parse(string), |
| not-found, |
| unauthorized, |
| forbidden, |
| rate-limited(option<u32>), |
| timeout, |
| cancelled, |
| unsupported, |
| invalid-input(string), |
| internal(string), |
| } |
| } |
| |
| interface http { |
| use common.{attr, plugin-error}; |
| |
| enum method { get, post, put, delete, head, patch, options } |
| enum cache-mode { normal, no-store, only-cache, force-refresh } |
| record request { |
| method: method, |
| url: string, |
| headers: list<attr>, |
| body: option<list<u8>>, |
| timeout-ms: option<u32>, |
| follow-redirects: bool, |
| cache-mode: cache-mode, |
| max-bytes: option<u64>, |
| } |
| record response { |
| status: u16, |
| headers: list<attr>, |
| body: list<u8>, |
| cached: bool, |
| final-url: string, |
| } |
| |
| /// Send an HTTP request and return the response. |
| /// This is a simple function-based API (no resource types) for simplicity. |
| send-request: func(req: request) -> result<response, plugin-error>; |
| } |
| |
| interface kv { |
| use common.{attr}; |
| set: func(key: string, value: list<u8>, ttl-seconds: option<u32>) -> bool; |
| get: func(key: string) -> option<list<u8>>; |
| remove: func(key: string) -> bool; |
| keys: func(prefix: string) -> list<string>; |
| } |
| |
| interface secrets { |
| get: func(key: string) -> option<string>; |
| } |
| |
| interface log { |
| use common.{attr}; |
| enum level { trace, debug, info, warn, error } |
| write: func(level: level, msg: string, fields: list<attr>); |
| } |
| |
| interface clock { |
| now-ms: func() -> u64; |
| monotonic: func() -> u64; |
| } |
| |
| interface rng { |
| bytes: func(len: u32) -> list<u8>; |
| } |
| |
| world plugin { |
| import http; |
| import kv; |
| import secrets; |
| import log; |
| import clock; |
| import rng; |
| |
| export api: interface { |
| use common.{ |
| request-context, page-cursor, paged-result, search-filters, |
| home-section, media-info, server, stream-source, |
| subtitle-query, subtitle-entry, subtitle-file, |
| article-section, article, plugin-error |
| }; |
| get-home: func(ctx: request-context) -> result<list<home-section>, plugin-error>; |
| get-category: func(ctx: request-context, id: string, page: page-cursor) -> result<paged-result, plugin-error>; |
| search: func(ctx: request-context, query: string, filters: search-filters) -> result<paged-result, plugin-error>; |
| get-info: func(ctx: request-context, id: string) -> result<media-info, plugin-error>; |
| get-servers: func(ctx: request-context, id: string) -> result<list<server>, plugin-error>; |
| resolve-stream: func(ctx: request-context, server: server) -> result<stream-source, plugin-error>; |
| search-subtitles: func(ctx: request-context, query: subtitle-query) -> result<list<subtitle-entry>, plugin-error>; |
| download-subtitle: func(ctx: request-context, id: string) -> result<subtitle-file, plugin-error>; |
| get-articles: func(ctx: request-context) -> result<list<article-section>, plugin-error>; |
| search-articles: func(ctx: request-context, query: string) -> result<list<article>, plugin-error>; |
| } |
| } |
| |