mirror of
https://github.com/oskvr37/tiddl.git
synced 2026-06-13 04:05:08 +03:00
✨ 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:
@@ -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.")
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(";")
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user