LaurenceRawlings / savify

Download Spotify songs to mp3 with full metadata and cover art!
MIT License
1.17k stars 80 forks source link

[BUG] Savify crashes when attempting to download a track whose title, author or album ends with an ellipsis. #42

Closed DevJake closed 3 years ago

DevJake commented 3 years ago

Describe the bug

Savify is unable to process Spotify tracks that end with an ellipsis (...) in either the track's name, album or artist, when grouping by track and album name. This seems to originate from the code to save the downloaded file. This would make sense, as Windows doesn't allow for folders to end with periods; "Folder names cannot end with a period in Windows, though the name can end with a period followed by a whitespace character such as a non-breaking space."

The following error is given:

Traceback (most recent call last):
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\savify\savify.py", line 250, in _download
    ffmpeg.run()
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\ffmpy.py", line 106, in run
    raise FFRuntimeError(self.cmd, self.process.returncode, out[0], out[1])
ffmpy.FFRuntimeError: `ffmpeg -i C:\Users\Admin\AppData\Roaming\Savify\temp/5w5vw9cokQ9s8dHQmQqLX4.mp3 -i C:\Users\Admin\AppData\Roaming\Savify\temp\29eea82c-708f-11eb-9af5-309c2344e680.jpg -loglevel quiet -hide_banner -y -map 0:0 -map 1:0 -c copy -id3v2_version 3 -metadata:s:v "title=Album cover" -metadata:s:v "comment=Cover (front)" "C:\Users\Admin\AppData\Roaming\Savify\downloads\Lyrics Born\Later That Day...\Lyrics Born - Bad Dreams.mp3"` exited with status 1

STDOUT:

STDERR:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\admin\appdata\local\programs\python\python38\lib\shutil.py", line 788, in move
    os.rename(src, real_dst)
FileNotFoundError: [WinError 3] The system cannot find the path specified: 'C:\\Users\\Admin\\AppData\\Roaming\\Savify\\temp/5w5vw9cokQ9s8dHQmQqLX4.mp3' -> 'C:\\Users\\Admin\\AppData\\Roaming\\Savify\\downloads\\Lyrics Born\\Later That Day...\\Lyrics Born - Bad Dreams.mp3'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\admin\appdata\local\programs\python\python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\admin\appdata\local\programs\python\python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Users\Admin\Downloads\YouTube DL\venv\Scripts\savify.exe\__main__.py", line 7, in <module>
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\click\core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\click\core.py", line 782, in main
    rv = self.invoke(ctx)
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\click\core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\click\core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\savify\cli.py", line 110, in main
    s.download(query, query_type=query_type)
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\savify\savify.py", line 109, in download
    jobs = pool.map(self._download, queue)
  File "c:\users\admin\appdata\local\programs\python\python38\lib\multiprocessing\pool.py", line 364, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "c:\users\admin\appdata\local\programs\python\python38\lib\multiprocessing\pool.py", line 771, in get
    raise self._value
  File "c:\users\admin\appdata\local\programs\python\python38\lib\multiprocessing\pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
  File "c:\users\admin\appdata\local\programs\python\python38\lib\multiprocessing\pool.py", line 48, in mapstar
    return list(map(*args))
  File "c:\users\admin\downloads\youtube dl\venv\lib\site-packages\savify\savify.py", line 255, in _download
    move(output_temp, output)
  File "c:\users\admin\appdata\local\programs\python\python38\lib\shutil.py", line 802, in move
    copy_function(src, real_dst)
  File "c:\users\admin\appdata\local\programs\python\python38\lib\shutil.py", line 432, in copy2
    copyfile(src, dst, follow_symlinks=follow_symlinks)
  File "c:\users\admin\appdata\local\programs\python\python38\lib\shutil.py", line 261, in copyfile
    with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Admin\\AppData\\Roaming\\Savify\\downloads\\Lyrics Born\\Later That Day...\\Lyrics Born - Bad Dreams.mp3'

To Reproduce

Enter the following command: savify [redacted; playlist share link] -g "%artist%/%album%"

Expected behaviour

Savify works as intended, downloading missing tracks, grouping them into folders according to the track's title and album. However, when a track's title or album ends with an ellipsis, Savify crashes.

Desktop (please complete the following information):

Additional context

As is shown, one such track that Savify cannot process is Bad Dreams by Lyrics Born, on their album Later That Day..., found here.

A second track that also fails is One Step Beyond... by Madness, on their album One Step Beyond. Whilst the Spotify track doesn't contain an ellipsis, it would appear that the YouTube equivalent does.

I imagine the solution is to either re-encode any suffix full-stops/periods with an alternative character or instead simply remove them. Folder names could also be appended with whitespace, although I feel this isn't a great long-term solution.

LaurenceRawlings commented 3 years ago

Thanks for your work on this :)