SpotDown 0.1.1__py3-none-any.whl → 1.3.0__py3-none-any.whl
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.
- SpotDown/downloader/youtube_downloader.py +20 -6
- SpotDown/extractor/spotify_extractor.py +165 -278
- SpotDown/extractor/youtube_extractor.py +15 -1
- SpotDown/main.py +6 -8
- SpotDown/upload/version.py +2 -2
- SpotDown/utils/config_json.py +2 -2
- SpotDown/utils/console_utils.py +1 -1
- SpotDown/utils/ffmpeg_installer.py +374 -0
- SpotDown/utils/file_utils.py +105 -1
- SpotDown/utils/logger.py +90 -0
- {spotdown-0.1.1.dist-info → spotdown-1.3.0.dist-info}/METADATA +63 -30
- spotdown-1.3.0.dist-info/RECORD +21 -0
- spotdown-0.1.1.dist-info/RECORD +0 -19
- {spotdown-0.1.1.dist-info → spotdown-1.3.0.dist-info}/WHEEL +0 -0
- {spotdown-0.1.1.dist-info → spotdown-1.3.0.dist-info}/entry_points.txt +0 -0
- {spotdown-0.1.1.dist-info → spotdown-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {spotdown-0.1.1.dist-info → spotdown-1.3.0.dist-info}/top_level.txt +0 -0
SpotDown/utils/logger.py
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# 05.04.2024
|
2
|
+
|
3
|
+
import os
|
4
|
+
import logging
|
5
|
+
from logging.handlers import RotatingFileHandler
|
6
|
+
|
7
|
+
|
8
|
+
# Internal utils
|
9
|
+
from SpotDown.utils.config_json import config_manager
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
class Logger:
|
14
|
+
_instance = None
|
15
|
+
|
16
|
+
def __new__(cls):
|
17
|
+
# Singleton pattern to avoid multiple logger instances
|
18
|
+
if cls._instance is None:
|
19
|
+
cls._instance = super(Logger, cls).__new__(cls)
|
20
|
+
cls._instance._initialized = False
|
21
|
+
return cls._instance
|
22
|
+
|
23
|
+
def __init__(self):
|
24
|
+
# Initialize only once
|
25
|
+
if getattr(self, '_initialized', False):
|
26
|
+
return
|
27
|
+
|
28
|
+
# Configure root logger
|
29
|
+
self.debug_mode = config_manager.get_bool('DEFAULT', "debug")
|
30
|
+
self.logger = logging.getLogger('')
|
31
|
+
|
32
|
+
# Remove any existing handlers to avoid duplication
|
33
|
+
for handler in self.logger.handlers[:]:
|
34
|
+
self.logger.removeHandler(handler)
|
35
|
+
|
36
|
+
# Reduce logging level for external libraries
|
37
|
+
logging.getLogger("httpx").setLevel(logging.WARNING)
|
38
|
+
logging.getLogger("httpcore").setLevel(logging.WARNING)
|
39
|
+
|
40
|
+
# Set logging level based on debug_mode
|
41
|
+
if self.debug_mode:
|
42
|
+
self.logger.setLevel(logging.DEBUG)
|
43
|
+
# In debug mode: log SOLO nel file, non nel terminale
|
44
|
+
self._configure_console_log_file()
|
45
|
+
else:
|
46
|
+
self.logger.setLevel(logging.ERROR)
|
47
|
+
# In modalità normale: log solo nel terminale per gli errori
|
48
|
+
self._configure_console_logging()
|
49
|
+
|
50
|
+
self._initialized = True
|
51
|
+
|
52
|
+
def _configure_console_logging(self):
|
53
|
+
"""Configure console logging output to terminal."""
|
54
|
+
console_handler = logging.StreamHandler()
|
55
|
+
console_handler.setLevel(logging.ERROR) # Solo errori nel terminale
|
56
|
+
formatter = logging.Formatter('[%(filename)s:%(lineno)s - %(funcName)20s() ] %(asctime)s - %(levelname)s - %(message)s')
|
57
|
+
console_handler.setFormatter(formatter)
|
58
|
+
self.logger.addHandler(console_handler)
|
59
|
+
|
60
|
+
def _configure_console_log_file(self):
|
61
|
+
"""Create a console.log file only when debug mode is enabled."""
|
62
|
+
console_log_path = "console.log"
|
63
|
+
try:
|
64
|
+
# Remove existing file if present
|
65
|
+
if os.path.exists(console_log_path):
|
66
|
+
os.remove(console_log_path)
|
67
|
+
|
68
|
+
# Create handler for console.log
|
69
|
+
console_file_handler = RotatingFileHandler(
|
70
|
+
console_log_path,
|
71
|
+
maxBytes=5*1024*1024, # 5 MB
|
72
|
+
backupCount=3
|
73
|
+
)
|
74
|
+
console_file_handler.setLevel(logging.DEBUG)
|
75
|
+
formatter = logging.Formatter('[%(filename)s:%(lineno)s - %(funcName)20s() ] %(asctime)s - %(levelname)s - %(message)s')
|
76
|
+
console_file_handler.setFormatter(formatter)
|
77
|
+
self.logger.addHandler(console_file_handler)
|
78
|
+
|
79
|
+
except Exception as e:
|
80
|
+
print(f"Error creating console.log: {e}")
|
81
|
+
|
82
|
+
@staticmethod
|
83
|
+
def get_logger(name=None):
|
84
|
+
"""
|
85
|
+
Get a specific logger for a module/component.
|
86
|
+
If name is None, returns the root logger.
|
87
|
+
"""
|
88
|
+
# Ensure Logger instance is initialized
|
89
|
+
Logger()
|
90
|
+
return logging.getLogger(name)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: SpotDown
|
3
|
-
Version:
|
3
|
+
Version: 1.3.0
|
4
4
|
Summary: A command-line program to download music
|
5
5
|
Home-page: https://github.com/Arrowar/spotdown
|
6
6
|
Author: Arrowar
|
@@ -13,12 +13,12 @@ Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
14
14
|
Requires-Dist: rich
|
15
15
|
Requires-Dist: httpx
|
16
|
-
Requires-Dist: playwright
|
17
16
|
Requires-Dist: unidecode
|
18
17
|
Requires-Dist: ua-generator
|
19
18
|
Requires-Dist: unidecode
|
20
19
|
Requires-Dist: yt-dlp
|
21
20
|
Requires-Dist: Pillow
|
21
|
+
Requires-Dist: spotipy
|
22
22
|
Dynamic: author
|
23
23
|
Dynamic: author-email
|
24
24
|
Dynamic: classifier
|
@@ -41,6 +41,7 @@ Dynamic: summary
|
|
41
41
|
## 💝 Support the Project
|
42
42
|
|
43
43
|
[](https://www.paypal.com/donate/?hosted_button_id=UXTWMT8P6HE2C)
|
44
|
+
|
44
45
|
## 🚀 Download & Install
|
45
46
|
|
46
47
|
[](https://github.com/Arrowar/spotdown/releases/latest/download/spotdown_win.exe)
|
@@ -50,7 +51,7 @@ Dynamic: summary
|
|
50
51
|
|
51
52
|
---
|
52
53
|
|
53
|
-
*⚡ **Quick Start:** `pip install spotdown
|
54
|
+
*⚡ **Quick Start:** `pip install spotdown && spotdown`*
|
54
55
|
|
55
56
|
</div>
|
56
57
|
|
@@ -58,9 +59,9 @@ Dynamic: summary
|
|
58
59
|
|
59
60
|
- [✨ Features](#features)
|
60
61
|
- [🛠️ Installation](#️installation)
|
62
|
+
- [⚙️ Setup](#setup)
|
61
63
|
- [⚙️ Configuration](#configuration)
|
62
64
|
- [💻 Usage](#usage)
|
63
|
-
- [⚠️ Disclaimer](#disclaimer)
|
64
65
|
|
65
66
|
## Features
|
66
67
|
|
@@ -68,38 +69,61 @@ Dynamic: summary
|
|
68
69
|
- 📋 **Download entire playlists** with ease
|
69
70
|
- 🔍 **No authentication required** - uses web scraping
|
70
71
|
- 🎨 **Automatic cover art embedding** (JPEG format)
|
72
|
+
- ⚡ **Simple command-line interface** - just run `spotdown`!
|
71
73
|
|
72
74
|
## Installation
|
73
75
|
|
74
|
-
###
|
76
|
+
### Method 1: PyPI (Recommended)
|
75
77
|
|
76
|
-
|
77
|
-
|
78
|
-
|
78
|
+
```bash
|
79
|
+
pip install spotdown
|
80
|
+
```
|
79
81
|
|
80
|
-
|
82
|
+
That's it! You can now run `spotdown` from anywhere in your terminal.
|
83
|
+
|
84
|
+
### Method 2: From Source
|
85
|
+
|
86
|
+
If you prefer to install from source:
|
81
87
|
|
82
88
|
```bash
|
83
|
-
|
89
|
+
git clone https://github.com/Arrowar/spotdown.git
|
90
|
+
cd spotdown
|
91
|
+
pip install -e .
|
84
92
|
```
|
85
93
|
|
86
|
-
###
|
94
|
+
### Prerequisites
|
95
|
+
|
96
|
+
The following dependencies will be automatically installed:
|
97
|
+
|
98
|
+
- **Python 3.8+**
|
99
|
+
- **FFmpeg** (for audio processing)
|
100
|
+
- **yt-dlp** (for downloading)
|
101
|
+
- **Playwright** (for web scraping)
|
102
|
+
|
103
|
+
After installation, run this one-time setup command:
|
87
104
|
|
88
105
|
```bash
|
89
106
|
playwright install chromium
|
90
107
|
```
|
91
108
|
|
92
|
-
|
109
|
+
## Setup
|
93
110
|
|
94
|
-
|
111
|
+
1. Go to the [Spotify Developer Dashboard](https://developer.spotify.com/dashboard/)
|
112
|
+
2. Log in and create a new application
|
113
|
+
3. Copy your **Client ID** and **Client Secret**
|
114
|
+
4. Create a file named `.env` in the SpotDown directory with the following content:
|
95
115
|
|
96
|
-
```
|
97
|
-
|
98
|
-
|
99
|
-
if __name__ == "__main__":
|
100
|
-
main()
|
116
|
+
```
|
117
|
+
SPOTIFY_CLIENT_ID=your_client_id_here
|
118
|
+
SPOTIPY_CLIENT_SECRET=your_client_secret_here
|
101
119
|
```
|
102
120
|
|
121
|
+
5. Save the file. SpotDown will automatically load these credentials.
|
122
|
+
|
123
|
+
### Error Handling
|
124
|
+
- If the credentials are missing, SpotDown will log an error and exit.
|
125
|
+
- If the credentials are invalid, SpotDown will log an error and exit. Please double-check your `.env` file and credentials.
|
126
|
+
|
103
127
|
## Configuration
|
104
128
|
|
105
129
|
SpotDown uses a JSON configuration file with the following structure:
|
@@ -113,10 +137,6 @@ SpotDown uses a JSON configuration file with the following structure:
|
|
113
137
|
"DOWNLOAD": {
|
114
138
|
"auto_first": false,
|
115
139
|
"quality": "320K"
|
116
|
-
},
|
117
|
-
"BROWSER": {
|
118
|
-
"headless": true,
|
119
|
-
"timeout": 6
|
120
140
|
}
|
121
141
|
}
|
122
142
|
```
|
@@ -131,21 +151,21 @@ SpotDown uses a JSON configuration file with the following structure:
|
|
131
151
|
- **`auto_first`**: Automatically select first search result
|
132
152
|
- **`quality`**: Audio quality (320K recommended for best quality)
|
133
153
|
|
134
|
-
#### BROWSER Settings
|
135
|
-
- **`headless`**: Run browser in background (recommended: true)
|
136
|
-
- **`timeout`**: Browser timeout in seconds
|
137
|
-
|
138
154
|
## Usage
|
139
155
|
|
140
|
-
###
|
156
|
+
### Starting SpotDown
|
157
|
+
|
158
|
+
Simply run the following command in your terminal:
|
141
159
|
|
142
160
|
```bash
|
143
|
-
|
161
|
+
spotdown
|
144
162
|
```
|
145
163
|
|
164
|
+
The interactive interface will guide you through the download process.
|
165
|
+
|
146
166
|
### Download Individual Songs
|
147
167
|
|
148
|
-
1. Run
|
168
|
+
1. Run `spotdown`
|
149
169
|
2. Paste the Spotify song URL when prompted
|
150
170
|
3. The script will automatically:
|
151
171
|
- Extract song information
|
@@ -154,15 +174,28 @@ python run.py
|
|
154
174
|
|
155
175
|
### Download Playlists
|
156
176
|
|
157
|
-
1. Run
|
177
|
+
1. Run `spotdown`
|
158
178
|
2. Paste the Spotify playlist URL when prompted
|
159
179
|
3. All songs in the playlist will be downloaded automatically
|
160
180
|
|
181
|
+
### Example Usage
|
182
|
+
|
183
|
+
```bash
|
184
|
+
$ spotdown
|
185
|
+
🎵 Welcome to SpotDown!
|
186
|
+
Please paste your Spotify URL: https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh
|
187
|
+
🔍 Processing: Song Name - Artist Name
|
188
|
+
⬇️ Downloading...
|
189
|
+
✅ Download complete!
|
190
|
+
```
|
191
|
+
|
161
192
|
## To Do
|
162
193
|
|
163
194
|
- [ ] Implement batch download queue
|
164
195
|
- [ ] Add GUI interface option
|
165
196
|
- [ ] Support for additional music platforms
|
197
|
+
- [ ] Album art quality selection
|
198
|
+
- [ ] Custom output directory configuration
|
166
199
|
|
167
200
|
## Disclaimer
|
168
201
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
SpotDown/__init__.py,sha256=ebKRxKh14_cO7UWvOgE4R1RqIFBdekg50xtzc1LU6DU,59
|
2
|
+
SpotDown/main.py,sha256=qTNHAyXdxe6BMwwTMssuFBdpfdxMEYwFM6LweGiBBYI,5084
|
3
|
+
SpotDown/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
SpotDown/downloader/youtube_downloader.py,sha256=i4Iq7jFKD8dFxpWHPcxgE2_hykwHf6TQXZSal_FHUAY,5557
|
5
|
+
SpotDown/extractor/__init__.py,sha256=pQtkjMzB4D8AVEFQ3pnp_UQI-KbYaQhZbKuDnMImN0o,161
|
6
|
+
SpotDown/extractor/spotify_extractor.py,sha256=gI4iJvs_MYV7MO-zcuUXavqtQo5jDAuXNqXs2ScTjDE,7755
|
7
|
+
SpotDown/extractor/youtube_extractor.py,sha256=v1JDV_NHBpc56UU5kk4tfaRjPB0Jy23_F5r4LE2gOlU,10442
|
8
|
+
SpotDown/upload/version.py,sha256=uvgDGChIXb3JAYtO_GQPGc-au8t6sDfzX40RkqQex14,161
|
9
|
+
SpotDown/utils/__init__.py,sha256=ZhJJhNQkUd4XG6vkoVQSC3qvSlaArhsRjscn4bfC9WA,128
|
10
|
+
SpotDown/utils/config_json.py,sha256=q_9lQhGLmsaZfM1WU-kOMByf8y1Wt9QWnZT5g_IR4Lg,7447
|
11
|
+
SpotDown/utils/console_utils.py,sha256=oW7jD3UjrSlYoZ8R7VJAV8WPymD2NZGs1SS5BUUQ3Zk,6825
|
12
|
+
SpotDown/utils/ffmpeg_installer.py,sha256=kFcjr9HqQyxu01mpWumt8d_0D9aEkxMb5sSBJqSkR0w,14889
|
13
|
+
SpotDown/utils/file_utils.py,sha256=eNb0JT99FyeMGCoVzFkyhF-39FZE-yogwtUgKSbaTCs,7132
|
14
|
+
SpotDown/utils/headers.py,sha256=nSF2rEQEl7g2tIJMjz9c5mAQfLiugfWwdlJBhtMfBSo,312
|
15
|
+
SpotDown/utils/logger.py,sha256=Bzje-6nwGxL7TzMVhJfhPe7mv-9upYylFvx_zjWJX3M,3290
|
16
|
+
spotdown-1.3.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
17
|
+
spotdown-1.3.0.dist-info/METADATA,sha256=apC3RZd0_akzY0ujIZ_EdcdqWkBsx-9gxMM0CaUh9CA,6836
|
18
|
+
spotdown-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
19
|
+
spotdown-1.3.0.dist-info/entry_points.txt,sha256=qHq6M94aU-XQL0y9R4yFKoqnHjU2nsN53Bj4OuHp3vQ,47
|
20
|
+
spotdown-1.3.0.dist-info/top_level.txt,sha256=1E-ZZ8rsrXmBPAsseY_kEfHfNo9w9PtSCaS6pM63-tw,9
|
21
|
+
spotdown-1.3.0.dist-info/RECORD,,
|
spotdown-0.1.1.dist-info/RECORD
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
SpotDown/__init__.py,sha256=ebKRxKh14_cO7UWvOgE4R1RqIFBdekg50xtzc1LU6DU,59
|
2
|
-
SpotDown/main.py,sha256=TjxUMIe0ee8IMbnYhXekO2MoLRiY6pJ5CCPgz7pOpHg,5042
|
3
|
-
SpotDown/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
SpotDown/downloader/youtube_downloader.py,sha256=zHl98F2Ax72wTg3n8pohmkBZgBIPff0NrD9QKhG-TBM,4589
|
5
|
-
SpotDown/extractor/__init__.py,sha256=pQtkjMzB4D8AVEFQ3pnp_UQI-KbYaQhZbKuDnMImN0o,161
|
6
|
-
SpotDown/extractor/spotify_extractor.py,sha256=abE48E4M8s3xf95a28IYD8L4K2-QFDaYoZC5V0Jqu-4,13486
|
7
|
-
SpotDown/extractor/youtube_extractor.py,sha256=XIPNWEBb5oUkGP1DrQ4h4XTJvHlBlbVIkAFNdpFE-Rc,9586
|
8
|
-
SpotDown/upload/version.py,sha256=hjqk3lk5Ic6SKn0Dk_-gfU6u75JmZLl5bcDSWIKdOAE,162
|
9
|
-
SpotDown/utils/__init__.py,sha256=ZhJJhNQkUd4XG6vkoVQSC3qvSlaArhsRjscn4bfC9WA,128
|
10
|
-
SpotDown/utils/config_json.py,sha256=Z_fuM2mYQVPc51sQ_-LXrX-ArTPL-lRDcQ3lLM_hmck,7435
|
11
|
-
SpotDown/utils/console_utils.py,sha256=A1zNRyB9yG7BqWzlQgfVZ25cWUjMmYQooRKyeqVlcDw,6823
|
12
|
-
SpotDown/utils/file_utils.py,sha256=Lgq_Nu1r-bVIH37H7Mx73WgotN_nrgMUAT2STDyEYoY,3495
|
13
|
-
SpotDown/utils/headers.py,sha256=nSF2rEQEl7g2tIJMjz9c5mAQfLiugfWwdlJBhtMfBSo,312
|
14
|
-
spotdown-0.1.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
15
|
-
spotdown-0.1.1.dist-info/METADATA,sha256=C3V6JqDDU14RFwGsniGuO-uEHOzvVvOezNPZ7Haqi_I,5744
|
16
|
-
spotdown-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
17
|
-
spotdown-0.1.1.dist-info/entry_points.txt,sha256=qHq6M94aU-XQL0y9R4yFKoqnHjU2nsN53Bj4OuHp3vQ,47
|
18
|
-
spotdown-0.1.1.dist-info/top_level.txt,sha256=1E-ZZ8rsrXmBPAsseY_kEfHfNo9w9PtSCaS6pM63-tw,9
|
19
|
-
spotdown-0.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|