feat yandex desktop downloads

This commit is contained in:
2026-06-10 12:58:04 +02:00
parent fa39582849
commit 0ae8c7e008
15 changed files with 1543 additions and 8 deletions

View File

@@ -65,7 +65,7 @@ func addURLToQueue(ctx context.Context, mainApp *app.Main, raw string) bool {
fmt.Printf("not yet supported: %s (kind=%s)\n", raw, parsed.Kind)
return false
}
if parsed.Source != "qobuz" && parsed.Source != "tidal" && parsed.Source != "deezer" && parsed.Source != "soundcloud" {
if parsed.Source != "qobuz" && parsed.Source != "tidal" && parsed.Source != "deezer" && parsed.Source != "yandex" && parsed.Source != "soundcloud" {
fmt.Printf("provider not yet implemented: source=%s url=%s\n", parsed.Source, raw)
return false
}

View File

@@ -317,6 +317,8 @@ func main() {
cfg.Session.Qobuz.Quality = opts.quality
case "tidal":
cfg.Session.Tidal.Quality = opts.quality
case "yandex":
cfg.Session.Yandex.Quality = opts.quality
}
}
@@ -346,7 +348,7 @@ func main() {
var sopts searchOptions
if len(os.Args) < 5 {
if !term.IsTerminal(int(os.Stdin.Fd())) {
fmt.Println("usage: rip search <qobuz|tidal|deezer|soundcloud> <track|album|playlist|artist|label|video> <query...> [--limit N] [--force|--ignore-db] [--no-download]")
fmt.Println("usage: rip search <qobuz|tidal|deezer|yandex|soundcloud> <track|album|playlist|artist|label|video> <query...> [--limit N] [--force|--ignore-db] [--no-download]")
os.Exit(2)
}
source, mediaType, sopts, err = promptSearchInteractive(cfg.Session.CLI.MaxSearchResults)
@@ -380,6 +382,10 @@ func main() {
fmt.Fprintln(os.Stderr, "soundcloud search currently supports media types track and playlist")
os.Exit(2)
}
if source == "yandex" && mediaType != "track" && mediaType != "album" && mediaType != "playlist" && mediaType != "artist" {
fmt.Fprintln(os.Stderr, "yandex search currently supports media types track, album, playlist, and artist")
os.Exit(2)
}
if sopts.query == "" {
fmt.Fprintln(os.Stderr, "search query cannot be empty")
os.Exit(2)

View File

@@ -293,7 +293,7 @@ func writeSearchResultsToFile(source, mediaType string, results []searchResult,
}
func isAllowedSearchSource(source string) bool {
return source == "qobuz" || source == "tidal" || source == "deezer" || source == "soundcloud"
return source == "qobuz" || source == "tidal" || source == "deezer" || source == "yandex" || source == "soundcloud"
}
func isAllowedMediaType(mediaType string) bool {
@@ -318,7 +318,7 @@ func promptSearchInteractive(defaultLimit int) (string, string, searchOptions, e
}
for {
source, err := read("Source [qobuz/tidal/deezer/soundcloud]: ")
source, err := read("Source [qobuz/tidal/deezer/yandex/soundcloud]: ")
if err != nil {
return "", "", searchOptions{}, err
}
@@ -341,6 +341,10 @@ func promptSearchInteractive(defaultLimit int) (string, string, searchOptions, e
fmt.Println("SoundCloud search supports track and playlist only.")
continue
}
if source == "yandex" && mediaType != "track" && mediaType != "album" && mediaType != "playlist" && mediaType != "artist" {
fmt.Println("Yandex search supports track, album, playlist, and artist only.")
continue
}
query, err := read("Query: ")
if err != nil {
@@ -544,6 +548,48 @@ func normalizeSearchResults(source, mediaType string, pages []map[string]any) []
)
appendUnique(searchResult{ID: id, Title: title, Artist: artist, Date: date, TrackCount: trackCount})
}
case "yandex":
items, ok := page["items"].([]any)
if !ok {
continue
}
for _, raw := range items {
itm, ok := raw.(map[string]any)
if !ok {
continue
}
id := asString(itm["id"])
title := asString(itm["title"])
if title == "" {
title = asString(itm["name"])
}
artist := nestedSearchString(itm, "artist", "name")
if artist == "" {
artist = nestedSearchString(itm, "performer", "name")
}
album := nestedSearchString(itm, "album", "title")
trackCount := firstPositiveInt(
searchInt(itm["trackCount"]),
searchInt(itm["track_count"]),
searchInt(itm["tracks_count"]),
)
explicit := searchBool(itm["explicit"])
date := firstNonEmpty(
asString(itm["release_date"]),
asString(itm["releaseDate"]),
nestedSearchString(itm, "album", "release_date"),
nestedSearchString(itm, "album", "releaseDate"),
)
releases := 0
if mediaType == "artist" {
releases = firstPositiveInt(
searchInt(itm["albums_count"]),
searchInt(itm["numberOfAlbums"]),
nestedSearchInt(itm, "albums", "total"),
)
}
appendUnique(searchResult{ID: id, Title: title, Artist: artist, Album: album, Date: date, Releases: releases, TrackCount: trackCount, Explicit: explicit})
}
}
}
return results