♻️ Refactored search command

This commit is contained in:
Oskar Dudziński
2026-04-28 16:49:36 +02:00
parent 859d50772d
commit 410146bdcf
+53 -19
View File
@@ -12,16 +12,14 @@ from rich.table import Table
search_subcommand = typer.Typer()
@search_subcommand.command(
no_args_is_help=True,
)
def search(
ctx: Context,
query: Annotated[str, typer.Argument()],
resource_types: Annotated[
QUERY: Annotated[str, typer.Argument()],
RESOURCE_TYPES: Annotated[
list[str],
typer.Option(
"-t",
@@ -29,29 +27,55 @@ def search(
metavar="<resource>",
help="Narrow resource types, usage: -t track -t album etc. Available resources: track, video, album, playlist, artist.",
),
] = ["track", "video", "album", "playlist", "artist"], top_per_type: Annotated[int, typer.Option("--num-top", "-n", help="Number of top results to display per resource type.")] = 3,
pick_top_hit: Annotated[bool, typer.Option("--top", "-T", help="Automatically pick the top hit if it exists and matches the specified resource types.")] = False,
] = ["track", "video", "album", "playlist", "artist"],
NUMBER_TOP_RESULTS: Annotated[
int,
typer.Option(
"--num-top",
"-n",
help="Number of top results to display per resource type.",
),
] = 3,
PICK_TOP_HIT: Annotated[
bool,
typer.Option(
"--top",
"-T",
help="Automatically pick the top hit if it exists and matches the specified resource types.",
),
] = False,
):
"""
Search Tidal for tracks, videos, albums, playlists, artists, and mixes.
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)
table = _prepare_table(query)
results: Search = ctx.obj.api.get_search(query=QUERY)
table = _prepare_table(QUERY)
results_to_display = []
if results.topHit is not None:
top_hit = results.topHit
top_hit_type = top_hit.type.rstrip("S").lower() # "ARTISTS" -> "artist"
if top_hit_type in resource_types:
if pick_top_hit:
ctx.obj.resources.append(TidalResource.from_string(f"{top_hit_type}/{_display_id(top_hit.value)}"))
ctx.obj.console.print(f"[green]Automatically added top hit: {top_hit.type.title()} '{_display_name(top_hit.value)}'")
if top_hit_type in RESOURCE_TYPES:
if PICK_TOP_HIT:
ctx.obj.resources.append(
TidalResource.from_string(
f"{top_hit_type}/{_display_id(top_hit.value)}"
)
)
ctx.obj.console.print(
f"[green]Automatically added top hit: {top_hit.type.title()} '{_display_name(top_hit.value)}'"
)
return
else:
results_to_display.append(
(top_hit_type.title(), _display_name(top_hit.value), _display_id(top_hit.value))
(
top_hit_type.title(),
_display_name(top_hit.value),
_display_id(top_hit.value),
)
)
type_to_items = {
@@ -63,27 +87,35 @@ def search(
}
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(
(resource_type.title(), _display_name(item), _display_id(item))
for item in items[:top_per_type]
for item in items[:NUMBER_TOP_RESULTS]
)
for i, (resource_type, name, id) in enumerate(results_to_display, start=1):
table.add_row(str(i), resource_type, name, id)
panel = Panel(table, title="Search Results", highlight=True, expand=True)
ctx.obj.console.print(panel)
selection = ctx.obj.console.input("[bold green]Enter the number of the resource to add to your list (comma-separated for multiple, q/empty = quit): ")
selection = ctx.obj.console.input(
"[bold green]Enter the number of the resource to add to your list (comma-separated for multiple, q/empty = quit): "
)
selected_numbers = [s.strip() for s in selection.split(",")]
for num in selected_numbers:
if num.lower() == "q":
return
if not num.isdigit() or int(num) < 1 or int(num) > len(results_to_display):
ctx.obj.console.print(f"[red]Invalid selection: {num}")
continue
selected_resource = results_to_display[int(num)-1]
selected_resource = results_to_display[int(num) - 1]
resource_type, name, id = selected_resource
ctx.obj.resources.append(TidalResource.from_string(f"{resource_type.lower()}/{id}"))
ctx.obj.resources.append(
TidalResource.from_string(f"{resource_type.lower()}/{id}")
)
ctx.obj.console.print(f"[green]Added {resource_type} '{name}' to your list")
@@ -98,9 +130,11 @@ def _display_name(item) -> str:
else: # Playlist
return item.title
def _display_id(item) -> str:
return item.uuid if isinstance(item, Playlist) else str(item.id)
def _prepare_table(query: str) -> Table:
table = Table(title=f"{query}", expand=True)
table.add_column("#", style="yellow", ratio=1)