1
0
Fork 0
mirror of https://github.com/fiso64/slsk-batchdl.git synced 2024-12-22 22:42:41 +00:00
This commit is contained in:
fiso64 2024-08-27 18:48:50 +02:00
parent 6e7b8d5d67
commit f8c5ed23da
6 changed files with 50 additions and 40 deletions

View file

@ -199,8 +199,8 @@ Usage: sldl <input> [OPTIONS]
Aggregate Download Aggregate Download
-g, --aggregate Aggregate download mode: Find and download all distinct -g, --aggregate Aggregate download mode: Find and download all distinct
songs associated with the provided artist, album, or title. songs associated with the provided artist, album, or title.
--min-users-aggregate <num> Minimum number of users sharing a track or album for it to --min-shares-aggregate <num> Minimum number of shares of a track or album for it to be
be downloaded in aggregate mode. (Default: 2) downloaded in aggregate mode. (Default: 2)
--relax-filtering Slightly relax file filtering in aggregate mode to include --relax-filtering Slightly relax file filtering in aggregate mode to include
more results more results
``` ```
@ -288,26 +288,25 @@ Input String | Artist | Title | Album | Lengt
string or csv row has no track title, or when -a/--album is enabled. string or csv row has no track title, or when -a/--album is enabled.
### Aggregate ### Aggregate
With -g/--aggregate, sldl will first perform an ordinary search for the input, then With -g/--aggregate, sldl will first perform an ordinary search for the input, then attempt to
attempt to group the results into distinct songs and download one of each kind. A common use group the results into distinct songs and download one of each kind. A common use case is
case is finding all remixes of a song or printing all songs by an artist that are not your finding all remixes of a song or printing all songs by an artist that are not your music dir.
music dir. Two files are considered equal if their inferred track title and artist name are equal
Two files are considered equal if their inferred track title and artist name are equal (ignoring case and some special characters), and their lengths are within --length-tol of each
(ignoring case and some special characters), and their lengths are within --length-tol of each other.
other. Note that this mode is not 100% reliable, which is why --min-shares-aggregate is set to 2 by
Note that this mode is not 100% reliable, which is why --min-users-aggregate is set to 2 by default, default, i.e. any song that is shared only once will be ignored. Enable --relax-filtering to
i.e. any song that is shared by only one peer will be ignored. Enable --relax-filtering to make the file filtering less aggressive.
make the file filtering less aggressive.
### Album Aggregate ### Album Aggregate
Activated when --album and --aggregate are enabled, in this mode sldl searches for the query Activated when --album and --aggregate are enabled, in this mode sldl searches for the query
and groups results into distinct albums. Two folders are considered same if they have the and groups results into distinct albums. Two folders are considered same if they have the
same number of audio files, and the durations of the files are within --length-tol of each same number of audio files, and the durations of the files are within --length-tol of each
other (or within 3 seconds if length-tol is not configured). If both folders have exactly one other (or within 3 seconds if length-tol is not configured). If both folders have exactly one
audio file with similar lengths, also checks if the inferred title and artist name coincide. audio file with similar lengths, also checks if the inferred title and artist name coincide.
More reliable than normal aggregate due to much simpler grouping logic. More reliable than normal aggregate due to much simpler grouping logic.
Note that --min-users-aggregate is 2 by default, which means that folders shared by only one Note that --min-shares-aggregate is 2 by default, which means that folders shared only once
peer are ignored. will be ignored.
## Searching ## Searching

View file

@ -80,7 +80,7 @@ static class Config
public static int minAlbumTrackCount = -1; public static int minAlbumTrackCount = -1;
public static int maxAlbumTrackCount = -1; public static int maxAlbumTrackCount = -1;
public static int fastSearchDelay = 300; public static int fastSearchDelay = 300;
public static int minUsersAggregate = 2; public static int minSharesAggregate = 2;
public static int maxTracks = int.MaxValue; public static int maxTracks = int.MaxValue;
public static int offset = 0; public static int offset = 0;
public static int maxStaleTime = 50000; public static int maxStaleTime = 50000;
@ -625,9 +625,9 @@ static class Config
case "--aggregate": case "--aggregate":
setFlag(ref aggregate, ref i); setFlag(ref aggregate, ref i);
break; break;
case "--mua": case "--msa":
case "--min-users-aggregate": case "--min-shares-aggregate":
minUsersAggregate = int.Parse(args[++i]); minSharesAggregate = int.Parse(args[++i]);
break; break;
case "--rf": case "--rf":
case "--relax": case "--relax":

View file

@ -25,6 +25,7 @@ namespace Data
public bool OutputsDirectory => Type != TrackType.Normal; public bool OutputsDirectory => Type != TrackType.Normal;
public Soulseek.File? FirstDownload => Downloads?.FirstOrDefault().Value.Item2; public Soulseek.File? FirstDownload => Downloads?.FirstOrDefault().Value.Item2;
public string? FirstUsername => Downloads?.FirstOrDefault().Value.Item1.Username;
public Track() { } public Track() { }

View file

@ -172,8 +172,8 @@ public static class Help
Aggregate Download Aggregate Download
-g, --aggregate Aggregate download mode: Find and download all distinct -g, --aggregate Aggregate download mode: Find and download all distinct
songs associated with the provided artist, album, or title. songs associated with the provided artist, album, or title.
--min-users-aggregate <num> Minimum number of users sharing a track or album for it to --min-shares-aggregate <num> Minimum number of shares of a track or album for it to be
be downloaded in aggregate mode. (Default: 2) downloaded in aggregate mode. (Default: 2)
--relax-filtering Slightly relax file filtering in aggregate mode to include --relax-filtering Slightly relax file filtering in aggregate mode to include
more results more results
@ -265,9 +265,9 @@ public static class Help
Two files are considered equal if their inferred track title and artist name are equal Two files are considered equal if their inferred track title and artist name are equal
(ignoring case and some special characters), and their lengths are within --length-tol of each (ignoring case and some special characters), and their lengths are within --length-tol of each
other. other.
Note that this mode is not 100% reliable, which is why --min-users-aggregate is set to 2 by Note that this mode is not 100% reliable, which is why --min-shares-aggregate is set to 2 by
default, i.e. any song that is shared by only one peer will be ignored. Enable --relax-filtering default, i.e. any song that is shared only once will be ignored. Enable --relax-filtering to
to make the file filtering less aggressive. make the file filtering less aggressive.
Album Aggregate Album Aggregate
Activated when --album and --aggregate are enabled, in this mode sldl searches for the query Activated when --album and --aggregate are enabled, in this mode sldl searches for the query
@ -276,8 +276,8 @@ public static class Help
other (or within 3 seconds if length-tol is not configured). If both folders have exactly one other (or within 3 seconds if length-tol is not configured). If both folders have exactly one
audio file with similar lengths, also checks if the inferred title and artist name coincide. audio file with similar lengths, also checks if the inferred title and artist name coincide.
More reliable than normal aggregate due to much simpler grouping logic. More reliable than normal aggregate due to much simpler grouping logic.
Note that --min-users-aggregate is 2 by default, which means that folders shared by only one Note that --min-shares-aggregate is 2 by default, which means that folders shared only once
peer are ignored. will be ignored.
"; ";
const string searchHelp = @" const string searchHelp = @"

View file

@ -243,10 +243,10 @@ static partial class Program
if (tle.needSourceSearch) if (tle.needSourceSearch)
{ {
Console.WriteLine($"{tle.source.Type} download: {tle.source.ToString(true)}, searching..");
await InitClientAndUpdateIfNeeded(); await InitClientAndUpdateIfNeeded();
Console.WriteLine($"{tle.source.Type} download: {tle.source.ToString(true)}, searching..");
if (tle.source.Type == TrackType.Album) if (tle.source.Type == TrackType.Album)
{ {
tle.list = await GetAlbumDownloads(tle.source, responseData); tle.list = await GetAlbumDownloads(tle.source, responseData);
@ -260,7 +260,10 @@ static partial class Program
var res = await GetAggregateAlbums(tle.source, responseData); var res = await GetAggregateAlbums(tle.source, responseData);
foreach (var item in res) foreach (var item in res)
trackLists.AddEntry(new TrackListEntry(item, tle.source, false, true, true, false, false)); {
var newSource = new Track(tle.source) { Type = TrackType.Album };
trackLists.AddEntry(new TrackListEntry(item, newSource, false, true, true, false, false));
}
} }
if (Config.skipExisting && tle.needSkipExistingAfterSearch) if (Config.skipExisting && tle.needSkipExistingAfterSearch)
@ -993,7 +996,8 @@ static partial class Program
user = new string(Enumerable.Repeat(chars, 10).Select(s => s[r.Next(s.Length)]).ToArray()); user = new string(Enumerable.Repeat(chars, 10).Select(s => s[r.Next(s.Length)]).ToArray());
pass = new string(Enumerable.Repeat(chars, 10).Select(s => s[r.Next(s.Length)]).ToArray()); pass = new string(Enumerable.Repeat(chars, 10).Select(s => s[r.Next(s.Length)]).ToArray());
} }
WriteLine($"Login {user}", debugOnly: true);
WriteLine($"Login {user}");
while (true) while (true)
{ {

View file

@ -482,18 +482,24 @@ static partial class Program
var albums = await GetAlbumDownloads(track, responseData); var albums = await GetAlbumDownloads(track, responseData);
var sortedLengthLists = new List<(int[] lengths, List<Track> album)>(); var sortedLengthLists = new List<(int[] lengths, List<Track> album, string username)>();
foreach (var album in albums) foreach (var album in albums)
{ {
if (album.Count == 0)
{
continue;
}
var sortedLengths = album.Where(x => !x.IsNotAudio).Select(x => x.Length).OrderBy(x => x).ToArray(); var sortedLengths = album.Where(x => !x.IsNotAudio).Select(x => x.Length).OrderBy(x => x).ToArray();
sortedLengthLists.Add((sortedLengths, album)); string user = album[0].FirstUsername;
sortedLengthLists.Add((sortedLengths, album, user));
} }
var lengthsList = new List<int[]>(); var lengthsList = new List<int[]>();
var res = new List<List<List<Track>>>(); var res = new List<List<List<Track>>>();
foreach ((var lengths, var album) in sortedLengthLists) foreach ((var lengths, var album, var user) in sortedLengthLists)
{ {
bool found = false; bool found = false;
@ -536,7 +542,7 @@ static partial class Program
} }
} }
res = res.Where(x => x.Count >= Config.minUsersAggregate).OrderByDescending(x => x.Count).ToList(); res = res.Where(x => x.Count >= Config.minSharesAggregate).OrderByDescending(x => x.Count).ToList();
return res; // Note: The nested lists are still ordered according to OrderedResults return res; // Note: The nested lists are still ordered according to OrderedResults
} }
@ -611,7 +617,7 @@ static partial class Program
IEnumerable<(SlResponse, SlFile)> fileResponses, int minShares = -1) IEnumerable<(SlResponse, SlFile)> fileResponses, int minShares = -1)
{ {
if (minShares == -1) if (minShares == -1)
minShares = Config.minUsersAggregate; minShares = Config.minSharesAggregate;
Track inferTrack((SearchResponse r, Soulseek.File f) x) Track inferTrack((SearchResponse r, Soulseek.File f) x)
{ {