Skip to content

Commit

Permalink
search_release: allow general queries
Browse files Browse the repository at this point in the history
previously, an artist and album had to both be supplied, in order to be
able to construct a 'strict' /database/search api call. this commit
makes both params optional, in order to allow a more relaxed api call,
primarily to make searches from the repl less annoying.
  • Loading branch information
hejops committed May 31, 2024
1 parent 7b116df commit d51e350
Showing 1 changed file with 43 additions and 184 deletions.
227 changes: 43 additions & 184 deletions dita/discogs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,105 +515,37 @@ def search_with_relpath(relpath: str) -> dict:
def cli_search(
artist: str,
album: str,
# date: str,
# sep: str = " / ",
) -> list[str]:
"""Wrapper for search_discogs_release, that allows user to edit search
queries. A great interface is tough within the confines of readline.
"""
Wrapper for search_discogs_release, that allows user to edit search
queries.
Returns list of release ids.
"""

# artist, album, year = input_with_prefill(
# "Search: ",
# text=sep.join([artist, album, date]),
# ).split(sep)

# multiline, depends on how good the user is with readline
prefill = "\n".join([f"artist:{artist}", f"album:{album}"])
# f"date:{date}",
artist, album = [
l.partition(":")[2]
for l in input_with_prefill(
"Search:\n",
text=prefill,
).split("\n")
]
delim = " ::: "
prefill = delim.join([artist, album])
query = input_with_prefill("Search:\n", text=prefill)

results = search_release(
artist=artist,
album=album,
# year=year,
)
if delim in query:
artist, album = query.split(delim)
results = search_release(
artist=artist,
album=album,
primary=True,
)
else:
results = search_release(
album=prefill,
primary=True,
)

if not results:
if results.empty:
eprint("no results")
return []

return [r["id"] for r in results]


def release_as_str(rel: dict) -> str:
"""Display essential information of a Discogs release. tabulate is always
preferred because right-aligned strings from the default printer are
annoying to read."""
pd.set_option("display.max_columns", None)
pd.set_option("display.max_rows", None)

_str = [tabulate_dict(release.get_release_tracklist(rel))]

tags = release.get_discogs_tags(rel)
if not tags.empty:
_str = _str + [tags.artist.iloc[0], tags.album.iloc[0]]

return "\n".join(_str)


def display_release_results(
ids: list[str],
num_tracks: int,
) -> dict:
"""Only used in tag.fix; may be replaced with the simpler display_release().
Similar to try_auto(), might merge.
Args:
ids: [TODO:description]
num_tracks: [TODO:description]
Returns:
Discogs release, empty if nothing matches
"""
for i in ids:
rel = d_get(i)

if not {"artists", "tracklist", "uri"}.issubset(rel):
continue

print(rel["uri"].partition("-")[0])
print(rel["title"])
print(release_as_str(rel))

tracklist = release.get_release_tracklist(rel)

# lprint(rel)
print(" / ".join(a["name"] for a in rel["artists"]))
# print(rel["artists_sort"])
print(rel["title"])
print(rel["year"])
print(rel["uri"])
print(tracklist)
print()

if len(tracklist) != num_tracks:
continue

ans = input("Accept? [y/N]: ")

if ans == "y":
return rel

print("Not found")
return {}
return results.id.to_list()


def remove_words(
Expand All @@ -633,33 +565,26 @@ def remove_words(


def search_release(
artist: str,
album: str,
interactive: bool = True,
artist: str = "",
album: str = "",
# interactive: bool = True,
primary: bool = False,
) -> list[dict[str, Any]]:
"""Returns Discogs search results of an artist/album query. Limited to
first 10; I've never found a larger number to be necessary.
) -> pd.DataFrame:
"""Return Discogs search results of an `artist`/`album` query.
If either param is omitted, a general search is performed.
Only the first 10 are retrieved; I've never found a larger number to be
necessary.
If a match is not found in non-interactive mode, an empty dict is returned
immediately. In interactive mode, search queries are allowed to be edited
until a match is found (or until the search is aborted).
Not url encoding is apparently ok.
Args:
artist: [TODO:description]
album: [TODO:description]
interactive: [TODO:description]
primary: whether to return primary release, regardless of tracklist.
releases with no 'master_url' are "orphans" and will be ignored.
Returns:
list[dict]: Discogs search results; empty if no match found. Almost
always transformed into a DataFrame.
Note: search results are NOT the same as releases. Most importantly,
the former does not contain tracklist/artists, while the latter does.
Note: search results are NOT the same as releases. Most importantly, search
results do not contain tracklist/artists, while releases do.
"""

Expand Down Expand Up @@ -690,46 +615,8 @@ def sanitize(artist: str, album: str):

max_results = 10

if not (artist and album):
return []

artist, album = sanitize(artist, album)

# print(interactive)
# sys.exit()

# album = remove_words(album)
# print(album)
# raise ValueError

# if not " ".join(w for w in artist.split() if "!" not in w): # TVXQ!
# raise NotImplementedError

# d_get(get_artist_id(artist)["results"][0]["uri"] + "/releases")

# {
# "id": 4337911,
# "master_id": None,
# "master_url": None,
# "resource_url": "https://api.discogs.com/artists/4337911",
# "title": "TVXQ!",
# "type": "artist",
# "uri": "/artist/4337911-TVXQ!",
# "user_data": {"in_collection": True, "in_wantlist": False},
# }

# from urllib.parse import quote_plus
# artist = quote_plus(artist)

# from urllib.parse import quote
# artist = quote(artist)

# from urllib.parse import quote
# album = quote(album)

# from urllib.parse import quote_plus
# album = quote_plus(album)

# Notes:
#
# - Searches only return results that match artist's "main" name; aliases
Expand All @@ -745,49 +632,21 @@ def sanitize(artist: str, album: str):

# anv should not be used over artist

search_url = f"/database/search?release_title={album}&artist={artist}&type=release"

# if year:
# search_url += f"&year={year}"
# eprint(f"Searching discogs: {artist} - {album} - {year}")
# else:

# eprint(f"Searching discogs: {artist} - {album}")

# TODO: use translit name to find non-ascii name
data = d_get(
search_url,
# verbose=True,
)

# print(data)
# raise ValueError

if not interactive and not data.get("results"):
eprint(f"No results: {artist} - {album}")
return []

# dict.get is safer, because some searches are invalid and don't contain a
# 'results' field
# TODO: has a lot of parallels with cli_search
while not data.get("results"):
# if search fails, ask to change search terms, then re-run search
sep = " / "
query = input_with_prefill("Search query: ", f"{artist}{sep}{album}")

try:
artist, album = query.split(sep)
except ValueError:
return []

if artist and album:
search_url = (
f"/database/search?release_title={album}&artist={artist}&type=release"
)
data = d_get(search_url)
eprint(f"Searching discogs: {artist} - {album}")
else:
query = " ".join((artist, album))
query = re.sub(r"[^\w -']", " ", query)
search_url = f"/database/search?q={query}&type=release"

eprint(len(data["results"]), "results found\n")
data = d_get(search_url)

results: list[dict] = data["results"]
# if not interactive and not data.get("results"):
# eprint(f"No results: {artist} - {album}")
# return pd.DataFrame()

# # no real way to distinguish Draft releases without extra GET
# pprint(results)
Expand Down

0 comments on commit d51e350

Please sign in to comment.