1
0
Fork 0
mirror of https://github.com/fiso64/slsk-batchdl.git synced 2024-12-22 06:22:41 +00:00
This commit is contained in:
fiso64 2024-08-30 18:35:44 +02:00
parent c5d11b995d
commit 8cf3016e6b
7 changed files with 79 additions and 39 deletions

View file

@ -23,6 +23,7 @@ See the [examples](#examples-1).
- [Configuration](#configuration)
- [Examples](#examples-1)
- [Notes](#notes)
- [Docker](#docker)
## Options
@ -48,7 +49,7 @@ Usage: sldl <input> [OPTIONS]
-o, --offset <offset> Skip a specified number of tracks
-r, --reverse Download tracks in reverse order
-c, --config <path> Set config file location. Set to 'none' to ignore config
--profile <name> Configuration profile to use. See --help "config".
--profile <names> Configuration profile(s) to use. See --help "config".
--concurrent-downloads <num> Max concurrent downloads (default: 2)
--m3u <option> Create an m3u8 playlist file in the output directory
'none' (default for single inputs): Do not create
@ -78,14 +79,15 @@ Usage: sldl <input> [OPTIONS]
--debug Print extra debug info
--listen-port <port> Port for incoming connections (default: 49998)
--on-complete <command> Run a specified command whenever a file is downloaded.
--on-complete <command> Run a command whenever a file is downloaded.
Available placeholders: {path} (local save path), {title},
{artist},{album},{uri},{length},{failure-reason},{state}.
Prepend a state number to only download in specific cases:
1:, 2:, 3:, 4: for the Downloaded, Failed, Exists, and
NotFoundLastTime states respectively.
NotFoundLastTime states respectively.
E.g: '1:<cmd>' will only run the command if the file is
downloaded successfully.
downloaded successfully. Prepend 's:' to use the system
shell to execute the command.
```
```
Searching
@ -420,7 +422,7 @@ tag1 is null, use tag2. String literals enclosed in parentheses are ignored in t
- "{artist( - )title|filename}"
If artist and title are not null, name it 'Artist - Title', otherwise use the original
filename.
- "{artist(/)album(/)track(. )title|(missing-tags/)filename}"
- "{albumartist(/)album(/)track(. )title|(missing-tags/)filename}"
Sort files into artist/album folders if all tags are present, otherwise put them in
the 'missing-tags' folder.

8
changelog.md Normal file
View file

@ -0,0 +1,8 @@
- configuration profiles, auto-profiles
- album aggregate download mode
- automatically browse user shares during album downloads to guarantee that all files from the parent folder are downloaded
- skip-existing is now much faster. Default mode is now m3u as it is more reliable. Changed how m3u skip-existing works (not backward compatible). Added `m3u-cond` skip mode. m3u modes can now skip album downloads.
- can now download entire bandcamp artist discographies
- added `--on-complete` to run a command whenever a file is downloaded
- now also looks in the user config directories for `sldl.conf`
- many bug fixes

View file

@ -173,7 +173,7 @@ static class Config
ApplyAutoProfiles();
}
ApplyProfile(profile);
ApplyProfiles(profile);
ProcessArgs(args);
@ -326,24 +326,27 @@ static class Config
{
//appliedProfiles.Clear();
appliedProfiles.UnionWith(newProfiles);
ApplyProfile(profile);
ApplyProfiles(profile);
ProcessArgs(arguments);
PostProcessArgs();
}
}
static void ApplyProfile(string name)
static void ApplyProfiles(string names)
{
if (name.Length > 0 && name != "default")
foreach (var name in names.Split(','))
{
if (profiles.ContainsKey(name))
if (name.Length > 0 && name != "default")
{
ProcessArgs(profiles[name].args);
appliedProfiles.Add(name);
if (profiles.ContainsKey(name))
{
ProcessArgs(profiles[name].args);
appliedProfiles.Add(name);
}
else
Console.WriteLine($"Error: No profile '{name}' found in config");
}
else
Console.WriteLine($"Error: No profile '{name}' found in config");
}
}
@ -359,7 +362,7 @@ static class Config
{
if (key == "default" || appliedProfiles.Contains(key))
continue;
if (key != profile && val.cond != null && ProfileConditionSatisfied(val.cond, tle))
if (val.cond != null && ProfileConditionSatisfied(val.cond, tle))
{
Console.WriteLine($"Applying auto profile: {key}");
ProcessArgs(val.args);

View file

@ -40,14 +40,14 @@ namespace Extractors
if (Config.input == "spotify-likes")
{
Console.WriteLine("Loading Spotify likes");
Console.WriteLine("Loading Spotify likes..");
var tracks = await spotifyClient.GetLikes(max, off);
playlistName = "Spotify Likes";
tle.list.Add(tracks);
}
else if (Config.input.Contains("/album/"))
{
Console.WriteLine("Loading Spotify album");
Console.WriteLine("Loading Spotify album..");
(var source, var tracks) = await spotifyClient.GetAlbum(Config.input);
playlistName = source.ToString(noInfo: true);
tle.source = source;
@ -60,7 +60,7 @@ namespace Extractors
}
else if (Config.input.Contains("/artist/"))
{
Console.WriteLine("Loading spotify artist");
Console.WriteLine("Loading spotify artist..");
Console.WriteLine("Error: Spotify artist download currently not supported.");
Environment.Exit(0);
}
@ -203,12 +203,12 @@ namespace Extractors
{
if (_clientToken.Length != 0)
{
Console.WriteLine("Testing Spotify access with existing token...");
//Console.WriteLine("Testing Spotify access with existing token...");
var client = new SpotifyClient(_clientToken);
try
{
var me = await client.UserProfile.Current();
Console.WriteLine("Spotify access is good!");
//Console.WriteLine("Spotify access is good!");
_client = client;
return true;
}
@ -229,7 +229,7 @@ namespace Extractors
{
var oauthClient = new OAuthClient();
var refreshResponse = await oauthClient.RequestToken(refreshRequest);
Console.WriteLine($"We got a new refreshed access token from server: {refreshResponse.AccessToken}");
//Console.WriteLine($"We got a new refreshed access token from server: {refreshResponse.AccessToken}");
_clientToken = refreshResponse.AccessToken;
_client = new SpotifyClient(_clientToken);
return true;

View file

@ -27,7 +27,7 @@ public static class Help
-o, --offset <offset> Skip a specified number of tracks
-r, --reverse Download tracks in reverse order
-c, --config <path> Set config file location. Set to 'none' to ignore config
--profile <name> Configuration profile to use. See --help ""config"".
--profile <names> Configuration profile(s) to use. See --help ""config"".
--concurrent-downloads <num> Max concurrent downloads (default: 2)
--m3u <option> Create an m3u8 playlist file in the output directory
'none' (default for single inputs): Do not create
@ -57,14 +57,15 @@ public static class Help
--debug Print extra debug info
--listen-port <port> Port for incoming connections (default: 49998)
--on-complete <command> Run a specified command whenever a file is downloaded.
--on-complete <command> Run a command whenever a file is downloaded.
Available placeholders: {path} (local save path), {title},
{artist},{album},{uri},{length},{failure-reason},{state}.
Prepend a state number to only download in specific cases:
1:, 2:, 3:, 4: for the Downloaded, Failed, Exists, and
NotFoundLastTime states respectively.
E.g: '1:<cmd>' will only run the command if the file is
downloaded successfully.
downloaded successfully. Prepend 's:' to use the system
shell to execute the command.
Searching
--fast-search Begin downloading as soon as a file satisfying the preferred
@ -393,7 +394,7 @@ public static class Help
""{artist( - )title|filename}""
If artist and title are not null, name it 'Artist - Title', otherwise use the original
filename.
""{artist(/)album(/)track(. )title|(missing-tags/)filename}""
""{albumartist(/)album(/)track(. )title|(missing-tags/)filename}""
Sort files into artist/album folders if all tags are present, otherwise put them in
the 'missing-tags' folder.

View file

@ -258,7 +258,6 @@ public static class Printing
WriteLine($"User : {userInfo}\nFolder: {parents}\nProps : {props}", ConsoleColor.White);
PrintTracks(albumTracks.ToList(), pathsOnly: true, showAncestors: false, showUser: false);
Console.WriteLine();
}

View file

@ -432,7 +432,7 @@ static partial class Program
bool succeeded = false;
string? soulseekDir = null;
while (tle.list.Count > 0)
while (tle.list.Count > 0 && !Config.albumArtOnly)
{
int index = 0;
bool wasInteractive = Config.interactiveMode;
@ -531,7 +531,7 @@ static partial class Program
int[]? sortedLengths = null;
if (chosenAlbum != null && chosenAlbum.Count(t => !t.IsNotAudio) > 0)
if (chosenAlbum != null && chosenAlbum.Any(t => !t.IsNotAudio))
sortedLengths = chosenAlbum.Where(t => !t.IsNotAudio).Select(t => t.Length).OrderBy(x => x).ToArray();
var albumArts = downloads
@ -556,7 +556,9 @@ static partial class Program
{
mSize = chosenAlbum
.Where(t => t.State == TrackState.Downloaded && Utils.IsImageFile(t.DownloadPath))
.Max(t => t.FirstDownload.Size);
.Select(t => t.FirstDownload.Size)
.DefaultIfEmpty(0)
.Max();
}
}
else if (option == AlbumArtOption.Most)
@ -772,6 +774,7 @@ static partial class Program
}
PrintAlbum(tracks);
Console.WriteLine();
string userInput = interactiveModeLoop().Trim();
switch (userInput)
@ -913,15 +916,30 @@ static partial class Program
{
if (onComplete.Length == 0)
return;
else if (onComplete.Length > 2 && onComplete[0].IsDigit() && onComplete[1] == ':')
bool useShellExecute = false;
int count = 0;
while (onComplete.Length > 2 && count++ < 2)
{
if ((int)track.State != int.Parse(onComplete[0].ToString()))
return;
if (onComplete[0] == 's' && onComplete[1] == ':')
{
useShellExecute = true;
}
else if (onComplete[0].IsDigit() && onComplete[1] == ':')
{
if ((int)track.State != int.Parse(onComplete[0].ToString()))
return;
}
else
{
break;
}
onComplete = onComplete[2..];
}
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
var process = new Process();
var startInfo = new ProcessStartInfo();
onComplete = onComplete.Replace("{title}", track.Title)
.Replace("{artist}", track.Artist)
@ -957,16 +975,25 @@ static partial class Program
startInfo.Arguments = parts.Length > 1 ? parts[1] : "";
}
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
if (!useShellExecute)
{
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
}
startInfo.UseShellExecute = useShellExecute;
process.StartInfo = startInfo;
WriteLine($"on-complete: FileName={startInfo.FileName}, Arguments={startInfo.Arguments}", debugOnly: true);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (!useShellExecute)
{
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
process.WaitForExit();
}