mirror of
https://github.com/oskvr37/tiddl.git
synced 2026-06-13 04:05:08 +03:00
♻️ Refactored search command
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user