Add output file feature

This commit is contained in:
Nathan Thomas 2023-12-22 11:43:37 -08:00
parent 5034c3e82b
commit 725553e501
2 changed files with 60 additions and 9 deletions

View file

@ -266,22 +266,42 @@ def database_browse(ctx, table):
help="Automatically download the first search result without showing the menu.", help="Automatically download the first search result without showing the menu.",
is_flag=True, is_flag=True,
) )
@click.option(
"-o",
"--output-file",
help="Write search results to a file instead of showing interactive menu.",
type=click.Path(writable=True),
)
@click.option(
"-n",
"--num-results",
help="Maximum number of search results to show",
default=100,
type=click.IntRange(min=1),
)
@click.argument("source", required=True) @click.argument("source", required=True)
@click.argument("media-type", required=True) @click.argument("media-type", required=True)
@click.argument("query", required=True) @click.argument("query", required=True)
@click.pass_context @click.pass_context
@coro @coro
async def search(ctx, first, source, media_type, query): async def search(ctx, first, output_file, num_results, source, media_type, query):
"""Search for content using a specific source. """Search for content using a specific source.
Example: Example:
-------
rip search qobuz album 'rumours' rip search qobuz album 'rumours'
""" """
if first and output_file:
console.print("Cannot choose --first and --output-file!")
return
with ctx.obj["config"] as cfg: with ctx.obj["config"] as cfg:
async with Main(cfg) as main: async with Main(cfg) as main:
if first: if first:
await main.search_take_first(source, media_type, query) await main.search_take_first(source, media_type, query)
elif output_file:
await main.search_output_file(
source, media_type, query, output_file, num_results
)
else: else:
await main.search_interactive(source, media_type, query) await main.search_interactive(source, media_type, query)
await main.resolve() await main.resolve()

View file

@ -1,6 +1,8 @@
import asyncio import asyncio
import logging import logging
import os import platform
import aiofiles
from .. import db from .. import db
from ..client import Client, DeezerClient, QobuzClient, SoundcloudClient, TidalClient from ..client import Client, DeezerClient, QobuzClient, SoundcloudClient, TidalClient
@ -105,7 +107,6 @@ class Main:
with console.status(f"[cyan]Logging into {source}", spinner="dots"): with console.status(f"[cyan]Logging into {source}", spinner="dots"):
# Log into client using credentials from config # Log into client using credentials from config
await client.login() await client.login()
# await client.login()
assert client.logged_in assert client.logged_in
return client return client
@ -135,7 +136,7 @@ class Main:
return return
search_results = SearchResults.from_pages(source, media_type, pages) search_results = SearchResults.from_pages(source, media_type, pages)
if os.name == "nt": if platform.system() == "Windows": # simple term menu not supported for windows
from pick import pick from pick import pick
choices = pick( choices = pick(
@ -150,7 +151,7 @@ class Main:
assert isinstance(choices, list) assert isinstance(choices, list)
await self.add_all( await self.add_all(
[f"http://{source}.com/{media_type}/{item.id}" for item, i in choices], [self.dummy_url(source, media_type, item.id) for item, _ in choices],
) )
else: else:
@ -175,14 +176,16 @@ class Main:
choices = search_results.get_choices(chosen_ind) choices = search_results.get_choices(chosen_ind)
await self.add_all( await self.add_all(
[ [
f"http://{source}.com/{item.media_type()}/{item.id}" self.dummy_url(source, item.media_type(), item.id)
for item in choices for item in choices
], ],
) )
async def search_take_first(self, source: str, media_type: str, query: str): async def search_take_first(self, source: str, media_type: str, query: str):
client = await self.get_logged_in_client(source) client = await self.get_logged_in_client(source)
with console.status(f"[bold]Searching {source}", spinner="dots"):
pages = await client.search(media_type, query, limit=1) pages = await client.search(media_type, query, limit=1)
if len(pages) == 0: if len(pages) == 0:
console.print(f"[red]No search results found for query {query}") console.print(f"[red]No search results found for query {query}")
return return
@ -190,7 +193,31 @@ class Main:
search_results = SearchResults.from_pages(source, media_type, pages) search_results = SearchResults.from_pages(source, media_type, pages)
assert len(search_results.results) > 0 assert len(search_results.results) > 0
first = search_results.results[0] first = search_results.results[0]
await self.add(f"http://{source}.com/{first.media_type()}/{first.id}") url = self.dummy_url(source, first.media_type(), first.id)
await self.add(url)
async def search_output_file(
self, source: str, media_type: str, query: str, filepath: str, limit: int
):
client = await self.get_logged_in_client(source)
with console.status(f"[bold]Searching {source}", spinner="dots"):
pages = await client.search(media_type, query, limit=limit)
if len(pages) == 0:
console.print(f"[red]No search results found for query {query}")
return
search_results = SearchResults.from_pages(source, media_type, pages)
file_contents = "\n".join(
f"{self.dummy_url(source, item.media_type(), item.id)} [{item.summarize()}]"
for item in search_results.results
)
async with aiofiles.open(filepath, "w") as f:
await f.write(file_contents)
console.print(
f"Wrote dummy urls for [purple]{len(search_results.results)}[/purple] results to [cyan]{filepath}!"
)
async def resolve_lastfm(self, playlist_url: str): async def resolve_lastfm(self, playlist_url: str):
"""Resolve a last.fm playlist.""" """Resolve a last.fm playlist."""
@ -214,6 +241,10 @@ class Main:
if playlist is not None: if playlist is not None:
self.media.append(playlist) self.media.append(playlist)
@staticmethod
def dummy_url(source, media_type, item_id):
return f"http://{source}.com/{media_type}/{item_id}"
async def __aenter__(self): async def __aenter__(self):
return self return self