lushapp 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/lush CHANGED
@@ -17,6 +17,69 @@ for path_cand in [
17
17
  import shutil
18
18
  import subprocess
19
19
 
20
+ def ensure_python_deps():
21
+ """Detects missing Python dependencies and auto-installs them on demand."""
22
+ missing = []
23
+
24
+ # Check curses on Windows
25
+ if sys.platform == "win32" or os.name == "nt":
26
+ try:
27
+ import curses
28
+ except ImportError:
29
+ try:
30
+ import windows_curses
31
+ except ImportError:
32
+ missing.append("windows-curses")
33
+
34
+ # Check requests
35
+ try:
36
+ import requests
37
+ except ImportError:
38
+ missing.append("requests")
39
+
40
+ # Check pyperclip
41
+ try:
42
+ import pyperclip
43
+ except ImportError:
44
+ missing.append("pyperclip")
45
+
46
+ # Check yt-dlp
47
+ try:
48
+ import yt_dlp
49
+ except ImportError:
50
+ missing.append("yt-dlp")
51
+
52
+ if not missing:
53
+ return
54
+
55
+ install_cmd = [sys.executable, "-m", "pip", "install", *missing]
56
+ cmd_str = f"pip install {' '.join(missing)}"
57
+
58
+ if sys.stdin.isatty():
59
+ print("\033[1;95m┌────────────────────────────────────────────────────────────────────────┐\033[0m")
60
+ print(f"\033[1;95m│\033[0m \033[1;96mLUSH Setup:\033[0m Missing Python package(s): \033[1;93m{', '.join(missing):<29}\033[0m \033[1;95m│\033[0m")
61
+ print(f"\033[1;95m│\033[0m Auto-installing via \033[1;92mpip\033[0m... \033[1;95m│\033[0m")
62
+ print("\033[1;95m└────────────────────────────────────────────────────────────────────────┘\033[0m")
63
+ try:
64
+ ans = input(f"Install required packages ({', '.join(missing)})? [Y/n]: ").strip().lower()
65
+ if ans in ("", "y", "yes"):
66
+ print(f"\n\033[1;96mInstalling: {', '.join(missing)}...\033[0m\n")
67
+ res = subprocess.run(install_cmd)
68
+ if res.returncode == 0:
69
+ print("\033[1;92m✓ Python dependencies installed successfully!\033[0m\n")
70
+ else:
71
+ print(f"\n\033[1;91m[ERROR]\033[0m Installation failed. Please run: \033[1;96m{cmd_str}\033[0m\n")
72
+ sys.exit(1)
73
+ else:
74
+ print(f"\n\033[1;93m[NOTICE]\033[0m Please run manually: \033[1;96m{cmd_str}\033[0m\n")
75
+ sys.exit(1)
76
+ except (KeyboardInterrupt, EOFError):
77
+ sys.exit(1)
78
+ else:
79
+ print(f"\033[1;91m[ERROR]\033[0m Missing Python dependencies: {', '.join(missing)}")
80
+ print(f"Please install via: \033[1;96m{cmd_str}\033[0m")
81
+ sys.exit(1)
82
+
20
83
  def ensure_audio_backend():
21
84
  """Detects if an audio player backend is available; offers auto-install if missing."""
22
85
  if shutil.which("mpv") or shutil.which("ffplay") or shutil.which("cvlc"):
@@ -54,6 +117,7 @@ def ensure_audio_backend():
54
117
  except (KeyboardInterrupt, EOFError):
55
118
  pass
56
119
 
120
+ ensure_python_deps()
57
121
  ensure_audio_backend()
58
122
 
59
123
  from lush.__main__ import main
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lushapp",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "A hyper-aesthetic terminal radio player with 560+ live stations, real-time CAVA DSP audio visualizers, ambient soundscapes, and artist discographies.",
5
5
  "main": "bin/lush.js",
6
6
  "bin": {
@@ -58,4 +58,4 @@
58
58
  "engines": {
59
59
  "node": ">=14.0.0"
60
60
  }
61
- }
61
+ }
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lushapp"
7
- version = "2.0.0"
7
+ version = "2.0.2"
8
8
  description = "A hyper-aesthetic terminal radio player with 560+ live stations, real-time CAVA DSP visualizers, and artist discographies."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "pseudoshell" }]
@@ -17,6 +17,16 @@ if (!which('mpv')) missing.push('mpv');
17
17
  if (!which('cava')) missing.push('cava');
18
18
  if (!which('ffmpeg')) missing.push('ffmpeg');
19
19
 
20
+ const pyCmd = which('python3') ? 'python3' : (which('python') ? 'python' : (which('py') ? 'py' : null));
21
+ if (pyCmd) {
22
+ try {
23
+ const pipDeps = process.platform === 'win32'
24
+ ? ['windows-curses', 'requests', 'pyperclip', 'yt-dlp']
25
+ : ['requests', 'pyperclip', 'yt-dlp'];
26
+ execSync(`${pyCmd} -m pip install -q ${pipDeps.join(' ')}`, { stdio: 'ignore' });
27
+ } catch {}
28
+ }
29
+
20
30
  if (missing.length === 0) {
21
31
  console.log('\x1b[1;92m✓ [LUSH]\x1b[0m All system dependencies (python3, mpv, cava, ffmpeg) are verified.');
22
32
  process.exit(0);
package/setup.py CHANGED
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="lushapp",
5
- version="2.0.0",
5
+ version="2.0.2",
6
6
  package_dir={"": "src"},
7
7
  packages=find_packages(where="src"),
8
8
  include_package_data=True,
@@ -1,7 +1,8 @@
1
1
  import os
2
+ import sys
2
3
  os.environ["ESCDELAY"] = "25"
3
4
 
4
- __version__ = "2.0.0"
5
+ __version__ = "2.0.2"
5
6
 
6
7
  def run_app():
7
8
  try:
@@ -10,10 +11,33 @@ def run_app():
10
11
  try:
11
12
  import windows_curses as curses
12
13
  except ImportError:
13
- print("\033[1;91m[ERROR]\033[0m Python curses library is required to run LUSH.")
14
14
  if os.name == "nt":
15
- print("On Windows, install it via: \033[1;96mpip install windows-curses\033[0m")
16
- return
15
+ if sys.stdin.isatty():
16
+ print("\033[1;95m┌────────────────────────────────────────────────────────────────────────┐\033[0m")
17
+ print("\033[1;95m│\033[0m \033[1;96mLUSH Setup:\033[0m Windows requires \033[1;93mwindows-curses\033[0m for terminal UI. \033[1;95m│\033[0m")
18
+ print("\033[1;95m└────────────────────────────────────────────────────────────────────────┘\033[0m")
19
+ try:
20
+ ans = input("Auto-install windows-curses via pip? [Y/n]: ").strip().lower()
21
+ if ans in ("", "y", "yes"):
22
+ import subprocess
23
+ subprocess.run([sys.executable, "-m", "pip", "install", "windows-curses"])
24
+ try:
25
+ import windows_curses as curses
26
+ except ImportError:
27
+ print("\033[1;91m[ERROR]\033[0m Failed to load curses. Please run: \033[1;96mpip install windows-curses\033[0m")
28
+ return
29
+ else:
30
+ print("\n\033[1;93m[NOTICE]\033[0m Please run: \033[1;96mpip install windows-curses\033[0m\n")
31
+ return
32
+ except (KeyboardInterrupt, EOFError):
33
+ return
34
+ else:
35
+ print("\033[1;91m[ERROR]\033[0m Python curses library is required to run LUSH.")
36
+ print("On Windows, install it via: \033[1;96mpip install windows-curses\033[0m")
37
+ return
38
+ else:
39
+ print("\033[1;91m[ERROR]\033[0m Python curses library is required to run LUSH.")
40
+ return
17
41
 
18
42
  import threading
19
43
  from .state import PlayerState, metadata_loop