Index: /ipk/source.arm/playersnp_vavoo/CONTROL/control
===================================================================
--- /ipk/source.arm/playersnp_vavoo/CONTROL/control	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/CONTROL/control	(revision 47966)
@@ -0,0 +1,7 @@
+Package: titan-plugin-player-vavoo
+Version: 1.0
+Description: IpTV Vavoo Plesk Server
+Section: player
+Architecture: armv7
+Showname: Vavoo
+Usepath: mnt
Index: /ipk/source.arm/playersnp_vavoo/CONTROL/postinst
===================================================================
--- /ipk/source.arm/playersnp_vavoo/CONTROL/postinst	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/CONTROL/postinst	(revision 47966)
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+echo Use Install Dest: $1
+echo Start Install Script: $0
+
+INSTDIR="$1"
+
+sed s#_path_#"$INSTDIR"#g -i "$INSTDIR/python/vavoo.py"
+
+exit 0
Index: /ipk/source.arm/playersnp_vavoo/CONTROL/postrm
===================================================================
--- /ipk/source.arm/playersnp_vavoo/CONTROL/postrm	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/CONTROL/postrm	(revision 47966)
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo Use Install Dest: $1
+echo Start Install Script: $0
+
+exit 0
Index: /ipk/source.arm/playersnp_vavoo/CONTROL/preinst
===================================================================
--- /ipk/source.arm/playersnp_vavoo/CONTROL/preinst	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/CONTROL/preinst	(revision 47966)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+echo Use Install Dest: $1
+echo Start Install Script: $0
+
+
+exit 0
Index: /ipk/source.arm/playersnp_vavoo/CONTROL/prerm
===================================================================
--- /ipk/source.arm/playersnp_vavoo/CONTROL/prerm	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/CONTROL/prerm	(revision 47966)
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo Use Install Dest: $1
+echo Start Install Script: $0
+
+exit 0
Index: /ipk/source.arm/playersnp_vavoo/_path_/etc/init.d/manage-vavoo.sh
===================================================================
--- /ipk/source.arm/playersnp_vavoo/_path_/etc/init.d/manage-vavoo.sh	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/_path_/etc/init.d/manage-vavoo.sh	(revision 47966)
@@ -0,0 +1,107 @@
+
+
+#!/bin/bash
+
+# Pfad zum Python3-Skript und Log-Datei
+SCRIPT_PATH="_path_/python/vavoo.py"
+LOG_FILE="_path_/logs/vavoo.log"
+
+# Funktion zum Starten des Skripts
+start_script() {
+    if [ ! -f "$SCRIPT_PATH" ]; then
+        echo "Skript '$SCRIPT_PATH' existiert nicht."
+        exit 1
+    fi
+
+    if pgrep -f "python3 $SCRIPT_PATH" > /dev/null; then
+        echo "Skript '$SCRIPT_PATH' läuft bereits."
+        exit 0
+    fi
+
+    echo "Starte Skript '$SCRIPT_PATH'..."
+    nohup python3 "$SCRIPT_PATH" > "$LOG_FILE" 2>&1 &
+    PID=$!
+    echo "Skript '$SCRIPT_PATH' wurde mit PID $PID gestartet. Logs: '$LOG_FILE'."
+}
+
+# Funktion zum Stoppen des Skripts
+stop_script() {
+    PID=$(pgrep -f "python3 $SCRIPT_PATH")
+
+    if [ -z "$PID" ]; then
+        echo "Skript '$SCRIPT_PATH' läuft nicht."
+        return 0
+    fi
+
+    echo "Beende Skript '$SCRIPT_PATH' mit PID $PID..."
+    kill "$PID"
+
+    # Warte kurz und prüfe, ob der Prozess wirklich beendet wurde
+    sleep 1
+    if pgrep -f "python3 $SCRIPT_PATH" > /dev/null; then
+        echo "Skript konnte nicht normal beendet werden. Versuche mit 'kill -9'..."
+        kill -9 "$PID"
+        sleep 1
+        if pgrep -f "python3 $SCRIPT_PATH" > /dev/null; then
+            echo "Skript konnte nicht beendet werden."
+            return 1
+        else
+            echo "Skript erfolgreich mit 'kill -9' beendet."
+        fi
+    else
+        echo "Skript erfolgreich beendet."
+    fi
+    return 0
+}
+
+# Funktion zum Restarten des Skripts
+restart_script() {
+    stop_script
+    sleep 0.5
+    start_script
+}
+
+# Funktion zum Abfragen des Status
+status_script() {
+    if pgrep -f "python3 $SCRIPT_PATH" > /dev/null; then
+        PID=$(pgrep -f "python3 $SCRIPT_PATH")
+        echo "Skript '$SCRIPT_PATH' läuft mit PID $PID."
+    else
+        echo "Skript '$SCRIPT_PATH' läuft nicht."
+    fi
+}
+
+# Hauptlogik: Argumente auswerten
+if [ $# -eq 0 ]; then
+    # Interaktives Menü, falls kein Argument übergeben wurde
+    echo "Wähle eine Aktion für das Skript '$SCRIPT_PATH':"
+    echo "start) Starten"
+    echo "stop) Stoppen"
+    echo "restart) Restarten"
+    echo "status) Status abfragen"
+    read -p "Eingabe (start/stop/restart/status): " choice
+else
+    # Argument auswerten
+    choice="$1"
+fi
+
+case "$choice" in
+    start)
+        start_script
+        ;;
+    stop)
+        stop_script
+        ;;
+    restart)
+        restart_script
+        ;;
+    status)
+        status_script
+        ;;
+    *)
+        echo "Ungültige Eingabe. Bitte wähle start, stop, restart oder status."
+        exit 1
+        ;;
+esac
+
+
Index: /ipk/source.arm/playersnp_vavoo/_path_/python/vavoo.py
===================================================================
--- /ipk/source.arm/playersnp_vavoo/_path_/python/vavoo.py	(revision 47966)
+++ /ipk/source.arm/playersnp_vavoo/_path_/python/vavoo.py	(revision 47966)
@@ -0,0 +1,326 @@
+###############################################################
+PORT = 4323
+ADDON_SIG_TTL = 600  # 10 Minuten
+###############################################################
+
+import json
+import gzip
+import requests
+import os
+from io import BytesIO
+import uuid
+from flask import Flask, request, Response, abort
+import time
+import socket
+import threading
+
+# ---------------- LÄNDER ----------------
+
+REGIONS = [
+    {"language": "nl", "region": "BE"},
+]
+
+GEOIP_URL = "https://www.vavoo.tv/geoip"
+PING_URL = "https://www.vavoo.tv/api/app/ping"
+CATALOG_URL = "https://vavoo.to/mediahubmx-catalog.json"
+RESOLVE_URL = "https://vavoo.to/mediahubmx-resolve.json"
+
+LANGUAGE = "de"
+REGION = "DE"
+
+HEADERS = {
+    "accept": "*/*",
+    "user-agent": "electron-fetch/1.0 electron (+https://github.com/arantes555/electron-fetch)",
+    "Accept-Language": LANGUAGE,
+    "Accept-Encoding": "gzip, deflate",
+    "Connection": "close",
+}
+
+def decode_response(resp):
+    if resp.content[:2] == b'\x1f\x8b':
+        return json.loads(gzip.decompress(resp.content))
+    return resp.json()
+
+session = requests.Session()
+session.headers.update(HEADERS)
+
+# ---------------- GEO + INITIAL PING ----------------
+
+r_geo = session.get(GEOIP_URL)
+r_geo.raise_for_status()
+geo_data = decode_response(r_geo)
+
+unique_id = str(uuid.uuid4())
+current_timestamp = int(time.time() * 1000)
+
+initial_payload = {
+    "reason": "app-focus",
+    "locale": "de",
+    "theme": "dark",
+    "metadata": {
+        "device": {"type": "desktop", "uniqueId": unique_id},
+        "os": {"name": "win32", "version": "Windows 10 Pro", "abis": ["x64"], "host": "Lenovo"},
+        "app": {"platform": "electron"},
+        "version": {"package": "tv.vavoo.app", "binary": "3.1.8", "js": "3.1.8"},
+    },
+    "appFocusTime": 0,
+    "playerActive": False,
+    "playDuration": 0,
+    "devMode": False,
+    "hasAddon": True,
+    "castConnected": False,
+    "package": "tv.vavoo.app",
+    "version": "3.1.8",
+    "process": "app",
+    "firstAppStart": current_timestamp,
+    "lastAppStart": current_timestamp,
+    "ipLocation": None,
+    "adblockEnabled": True,
+    "proxy": {"supported": ["ss"], "engine": "Mu", "enabled": False, "autoServer": True},
+    "iap": {"supported": False},
+}
+
+r1 = session.post(PING_URL, json=initial_payload)
+r1.raise_for_status()
+data1 = decode_response(r1)
+
+# ---------------- ADDON SIG MANAGEMENT ----------------
+
+addon_sig_lock = threading.Lock()
+addon_sig_data = {
+    "sig": data1.get("addonSig"),
+    "ts": time.time()
+}
+
+def refresh_addon_sig_if_needed(force=False):
+    with addon_sig_lock:
+        now = time.time()
+        if not force and now - addon_sig_data["ts"] < ADDON_SIG_TTL:
+            return addon_sig_data["sig"]
+
+        payload = initial_payload.copy()
+        payload["lastAppStart"] = int(time.time() * 1000)
+
+        r = session.post(PING_URL, json=payload)
+        r.raise_for_status()
+        data = decode_response(r)
+
+        sig = data.get("addonSig")
+        if not sig:
+            raise RuntimeError("No addonSig received")
+
+        addon_sig_data["sig"] = sig
+        addon_sig_data["ts"] = now
+
+        print("[✓] addonSig refreshed")
+        return sig
+
+# ---------------- CATALOG LOAD (MULTI-REGION) ----------------
+
+items_by_region = {}
+
+for entry in REGIONS:
+    LANGUAGE = entry["language"]
+    REGION = entry["region"]
+    region_key = f"{LANGUAGE}-{REGION}"
+
+    print(f"[+] Lade Katalog für {region_key}")
+
+    catalog_headers = {
+        "content-type": "application/json; charset=utf-8",
+        "mediahubmx-signature": addon_sig_data["sig"],
+        "user-agent": "MediaHubMX/2",
+        "accept": "*/*",
+        "Accept-Language": LANGUAGE,
+        "Accept-Encoding": "gzip, deflate",
+        "Connection": "close",
+    }
+
+    cursor = None
+
+    while True:
+        catalog_payload = {
+            "language": LANGUAGE,
+            "region": REGION,
+            "catalogId": "iptv",
+            "id": "iptv",
+            "adult": False,
+            "search": "",
+            "sort": "",
+            "filter": {},
+            "cursor": cursor,
+            "clientVersion": "3.0.2"
+        }
+
+        r_catalog = session.post(CATALOG_URL, json=catalog_payload, headers=catalog_headers)
+        r_catalog.raise_for_status()
+        catalog_data = decode_response(r_catalog)
+
+        for item in catalog_data.get("items", []):
+            if item.get("type") == "iptv":
+                items_by_region.setdefault(region_key, []).append({
+                    "id": item["ids"]["id"],
+                    "url": item["url"],
+                    "name": item["name"],
+                    "group": item["group"],
+                    "logo": item["logo"],
+                    "language": LANGUAGE,
+                    "region": REGION
+                })
+
+        cursor = catalog_data.get("nextCursor")
+        if not cursor:
+            break
+
+print(f"[✓] Gesamtanzahl IPTV-Sender: {sum(len(v) for v in items_by_region.values())}")
+
+# ---------------- M3U SAVE (MULTI-FILE) ----------------
+
+LOCAL_IP = "127.0.0.1"
+
+def get_local_ip():
+    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    s.connect(("8.8.8.8", 80))  # Connecting to Google's DNS server
+    local_ip = s.getsockname()[0]  # Getting the local IP address
+    s.close()
+    print("Local IP address:", local_ip)
+    return local_ip
+#    return LOCAL_IP
+
+# Unterordner erstellen
+PLAYLIST_DIR = "playlists"
+os.makedirs(PLAYLIST_DIR, exist_ok=True)
+
+def save_m3u_files():
+    local_ip = get_local_ip()
+
+    for region_key, items in items_by_region.items():
+        filename = os.path.join(PLAYLIST_DIR, f"vavoo_{region_key}.m3u")
+        m3u = "#EXTM3U\n"
+
+        for item in items:
+            m3u += (
+                f'#EXTINF:-1 tvg-id="{item["id"]}" '
+                f'tvg-name="{item["name"]}" '
+                f'tvg-logo="{item["logo"]}" '
+#                f'group-title="{item["group"]} ({item["region"]})",{item["name"]}\n'
+                f'group-title="{item["group"]}",{item["name"]}\n'
+            )
+            m3u += f"http://{local_ip}:{PORT}/vavoo?channel={item['id']}\n"
+
+        with open(filename, "w", encoding="utf-8") as f:
+            f.write(m3u)
+
+        print(f"[✓] {filename} geschrieben")
+
+def save_master_m3u():
+    master = "#EXTM3U\n"
+
+    for region_key in items_by_region.keys():
+        filename = f"playlists/vavoo_{region_key}.m3u"
+        master += f'#EXTINF:-1 group-title="Master",{region_key}\n'
+        master += f"{filename}\n"
+
+    with open("vavoo_master.m3u", "w", encoding="utf-8") as f:
+        f.write(master)
+
+    print("[✓] vavoo_master.m3u geschrieben")
+
+save_m3u_files()
+save_master_m3u()
+
+# ---------------- FLASK APP ----------------
+
+app = Flask(__name__)
+
+@app.route("/vavoo")
+def stream_proxy():
+    channel_id = request.args.get("channel")
+    if not channel_id:
+        abort(400)
+
+    channel = None
+    for region_items in items_by_region.values():
+        for i in region_items:
+            if i["id"] == channel_id:
+                channel = i
+                break
+
+    if not channel:
+        abort(404)
+
+    try:
+        sig = refresh_addon_sig_if_needed()
+    except Exception as e:
+        abort(502, str(e))
+
+    resolve_headers = {
+        "content-type": "application/json; charset=utf-8",
+        "mediahubmx-signature": sig,
+        "user-agent": "MediaHubMX/2",
+        "accept": "*/*",
+        "Accept-Language": channel["language"],
+        "Accept-Encoding": "gzip, deflate",
+        "Connection": "close",
+    }
+
+    resolve_payload = {
+        "language": channel["language"],
+        "region": channel["region"],
+        "url": channel["url"],
+        "clientVersion": "3.0.2"
+    }
+
+    r_resolve = session.post(RESOLVE_URL, json=resolve_payload, headers=resolve_headers)
+
+    if r_resolve.status_code == 403:
+        sig = refresh_addon_sig_if_needed(force=True)
+        resolve_headers["mediahubmx-signature"] = sig
+        r_resolve = session.post(RESOLVE_URL, json=resolve_payload, headers=resolve_headers)
+
+    r_resolve.raise_for_status()
+    result = decode_response(r_resolve)
+
+    if result:
+        return Response(status=302, headers={"Location": result[0]["url"]})
+
+    abort(404)
+
+
+# ---------------- ALL-IN-ONE PLAYLIST ----------------
+
+@app.route("/playlist.m3u")
+def playlist():
+    local_ip = get_local_ip()
+    m3u = "#EXTM3U\n"
+
+    for region_items in items_by_region.values():
+        for item in region_items:
+            m3u += (
+                f'#EXTINF:-1 tvg-id="{item["id"]}" '
+                f'tvg-name="{item["name"]}" '
+                f'tvg-logo="{item["logo"]}" '
+#                f'group-title="{item["group"]} ({item["region"]})",{item["name"]}\n'
+                f'group-title="{item["group"]}",{item["name"]}\n'
+            )
+            m3u += f"http://{local_ip}:{PORT}/vavoo?channel={item['id']}\n"
+
+    return Response(m3u, mimetype="application/x-mpegURL")
+
+
+# ---------------- MASTER PLAYLIST ----------------
+
+@app.route("/master.m3u")
+def master_playlist():
+    try:
+        with open("vavoo_master.m3u", "r", encoding="utf-8") as f:
+            content = f.read()
+        return Response(content, mimetype="application/x-mpegURL")
+    except FileNotFoundError:
+        return Response("#EXTM3U\n# Master playlist not found\n", mimetype="application/x-mpegURL")
+
+
+# ---------------- START SERVER ----------------
+
+if __name__ == "__main__":
+    app.run(host="0.0.0.0", port=PORT)
