nathom / streamrip

A scriptable music downloader for Qobuz, Tidal, SoundCloud, and Deezer
GNU General Public License v3.0
2.4k stars 211 forks source link

[BUG] "NameError: name 'sanitize_filepath' is not defined" when ripping from Deezer #585

Closed wund0r closed 6 months ago

wund0r commented 6 months ago

Describe the bug

Command Used

rip url https://www.deezer.com/en/album/123456 (123456 is arbitrary, any album produces the error)

Debug Traceback

[20:42:18] DEBUG    Showing all debug logs                                                                                                                                                                                                                                    cli.py:102
[20:42:20] DEBUG    Removing dirs set()                                                                                                                                                                                                                                    artwork.py:19
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/myhome/tmp/streamrip/venv-test/bin/rip:8 in <module>                                        │
│                                                                                                  │
│   5 from streamrip.rip import rip                                                                │
│   6 if __name__ == '__main__':                                                                   │
│   7 │   sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])                         │
│ ❱ 8 │   sys.exit(rip())                                                                          │
│   9                                                                                              │
│                                                                                                  │
│ ╭─────────────────────────── locals ────────────────────────────╮                                │
│ │  re = <module 're' from '/usr/lib/python3.11/re/__init__.py'> │                                │
│ │ rip = <HelpColorsGroup rip>                                   │                                │
│ │ sys = <module 'sys' (built-in)>                               │                                │
│ ╰───────────────────────────────────────────────────────────────╯                                │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/click/core.py:1157 in __call__  │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/click/core.py:1078 in main      │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/click/core.py:1688 in invoke    │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/click/core.py:1434 in invoke    │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/click/core.py:783 in invoke     │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/click/decorators.py:33 in       │
│ new_func                                                                                         │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/rip/cli.py:28 in      │
│ wrapper                                                                                          │
│                                                                                                  │
│    25 def coro(f):                                                                               │
│    26 │   @wraps(f)                                                                              │
│    27 │   def wrapper(*args, **kwargs):                                                          │
│ ❱  28 │   │   return asyncio.run(f(*args, **kwargs))                                             │
│    29 │                                                                                          │
│    30 │   return wrapper                                                                         │
│    31                                                                                            │
│                                                                                                  │
│ ╭──────────────────────────── locals ────────────────────────────╮                               │
│ │   args = (<click.core.Context object at 0x7ee8062b96d0>,)      │                               │
│ │      f = <function url at 0x7ee803d353a0>                      │                               │
│ │ kwargs = {'urls': ('https://www.deezer.com/en/album/123456',)} │                               │
│ ╰────────────────────────────────────────────────────────────────╯                               │
│                                                                                                  │
│ /usr/lib/python3.11/asyncio/runners.py:190 in run                                                │
│                                                                                                  │
│   187 │   │   │   "asyncio.run() cannot be called from a running event loop")                    │
│   188 │                                                                                          │
│   189 │   with Runner(debug=debug) as runner:                                                    │
│ ❱ 190 │   │   return runner.run(main)                                                            │
│   191                                                                                            │
│   192                                                                                            │
│   193 def _cancel_all_tasks(loop):                                                               │
│                                                                                                  │
│ ╭────────────────────────── locals ──────────────────────────╮                                   │
│ │  debug = None                                              │                                   │
│ │   main = <coroutine object url at 0x7ee803c62200>          │                                   │
│ │ runner = <asyncio.runners.Runner object at 0x7ee803d3a150> │                                   │
│ ╰────────────────────────────────────────────────────────────╯                                   │
│                                                                                                  │
│ /usr/lib/python3.11/asyncio/runners.py:118 in run                                                │
│                                                                                                  │
│   115 │   │                                                                                      │
│   116 │   │   self._interrupt_count = 0                                                          │
│   117 │   │   try:                                                                               │
│ ❱ 118 │   │   │   return self._loop.run_until_complete(task)                                     │
│   119 │   │   except exceptions.CancelledError:                                                  │
│   120 │   │   │   if self._interrupt_count > 0:                                                  │
│   121 │   │   │   │   uncancel = getattr(task, "uncancel", None)                                 │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │        context = <_contextvars.Context object at 0x7ee803942980>                             │ │
│ │           coro = <coroutine object url at 0x7ee803c62200>                                    │ │
│ │           self = <asyncio.runners.Runner object at 0x7ee803d3a150>                           │ │
│ │ sigint_handler = functools.partial(<bound method Runner._on_sigint of                        │ │
│ │                  <asyncio.runners.Runner object at 0x7ee803d3a150>>, main_task=<Task         │ │
│ │                  finished name='Task-1' coro=<url() done, defined at                         │ │
│ │                  /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip… │ │
│ │                  exception=NameError("name 'sanitize_filepath' is not defined")>)            │ │
│ │           task = <Task finished name='Task-1' coro=<url() done, defined at                   │ │
│ │                  /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip… │ │
│ │                  exception=NameError("name 'sanitize_filepath' is not defined")>             │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /usr/lib/python3.11/asyncio/base_events.py:653 in run_until_complete                             │
│                                                                                                  │
│    650 │   │   if not future.done():                                                             │
│    651 │   │   │   raise RuntimeError('Event loop stopped before Future completed.')             │
│    652 │   │                                                                                     │
│ ❱  653 │   │   return future.result()                                                            │
│    654 │                                                                                         │
│    655 │   def stop(self):                                                                       │
│    656 │   │   """Stop running the event loop.                                                   │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   future = <Task finished name='Task-1' coro=<url() done, defined at                         │ │
│ │            /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/rip/c… │ │
│ │            exception=NameError("name 'sanitize_filepath' is not defined")>                   │ │
│ │ new_task = False                                                                             │ │
│ │     self = <_UnixSelectorEventLoop running=False closed=True debug=False>                    │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/rip/cli.py:167 in url │
│                                                                                                  │
│   164 │   │                                                                                      │
│   165 │   │   async with Main(cfg) as main:                                                      │
│   166 │   │   │   await main.add_all(urls)                                                       │
│ ❱ 167 │   │   │   await main.resolve()                                                           │
│   168 │   │   │   await main.rip()                                                               │
│   169 │   │                                                                                      │
│   170 │   │   if version_coro is not None:                                                       │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │          cfg = <streamrip.config.Config object at 0x7ee803d3a7d0>                            │ │
│ │          ctx = <click.core.Context object at 0x7ee8062b96d0>                                 │ │
│ │         main = <streamrip.rip.main.Main object at 0x7ee803942010>                            │ │
│ │      updates = True                                                                          │ │
│ │         urls = ('https://www.deezer.com/en/album/123456',)                                   │ │
│ │ version_coro = <Task finished name='Task-2' coro=<latest_streamrip_version() done, defined   │ │
│ │                at                                                                            │ │
│ │                /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/r… │ │
│ │                result=('2.0.4', None)>                                                       │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/rip/main.py:157 in    │
│ resolve                                                                                          │
│                                                                                                  │
│   154 │   │   with console.status("Resolving URLs...", spinner="dots"):                          │
│   155 │   │   │   coros = [p.resolve() for p in self.pending]                                    │
│   156 │   │   │   new_media: list[Media] = [                                                     │
│ ❱ 157 │   │   │   │   m for m in await asyncio.gather(*coros) if m is not None                   │
│   158 │   │   │   ]                                                                              │
│   159 │   │                                                                                      │
│   160 │   │   self.media.extend(new_media)                                                       │
│                                                                                                  │
│ ╭────────────────────────────── locals ───────────────────────────────╮                          │
│ │ coros = [<coroutine object PendingAlbum.resolve at 0x7ee803e0e3e0>] │                          │
│ │  self = <streamrip.rip.main.Main object at 0x7ee803942010>          │                          │
│ ╰─────────────────────────────────────────────────────────────────────╯                          │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/media/album.py:63 in  │
│ resolve                                                                                          │
│                                                                                                  │
│   60 │   │                                                                                       │
│   61 │   │   tracklist = get_album_track_ids(self.client.source, resp)                           │
│   62 │   │   folder = self.config.session.downloads.folder                                       │
│ ❱ 63 │   │   album_folder = self._album_folder(folder, meta)                                     │
│   64 │   │   os.makedirs(album_folder, exist_ok=True)                                            │
│   65 │   │   embed_cover, _ = await download_artwork(                                            │
│   66 │   │   │   self.client.session,                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │    folder = '/home/myhome/tmp/streamrip/StreamripDownloads'                                   │ │
│ │      meta = AlbumMetadata(                                                                   │ │
│ │             │   info=AlbumInfo(                                                              │ │
│ │             │   │   id='123456',                                                             │ │
│ │             │   │   quality=2,                                                               │ │
│ │             │   │   container='FLAC',                                                        │ │
│ │             │   │   label='Universal-Island Records Ltd.',                                   │ │
│ │             │   │   explicit=False,                                                          │ │
│ │             │   │   sampling_rate=44100,                                                     │ │
│ │             │   │   bit_depth=16,                                                            │ │
│ │             │   │   booklets=None                                                            │ │
│ │             │   ),                                                                           │ │
│ │             │   album='Love It When You Call (Tom Neville Vocal Remix) (e-Release)',         │ │
│ │             │   albumartist='The Feeling',                                                   │ │
│ │             │   year='2006',                                                                 │ │
│ │             │   genre=['Pop'],                                                               │ │
│ │             │   covers=Covers(('original',                                                   │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)                                                                            │ │
│ │             ('large',                                                                        │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)                                                                            │ │
│ │             ('small',                                                                        │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)                                                                            │ │
│ │             ('thumbnail',                                                                    │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)),                                                                          │ │
│ │             │   tracktotal=1,                                                                │ │
│ │             │   disctotal=1,                                                                 │ │
│ │             │   albumcomposer=None,                                                          │ │
│ │             │   comment=None,                                                                │ │
│ │             │   compilation=None,                                                            │ │
│ │             │   copyright=None,                                                              │ │
│ │             │   date='2006-11-20',                                                           │ │
│ │             │   description=None,                                                            │ │
│ │             │   encoder=None,                                                                │ │
│ │             │   grouping=None,                                                               │ │
│ │             │   lyrics=None,                                                                 │ │
│ │             │   purchase_date=None                                                           │ │
│ │             )                                                                                │ │
│ │      resp = {                                                                                │ │
│ │             │   'id': 123456,                                                                │ │
│ │             │   'title': 'Love It When You Call (Tom Neville Vocal Remix) (e-Release)',      │ │
│ │             │   'upc': '602517171398',                                                       │ │
│ │             │   'link': 'https://www.deezer.com/album/123456',                               │ │
│ │             │   'share':                                                                     │ │
│ │             'https://www.deezer.com/album/123456?utm_source=deezer&utm_content=album-123456… │ │
│ │             │   'cover': 'https://api.deezer.com/album/123456/image',                        │ │
│ │             │   'cover_small':                                                               │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             │   'cover_medium':                                                              │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             │   'cover_big':                                                                 │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             │   'cover_xl':                                                                  │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             │   ... +19                                                                      │ │
│ │             }                                                                                │ │
│ │      self = PendingAlbum(                                                                    │ │
│ │             │   id='123456',                                                                 │ │
│ │             │   client=<streamrip.client.deezer.DeezerClient object at 0x7ee803941c10>,      │ │
│ │             │   config=<streamrip.config.Config object at 0x7ee803d3a7d0>,                   │ │
│ │             │   db=Database(                                                                 │ │
│ │             │   │   downloads=<streamrip.db.Downloads object at 0x7ee8038df650>,             │ │
│ │             │   │   failed=<streamrip.db.Failed object at 0x7ee8038df550>                    │ │
│ │             │   )                                                                            │ │
│ │             )                                                                                │ │
│ │ tracklist = [1152526]                                                                        │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/media/album.py:92 in  │
│ _album_folder                                                                                    │
│                                                                                                  │
│   89 │   │   if config.downloads.source_subdirectories:                                          │
│   90 │   │   │   parent = os.path.join(parent, self.client.source.capitalize())                  │
│   91 │   │   formatter = config.filepaths.folder_format                                          │
│ ❱ 92 │   │   folder = clean_filepath(                                                            │
│   93 │   │   │   meta.format_folder_path(formatter), config.filepaths.restrict_characters        │
│   94 │   │   )                                                                                   │
│   95                                                                                             │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │    config = ConfigData(                                                                      │ │
│ │             │   toml={'downloads': {'folder':                                                │ │
│ │             '/home/myhome/tmp/streamrip/StreamripDownloads', 'source_subdirectories': False,  │ │
│ │             'concurrency': True, 'max_connections': 6, 'requests_per_minute': 60}, 'qobuz':  │ │
│ │             {'quality': 3, 'download_booklets': True, 'use_auth_token': False,               │ │
│ │             'email_or_userid': '', 'password_or_token': '', 'app_id': '', 'secrets': []},    │ │
│ │             'tidal': {'quality': 3, 'download_videos': True, 'user_id': '', 'country_code':  │ │
│ │             '', 'access_token': '', 'refresh_token': '', 'token_expiry': ''}, 'deezer':      │ │
│ │             {'quality': 2, 'arl':                                                            │ │
│ │             'myarl… │ │
│ │             'use_deezloader': True, 'deezloader_warnings': True}, 'soundcloud': {'quality':  │ │
│ │             0, 'client_id': 'C1pU2xkeCVWOwE2HL6qDLUarH2e61RWw', 'app_version':               │ │
│ │             '1705676406'}, 'youtube': {'quality': 0, 'download_videos': False,               │ │
│ │             'video_downloads_folder': '/home/myhome/StreamripDownloads/YouTubeVideos'},       │ │
│ │             'database': {'downloads_enabled': True, 'downloads_path':                        │ │
│ │             '/home/myhome/.config/streamrip/downloads.db', 'failed_downloads_enabled': True,  │ │
│ │             'failed_downloads_path': '/home/myhome/.config/streamrip/failed_downloads.db'},   │ │
│ │             'conversion': {'enabled': False, 'codec': 'ALAC', 'sampling_rate': 48000,        │ │
│ │             'bit_depth': 24, 'lossy_bitrate': 320}, 'qobuz_filters': {'extras': False,       │ │
│ │             'repeats': False, 'non_albums': False, 'features': False, 'non_studio_albums':   │ │
│ │             False, 'non_remaster': False}, 'artwork': {'embed': True, 'embed_size': 'large', │ │
│ │             'embed_max_width': -1, 'save_artwork': True, 'saved_max_width': -1}, 'metadata': │ │
│ │             {'set_playlist_to_album': True, 'renumber_playlist_tracks': True, 'exclude':     │ │
│ │             []}, 'filepaths': {'add_singles_to_folder': False, 'folder_format':              │ │
│ │             '{albumartist} - {title} ({year}) [{container}]                                  │ │
│ │             [{bit_depth}B-{sampling_rate}kHz]', 'track_format': '{tracknumber}. {artist} -   │ │
│ │             {title}{explicit}', 'restrict_characters': False, 'truncate_to': 120}, 'lastfm': │ │
│ │             {'source': 'qobuz', 'fallback_source': ''}, 'cli': {'text_output': True,         │ │
│ │             'progress_bars': True, 'max_search_results': 100}, 'misc': {'version': '2.0.3',  │ │
│ │             'check_for_updates': True}},                                                     │ │
│ │             │   downloads=DownloadsConfig(                                                   │ │
│ │             │   │   folder='/home/myhome/tmp/streamrip/StreamripDownloads',                   │ │
│ │             │   │   source_subdirectories=False,                                             │ │
│ │             │   │   concurrency=True,                                                        │ │
│ │             │   │   max_connections=6,                                                       │ │
│ │             │   │   requests_per_minute=60                                                   │ │
│ │             │   ),                                                                           │ │
│ │             │   qobuz=QobuzConfig(                                                           │ │
│ │             │   │   use_auth_token=False,                                                    │ │
│ │             │   │   email_or_userid='',                                                      │ │
│ │             │   │   password_or_token='',                                                    │ │
│ │             │   │   app_id='',                                                               │ │
│ │             │   │   quality=3,                                                               │ │
│ │             │   │   download_booklets=True,                                                  │ │
│ │             │   │   secrets=[]                                                               │ │
│ │             │   ),                                                                           │ │
│ │             │   tidal=TidalConfig(                                                           │ │
│ │             │   │   user_id='',                                                              │ │
│ │             │   │   country_code='',                                                         │ │
│ │             │   │   access_token='',                                                         │ │
│ │             │   │   refresh_token='',                                                        │ │
│ │             │   │   token_expiry='',                                                         │ │
│ │             │   │   quality=3,                                                               │ │
│ │             │   │   download_videos=True                                                     │ │
│ │             │   ),                                                                           │ │
│ │             │   deezer=DeezerConfig(                                                         │ │
│ │             │   │                                                                            │ │
│ │             arl='myarl… │ │
│ │             │   │   quality=2,                                                               │ │
│ │             │   │   use_deezloader=True,                                                     │ │
│ │             │   │   deezloader_warnings=True                                                 │ │
│ │             │   ),                                                                           │ │
│ │             │   soundcloud=SoundcloudConfig(                                                 │ │
│ │             │   │   client_id='clientid',                            │ │
│ │             │   │   app_version='1705676406',                                                │ │
│ │             │   │   quality=0                                                                │ │
│ │             │   ),                                                                           │ │
│ │             │   youtube=YoutubeConfig(                                                       │ │
│ │             │   │   video_downloads_folder='/home/myhome/StreamripDownloads/YouTubeVideos',   │ │
│ │             │   │   quality=0,                                                               │ │
│ │             │   │   download_videos=False                                                    │ │
│ │             │   ),                                                                           │ │
│ │             │   lastfm=LastFmConfig(source='qobuz', fallback_source=''),                     │ │
│ │             │   filepaths=FilepathsConfig(                                                   │ │
│ │             │   │   add_singles_to_folder=False,                                             │ │
│ │             │   │   folder_format='{albumartist} - {title} ({year}) [{container}]            │ │
│ │             [{bit_depth}B-{sampling_rate}kHz]',                                              │ │
│ │             │   │   track_format='{tracknumber}. {artist} - {title}{explicit}',              │ │
│ │             │   │   restrict_characters=False,                                               │ │
│ │             │   │   truncate_to=120                                                          │ │
│ │             │   ),                                                                           │ │
│ │             │   artwork=ArtworkConfig(                                                       │ │
│ │             │   │   embed=True,                                                              │ │
│ │             │   │   embed_size='large',                                                      │ │
│ │             │   │   embed_max_width=-1,                                                      │ │
│ │             │   │   save_artwork=True,                                                       │ │
│ │             │   │   saved_max_width=-1                                                       │ │
│ │             │   ),                                                                           │ │
│ │             │   metadata=MetadataConfig(                                                     │ │
│ │             │   │   set_playlist_to_album=True,                                              │ │
│ │             │   │   renumber_playlist_tracks=True,                                           │ │
│ │             │   │   exclude=[]                                                               │ │
│ │             │   ),                                                                           │ │
│ │             │   qobuz_filters=QobuzDiscographyFilterConfig(                                  │ │
│ │             │   │   extras=False,                                                            │ │
│ │             │   │   repeats=False,                                                           │ │
│ │             │   │   non_albums=False,                                                        │ │
│ │             │   │   features=False,                                                          │ │
│ │             │   │   non_studio_albums=False,                                                 │ │
│ │             │   │   non_remaster=False                                                       │ │
│ │             │   ),                                                                           │ │
│ │             │   cli=CliConfig(                                                               │ │
│ │             │   │   text_output=True,                                                        │ │
│ │             │   │   progress_bars=True,                                                      │ │
│ │             │   │   max_search_results=100                                                   │ │
│ │             │   ),                                                                           │ │
│ │             │   database=DatabaseConfig(                                                     │ │
│ │             │   │   downloads_enabled=True,                                                  │ │
│ │             │   │   downloads_path='/home/myhome/.config/streamrip/downloads.db',             │ │
│ │             │   │   failed_downloads_enabled=True,                                           │ │
│ │             │   │                                                                            │ │
│ │             failed_downloads_path='/home/myhome/.config/streamrip/failed_downloads.db'        │ │
│ │             │   ),                                                                           │ │
│ │             │   conversion=ConversionConfig(                                                 │ │
│ │             │   │   enabled=False,                                                           │ │
│ │             │   │   codec='ALAC',                                                            │ │
│ │             │   │   sampling_rate=48000,                                                     │ │
│ │             │   │   bit_depth=24,                                                            │ │
│ │             │   │   lossy_bitrate=320                                                        │ │
│ │             │   ),                                                                           │ │
│ │             │   misc=MiscConfig(version='2.0.3', check_for_updates=True),                    │ │
│ │             │   _modified=False                                                              │ │
│ │             )                                                                                │ │
│ │ formatter = '{albumartist} - {title} ({year}) [{container}]                                  │ │
│ │             [{bit_depth}B-{sampling_rate}kHz]'                                               │ │
│ │      meta = AlbumMetadata(                                                                   │ │
│ │             │   info=AlbumInfo(                                                              │ │
│ │             │   │   id='123456',                                                             │ │
│ │             │   │   quality=2,                                                               │ │
│ │             │   │   container='FLAC',                                                        │ │
│ │             │   │   label='Universal-Island Records Ltd.',                                   │ │
│ │             │   │   explicit=False,                                                          │ │
│ │             │   │   sampling_rate=44100,                                                     │ │
│ │             │   │   bit_depth=16,                                                            │ │
│ │             │   │   booklets=None                                                            │ │
│ │             │   ),                                                                           │ │
│ │             │   album='Love It When You Call (Tom Neville Vocal Remix) (e-Release)',         │ │
│ │             │   albumartist='The Feeling',                                                   │ │
│ │             │   year='2006',                                                                 │ │
│ │             │   genre=['Pop'],                                                               │ │
│ │             │   covers=Covers(('original',                                                   │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)                                                                            │ │
│ │             ('large',                                                                        │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)                                                                            │ │
│ │             ('small',                                                                        │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)                                                                            │ │
│ │             ('thumbnail',                                                                    │ │
│ │             'https://e-cdns-images.dzcdn.net/images/cover/51c612bb8d4c32790c35bea33f12c657/… │ │
│ │             None)),                                                                          │ │
│ │             │   tracktotal=1,                                                                │ │
│ │             │   disctotal=1,                                                                 │ │
│ │             │   albumcomposer=None,                                                          │ │
│ │             │   comment=None,                                                                │ │
│ │             │   compilation=None,                                                            │ │
│ │             │   copyright=None,                                                              │ │
│ │             │   date='2006-11-20',                                                           │ │
│ │             │   description=None,                                                            │ │
│ │             │   encoder=None,                                                                │ │
│ │             │   grouping=None,                                                               │ │
│ │             │   lyrics=None,                                                                 │ │
│ │             │   purchase_date=None                                                           │ │
│ │             )                                                                                │ │
│ │    parent = '/home/myhome/tmp/streamrip/StreamripDownloads'                                   │ │
│ │      self = PendingAlbum(                                                                    │ │
│ │             │   id='123456',                                                                 │ │
│ │             │   client=<streamrip.client.deezer.DeezerClient object at 0x7ee803941c10>,      │ │
│ │             │   config=<streamrip.config.Config object at 0x7ee803d3a7d0>,                   │ │
│ │             │   db=Database(                                                                 │ │
│ │             │   │   downloads=<streamrip.db.Downloads object at 0x7ee8038df650>,             │ │
│ │             │   │   failed=<streamrip.db.Failed object at 0x7ee8038df550>                    │ │
│ │             │   )                                                                            │ │
│ │             )                                                                                │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/myhome/tmp/streamrip/venv-test/lib/python3.11/site-packages/streamrip/filepath_utils.py:16  │
│ in clean_filepath                                                                                │
│                                                                                                  │
│   13 │   return path                                                                             │
│   14                                                                                             │
│   15 def clean_filepath(fn: str, restrict: bool = False) -> str:                                 │
│ ❱ 16 │   path = str(sanitize_filepath(fn))                                                       │
│   17 │   if restrict:                                                                            │
│   18 │   │   path = "".join(c for c in path if c in ALLOWED_CHARS)                               │
│   19                                                                                             │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │       fn = 'The Feeling - Love It When You Call (Tom Neville Vocal Remix) (e-Release)        │ │
│ │            (2006)'+22                                                                        │ │
│ │ restrict = False                                                                             │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
NameError: name 'sanitize_filepath' is not defined

Config File

[downloads]
# Folder where tracks are downloaded to
folder = "/home/myhome/tmp/streamrip/StreamripDownloads"
# Put Qobuz albums in a 'Qobuz' folder, Tidal albums in 'Tidal' etc.
source_subdirectories = false

# Download (and convert) tracks all at once, instead of sequentially. 
# If you are converting the tracks, or have fast internet, this will 
# substantially improve processing speed.
concurrency = true
# The maximum number of tracks to download at once
# If you have very fast internet, you will benefit from a higher value,
# A value that is too high for your bandwidth may cause slowdowns
# Set to -1 for no limit
max_connections = 6
# Max number of API requests per source to handle per minute
# Set to -1 for no limit
requests_per_minute = 60

[qobuz]
# 1: 320kbps MP3, 2: 16/44.1, 3: 24/<=96, 4: 24/>=96
quality = 3
# This will download booklet pdfs that are included with some albums
download_booklets = true

# Authenticate to Qobuz using auth token? Value can be true/false only
use_auth_token = false
# Enter your userid if the above use_auth_token is set to true, else enter your email
email_or_userid = ""
# Enter your auth token if the above use_auth_token is set to true, else enter the md5 hash of your plaintext password
password_or_token = ""
# Do not change
app_id = ""
# Do not change
secrets = []

[tidal]
# 0: 256kbps AAC, 1: 320kbps AAC, 2: 16/44.1 "HiFi" FLAC, 3: 24/44.1 "MQA" FLAC
quality = 3
# This will download videos included in Video Albums.
download_videos = true

# Do not change any of the fields below
user_id = ""
country_code = ""
access_token = ""
refresh_token = ""
# Tokens last 1 week after refresh. This is the Unix timestamp of the expiration
# time. If you haven't used streamrip in more than a week, you may have to log
# in again using `rip config --tidal`
token_expiry = ""

[deezer]
# 0, 1, or 2
# This only applies to paid Deezer subscriptions. Those using deezloader
# are automatically limited to quality = 1
quality = 2
# An authentication cookie that allows streamrip to use your Deezer account
# See https://github.com/nathom/streamrip/wiki/Finding-Your-Deezer-ARL-Cookie
# for instructions on how to find this
arl = "myarl"
# This allows for free 320kbps MP3 downloads from Deezer
# If an arl is provided, deezloader is never used
use_deezloader = true
# This warns you when the paid deezer account is not logged in and rip falls
# back to deezloader, which is unreliable
deezloader_warnings = true

[soundcloud]
# Only 0 is available for now
quality = 0
# This changes periodically, so it needs to be updated
client_id = "clientid"
app_version = "1705676406"

[youtube]
# Only 0 is available for now
quality = 0
# Download the video along with the audio
download_videos = false
# The path to download the videos to
video_downloads_folder = "/home/myhome/StreamripDownloads/YouTubeVideos"

[database]
# Create a database that contains all the track IDs downloaded so far
# Any time a track logged in the database is requested, it is skipped
# This can be disabled temporarily with the --no-db flag
downloads_enabled = true
# Path to the downloads database 
downloads_path = "/home/myhome/.config/streamrip/downloads.db"
# If a download fails, the item ID is stored here. Then, `rip repair` can be
# called to retry the downloads
failed_downloads_enabled = true
failed_downloads_path = "/home/myhome/.config/streamrip/failed_downloads.db"

# Convert tracks to a codec after downloading them.
[conversion]
enabled = false
# FLAC, ALAC, OPUS, MP3, VORBIS, or AAC
codec = "ALAC"
# In Hz. Tracks are downsampled if their sampling rate is greater than this. 
# Value of 48000 is recommended to maximize quality and minimize space
sampling_rate = 48000
# Only 16 and 24 are available. It is only applied when the bit depth is higher
# than this value.
bit_depth = 24
# Only applicable for lossy codecs
lossy_bitrate = 320

# Filter a Qobuz artist's discography. Set to 'true' to turn on a filter.
# This will also be applied to other sources, but is not guaranteed to work correctly
[qobuz_filters]
# Remove Collectors Editions, live recordings, etc.
extras = false
# Picks the highest quality out of albums with identical titles.
repeats = false
# Remove EPs and Singles
non_albums = false
# Remove albums whose artist is not the one requested
features = false
# Skip non studio albums
non_studio_albums = false
# Only download remastered albums
non_remaster = false

[artwork]
# Write the image to the audio file
embed = true
# The size of the artwork to embed. Options: thumbnail, small, large, original.
# "original" images can be up to 30MB, and may fail embedding. 
# Using "large" is recommended.
embed_size = "large"
# If this is set to a value > 0, max(width, height) of the embedded art will be set to this value in pixels
# Proportions of the image will remain the same
embed_max_width = -1
# Save the cover image at the highest quality as a seperate jpg file
save_artwork = true
# If this is set to a value > 0, max(width, height) of the saved art will be set to this value in pixels
# Proportions of the image will remain the same
saved_max_width = -1

[metadata]
# Sets the value of the 'ALBUM' field in the metadata to the playlist's name. 
# This is useful if your music library software organizes tracks based on album name.
set_playlist_to_album = true
# If part of a playlist, sets the `tracknumber` field in the metadata to the track's 
# position in the playlist instead of its position in its album
renumber_playlist_tracks = true
# The following metadata tags won't be applied
# See https://github.com/nathom/streamrip/wiki/Metadata-Tag-Names for more info
exclude = []

# Changes the folder and file names generated by streamrip.
[filepaths]
# Create folders for single tracks within the downloads directory using the folder_format
# template
add_singles_to_folder = false
# Available keys: "albumartist", "title", "year", "bit_depth", "sampling_rate",
# "id", and "albumcomposer"
folder_format = "{albumartist} - {title} ({year}) [{container}] [{bit_depth}B-{sampling_rate}kHz]"
# Available keys: "tracknumber", "artist", "albumartist", "composer", "title",
# and "albumcomposer", "explicit"
track_format = "{tracknumber}. {artist} - {title}{explicit}"
# Only allow printable ASCII characters in filenames.
restrict_characters = false
# Truncate the filename if it is greater than this number of characters
# Setting this to false may cause downloads to fail on some systems
truncate_to = 120

# Last.fm playlists are downloaded by searching for the titles of the tracks
[lastfm]
# The source on which to search for the tracks.
source = "qobuz"
# If no results were found with the primary source, the item is searched for 
# on this one.
fallback_source = ""

[cli]
# Print "Downloading {Album name}" etc. to screen
text_output = true
# Show resolve, download progress bars
progress_bars = true
# The maximum number of search results to show in the interactive menu
max_search_results = 100

[misc]
# Metadata to identify this config file. Do not change.
version = "2.0.3"
# Print a message if a new version of streamrip is available 
check_for_updates = true

Operating System

Arch Linux, Python 3.11.6, streamrip is in venv

streamrip version

2.0.4

Screenshots and recordings

No response

Additional context

Thanks for streamrip btw :heart:

jieweix commented 6 months ago

Same for Qobuz. Apparently in line 3 of filepath_utils.py one needs to add ,sanitize_filepath after from pathvalidate import sanitize_filename.

naiches commented 6 months ago

+1

kermitzo commented 6 months ago

+1

GGromadzki commented 6 months ago

Confirmed. line 3 should look like "from pathvalidate import sanitize_filename, sanitize_filepath # type: ignore" in file C:\Users\ [your user name here] \AppData\Local\Programs\Python\Python310\Lib\site-packages\streamrip\filepath_utils.py Please update it in next release.