Erste Version
This commit is contained in:
203
build.py
Normal file
203
build.py
Normal file
@@ -0,0 +1,203 @@
|
||||
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")
|
||||
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())
|
Reference in New Issue
Block a user