Saltar a contenido

Novedades para quienes escriben plugins

Lo que cambió en Kino y que importa cuando escribes un plugin, por versión de la app. Cada número está en el contrato y en los archivos de referencia.

Kino 0.9.53: kino.meta y kino.tmdb

Sin apiVersion nuevo: sigue siendo 7, y nada de esta lista te obliga a cambiar tu plugin. Las dos llamadas nuevas existen solo desde Kino 0.9.53, así que compruébalas antes de usarlas (typeof kino.meta === "function", typeof kino.tmdb === "function"); node sdk/validate.mjs avisa si tu código llama alguna sin esa comprobación.

  • kino.meta(query): pregúntale a Kino qué sabe de un título ({ type, ids: { imdb, tmdb, tvdb, kitsu, mal, anilist }, lang }) y recibe sinopsis, año, póster, fondo, logo, géneros, duración, capítulos con sus ids, la equivalencia de todos los ids, notas y reparto, o null. Kino responde con su propia consulta de TMDB, AniList para el anime y los demás plugins meta de la persona, combinados igual que en la ficha; tu plugin nunca toca una llave de TMDB, y nunca se le pregunta a sí mismo. 30 llamadas por minuto, máximo 8 s, en caché 30 minutos. La API kino.
  • kino.tmdb(path, params): la API v3 de TMDB, solo lectura, sin una llave en tu plugin. Primero va la llave propia de Kino, detrás de la caché de TMDB de Kino (en disco, la misma de sus pantallas, con una copia de hasta 7 días cuando TMDB no responde) y de límites propios (20 llamadas cada 10 s por plugin, 60 cada 10 s entre todos los plugins), para que los plugins no gasten la cuota de Kino. Solo cuando la llave de Kino falla (TMDB le responde 401/403/429, o se agota uno de esos límites) la misma petición sale otra vez con la llave de la persona: la que escribe en Ajustes ("Tu llave de TMDB", opcional, sincronizada entre sus aparatos) o, si no hay, la que configuró en un addon de Stremio instalado, si acepta usarla. Una llave que tu plugin guarda en sus propios ajustes nunca se usa. Kino pone la llave; tu código nunca ve ninguna, y TMDB no necesita una entrada en tus hosts. no_tmdb_key (con la frase de Kino para la persona en e.userMessage: "Agrega tu llave de TMDB en Ajustes, o instala un addon de TMDB de Stremio configurado con tu llave.") queda para una versión de Kino sin llave propia y una persona sin llave. Solo rutas de lectura permitidas, 40 llamadas cada 10 s por plugin conteste la llave que conteste, en caché 10 minutos. Un catálogo hecho con TMDB ya no necesita su propio ajuste de llave (déjalo solo como respaldo para versiones anteriores). La API kino, un ejemplo completo.
  • El kit de Node corre las dos: KINO_META_FIXTURE, KINO_TMDB_KEY (o "tmdbKey" en sdk/config.json) y KINO_TMDB_FIXTURE. Probar en local.

Kino 0.9.51: apiVersion 7

apiVersion 7 = Kino 0.9.51. El contrato (contract.json) dice ahora maxApiVersion 7 y kino.apiVersion reporta 7. Un manifiesto con "apiVersion": 7 se rechaza en Kino 0.9.50 y anteriores ("Este plugin necesita una versión más nueva de Kino"), así que declara 7 solo si usas tracking o segments. Nada más de esta lista te obliga a cambiar tu plugin.

  • tracking (apiVersion 7): tu plugin exporta track(event) y Kino le cuenta qué película o capítulo suena en ese aparato, de cualquier fuente: start, progress, stop y watched, con los ids propios del capítulo y los de la serie aparte. Se aprueba en rojo ("Le contará a … qué ves y cuándo lo terminas"), trae el interruptor "Enviar lo que veo" en tu pestaña de Ajustes, y los eventos esperan en una cola que sobrevive sin conexión y con la app cerrada (reintentos ordenados, 200 por plugin, 7 días). Devuelve { skipped: true } para un evento que a tu servicio no le sirve. Contarle a un servicio de seguimiento qué ve la persona.
  • segments (apiVersion 7): tu plugin exporta segments(query) y le dice a Kino dónde están la intro y los créditos de cualquier película o capítulo; los botones "Saltar intro" y "Saltar outro" y el salto automático los usan en celular y TV. Sin aprobación en rojo. Dónde están la intro y los créditos.
  • Subtítulos por archivo: subtitles() recibe file: { hash?, size?, name? }, lo que Kino sabe del archivo que suena (el hash de OpenSubtitles, su tamaño, su nombre, o uno al estilo de un release armado con el título), para poner primero la versión exacta. Un addon de Stremio lo recibe como los extras videoHash, videoSize y filename. Sin apiVersion nuevo. Subtítulos para cualquier título, Addons de Stremio.
  • meta con logo, notas y reparto: la respuesta de meta puede traer logo (se muestra en lugar del nombre en la ficha), ratings (hasta 6, de IMDb, Rotten Tomatoes, Letterboxd…) y cast (hasta 20); un addon de Stremio al estilo de AIOMetadata los da con su logo, imdbRating y app_extras.cast. Sin apiVersion nuevo: las versiones anteriores los ignoran. Describir otros títulos.
  • Los enlaces stremio:///detail/… abren el título en Kino (el "Open in Stremio" de Seenr y similares), en vez de ignorarse. Addons de Stremio.
  • "Tu servidor" 1.5.0, el plugin de referencia, ahora muestra todo lo que un servidor propio puede usar hasta apiVersion 7: tracking, segments, subtitles con file, meta con logo, notas y reparto, y lo de apiVersion 6 (sección, categorías, firma por petición, copias, el formulario de ajustes completo, una lista con resolve: true, liveSearch y paginación de canales). Plugins de ejemplo.

  • Compatibilidad de Nuvio v2: Kino convierte muchos más scrapers de Nuvio. Scrapers de varios archivos (los hermanos se leen del mismo repositorio, máximo 16 archivos y 1 MiB), un subconjunto de Node (path, url, util, events, querystring, timers, buffer y http/https/undici sobre kino.fetch; setInterval, queueMicrotask), el onSettings de cada scraper como formulario de ajustes que se sincroniza entre aparatos, y cada copia reproducible ofrecida como alternativa con etiqueta en el menú Servidor (las páginas de embed de últimas). Una dirección al estilo Kodi url|User-Agent=… se vuelve encabezados. Los scrapers P2P y de debrid se rechazan ("No compatible"). Nada de esto es para tu propio plugin: es lo que puede dar por hecho un scraper de Nuvio. Scrapers de Nuvio.

  • Formulario de ajustes: el hint de una section puede tener hasta 300 caracteres y se parte en varias líneas (sectionHintMaxChars en contract.json). Las versiones anteriores a 0.9.51 rechazan uno de más de 80, así que mantenlo corto si tu plugin tiene que instalarse en ellas. Formulario de ajustes.
  • Un % en el texto de un error ya no tumba la app. Hasta 0.9.50, un error de tu plugin cuyo texto llevaba un % (una URL codificada como ?q=Inception%20s en un "fetch failed") podía cerrar Kino de golpe. Ahora el texto de un error puede ser cualquiera; si tu plugin tiene que correr en 0.9.50 y anteriores, no metas direcciones codificadas en sus mensajes de error. Errores que tu código puede atrapar.
  • Recomendados suma addons de Stremio de utilidad (subtítulos como OpenSubtitles v3 y Subtis, catálogos como Cinemeta, TMDB e IMDb) y canales gratis y legales (Pluto TV, Radios). La lista ya no se publica en npm: Kino la lee de este repositorio en GitHub, luego de archive.org y luego de la copia de jsDelivr del mismo archivo de GitHub. Un addon que reproduce video sigue sin recomendarse. Addons de Stremio.
  • La tarjeta de tu plugin ya no lleva la insignia "Kino" (parecía hecho por Kino); los addons de Stremio y los scrapers de Nuvio conservan la suya.
  • Un addon de Stremio cuya descripción niega los torrents ya no se oculta ("no incluye streams, torrents ni contenido P2P"); el id y el nombre siguen estrictos. Lo que Kino rechaza.

Kino 0.9.50: apiVersion 6

apiVersion 6 = Kino 0.9.50. El contrato (contract.json) dice ahora maxApiVersion 6 y kino.apiVersion reporta 6. Un manifiesto con "apiVersion": 6 se rechaza en Kino 0.9.49 y anteriores ("Este plugin necesita una versión más nueva de Kino"), así que declara 6 solo si usas algo de esta lista. Todo lo que un plugin ahora puede cambiar de cómo lo muestra Kino está reunido en Personaliza tu plugin.

  • Secretos sellados más grandes y con tipo: hasta 8.192 bytes, y llaves de cifrado con tipo (use: "cipher-key") que sirven también para des-ede3. Manifiesto.
  • migrate: pasar a tu plugin lo que la persona tenía guardado y Kino ya no puede abrir. Pasar lo guardado.
  • Streams firmados por petición: signing: "request", signContext, el export sign, resolve(ref, { retry }) y alternateHosts. Firma por petición.
  • El formulario de ajustes: tipos section, status y action (hasta 16, además de los 12 con valor), settingsStatus, action con clearSettings, validateSettings, la pestaña propia en Ajustes y la sincronización entre aparatos. Formulario de ajustes.
  • debug y telemetry (true o "verbose"), kino.log.report, la página Registro, las etiquetas de logcat KinoPlugin/<id> y KinoPlay, y las métricas de reproducción. Registro y telemetría.
  • Modo debug en todo plugin: todo plugin instalado (el tuyo, un addon de Stremio convertido, un scraper de Nuvio) tiene un interruptor "Modo debug" en su pestaña de Ajustes, sin que hagas nada: encendido, sus fallas se ven en pantalla y su Registro se puede copiar o compartir, así que una persona te puede mandar una captura o su Registro. "debug": true ahora solo lo deja encendido de entrada; sin él arranca apagado. La decisión de la persona se conserva en las actualizaciones y se sincroniza con sus otros aparatos. Modo debug.
  • Los rechazos tempranos se atajan: un throw en una función async antes de su primer await lo ataja el try/catch de quien la llama (o un .catch(), un Promise.all), como en Node; solo un rechazo que nadie maneja nunca sigue haciendo fallar la llamada. Sigue haciendo el await primero si tu plugin tiene que correr en 0.9.49 y anteriores. La trampa del rechazo.
  • section, categories y theme: una sección propia, un grupo en Categorías y tus colores. Sección, categorías y colores.
  • scopedSearch: responder tú la búsqueda dentro de un "Ver más". Contrato.
  • kino.error(code, message, { userMessage }): tu propia frase para la persona, con reglas de seguridad y atribuida a tu plugin. Contrato.
  • Entradas adult: true detrás del código +18 de la persona (antes se descartaban). Contenido +18.
  • Canales en tus filas de Inicio (kind: "live" en home; antes se quitaban). Canales en vivo.
  • Pares de llaves en kino.crypto: generateKeyPair, sign, verify, importKey, deriveSharedSecret. API kino.
  • El navegador oculto: "browser": true (aprobado en rojo, "Puede abrir páginas web ocultas para encontrar el video") y kino.browser.capture, que abre un embed en una WebView oculta dentro de la app, en un resolve que empezó la persona, y devuelve las peticiones de video que hizo, retenidas para que sus tokens sigan frescos, con los encabezados y cookies para reproducirlas. Todo su tráfico pasa por un proxy con una credencial por captura e IP revisadas y fijas; la red de la casa nunca; una página a la vez; cookies y almacenamiento borrados. Una página que pide una persona termina con blocked: Kino nunca resuelve un captcha. El resolve de un plugin aprobado tiene 75 s. También, con "browser": "pages" (su propia línea roja), kino.browser.page, que lee el HTML de una página a través del mismo navegador oculto cuando la revisión automática del sitio pasa sola (nunca desde categories; el documento principal tiene que quedarse en tus hosts, revisando cada salto de redirección, o la lectura termina en blocked). Navegador oculto.
  • Stream.label y copias perezosas con etiqueta: nombra cada copia ("Latino · Servidor 1") para el nuevo menú Servidor del reproductor, y lista copias como { label, ref } que Kino resuelve con resolve(ref) solo cuando la persona escoge una, el cambio automático llega a ella (máximo 20 s cada una) o la elección de copia de una descarga la prueba. Si la escogida falla, se vuelve a la copia que se estaba viendo. Copias con etiqueta y perezosas.
  • meta: describir títulos que listaron otras fuentes (sinopsis, imágenes, capítulos) cuando TMDB y AniList no tienen nada. Describir otros títulos.

Sin apiVersion nuevo (sirve para cualquier plugin):

  • alternatives en un Stream: hasta 8 copias del mismo video; Kino pasa a la siguiente cuando una no se puede reproducir en el aparato. Contrato.
  • Reproducir en el TV desde el celular, capítulos nuevos de las series seguidas y "Para ti" funcionan para títulos de cualquier plugin. Lo que ve la persona.
  • Actualizaciones: revisión al abrir la app (máximo cada 12 h), insignia de pendientes, y una llamada fallida con una actualización pendiente lo dice. Publicar.
  • Un plugin firmado en dos repositorios cuenta como el mismo con el mismo id y la misma llave. Plugins firmados.
  • Export subtitles: responder la "Buscar subtítulos en línea" del reproductor para cualquier título que Kino conozca por id de IMDb o TMDB, junto a tus videos o como proveedor de subtítulos ("capabilities": ["subtitles"] sola). Subtítulos para cualquier título.
  • Stream.skip: dónde están la entrada y el cierre de este archivo, para "Saltar intro" / "Saltar outro"; los tuyos le ganan a AniSkip, una corrección a mano le gana a los tuyos. Contrato.
  • El campo categories del manifiesto (movies, series, anime, live, radio, subtitles, utilities, adult): los chips de categoría de la tienda de plugins. Manifiesto.
  • Formulario de ajustes: settingsStatus() se vuelve a pedir después de cada acción, así que refresh: true ya no hace falta. Formulario de ajustes.
  • Registros: solo un plugin que declara telemetry envía líneas de kino.log con una falla, recomendado o no; por ahora no hay interruptor para apagarlo. Registro y telemetría.
  • "De la comunidad" es su propia pestaña de la pantalla Plugins. Publicar.
  • Addons de subtítulos de Stremio (OpenSubtitles v3, traductores como GTSubs) se instalan como proveedores de subtítulos; las traducciones automáticas salen como "Español (traducido)". No tienes nada que escribir. Addons de Stremio.
  • Ids reservados: live, local, unknown, plugin, own, subtitle-keys, subtitle-prefs (la lista cambió: las versiones anteriores reservan algunos más, así que si una dice "El id … está reservado por Kino", escoge otro).
  • Reclamos y retiro de plugins de la comunidad: community-blocklist.json.
  • Enviar a la TV: todo HLS pasa por el celular; un archivo sin headers va directo y, si la TV no puede, por el celular. Enviar a la TV.
  • genre en una fila de Inicio, una categoría en vivo o una lista (peliculas, series, anime, infantil, documentales, deportes, noticias, musica, entretenimiento, otros): Categorías agrupa por él las filas navegables de todos los plugins, y En vivo filtra por él entre proveedores. Opcional; sin él, Kino lo adivina por el título. Contrato.
  • streamHeaders en una lista: el User-Agent o el Referer que el reproductor manda para cada canal de la lista, aparte de los headers de descarga de la propia lista. Canales en vivo.
  • Una llamada kino.* síncrona que falla se puede atajar (un kino.storage lleno, un error de kino.crypto): tu try/catch recibe un Error normal; Kino 0.9.49 terminaba ahí la llamada entera. Errores que tu código puede atrapar.
  • Después de actualizar Kino, las actualizaciones de plugins que esperan aprobación se instalan una vez, desde la dirección del propio plugin, con un aviso único "Se actualizaron tus plugins" que dice lo que cada uno puede hacer ahora. Publicar.
  • El formulario de ajustes, documentado entero: cada tipo de campo, atributo y valor por defecto, con un ejemplo completo. Formulario de ajustes.

(Las versiones de Kino anteriores a genre y streamHeaders los ignoran; no se revisó la versión exacta en que salió cada uno.)

También en esta versión (ya documentado antes en esta página como "próxima versión"):

  • Instalar desde la URL del manifiesto. La gente puede pegar la URL https de un kino-plugin.json en cualquier servidor público, no solo un owner/repo de GitHub. Una instalación url: así lee entry e icon al lado del manifiesto, no puede usar secrets sellados, siempre cuenta como no firmada y nunca sale en "De la comunidad" (el descubrimiento sigue usando el topic de GitHub). Una URL de kino-plugin.json en GitHub, raw.githubusercontent.com o jsDelivr (cdn.jsdelivr.net/gh/owner/repo@<ref exacta>/…; @latest es la rama por defecto, un rango de versiones se rechaza) se vuelve owner/repo como antes. Instalar desde la URL del manifiesto, Publicar.
  • liveSearch, un export opcional nuevo para canales en vivo (sin apiVersion nuevo: sigue siendo 3 con channels). Kino lo pide desde la búsqueda de En vivo mientras algunos de tus canales nunca se han listado; devuelve canales como una página de liveChannels, máximo 100 conservados, desde 2 caracteres escritos, 15 s. Canales en vivo.
  • Los catálogos en vivo grandes siguen paginando. liveChannels recibe 10 páginas al comienzo, y 5 más cada vez que la persona se acerca al final, hasta 10.000 canales (200 páginas) por categoría. Las versiones anteriores se quedan en 10 páginas. Pruébalo con node sdk/run.mjs . live search <consulta>.
  • Listas M3U en UTF-8, Latin-1 o UTF-16; los atributos de #EXTINF pueden ir con comillas simples o sin comillas; una lista de más de 20 MB o una guía de más de 50 MB se corta en su última línea completa en vez de rechazarse. Canales en vivo.
  • Addons de Stremio: la gente los puede instalar desde el mismo campo (Kino genera el plugin; no tienes nada que escribir). Su resolve, como el de un scraper de Nuvio convertido, tiene 75 s. Qué se admite, qué se rechaza (torrents y P2P siempre) y cómo hacer que un addon funcione bien: Addons de Stremio.
  • ditu ya no es un id de plugin reservado (las versiones anteriores lo siguen rechazando, así que evítalo).

Kino 0.9.46 a 0.9.49

  • Se acepta un ./ al principio de entry e icon. Kino lo quita e instala el plugin. Kino 0.9.45 y anteriores lo siguen rechazando (El campo "entry" debe ser una ruta relativa a un archivo .js), así que sigue escribiendo "plugin.js" e "icon.png". El validate.mjs del kit rechaza "./plugin.js" por eso. Detalles.
  • Tus logs ayudan cuando falla un plugin recomendado. En un plugin del catálogo recomendado de Kino, las últimas 30 líneas de kino.log de una llamada fallida (depuradas, 2 KB) van con el reporte del error como plugin_log. Registra pasos y estados, nunca lo que la persona escribió ni un secreto. kino.log.
  • Un canal en vivo nunca muestra el botón de descarga, aunque el plugin declare download.

Sobre la versión de cada punto

Estos puntos están en las versiones publicadas como 0.9.46 a 0.9.49; no se comprobó la versión exacta en la que apareció cada uno.

Kino 0.9.45

Contrato (contract.json, maxApiVersion 5):

  • Plugins firmados, apiVersion 5. Firma opcional del autor en kino-plugin.json (node sdk/seal.mjs --keygen, --sign; validate.mjs la comprueba), clave fijada en la primera instalación, "Firmado por su autor" en la hoja de consentimiento, insignia "Firmado", la clave del autor en los detalles. Necesita Kino 0.9.45+; las apps más viejas rechazan un manifiesto con apiVersion 5. Borradores anteriores de estos documentos decían 0.9.46: salió en 0.9.45. Plugins firmados.
  • Sin máximo de hosts. El límite de 20 desapareció (solo lo acota el manifiesto de 16 KB). Kino 0.9.44 y anteriores siguen rechazando más de 20, y el kit avisa. Manifiesto.
  • kino.apiVersion reporta 5.

Comportamiento que puedes notar (sin cambio de manifiesto):

  • Enviar a la TV (Chromecast y DLNA) funciona para títulos de plugins. Directo para mp4/webm y HLS sin headers; por el celular cuando pones headers; nunca para DRM, DASH, MPEG-TS progresivo o un formato que nada identifica. Enviar a la TV.
  • Los plugins acompañan a la persona entre sus aparatos (celular y TV): instalaciones, encendidos, aprobaciones, ajustes y contraseñas (cifradas) se sincronizan, y el otro aparato instala tu plugin desde la misma dirección. Plugins en otros aparatos.
  • Direcciones de instalación: también sirve una URL raw.githubusercontent.com/.../kino-plugin.json (o manifest.json, para Nuvio) o una github.com/.../blob/...; una ref que solo viene de una URL pegada no es un pin. Inicio, Scrapers de Nuvio.
  • Descargas HLS: EXT-X-DISCONTINUITY se deja tal cual salvo que el formato cambie en él; una llave mala o un segmento vacío terminan como "Este video no se puede descargar"; un reintento solo retoma con el mismo contenido. Las descargas siguen siendo declarativas: "download" en capabilities, nada que exportar. Descargas.
  • Headers de canales M3U: se leen #EXTHTTP, url|User-Agent=... y los headers de #KODIPROP; solo se conservan User-Agent, Referer, Origin y Cookie. Canales en vivo.
  • kino.fetch: los saltos de redirección rechazados cuentan para las 60 peticiones, máximo 6 fetch en vuelo, máximo 3 preguntas de host por llamada, se rechazan las formas IPv6 de direcciones privadas, sin proxy del dispositivo. Un plugin convertido desde un scraper de Nuvio tiene 250 peticiones y 75 s de resolve. Límites.

Sobre la versión de cada punto

El archivo del contrato fija la versión solo para los plugins firmados y el límite de hosts (0.9.45). Los demás puntos están en la compilación que se publicó como 0.9.45; no se verificó en qué versión exacta apareció cada uno.

Ya estaba antes de 0.9.45

streamHosts: "any" (apiVersion 4), liveStreamHosts: "any" (apiVersion 3 más la capacidad channels), fetchHosts: "any" (lo escribe Kino solo en scrapers de Nuvio convertidos, nunca para tu plugin), y la pregunta que Kino le hace a la persona la primera vez que un stream usa un host que no declaraste. Están documentados en el manifiesto, canales en vivo y el contrato.