summaryrefslogtreecommitdiff
path: root/tidal_dl_ng/helper
diff options
context:
space:
mode:
authorRobert Honz <exislow+github@gmail.com>2024-11-29 17:41:25 +0100
committerRobert Honz <exislow+github@gmail.com>2024-11-29 17:41:25 +0100
commit33a30537e9a205dd4b43e891b00c0b5f15a9b71b (patch)
tree9ccb8c4c273ce96fd6ebce8ea2077d281d812712 /tidal_dl_ng/helper
parentf2b3cc2505f4c64f09efacd775de3390ae204be0 (diff)
parent4deaf94fb53ad304db73f9384f817b29afcac4a8 (diff)
downloadtidal-dl-ng-33a30537e9a205dd4b43e891b00c0b5f15a9b71b.tar.gz
✨ Merge with master.
Diffstat (limited to 'tidal_dl_ng/helper')
-rw-r--r--tidal_dl_ng/helper/decryption.py7
-rw-r--r--tidal_dl_ng/helper/path.py36
-rw-r--r--tidal_dl_ng/helper/tidal.py8
-rw-r--r--tidal_dl_ng/helper/wrapper.py3
4 files changed, 40 insertions, 14 deletions
diff --git a/tidal_dl_ng/helper/decryption.py b/tidal_dl_ng/helper/decryption.py
index ebb946a..17ea19b 100644
--- a/tidal_dl_ng/helper/decryption.py
+++ b/tidal_dl_ng/helper/decryption.py
@@ -1,4 +1,5 @@
import base64
+import pathlib
from Crypto.Cipher import AES
from Crypto.Util import Counter
@@ -35,7 +36,7 @@ def decrypt_security_token(security_token: str) -> (str, str):
return key, nonce
-def decrypt_file(path_file_encrypted: str, path_file_destination: str, key: str, nonce: str) -> None:
+def decrypt_file(path_file_encrypted: pathlib.Path, path_file_destination: pathlib.Path, key: str, nonce: str) -> None:
"""
Decrypts an encrypted MQA file given the file, key and nonce.
TODO: Is it really only necessary for MQA of for all other formats, too?
@@ -46,9 +47,9 @@ def decrypt_file(path_file_encrypted: str, path_file_destination: str, key: str,
decryptor = AES.new(key, AES.MODE_CTR, counter=counter)
# Open and decrypt
- with open(path_file_encrypted, "rb") as f_src:
+ with path_file_encrypted.open("rb") as f_src:
audio_decrypted = decryptor.decrypt(f_src.read())
# Replace with decrypted file
- with open(path_file_destination, "wb") as f_dst:
+ with path_file_destination.open("wb") as f_dst:
f_dst.write(audio_decrypted)
diff --git a/tidal_dl_ng/helper/path.py b/tidal_dl_ng/helper/path.py
index cc8d5b6..fb7bb87 100644
--- a/tidal_dl_ng/helper/path.py
+++ b/tidal_dl_ng/helper/path.py
@@ -1,8 +1,10 @@
import math
import os
+import pathlib
+import posixpath
import re
import sys
-from pathlib import Path, PosixPath
+from urllib.parse import unquote, urlsplit
from pathvalidate import sanitize_filename, sanitize_filepath
from pathvalidate.error import ValidationError
@@ -77,8 +79,7 @@ def format_str_media(name: str, media: Track | Album | Playlist | UserPlaylist |
elif hasattr(media, "artist"):
result = media.artist.name
case "album_artist":
- if isinstance(media, Album):
- result = name_builder_album_artist(media)
+ result = name_builder_album_artist(media)
case "track_title":
if isinstance(media, Track | Video):
result = name_builder_title(media)
@@ -195,7 +196,7 @@ def get_format_template(
def path_file_sanitize(path_file: str, adapt: bool = False, uniquify: bool = False) -> (bool, str):
# Split into path and filename
pathname, filename = os.path.split(path_file)
- file_extension: str = Path(path_file).suffix
+ file_extension: str = pathlib.Path(path_file).suffix
# Sanitize path
try:
@@ -205,7 +206,7 @@ def path_file_sanitize(path_file: str, adapt: bool = False, uniquify: bool = Fal
except ValidationError:
# If adaption of path is allowed in case of an error set path to HOME.
if adapt:
- pathname_sanitized: str = Path.home()
+ pathname_sanitized: str = str(pathlib.Path.home())
else:
raise
@@ -272,10 +273,10 @@ def file_unique_suffix(path_file: str, seperator: str = "_") -> str:
return unique_suffix
-def check_file_exists(path_file: str, extension_ignore: bool = False) -> bool:
+def check_file_exists(path_file: pathlib.Path, extension_ignore: bool = False) -> bool:
if extension_ignore:
- path_file_stem: str = Path(path_file).stem
- path_parent: PosixPath = Path(path_file).parent
+ path_file_stem: str = pathlib.Path(path_file).stem
+ path_parent: pathlib.Path = pathlib.Path(path_file).parent
path_files: [str] = []
for extension in AudioExtensions:
@@ -295,3 +296,22 @@ def resource_path(relative_path):
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
+
+
+def url_to_filename(url: str) -> str:
+ """Return basename corresponding to url.
+ >>> print(url_to_filename('http://example.com/path/to/file%C3%80?opt=1'))
+ fileÀ
+ >>> print(url_to_filename('http://example.com/slash%2fname')) # '/' in name
+ Taken from https://gist.github.com/zed/c2168b9c52b032b5fb7d
+ Traceback (most recent call last):
+ ...
+ ValueError
+ """
+ urlpath: str = urlsplit(url).path
+ basename: str = posixpath.basename(unquote(urlpath))
+
+ if os.path.basename(basename) != basename or unquote(posixpath.basename(urlpath)) != basename:
+ raise ValueError # reject '%2f' or 'dir%5Cbasename.ext' on Windows
+
+ return basename
diff --git a/tidal_dl_ng/helper/tidal.py b/tidal_dl_ng/helper/tidal.py
index d679d5e..e568cc6 100644
--- a/tidal_dl_ng/helper/tidal.py
+++ b/tidal_dl_ng/helper/tidal.py
@@ -25,8 +25,10 @@ def name_builder_album_artist(media: Track | Album) -> str:
return ", ".join(artists_tmp)
-def name_builder_title(media: Track | Video) -> str:
- result: str = media.full_name if hasattr(media, "full_name") else media.name
+def name_builder_title(media: Track | Video | Mix | Playlist | Album | Video) -> str:
+ result: str = (
+ media.title if isinstance(media, Mix) else media.full_name if hasattr(media, "full_name") else media.name
+ )
return result
@@ -186,7 +188,7 @@ def instantiate_media(
def quality_audio_highest(media: Track | Album) -> Quality:
quality: Quality
- if MediaMetadataTags.hires_lossless in media.media_metadata_tags:
+ if MediaMetadataTags.hi_res_lossless in media.media_metadata_tags:
quality = Quality.hi_res_lossless
elif MediaMetadataTags.lossless in media.media_metadata_tags:
quality = Quality.high_lossless
diff --git a/tidal_dl_ng/helper/wrapper.py b/tidal_dl_ng/helper/wrapper.py
index d8ffb09..cd8e6ba 100644
--- a/tidal_dl_ng/helper/wrapper.py
+++ b/tidal_dl_ng/helper/wrapper.py
@@ -21,3 +21,6 @@ class LoggerWrapped:
def critical(self, value):
self.fn_print(value)
+
+ def exception(self, value):
+ self.fn_print(value)