1
0
Fork 0
mirror of https://github.com/fiso64/slsk-batchdl.git synced 2024-12-22 14:32:40 +00:00
This commit is contained in:
fiso64 2024-06-24 22:55:30 +02:00
parent 93fb18f221
commit b0fc22364d
3 changed files with 71 additions and 36 deletions

View file

@ -197,6 +197,7 @@ Options:
'name-precise' (default): Use filenames and check conditions 'name-precise' (default): Use filenames and check conditions
'tag': Use file tags (slower) 'tag': Use file tags (slower)
'tag-precise': Use file tags and check file conditions 'tag-precise': Use file tags and check file conditions
'm3u': Skip all tracks that don't have a fail entry in m3u
--music-dir <path> Specify to also skip downloading tracks found in a music --music-dir <path> Specify to also skip downloading tracks found in a music
library. Use with --skip-existing library. Use with --skip-existing
--skip-not-found Skip searching for tracks that weren't found on Soulseek --skip-not-found Skip searching for tracks that weren't found on Soulseek

View file

@ -96,7 +96,6 @@ static class Program
static string timeUnit = "s"; static string timeUnit = "s";
static string displayStyle = "single"; static string displayStyle = "single";
static string input = ""; static string input = "";
static bool preciseSkip = true;
static string nameFormat = ""; static string nameFormat = "";
static string invalidReplaceStr = " "; static string invalidReplaceStr = " ";
static bool skipNotFound = false; static bool skipNotFound = false;
@ -114,7 +113,6 @@ static class Program
static string ytdlpArgument = ""; static string ytdlpArgument = "";
static bool skipExisting = false; static bool skipExisting = false;
static string m3uOption = "fails"; static string m3uOption = "fails";
static bool useTagsCheckExisting = false;
static bool removeTracksFromSource = false; static bool removeTracksFromSource = false;
static bool getDeleted = false; static bool getDeleted = false;
static bool deletedOnly = false; static bool deletedOnly = false;
@ -168,6 +166,17 @@ static class Program
CSV CSV
}; };
static SkipMode skipMode = SkipMode.NamePrecise;
public enum SkipMode
{
Name,
NamePrecise,
Tag,
TagPrecise,
M3u,
};
static void PrintHelp() static void PrintHelp()
{ {
Console.WriteLine("Usage: sldl <input> [OPTIONS]" + Console.WriteLine("Usage: sldl <input> [OPTIONS]" +
@ -280,6 +289,7 @@ static class Program
"\n 'name-precise' (default): Use filenames and check conditions" + "\n 'name-precise' (default): Use filenames and check conditions" +
"\n 'tag': Use file tags (slower)" + "\n 'tag': Use file tags (slower)" +
"\n 'tag-precise': Use file tags and check file conditions" + "\n 'tag-precise': Use file tags and check file conditions" +
"\n 'm3u': Skip all tracks that don't have a fail entry in m3u" +
"\n --music-dir <path> Specify to also skip downloading tracks found in a music" + "\n --music-dir <path> Specify to also skip downloading tracks found in a music" +
"\n library. Use with --skip-existing" + "\n library. Use with --skip-existing" +
"\n --skip-not-found Skip searching for tracks that weren't found on Soulseek" + "\n --skip-not-found Skip searching for tracks that weren't found on Soulseek" +
@ -706,7 +716,7 @@ static class Program
albumArtOption = ""; albumArtOption = "";
break; break;
default: default:
throw new ArgumentException($"Invalid album art download mode \'{args[i]}\'"); throw new ArgumentException($"Invalid album art download mode '{args[i]}'");
} }
break; break;
case "--aao": case "--aao":
@ -852,11 +862,6 @@ static class Program
case "--no-modify-share-count": case "--no-modify-share-count":
noModifyShareCount = true; noModifyShareCount = true;
break; break;
case "--seut":
case "--skip-existing-use-tags":
skipExisting = true;
useTagsCheckExisting = true;
break;
case "-d": case "-d":
case "--desperate": case "--desperate":
desperateSearch = true; desperateSearch = true;
@ -872,23 +877,20 @@ static class Program
displayStyle = args[i]; displayStyle = args[i];
break; break;
default: default:
throw new ArgumentException($"Invalid display style \"{args[i]}\""); throw new ArgumentException($"Invalid display style '{args[i]}'");
} }
break; break;
case "--sm": case "--sm":
case "--skip-mode": case "--skip-mode":
switch (args[++i]) skipMode = args[++i].ToLower().Trim() switch
{ {
case "name": "name" => SkipMode.Name,
case "name-precise": "name-precise" => SkipMode.NamePrecise,
case "tag": "tag" => SkipMode.Tag,
case "tag-precise": "tag-precise" => SkipMode.TagPrecise,
useTagsCheckExisting = args[i].Contains("tag"); "m3u" => SkipMode.M3u,
preciseSkip = args[i].Contains("-precise"); _ => throw new ArgumentException($"Invalid skip mode '{args[i]}'"),
break; };
default:
throw new ArgumentException($"Invalid skip mode \'{args[i]}\'");
}
break; break;
case "--nrsc": case "--nrsc":
case "--no-remove-special-chars": case "--no-remove-special-chars":
@ -1497,19 +1499,27 @@ static class Program
static List<Track> DoSkipExisting(List<Track> tracks, bool print, bool useCache) static List<Track> DoSkipExisting(List<Track> tracks, bool print, bool useCache)
{ {
var existing = new Dictionary<Track, string>(); var existing = new Dictionary<Track, string>();
if (!(musicDir != "" && outputFolder.StartsWith(musicDir, StringComparison.OrdinalIgnoreCase)) && System.IO.Directory.Exists(outputFolder))
if (skipMode == SkipMode.M3u)
{ {
var d = SkipExisting(tracks, outputFolder, necessaryCond, useTagsCheckExisting, preciseSkip, useCache); existing = SkipExistingM3u(tracks);
d.ToList().ForEach(x => existing.TryAdd(x.Key, x.Value));
} }
if (musicDir != "" && System.IO.Directory.Exists(musicDir)) else
{ {
if (print) Console.WriteLine($"Checking if tracks exist in library.."); if (!(musicDir != "" && outputFolder.StartsWith(musicDir, StringComparison.OrdinalIgnoreCase)) && System.IO.Directory.Exists(outputFolder))
var d = SkipExisting(tracks, musicDir, necessaryCond, useTagsCheckExisting, preciseSkip, useCache); {
d.ToList().ForEach(x => existing.TryAdd(x.Key, x.Value)); var d = SkipExisting(tracks, outputFolder, necessaryCond, skipMode, useCache);
d.ToList().ForEach(x => existing.TryAdd(x.Key, x.Value));
}
if (musicDir != "" && System.IO.Directory.Exists(musicDir))
{
if (print) Console.WriteLine($"Checking if tracks exist in library..");
var d = SkipExisting(tracks, musicDir, necessaryCond, skipMode, useCache);
d.ToList().ForEach(x => existing.TryAdd(x.Key, x.Value));
}
else if (musicDir != "" && !System.IO.Directory.Exists(musicDir))
if (print) Console.WriteLine($"Music dir does not exist: {musicDir}");
} }
else if (musicDir != "" && !System.IO.Directory.Exists(musicDir))
if (print) Console.WriteLine($"Musid dir does not exist: {musicDir}");
return existing.Select(x => x.Key).ToList(); return existing.Select(x => x.Key).ToList();
} }
@ -3950,11 +3960,13 @@ static class Program
return false; return false;
} }
static Dictionary<Track, string> SkipExisting(List<Track> tracks, string dir, FileConditions necessaryCond, bool useTags, bool precise, bool useCache) static Dictionary<Track, string> SkipExisting(List<Track> tracks, string dir, FileConditions necessaryCond, SkipMode mode, bool useCache)
{ {
var existing = new Dictionary<Track, string>(); var existing = new Dictionary<Track, string>();
List<string> musicFiles; List<string> musicFiles;
List<TagLib.File> musicIndex; List<TagLib.File> musicIndex;
bool useTags = mode == SkipMode.Tag || mode == SkipMode.TagPrecise;
bool precise = mode == SkipMode.NamePrecise || mode == SkipMode.TagPrecise;
if (useCache && MusicCache.TryGetValue(dir, out var cached)) if (useCache && MusicCache.TryGetValue(dir, out var cached))
{ {
@ -3991,6 +4003,22 @@ static class Program
return existing; return existing;
} }
static Dictionary<Track, string> SkipExistingM3u(List<Track> tracks)
{
var existing = new Dictionary<Track, string>();
for (int i = 0; i < tracks.Count; i++)
{
if (!m3uEditor.HasFail(tracks[i], out _))
{
existing.TryAdd(tracks[i], "");
tracks[i] = new Track(tracks[i]) { TrackState = Track.State.Exists, DownloadPath = "" };
}
}
return existing;
}
static List<TagLib.File> BuildMusicIndex(List<string> musicFiles) static List<TagLib.File> BuildMusicIndex(List<string> musicFiles)
{ {
var musicIndex = new List<TagLib.File>(); var musicIndex = new List<TagLib.File>();
@ -4761,18 +4789,18 @@ public class M3UEditor
this.offset = offset; this.offset = offset;
this.option = option; this.option = option;
path = Path.GetFullPath(m3uPath); path = Path.GetFullPath(m3uPath);
m3uListLabels = false;/*trackLists.lists.Any(x => x.type != TrackLists.ListType.Normal);*/
fails = ReadAllLines() var lines = ReadAllLines();
.Where(x => x.StartsWith("# Failed: ")) fails = lines.Where(x => x.StartsWith("# Failed: "))
.Select(line => .Select(line =>
{ {
var lastBracketIndex = line.LastIndexOf('['); var lastBracketIndex = line.LastIndexOf('[');
lastBracketIndex = lastBracketIndex == -1 ? line.Length : lastBracketIndex; lastBracketIndex = lastBracketIndex == -1 ? line.Length : lastBracketIndex;
var key = line.Substring("# Failed: ".Length, lastBracketIndex - "# Failed: ".Length).Trim(); var key = line.Substring("# Failed: ".Length, lastBracketIndex - "# Failed: ".Length).Trim();
var value = lastBracketIndex != line.Length ? line.Substring(lastBracketIndex + 1).Trim().TrimEnd(']') : ""; var value = lastBracketIndex != line.Length ? line.Substring(lastBracketIndex + 1).Trim().TrimEnd(']') : "";
return new { Key = key, Value = value }; return new { Key = key, Reason = value };
}) })
.ToSafeDictionary(pair => pair.Key, pair => pair.Value); .ToSafeDictionary(pair => pair.Key, pair => pair.Reason);
} }
public void Update() public void Update()
@ -4829,6 +4857,12 @@ public class M3UEditor
if (type != TrackLists.ListType.Normal) if (type != TrackLists.ListType.Normal)
index++; index++;
} }
else if (option == "fails" && track.TrackState == Track.State.Downloaded && index < lines.Count && lines[index].StartsWith($"# Failed: {track}"))
{
lines[index] = "";
needUpdate = true;
}
if (type == TrackLists.ListType.Normal) if (type == TrackLists.ListType.Normal)
index++; index++;
} }

View file

@ -23,7 +23,7 @@
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.63.0.3205" /> <PackageReference Include="Google.Apis.YouTube.v3" Version="1.63.0.3205" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.54" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.54" />
<PackageReference Include="SmallestCSVParser" Version="1.1.1" /> <PackageReference Include="SmallestCSVParser" Version="1.1.1" />
<PackageReference Include="Soulseek" Version="6.4.1" /> <PackageReference Include="Soulseek" Version="6.5.0" />
<PackageReference Include="SpotifyAPI.Web" Version="7.1.1" /> <PackageReference Include="SpotifyAPI.Web" Version="7.1.1" />
<PackageReference Include="SpotifyAPI.Web.Auth" Version="7.1.1" /> <PackageReference Include="SpotifyAPI.Web.Auth" Version="7.1.1" />
<PackageReference Include="TagLibSharp" Version="2.3.0" /> <PackageReference Include="TagLibSharp" Version="2.3.0" />