mirror of
https://github.com/nathom/streamrip.git
synced 2025-05-13 06:34:45 -04:00
Add output file feature
This commit is contained in:
parent
5034c3e82b
commit
725553e501
2 changed files with 60 additions and 9 deletions
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue