212 lines
7.7 KiB
Python
212 lines
7.7 KiB
Python
import os
|
|
import sys
|
|
import shutil
|
|
import subprocess
|
|
import argparse
|
|
import importlib.util
|
|
import json
|
|
import re
|
|
|
|
def check_requirements():
|
|
"""Überprüft, ob alle erforderlichen Pakete installiert sind."""
|
|
try:
|
|
import PyQt5
|
|
import PyInstaller
|
|
except ImportError as e:
|
|
print(f"Fehler: {e}")
|
|
print("Bitte führe 'pip install -r requirements.txt' aus.")
|
|
return False
|
|
return True
|
|
|
|
def find_yt_dlp():
|
|
"""Versucht, yt-dlp im PATH zu finden."""
|
|
try:
|
|
result = subprocess.run(
|
|
["where", "yt-dlp"] if os.name == "nt" else ["which", "yt-dlp"],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode == 0:
|
|
path = result.stdout.strip().split("\n")[0]
|
|
return path
|
|
return None
|
|
except Exception:
|
|
return None
|
|
|
|
def download_yt_dlp():
|
|
"""Lädt die aktuelle Version von yt-dlp herunter."""
|
|
bin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bin")
|
|
|
|
if not os.path.exists(bin_dir):
|
|
os.makedirs(bin_dir)
|
|
|
|
print("Lade yt-dlp herunter...")
|
|
|
|
ytdlp_url = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe"
|
|
ytdlp_path = os.path.join(bin_dir, "yt-dlp.exe")
|
|
|
|
try:
|
|
import requests
|
|
response = requests.get(ytdlp_url)
|
|
with open(ytdlp_path, "wb") as f:
|
|
f.write(response.content)
|
|
print(f"yt-dlp wurde nach {ytdlp_path} heruntergeladen.")
|
|
return True
|
|
except Exception as e:
|
|
print(f"Fehler beim Herunterladen von yt-dlp: {e}")
|
|
print("Bitte lade yt-dlp manuell herunter und platziere es im 'bin' Ordner.")
|
|
return False
|
|
|
|
def copy_yt_dlp_from_path():
|
|
"""Kopiert yt-dlp aus dem PATH in den bin-Ordner."""
|
|
ytdlp_path = find_yt_dlp()
|
|
|
|
if not ytdlp_path:
|
|
print("yt-dlp wurde nicht im PATH gefunden.")
|
|
return False
|
|
|
|
bin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bin")
|
|
|
|
if not os.path.exists(bin_dir):
|
|
os.makedirs(bin_dir)
|
|
|
|
try:
|
|
dest_path = os.path.join(bin_dir, "yt-dlp.exe" if os.name == "nt" else "yt-dlp")
|
|
shutil.copy2(ytdlp_path, dest_path)
|
|
print(f"yt-dlp wurde nach {dest_path} kopiert.")
|
|
return True
|
|
except Exception as e:
|
|
print(f"Fehler beim Kopieren von yt-dlp: {e}")
|
|
return False
|
|
|
|
def build_exe(onedir=False, console=False):
|
|
"""Erstellt die ausführbare Datei mit PyInstaller."""
|
|
print("Erstelle EXE-Datei...")
|
|
# Nur Default-Presets übernehmen
|
|
main_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "main.py")
|
|
with open(main_path, "r", encoding="utf-8") as f:
|
|
main_code = f.read()
|
|
# Default-Presets extrahieren (vereinfachte Suche)
|
|
match = re.search(r'defaults\s*=\s*\[(.*?)\n\s*\]', main_code, re.DOTALL)
|
|
if match:
|
|
defaults_code = "[" + match.group(1) + "]"
|
|
try:
|
|
# eval mit eingeschränktem Namespace
|
|
defaults = eval(defaults_code, {"__builtins__": None}, {})
|
|
except Exception as e:
|
|
print(f"Fehler beim Parsen der Default-Presets: {e}")
|
|
defaults = []
|
|
else:
|
|
print("Konnte Default-Presets nicht finden!")
|
|
defaults = []
|
|
# Presets-Ordner bereinigen und nur Default-Presets schreiben
|
|
bin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bin")
|
|
presets_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "presets")
|
|
if os.path.exists(presets_dir):
|
|
for f in os.listdir(presets_dir):
|
|
if f.endswith('.json'):
|
|
try:
|
|
os.remove(os.path.join(presets_dir, f))
|
|
except Exception:
|
|
pass
|
|
else:
|
|
os.makedirs(presets_dir)
|
|
for preset in defaults:
|
|
filename = f"{preset['name'].lower().replace(' ', '_')}.json"
|
|
try:
|
|
with open(os.path.join(presets_dir, filename), 'w', encoding='utf-8') as f:
|
|
json.dump(preset, f, indent=4, ensure_ascii=False)
|
|
except Exception as e:
|
|
print(f"Fehler beim Schreiben von Default-Preset {preset['name']}: {e}")
|
|
# Rest wie gehabt
|
|
cmd = ["pyinstaller"]
|
|
if not onedir:
|
|
cmd.append("--onefile")
|
|
if not console:
|
|
cmd.append("--windowed")
|
|
|
|
# Icon-Pfad festlegen und zur Befehlszeile hinzufügen
|
|
icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon.ico")
|
|
if os.path.exists(icon_path):
|
|
cmd.extend(["--icon", icon_path])
|
|
print(f"Icon wird verwendet: {icon_path}")
|
|
else:
|
|
print("Warnung: icon.ico wurde nicht gefunden.")
|
|
|
|
if os.path.exists(bin_dir) and os.listdir(bin_dir):
|
|
cmd.extend(["--add-data", f"{bin_dir}{os.pathsep}bin"])
|
|
if os.path.exists(presets_dir):
|
|
cmd.extend(["--add-data", f"{presets_dir}{os.pathsep}presets"])
|
|
cmd.append("main.py")
|
|
print(f"Führe aus: {' '.join(cmd)}")
|
|
try:
|
|
try:
|
|
subprocess.run(cmd, check=True)
|
|
except FileNotFoundError:
|
|
print("pyinstaller nicht im PATH gefunden, versuche 'python -m PyInstaller' ...")
|
|
cmd[0:1] = [sys.executable, "-m", "PyInstaller"]
|
|
subprocess.run(cmd, check=True)
|
|
if onedir:
|
|
print("Die ausführbare Datei wurde im 'dist/main' Ordner erstellt.")
|
|
else:
|
|
print("Die ausführbare Datei wurde als 'dist/main.exe' erstellt.")
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Fehler beim Erstellen der EXE-Datei: {e}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"Unerwarteter Fehler: {e}")
|
|
return False
|
|
|
|
def parse_arguments():
|
|
"""Parst die Kommandozeilenargumente."""
|
|
parser = argparse.ArgumentParser(description="Build-Skript für YT-DLP GUI")
|
|
parser.add_argument("--onedir", action="store_true", help="Erstellt einen Ordner statt einer einzelnen Datei")
|
|
parser.add_argument("--console", action="store_true", help="Zeigt die Konsole an")
|
|
parser.add_argument("--download-ytdlp", action="store_true", help="Lädt yt-dlp herunter")
|
|
parser.add_argument("--copy-ytdlp", action="store_true", help="Kopiert yt-dlp aus dem PATH")
|
|
|
|
return parser.parse_args()
|
|
|
|
def main():
|
|
args = parse_arguments()
|
|
|
|
if not check_requirements():
|
|
return 1
|
|
|
|
# Überprüfe, ob yt-dlp bereits im bin-Ordner existiert
|
|
bin_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "bin")
|
|
ytdlp_exists = os.path.exists(os.path.join(bin_dir, "yt-dlp.exe" if os.name == "nt" else "yt-dlp"))
|
|
|
|
if not ytdlp_exists:
|
|
if args.download_ytdlp:
|
|
if not download_yt_dlp():
|
|
return 1
|
|
elif args.copy_ytdlp:
|
|
if not copy_yt_dlp_from_path():
|
|
print("yt-dlp konnte nicht kopiert werden. Versuche, es herunterzuladen...")
|
|
if not download_yt_dlp():
|
|
return 1
|
|
else:
|
|
# Frage den Benutzer
|
|
print("yt-dlp wurde nicht im bin-Ordner gefunden.")
|
|
choice = input("Möchten Sie (1) yt-dlp herunterladen, (2) aus dem PATH kopieren oder (3) ohne fortfahren? [1/2/3]: ")
|
|
|
|
if choice == "1":
|
|
if not download_yt_dlp():
|
|
return 1
|
|
elif choice == "2":
|
|
if not copy_yt_dlp_from_path():
|
|
print("yt-dlp konnte nicht kopiert werden. Versuche, es herunterzuladen...")
|
|
if not download_yt_dlp():
|
|
return 1
|
|
|
|
# Erstelle die ausführbare Datei
|
|
if not build_exe(onedir=args.onedir, console=args.console):
|
|
return 1
|
|
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |