mirror of
https://github.com/fiso64/slsk-batchdl.git
synced 2024-12-22 22:42:41 +00:00
commit
This commit is contained in:
parent
6e7b8d5d67
commit
f8c5ed23da
6 changed files with 50 additions and 40 deletions
39
README.md
39
README.md
|
@ -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
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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() { }
|
||||||
|
|
||||||
|
|
|
@ -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 = @"
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue