Updated auth credentials (#344)

* fix search command error

* update auth credentials

* log debug path at `add_flac_metadata`

* extract flac from high and max quality

* add --force option to auth logout
This commit is contained in:
Oskar Dudziński
2026-04-28 22:46:08 +02:00
committed by GitHub
parent 33b1e6c826
commit d830a8ed73
5 changed files with 41 additions and 24 deletions
+26 -7
View File
@@ -79,16 +79,35 @@ def login(
@auth_command.command(help="Logout and remove token from app.") @auth_command.command(help="Logout and remove token from app.")
def logout(): def logout(
loaded_auth_data = load_auth_data() force: Annotated[
bool,
typer.Option(
"--force",
"-f",
help="Clears local auth data even if the server request fails.",
),
] = False,
):
auth_data = load_auth_data()
if loaded_auth_data.token: # If there's no token, we are effectively already logged out locally
auth_api = AuthAPI() if not auth_data.token:
auth_api.logout_token(loaded_auth_data.token) console.print("[yellow]No active session found.")
return
save_auth_data(AuthData()) try:
AuthAPI().logout_token(auth_data.token)
success = True
except Exception as error:
console.print(f"[bold red]Logout request failed: {error}")
success = False
console.print("[bold green]Logged out!") if success or force:
save_auth_data(AuthData())
console.print("[bold green]Logged out successfully!")
else:
console.print("[bold yellow]Local session retained. Use --force to override.")
@auth_command.command(help="Refreshes your token in app.") @auth_command.command(help="Refreshes your token in app.")
+1 -5
View File
@@ -151,17 +151,13 @@ class Downloader:
) )
return None, False return None, False
urls, actual_ext = parse_track_stream(stream) urls, _ = parse_track_stream(stream)
if filename.suffix.lower() != actual_ext:
filename = filename.with_suffix(actual_ext)
download_path = self.get_path(self.download_path, filename) download_path = self.get_path(self.download_path, filename)
quality = track_qualities_color[stream.audioQuality] quality = track_qualities_color[stream.audioQuality]
if stream.audioQuality in ["HI_RES_LOSSLESS", "LOSSLESS"]: if stream.audioQuality in ["HI_RES_LOSSLESS", "LOSSLESS"]:
quality = f"{quality} {stream.bitDepth}-bit, {(stream.sampleRate or 0) / 1000:.1f} kHz" quality = f"{quality} {stream.bitDepth}-bit, {(stream.sampleRate or 0) / 1000:.1f} kHz"
if stream.audioQuality == "HI_RES_LOSSLESS":
should_extract_flac = True should_extract_flac = True
elif isinstance(item, Video): elif isinstance(item, Video):
+11 -11
View File
@@ -18,8 +18,8 @@ search_subcommand = typer.Typer()
) )
def search( def search(
ctx: Context, ctx: Context,
QUERY: Annotated[str, typer.Argument()], query: Annotated[str, typer.Argument()],
RESOURCE_TYPES: Annotated[ resource_types: Annotated[
list[str], list[str],
typer.Option( typer.Option(
"-t", "-t",
@@ -28,7 +28,7 @@ def search(
help="Narrow resource types, usage: -t track -t album etc. Available resources: track, video, album, playlist, artist.", help="Narrow resource types, usage: -t track -t album etc. Available resources: track, video, album, playlist, artist.",
), ),
] = ["track", "video", "album", "playlist", "artist"], ] = ["track", "video", "album", "playlist", "artist"],
NUMBER_TOP_RESULTS: Annotated[ number_top_results: Annotated[
int, int,
typer.Option( typer.Option(
"--num-top", "--num-top",
@@ -36,7 +36,7 @@ def search(
help="Number of top results to display per resource type.", help="Number of top results to display per resource type.",
), ),
] = 3, ] = 3,
PICK_TOP_HIT: Annotated[ pick_top_hit: Annotated[
bool, bool,
typer.Option( typer.Option(
"--top", "--top",
@@ -51,15 +51,15 @@ def search(
By default, it searches for all resource types. You can specify which resource types to search for using the `--type` option. By default, it searches for all resource types. You can specify which resource types to search for using the `--type` option.
""" """
results: Search = ctx.obj.api.get_search(query=QUERY) results: Search = ctx.obj.api.get_search(query=query)
table = _prepare_table(QUERY) table = _prepare_table(query)
results_to_display = [] results_to_display = []
if results.topHit is not None: if results.topHit is not None:
top_hit = results.topHit top_hit = results.topHit
top_hit_type = top_hit.type.rstrip("S").lower() # "ARTISTS" -> "artist" top_hit_type = top_hit.type.rstrip("S").lower() # "ARTISTS" -> "artist"
if top_hit_type in RESOURCE_TYPES: if top_hit_type in resource_types:
if PICK_TOP_HIT: if pick_top_hit:
ctx.obj.resources.append( ctx.obj.resources.append(
TidalResource.from_string( TidalResource.from_string(
f"{top_hit_type}/{_display_id(top_hit.value)}" f"{top_hit_type}/{_display_id(top_hit.value)}"
@@ -87,10 +87,10 @@ def search(
} }
for resource_type, items in type_to_items.items(): for resource_type, items in type_to_items.items():
if resource_type in RESOURCE_TYPES: if resource_type in resource_types:
results_to_display.extend( results_to_display.extend(
(resource_type.title(), _display_name(item), _display_id(item)) (resource_type.title(), _display_name(item), _display_id(item))
for item in items[:NUMBER_TOP_RESULTS] for item in items[:number_top_results]
) )
for i, (resource_type, name, id) in enumerate(results_to_display, start=1): for i, (resource_type, name, id) in enumerate(results_to_display, start=1):
@@ -106,7 +106,7 @@ def search(
for num in selected_numbers: for num in selected_numbers:
if num.lower() == "q": if num.lower() == "q":
return return
if not num.isdigit() or int(num) < 1 or int(num) > len(results_to_display): if not num.isdigit() or int(num) < 1 or int(num) > len(results_to_display):
ctx.obj.console.print(f"[red]Invalid selection: {num}") ctx.obj.console.print(f"[red]Invalid selection: {num}")
continue continue
+1 -1
View File
@@ -11,7 +11,7 @@ def get_auth_credentials() -> tuple[str, str]:
client_id, client_secret = ( client_id, client_secret = (
base64.b64decode( base64.b64decode(
"ZlgySnhkbW50WldLMGl4VDsxTm45QWZEQWp4cmdKRkpiS05XTGVBeUtHVkdtSU51WFBQTEhWWEF2eEFnPQ==" "NE4zbjZRMXg5NUxMNUs3cDtvS09YZkpXMzcxY1g2eGFaMFB5aGdHTkJkTkxsQlpkNEFLS1lvdWdNamlrPQ=="
) )
.decode() .decode()
.split(";") .split(";")
+2
View File
@@ -36,6 +36,8 @@ class Metadata:
def add_flac_metadata(track_path: Path, metadata: Metadata) -> None: def add_flac_metadata(track_path: Path, metadata: Metadata) -> None:
log.debug(f"{track_path=}")
mutagen = MutagenFLAC(track_path) mutagen = MutagenFLAC(track_path)
if metadata.cover_data: if metadata.cover_data: