mirror of
https://github.com/fiso64/slsk-batchdl.git
synced 2024-12-22 14:32:40 +00:00
fix aggregate, fix name skip-existing
This commit is contained in:
parent
01586d9366
commit
d1228110a2
6 changed files with 88 additions and 27 deletions
|
@ -250,7 +250,7 @@ The id and secret can be obtained at https://developer.spotify.com/dashboard/app
|
||||||
Create an app and add http://localhost:48721/callback as a redirect url in its settings.
|
Create an app and add http://localhost:48721/callback as a redirect url in its settings.
|
||||||
|
|
||||||
### Bandcamp
|
### Bandcamp
|
||||||
An bandcamp url: Download a single track, and album, or an artist's entire discography.
|
A bandcamp url: Download a single track, and album, or an artist's entire discography.
|
||||||
Extracts the artist name, album name and sets --album-track-count="n+", where n is the
|
Extracts the artist name, album name and sets --album-track-count="n+", where n is the
|
||||||
number of visible tracks on the bandcamp page.
|
number of visible tracks on the bandcamp page.
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
public class NameExistingChecker : ExistingChecker
|
public class NameExistingChecker : ExistingChecker
|
||||||
{
|
{
|
||||||
readonly string[] ignore = new string[] { " ", "_", "-", ".", "(", ")", "[", "]" };
|
readonly string[] ignore = new string[] { "_", "-", ".", "(", ")", "[", "]" };
|
||||||
readonly string dir;
|
readonly string dir;
|
||||||
readonly List<(string, string, string)> index = new(); // (Path, PreprocessedPath, PreprocessedName)
|
readonly List<(string, string, string)> index = new(); // (Path, PreprocessedPath, PreprocessedName)
|
||||||
|
|
||||||
|
@ -42,15 +42,22 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
private string Preprocess(string s, bool removeSlash)
|
private string Preprocess(string s, bool removeSlash)
|
||||||
{
|
{
|
||||||
s = s.ToLower().Replace(ignore, "");
|
s = s.ToLower();
|
||||||
s = s.ReplaceInvalidChars("", false, removeSlash);
|
|
||||||
s = s.RemoveFt();
|
s = s.RemoveFt();
|
||||||
s = s.RemoveDiacritics();
|
s = s.Replace(ignore, " ");
|
||||||
|
s = s.ReplaceInvalidChars(' ', false, removeSlash);
|
||||||
|
s = s.RemoveConsecutiveWs();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void BuildIndex()
|
public override void BuildIndex()
|
||||||
{
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
IndexIsBuilt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
int removeLen = Preprocess(dir, false).Length + 1;
|
int removeLen = Preprocess(dir, false).Length + 1;
|
||||||
|
@ -59,7 +66,7 @@ namespace ExistingCheckers
|
||||||
{
|
{
|
||||||
if (Utils.IsMusicFile(path))
|
if (Utils.IsMusicFile(path))
|
||||||
{
|
{
|
||||||
string ppath = Preprocess(path[..path.LastIndexOf('.')], false)[removeLen..];
|
string ppath = Preprocess(path[removeLen..path.LastIndexOf('.')], false);
|
||||||
string pname = Path.GetFileName(ppath);
|
string pname = Path.GetFileName(ppath);
|
||||||
index.Add((path, ppath, pname));
|
index.Add((path, ppath, pname));
|
||||||
}
|
}
|
||||||
|
@ -80,8 +87,7 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
foreach ((var path, var ppath, var pname) in index)
|
foreach ((var path, var ppath, var pname) in index)
|
||||||
{
|
{
|
||||||
if (pname.ContainsWithBoundaryIgnoreWs(title, acceptLeftDigit: true)
|
if (pname.ContainsWithBoundary(title) && ppath.ContainsWithBoundary(artist))
|
||||||
&& ppath.ContainsWithBoundaryIgnoreWs(artist, acceptLeftDigit: true))
|
|
||||||
{
|
{
|
||||||
foundPath = path;
|
foundPath = path;
|
||||||
return true;
|
return true;
|
||||||
|
@ -95,7 +101,7 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
public class NameConditionExistingChecker : ExistingChecker
|
public class NameConditionExistingChecker : ExistingChecker
|
||||||
{
|
{
|
||||||
readonly string[] ignore = new string[] { " ", "_", "-", ".", "(", ")", "[", "]" };
|
readonly string[] ignore = new string[] { "_", "-", ".", "(", ")", "[", "]" };
|
||||||
readonly string dir;
|
readonly string dir;
|
||||||
readonly List<(string, string, SimpleFile)> index = new(); // (PreprocessedPath, PreprocessedName, file)
|
readonly List<(string, string, SimpleFile)> index = new(); // (PreprocessedPath, PreprocessedName, file)
|
||||||
FileConditions conditions;
|
FileConditions conditions;
|
||||||
|
@ -108,15 +114,22 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
private string Preprocess(string s, bool removeSlash)
|
private string Preprocess(string s, bool removeSlash)
|
||||||
{
|
{
|
||||||
s = s.ToLower().Replace(ignore, "");
|
s = s.ToLower();
|
||||||
s = s.ReplaceInvalidChars("", false, removeSlash);
|
|
||||||
s = s.RemoveFt();
|
s = s.RemoveFt();
|
||||||
s = s.RemoveDiacritics();
|
s = s.Replace(ignore, " ");
|
||||||
|
s = s.ReplaceInvalidChars(' ', false, removeSlash);
|
||||||
|
s = s.RemoveConsecutiveWs();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void BuildIndex()
|
public override void BuildIndex()
|
||||||
{
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
IndexIsBuilt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
int removeLen = Preprocess(dir, false).Length + 1;
|
int removeLen = Preprocess(dir, false).Length + 1;
|
||||||
|
@ -150,9 +163,7 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
foreach ((var ppath, var pname, var musicFile) in index)
|
foreach ((var ppath, var pname, var musicFile) in index)
|
||||||
{
|
{
|
||||||
if (pname.ContainsWithBoundaryIgnoreWs(title, acceptLeftDigit: true)
|
if (pname.ContainsWithBoundary(title) && ppath.ContainsWithBoundary(artist) && conditions.FileSatisfies(musicFile, track))
|
||||||
&& ppath.ContainsWithBoundaryIgnoreWs(artist, acceptLeftDigit: true)
|
|
||||||
&& conditions.FileSatisfies(musicFile, track))
|
|
||||||
{
|
{
|
||||||
foundPath = musicFile.Path;
|
foundPath = musicFile.Path;
|
||||||
return true;
|
return true;
|
||||||
|
@ -176,11 +187,17 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
private string Preprocess(string s)
|
private string Preprocess(string s)
|
||||||
{
|
{
|
||||||
return s.Replace(" ", "").RemoveFt().ToLower();
|
return s.RemoveFt().Replace(" ", "").ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void BuildIndex()
|
public override void BuildIndex()
|
||||||
{
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
IndexIsBuilt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
foreach (var path in files)
|
foreach (var path in files)
|
||||||
|
@ -237,11 +254,17 @@ namespace ExistingCheckers
|
||||||
|
|
||||||
private string Preprocess(string s)
|
private string Preprocess(string s)
|
||||||
{
|
{
|
||||||
return s.Replace(" ", "").RemoveFt().ToLower();
|
return s.RemoveFt().Replace(" ", "").ToLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void BuildIndex()
|
public override void BuildIndex()
|
||||||
{
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
IndexIsBuilt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
var files = Directory.GetFiles(dir, "*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
foreach (var path in files)
|
foreach (var path in files)
|
||||||
|
@ -293,6 +316,7 @@ namespace ExistingCheckers
|
||||||
{
|
{
|
||||||
this.m3uEditor = m3UEditor;
|
this.m3uEditor = m3UEditor;
|
||||||
this.checkFileExists = checkFileExists;
|
this.checkFileExists = checkFileExists;
|
||||||
|
IndexIsBuilt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool TrackExists(Track track, out string? foundPath)
|
public override bool TrackExists(Track track, out string? foundPath)
|
||||||
|
@ -334,6 +358,7 @@ namespace ExistingCheckers
|
||||||
{
|
{
|
||||||
this.m3uEditor = m3UEditor;
|
this.m3uEditor = m3UEditor;
|
||||||
this.conditions = conditions;
|
this.conditions = conditions;
|
||||||
|
IndexIsBuilt = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool TrackExists(Track track, out string? foundPath)
|
public override bool TrackExists(Track track, out string? foundPath)
|
||||||
|
|
|
@ -221,7 +221,7 @@ public static class Help
|
||||||
Create an app and add http://localhost:48721/callback as a redirect url in its settings.
|
Create an app and add http://localhost:48721/callback as a redirect url in its settings.
|
||||||
|
|
||||||
Bandcamp
|
Bandcamp
|
||||||
An bandcamp url: Download a single track, and album, or an artist's entire discography.
|
A bandcamp url: Download a single track, and album, or an artist's entire discography.
|
||||||
Extracts the artist name, album name and sets --album-track-count=""n+"", where n is the
|
Extracts the artist name, album name and sets --album-track-count=""n+"", where n is the
|
||||||
number of visible tracks on the bandcamp page.
|
number of visible tracks on the bandcamp page.
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ static partial class Program
|
||||||
|
|
||||||
m3uEditor = new M3uEditor(Config.m3uFilePath, trackLists, Config.m3uOption, Config.offset);
|
m3uEditor = new M3uEditor(Config.m3uFilePath, trackLists, Config.m3uOption, Config.offset);
|
||||||
|
|
||||||
InitExistingChecker();
|
InitExistingCheckers();
|
||||||
|
|
||||||
await MainLoop();
|
await MainLoop();
|
||||||
WriteLine("Mainloop done", debugOnly: true);
|
WriteLine("Mainloop done", debugOnly: true);
|
||||||
|
@ -109,7 +109,7 @@ static partial class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void InitExistingChecker()
|
static void InitExistingCheckers()
|
||||||
{
|
{
|
||||||
if (Config.skipExisting)
|
if (Config.skipExisting)
|
||||||
{
|
{
|
||||||
|
@ -123,7 +123,7 @@ static partial class Program
|
||||||
if (!Directory.Exists(Config.musicDir))
|
if (!Directory.Exists(Config.musicDir))
|
||||||
Console.WriteLine("Error: Music directory does not exist");
|
Console.WriteLine("Error: Music directory does not exist");
|
||||||
else
|
else
|
||||||
musicDirExistingChecker = ExistingCheckerRegistry.GetChecker(Config.skipModeMusicDir, Config.outputFolder, cond, m3uEditor);
|
musicDirExistingChecker = ExistingCheckerRegistry.GetChecker(Config.skipModeMusicDir, Config.musicDir, cond, m3uEditor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ static partial class Program
|
||||||
}
|
}
|
||||||
else if (tle.source.Type == TrackType.Aggregate)
|
else if (tle.source.Type == TrackType.Aggregate)
|
||||||
{
|
{
|
||||||
tle.list[0] = await GetAggregateTracks(tle.source, responseData);
|
tle.list.Insert(0, await GetAggregateTracks(tle.source, responseData));
|
||||||
}
|
}
|
||||||
else if (tle.source.Type == TrackType.AlbumAggregate)
|
else if (tle.source.Type == TrackType.AlbumAggregate)
|
||||||
{
|
{
|
||||||
|
@ -271,7 +271,7 @@ static partial class Program
|
||||||
if (Config.skipExisting && tle.needSkipExistingAfterSearch)
|
if (Config.skipExisting && tle.needSkipExistingAfterSearch)
|
||||||
{
|
{
|
||||||
foreach (var tracks in tle.list)
|
foreach (var tracks in tle.list)
|
||||||
notFound.AddRange(DoSkipExisting(tracks));
|
existing.AddRange(DoSkipExisting(tracks));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tle.gotoNextAfterSearch)
|
if (tle.gotoNextAfterSearch)
|
||||||
|
@ -412,7 +412,7 @@ static partial class Program
|
||||||
Console.WriteLine("\n-----------------------------------------------\n");
|
Console.WriteLine("\n-----------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.PrintTracks)
|
if (Config.PrintTracks || Config.PrintResults)
|
||||||
{
|
{
|
||||||
if (existing.Count > 0)
|
if (existing.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -363,7 +363,7 @@ static partial class Program
|
||||||
{
|
{
|
||||||
int musicFileCount = val.Count(x => Utils.IsMusicFile(x.file.Filename));
|
int musicFileCount = val.Count(x => Utils.IsMusicFile(x.file.Filename));
|
||||||
|
|
||||||
if (!countIsGood(musicFileCount))
|
if (musicFileCount == 0 || !countIsGood(musicFileCount))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var ls = new List<Track>();
|
var ls = new List<Track>();
|
||||||
|
@ -433,6 +433,8 @@ static partial class Program
|
||||||
string trackName = track.Title.Trim();
|
string trackName = track.Title.Trim();
|
||||||
string albumName = track.Album.Trim();
|
string albumName = track.Album.Trim();
|
||||||
|
|
||||||
|
//var orderedResults = OrderedResults(results, track, false, false, false);
|
||||||
|
|
||||||
var fileResponses = results.Select(x => x.Value);
|
var fileResponses = results.Select(x => x.Value);
|
||||||
|
|
||||||
var equivalentFiles = EquivalentFiles(track, fileResponses).ToList();
|
var equivalentFiles = EquivalentFiles(track, fileResponses).ToList();
|
||||||
|
@ -961,9 +963,11 @@ static partial class Program
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Track InferTrack(string filename, Track defaultTrack)
|
static Track InferTrack(string filename, Track defaultTrack, TrackType type = TrackType.Normal)
|
||||||
{
|
{
|
||||||
var t = new Track(defaultTrack);
|
var t = new Track(defaultTrack);
|
||||||
|
t.Type = type;
|
||||||
|
|
||||||
filename = Utils.GetFileNameWithoutExtSlsk(filename).Replace(" — ", " - ").Replace('_', ' ').Trim().RemoveConsecutiveWs();
|
filename = Utils.GetFileNameWithoutExtSlsk(filename).Replace(" — ", " - ").Replace('_', ' ').Trim().RemoveConsecutiveWs();
|
||||||
|
|
||||||
var trackNumStart = new Regex(@"^(?:(?:[0-9][-\.])?\d{2,3}[. -]|\b\d\.\s|\b\d\s-\s)(?=.+\S)");
|
var trackNumStart = new Regex(@"^(?:(?:[0-9][-\.])?\d{2,3}[. -]|\b\d\.\s|\b\d\s-\s)(?=.+\S)");
|
||||||
|
|
|
@ -357,7 +357,7 @@ public static class Utils
|
||||||
return s.Contains(other, StringComparison.OrdinalIgnoreCase);
|
return s.Contains(other, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly HashSet<char> boundarySet = new("-|.\\/_—()[],:?!;@:*=+{}|'\"$^&`~%<>".ToCharArray());
|
static readonly HashSet<char> boundarySet = new("-|.\\/_—()[],:?!;@#:*=+{}|'\"$^&`~%<>".ToCharArray());
|
||||||
|
|
||||||
public static bool ContainsWithBoundary(this string str, string value, bool ignoreCase = false)
|
public static bool ContainsWithBoundary(this string str, string value, bool ignoreCase = false)
|
||||||
{
|
{
|
||||||
|
@ -434,6 +434,38 @@ public static class Utils
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ContainsInBracketsOptimized(this string str, string searchTerm, bool ignoreCase = false)
|
||||||
|
{
|
||||||
|
if (str.Length == 0 && searchTerm.Length > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var comp = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
|
||||||
|
int depth = 0;
|
||||||
|
int searchTermLen = searchTerm.Length;
|
||||||
|
|
||||||
|
for (int i = 0; i < str.Length; i++)
|
||||||
|
{
|
||||||
|
char c = str[i];
|
||||||
|
|
||||||
|
if (c == '[' || c == '(')
|
||||||
|
{
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
else if (c == ']' || c == ')')
|
||||||
|
{
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth > 0 && i + searchTermLen <= str.Length)
|
||||||
|
{
|
||||||
|
if (str.Substring(i, searchTermLen).Equals(searchTerm, comp))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool RemoveRegexIfExist(this string s, string reg, out string res)
|
public static bool RemoveRegexIfExist(this string s, string reg, out string res)
|
||||||
{
|
{
|
||||||
res = Regex.Replace(s, reg, string.Empty);
|
res = Regex.Replace(s, reg, string.Empty);
|
||||||
|
|
Loading…
Reference in a new issue