diff --git a/streamrip/cli.py b/streamrip/cli.py index 8d1b07b..9f83ce0 100644 --- a/streamrip/cli.py +++ b/streamrip/cli.py @@ -58,7 +58,7 @@ def cli(ctx, **kwargs): config.session["conversion"]["enabled"] = True config.session["conversion"]["codec"] = kwargs["convert"] if kwargs["quality"] is not None: - quality = int(kwargs['quality']) + quality = int(kwargs["quality"]) if quality not in range(5): click.secho("Invalid quality", fg="red") return diff --git a/streamrip/core.py b/streamrip/core.py index 13e6349..de3a6cb 100644 --- a/streamrip/core.py +++ b/streamrip/core.py @@ -1,10 +1,10 @@ import logging -from pprint import pprint import os import re import sys from getpass import getpass from hashlib import md5 +from pprint import pprint from string import Formatter from typing import Generator, Optional, Tuple, Union @@ -12,7 +12,13 @@ import click from .clients import DeezerClient, QobuzClient, SoundCloudClient, TidalClient from .config import Config -from .constants import (CONFIG_PATH, DB_PATH, SOUNDCLOUD_URL_REGEX, URL_REGEX, MEDIA_TYPES) +from .constants import ( + CONFIG_PATH, + DB_PATH, + MEDIA_TYPES, + SOUNDCLOUD_URL_REGEX, + URL_REGEX, +) from .db import MusicDB from .downloader import Album, Artist, Label, Playlist, Track from .exceptions import AuthenticationError, ParsingError @@ -129,8 +135,8 @@ class MusicDL(list): client = self.get_client(source) if media_type not in MEDIA_TYPES: - if 'playlist' in media_type: # for SoundCloud - media_type = 'playlist' + if "playlist" in media_type: # for SoundCloud + media_type = "playlist" assert media_type in MEDIA_TYPES, media_type item = MEDIA_CLASS[media_type](client=client, id=item_id) @@ -265,7 +271,9 @@ class MusicDL(list): if i > limit: return else: - for item in results.get("data") or results.get("items"): + for item in ( + results.get("data") or results.get("items") or results.get("collection") + ): yield MEDIA_CLASS[media_type].from_api(item, client) i += 1 if i > limit: @@ -283,6 +291,13 @@ class MusicDL(list): fmt = "{name}" elif isinstance(media, Track): fmt = "{artist} - {title}\nReleased on {year}" + elif isinstance(media, Playlist): + fmt = ( + "{title}\n" + "{tracktotal} tracks\n" + "{popularity}\n" + "Description: {description}" + ) else: raise NotImplementedError @@ -301,7 +316,7 @@ class MusicDL(list): def from_title(s): num = [] for char in s: - if char.isdigit(): + if char != '.': num.append(char) else: break diff --git a/streamrip/downloader.py b/streamrip/downloader.py index 89d1834..1223940 100644 --- a/streamrip/downloader.py +++ b/streamrip/downloader.py @@ -1,5 +1,4 @@ import logging -from pprint import pprint import os import re import shutil @@ -133,7 +132,9 @@ class Track: elif self.client.source == "deezer": self.cover_url = self.resp["album"]["cover_medium"] elif self.client.source == "soundcloud": - self.cover_url = (self.resp["artwork_url"] or self.resp['user'].get("avatar_url")).replace("large", "t500x500") + self.cover_url = ( + self.resp["artwork_url"] or self.resp["user"].get("avatar_url") + ).replace("large", "t500x500") else: raise InvalidSourceError(self.client.source) except KeyError: @@ -241,7 +242,7 @@ class Track: [ "ffmpeg", "-i", - dl_info['url'], + dl_info["url"], "-c", "copy", "-y", @@ -718,6 +719,9 @@ class Album(Tracklist): @classmethod def from_api(cls, resp, client): + if client.source == "soundcloud": + return Playlist.from_api(resp, client) + info = cls._parse_get_resp(resp, client) return cls(client, **info) @@ -731,7 +735,7 @@ class Album(Tracklist): """ if client.source == "qobuz": if resp.get("maximum_sampling_rate", False): - sampling_rate = resp['maximum_sampling_rate'] * 1000 + sampling_rate = resp["maximum_sampling_rate"] * 1000 else: sampling_rate = None @@ -1063,6 +1067,7 @@ class Playlist(Tracklist): else: raise NotImplementedError + self.tracktotal = len(tracklist) if self.client.source == "soundcloud": # No meta is included in soundcloud playlist # response, so it is loaded at download time @@ -1147,6 +1152,14 @@ class Playlist(Tracklist): "name": item["title"], "id": item["id"], } + elif client.source == "soundcloud": + return { + "name": item["title"], + "id": item["permalink_url"], + "description": item["description"], + "popularity": f"{item['likes_count']} likes", + "tracktotal": len(item["tracks"]), + } raise InvalidSourceError(client.source)