Systém modulů Streamlet
Úvod
Tento dokument popisuje, jak v projektu Streamlet vytvářet a integrovat moduly formou JSON konfigurací. Cílem je, aby vývojář mohl přidat nové zdroje dat katalogů a streamů (API i scraper moduly) pro filmy a seriály.
- Dva typy modulů:
- API moduly - volají HTTP API (JSON/XML) a mapují odpovědi.
- Scraper moduly - stahují HTML stránky a extrahují data pomocí CSS selektorů a malého DSL.
- Šifrované moduly (.slet) - aplikace podporuje i šifrované json moduly ve formátu
.sletpro ochranu proprietárního kódu. Šifrování modulů je možné provést na https://streamlet.info/encrypt/.
Společná metadata modulu (top‑level JSON)
Každý modul (API i Scraper) začíná základními metadaty. Příklady viz TMDB (API katalog), ČSFD (scraper katalog), Webshare (API streamy).
id: unikátní identifikátor modulu (např."tmdb","csfd").media: pole typů obsahu, které modul podporuje -["movies", "series"].type: seznam schopností modulu -["catalogues", "details", "stream"].name,website,author,description: informační pole pro UI a katalog.version,repository: definice repozitáře (url) a verze - po změně verze dojde k automatciké aktualizaci v aplikaci.baseUrl: základ URL pro všechny endpointy modulu. Nově podporuje placeholdery (např.https://api.example.com/{catalogueLanguage},{token:authToken},{apiKey}), které se před voláním nahradí.responseFormat:- API moduly:
"json"nebo"xml"(defaultjson). - Scraper moduly:
"scraper".
- API moduly:
headers: volitelné HTTP hlavičky přidávané ke všem požadavkům (API i Scraper).userAgent: volitelný UA string pro Scraper modul (pokud není uveden, použije se výchozí desktop UA).config: definice konfiguračních položek (např. přihlašovací údaje nebo API klíče). Struktura:- Každá položka má:
type("string"/"password"),label,default,required(bool).
- Každá položka má:
Příklad (zjednodušený):
{
"id": "tmdb",
"media": ["movies", "series"],
"type": ["catalogues", "details"],
"name": "TMDB",
"baseUrl": "https://api.themoviedb.org/3",
"responseFormat": "json",
"headers": { "accept": "application/json", "Authorization": "Bearer ..." },
"config": {
"apiKey": { "type": "string", "label": "API Key", "required": false }
}
}
Konvence endpointů a placeholderů
V obou typech modulů se nadále používají pojmenované „typy“ endpointů, které Streamlet umí zpracovat a namapovat:
- Katalogy a vyhledávání:
catalogue_movies,catalogue_series,search_movies,search_series - Detaily:
movie_detail,series_detail,series_episodes(epizody konkrétní sezóny) - Streamy:
stream_search(vyhledání souborů/zdrojů),serviceId(volitelný - získání service ID pro stream provider),link(získání stream linku pro konkrétní id)
Běžné placeholdery v URL a tělech požadavků:
- Paging a jazyk:
{page},{catalogueLanguage} - Identifikátory:
{id},{movieId},{seriesId},{seasonNumber} - Hledání:
{what},{title},{searchTerm} - Tokeny po autentizaci:
{token:authToken}(viz Autentizace) - Media parametry:
{tmdbId},{imdbId},{year},{originalTitle}(dostupné při vyhledávání streamů) - Service ID:
{serviceId}(dostupný po volání serviceId endpointu)
Placeholdery nahrazuje aplikace automaticky – fungují jak v URL, tak v tělech požadavků.
Placeholder systém
Placeholdery se nahrazují ve dvou oblastech: v URL/tělech endpointů a v textových labelech (přes vícejazyčnou podporu aplikace).
Endpoint placeholdery
Aplikace podporuje následující placeholdery v URL i tělech požadavků:
{id}- Obecný identifikátor (film/seriál/epizoda) – předává se explicitně parametrem
id. {page}- Číslo stránky (1‑n). Pokročilá varianta:
{page(offset,limit)}(dříve{page(start,multiplier)}). Vrací offset: page=1 → offset, page>1 → offset + (page-1) * limit. Příklad:{page(0,50)}→ 0, 50, 100…; použijte např.offset={page(0,50)}. (Změna: již se nepoužívá samostatnéstart+offset.) {catalogueLanguage},{appLanguage},{subtitlesLanguage},{audioLanguage}- Jazykové kódy předané z aplikace (např.
cs-CZ,en-US). - Vlastní placeholdery
-
customPlaceholders: mapa"key" → "value", nahrazuje{key}.customParams: libovolné typy hodnot – aplikace je převede na řetězec a nahradí{key}(podporuje čísla i boolean).
Aplikace rozpozná přítomnost placeholderu {page} (včetně varianty s parametry) a podle toho řídí stránkování.
Auth token placeholdery
Po autentizaci API modulu lze do URL/těl vkládat tokeny:
{token:<key>}– např.{token:authToken}; nahradí se hodnotou uloženou během auth kroků.- „Přímé“ token klíče – pokud řetězec obsahuje
{authToken}nebo cokoliv končící naToken, pokusí se nahradit z uložených tokenů.
Náhrady tokenů probíhají i uvnitř vnořených struktur (řetězce, mapy, seznamy).
Překlady textů
Aplikace umí překládat známé textové klíče v závorkách {...} (např. v popisech, labelech nastavení). Pokud jsou složené závorky vypnuté, je celý řetězec brán jako klíč překladu. Podporované příklady: media, catalogues, movies, series, search, appLanguage, popularMovies, topRatedMovies, popularSeries, topRatedSeries, apiKey, username, usernameEmail, password a řada žánrů (action, adventure, comedy, …). Konkrétní zobrazované texty závisejí na zvoleném jazyce aplikace.
API moduly
API modul definuje pole api s listem endpointů. Každý endpoint typicky obsahuje:
name: volitelný popisný název (pro UI).type: viz „Konvence endpointů“.method:GETneboPOST.url: relativní cesta (bude připojena kbaseUrl), může obsahovat placeholdery.body: volitelné - objekt klíč=hodnota pro POST (placeholdery se vyhodnotí a odešlou jakoapplication/x-www-form-urlencoded).response: nastavení parsování odpovědiitemsKey: cesta k poli položek v odpovědi (pro listové endpointy). Pokud chybí a odpověď je pole, použije se přímo.mapping: mapování polí z odpovědi na interní klíče (viz Mapování dat níže).status: volitelné mapování stavů na chyby -{ path: "...", states: { ok: "OK", autherror: "LOGIN_FATAL_1", ... } }.
imageBaseUrl/posterBaseUrl/backdropBaseUrl: volitelná základna pro skládání URL obrázků na úrovni endpointu. Nově podporují placeholdery (jazyk, token, API klíč), např."imageBaseUrl": "https://cdn.example.com/{catalogueLanguage}/img".
Příklad list endpointu (zkrácený):
{
"type": "search_movies",
"method": "GET",
"url": "/search/movie?query={what}&language={catalogueLanguage}&page={page}",
"response": {
"itemsKey": "results",
"mapping": {
"id": "id",
"title": "title",
"poster": "poster_path",
"rating": "vote_average"
}
},
"imageBaseUrl": "https://image.tmdb.org/t/p/w500"
}
Scraper moduly
Scraper modul definuje pole scraper s listem endpointů. Každý endpoint obsahuje:
type: viz „Konvence endpointů“.name: volitelný popis pro UI.url: absolutní nebo relativní cesta (pokud začíná/, připojí sebaseUrl). Může obsahovat placeholdery.mapping: mapování názvů polí na selektory/DSL výrazy. Tyto klíče odpovídají mapovacím klíčům (např.id,title,poster,rating,link, atd.).imageBaseUrl/posterBaseUrl/backdropBaseUrl: volitelné základny pro skládání URL obrázků. Nově podporují placeholdery (např.{catalogueLanguage},{token:authToken}). Poleelementsbylo sjednoceno domapping– starší moduly přejmenujte.
Extraktor automaticky rozpoznává, zda jde o seznam (typy začínající catalogue_ nebo search_) nebo detail.
Poznámky k seznamům:
- Scraper se pokusí najít „kontejnery“ položek heuristicky (
article,.item,.card,li,tr, …). - Selektory v
mappingse při listových endpointech aplikují relativně k jednotlivé nalezené položce. Doporučuje se používat krátké relativní selektory (např.a.title,img.poster,span.rating). - Pokud kontejner nelze spolehlivě detekovat, extraktor se pokusí vyčíst data jako „single“ a výsledek zabalí do seznamu.
Selektorové DSL (Scraper)
Kromě běžných CSS selektorů lze použít rozšíření:
selector(query)- vrátí text prvního elementu dle CSS selektoru.selectorAll(query)- vrátí list textů všech odpovídajících elementů.attribute(query, attr)- vrátí hodnotu atributuattrz elementu nalezenéhoquery.attribute(attr)- speciální varianta pro „aktuální“ element (v režimu listu je to položka). Vrátí hodnotu atributu přímo z něj.attributeAll(query, attr)- list všech hodnot atributůattrz elementů dlequery.regex(baseSelector, pattern, groupIndex)- vyhledá text (nebo atribut - viz níže) a aplikací regulárního výrazu vrátí skupinugroupIndex(default 0).patternuzavírejte do uvozovek.baseSelectormůže být:selector(...),text(...),attribute(query, attr),attribute(attr), nebo přímý CSS selektor na text.
regex_replace(baseSelector, pattern, replacement)- jako výše, ale provede nahrazení a vrátí upravený text.- Podpora
:not(...)- pro složitější selekce (např. vyřazení potomků z textu). Implementace najde základní selektor a odstraní podstromy odpovídající:not().
Příklady selektorů:
"title": "selector(h1.movie-title)"
"poster": "attribute(img.poster, src)"
"genres": "selectorAll(.genres a)" // list hodnot
"rating": "regex(selector(.rating), '([0-9]+\.?[0-9]*)', 1)"
"plot": "selector(.plot-full p:not(em.span-more-small))"
Mapování dat do interních modelů
Interní mapování probíhá v následujících mapperech. Fallback logika: pokud klíč není v mapping definován, mapper použije vestavěný výchozí název pole (např. posterPath → poster_path, rating → vote_average). ID hodnoty se vždy převádějí bezpečně na String. Seznamy jsou získány z pole objektů (genres[name]) nebo ze stringu (rozdělením podle , ; /). Dynamické placeholdery {{endpoint_type}} se vyhodnotí před mapováním a injektované výsledky lze pak číst standardně pod daným klíčem.
- CatalogItemMapper (katalogy a vyhledávání):
- Klíče:
id,title,poster/posterPath,rating,link, volitelněreleaseDate,genres. postermůže být relativní cesta (kombinuje se simageBaseUrl/posterBaseUrl) nebo absolutní URL.genresakceptuje pole objektů (genres[name]) i jednoduchý string (rozdělí se).- Výsledný model:
CatalogItem(doplní semediaTypez endpointu asourceModuleId).
- Klíče:
- MovieDetailMapper (detail filmu):
- Klíče:
id,title,originalTitle,tmdbId,imdbId,overview,tagline,status,releaseDate,runtime,popularity,rating,posterPath,backdropPath,homepage,revenue,budget,adult, seznamy:genres,originCountry,productionCompanies,productionCountries,spokenLanguages,actors,originalLanguage. runtimese parsuje z formátů typu"142","142 min","2h 20m".- ID vždy převedeno na
String(podporuje int).posterPath/backdropPathkombinují base URL pokud není absolutní.
- Klíče:
- SeriesDetailMapper (detail seriálu):
- Klíče:
id,title/name,originalTitle/originalName,numberOfSeasons,numberOfEpisodes,overview,tagline,status,firstAirDate,lastAirDate,popularity,rating,posterPath,backdropPath,homepage,adult, seznamy:genres,originCountry,productionCompanies,productionCountries,spokenLanguages,languages,networks,createdBy,episodeRunTime(list int),seasonsUrls(list string). - Inference: pokud
numberOfSeasonschybí, dopočítá se z délky poleseasons. PokudnumberOfEpisodeschybí, sečtou seepisodeCountkaždé sezóny. - ID a číselné počty jsou robustně parsovány (int nebo string).
- Klíče:
- SeriesEpisodesMapper (epizody sezóny):
- Klíče:
id,showId,seasonNumber,episodeNumber,name,overview,airDate,rating/vote_average,stillPath,episodeType,runtime. - ID i showId vždy jako
String. Číselné hodnoty bezpečně parsovány ze stringu.
- Klíče:
- StreamModelMapper (výsledky stream vyhledávání):
- Klíče:
id,title,name,type,size(string/number → double),ratingUp,ratingDown,seeds,info,audioLanguages,subtitleLanguages,hash,custom. sizepřevod string/number →double, vote counts a seeds →int(fallback 0).- Jazykové seznamy musí být pole; prvky se převádějí na string.
- Klíče:
Nové možnosti: episodeMapping (u kombinovaných seriálových endpointů), dynamické injektování {{endpoint_type}}, placeholdery v baseUrl a *BaseUrl. Přidáním dalších klíčů do mapping nikdy „nerozbijete“ mapper – neznámé klíče jsou ignorovány.
Cesty v mapování (path syntax)
Pro API moduly se používá dot‑notace a speciální zápis pro pole:
- Jednoduché pole:
"title": "title","id": "id". - Vnoření:
"crewName": "crew.0.name". - Extrakce hodnot z pole objektů:
genres[name]vrátí list hodnotnameze všech objektů vgenres. - Pokud
extractStringList()dostaneString, rozseká jej na seznam podle,/;//.
Scraper moduly nepoužívají „path“ přes JSON, ale přímo vracejí cílové klíče pomocí mapping a selektorového DSL.
Obrázky: poster/backdrop/image URL
URL obrázků se skládají utilitou ImageUtils.buildUrl(...):
- Pokud je hodnota již absolutní URL, použije se přímo.
- Jinak se vezme hodnota z endpointu (
posterBaseUrl/backdropBaseUrl/imageBaseUrl) nebo z modulu a připojí se relativní cesta. - Pro Scraper moduly je logika skládání adres shodná – použije se základna a relativní cesta.
V mapování proto dbejte na to, aby poster/posterPath resp. backdropPath vracely relativní cestu, pokud používáte base URL; nebo absolutní URL, pokud je chcete použít přímo.
Zpracování chyb
Aplikace automaticky zpracovává chybové stavy z API a scraper modulů. Chybové kódy se normalizují a převádějí na uživatelsky přívětivá hlášení.
Pro úplný seznam podporovaných chybových kódů, jejich významů a zobrazení v UI viz Kompletní reference chybových kódů.
Příklad mapování chyb v endpointu
{
"response": {
"status": {
"path": "response.code",
"states": {
"ok": "OK",
"userNotFound": "user_not_found",
"invalidPassword": "invalid_credentials",
"serverError": "server_error"
}
}
}
}
Aplikace vyhodnotí hodnotu na cestě path a převede ji podle states na standardizovaný chybový kód, který se zobrazí s příslušnou ikonou, barvou a zprávou.
Autentizace API modulů
API moduly mohou vyžadovat autentizaci pro přístup k chráněným zdrojům. Streamlet podporuje dva hlavní způsoby autentizace:
- API klíč v URL nebo hlavičce - jednoduchá statická autentizace
- Vícekrokový auth proces - složitější autentizace s tokenem (např. login/password)
1. API klíč v konfiguraci
Nejjednodušší způsob autentizace je pomocí API klíče, který uživatel zadá v nastavení modulu. Klíč lze použít dvěma způsoby:
a) API klíč v URL (jako query parametr)
{
"config": {
"apiKey": {
"type": "string",
"target": "endpoint",
"label": "{apiKey}",
"default": "",
"fullValue": "?api_key={apiKey}",
"required": true
}
}
}
Klíč target: "endpoint" říká, že hodnota se připojí přímo k URL endpointu. Parametr fullValue definuje, jak bude klíč vložen (včetně query stringu).
b) API klíč v hlavičce
{
"headers": {
"accept": "application/json",
"Authorization": "Bearer YOUR_API_KEY_HERE"
},
"config": {
"apiKey": {
"type": "string",
"label": "{apiKey}",
"required": false
}
}
}
API klíč lze přímo zakódovat do headers, nebo ho nechat uživatele zadat v konfiguraci a použít jako placeholder.
2. Vícekrokový autentizační proces
Pro služby vyžadující login a heslo použijte sekci auth s polem steps. Každý krok je API požadavek, který může:
- Uložit mezivýsledky (např.
salt) pro použití v dalším kroku - Získat autentizační token pro následné požadavky
- Kontrolovat chybové stavy a převádět je na srozumitelné kódy
Struktura auth kroku
name- Popisný název kroku (např. "salt", "login")
method- HTTP metoda:
GETneboPOST url- URL endpointu (relativní k
baseUrl) body- Tělo požadavku (objekt klíč=hodnota). Může obsahovat:
- Placeholdery z config:
{login},{password} - Uložené hodnoty z předchozích kroků:
{salt} - Speciální funkce:
sha1(md5_crypt({password}, {salt}))
- Placeholdery z config:
response- Nastavení zpracování odpovědi:
storeAs: název pro uložení mezivýsledku (použitelný v dalších krocích)path: cesta k hodnotě v odpovědi (dot-notace)tokenPath: cesta k autentizačnímu tokenu v odpovědistatus: mapování stavových kódů na chyby (viz níže)
storeTokenAs- Název klíče, pod kterým se uloží token pro použití v endpointech (např.
"authToken")
Příklad: Webshare.cz autentizace (2 kroky)
{
"config": {
"login": {
"type": "string",
"label": "{usernameEmail}",
"required": true
},
"password": {
"type": "password",
"label": "{password}",
"required": true
}
},
"auth": {
"steps": [
{
"name": "salt",
"method": "POST",
"url": "/salt/",
"body": {
"username_or_email": "{login}"
},
"response": {
"storeAs": "salt",
"path": "response.salt",
"status": {
"path": "response.code",
"states": {
"ok": "OK",
"userNotFound": "user_not_found"
}
}
}
},
{
"name": "login",
"method": "POST",
"url": "/login/",
"body": {
"username_or_email": "{login}",
"password": "sha1(md5_crypt({password}, {salt}))",
"keep_logged_in": "1"
},
"response": {
"tokenPath": "response.token",
"status": {
"path": "response.code",
"states": {
"autherror": "authentication_error"
}
}
},
"storeTokenAs": "authToken"
}
]
}
}
3. Použití tokenů v endpointech
Po úspěšné autentizaci lze uložené tokeny použít v URL i tělech požadavků pomocí placeholderů:
{token:authToken}- formáttoken:názevKlíče{authToken}- přímý název klíče (pokud končí na "Token")
Příklad použití v URL
{
"type": "stream_search",
"url": "/api/search?token={token:authToken}&query={what}"
}
Příklad použití v těle požadavku
{
"type": "stream_search",
"method": "POST",
"url": "/search/",
"body": {
"what": "{title}",
"wst": "{token:authToken}",
"limit": "50"
}
}
4. Service ID endpoint (volitelný)
Pro stream moduly, které vyžadují získání service ID před vyhledáváním streamů, lze definovat volitelný endpoint typu serviceId:
{
"name": "get_service_id",
"type": "serviceId",
"method": "GET",
"url": "/service/tmdb/{tmdbId}",
"response": {
"mapping": {
"serviceId": "response.service_id"
}
}
}
Pokud tento endpoint existuje, aplikace ho automaticky zavolá před stream_search a získaný serviceId bude dostupný jako placeholder {serviceId} pro další endpointy:
{
"name": "search",
"type": "stream_search",
"method": "POST",
"url": "/search/",
"body": {
"what": "{title}",
"service_id": "{serviceId}",
"tmdb_id": "{tmdbId}",
"year": "{year}",
"wst": "{token:authToken}"
}
}
Endpoint serviceId je zcela volitelný - pokud není definován, vyhledávání streamů funguje normálně bez něj. Do tohoto endpointu se automaticky předávají všechny dostupné media parametry (tmdbId, imdbId, year, originalTitle, atd.).
5. Stavové kódy a chyby
Každý auth krok i běžný endpoint může definovat response.status pro mapování chybových stavů:
"response": {
"status": {
"path": "response.code",
"states": {
"ok": "OK",
"userNotFound": "user_not_found",
"invalidPassword": "invalid_credentials",
"autherror": "authentication_error",
"rateLimited": "rate_limited"
}
}
}
Aplikace vyhodnotí hodnotu na cestě path a pokud odpovídá některému klíči v states, převede ji na standardní chybový kód.
- Hodnota
"OK"znamená úspěch (case-insensitive) - Ostatní hodnoty jsou chybové kódy - viz Kompletní reference chybových kódů
5. Kryptografické funkce
V body auth kroků lze použít speciální funkce pro hashování:
md5_crypt({password}, {salt})- MD5 hash hesla se solí
sha1(...)- SHA1 hash (může obsahovat vnořené funkce)
- Kombinace
"password": "sha1(md5_crypt({password}, {salt}))"- nejprve MD5 se solí, pak SHA1
6. Kontrola přihlašovacích údajů
Pokud uživatel nezadá požadované údaje (označené "required": true), aplikace automaticky vrátí chybu no_credentials se seznamem chybějících položek. Uživatel bude vyzván k zadání údajů v nastavení modulu.
Tip: Pro inspiraci viz modul webshare.json, který demonstruje kompletní 2krokovou autentizaci s hashem hesla.
Podmínky endpointů (condition)
Mechanika: primární endpoint může mít klíč "condition": "typ_podminky". Než se provede hlavní volání, aplikace zavolá endpoint daného typu. Ten musí vracet response.condition objekt s klíči path, alert, states (ok/nok). Pokud hodnota na path odpovídá states.ok, pokračuje se; pokud states.nok, hlavní endpoint se přeskočí a vrátí se chyba s kódem alert.
{
"name": "check_vip",
"type": "check_vip",
"method": "POST",
"url": "/user_data/",
"body": { "wst": "{token:authToken}" },
"response": {
"condition": {
"path": "response.vip",
"alert": "membership_required",
"states": { "ok": "1", "nok": "0" }
}
}
}
// Primární endpoint podmíněný check_vip:
{
"name": "link",
"type": "link",
"condition": "check_vip",
"method": "POST",
"url": "/file_link/",
"body": { "ident": "{id}", "download_type": "video_stream", "wst": "{token:authToken}" }
}
Poznámka: vyhněte se řetězení podmínek do cyklu (A závisí na B, B na A).
Dynamické endpoint placeholdery {{endpoint_type}}
V response.mapping lze uvést zástupné hodnoty ve tvaru {{typ}}. Před mapováním aplikace zavolá odpovídající endpoint typ (se stejnými původními parametry) a jeho výsledek (result) vloží do dat pod tímto klíčem.
{
"type": "movie_detail",
"url": "/movie/{id}?language={catalogueLanguage}",
"response": {
"mapping": {
"id": "id",
"title": "title",
"relatedSearch": "{{search_movies}}"
}
}
}
Tip: vhodné pro doplnění souvisejících položek (např. nabízet uživateli přímý seznam nalezených filmů souvisejících s detailem). Vyhněte se rekurzi.
Rozšířené mapování
episodeMapping: pro kombinované odpovědi (detail seriálu + sezóny + epizody). Aplikace vybere sezónu dle{seasonNumber}a pak mapuje její epizody pomocíepisodeMapping.itemsKey: určuje list pro katalogy/vyhledávání (nezměněno).{{endpoint_type}}hodnoty v mappingu umožňují dynamické injektování dat jiného endpointu.- Placeholdery v
baseUrla*BaseUrl(image/poster/backdrop) umožňují jazykové/autorizační varianty cest.
Stránkování – sjednocený offset
Starý tvar {page(start,multiplier)} byl nahrazen {page(offset,limit)}. Vrací přímo offset pro danou stránku. Příklad použití: "url": "/api/movies?offset={page(0,20)}&limit=20".
Příklady
1) API: katalog/seek přes TMDB (výřez)
{
"type": "catalogue_movies",
"method": "GET",
"url": "/movie/popular?language={catalogueLanguage}&page={page}",
"response": {
"itemsKey": "results",
"mapping": { "id": "id", "title": "title", "poster": "poster_path", "rating": "vote_average" }
},
"imageBaseUrl": "https://image.tmdb.org/t/p/w500"
}
2) API: stream provider s autentizací (výřez podle Webshare)
"auth": {
"steps": [
{
"name": "salt",
"method": "POST",
"url": "/salt/",
"body": { "username_or_email": "{login}" },
"response": { "storeAs": "salt", "path": "response.salt", "status": { "path": "response.code", "states": { "ok": "OK", "userNotFound": "SALT_FATAL_1" } } }
},
{
"name": "login",
"method": "POST",
"url": "/login/",
"body": {
"username_or_email": "{login}",
"password": "sha1(md5_crypt({password}, {salt}))",
"keep_logged_in": "1"
},
"response": {
"tokenPath": "response.token",
"status": { "path": "response.code", "states": { "autherror": "LOGIN_FATAL_1" } }
},
"storeTokenAs": "authToken"
}
]
}
Po úspěchu lze token použít v těle/URL: "wst": "{token:authToken}".
3) Scraper: katalog přes ČSFD (schematicky)
{
"type": "search_movies",
"url": "/hledat/?q={what}",
"mapping": {
"id": "attribute(a, href)",
"title": "selector(h3 a)",
"poster": "attribute(img, src)",
"rating": "regex(selector(.rating), '([0-9]+)', 1)",
"link": "attribute(a, href)"
},
"imageBaseUrl": "https://www.csfd.cz"
}
Best practices
- Stabilní selektory: u Scraperu preferujte selektory odolné vůči změnám layoutu (třídy, data‑atributy). Omezte závislost na pořadí elementů.
- Relativní vs. absolutní URL: vracejte relativní cesty k obrázkům a nastavte
imageBaseUrl/posterBaseUrl/backdropBaseUrl- nebo vraťte přímo absolutní URL. - Stránkování: vždy podporujte
{page}, pokud to zdroj umožňuje. - Jazyk: používejte
{catalogueLanguage}, pokud API nabízí lokalizaci. - Status kódy: u API definujte
response.status, abychom chybové stavy převáděli na srozumitelné chyby v UI. - Výkon: omezujte počet položek (
limit), používejte specifické selektory a nerozšiřujte extrakci nad rámec potřebných polí. - Testování: průběžně ověřujte, že klíče v
mapping/mappingkorespondují s mappery (viz sekce „Mapování dat“).
Troubleshooting
- Prázdné výsledky u Scraperu: zkontrolujte, zda heuristika našla správné kontejnery; upravte selektory v
mappingtak, aby byly relativní k položce (a,img,spanuvnitř jednoho „card“/article). - Obrázky se nenačítají: ověřte
imageBaseUrl/posterBaseUrl/backdropBaseUrla to, zdaposter/posterPathvrací pouze relativní cestu. - Špatné typy (např.
size,ratingUp):StreamModelMapperčísla parsuje ze stringu; dbejte na konzistentní formát hodnot vmapping. - Chyby autentizace: doplňte
response.statusdo auth kroků i endpointů; ověřte hashovací řetězce a dostupnost{token:...}v tělech. - List endpoint vrací pouze jednu položku: přidejte výraznější selektory v
mapping(aby se v rámci položky daly najít hodnoty), případně upravte stránku (jiný typ endpointu -search_vscatalogue_).
Rychlý checklist pro nový modul
- Vyberte typ (API/Scraper) a připravte metadata (
id,name,baseUrl,headers,config…). - Definujte endpointy dle konvencí (
catalogue_*",search_*,movie_detail,series_detail,series_episodes,stream_search,serviceId,link). - Pro list endpointy uveďte
response.itemsKey(API) nebo připravte elementové selektory (Scraper). - Nastavte
mapping/mappingtak, aby odpovídaly očekávaným klíčům mapperů. - Přidejte
imageBaseUrl/posterBaseUrl/backdropBaseUrlpodle potřeby. - U API s chybovými stavy doplňte
response.statusa případně autentizační krokyauth.steps. - U stream modulů zvažte, zda je potřeba volitelný
serviceIdendpoint pro získání service ID před vyhledáváním. - Ověřte, že vše funguje pro
moviesi/neboseriesdlemedia.
Tip: Jako referenci používejte existující moduly v modules/ - tmdb.json (API JSON), webshare.json (API XML + auth), csfd.json (Scraper). Ty ukazují praktické použití všech výše popsaných prvků.
Kompletní reference chybových kódů
Následující tabulka obsahuje všechny podporované chybové kódy, které lze vracet z API modulů v response.status.states. Aplikace automaticky zobrazí uživatelsky přívětivou hlášku včetně ikony a barvy.
Seznam všech chybových kódů
| Kód | Titulek v UI | Zpráva | Ikona | Barva | Obnovitelná |
|---|---|---|---|---|---|
unknown |
Chyba | Zobrazí se předaná zpráva nebo "Neznámá chyba" | warning | grey | Ne |
network |
Problém se sítí | Zkontrolujte připojení k internetu a zkuste to znovu. | wifi_off | orange | Ano |
connection |
Problém se sítí | Zkontrolujte připojení k internetu a zkuste to znovu. | wifi_off | orange | Ano |
http_error |
Chyba | Zobrazí se předaná zpráva nebo "Neznámá chyba" | warning | grey | Ne |
endpoint_not_found |
Endpoint nenalezen | API endpoint nenalezen. | data_saver_off | purple | Ne |
mapping_error |
Chyba | Zobrazí se předaná zpráva nebo "Neznámá chyba" | warning | grey | Ne |
authentication |
Chyba přihlášení | Přihlášení se nezdařilo. Zkontrolujte své údaje. | lock | red | Ne |
authentication_failed |
Chyba přihlášení | Přihlášení se nezdařilo. Zkontrolujte své údaje. | lock | red | Ne |
authentication_error |
Neplatné přihlašovací údaje | Zkontrolujte své uživatelské jméno a heslo. | lock | red | Ne |
no_credentials |
Nezadané přihlašovací údaje | Zadejte přihlašovací údaje (zobrazí se seznam chybějících položek). | lock | red | Ne |
invalid_credentials |
Neplatné přihlašovací údaje | Zkontrolujte své uživatelské jméno a heslo. | lock | red | Ne |
user_not_found |
Uživatel nenalezen | Zadané uživatelské jméno neexistuje. | person_off | red | Ne |
forbidden |
Přístup zamítnut | Nemáte oprávnění k této operaci. | block | red | Ne |
not_found |
Nenalezeno | Požadovaný obsah nebyl nalezen. | search_off | blue | Ne |
server_error |
Chyba serveru | Server právě není dostupný. Zkuste to později. | error | red | Ano |
fatal |
Chyba serveru | Server právě není dostupný. Zkuste to později. | error | red | Ano |
rate_limited |
Příliš mnoho požadavků | Počkejte chvíli před dalším pokusem. | hourglass_empty | amber | Ano |
parsing |
Chyba zpracování dat | Data nelze zpracovat. Zkuste to později. | data_saver_off | purple | Ne |
scraping_error |
Chyba | Zobrazí se předaná zpráva nebo "Neznámá chyba" | warning | grey | Ne |
stream_error |
Chyba streamu | Stream právě není dostupný. Zkuste to později. | error | red | Ano |
unsupported_module |
Chyba | Zobrazí se předaná zpráva nebo "Neznámá chyba" | warning | grey | Ne |
unsupported_operation |
Chyba | Zobrazí se předaná zpráva nebo "Neznámá chyba" | warning | grey | Ne |
Normalizace chybových kódů
Aplikace automaticky normalizuje běžné varianty názvů chyb:
"httperror","http error"→http_error"endpointnotfound","endpoint-not-found"→endpoint_not_found"mappingerror","mapping-error"→mapping_error"autherror","auth_error"→authentication_error"usernotfound","user_not_found"→user_not_found
Příklad použití v modulu
{
"response": {
"status": {
"path": "response.code",
"states": {
"ok": "OK",
"userNotFound": "user_not_found",
"invalidPassword": "invalid_credentials",
"rateLimited": "rate_limited",
"serverError": "server_error"
}
}
}
}
Kompletní reference placeholderů
Placeholdery se používají v URL a tělech požadavků pro dynamické nahrazení hodnot. Všechny placeholdery mají formát {názevPlaceholderu}.
Základní placeholdery
| Placeholder | Popis | Příklad hodnoty |
|---|---|---|
{id} |
Obecný identifikátor (film/seriál/epizoda/soubor) | 12345 |
{page} |
Číslo stránky pro stránkování | 1, 2, 3 |
{page(offset,limit)} |
Vrátí offset: page=1 → offset, page>1 → offset + (page-1) * limit. (Dříve {page(start,multiplier)}) |
{page(0,50)} → 0, 50, 100... |
{catalogueLanguage} |
Jazyk pro katalog (nastavený uživatelem) | cs-CZ, en-US |
{appLanguage} |
Jazyk aplikace | cs, en |
{subtitlesLanguage} |
Preferovaný jazyk titulků | cs, en |
{audioLanguage} |
Preferovaný jazyk zvuku | cs, en |
{what} |
Hledaný výraz (pro vyhledávání) | Matrix |
{title} |
Název filmu/seriálu | The Matrix |
{searchTerm} |
Alternativa pro hledaný výraz | Matrix |
{movieId} |
Specifické ID filmu | 603 |
{seriesId} |
Specifické ID seriálu | 1399 |
{seasonNumber} |
Číslo sezóny | 1, 2 |
Auth token placeholdery
Po úspěšné autentizaci modulu lze do URL a těl požadavků vkládat tokeny uložené během auth procesu:
| Placeholder | Popis | Příklad |
|---|---|---|
{token:keyName} |
Nahradí se hodnotou tokenu uloženého pod klíčem keyName |
{token:authToken}, {token:refreshToken} |
{authToken} |
Přímý přístup k tokenu s názvem authToken |
{authToken} |
{*Token} |
Libovolný klíč končící na Token se pokusí najít v uložených tokenech |
{refreshToken}, {apiToken} |
Config placeholdery
Hodnoty z konfigurace modulu (uživatelské údaje) lze vkládat pomocí jejich klíčů:
| Placeholder | Popis |
|---|---|
{login} |
Uživatelské jméno nebo email z konfigurace |
{password} |
Heslo z konfigurace |
{apiKey} |
API klíč z konfigurace |
{jakýkolivKlíč} |
Libovolný klíč definovaný v config sekci modulu |
Vlastní placeholdery
Můžete definovat vlastní placeholdery pomocí customPlaceholders (mapa string→string) nebo customParams (libovolné typy, převedou se na string).
Příklady použití
// Základní použití
"/search/movie?query={what}&language={catalogueLanguage}&page={page}"
// Pokročilé stránkování
"/api/movies?offset={page(0,20)}&limit=20"
// Auth token v URL
"/api/user/favorites?token={token:authToken}"
// Auth token v těle
{
"wst": "{token:authToken}",
"ident": "{id}"
}
// Config hodnoty
{
"username": "{login}",
"password": "{password}",
"api_key": "{apiKey}"
}
Kompletní reference překladů
Aplikace podporuje automatické překlady textových klíčů v závorkách {klíč}. Tyto překlady lze použít v popisech modulů, labelech konfigurace a názvech endpointů. Zobrazený text závisí na jazyce aplikace.
Obecné pojmy
| Klíč | České zobrazení | Použití |
|---|---|---|
media |
Média | Obecný pojem pro obsah |
catalogues |
Katalogy | Seznam katalogů |
series |
Seriály | TV seriály |
movies |
Filmy | Filmy |
details |
Detaily | Podrobnosti |
library |
Knihovna | Uživatelská knihovna |
stream |
Stream | Streamování |
modules |
Moduly | Systém modulů |
settings |
Nastavení | Konfigurace aplikace |
search |
Vyhledávání | Funkce vyhledávání |
error |
Chyba | Chybové stavy |
authFailed |
Přihlášení selhalo | Chyba autentizace |
Nastavení a konfigurace
| Klíč | České zobrazení |
|---|---|
apperance |
Vzhled |
appLanguage |
Jazyk aplikace |
theme |
Motiv |
systemTheme |
Systémový motiv |
darkTheme |
Tmavý motiv |
lightTheme |
Světlý motiv |
defaultCatalogueLanguage |
Výchozí jazyk katalogů |
defaultAudioLanguage |
Výchozí jazyk zvuku |
defaultSubtitleLanguage |
Výchozí jazyk titulků |
playback |
Přehrávání |
autoplayNextEpisode |
Automaticky přehrát další epizodu |
aboutApp |
O aplikaci |
Typy katalogů
| Klíč | České zobrazení |
|---|---|
popularMovies |
Populární filmy |
topRatedMovies |
Nejlépe hodnocené filmy |
popularSeries |
Populární seriály |
topRatedSeries |
Nejlépe hodnocené seriály |
searchMovies |
Hledat filmy |
searchSeries |
Hledat seriály |
Přihlašovací údaje
| Klíč | České zobrazení |
|---|---|
apiKey |
API klíč |
name |
Jméno |
login |
Přihlašovací jméno / Email |
username |
Uživatelské jméno |
usernameEmail |
Přihlašovací jméno / Email |
password |
Heslo |
enterLoginDetails |
Zadejte přihlašovací údaje |
Žánry filmů
| Klíč | České zobrazení |
|---|---|
action |
Akční |
adventure |
Dobrodružný |
animation |
Animovaný |
comedy |
Komedie |
crime |
Krimi |
documentary |
Dokumentární |
drama |
Drama |
family |
Rodinný |
fantasy |
Fantasy |
history |
Historický |
horror |
Horor |
music |
Hudební |
mystery |
Mysteriózní |
romance |
Romantický |
scienceFiction |
Sci-Fi |
tvMovie |
TV film |
thriller |
Thriller |
war |
Válečný |
western |
Western |
Žánry seriálů
| Klíč | České zobrazení |
|---|---|
actionAdventure |
Akční a dobrodružný |
kids |
Pro děti |
news |
Zprávy |
reality |
Reality show |
sciFiFantasy |
Sci-Fi a Fantasy |
soap |
Mýdlová opera |
talk |
Talk show |
warPolitics |
Válka a politika |
Příklady použití v modulech
// V popisu modulu
{
"name": "TMDB",
"description": "Katalog {movies} a {series} z {tmdb}"
}
// V názvu endpointu
{
"name": "{popularMovies}",
"type": "catalogue_movies"
}
// V konfiguraci
{
"config": {
"apiKey": {
"type": "string",
"label": "{apiKey}",
"required": true
},
"login": {
"type": "string",
"label": "{usernameEmail}",
"required": true
}
}
}
Poznámka: Všechny překlady jsou automaticky zobrazeny v jazyce aplikace, který si uživatel zvolil v nastavení.