StreamujTo Logo StreamujTo Stáhnout

Dokumentace Addon Systému

Kompletní průvodce tvorbou externích doplňků úložišť pro StreamujTo

Úvod

Aplikace StreamujTo v základní instalaci neobsahuje žádný zdroj streamů ani přístup k žádnému úložišti. Veškerá funkcionalita spojená s vyhledáváním a přehráváním souborů z externích služeb je zajištěna doplňky (addony), které si uživatel importuje sám – z URL adresy nebo lokálního JSON souboru.

Addon je čistě deklarativní JSON soubor, který popisuje:

Addon neobsahuje žádný spustitelný kód. Jedná se o deklarativní pipeline, kterou interpretuje vestavěný Addon Engine aplikace.

Addon systém je navržen tak, aby byl maximálně bezpečný. JSON definice nemůže spustit libovolný kód – může pouze provádět předem definované akce (HTTP požadavky, hashování, regex).

Architektura

Addon systém se skládá z následujících komponent:

┌──────────────────────────────────────────────────────────────┐ StreamujTo App │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ AddonStore │ │ AddonRegistry │ │ AddonImporter │ │ │ │ (persistence) │ │ (runtime) │ │ (URL/file) │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ └───────────┬───────┘───────────┬───────┘ │ │ ▼ ▼ │ │ ┌──────────────────────────────────┐ │ │ │ AddonEngine │ │ │ │ (JSON interpreter / runner) │ │ │ └────────────────┬─────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────┐ │ │ │ AddonInterface │ │ │ │ (abstract API kontrakt) │ │ │ └──────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────┘
KomponentaPopis
AddonDefinitionDatový model parsovaný z JSON souboru. Obsahuje manifest, auth, search a streamUrl sekce.
AddonEngineInterpret, který implementuje AddonInterface na základě JSON definice. Vykonává pipeline kroků (steps).
AddonStorePersistentní úložiště (SharedPreferences). Ukládá raw JSON definice, takže přežijí restart aplikace.
AddonRegistrySingleton registr běžících addonů. Spravuje stav, credentials, aktivní addon.
AddonImporterImport z URL (HTTP download) nebo lokálního souboru (file picker).
AddonInterfaceAbstraktní kontrakt definující metody: authenticate, search, getStreamUrl, atd.

Životní cyklus addonu

  1. Import – uživatel zadá URL nebo vybere JSON soubor. AddonImporter stáhne/přečte JSON a validuje ho.
  2. ParsováníAddonDefinition.fromJson() rozloží JSON na strukturované objekty (manifest, auth, search, streamUrl).
  3. Registrace – vytvoří se AddonEngine instance a zaregistruje se do AddonRegistry.
  4. Persistence – raw JSON se uloží do AddonStore (SharedPreferences), aby addon přežil restart.
  5. Autentizace – uživatel vyplní přihlašovací údaje → engine spustí auth.login pipeline.
  6. Použití – při vyhledávání engine spustí search pipeline, při přehrávání streamUrl pipeline.
  7. Obnova – při startu aplikace StorageManager načte všechny definice z AddonStore a obnoví enginy + autentizaci.

Kořenová struktura JSON

Každý addon je jeden JSON soubor s následující kořenovou strukturou:

JSON{
  "manifest": { ... },
  "auth": { ... },
  "search": { ... },
  "streamUrl": { ... }
}
KlíčTypPovinnýPopis
manifestObjectAnoMetadata addonu – identifikace, verze, schopnosti.
authObjectNeDefinice autentizačního flow. Pokud chybí, addon nevyžaduje přihlášení.
searchObjectAnoPipeline pro vyhledávání souborů.
streamUrlObjectAnoPipeline pro získání přímého stream odkazu.

Sekce manifest

Manifest obsahuje veškeré metadata o addonu. Tyto informace se zobrazují v nastavení aplikace.

JSON{
  "manifest": {
    "id": "muj-addon",
    "name": "Můj Addon",
    "version": "1.0.0",
    "description": "Popis toho, co addon dělá.",
    "author": "Jan Novák",
    "type": "api",
    "capabilities": ["search", "auth", "directStream"],
    "homeUrl": "https://example.com",
    "iconUrl": "https://example.com/icon.png"
  }
}
PoleTypPovinnýPopis
idStringAnoUnikátní identifikátor addonu. Používá se interně pro ukládání stavu, credentials apod. Doporučený formát: kebab-case bez mezer a diakritiky (např. "webshare", "muj-addon").
nameStringAnoZobrazovaný název addonu v UI (např. "Webshare.cz").
versionStringNeVerze addonu ve formátu semver. Výchozí: "1.0.0".
descriptionStringNeKrátký popis addonu.
authorStringNeJméno autora addonu. Výchozí: "Unknown".
typeStringNeTyp addonu: "api", "scraper" nebo "hybrid". Výchozí: "api". Viz Addon Types.
capabilitiesArray<String>NeSeznam schopností addonu. Výchozí: ["search"]. Viz Capabilities.
homeUrlStringNeURL domovské stránky služby.
iconUrlStringNeURL ikony addonu (zobrazuje se v UI).

Pole id musí být napříč všemi addony unikátní. Pokud se pokusíte importovat addon se stejným id jako již nainstalovaný, import bude odmítnut.

Sekce auth

Definuje autentizační flow – tj. jaká pole uživatel vyplní a jaké kroky se provedou pro přihlášení, ověření stavu a odhlášení.

JSON{
  "auth": {
    "type": "credentials",
    "fields": [
      {
        "key": "username",
        "label": "Uživatelské jméno",
        "hint": "Zadejte uživatelské jméno",
        "isSecret": false,
        "required": true
      },
      {
        "key": "password",
        "label": "Heslo",
        "hint": "Zadejte heslo",
        "isSecret": true,
        "required": true
      }
    ],
    "login": [ ... ],
    "check": [ ... ],
    "logout": [ ... ]
  }
}

Typy autentizace

Hodnota typePopis
"none"Addon nevyžaduje přihlášení. Sekce auth může zcela chybět.
"credentials"Klasické přihlášení uživatelským jménem a heslem.
"token"Autentizace API tokenem / klíčem.
"oauth"OAuth2 flow (rezervováno pro budoucí použití).

Definice polí (fields)

Pole definují formulář, který se zobrazí uživateli v nastavení. Klíč (key) se použije jako název proměnné – viz Proměnné.

PoleTypPovinnýPopis
keyStringAnoUnikátní klíč pole. Stane se názvem runtime proměnné (např. "username", "api_key").
labelStringAnoPopisek zobrazený v UI.
hintStringNePlaceholder / nápověda v textovém poli.
isSecretBooleanNeZobrazit jako heslo (skryté znaky). Výchozí: false.
requiredBooleanNeJe pole povinné? Výchozí: true.

Login / Check / Logout pipelines

Každá z těchto sekcí je pole kroků (steps) – viz Akce.

PipelineKdy se spouštíPovinný
loginKdyž uživatel vyplní credentials a potvrdí přihlášení.Ne (ale bez něj se přihlášení nespustí)
checkKdyž engine potřebuje ověřit, zda je session stále platná.Ne (fallback: kontrola existence proměnné token)
logoutKdyž se uživatel odhlásí.Ne

Pokud pipeline check není definován, engine jako fallback zkontroluje, zda existuje neprázdná runtime proměnná token. Proto je doporučeno, aby login kroky uložily token do proměnné s klíčem "token".

Definuje pipeline pro vyhledávání souborů. Výsledkem musí být seznam položek (viz Seznam výsledků).

JSON{
  "search": {
    "steps": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://api.example.com/search",
        "contentType": "application/x-www-form-urlencoded",
        "body": "q={{query}}&limit=100&token={{token}}",
        "responseType": "xml",
        "listElement": "file",
        "itemMapping": {
          "title": "name",
          "size": "size",
          "link": "ident"
        }
      }
    ]
  }
}

Search pipeline má přístup k těmto automaticky dostupným proměnným:

ProměnnáHodnota
{{query}}Hledaný text zadaný uživatelem.
{{page}}Číslo stránky (1-based) pro stránkování výsledků.
{{token}}Autentizační token (pokud addon vyžaduje auth).

Item Mapping

Klíčový parametr HTTP kroku v search pipeline je itemMapping, který mapuje pole z odpovědi na interní strukturu:

Cílové polePovinnýPopis
title nebo nameAnoNázev souboru. Engine nejdřív hledá title, pak name.
sizeNeVelikost souboru v bajtech (celé číslo). Engine automaticky převede na čitelný formát (MB/GB).
link nebo urlAnoUnikátní identifikátor položky. Bude předán do streamUrl pipeline jako {{identifier}}.

Sekce streamUrl

Definuje pipeline pro získání přímého streamovacího odkazu ze zvoleného souboru.

JSON{
  "streamUrl": {
    "steps": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://api.example.com/file_link",
        "contentType": "application/x-www-form-urlencoded",
        "body": "ident={{identifier}}&token={{token}}",
        "responseType": "xml",
        "outputs": {
          "stream_url": "link"
        }
      }
    ],
    "result": "{{stream_url}}",
    "headers": {
      "Referer": "https://example.com/",
      "User-Agent": "StreamujTo/1.0",
      "Authorization": "Bearer {{token}}"
    }
  }
}
PoleTypPopis
stepsArray<Step>Pipeline kroků pro získání odkazu.
resultStringTemplate s proměnnou, která obsahuje finální stream URL. Typicky "{{stream_url}}".
headersObjectNe Extra HTTP hlavičky, které přehrávač pošle při streamování. Podporuje template proměnné. Typicky Referer, User-Agent, Cookie nebo Authorization.

StreamUrl pipeline má automaticky k dispozici:

ProměnnáHodnota
{{identifier}}Identifikátor souboru ze search výsledků (hodnota z link/url v itemMapping).
{{token}}Autentizační token.

Akce: http

Provede HTTP požadavek. Nejdůležitější a nejčastěji používaná akce.

JSON{
  "action": "http",
  "method": "POST",
  "url": "https://api.example.com/endpoint",
  "contentType": "application/x-www-form-urlencoded",
  "body": "param1={{value1}}¶m2={{value2}}",
  "responseType": "xml",
  "headers": {
    "Authorization": "Bearer {{token}}",
    "X-Custom": "value"
  },
  "outputs": {
    "moje_promenna": "xml_tag_name"
  }
}
ParametrTypVýchozíPopis
actionStringMusí být "http".
methodString"GET"HTTP metoda: "GET" nebo "POST".
urlStringURL endpointu. Podporuje interpolaci.
contentTypeStringHodnota hlavičky Content-Type.
bodyStringTělo požadavku (pro POST). Podporuje interpolaci.
responseTypeString"xml"Formát odpovědi: "xml" nebo "json". Ovlivňuje parsování outputs.
headersObject{}Vlastní HTTP hlavičky. Hodnoty podporují interpolaci.
outputsObjectMapování: { "nazev_promenne": "cesta_v_odpovedi" }. Viz XML / JSON parsing.
listElementStringPouze v search: název elementu, který představuje jednu položku v seznamu.
itemMappingObjectPouze v search: mapování polí položky. Viz Seznam výsledků.

Pokud HTTP krok vrátí jiný status než 200, celá pipeline selže. Engine nepodporuje přesměrování ani jiné 2xx kódy.

Akce: md5crypt

Vypočítá Unix MD5-crypt hash (formát $1$salt$hash). Používá se typicky pro starší API, které vyžadují tento typ hashování hesel.

JSON{
  "action": "md5crypt",
  "input": "{{password}}",
  "salt": "{{salt}}",
  "output": "crypted_password"
}
ParametrTypPopis
inputStringVstupní text (typicky heslo). Podporuje interpolaci.
saltStringSalt pro hashování. Podporuje interpolaci. Max 8 znaků.
outputStringNázev proměnné, do které se uloží výsledný hash.

Příklad výstupu: $1$abcdefgh$k4x3gHwmKj1vC0B.Xr5M/.

Akce: sha1

Vypočítá SHA-1 hash vstupního textu.

JSON{
  "action": "sha1",
  "input": "{{crypted_password}}",
  "output": "hashed_password"
}
ParametrTypPopis
inputStringVstupní text. Podporuje interpolaci.
outputStringNázev proměnné pro hex-encoded výstup.

Příklad výstupu: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3

Akce: md5

Vypočítá MD5 hash vstupního textu.

JSON{
  "action": "md5",
  "input": "{{some_value}}",
  "output": "md5_hash"
}
ParametrTypPopis
inputStringVstupní text. Podporuje interpolaci.
outputStringNázev proměnné pro hex-encoded výstup.

Příklad výstupu: 5d41402abc4b2a76b9719d911017c592

Akce: assert

Porovná hodnotu runtime proměnné s očekávanou hodnotou. Pokud se neshodují, pipeline selže a další kroky se neprovádí.

JSON{
  "action": "assert",
  "variable": "login_status",
  "equals": "OK"
}
ParametrTypPopis
variableStringNázev runtime proměnné k ověření.
equalsStringOčekávaná hodnota.

Assert je klíčový pro validaci odpovědí API. Umístěte ho bezprostředně za HTTP krok, abyste ověřili, že operace (přihlášení, vyhledávání) proběhla úspěšně.

Akce: clear

Odstraní runtime proměnné ze stavu enginu.

JSON{
  "action": "clear",
  "variables": ["token", "salt", "crypted_password", "temp_value"]
}
ParametrTypPopis
variablesArray<String>Seznam názvů proměnných k odstranění.

Typicky se používá v logout pipeline pro vyčištění tokenů.

Akce: regex

Extrahuje text z hodnoty proměnné pomocí regulárního výrazu.

JSON{
  "action": "regex",
  "input": "{{_response}}",
  "pattern": "href=\"(https://[^\"]+\\.mp4)\"",
  "group": 1,
  "output": "video_url"
}
ParametrTypVýchozíPopis
inputStringVstupní text. Podporuje interpolaci. Typicky {{_response}}.
patternStringRegulární výraz (Dart/PCRE syntaxe).
groupInteger1Číslo zachytávací skupiny k extrakci.
outputStringNázev proměnné pro extrahovanou hodnotu.
optionalBooleanfalsePokud true, selhání kroku nezpůsobí selhání celého pipeline — pokračuje se dalším krokem. Viz Volitelné kroky.

Pokud regex nenajde shodu a krok není označený jako "optional": true, pipeline selže. Ujistěte se, že vzor odpovídá formátu odpovědi, nebo použijte volitelné kroky s fallbackem.

Volitelné kroky (optional)

Jakýkoli krok v pipeline může být označen jako volitelný přidáním "optional": true. Pokud volitelný krok selže, pipeline pokračuje dalším krokem místo okamžitého ukončení.

U akce regex platí navíc: pokud je výstupní proměnná (output) již naplněná předchozím krokem, volitelný regex se přeskočí. To umožňuje řetězení fallbacků:

Příklad — fallback řetězení{
  "steps": [
    { "action": "http", "method": "GET", "url": "https://api.example.com/{{identifier}}", "responseType": "json" },
    {
      "action": "regex",
      "input": "{{_response}}",
      "pattern": "\"name\":\\s*\"([^\"]+\\.mp4)\",\\s*\"source\":\\s*\"original\"",
      "group": 1,
      "output": "video_file",
      "optional": true
    },
    {
      "action": "regex",
      "input": "{{_response}}",
      "pattern": "\"name\":\\s*\"([^/\"]+\\.mp4)\"",
      "group": 1,
      "output": "video_file",
      "optional": true
    }
  ],
  "result": "https://example.com/download/{{identifier}}/{{video_file|urlencode}}"
}

V tomto příkladě se nejprve hledá MP4 soubor s source: "original". Pokud není nalezen, druhý regex zkusí najít jakýkoli MP4. Pokud první regex uspěje, druhý se přeskočí (proměnná video_file je již nastavena).

Parametr optional lze použít u všech akcí (http, regex, assert, atd.), nejen u regex.

Akce: set

Přímo nastaví proměnnou na zadanou hodnotu. Užitečné pro sestavení složených hodnot z více proměnných nebo nastavení výchozí hodnoty.

JSON{
  "action": "set",
  "output": "full_url",
  "value": "https://cdn.example.com/{{path}}/{{filename|urlencode}}"
}
ParametrTypPopis
outputStringNázev proměnné, do které se uloží výsledek.
valueStringHodnota (podporuje interpolaci a filtry).

Akce: parallel

Spustí více nezávislých kroků současně. Všechny vnořené kroky běží paralelně a výsledek je úspěšný, pokud všechny uspějí.

JSON{
  "action": "parallel",
  "steps": [
    {
      "action": "http",
      "method": "GET",
      "url": "https://api.example.com/metadata/{{identifier}}",
      "responseType": "json",
      "outputs": { "meta_title": "title" }
    },
    {
      "action": "http",
      "method": "GET",
      "url": "https://api.example.com/files/{{identifier}}",
      "responseType": "json",
      "outputs": { "file_url": "url" }
    }
  ]
}
ParametrTypPopis
stepsArray<Step>Seznam kroků ke spuštění paralelně. Každý krok je standardní definice akce.

Paralelní kroky by neměly záviset navzájem na svých výstupech. Pokud krok B potřebuje výstup kroku A, musí běžet sekvenčně (mimo parallel).

Proměnné

Addon Engine udržuje runtime slovník proměnných (Map<String, String>). Proměnné se plní z:

Interpolace {{proměnná}}

Kde je v parametrech textová hodnota, lze použít interpolaci dvojitými složenými závorkami:

Příklad"url": "https://api.example.com/search?q={{query}}&token={{token}}"
"body": "username={{username}}&password={{hashed_password}}"
"input": "{{crypted}}"

Engine nahradí každý výskyt {{nazev}} aktuální hodnotou ze slovníku proměnných. Pokud proměnná neexistuje, nahradí se prázdným řetězcem.

Filtry {{proměnná|filtr}}

Za název proměnné lze přidat filtr oddělený svislítkem (|), který transformuje hodnotu před vložením:

Příklad"url": "https://api.example.com/search?q={{query|urlencode}}"
"body": "token={{token|base64}}"
"header": "{{api_key|uppercase}}"
FiltrPopisPříklad vstupu → výstupu
urlencodeURL-enkódování (percent-encoding). Doporučeno pro {{query}} v URL.Český film%C4%8Cesk%C3%BD%20film
base64Base64 enkódování.helloaGVsbG8=
lowercasePřevod na malá písmena.HELLOhello
uppercasePřevod na velká písmena.helloHELLO
trimOdstraň bílé znaky na začátku a konci. hello hello
htmldecodeDekoduje HTML entity.&amp; &lt;& <
lengthDélka řetězce (výstup je číslo).hello5
reverseObrátí znaky v řetězci.helloolleh
timestampVrátí aktuální Unix timestamp v sekundách (ignoruje hodnotu proměnné).1741700000
timestamp_msVrátí aktuální Unix timestamp v milisekundách.1741700000000

Pokud filtr není rozpoznán, hodnota se vloží bez transformace.

Speciální proměnné

ProměnnáAutomaticky dostupnáPopis
_responsePo každém HTTP krokuCelé tělo poslední HTTP odpovědi (raw text). Užitečné pro regex akci.
_http_statusPo neúspěšném HTTP krokuHTTP stavový kód posledního neúspěšného požadavku (např. 403, 500). Užitečné pro diagnostiku.
queryV search pipelineText, který uživatel hledá.
pageV search pipelineČíslo stránky (1, 2, 3...).
identifierV streamUrl pipelineIdentifikátor vybraného souboru (z itemMapping link/url).
tokenPo login pipelineAutentizační token. Doporučený název pro výstup z login kroků.
{{timestamp}}VždyAktuální Unix timestamp v sekundách. Lze použít přímo bez proměnné.
{{timestamp_ms}}VždyAktuální Unix timestamp v milisekundách.

XML parsing

Při "responseType": "xml" engine extrahuje hodnoty pomocí názvů XML tagů.

XML odpověď<response>
  <status>OK</status>
  <token>abc123xyz</token>
  <user_id>42</user_id>
</response>
outputs"outputs": {
  "status_var": "status",
  "token": "token",
  "uid": "user_id"
}

Výsledek: status_var = "OK", token = "abc123xyz", uid = "42"

XML parser podporuje tagy s atributy – např. <file id="123">...</file> bude nalezeno při hledání tagu file. Pro extrakci atributů použijte notáci tag@attr v mappingu (viz níže).

Pro extrakci atributů z XML tagů použijte notáci tag@atribut:

XML s atributy<files>
  <file id="abc123" type="video">Film.mp4</file>
  <file id="def456" type="subtitle">Film.srt</file>
</files>
itemMapping"itemMapping": {
  "title": "file",
  "link": "file@id",
  "type": "file@type"
}

Výsledek: link = "abc123", type = "video". Notáce @attr (bez tagu) extrahuje atribut z rodičovského elementu.

JSON parsing

Při "responseType": "json" engine používá tečkovou notaci pro navigaci v JSON struktuře.

JSON odpověď{
  "status": "ok",
  "data": {
    "token": "xyz789",
    "user": {
      "id": 42,
      "name": "Jan"
    }
  }
}
outputs"outputs": {
  "my_token": "data.token",
  "user_name": "data.user.name",
  "user_id": "data.user.id"
}

Výsledek: my_token = "xyz789", user_name = "Jan", user_id = "42"

Pro přístup k prvkům pole použijte číselný index nebo hranatou notaci:

JSON cesta s polem"outputs": {
  "first_item": "results[0].name",
  "first_item_alt": "results.0.name"
}

Pro filtrování pole podle hodnoty klíče použijte [?(@.key=='value')]:

JSON cesta s filtrem"outputs": {
  "video_file": "files[?(@.source=='original')].name"
}

Filtr projde pole files a vrátí první prvek, kde source je "original", pak z něj extrahuje name.

V itemMapping search kroků lze rovněž použít vnořené cesty: "title": "metadata.title" nebo "id": "files[0].id".

Seznam výsledků (List parsing)

Pro search pipeline musí HTTP krok s listElement identifikovat opakující se prvky v odpovědi:

XML seznam

XML odpověď<response>
  <status>OK</status>
  <file>
    <name>Film.2024.CZ.mkv</name>
    <size>1536000000</size>
    <ident>abc123</ident>
  </file>
  <file>
    <name>Film.2024.EN.mp4</name>
    <size>987000000</size>
    <ident>def456</ident>
  </file>
</response>
Search krok{
  "action": "http",
  "method": "POST",
  "url": "https://api.example.com/search",
  "body": "q={{query}}&token={{token}}",
  "responseType": "xml",
  "listElement": "file",
  "itemMapping": {
    "title": "name",
    "size": "size",
    "link": "ident"
  }
}

Engine najde všechny <file>...</file> bloky a z každého extrahuje name, size, ident podle mappingu.

JSON seznam

JSON odpověď{
  "status": "ok",
  "results": [
    { "title": "Film.2024.CZ.mkv", "filesize": 1536000000, "id": "abc123" },
    { "title": "Film.2024.EN.mp4", "filesize": 987000000, "id": "def456" }
  ]
}
Search krok{
  "action": "http",
  "method": "GET",
  "url": "https://api.example.com/search?q={{query|urlencode}}",
  "responseType": "json",
  "listElement": "results",
  "itemMapping": {
    "title": "title",
    "size": "filesize",
    "link": "id"
  }
}

listElement u JSON odpovědi je cesta (tečková notace) k poli objektů. U každého objektu se klíče z itemMapping použijí k nalezení příslušné hodnoty.

Příklad: Kompletní addon s autentizací

Ukázkový addon pro fiktivní službu „CloudStorage.cz" s plným auth flow (salt + md5crypt + sha1):

cloudstorage.json{
  "manifest": {
    "id": "cloudstorage",
    "name": "CloudStorage.cz",
    "version": "1.0.0",
    "description": "Demo addon pro CloudStorage.cz.",
    "author": "Komunita",
    "type": "api",
    "capabilities": ["search", "auth", "directStream"],
    "homeUrl": "https://cloudstorage.cz"
  },
  "auth": {
    "type": "credentials",
    "fields": [
      {
        "key": "username",
        "label": "Uživatelské jméno",
        "hint": "Váš e-mail nebo přezdívka",
        "isSecret": false,
        "required": true
      },
      {
        "key": "password",
        "label": "Heslo",
        "hint": "Zadejte heslo k účtu",
        "isSecret": true,
        "required": true
      }
    ],
    "login": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://cloudstorage.cz/api/salt/",
        "contentType": "application/x-www-form-urlencoded",
        "body": "username={{username}}",
        "responseType": "xml",
        "outputs": {
          "salt": "salt",
          "salt_status": "status"
        }
      },
      {
        "action": "assert",
        "variable": "salt_status",
        "equals": "OK"
      },
      {
        "action": "md5crypt",
        "input": "{{password}}",
        "salt": "{{salt}}",
        "output": "crypted"
      },
      {
        "action": "sha1",
        "input": "{{crypted}}",
        "output": "hashed_password"
      },
      {
        "action": "http",
        "method": "POST",
        "url": "https://cloudstorage.cz/api/login/",
        "contentType": "application/x-www-form-urlencoded",
        "body": "username={{username}}&password={{hashed_password}}&keep_logged_in=1",
        "responseType": "xml",
        "outputs": {
          "token": "token",
          "login_status": "status"
        }
      },
      {
        "action": "assert",
        "variable": "login_status",
        "equals": "OK"
      }
    ],
    "check": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://cloudstorage.cz/api/user_data/",
        "contentType": "application/x-www-form-urlencoded",
        "body": "token={{token}}",
        "responseType": "xml",
        "outputs": {
          "check_status": "status"
        }
      },
      {
        "action": "assert",
        "variable": "check_status",
        "equals": "OK"
      }
    ],
    "logout": [
      {
        "action": "clear",
        "variables": ["token", "salt", "crypted", "hashed_password"]
      }
    ]
  },
  "search": {
    "steps": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://cloudstorage.cz/api/search/",
        "contentType": "application/x-www-form-urlencoded",
        "body": "what={{query}}&sort=largest&limit=100&category=video&token={{token}}",
        "responseType": "xml",
        "listElement": "file",
        "itemMapping": {
          "title": "name",
          "size": "size",
          "link": "ident"
        }
      }
    ]
  },
  "streamUrl": {
    "steps": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://cloudstorage.cz/api/file_link/",
        "contentType": "application/x-www-form-urlencoded",
        "body": "ident={{identifier}}&download_type=video_stream&token={{token}}",
        "responseType": "xml",
        "outputs": {
          "stream_url": "link"
        }
      }
    ],
    "result": "{{stream_url}}"
  }
}

Příklad: Addon bez autentizace

Jednoduchý addon pro veřejné API, které nevyžaduje přihlášení:

public-api.json{
  "manifest": {
    "id": "public-videos",
    "name": "Public Videos API",
    "version": "1.0.0",
    "description": "Veřejné API pro vyhledávání videí.",
    "author": "Komunita",
    "type": "api",
    "capabilities": ["search", "directStream"]
  },
  "search": {
    "steps": [
      {
        "action": "http",
        "method": "GET",
        "url": "https://public-api.example.com/videos?search={{query|urlencode}}&page={{page}}",
        "responseType": "json",
        "listElement": "data.videos",
        "itemMapping": {
          "title": "filename",
          "size": "bytes",
          "link": "video_id"
        }
      }
    ]
  },
  "streamUrl": {
    "steps": [
      {
        "action": "http",
        "method": "GET",
        "url": "https://public-api.example.com/videos/{{identifier}}/stream",
        "responseType": "json",
        "outputs": {
          "stream_url": "url"
        }
      }
    ],
    "result": "{{stream_url}}"
  }
}

Pokud addon nevyžaduje autentizaci, sekce auth může zcela chybět – nebo nastavte "type": "none".

Příklad: JSON API s vnořenou strukturou

Addon, který pracuje s REST JSON API a používá vnořené JSON cesty:

nested-json.json{
  "manifest": {
    "id": "nested-api",
    "name": "Nested JSON API",
    "version": "1.0.0",
    "description": "Příklad práce s vnořeným JSON.",
    "author": "Komunita",
    "type": "api",
    "capabilities": ["search", "auth", "directStream"]
  },
  "auth": {
    "type": "token",
    "fields": [
      {
        "key": "api_key",
        "label": "API klíč",
        "hint": "Vložte váš API klíč",
        "isSecret": true,
        "required": true
      }
    ],
    "login": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://api.example.com/v2/auth",
        "contentType": "application/json",
        "body": "{\"api_key\": \"{{api_key}}\"}",
        "responseType": "json",
        "outputs": {
          "token": "data.session.token",
          "auth_status": "status"
        }
      },
      {
        "action": "assert",
        "variable": "auth_status",
        "equals": "ok"
      }
    ]
  },
  "search": {
    "steps": [
      {
        "action": "http",
        "method": "GET",
        "url": "https://api.example.com/v2/files?q={{query|urlencode}}&page={{page}}",
        "responseType": "json",
        "headers": {
          "Authorization": "Bearer {{token}}"
        },
        "listElement": "data.files",
        "itemMapping": {
          "title": "name",
          "size": "size_bytes",
          "link": "file_id"
        }
      }
    ]
  },
  "streamUrl": {
    "steps": [
      {
        "action": "http",
        "method": "GET",
        "url": "https://api.example.com/v2/files/{{identifier}}/download",
        "responseType": "json",
        "headers": {
          "Authorization": "Bearer {{token}}"
        },
        "outputs": {
          "stream_url": "data.download_url"
        }
      }
    ],
    "result": "{{stream_url}}"
  }
}

Příklad: Token-based auth s regexem

Addon, který extrahuje token z HTML odpovědi pomocí regexu:

scraper-addon.json{
  "manifest": {
    "id": "my-scraper",
    "name": "My Scraper",
    "version": "1.0.0",
    "description": "Ukázkový scraper addon s regex extrakcí.",
    "author": "Komunita",
    "type": "scraper",
    "capabilities": ["search", "auth", "directStream"]
  },
  "auth": {
    "type": "credentials",
    "fields": [
      {
        "key": "email",
        "label": "E-mail",
        "isSecret": false,
        "required": true
      },
      {
        "key": "password",
        "label": "Heslo",
        "isSecret": true,
        "required": true
      }
    ],
    "login": [
      {
        "action": "http",
        "method": "POST",
        "url": "https://example.com/login",
        "contentType": "application/x-www-form-urlencoded",
        "body": "email={{email}}&password={{password}}",
        "responseType": "xml"
      },
      {
        "action": "regex",
        "input": "{{_response}}",
        "pattern": "session_token[\"']?\\s*[:=]\\s*[\"']([a-f0-9]{32})[\"']",
        "group": 1,
        "output": "token"
      }
    ]
  },
  "search": {
    "steps": [
      {
        "action": "http",
        "method": "GET",
        "url": "https://example.com/search?q={{query|urlencode}}",
        "responseType": "xml",
        "headers": {
          "Cookie": "session={{token}}"
        }
      },
      {
        "action": "regex",
        "input": "{{_response}}",
        "pattern": "data-results='(\\[.*?\\])'",
        "group": 1,
        "output": "json_results"
      },
      {
        "action": "http",
        "method": "GET",
        "url": "https://example.com/api/parse-results",
        "responseType": "json",
        "headers": {
          "X-Data": "{{json_results}}"
        },
        "listElement": "items",
        "itemMapping": {
          "title": "name",
          "size": "size",
          "link": "url"
        }
      }
    ]
  },
  "streamUrl": {
    "steps": [
      {
        "action": "http",
        "method": "GET",
        "url": "{{identifier}}",
        "responseType": "xml",
        "headers": {
          "Cookie": "session={{token}}"
        }
      },
      {
        "action": "regex",
        "input": "{{_response}}",
        "pattern": "source\\s+src=[\"'](https://[^\"']+\\.mp4)[\"']",
        "group": 1,
        "output": "stream_url"
      }
    ],
    "result": "{{stream_url}}"
  }
}

Capabilities (schopnosti)

HodnotaPopis
"search"Addon umí vyhledávat soubory. Povinné – každý addon musí umět vyhledávat.
"auth"Addon vyžaduje autentizaci (přihlášení).
"directStream"Addon poskytuje přímé streamovací odkazy (ne redirect).
"subtitles"Addon podporuje titulky (rezervováno pro budoucí použití).
"download"Addon podporuje stahování souborů (rezervováno pro budoucí použití).

Addon Types (typy)

HodnotaPopis
"api"Data jsou získávána přes strukturované API (REST, XML-RPC, GraphQL...).
"scraper"Data jsou získávána parsováním HTML stránek (pomocí regexu).
"hybrid"Kombinace obojího – některé endpointy jsou API, některé vyžadují scraping.

Typ addonu je informativní metadata – nemá vliv na chování enginu. Engine vykonává kroky stejně bez ohledu na typ.

Chybové stavy

Engine může selhat v několika situacích:

SituaceCo se stane
HTTP krok vrátí jiný status než 200Pipeline se zastaví, krok vrátí false.
Assert selže (hodnota != expected)Pipeline se zastaví, celý flow vrátí false.
Regex nenajde shoduPipeline se zastaví, krok vrátí false.
Neznámá akcePipeline se zastaví, vypíše se warning do konzole.
Timeout HTTP požadavkuEngine zachytí výjimku, krok vrátí false.
Neplatný JSON souborImport selže, zobrazí se chybová hláška.
Duplicitní addon IDImport je odmítnut s upozorněním.

Omezení a limity

Právní upozornění

Aplikace StreamujTo neobsahuje žádný obsah ani přístup k jakémukoli úložišti. Veškerá funkcionalita úložišť je zajištěna výhradně doplňky, které si uživatel importuje na vlastní odpovědnost. Vývojář aplikace neposkytuje, neschvaluje ani nekontroluje žádné doplňky.

Instalací jakéhokoli doplňku přebíráte plnou odpovědnost za jeho použití. Ujistěte se, že dodržujete platné zákony vaší země, zejména v oblasti autorských práv. Vývojář nenese žádnou zodpovědnost za obsah zpřístupněný prostřednictvím doplňků třetích stran.