LooStream : addon Stremio pour l’agrégation de flux streaming + userscript bypass proxy

LooStream : addon Stremio pour l’agrégation de flux streaming + userscript bypass proxy

Loo-Stick a pensé à ceux qui ne veulent pas payer de débrideur pour utiliser Stremio/Nuvio/whatever en créant cet addon de flux qui agrège les sources vidéos de divers sites de streaming.
Faut pas voir ça comme la source de flux par excellence mais c’est entièrement gratuit, ça dépanne et c’est sale à souhait vis-à-vis des sites de streaming 🙂

Voici mon exemple de compose. Il ne prévoit pas de proxy, pour le compose originel, voir GitHub.

services:
  loostream:
    image: ghcr.io/loo-stick/loostream:latest
    container_name: stremio-loostream
    restart: always
    ports:
      - ${PORT:-7002}:${PORT:-7002}
    env_file:
      - .env
    environment:
      - NODE_ENV=production
    volumes:
      - /home/aerya/docker/stremio-loostream:/app/config
    healthcheck:
      test:
        - CMD
        - node
        - -e
        - require('http').get('http://localhost:7002/api/stats',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
networks: {}

Et le .env d’exemple est à prendre sur le GitHub directement.


Addon sympa mais qui souffre de 2 défauts à mon goût :
– impossible de le configurer sans proxy pour streamer depuis les sites de streaming (le proxy local = passer par le serveur hébergeant l’addon),
– s’il est possible de modifier l’ordre de VF, MULTI, VO et VOSTFR, on ne peut en revanche pas en désélectionner.


Addon amélioré hier et ces fonctionnalités ont été ajoutées :


Fiabilité nettement améliorée (rétro-ingénierie façon Onyx) • Fini la mire « troll » sur fsvid (Movix HD, FrenchStream, Coflix) • Vidmoly & luluvdo (Wiflix, VoirDrama, VoirAnime) réparés • Liste de sources plus rapide (moins de latence)
Nouveau dans le configure • Cases à cocher pour exclure les langues non voulues • Option « Direct — sans proxy »


Du coup, voici un userscript qui ajoute ces fonctionnalités. A utiliser avec ViolentMonkey, TamperMonkey etc. Pensez à modifier l’URL de l’addon dans // @match

// ==UserScript==
// @name         LooStream - Mode Direct + filtres langues
// @namespace    https://github.com/Loo-stick/loostream
// @version      1.1.0
// @description  Ajoute un mode Direct et permet d'activer/désactiver MULTI, VF, VOSTFR et VO
// @match        http://192.168.0.196:7002/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function () {
    'use strict';

    if (!location.pathname.endsWith('/configure')) return;

    let directMode = false;

    // ------------------------------------------------------------------------
    // MODE DIRECT
    // ------------------------------------------------------------------------

    const proxyCard = [...document.querySelectorAll('.card')]
        .find(card => card.querySelector('h2')?.textContent.includes('Mode de proxy'));

    if (proxyCard) {
        const localOption = proxyCard.querySelector('[data-mode="local"]');

        if (localOption && !proxyCard.querySelector('[data-mode="direct"]')) {
            const directOption = document.createElement('div');

            directOption.className = 'option';
            directOption.dataset.mode = 'direct';

            directOption.innerHTML = `
                <h3>
                    <span>🚀</span> Direct — sans proxy
                    <span class="badge">Self-host</span>
                </h3>
                <p>
                    LooStream récupère les URLs des flux puis Stremio lit
                    directement depuis les CDN, sans MediaFlow.
                </p>
            `;

            localOption.insertAdjacentElement('afterend', directOption);

            directOption.addEventListener('click', () => {
                directMode = true;

                document.querySelectorAll('.option').forEach(option => {
                    option.classList.remove('selected');
                });

                directOption.classList.add('selected');

                document.getElementById('mf-config')?.classList.remove('show');
                document.getElementById('local-warning')?.classList.remove('show');
                document.getElementById('result')?.classList.remove('show');
            });

            document
                .querySelectorAll('[data-mode="mediaflow"], [data-mode="local"]')
                .forEach(option => {
                    option.addEventListener('click', () => {
                        directMode = false;
                    });
                });
        }
    }

    // ------------------------------------------------------------------------
    // FILTRES LANGUES
    // ------------------------------------------------------------------------

    const langList = document.getElementById('lang-list');

    if (langList) {
        const title = langList
            .closest('.input-group')
            ?.querySelector('label');

        if (title) {
            title.textContent =
                'Langues activées et ordre de préférence (glisser pour réordonner)';
        }

        langList.querySelectorAll('.lang-item').forEach(item => {
            const lang = item.dataset.lang;

            if (!lang || item.querySelector('.loostream-lang-toggle')) return;

            const checkbox = document.createElement('input');

            checkbox.type = 'checkbox';
            checkbox.checked = true;
            checkbox.className = 'loostream-lang-toggle';
            checkbox.dataset.lang = lang;

            checkbox.style.width = '18px';
            checkbox.style.height = '18px';
            checkbox.style.cursor = 'pointer';
            checkbox.style.flexShrink = '0';

            // Empêche le clic sur la checkbox de lancer le drag
            checkbox.addEventListener('mousedown', e => {
                e.stopPropagation();
            });

            checkbox.addEventListener('click', e => {
                e.stopPropagation();

                item.style.opacity = checkbox.checked ? '1' : '0.45';

                const desc = item.querySelector('.lang-desc');

                if (desc) {
                    desc.style.textDecoration =
                        checkbox.checked ? '' : 'line-through';
                }

                document.getElementById('result')
                    ?.classList.remove('show');
            });

            item.insertBefore(
                checkbox,
                item.querySelector('.position')?.nextSibling || item.firstChild
            );
        });

        // Valeurs par défaut :
        // MULTI = activé
        // VF = activé
        // VOSTFR = désactivé
        // VO = désactivé

        ['VOSTFR', 'VO'].forEach(lang => {
            const checkbox =
                langList.querySelector(
                    `.loostream-lang-toggle[data-lang="${lang}"]`
                );

            if (checkbox) {
                checkbox.checked = false;

                const item = checkbox.closest('.lang-item');

                if (item) {
                    item.style.opacity = '0.45';

                    const desc = item.querySelector('.lang-desc');

                    if (desc) {
                        desc.style.textDecoration = 'line-through';
                    }
                }
            }
        });
    }

    // ------------------------------------------------------------------------
    // LANGUES SÉLECTIONNÉES
    // ------------------------------------------------------------------------

    function getSelectedLangOrder() {
        const result = [];

        document
            .querySelectorAll('#lang-list .lang-item')
            .forEach(item => {
                const checkbox =
                    item.querySelector('.loostream-lang-toggle');

                if (checkbox?.checked) {
                    result.push(item.dataset.lang);
                }
            });

        return result;
    }

    // ------------------------------------------------------------------------
    // GÉNÉRATION DU MANIFESTE
    // ------------------------------------------------------------------------

    const originalGenerateUrl = window.generateUrl;

    window.generateUrl = function () {

        // Pour MediaFlow / Local, on conserve le fonctionnement LooStream
        // mais on veut quand même appliquer le filtrage des langues.
        if (!directMode) {
            const originalGetLangOrder = window.getLangOrder;

            window.getLangOrder = getSelectedLangOrder;

            try {
                return originalGenerateUrl();
            } finally {
                window.getLangOrder = originalGetLangOrder;
            }
        }

        const tmdbKey =
            document.getElementById('tmdb-key')?.value.trim();

        if (!tmdbKey) {
            alert('Veuillez entrer votre clé API TMDB');
            return;
        }

        const langOrder = getSelectedLangOrder();

        if (langOrder.length === 0) {
            alert('Sélectionnez au moins une langue.');
            return;
        }

        const config = {
            // Le backend LooStream accepte "mediaflow".
            // Sans mfUrl, il utilise son fallback URL directe.
            proxy: 'mediaflow',

            tmdbKey,

            prefQuality:
                document.getElementById('pref-quality')?.value || '1080p',

            langOrder,

            minStreams:
                parseInt(
                    document.getElementById('min-streams')?.value || '5',
                    10
                )
        };

        const accessKey =
            document.getElementById('access-key')?.value.trim();

        if (accessKey) {
            config.accessKey = accessKey;
        }

        // Volontairement absents :
        //
        // config.mfUrl
        // config.mfPass

        const configStr =
            btoa(JSON.stringify(config));

        const installUrl =
            `${location.origin}/${configStr}/manifest.json`;

        const input =
            document.getElementById('install-url');

        if (input) {
            input.value = installUrl;
        }

        document
            .getElementById('result')
            ?.classList.add('show');

        console.log(
            '[LooStream Direct] Config générée:',
            config
        );
    };

    console.log(
        '[LooStream Direct] Mode Direct + sélection des langues activés.'
    );

})();
1
2
S’abonner
Notification pour
guest
0 Commentaires
Le plus ancien
Le plus récent Le plus populaire