mirror of
https://github.com/fiso64/slsk-batchdl.git
synced 2024-12-22 14:32:40 +00:00
sss
This commit is contained in:
parent
e830f3f891
commit
681bfbb859
1 changed files with 48 additions and 45 deletions
|
@ -3,8 +3,6 @@ using Konsole;
|
||||||
using Soulseek;
|
using Soulseek;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Net.NetworkInformation;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
using ProgressBar = Konsole.ProgressBar;
|
using ProgressBar = Konsole.ProgressBar;
|
||||||
|
@ -16,6 +14,38 @@ using Directory = System.IO.Directory;
|
||||||
using SlDictionary = System.Collections.Concurrent.ConcurrentDictionary<string, (Soulseek.SearchResponse, Soulseek.File)>;
|
using SlDictionary = System.Collections.Concurrent.ConcurrentDictionary<string, (Soulseek.SearchResponse, Soulseek.File)>;
|
||||||
|
|
||||||
|
|
||||||
|
// todo: --get-parents: When not downloading albums, --get-parents will make the program retrieve and download
|
||||||
|
// all parent folders for every track (parent of parent if parent is a disc folder).
|
||||||
|
// Implementation: handle it under one download so that downloads for other tracks may continue
|
||||||
|
// simultaneously. However the downloads of a parent folder must continue after fails, unless that fail
|
||||||
|
// is the original track itself (jump to the next track + parent folder in that case).
|
||||||
|
// The result should be RefreshOrPrinted in the same progress bar: E.g if
|
||||||
|
// all parent tracks have been successfully downloaded, the progress bar should read
|
||||||
|
// "Succeeded (10/10 parent files): original track filepath", if 1 or more of the files failed to download
|
||||||
|
// "Succeeded with fails (02/10 parent files): original track filepath, (Failed: track1.mp3, track2.mp3)"
|
||||||
|
// Note that the success file count should always be 1 or more since the original track should always be a success,
|
||||||
|
// otherwise it should select another source for that track and download the files from the new parent.
|
||||||
|
// The original track should always be the first to be downloaded regardless of its order in the parent folder.
|
||||||
|
// Maybe create a new function GetParent(SlResponse, SlFile, ProgressBar, bool notThisFile=true) that will request the parent folder and download the files
|
||||||
|
// while properly updating the progress bar. The original track can be downloaded in SearchAndDownload (skipping to the next as usual on fail)
|
||||||
|
// and if successful, run GetParent to dl all files from the parent that arent the original track. The default resulting save file paths should be the same
|
||||||
|
// as the parent, e.g if parent folder is someuser\music\artist\album and one of the tracks is someuser\music\artist\disc 1\track.mp3 then we save
|
||||||
|
// it as outputFolder/album/disc 1/track.mp3.
|
||||||
|
// Note: It's possible that the parent folder downloads will contain a track that also appears in the track list later. We can check for this in the following
|
||||||
|
// way: Save a list/dict of all downloaded tracks together with the their key = username + "\\" + filename (check if one of the existing dicts/bags I define
|
||||||
|
// below can already be used for that as well). Then when performing a search for a particular track, we check if one of the results has been downloaded already
|
||||||
|
// AND satisfies the preferred conditions. If that is the case, we skip the track and refresh the progress bar with "Succeeded". If all results only satisfy nec
|
||||||
|
// conditions and a downloaded file also satisfies nec conditions, do the same.
|
||||||
|
//
|
||||||
|
// todo: --get-all
|
||||||
|
//
|
||||||
|
// todo: make --interactive work for non-albums as well, allowing the user to specify the desired file and to
|
||||||
|
// skip downloading a track. Important for --get-parents to avoid large numbers of unwanted files. When --get-parents is active,
|
||||||
|
// interactive should also print the list of files in the parent folder that are about to be downloaded, and there should be an
|
||||||
|
// additional option "Only Source Track [t]" which will make it only download the original track and not all the files in the parent.
|
||||||
|
//
|
||||||
|
// todo: --pref-users <list>
|
||||||
|
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
static SoulseekClient? client = null;
|
static SoulseekClient? client = null;
|
||||||
|
@ -137,7 +167,6 @@ static class Program
|
||||||
static bool printResultsFull = false;
|
static bool printResultsFull = false;
|
||||||
static bool debugPrintTracksFull = false;
|
static bool debugPrintTracksFull = false;
|
||||||
static bool useRandomLogin = false;
|
static bool useRandomLogin = false;
|
||||||
static bool noWaitForInternet = false;
|
|
||||||
|
|
||||||
static int searchesPerTime = 34;
|
static int searchesPerTime = 34;
|
||||||
static int searchResetTime = 220;
|
static int searchResetTime = 220;
|
||||||
|
@ -664,9 +693,6 @@ static class Program
|
||||||
case "--debug":
|
case "--debug":
|
||||||
debugInfo = true;
|
debugInfo = true;
|
||||||
break;
|
break;
|
||||||
case "--no-wait-for-internet":
|
|
||||||
noWaitForInternet = true;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException($"Unknown argument: {args[i]}");
|
throw new ArgumentException($"Unknown argument: {args[i]}");
|
||||||
}
|
}
|
||||||
|
@ -1054,10 +1080,11 @@ static class Program
|
||||||
await semaphore.WaitAsync(mainLoopCts.Token);
|
await semaphore.WaitAsync(mainLoopCts.Token);
|
||||||
int tries = 2;
|
int tries = 2;
|
||||||
retry:
|
retry:
|
||||||
await WaitForNetworkAndLogin();
|
await WaitForLogin();
|
||||||
mainLoopCts.Token.ThrowIfCancellationRequested();
|
mainLoopCts.Token.ThrowIfCancellationRequested();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
WriteLine($"SearchAndDownload {track}", debugOnly: true);
|
||||||
var savedFilePath = await SearchAndDownload(track);
|
var savedFilePath = await SearchAndDownload(track);
|
||||||
var curSet = downloadingImages ? downloadedImages : downloadedFiles;
|
var curSet = downloadingImages ? downloadedImages : downloadedFiles;
|
||||||
curSet.TryAdd(savedFilePath, char.MinValue);
|
curSet.TryAdd(savedFilePath, char.MinValue);
|
||||||
|
@ -1069,17 +1096,18 @@ static class Program
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (ex is SearchAndDownloadException)
|
WriteLine($"Exception thrown: {ex}", debugOnly: true);
|
||||||
|
if (!client.State.HasFlag(SoulseekClientStates.LoggedIn))
|
||||||
|
{
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
else if (ex is SearchAndDownloadException)
|
||||||
{
|
{
|
||||||
Interlocked.Increment(ref failCount);
|
Interlocked.Increment(ref failCount);
|
||||||
if (m3uOption == "fails" || m3uOption == "all" && !debugDisableDownload && inputType != "string" && !album)
|
if (m3uOption == "fails" || m3uOption == "all" && !debugDisableDownload && inputType != "string" && !album)
|
||||||
m3uEditor.WriteFail(ex.Message, track);
|
m3uEditor.WriteFail(ex.Message, track);
|
||||||
failedDownloads.Add((track, ex.Message));
|
failedDownloads.Add((track, ex.Message));
|
||||||
}
|
}
|
||||||
else if (!client.State.HasFlag(SoulseekClientStates.LoggedIn))
|
|
||||||
{
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteLine($"\n{ex.Message}\n{ex.StackTrace}\n", ConsoleColor.DarkYellow, true);
|
WriteLine($"\n{ex.Message}\n{ex.StackTrace}\n", ConsoleColor.DarkYellow, true);
|
||||||
|
@ -1114,6 +1142,7 @@ static class Program
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
|
WriteLine("Mainloop operation cancelled", debugOnly: true);
|
||||||
if (album && !albumIgnoreFails)
|
if (album && !albumIgnoreFails)
|
||||||
{
|
{
|
||||||
albumDlFailed = true;
|
albumDlFailed = true;
|
||||||
|
@ -1262,7 +1291,6 @@ static class Program
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await WaitForInternetConnection();
|
|
||||||
WriteLine($"Connecting {user}", debugOnly: true);
|
WriteLine($"Connecting {user}", debugOnly: true);
|
||||||
await client.ConnectAsync(user, pass);
|
await client.ConnectAsync(user, pass);
|
||||||
if (!noModifyShareCount) {
|
if (!noModifyShareCount) {
|
||||||
|
@ -1273,8 +1301,10 @@ static class Program
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
WriteLine($"Exception while logging in: {e}", debugOnly: true);
|
WriteLine($"Exception while logging in: {e}", debugOnly: true);
|
||||||
if (--tries == 0) throw;
|
if (!(e is Soulseek.AddressException) && --tries == 0)
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
await Task.Delay(500);
|
||||||
WriteLine($"Retry login {user}", debugOnly: true);
|
WriteLine($"Retry login {user}", debugOnly: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1880,7 +1910,6 @@ static class Program
|
||||||
static async Task Search(string search, SearchOptions opts, Action<SearchResponse> rHandler, CancellationToken ct, Action? onSearch = null)
|
static async Task Search(string search, SearchOptions opts, Action<SearchResponse> rHandler, CancellationToken ct, Action? onSearch = null)
|
||||||
{
|
{
|
||||||
await searchSemaphore.WaitAsync();
|
await searchSemaphore.WaitAsync();
|
||||||
await WaitForInternetConnection();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
search = CleanSearchString(search);
|
search = CleanSearchString(search);
|
||||||
|
@ -2058,6 +2087,7 @@ static class Program
|
||||||
if (debugDisableDownload)
|
if (debugDisableDownload)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
|
||||||
|
await WaitForLogin();
|
||||||
System.IO.Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
System.IO.Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||||
string origPath = filePath;
|
string origPath = filePath;
|
||||||
filePath = filePath + ".incomplete";
|
filePath = filePath + ".incomplete";
|
||||||
|
@ -2083,7 +2113,6 @@ static class Program
|
||||||
{
|
{
|
||||||
lock (downloads)
|
lock (downloads)
|
||||||
downloads.TryAdd(file.Filename, new DownloadWrapper(origPath, response, file, track, cts, progress));
|
downloads.TryAdd(file.Filename, new DownloadWrapper(origPath, response, file, track, cts, progress));
|
||||||
await WaitForInternetConnection();
|
|
||||||
await client.DownloadAsync(response.Username, file.Filename, () => Task.FromResult((Stream)outputStream), file.Size, options: transferOptions, cancellationToken: cts.Token);
|
await client.DownloadAsync(response.Username, file.Filename, () => Task.FromResult((Stream)outputStream), file.Size, options: transferOptions, cancellationToken: cts.Token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3215,40 +3244,14 @@ static class Program
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task WaitForInternetConnection()
|
public static async Task WaitForLogin()
|
||||||
{
|
{
|
||||||
if (noWaitForInternet)
|
|
||||||
return;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
WriteLine("Wait for internet", debugOnly: true);
|
WriteLine($"Wait for login, state: {client.State}", debugOnly: true);
|
||||||
if (NetworkInterface.GetIsNetworkAvailable())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var client = new System.Net.WebClient())
|
|
||||||
using (var stream = client.OpenRead("https://www.google.com"))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task WaitForNetworkAndLogin()
|
|
||||||
{
|
|
||||||
await WaitForInternetConnection();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
WriteLine("Wait for login", debugOnly: true);
|
|
||||||
if (client.State.HasFlag(SoulseekClientStates.LoggedIn))
|
if (client.State.HasFlag(SoulseekClientStates.LoggedIn))
|
||||||
break;
|
break;
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue