diff --git a/GoFile DL/Entities/CreateAccountResponse.cs b/GoFile DL/Entities/CreateAccountResponse.cs index 9dbb2a6..78e51fc 100644 --- a/GoFile DL/Entities/CreateAccountResponse.cs +++ b/GoFile DL/Entities/CreateAccountResponse.cs @@ -8,11 +8,11 @@ namespace GoFile_DL.Entities { public class CreateAccountResponse { - public string status { get; set; } - public Data data { get; set; } + public string? status { get; set; } + public Data? data { get; set; } public class Data { - public string token { get; set; } + public string? token { get; set; } } } } diff --git a/GoFile DL/Entities/File.cs b/GoFile DL/Entities/File.cs index 4fd97e0..a5d62ba 100644 --- a/GoFile DL/Entities/File.cs +++ b/GoFile DL/Entities/File.cs @@ -8,10 +8,10 @@ namespace GoFile_DL.Entities { public class File { - public string Id { get; set; } - public string Name { get; set; } - public string DownloadLink { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } + public string? DownloadLink { get; set; } public long Size { get; set; } - public string MD5Hash { get; set; } + public string? MD5Hash { get; set; } } } diff --git a/GoFile DL/Entities/Folder.cs b/GoFile DL/Entities/Folder.cs index cc34f00..4299794 100644 --- a/GoFile DL/Entities/Folder.cs +++ b/GoFile DL/Entities/Folder.cs @@ -8,11 +8,11 @@ namespace GoFile_DL.Entities { public class Folder { - public string Id { get; set; } - public string Name { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } public List Folders { get; set; } public List Files { get; set; } - public string DownloadPath { get; set; } + public string? DownloadPath { get; set; } public Folder() { Folders = new List(); @@ -21,13 +21,16 @@ public Folder() public async Task IterateFoldersAsync(Func folderActionAsync, string currentPath) { - string folderPath = Path.Combine(currentPath, Name); + if(!string.IsNullOrEmpty(Name)) + { + string folderPath = Path.Combine(currentPath, Name); - await folderActionAsync(this, folderPath); + await folderActionAsync(this, folderPath); - foreach (var subfolder in Folders) - { - await subfolder.IterateFoldersAsync(folderActionAsync, folderPath); + foreach (var subfolder in Folders) + { + await subfolder.IterateFoldersAsync(folderActionAsync, folderPath); + } } } } diff --git a/GoFile DL/Entities/GetContentResponse.cs b/GoFile DL/Entities/GetContentResponse.cs index 9a3e688..3901cd6 100644 --- a/GoFile DL/Entities/GetContentResponse.cs +++ b/GoFile DL/Entities/GetContentResponse.cs @@ -8,40 +8,40 @@ namespace GoFile_DL.Entities { public class GetContentResponse { - public string status { get; set; } - public Data data { get; set; } + public string? status { get; set; } + public Data? data { get; set; } public class Data { public bool isOwner { get; set; } - public string id { get; set; } - public string type { get; set; } - public string name { get; set; } - public string parentFolder { get; set; } - public string code { get; set; } + public string? id { get; set; } + public string? type { get; set; } + public string? name { get; set; } + public string? parentFolder { get; set; } + public string? code { get; set; } public long createTime { get; set; } public bool @public { get; set; } - public List childs { get; set; } + public List? childs { get; set; } public int totalDownloadCount { get; set; } public long totalSize { get; set; } - public Dictionary contents { get; set; } + public Dictionary? contents { get; set; } } public class Content { - public string id { get; set; } - public string type { get; set; } - public string name { get; set; } - public string parentFolder { get; set; } + public string? id { get; set; } + public string? type { get; set; } + public string? name { get; set; } + public string? parentFolder { get; set; } public long createTime { get; set; } - public List childs { get; set; } - public string code { get; set; } + public List? childs { get; set; } + public string? code { get; set; } public bool @public { get; set; } public long size { get; set; } public int downloadCount { get; set; } - public string md5 { get; set; } - public string mimetype { get; set; } - public string serverChoosen { get; set; } - public string link { get; set; } + public string? md5 { get; set; } + public string? mimetype { get; set; } + public string? serverChoosen { get; set; } + public string? link { get; set; } public bool overloaded { get; set; } } } diff --git a/GoFile DL/Helpers/APIHelper.cs b/GoFile DL/Helpers/APIHelper.cs index 9f5949f..a8b185c 100644 --- a/GoFile DL/Helpers/APIHelper.cs +++ b/GoFile DL/Helpers/APIHelper.cs @@ -20,8 +20,8 @@ public class APIHelper : IAPIHelper { response.EnsureSuccessStatusCode(); string body = await response.Content.ReadAsStringAsync(); - CreateAccountResponse account = JsonConvert.DeserializeObject(body); - if (account != null && account.status == "ok") + CreateAccountResponse? account = JsonConvert.DeserializeObject(body); + if (account != null && account.data != null && account.data.token != null && account.status == "ok") { return account.data.token; } @@ -76,27 +76,30 @@ public class APIHelper : IAPIHelper { try { - Dictionary getParams = new() + if(config != null && !string.IsNullOrEmpty(config.Token) && !string.IsNullOrEmpty(config.SiteToken)) { - { "contentId", contentId }, - { "token", config.Token }, - { "websiteToken", config.SiteToken } - }; - string queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); - HttpClient client = new HttpClient(); - HttpRequestMessage request = new HttpRequestMessage - { - Method = HttpMethod.Get, - RequestUri = new Uri("https://api.gofile.io/getContent" + queryParams) - }; - using (var response = await client.SendAsync(request)) - { - response.EnsureSuccessStatusCode(); - string body = await response.Content.ReadAsStringAsync(); - GetContentResponse content = JsonConvert.DeserializeObject(body); - if(content != null) + Dictionary getParams = new() + { + { "contentId", contentId }, + { "token", config.Token }, + { "websiteToken", config.SiteToken } + }; + string queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); + HttpClient client = new HttpClient(); + HttpRequestMessage request = new HttpRequestMessage { - return content; + Method = HttpMethod.Get, + RequestUri = new Uri("https://api.gofile.io/getContent" + queryParams) + }; + using (var response = await client.SendAsync(request)) + { + response.EnsureSuccessStatusCode(); + string body = await response.Content.ReadAsStringAsync(); + GetContentResponse? content = JsonConvert.DeserializeObject(body); + if (content != null) + { + return content; + } } } } @@ -110,28 +113,31 @@ public class APIHelper : IAPIHelper { try { - Dictionary getParams = new() + if(config != null && !string.IsNullOrEmpty(config.Token) && !string.IsNullOrEmpty(config.SiteToken)) { - { "contentId", contentId }, - { "token", config.Token }, - { "websiteToken", config.SiteToken }, - { "password", password } - }; - string queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); - HttpClient client = new HttpClient(); - HttpRequestMessage request = new HttpRequestMessage - { - Method = HttpMethod.Get, - RequestUri = new Uri("https://api.gofile.io/getContent" + queryParams) - }; - using (var response = await client.SendAsync(request)) - { - response.EnsureSuccessStatusCode(); - string body = await response.Content.ReadAsStringAsync(); - GetContentResponse content = JsonConvert.DeserializeObject(body); - if (content != null) + Dictionary getParams = new() + { + { "contentId", contentId }, + { "token", config.Token }, + { "websiteToken", config.SiteToken }, + { "password", password } + }; + string queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); + HttpClient client = new HttpClient(); + HttpRequestMessage request = new HttpRequestMessage { - return content; + Method = HttpMethod.Get, + RequestUri = new Uri("https://api.gofile.io/getContent" + queryParams) + }; + using (var response = await client.SendAsync(request)) + { + response.EnsureSuccessStatusCode(); + string body = await response.Content.ReadAsStringAsync(); + GetContentResponse? content = JsonConvert.DeserializeObject(body); + if (content != null) + { + return content; + } } } } diff --git a/GoFile DL/Helpers/APIParser.cs b/GoFile DL/Helpers/APIParser.cs index 852722c..d19ccaf 100644 --- a/GoFile DL/Helpers/APIParser.cs +++ b/GoFile DL/Helpers/APIParser.cs @@ -15,18 +15,21 @@ static APIParser() } public async Task ParseApiResponse(GetContentResponse response, Config config) { - Folder rootFolder = new Folder + if(response != null && response.data != null && response.data.contents != null) { - Id = response.data.id, - Name = response.data.name, - Folders = new List(), - Files = new List() - }; + Folder? rootFolder = new Folder + { + Id = response.data.id, + Name = response.data.name, + Folders = new List(), + Files = new List() + }; - // Recursively parse contents - await ParseContents(response.data.contents, rootFolder.Folders, rootFolder.Files, config); + await ParseContents(response.data.contents, rootFolder.Folders, rootFolder.Files, config); - return rootFolder; + return rootFolder; + } + return new Folder(); } public async Task ParseContents(Dictionary contents, List folders, List files, Config config) @@ -44,9 +47,14 @@ public async Task ParseContents(Dictionary c }; folders.Add(folder); - // Fetch folder content dynamically - var folderContentResponse = await FetchFolderContentAsync(content.name, content.id, config); // Implement this method to make the API request - await ParseContents(folderContentResponse.data.contents, folder.Folders, folder.Files, config); + if(content != null && content.name != null && content.id != null) + { + GetContentResponse? folderContentResponse = await FetchFolderContentAsync(content.name, content.id, config); + if (folderContentResponse != null && folderContentResponse.data != null && folderContentResponse.data.contents != null) + { + await ParseContents(folderContentResponse.data.contents, folder.Folders, folder.Files, config); + } + } } else if (content.type == "file") { @@ -63,9 +71,9 @@ public async Task ParseContents(Dictionary c } } - private async Task FetchFolderContentAsync(string folderName, string folderId, Config config) + private async Task FetchFolderContentAsync(string folderName, string folderId, Config config) { - GetContentResponse getContentResponse = await aPIHelper.GetContent(folderId, config); + GetContentResponse? getContentResponse = await aPIHelper.GetContent(folderId, config); if (getContentResponse != null && getContentResponse.status == "ok") { return getContentResponse; diff --git a/GoFile DL/Program.cs b/GoFile DL/Program.cs index 2cca45c..689caac 100644 --- a/GoFile DL/Program.cs +++ b/GoFile DL/Program.cs @@ -37,7 +37,7 @@ public static async Task Main() UpdateConfig(); } - string siteToken = await aPIHelper.GetSiteToken(); + string? siteToken = await aPIHelper.GetSiteToken(); if(Config != null && Config.Token != siteToken) { Config.SiteToken = siteToken; @@ -67,144 +67,151 @@ public static async Task Main() break; } } while (true); - - } public static async Task SingleURLDownload() { try { - string inputUrl = AnsiConsole.Prompt( - new TextPrompt("[red]Please enter a GoFile URL: [/]") - .ValidationErrorMessage("[red]Please enter a valid GoFile link[/]") - .Validate(url => - { - Regex regex = new Regex("https://gofile\\.io/d/([A-Za-z]+)", RegexOptions.IgnoreCase); - if (regex.IsMatch(url)) - { - return ValidationResult.Success(); - } - return ValidationResult.Error("[red]Please enter a valid GoFile link[/]"); - })); - - GetContentResponse? getContentResponse = await aPIHelper.GetContent(GetCode(inputUrl), Config); - if (getContentResponse != null && getContentResponse.status == "ok") + if(Config != null) { - Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponse, Config); - if (!Path.Exists("Downloads")) - { - Directory.CreateDirectory("Downloads"); - } - - HttpClient client = CreateHttpClient(Config.Token); + string inputUrl = AnsiConsole.Prompt( + new TextPrompt("[red]Please enter a GoFile URL: [/]") + .ValidationErrorMessage("[red]Please enter a valid GoFile link[/]") + .Validate(url => + { + Regex regex = new Regex("https://gofile\\.io/d/([A-Za-z]+)", RegexOptions.IgnoreCase); + if (regex.IsMatch(url)) + { + return ValidationResult.Success(); + } + return ValidationResult.Error("[red]Please enter a valid GoFile link[/]"); + })); - await rootFolder.IterateFoldersAsync(async (folder, folderPath) => + GetContentResponse? getContentResponse = await aPIHelper.GetContent(GetCode(inputUrl), Config); + if (getContentResponse != null && getContentResponse.status == "ok" && Config != null && !string.IsNullOrEmpty(Config.Token) && !string.IsNullOrEmpty(Config.SiteToken)) { - if (!Directory.Exists(folderPath)) + Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponse, Config); + if (!Path.Exists("Downloads")) { - Directory.CreateDirectory(folderPath); + Directory.CreateDirectory("Downloads"); } - if (folder.Files.Count > 0) - { - AnsiConsole.Markup($"[red]Downloading Content for Folder - {folder.Name}[/]"); - } + HttpClient client = CreateHttpClient(Config.Token); - foreach (Entities.File file in folder.Files) + await rootFolder.IterateFoldersAsync(async (folder, folderPath) => { - await AnsiConsole.Progress() - .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) - .StartAsync(async ctx => - { - var downloadTask = ctx.AddTask($"[red]{folderPath.Replace("\\", "/")}/{file.Name}[/]"); - downloadTask.MaxValue = file.Size; + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } - bool downloadSuccessful = false; + if (folder.Files.Count > 0) + { + AnsiConsole.Markup($"[red]Downloading Content for Folder - {folder.Name}[/]"); + } - do + foreach (Entities.File file in folder.Files) + { + if(file != null && file.Name != null && file.DownloadLink != null && file.MD5Hash != null) + { + await AnsiConsole.Progress() + .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) + .StartAsync(async ctx => { - await DownloadHelper.DownloadFile(folderPath, file.Name, file.DownloadLink, client, downloadTask); + var downloadTask = ctx.AddTask($"[red]{folderPath.Replace("\\", "/")}/{file.Name}[/]"); + downloadTask.MaxValue = file.Size; - bool isMD5Valid = DownloadHelper.VerifyMD5(folderPath + "/" + file.Name, file.MD5Hash); + bool downloadSuccessful = false; - if (isMD5Valid) - { - downloadSuccessful = true; - } - else + do { - AnsiConsole.Markup($"MD5 hash check failed for {file.Name}. Retrying download..."); - System.IO.File.Delete(folderPath + "/" + file.Name); - } + await DownloadHelper.DownloadFile(folderPath, file.Name, file.DownloadLink, client, downloadTask); - } while (!downloadSuccessful); - }); - } - }, "Downloads"); - } - else if (getContentResponse != null && getContentResponse.status == "error-passwordRequired") - { - AnsiConsole.Markup($"[red]Base Folder is password protected\n[/]"); - while (true) - { - string inputPassword = AnsiConsole.Prompt(new TextPrompt("[red]Enter Password: [/]")); - string hashedPassword = PasswordHelper.ComputeSHA256Hash(inputPassword); - GetContentResponse? getContentResponseWithPassword = await aPIHelper.GetContentWithPassword(GetCode(inputUrl), hashedPassword, Config); - if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "ok") - { - Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponseWithPassword, Config); - if (!Path.Exists("Downloads")) - { - Directory.CreateDirectory("Downloads"); - } + bool isMD5Valid = DownloadHelper.VerifyMD5(folderPath + "/" + file.Name, file.MD5Hash); - HttpClient client = CreateHttpClient(Config.Token); + if (isMD5Valid) + { + downloadSuccessful = true; + } + else + { + AnsiConsole.Markup($"MD5 hash check failed for {file.Name}. Retrying download..."); + System.IO.File.Delete(folderPath + "/" + file.Name); + } - await rootFolder.IterateFoldersAsync(async (folder, folderPath) => + } while (!downloadSuccessful); + }); + } + } + }, "Downloads"); + } + else if (getContentResponse != null && getContentResponse.status == "error-passwordRequired" && Config != null && !string.IsNullOrEmpty(Config.Token)) + { + AnsiConsole.Markup($"[red]Base Folder is password protected\n[/]"); + while (true) + { + string inputPassword = AnsiConsole.Prompt(new TextPrompt("[red]Enter Password: [/]")); + string hashedPassword = PasswordHelper.ComputeSHA256Hash(inputPassword); + GetContentResponse? getContentResponseWithPassword = await aPIHelper.GetContentWithPassword(GetCode(inputUrl), hashedPassword, Config); + if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "ok") { - if (!Directory.Exists(folderPath)) + Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponseWithPassword, Config); + if (!Path.Exists("Downloads")) { - Directory.CreateDirectory(folderPath); + Directory.CreateDirectory("Downloads"); } - foreach (Entities.File file in folder.Files) + HttpClient client = CreateHttpClient(Config.Token); + + await rootFolder.IterateFoldersAsync(async (folder, folderPath) => { - await AnsiConsole.Progress() - .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) - .StartAsync(async ctx => + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + + foreach (Entities.File file in folder.Files) + { + if (file != null && file.Name != null && file.DownloadLink != null && file.MD5Hash != null) { - var downloadTask = ctx.AddTask($"[red]{folderPath.Replace("\\", "/")}/{file.Name}[/]"); - downloadTask.MaxValue = file.Size; + await AnsiConsole.Progress() + .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) + .StartAsync(async ctx => + { + var downloadTask = ctx.AddTask($"[red]{folderPath.Replace("\\", "/")}/{file.Name}[/]"); + downloadTask.MaxValue = file.Size; - bool downloadSuccessful = false; + bool downloadSuccessful = false; - do - { - await DownloadHelper.DownloadFile(folderPath, file.Name, file.DownloadLink, client, downloadTask); + do + { + await DownloadHelper.DownloadFile(folderPath, file.Name, file.DownloadLink, client, downloadTask); - bool isMD5Valid = DownloadHelper.VerifyMD5(folderPath + "/" + file.Name, file.MD5Hash); + bool isMD5Valid = DownloadHelper.VerifyMD5(folderPath + "/" + file.Name, file.MD5Hash); - if (isMD5Valid) - { - downloadSuccessful = true; - } - else - { - AnsiConsole.Markup($"MD5 hash check failed for {file.Name}. Retrying download..."); - System.IO.File.Delete(folderPath + "/" + file.Name); - } + if (isMD5Valid) + { + downloadSuccessful = true; + } + else + { + AnsiConsole.Markup($"MD5 hash check failed for {file.Name}. Retrying download..."); + System.IO.File.Delete(folderPath + "/" + file.Name); + } - } while (!downloadSuccessful); - }); - } - }, "Downloads"); - break; - } - else if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "error-passwordWrong") - { - AnsiConsole.Markup("[red]Password is incorrect, please try again\n[/]"); - continue; + } while (!downloadSuccessful); + }); + } + } + }, "Downloads"); + break; + } + else if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "error-passwordWrong") + { + AnsiConsole.Markup("[red]Password is incorrect, please try again\n[/]"); + continue; + } } } } @@ -224,96 +231,43 @@ public static async Task BatchURLDownload() { try { - using (StreamReader sr = new StreamReader("Links.txt")) + if(Config != null && !string.IsNullOrEmpty(Config.Token)) { - string line; - - while ((line = sr.ReadLine()) != null) + using (StreamReader sr = new StreamReader("Links.txt")) { - Regex regex = new Regex("https://gofile\\.io/d/([A-Za-z]+)", RegexOptions.IgnoreCase); - if (regex.IsMatch(line)) + string? line; + + while ((line = sr.ReadLine()) != null) { - GetContentResponse? getContentResponse = await aPIHelper.GetContent(GetCode(line), Config); - if (getContentResponse != null && getContentResponse.status == "ok") + Regex regex = new Regex("https://gofile\\.io/d/([A-Za-z]+)", RegexOptions.IgnoreCase); + if (regex.IsMatch(line)) { - Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponse, Config); - if (!Path.Exists("Downloads")) - { - Directory.CreateDirectory("Downloads"); - } - - HttpClient client = CreateHttpClient(Config.Token); - - await rootFolder.IterateFoldersAsync(async (folder, folderPath) => + GetContentResponse? getContentResponse = await aPIHelper.GetContent(GetCode(line), Config); + if (getContentResponse != null && getContentResponse.status == "ok") { - if (!Directory.Exists(folderPath)) + Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponse, Config); + if (!Path.Exists("Downloads")) { - Directory.CreateDirectory(folderPath); + Directory.CreateDirectory("Downloads"); } - if (folder.Files.Count > 0) - { - AnsiConsole.Markup($"[red]Downloading Content for Folder - {folder.Name}[/]"); - } + HttpClient client = CreateHttpClient(Config.Token); - foreach (Entities.File file in folder.Files) + await rootFolder.IterateFoldersAsync(async (folder, folderPath) => { - await AnsiConsole.Progress() - .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) - .StartAsync(async ctx => - { - var downloadTask = ctx.AddTask($"[red]{folderPath.Replace("\\", "/")}/{file.Name}[/]"); - downloadTask.MaxValue = file.Size; - - bool downloadSuccessful = false; - - do - { - await DownloadHelper.DownloadFile(folderPath, file.Name, file.DownloadLink, client, downloadTask); - - bool isMD5Valid = DownloadHelper.VerifyMD5(folderPath + "/" + file.Name, file.MD5Hash); - - if (isMD5Valid) - { - downloadSuccessful = true; - } - else - { - AnsiConsole.Markup($"MD5 hash check failed for {file.Name}. Retrying download..."); - System.IO.File.Delete(folderPath + "/" + file.Name); - } - - } while (!downloadSuccessful); - }); - } - }, "Downloads"); - } - else if (getContentResponse != null && getContentResponse.status == "error-passwordRequired") - { - AnsiConsole.Markup($"[red]Base Folder is password protected\n[/]"); - while (true) - { - string inputPassword = AnsiConsole.Prompt(new TextPrompt("[red]Enter Password: [/]")); - string hashedPassword = PasswordHelper.ComputeSHA256Hash(inputPassword); - GetContentResponse? getContentResponseWithPassword = await aPIHelper.GetContentWithPassword(GetCode(line), hashedPassword, Config); - if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "ok") - { - Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponseWithPassword, Config); - if (!Path.Exists("Downloads")) + if (!Directory.Exists(folderPath)) { - Directory.CreateDirectory("Downloads"); + Directory.CreateDirectory(folderPath); } - HttpClient client = CreateHttpClient(Config.Token); - - await rootFolder.IterateFoldersAsync(async (folder, folderPath) => + if (folder.Files.Count > 0) { - if (!Directory.Exists(folderPath)) - { - Directory.CreateDirectory(folderPath); - } + AnsiConsole.Markup($"[red]Downloading Content for Folder - {folder.Name}[/]"); + } - foreach (Entities.File file in folder.Files) + foreach (Entities.File file in folder.Files) + { + if (file != null && file.Name != null && file.DownloadLink != null && file.MD5Hash != null) { await AnsiConsole.Progress() .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) @@ -343,20 +297,82 @@ await AnsiConsole.Progress() } while (!downloadSuccessful); }); } - }, "Downloads"); - break; - } - else if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "error-passwordWrong") + } + }, "Downloads"); + } + else if (getContentResponse != null && getContentResponse.status == "error-passwordRequired") + { + AnsiConsole.Markup($"[red]Base Folder is password protected\n[/]"); + while (true) { - AnsiConsole.Markup("[red]Password is incorrect, please try again\n[/]"); - continue; + string inputPassword = AnsiConsole.Prompt(new TextPrompt("[red]Enter Password: [/]")); + string hashedPassword = PasswordHelper.ComputeSHA256Hash(inputPassword); + GetContentResponse? getContentResponseWithPassword = await aPIHelper.GetContentWithPassword(GetCode(line), hashedPassword, Config); + if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "ok") + { + Folder rootFolder = await aPIParser.ParseApiResponse(getContentResponseWithPassword, Config); + if (!Path.Exists("Downloads")) + { + Directory.CreateDirectory("Downloads"); + } + + HttpClient client = CreateHttpClient(Config.Token); + + await rootFolder.IterateFoldersAsync(async (folder, folderPath) => + { + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + + foreach (Entities.File file in folder.Files) + { + if (file != null && file.Name != null && file.DownloadLink != null && file.MD5Hash != null) + { + await AnsiConsole.Progress() + .Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn()) + .StartAsync(async ctx => + { + var downloadTask = ctx.AddTask($"[red]{folderPath.Replace("\\", "/")}/{file.Name}[/]"); + downloadTask.MaxValue = file.Size; + + bool downloadSuccessful = false; + + do + { + await DownloadHelper.DownloadFile(folderPath, file.Name, file.DownloadLink, client, downloadTask); + + bool isMD5Valid = DownloadHelper.VerifyMD5(folderPath + "/" + file.Name, file.MD5Hash); + + if (isMD5Valid) + { + downloadSuccessful = true; + } + else + { + AnsiConsole.Markup($"MD5 hash check failed for {file.Name}. Retrying download..."); + System.IO.File.Delete(folderPath + "/" + file.Name); + } + + } while (!downloadSuccessful); + }); + } + } + }, "Downloads"); + break; + } + else if (getContentResponseWithPassword != null && getContentResponseWithPassword.status == "error-passwordWrong") + { + AnsiConsole.Markup("[red]Password is incorrect, please try again\n[/]"); + continue; + } } } } - } - else - { - AnsiConsole.Markup($"[red]{line} is not a valid GoFile URL\n[/]"); + else + { + AnsiConsole.Markup($"[red]{line} is not a valid GoFile URL\n[/]"); + } } } }