Skip to content

Commit a393cc4

Browse files
authored
Release v4.0.0.rc.5
2 parents c159840 + 07fadad commit a393cc4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+52704
-57799
lines changed

Dockerfile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@ RUN apk add --no-cache \
1717
# Install poetry and update pip/wheel
1818
RUN pip install --upgrade pip poetry wheel
1919

20+
# Copy requirements files
21+
COPY poetry.lock pyproject.toml /
22+
23+
# Install spotdl requirements
24+
RUN poetry install
25+
2026
# Add source code files to WORKDIR
2127
ADD . .
2228

23-
# Install requirements
29+
# Install spotdl itself
2430
RUN poetry install
2531

2632
# Create music directory

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
version: '3'
1+
version: "3"
22
services:
33
spotdl:
4-
image: "spotDL/spotify-downloader"
4+
image: "spotdl/spotify-downloader"
55
volumes:
66
- .:/music

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "spotdl"
3-
version = "4.0.0-rc.4"
3+
version = "4.0.0-rc.5"
44
description = "Download your Spotify playlists and songs along with album art and metadata"
55
license = "MIT"
66
authors = ["spotDL Team <[email protected]>"]
@@ -26,7 +26,7 @@ classifiers = [
2626
]
2727

2828
[tool.poetry.dependencies]
29-
python = ">=3.7,<3.11"
29+
python = ">=3.7,<=3.11"
3030

3131
spotipy = "^2.19.0"
3232
ytmusicapi = "^0.22.0"

spotdl/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
Version module for spotdl.
33
"""
44

5-
__version__ = "4.0.0-rc.4"
5+
__version__ = "4.0.0-rc.5"

spotdl/console/entry_point.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,13 @@ def entry_point():
171171
bitrate=settings["bitrate"],
172172
ffmpeg_args=settings["ffmpeg_args"],
173173
output_format=settings["format"],
174-
save_file=settings["save_file"],
175174
threads=settings["threads"],
176175
output=settings["output"],
176+
save_file=settings["save_file"],
177177
overwrite=settings["overwrite"],
178-
search_query=settings["search_query"],
179178
cookie_file=settings["cookie_file"],
179+
filter_results=settings["filter_results"],
180+
search_query=settings["search_query"],
180181
log_level=settings["log_level"],
181182
simple_tui=settings["simple_tui"],
182183
restrict=settings["restrict"],

spotdl/console/meta.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ def process_file(file: Path):
9696
f"Fetching lyrics for {song.display_name}"
9797
)
9898
lyrics = downloader.search_lyrics(song)
99-
song.lyrics = lyrics
99+
if lyrics:
100+
song.lyrics = lyrics
101+
downloader.progress_handler.log(
102+
f"No lyrics found for song: {song.display_name}"
103+
)
100104

101105
# Apply metadata to the song
102106
embed_metadata(file, song, file.suffix.split(".")[-1])

spotdl/download/downloader.py

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from yt_dlp.postprocessor.sponsorblock import SponsorBlockPP
1717
from yt_dlp.postprocessor.modify_chapters import ModifyChaptersPP
1818

19-
from spotdl.types import Song, SongList
19+
from spotdl.types import Song
2020
from spotdl.utils.ffmpeg import FFmpegError, convert, get_ffmpeg_path
2121
from spotdl.utils.metadata import embed_metadata, MetadataError, get_song_metadata
2222
from spotdl.utils.formatter import create_file_name, restrict_filename
@@ -26,6 +26,7 @@
2626
from spotdl.providers.audio import YouTube, YouTubeMusic
2727
from spotdl.download.progress_handler import NAME_TO_LEVEL, ProgressHandler
2828
from spotdl.utils.config import get_errors_path, get_temp_path
29+
from spotdl.utils.search import reinit_song
2930

3031

3132
AUDIO_PROVIDERS: Dict[str, Type[AudioProvider]] = {
@@ -80,10 +81,10 @@ def __init__(
8081
search_query: Optional[str] = None,
8182
log_level: str = "INFO",
8283
simple_tui: bool = False,
83-
loop: Optional[asyncio.AbstractEventLoop] = None,
8484
restrict: bool = False,
8585
print_errors: bool = False,
8686
sponsor_block: bool = False,
87+
loop: Optional[asyncio.AbstractEventLoop] = None,
8788
):
8889
"""
8990
Initialize the Downloader class.
@@ -299,15 +300,15 @@ def search(self, song: Song) -> Tuple[str, AudioProvider]:
299300

300301
raise LookupError(f"No results found for song: {song.display_name}")
301302

302-
def search_lyrics(self, song: Song) -> str:
303+
def search_lyrics(self, song: Song) -> Optional[str]:
303304
"""
304305
Search for lyrics using all available providers.
305306
306307
### Arguments
307308
- song: The song to search for.
308309
309310
### Returns
310-
- lyrics if successful.
311+
- lyrics if successful else None.
311312
"""
312313

313314
for lyrics_provider in self.lyrics_providers:
@@ -323,7 +324,7 @@ def search_lyrics(self, song: Song) -> str:
323324
f"for {song.display_name}"
324325
)
325326

326-
raise LookupError(f"No lyrics found for song: {song.display_name}")
327+
return None
327328

328329
def search_and_download(self, song: Song) -> Tuple[Song, Optional[Path]]:
329330
"""
@@ -344,30 +345,19 @@ def search_and_download(self, song: Song) -> Tuple[Song, Optional[Path]]:
344345
# If it's None extract the current metadata
345346
# And reinitialize the song object
346347
if song.name is None and song.url:
347-
data = song.json
348-
new_data = Song.from_url(data["url"]).json
349-
data.update((k, v) for k, v in new_data.items() if v is not None)
350-
351-
if data.get("song_list"):
352-
# Reinitialize the correct song list object
353-
song_list: Type[SongList] = song.song_list.__class__(
354-
**data["song_list"]
355-
)
356-
data["song_list"] = song_list
357-
data["list_position"] = song_list.urls.index(song.url)
358-
359-
# Reinitialize the song object
360-
song = Song(**data)
348+
song = reinit_song(song)
361349

362350
# Find song lyrics and add them to the song object
363-
try:
364-
song.lyrics = self.search_lyrics(song)
365-
except LookupError:
351+
lyrics = self.search_lyrics(song)
352+
if song.lyrics is None:
366353
self.progress_handler.debug(
367354
f"No lyrics found for {song.display_name}, "
368355
"lyrics providers: "
369356
f"{', '.join([lprovider.name for lprovider in self.lyrics_providers])}"
370357
)
358+
else:
359+
song.lyrics = lyrics
360+
self.progress_handler.log(f"No lyrics found for song: {song.display_name}")
371361

372362
# Create the output file path
373363
output_file = create_file_name(song, self.output, self.output_format)

spotdl/utils/arguments.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ def parse_main_options(parser: _ArgumentGroup):
178178
parser.add_argument(
179179
"--dont-filter-results",
180180
dest="filter_results",
181+
action="store_const",
182+
const=False,
181183
help="Disable filtering results.",
182184
)
183185

@@ -193,6 +195,8 @@ def parse_spotify_options(parser: _ArgumentGroup):
193195
# Add login argument
194196
parser.add_argument(
195197
"--user-auth",
198+
action="store_const",
199+
const=True,
196200
help="Login to Spotify using OAuth.",
197201
)
198202

spotdl/utils/search.py

Lines changed: 32 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -68,59 +68,14 @@ def parse_query(
6868
- List of song objects
6969
"""
7070

71-
urls: List[str] = []
72-
songs: List[Song] = []
73-
for request in query:
74-
if (
75-
"youtube.com/watch?v=" in request
76-
or "youtu.be/" in request
77-
and "open.spotify.com" in request
78-
and "track" in request
79-
and "|" in request
80-
):
81-
split_urls = request.split("|")
82-
if (
83-
len(split_urls) <= 1
84-
or "youtube" not in split_urls[0]
85-
and "youtu.be" not in split_urls[0]
86-
or "spotify" not in split_urls[1]
87-
):
88-
raise QueryError(
89-
"Incorrect format used, please use YouTubeURL|SpotifyURL"
90-
)
91-
92-
songs.append(
93-
Song.from_dict(
94-
{
95-
**Song.from_url(split_urls[1]).json,
96-
"download_url": split_urls[0],
97-
}
98-
)
99-
)
100-
elif "open.spotify.com" in request and "track" in request:
101-
urls.append(request)
102-
elif "open.spotify.com" in request and "playlist" in request:
103-
urls.extend(Playlist.get_urls(request))
104-
elif "open.spotify.com" in request and "album" in request:
105-
urls.extend(Album.get_urls(request))
106-
elif "open.spotify.com" in request and "artist" in request:
107-
for album_url in Artist.get_albums(request):
108-
urls.extend(Album.get_urls(album_url))
109-
elif request == "saved":
110-
urls.extend(Saved.get_urls("saved"))
111-
elif request.endswith(".spotdl"):
112-
with open(request, "r", encoding="utf-8") as m3u_file:
113-
for track in json.load(m3u_file):
114-
# Append to songs
115-
songs.append(Song.from_dict(track))
116-
else:
117-
songs.append(Song.from_search_term(request))
71+
songs: List[Song] = get_simple_songs(query)
11872

73+
results = []
11974
with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor:
120-
for song in executor.map(Song.from_url, urls):
121-
songs.append(song)
75+
for song in executor.map(reinit_song, songs):
76+
results.append(song)
12277

123-
return songs
78+
return results
12479

12580

12681
def create_empty_song(
@@ -263,3 +218,30 @@ def get_simple_songs(
263218
) # type: ignore
264219

265220
return songs
221+
222+
223+
def reinit_song(song: Song) -> Song:
224+
"""
225+
Update song object with new data
226+
from Spotify
227+
228+
### Arguments
229+
- song: Song object
230+
231+
### Returns
232+
- Updated song object
233+
"""
234+
235+
data = song.json
236+
new_data = Song.from_url(data["url"]).json
237+
data.update((k, v) for k, v in new_data.items() if v is not None)
238+
239+
if data.get("song_list"):
240+
# Reinitialize the correct song list object
241+
if song.song_list:
242+
song_list = song.song_list.__class__(**data["song_list"])
243+
data["song_list"] = song_list
244+
data["list_position"] = song_list.urls.index(song.url)
245+
246+
# return reinitialized song object
247+
return Song(**data)

0 commit comments

Comments
 (0)