mirror of
https://github.com/fiso64/slsk-batchdl.git
synced 2024-12-22 14:32:40 +00:00
commit
This commit is contained in:
parent
8cf3016e6b
commit
95d6cb7493
8 changed files with 54 additions and 24 deletions
18
README.md
18
README.md
|
@ -56,6 +56,7 @@ Usage: sldl <input> [OPTIONS]
|
||||||
'index' (default): Write a line indexing all downloaded
|
'index' (default): Write a line indexing all downloaded
|
||||||
files, required for skip-not-found or skip-existing=m3u
|
files, required for skip-not-found or skip-existing=m3u
|
||||||
'all': Write the index and a list of paths and fails
|
'all': Write the index and a list of paths and fails
|
||||||
|
--m3u-path <path> Override default m3u path
|
||||||
|
|
||||||
-s, --skip-existing Skip if a track matching file conditions is found in the
|
-s, --skip-existing Skip if a track matching file conditions is found in the
|
||||||
output folder or your music library (if provided)
|
output folder or your music library (if provided)
|
||||||
|
@ -558,7 +559,7 @@ sldl "title=MC MENTAL @ HIS BEST,length=242" --pref-format "flac,wav"
|
||||||
|
|
||||||
Interactive album download:
|
Interactive album download:
|
||||||
```
|
```
|
||||||
sldl "album=Some Album" --interactive
|
sldl "Some Album" --album --interactive
|
||||||
```
|
```
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
@ -568,10 +569,23 @@ sldl "artist=MC MENTAL" --aggregate --skip-existing --music-dir "path/to/music"
|
||||||
```
|
```
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
Download all albums by an artist that are on soulseek:
|
Download all albums by an artist found on soulseek:
|
||||||
```
|
```
|
||||||
sldl "artist=MC MENTAL" --aggregate --album
|
sldl "artist=MC MENTAL" --aggregate --album
|
||||||
```
|
```
|
||||||
|
<hr style="height:0px; visibility:hidden;" />
|
||||||
|
|
||||||
|
#### Advanced example: Automatic wishlist downloader
|
||||||
|
Create a file named wishlist.txt, and add your wishlist items:
|
||||||
|
```bash
|
||||||
|
echo title=My Favorite Song, artist=Artist >> wishlist.txt
|
||||||
|
echo https://spotify/album/url >> wishlist.txt
|
||||||
|
```
|
||||||
|
Set up a cron job (or scheduled task on windows) to periodically run sldl on every line of the wishlist file with the following options:
|
||||||
|
```
|
||||||
|
--skip-existing --skip-mode m3u --m3u index --m3u-path wishlist-archive.sldl
|
||||||
|
```
|
||||||
|
You can also use m3u-cond and specify some preferred conditions to e.g only stop searching for an item once a lossless version is downloaded.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
- For macOS builds you can use publish.sh to build the app. Download dotnet from https://dotnet.microsoft.com/en-us/download/dotnet/6.0, then run `chmod +x publish.sh && sh publish.sh`. For intel macs, uncomment the x64 and comment the arm64 section in publish.sh.
|
- For macOS builds you can use publish.sh to build the app. Download dotnet from https://dotnet.microsoft.com/en-us/download/dotnet/6.0, then run `chmod +x publish.sh && sh publish.sh`. For intel macs, uncomment the x64 and comment the arm64 section in publish.sh.
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
- 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
|
|
|
@ -846,6 +846,10 @@ static class Config
|
||||||
_ => throw new ArgumentException($"Invalid m3u option '{args[i]}'"),
|
_ => throw new ArgumentException($"Invalid m3u option '{args[i]}'"),
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case "--m3up":
|
||||||
|
case "--m3u-path":
|
||||||
|
m3uFilePath = args[++i];
|
||||||
|
break;
|
||||||
case "--lp":
|
case "--lp":
|
||||||
case "--port":
|
case "--port":
|
||||||
case "--listen-port":
|
case "--listen-port":
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace Data
|
||||||
Other = other.Other;
|
Other = other.Other;
|
||||||
MinAlbumTrackCount = other.MinAlbumTrackCount;
|
MinAlbumTrackCount = other.MinAlbumTrackCount;
|
||||||
MaxAlbumTrackCount = other.MaxAlbumTrackCount;
|
MaxAlbumTrackCount = other.MaxAlbumTrackCount;
|
||||||
CsvRow = other.CsvRow;
|
//CsvRow = other.CsvRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToKey()
|
public string ToKey()
|
||||||
|
|
|
@ -47,12 +47,19 @@ namespace Extractors
|
||||||
{
|
{
|
||||||
if (File.Exists(Config.input))
|
if (File.Exists(Config.input))
|
||||||
{
|
{
|
||||||
string[] lines = File.ReadAllLines(Config.input, System.Text.Encoding.UTF8);
|
try
|
||||||
|
|
||||||
if (lines.Length > track.CsvRow)
|
|
||||||
{
|
{
|
||||||
lines[track.CsvRow] = new string(',', Math.Max(0, csvColumnCount - 1));
|
string[] lines = File.ReadAllLines(Config.input, System.Text.Encoding.UTF8);
|
||||||
Utils.WriteAllLines(Config.input, lines, '\n');
|
|
||||||
|
if (track.CsvRow > -1 && track.CsvRow < lines.Length)
|
||||||
|
{
|
||||||
|
lines[track.CsvRow] = new string(',', Math.Max(0, csvColumnCount - 1));
|
||||||
|
Utils.WriteAllLines(Config.input, lines, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Printing.WriteLine($"Error removing from source: {e}", debugOnly: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,8 +106,15 @@ namespace Extractors
|
||||||
|
|
||||||
public async Task RemoveTrackFromSource(Track track)
|
public async Task RemoveTrackFromSource(Track track)
|
||||||
{
|
{
|
||||||
if (playlistUri.Length > 0 && track.URI.Length > 0)
|
try
|
||||||
await spotifyClient.RemoveTrackFromPlaylist(playlistUri, track.URI);
|
{
|
||||||
|
if (playlistUri.Length > 0 && track.URI.Length > 0)
|
||||||
|
await spotifyClient.RemoveTrackFromPlaylist(playlistUri, track.URI);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Printing.WriteLine($"Error removing from source: {e}", debugOnly: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ public static class Help
|
||||||
'index' (default): Write a line indexing all downloaded
|
'index' (default): Write a line indexing all downloaded
|
||||||
files, required for skip-not-found or skip-existing=m3u
|
files, required for skip-not-found or skip-existing=m3u
|
||||||
'all': Write the index and a list of paths and fails
|
'all': Write the index and a list of paths and fails
|
||||||
|
--m3u-path <path> Override default m3u path
|
||||||
|
|
||||||
-s, --skip-existing Skip if a track matching file conditions is found in the
|
-s, --skip-existing Skip if a track matching file conditions is found in the
|
||||||
output folder or your music library (if provided)
|
output folder or your music library (if provided)
|
||||||
|
|
|
@ -416,7 +416,7 @@ static partial class Program
|
||||||
|
|
||||||
var downloadTasks = tracks.Select(async (track, index) =>
|
var downloadTasks = tracks.Select(async (track, index) =>
|
||||||
{
|
{
|
||||||
await DownloadTask(tle, track, semaphore, organizer, null, false);
|
await DownloadTask(tle, track, semaphore, organizer, null, false, true);
|
||||||
m3uEditor.Update();
|
m3uEditor.Update();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -469,7 +469,7 @@ static partial class Program
|
||||||
{
|
{
|
||||||
var downloadTasks = tracks.Select(async track =>
|
var downloadTasks = tracks.Select(async track =>
|
||||||
{
|
{
|
||||||
await DownloadTask(tle, track, semaphore, organizer, cts, cancelOnFail: !Config.albumIgnoreFails);
|
await DownloadTask(tle, track, semaphore, organizer, cts, cancelOnFail: !Config.albumIgnoreFails, true);
|
||||||
});
|
});
|
||||||
await Task.WhenAll(downloadTasks);
|
await Task.WhenAll(downloadTasks);
|
||||||
|
|
||||||
|
@ -491,7 +491,7 @@ static partial class Program
|
||||||
tle.list.RemoveAt(index);
|
tle.list.RemoveAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tracks != null)
|
if (tracks != null && succeeded)
|
||||||
{
|
{
|
||||||
var downloadedAudio = tracks.Where(t => !t.IsNotAudio && t.State == TrackState.Downloaded && t.DownloadPath.Length > 0);
|
var downloadedAudio = tracks.Where(t => !t.IsNotAudio && t.State == TrackState.Downloaded && t.DownloadPath.Length > 0);
|
||||||
|
|
||||||
|
@ -499,6 +499,11 @@ static partial class Program
|
||||||
{
|
{
|
||||||
tle.source.State = TrackState.Downloaded;
|
tle.source.State = TrackState.Downloaded;
|
||||||
tle.source.DownloadPath = Utils.GreatestCommonDirectory(downloadedAudio.Select(t => t.DownloadPath));
|
tle.source.DownloadPath = Utils.GreatestCommonDirectory(downloadedAudio.Select(t => t.DownloadPath));
|
||||||
|
|
||||||
|
if (Config.removeTracksFromSource)
|
||||||
|
{
|
||||||
|
await extractor.RemoveTrackFromSource(tle.source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,7 +625,7 @@ static partial class Program
|
||||||
|
|
||||||
foreach (var track in tracks)
|
foreach (var track in tracks)
|
||||||
{
|
{
|
||||||
await DownloadTask(null, track, semaphore, organizer, null, false);
|
await DownloadTask(null, track, semaphore, organizer, null, false, false);
|
||||||
|
|
||||||
if (track.State == TrackState.Downloaded)
|
if (track.State == TrackState.Downloaded)
|
||||||
downloadedImages.Add(track);
|
downloadedImages.Add(track);
|
||||||
|
@ -636,7 +641,7 @@ static partial class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static async Task DownloadTask(TrackListEntry? tle, Track track, SemaphoreSlim semaphore, FileManager organizer, CancellationTokenSource? cts, bool cancelOnFail)
|
static async Task DownloadTask(TrackListEntry? tle, Track track, SemaphoreSlim semaphore, FileManager organizer, CancellationTokenSource? cts, bool cancelOnFail, bool removeFromSource)
|
||||||
{
|
{
|
||||||
if (track.State != TrackState.Initial)
|
if (track.State != TrackState.Initial)
|
||||||
return;
|
return;
|
||||||
|
@ -706,7 +711,7 @@ static partial class Program
|
||||||
track.DownloadPath = savedFilePath;
|
track.DownloadPath = savedFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.removeTracksFromSource)
|
if (removeFromSource && Config.removeTracksFromSource)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue