diff --git a/README.md b/README.md index de5db55..1b0c3e8 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ ![Media Fusion Streams](resources/images/ss2.png?raw=true) -- **Scraper Support**: +- **Advanced Scraper Support**: - 🏎️ **Formula Racing**: Exclusive scraping from TorrentGalaxy for all your racing needs. - 🥊 **Fighting Sports**: Catch up on all the latest fighting sports content from UFC and WWE. - 🏈🏀⚾⚽🏒🏉🎾 **American Football, Basketball, Baseball, Football, Hockey, Rugby/AFL, and Other Sports**: Now all scraping through sport-video.org.ua for catchup videos. @@ -35,8 +35,11 @@ - 🌟 **TamilBlasters**: Dedicated access to an extensive library of regional content. - 📺 **TamilUltra & NowMeTV**: Get the best of Live TV channels right at your fingertips. - 🔄 **Prowlarr Integration**: Supercharge your scraping streams with Prowlarr's powerful integration. + - 🔍 **Advanced Prowlarr Integration**: Improved Prowlarr feed scraping for more comprehensive content discovery with latest updates. - 🌊 **Torrentio/KnightCrawler Streams**: Optional scraping streams directly from Torrentio/KnightCrawler streams for even more variety. - - 🔍 **Zilean DMM Search**: Search for movies and TV shows with [Zilean DMM](https://github.com/iPromKnight/zilean) for a cached debrid contents. + - 🔍 **Zilean DMM Search**: Search for movies and TV shows with [Zilean DMM](https://github.com/iPromKnight/zilean) for cached debrid contents. + - 📺 **MPD DRM Scraping**: Scraping MPD & Support streaming functionality with MediaFlow MPD DRM support. + - **Additional Features**: - 🔒 **API Security**: Fortify your self-hosted API with a password to prevent unauthorized access. @@ -48,6 +51,13 @@ - ✨ **Manual Scraper Triggering UI**: Manage your scraping sources with a manual trigger UI for a more hands-on approach. - 🗑️ **Delete Watchlist**: Delete your watchlist from the stremio for quick control over your content. - 🔍 **Prowlarr Indexer Support**: Use [MediaFusion as an indexer in Prowlarr](/resources/yaml/mediafusion.yaml) for searching movies and TV shows with Radarr and Sonarr. + - 🔞 **Parental Controls**: Filter content based on nudity and certification ratings. + - 🎬 **IMDb Integration**: Display IMDb ratings with the logo for quick quality assessment. + - 🕰️ **Sports Event Timing**: View the time for sports events directly on the poster for better planning. + - 🌐 **MediaFlow Proxy**: Support for MediaFlow Proxy for Debrid and Live streams, enhancing accessibility. + - 🎥 **RPDB Posters**: RPDB posters support with fallback to MediaFusion posters. + - 📥 **Browser Download Support**: Support for downloading video files from debrid services directly in the browser. + - 🚫 **Support DMCA Take Down**: Torrent blocking feature for DMCA compliance. ## 🚀 Installation Guide diff --git a/deployment/docker-compose/docker-compose.yml b/deployment/docker-compose/docker-compose.yml index ed91f54..78f6871 100644 --- a/deployment/docker-compose/docker-compose.yml +++ b/deployment/docker-compose/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: mediafusion: - image: mhdzumair/mediafusion:beta + image: mhdzumair/mediafusion:4.0.0 ports: - "8000:8000" env_file: @@ -41,7 +41,7 @@ services: - "6379:6379" dramatiq-worker: - image: mhdzumair/mediafusion:beta + image: mhdzumair/mediafusion:4.0.0 command: ["pipenv", "run", "dramatiq", "api.task", "-p", "1", "-t", "1", "--queues", "scrapy"] env_file: - .env diff --git a/deployment/k8s/local-deployment.yaml b/deployment/k8s/local-deployment.yaml index 2283aed..9330a72 100644 --- a/deployment/k8s/local-deployment.yaml +++ b/deployment/k8s/local-deployment.yaml @@ -19,7 +19,7 @@ spec: spec: containers: - name: mediafusion - image: mhdzumair/mediafusion:v3.9.15 + image: mhdzumair/mediafusion:v4.0.0 ports: - containerPort: 8000 resources: @@ -124,7 +124,7 @@ spec: spec: containers: - name: dramatiq-worker - image: mhdzumair/mediafusion:v3.9.15 + image: mhdzumair/mediafusion:v4.0.0 command: ["pipenv", "run", "dramatiq", "api.task", "-p", "1", "-t", "1"] env: - name: HOST_URL diff --git a/deployment/qbittorrent-webdav/README.md b/deployment/qbittorrent-webdav/README.md index cefeabc..f8e73dd 100644 --- a/deployment/qbittorrent-webdav/README.md +++ b/deployment/qbittorrent-webdav/README.md @@ -57,10 +57,16 @@ Configure MediaFusion: 1. Open MediaFusion config page. 2. Select "qBittorrent - WebDav" as the streaming provider. -3. Fill in WebUI and WebDAV URLs (use local addresses for a local setup). -4. Enter WebDAV credentials if set; leave blank if not. -5. Adjust seeding settings and 'Play Video After Download' percentage. -6. Save and start streaming through Stremio. +3. Get the Docker IP address using following command: + ```bash + docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' + ``` +4. Fill in WebUI and WebDAV URLs: + - If running MediaFusion locally (not in Docker): Use `http://localhost:8080` + - If running MediaFusion in Docker: Use `http://:8080`, where `` is the IP obtained in step 3. +5. Enter WebDAV credentials if set; leave blank if not. +6. Adjust seeding settings and 'Play Video After Download' percentage. +7. Save and start streaming through Stremio. Refer to the screenshot below for a visual guide: ![MediaFusion qBittorrent-WebDAV Configuration](/deployment/qbittorrent-webdav/ss.png) diff --git a/deployment/qbittorrent-webdav/apache-config.conf b/deployment/qbittorrent-webdav/apache-config.conf index 9f95bff..37f0846 100644 --- a/deployment/qbittorrent-webdav/apache-config.conf +++ b/deployment/qbittorrent-webdav/apache-config.conf @@ -13,6 +13,6 @@ DAV On Options Indexes FollowSymLinks MultiViews AllowOverride All - Require all granted + # The authentication directives will be added here by the entrypoint script \ No newline at end of file diff --git a/deployment/qbittorrent-webdav/entrypoint.sh b/deployment/qbittorrent-webdav/entrypoint.sh index 995e729..f767b0b 100644 --- a/deployment/qbittorrent-webdav/entrypoint.sh +++ b/deployment/qbittorrent-webdav/entrypoint.sh @@ -29,11 +29,13 @@ HTPASSWD_PATH="/etc/apache2/.htpasswd" # Check if .htpasswd file exists and configure basic auth for WebDAV accordingly if [ -f "$HTPASSWD_PATH" ]; then echo "Basic auth password file found. Configuring WebDAV with basic auth." - sed -i '//,/<\/Directory>/{/Require /d}' /etc/apache2/conf.d/000-default.conf + sed -i '//,/<\/Directory>/{/AuthType/d;/AuthName/d;/AuthUserFile/d;/Require/d}' /etc/apache2/conf.d/000-default.conf sed -i '//a \\tAuthType Basic\n\tAuthName "WebDAV"\n\tAuthUserFile '"$HTPASSWD_PATH"'\n\tRequire valid-user' /etc/apache2/conf.d/000-default.conf else echo "No basic auth password file found. Configuring WebDAV without basic auth." + sed -i '//,/<\/Directory>/{/AuthType/d;/AuthName/d;/AuthUserFile/d;/Require/d}' /etc/apache2/conf.d/000-default.conf + sed -i '//a \\tRequire all granted' /etc/apache2/conf.d/000-default.conf fi # start supervisord -/usr/bin/supervisord -c /etc/supervisord.conf +/usr/bin/supervisord -c /etc/supervisord.conf \ No newline at end of file diff --git a/deployment/qbittorrent-webdav/ss.png b/deployment/qbittorrent-webdav/ss.png index 1f53d03..4cfcdc3 100644 Binary files a/deployment/qbittorrent-webdav/ss.png and b/deployment/qbittorrent-webdav/ss.png differ diff --git a/kodi/plugin.video.mediafusion/addon.xml b/kodi/plugin.video.mediafusion/addon.xml index eb10044..267d2ad 100644 --- a/kodi/plugin.video.mediafusion/addon.xml +++ b/kodi/plugin.video.mediafusion/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/kodi/plugin.video.mediafusion/lib/custom_settings_window.py b/kodi/plugin.video.mediafusion/lib/custom_settings_window.py index b26e53a..e44479b 100644 --- a/kodi/plugin.video.mediafusion/lib/custom_settings_window.py +++ b/kodi/plugin.video.mediafusion/lib/custom_settings_window.py @@ -104,6 +104,7 @@ class CustomSettingsWindow(xbmcgui.WindowXMLDialog): response = requests.post( urljoin(self.base_url, "kodi/generate_setup_code"), json=data ) + response.raise_for_status() data = response.json() code = data["code"] qr_code_url = data["qr_code_url"] diff --git a/kodi/plugin.video.mediafusion/lib/router.py b/kodi/plugin.video.mediafusion/lib/router.py index d70e426..bb7d92f 100644 --- a/kodi/plugin.video.mediafusion/lib/router.py +++ b/kodi/plugin.video.mediafusion/lib/router.py @@ -19,7 +19,7 @@ from .utils import ( def list_categories(): - manifest_data = fetch_data(f"{BASE_URL}/{SECRET_STR}/manifest.json") + manifest_data = fetch_data(parse.urljoin(BASE_URL, f"/{SECRET_STR}/manifest.json")) if not manifest_data: return @@ -106,7 +106,10 @@ def process_videos(videos, action, catalog_type, catalog_id): def list_catalog(params): log(f"Loading {params['catalog_type']} videos...", xbmc.LOGINFO) skip = int(params.get("skip", 0)) - url = f"{BASE_URL}/{SECRET_STR}/catalog/{params['catalog_type']}/{params['catalog_id']}/skip={skip}.json" + url = parse.urljoin( + BASE_URL, + f"/{SECRET_STR}/catalog/{params['catalog_type']}/{params['catalog_id']}/skip={skip}.json", + ) force_refresh = params.get("force_refresh", False) response = fetch_data(url, force_refresh) if not response: @@ -145,7 +148,10 @@ def search_catalog(params): if not search_query: return - url = f"{BASE_URL}/{SECRET_STR}/catalog/{params['catalog_type']}/{params['catalog_id']}/search={search_query}.json" + url = parse.urljoin( + BASE_URL, + f"/{SECRET_STR}/catalog/{params['catalog_type']}/{params['catalog_id']}/search={search_query}.json", + ) force_refresh = params.get("force_refresh", False) response = fetch_data(url, force_refresh) if not response: @@ -169,7 +175,10 @@ def search_catalog(params): def list_seasons(params): - url = f"{BASE_URL}/{SECRET_STR}/meta/{params['catalog_type']}/{params['video_id']}.json" + url = parse.urljoin( + BASE_URL, + f"/{SECRET_STR}/meta/{params['catalog_type']}/{params['video_id']}.json", + ) force_refresh = params.get("force_refresh", False) response = fetch_data(url, force_refresh) if not response: @@ -233,7 +242,10 @@ def list_seasons(params): def list_episodes(params): - url = f"{BASE_URL}/{SECRET_STR}/meta/{params['catalog_type']}/{params['video_id']}.json" + url = parse.urljoin( + BASE_URL, + f"/{SECRET_STR}/meta/{params['catalog_type']}/{params['video_id']}.json", + ) force_refresh = params.get("force_refresh", False) response = fetch_data(url, force_refresh) if not response: @@ -299,7 +311,10 @@ def list_episodes(params): def get_streams(params): - url = f"{BASE_URL}/{SECRET_STR}/stream/{params['catalog_type']}/{params['video_id']}.json" + url = parse.urljoin( + BASE_URL, + f"/{SECRET_STR}/stream/{params['catalog_type']}/{params['video_id']}.json", + ) force_refresh = params.get("force_refresh", False) response = fetch_data(url, force_refresh) if not response: diff --git a/kodi/plugin.video.mediafusion/lib/utils.py b/kodi/plugin.video.mediafusion/lib/utils.py index 37fe6f1..122ad2a 100644 --- a/kodi/plugin.video.mediafusion/lib/utils.py +++ b/kodi/plugin.video.mediafusion/lib/utils.py @@ -1,3 +1,4 @@ +import sqlite3 import sys from urllib import parse @@ -13,13 +14,6 @@ ADDON = xbmcaddon.Addon() ADDON_PATH = sys.argv[0] ADDON_ID = ADDON.getAddonInfo("id") -# Initialize requests_cache with CachedSession -cache_file = xbmcvfs.translatePath( - f"special://profile/addon_data/{ADDON_ID}/cache.sqlite" -) -session = requests_cache.CachedSession( - cache_name=cache_file, backend="sqlite", cache_control=True -) BASE_URL = ADDON.getSetting("base_url") SECRET_STR = ADDON.getSetting("secret_string") @@ -37,10 +31,13 @@ if not SECRET_STR: def remove_cache(url): + session = get_request_session() session.cache.delete_url(url) def fetch_data(url, force_refresh=False): + session = get_request_session() + if force_refresh: with session.cache_disabled(): response = session.get(url) @@ -120,3 +117,35 @@ def is_elementum_installed_and_enabled(): return True except Exception: return False + + +def get_request_session(): + # Initialize requests_cache with CachedSession + cache_file = xbmcvfs.translatePath( + f"special://profile/addon_data/{ADDON_ID}/cache.sqlite" + ) + try: + session = requests_cache.CachedSession( + cache_name=cache_file, backend="sqlite", cache_control=True + ) + except sqlite3.OperationalError as e: + xbmc.log(f"Failed to setup cache: {e}", xbmc.LOGERROR) + try: + fallback_cache_file = xbmcvfs.translatePath( + f"special://temp/{ADDON_ID}_cache.sqlite" + ) + session = requests_cache.CachedSession( + cache_name=fallback_cache_file, backend="sqlite", cache_control=True + ) + xbmc.log( + f"Using fallback cache location: {fallback_cache_file}", xbmc.LOGINFO + ) + except sqlite3.OperationalError: + xbmc.log("Fallback to in-memory cache", xbmc.LOGWARNING) + session = requests_cache.CachedSession( + cache_name="mediafusion_request", backend="memory", cache_control=True + ) + xbmcgui.Dialog().notification( + "MediaFusion", f"Cache setup issue: {str(e)}", xbmcgui.NOTIFICATION_WARNING + ) + return session diff --git a/kodi/plugin.video.mediafusion/resources/skins/default/1080i/custom_settings_window.xml b/kodi/plugin.video.mediafusion/resources/skins/default/1080i/custom_settings_window.xml index 0f02036..dca0241 100644 --- a/kodi/plugin.video.mediafusion/resources/skins/default/1080i/custom_settings_window.xml +++ b/kodi/plugin.video.mediafusion/resources/skins/default/1080i/custom_settings_window.xml @@ -33,7 +33,6 @@ 50 font60 - FF00FFFF center @@ -44,7 +43,7 @@ 50 50 FFFFFF00 - triangle-left.png + triangle-left.png triangle-left.png @@ -108,7 +107,7 @@ FF000000 FFFFFFFF - white.png + white.png white.png center center @@ -169,7 +168,7 @@ FF000000 FFFFFFFF - white.png + white.png white.png center center diff --git a/resources/html/configure.html b/resources/html/configure.html index b0c9a60..1312421 100644 --- a/resources/html/configure.html +++ b/resources/html/configure.html @@ -641,7 +641,7 @@ Kodi Addon Setup Guide - + - - diff --git a/resources/html/home.html b/resources/html/home.html index 430bbff..eec9688 100644 --- a/resources/html/home.html +++ b/resources/html/home.html @@ -5,18 +5,18 @@ - {{addon_name}} - Stremio Addon + {{ addon_name }} - Stremio Addon - +
- -

{{addon_name}} - {{version}}

+ +

{{ addon_name }} - {{ version }}

🔎 Advanced Scraping Capabilities

Tap into a world of content with our enhanced scraping features:

@@ -29,6 +29,8 @@
  • 📺 TamilUltra & NowMeTV: Get the best of Live TV channels right at your fingertips.
  • 🔄 Prowlarr Integration: Supercharge your scraping streams with Prowlarr's powerful integration.
  • 🌊 Torrentio/KnightCrawler Streams: Optional scraping streams directly from Torrentio/KnightCrawler streams for even more variety.
  • +
  • 🔍 Advanced Prowlarr Integration: Improved Prowlarr feed scraping for more comprehensive content discovery with latest updates.
  • +
  • 📺 MPD DRM Scraping: Scraping MPD & Support streaming functionality with MediaFlow MPD DRM support.
  • 🎬 Streaming Provider Integration

    @@ -49,35 +51,22 @@

    🛠️ Enhanced Additional Features

    Our addon comes packed with features designed to elevate your streaming experience:

      -
    • 🔒 API Security: Fortify your self-hosted API with a password to prevent unauthorized access. -
    • -
    • 🔐 User Data Encryption: Encrypt user data for heightened privacy and security, storing only - encrypted URLs on Stremio. -
    • -
    • 📋 Watchlist Catalog Support: Sync your streaming provider's watchlist directly into the - Stremio catalog for a personalized touch. -
    • -
    • ⚙️ Stream Filters: Customize your viewing experience with filters that sort streams by file - size, resolution, seeders and much more. -
    • -
    • - 🖼️ Poster with Title: Display the poster with the title for a more visually appealing - catalog on sport events. -
    • -
    • - 📺 M3U Playlist Import: Import M3U playlists for a more personalized streaming experience. -
    • -
    • - ✨ Manual Scraper Triggering UI: Manage your scraping sources with a manual trigger UI for a - more hands-on approach. -
    • -
    • - 🗑️ Delete Watchlist: Delete your watchlist from the stremio for quick control over your - content. -
    • -
    • - 🔍 Prowlarr Indexer Support: Use MediaFusion as an indexer in Prowlarr for searching movies and TV shows with Radarr and Sonarr. -
    • +
    • 🔒 API Security: Fortify your self-hosted API with a password to prevent unauthorized access.
    • +
    • 🔐 User Data Encryption: Encrypt user data for heightened privacy and security, storing only encrypted URLs on Stremio.
    • +
    • 📋 Watchlist Catalog Support: Sync your streaming provider's watchlist directly into the Stremio catalog for a personalized touch.
    • +
    • ⚙️ Stream Filters: Customize your viewing experience with filters that sort streams by file size, resolution, seeders and much more.
    • +
    • 🖼️ Poster with Title: Display the poster with the title for a more visually appealing catalog on sport events.
    • +
    • 📺 M3U Playlist Import: Import M3U playlists for a more personalized streaming experience.
    • +
    • ✨ Manual Scraper Triggering UI: Manage your scraping sources with a manual trigger UI for a more hands-on approach.
    • +
    • 🗑️ Delete Watchlist: Delete your watchlist from the stremio for quick control over your content.
    • +
    • 🔍 Prowlarr Indexer Support: Use MediaFusion as an indexer in Prowlarr for searching movies and TV shows with Radarr and Sonarr.
    • +
    • 🔞 Parental Controls: Filter content based on nudity and certification ratings.
    • +
    • 🎬 IMDb Integration: Display IMDb ratings with the logo for quick quality assessment.
    • +
    • 🕰️ Sports Event Timing: View the time for sports events directly on the poster for better planning.
    • +
    • 🌐 MediaFlow Proxy: Support for MediaFlow Proxy for Debrid and Live streams, enhancing accessibility.
    • +
    • 🎥 RPDB Posters: Support for RPDB posters with fallback to MediaFusion posters.
    • +
    • 📥 Browser Download Support: Support for downloading video files from debrid services directly in the browser.
    • +
    • 🚫 Support DMCA Take Down: Torrent blocking feature for DMCA compliance.
    diff --git a/resources/js/config_script.js b/resources/js/config_script.js index 45a2eaa..02f704b 100644 --- a/resources/js/config_script.js +++ b/resources/js/config_script.js @@ -407,16 +407,9 @@ function setupPasswordToggle(passwordInputId, toggleButtonId, toggleIconId) { } async function initiateKodiSetup() { - const urlParams = new URLSearchParams(window.location.search); - const kodiCode = urlParams.get('kodi_code'); - - if (kodiCode) { - await setupKodiAddon(kodiCode); - } else { - // Show modal to input Kodi code - const kodiCodeModal = new bootstrap.Modal(document.getElementById('kodiCodeModal')); - kodiCodeModal.show(); - } + // Show modal to input Kodi code + const kodiCodeModal = new bootstrap.Modal(document.getElementById('kodiCodeModal')); + kodiCodeModal.show(); } async function submitKodiCodeAndSetup() { diff --git a/resources/manifest.json b/resources/manifest.json index 1efa49c..a00f47b 100644 --- a/resources/manifest.json +++ b/resources/manifest.json @@ -1,6 +1,6 @@ { "id": "stremio.addons", - "version": "3.9.15", + "version": "4.0.0", "name": "Media Fusion", "contactEmail": "mhdzumair@gmail.com", "description": "Universal Stremio Add-on for Movies, Series, Live TV & Sports Events. Source: https://github.com/mhdzumair/MediaFusion", diff --git a/utils/network.py b/utils/network.py index f2f5e4e..83efa00 100644 --- a/utils/network.py +++ b/utils/network.py @@ -184,7 +184,7 @@ async def get_mediaflow_proxy_public_ip( try: async with httpx.AsyncClient() as client: response = await client.get( - mediaflow_proxy_url + "/proxy/ip", + parse.urljoin(mediaflow_proxy_url, "/proxy/ip"), params={"api_password": api_password}, timeout=10, )