From 71d1cd0e7f26c9c8555cb776b3da3b9b28cf2cdf Mon Sep 17 00:00:00 2001 From: ahjephson Date: Fri, 1 Nov 2024 22:04:10 +0000 Subject: [PATCH] Fix onlongtouch after refactor --- .../Dialogs/RenameFilesDialog.razor | 50 +++++++- .../Dialogs/RenameFilesDialog.razor.cs | 103 +++++++++++++-- Lantean.QBTMud/Components/FiltersNav.razor.cs | 1 - .../Components/TorrentActions.razor.cs | 38 ++++-- .../Components/UI/ContextMenu.razor.cs | 3 +- .../Components/UI/CustomNavLink.razor.cs | 3 +- .../Components/UI/DynamicTable.razor.cs | 1 - .../UI/TableDataLongPressEventArgs.cs | 3 +- .../Components/UI/TdExtended.razor.cs | 3 +- Lantean.QBTMud/EventHandlers/EventHandlers.cs | 2 +- .../EventHandlers/LongPressEventArgs.cs | 2 +- Lantean.QBTMud/Helpers/DialogHelper.cs | 86 +++++++------ Lantean.QBTMud/Lantean.QBTMud.csproj | 2 +- Lantean.QBTMud/Models/TorrentOptions.cs | 11 +- Lantean.QBTMud/Pages/Login.razor.cs | 2 +- ...module.js => Lantean.QBTMud.lib.module.js} | 0 Lantean.QBitTorrentClient/ApiClient.cs | 121 +++++++++++------- Lantean.QBitTorrentClient/IApiClient.cs | 8 +- .../Models/AddTorrentParams.cs | 54 ++++++++ .../Models/ShareLimitAction.cs | 12 ++ .../Models/StopCondition.cs | 9 ++ .../Models/TorrentContentLayout.cs | 9 ++ .../MultipartFormDataContentExtensions.cs | 5 + 23 files changed, 406 insertions(+), 122 deletions(-) rename Lantean.QBTMud/wwwroot/{Lantean.QBTMudBlade.lib.module.js => Lantean.QBTMud.lib.module.js} (100%) create mode 100644 Lantean.QBitTorrentClient/Models/AddTorrentParams.cs create mode 100644 Lantean.QBitTorrentClient/Models/ShareLimitAction.cs create mode 100644 Lantean.QBitTorrentClient/Models/StopCondition.cs create mode 100644 Lantean.QBitTorrentClient/Models/TorrentContentLayout.cs diff --git a/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor b/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor index 0de18b2..7dafb6d 100644 --- a/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor +++ b/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor @@ -1,7 +1,53 @@  - + + + + + + + + + + + + + + + + + + + + + + + + Filename + Extension + Filename + Extension + + + + + + + + + + + + + + + Replace + Replace all + + + + + Close - Rename + @(ReplaceAll ? "Replace all" : "Replace") diff --git a/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor.cs b/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor.cs index 3eab22f..9ab5b8d 100644 --- a/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor.cs +++ b/Lantean.QBTMud/Components/Dialogs/RenameFilesDialog.razor.cs @@ -6,6 +6,7 @@ using Lantean.QBTMud.Services; using Microsoft.AspNetCore.Components; using MudBlazor; using System.Collections.ObjectModel; +using static MudBlazor.Colors; namespace Lantean.QBTMud.Components.Dialogs { @@ -51,6 +52,11 @@ namespace Lantean.QBTMud.Components.Dialogs private ReadOnlyCollection GetFiles() { + if (!FileList.Any()) + { + return new ReadOnlyCollection([]); + } + var maxLevel = FileList.Max(f => f.Level); // this is a flat file structure if (maxLevel == 0) @@ -321,65 +327,107 @@ namespace Lantean.QBTMud.Components.Dialogs protected bool UseRegex { get; set; } - protected void UseRegexChanged(bool value) + protected async Task UseRegexChanged(bool value) { UseRegex = value; + + await UpdatePreferences(p => p.UseRegex = value); } protected bool MatchAllOccurrences { get; set; } - protected void MatchAllOccurrencesChanged(bool value) + protected async Task MatchAllOccurrencesChanged(bool value) { MatchAllOccurrences = value; + + await UpdatePreferences(p => p.MatchAllOccurrences = value); } protected bool CaseSensitive { get; set; } - protected void CaseSensitiveChanged(bool value) + protected async Task CaseSensitiveChanged(bool value) { CaseSensitive = value; + + await UpdatePreferences(p => p.CaseSensitive = value); } protected string Replacement { get; set; } = ""; - protected void ReplacementChanged(string value) + protected async Task ReplacementChanged(string value) { Replacement = value; + + await UpdatePreferences(p => p.Replace = value); } protected AppliesTo AppliesToValue { get; set; } = AppliesTo.FilenameExtension; - protected void AppliesToChanged(AppliesTo value) + protected async Task AppliesToChanged(AppliesTo value) { AppliesToValue = value; + + await UpdatePreferences(p => p.AppliesTo = value); } protected bool IncludeFiles { get; set; } = true; - protected void IncludeFilesChanged(bool value) + protected async Task IncludeFilesChanged(bool value) { IncludeFiles = value; + + await UpdatePreferences(p => p.IncludeFiles = value); } protected bool IncludeFolders { get; set; } - protected void IncludeFoldersChanged(bool value) + protected async Task IncludeFoldersChanged(bool value) { IncludeFolders = value; + + await UpdatePreferences(p => p.IncludeFolders = value); } protected int FileEnumerationStart { get; set; } - protected void FileEnumerationStartChanged(int value) + protected async Task FileEnumerationStartChanged(int value) { FileEnumerationStart = value; + + await UpdatePreferences(p => p.FileEnumerationStart = value); } protected bool ReplaceAll { get; set; } - protected void ReplaceAllChanged(bool value) + protected async Task ReplaceAllChanged(bool value) { ReplaceAll = value; + + await UpdatePreferences(p => p.ReplaceAll = value); + } + + protected bool RememberMultiRenameSettings { get; set; } + + protected async Task RememberMultiRenameSettingsChanged(bool value) + { + RememberMultiRenameSettings = value; + + await UpdatePreferences(p => p.RememberPreferences = value); + } + + private async Task UpdatePreferences(Action updateAction) + { + var preferences = await LocalStorage.GetItemAsync(_preferencesStorageKey) ?? new(); + updateAction(preferences); + if (preferences.RememberPreferences) + { + await LocalStorage.SetItemAsync(_preferencesStorageKey, preferences); + } + else + { + await LocalStorage.RemoveItemAsync(_preferencesStorageKey); + } + } protected override async Task OnInitializedAsync() @@ -414,8 +462,43 @@ namespace Lantean.QBTMud.Components.Dialogs MudDialog.Cancel(); } - protected void Submit() + protected async Task Submit() { + if (Hash is null) + { + MudDialog.Close(); + + return; + } + + var renamedFiles = FileNameMatcher.GetRenamedFiles( + SelectedItems, + Search, + UseRegex, + Replacement, + MatchAllOccurrences, + CaseSensitive, + AppliesToValue, + IncludeFiles, + IncludeFolders, + ReplaceAll, + FileEnumerationStart); + + foreach (var (_, renamedFile) in renamedFiles) + { + var oldPath = renamedFile.Path + renamedFile.OriginalName; + var newPath = renamedFile.Path + renamedFile.NewName; + if (renamedFile.IsFolder) + { + + await ApiClient.RenameFolder(Hash, oldPath, newPath); + } + else + { + await ApiClient.RenameFile(Hash, oldPath, newPath); + } + } + MudDialog.Close(); } diff --git a/Lantean.QBTMud/Components/FiltersNav.razor.cs b/Lantean.QBTMud/Components/FiltersNav.razor.cs index 4256982..090edc4 100644 --- a/Lantean.QBTMud/Components/FiltersNav.razor.cs +++ b/Lantean.QBTMud/Components/FiltersNav.razor.cs @@ -1,7 +1,6 @@ using Blazored.LocalStorage; using Lantean.QBitTorrentClient; using Lantean.QBTMud.Components.UI; -using Lantean.QBTMud.EventHandlers; using Lantean.QBTMud.Helpers; using Lantean.QBTMud.Models; using Microsoft.AspNetCore.Components; diff --git a/Lantean.QBTMud/Components/TorrentActions.razor.cs b/Lantean.QBTMud/Components/TorrentActions.razor.cs index 8aa64df..b989730 100644 --- a/Lantean.QBTMud/Components/TorrentActions.razor.cs +++ b/Lantean.QBTMud/Components/TorrentActions.razor.cs @@ -109,7 +109,7 @@ namespace Lantean.QBTMud.Components new("delete", "Remove", Icons.Material.Filled.Delete, Color.Error, CreateCallback(Remove), separatorBefore: true), new("setLocation", "Set location", Icons.Material.Filled.MyLocation, Color.Info, CreateCallback(SetLocation), separatorBefore: true), new("rename", "Rename", Icons.Material.Filled.DriveFileRenameOutline, Color.Info, CreateCallback(Rename)), - new("renameFiles", "Rename files", Icons.Material.Filled.DriveFileRenameOutline, Color.Warning, CreateCallback(Rename)), + new("renameFiles", "Rename files", Icons.Material.Filled.DriveFileRenameOutline, Color.Warning, CreateCallback(RenameFiles)), new("category", "Category", Icons.Material.Filled.List, Color.Info, CreateCallback(ShowCategories)), new("tags", "Tags", Icons.Material.Filled.Label, Color.Info, CreateCallback(ShowTags)), new("autoTorrentManagement", "Automatic Torrent Management", Icons.Material.Filled.Check, Color.Info, CreateCallback(ToggleAutoTMM)), @@ -174,14 +174,30 @@ namespace Lantean.QBTMud.Components protected async Task Pause() { - await ApiClient.PauseTorrents(Hashes); - Snackbar.Add("Torrent paused."); + if (MajorVersion < 5) + { + await ApiClient.PauseTorrents(Hashes); + Snackbar.Add("Torrent paused."); + } + else + { + await ApiClient.StopTorrents(Hashes); + Snackbar.Add("Torrent stopped."); + } } protected async Task Resume() { - await ApiClient.ResumeTorrents(Hashes); - Snackbar.Add("Torrent resumed."); + if (MajorVersion < 5) + { + await ApiClient.ResumeTorrents(Hashes); + Snackbar.Add("Torrent resumed."); + } + else + { + await ApiClient.StartTorrents(Hashes); + Snackbar.Add("Torrent started."); + } } protected async Task ForceStart() @@ -298,7 +314,7 @@ namespace Lantean.QBTMud.Components protected async Task MoveToTop() { - await ApiClient.MaximalTorrentPriority(null, Hashes.ToArray()); + await ApiClient.MaxTorrentPriority(null, Hashes.ToArray()); } protected async Task MoveUp() @@ -313,7 +329,7 @@ namespace Lantean.QBTMud.Components protected async Task MoveToBottom() { - await ApiClient.MinimalTorrentPriority(null, Hashes.ToArray()); + await ApiClient.MinTorrentPriority(null, Hashes.ToArray()); } protected async Task Copy(string value) @@ -557,18 +573,18 @@ namespace Lantean.QBTMud.Components if (MajorVersion >= 5) { - if (actionStates.ContainsKey("start")) + if (actionStates.TryGetValue("start", out ActionState? startActionState)) { - actionStates["start"].TextOverride = "Start"; + startActionState.TextOverride = "Start"; } else { actionStates["start"] = new ActionState { TextOverride = "Start" }; } - if (actionStates.ContainsKey("pause")) + if (actionStates.TryGetValue("pause", out ActionState? stopActionState)) { - actionStates["pause"].TextOverride = "Stop"; + stopActionState.TextOverride = "Stop"; } else { diff --git a/Lantean.QBTMud/Components/UI/ContextMenu.razor.cs b/Lantean.QBTMud/Components/UI/ContextMenu.razor.cs index 57d49d9..981a12f 100644 --- a/Lantean.QBTMud/Components/UI/ContextMenu.razor.cs +++ b/Lantean.QBTMud/Components/UI/ContextMenu.razor.cs @@ -1,5 +1,4 @@ -using Lantean.QBTMud.EventHandlers; -using Lantean.QBTMud.Interop; +using Lantean.QBTMud.Interop; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Microsoft.JSInterop; diff --git a/Lantean.QBTMud/Components/UI/CustomNavLink.razor.cs b/Lantean.QBTMud/Components/UI/CustomNavLink.razor.cs index f2ff61a..23e3bf1 100644 --- a/Lantean.QBTMud/Components/UI/CustomNavLink.razor.cs +++ b/Lantean.QBTMud/Components/UI/CustomNavLink.razor.cs @@ -1,5 +1,4 @@ -using Lantean.QBTMud.EventHandlers; -using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; using MudBlazor.Utilities; diff --git a/Lantean.QBTMud/Components/UI/DynamicTable.razor.cs b/Lantean.QBTMud/Components/UI/DynamicTable.razor.cs index 696e604..a8707d2 100644 --- a/Lantean.QBTMud/Components/UI/DynamicTable.razor.cs +++ b/Lantean.QBTMud/Components/UI/DynamicTable.razor.cs @@ -1,5 +1,4 @@ using Blazored.LocalStorage; -using Lantean.QBTMud.EventHandlers; using Lantean.QBTMud.Helpers; using Lantean.QBTMud.Models; using Microsoft.AspNetCore.Components; diff --git a/Lantean.QBTMud/Components/UI/TableDataLongPressEventArgs.cs b/Lantean.QBTMud/Components/UI/TableDataLongPressEventArgs.cs index 94601a0..d0fe205 100644 --- a/Lantean.QBTMud/Components/UI/TableDataLongPressEventArgs.cs +++ b/Lantean.QBTMud/Components/UI/TableDataLongPressEventArgs.cs @@ -1,5 +1,4 @@ -using Lantean.QBTMud.EventHandlers; -using MudBlazor; +using MudBlazor; namespace Lantean.QBTMud.Components.UI { diff --git a/Lantean.QBTMud/Components/UI/TdExtended.razor.cs b/Lantean.QBTMud/Components/UI/TdExtended.razor.cs index 7d958f6..cffe7c9 100644 --- a/Lantean.QBTMud/Components/UI/TdExtended.razor.cs +++ b/Lantean.QBTMud/Components/UI/TdExtended.razor.cs @@ -1,5 +1,4 @@ -using Lantean.QBTMud.EventHandlers; -using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using MudBlazor; diff --git a/Lantean.QBTMud/EventHandlers/EventHandlers.cs b/Lantean.QBTMud/EventHandlers/EventHandlers.cs index cdfad75..65c7e77 100644 --- a/Lantean.QBTMud/EventHandlers/EventHandlers.cs +++ b/Lantean.QBTMud/EventHandlers/EventHandlers.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Components; -namespace Lantean.QBTMud.EventHandlers +namespace Lantean.QBTMud { [EventHandler("onlongpress", typeof(LongPressEventArgs), enableStopPropagation: true, enablePreventDefault: true)] public static class EventHandlers diff --git a/Lantean.QBTMud/EventHandlers/LongPressEventArgs.cs b/Lantean.QBTMud/EventHandlers/LongPressEventArgs.cs index 74c50fe..e5ae58f 100644 --- a/Lantean.QBTMud/EventHandlers/LongPressEventArgs.cs +++ b/Lantean.QBTMud/EventHandlers/LongPressEventArgs.cs @@ -1,4 +1,4 @@ -namespace Lantean.QBTMud.EventHandlers +namespace Lantean.QBTMud { public class LongPressEventArgs : EventArgs { diff --git a/Lantean.QBTMud/Helpers/DialogHelper.cs b/Lantean.QBTMud/Helpers/DialogHelper.cs index cb517b7..154b411 100644 --- a/Lantean.QBTMud/Helpers/DialogHelper.cs +++ b/Lantean.QBTMud/Helpers/DialogHelper.cs @@ -53,24 +53,10 @@ namespace Lantean.QBTMud.Helpers files.Add(file.Name, stream); } - await apiClient.AddTorrent( - urls: null, - files, - options.SavePath, - options.Cookie, - options.Category, - tags: null, - options.SkipHashCheck, - !options.StartTorrent, - options.ContentLayout, - options.RenameTorrent, - options.UploadLimit, - options.DownloadLimit, - ratioLimit: null, - seedingTimeLimit: null, - options.TorrentManagementMode, - options.DownloadInSequentialOrder, - options.DownloadFirstAndLastPiecesFirst); + var addTorrentParams = CreateAddTorrentParams(options); + addTorrentParams.Torrents = files; + + await apiClient.AddTorrent(addTorrentParams); foreach (var stream in streams) { @@ -78,6 +64,46 @@ namespace Lantean.QBTMud.Helpers } } + private static QBitTorrentClient.Models.AddTorrentParams CreateAddTorrentParams(TorrentOptions options) + { + var addTorrentParams = new QBitTorrentClient.Models.AddTorrentParams(); + addTorrentParams.AddToTopOfQueue = options.AddToTopOfQueue; + addTorrentParams.AutoTorrentManagement = options.TorrentManagementMode; + addTorrentParams.Category = options.Category; + if (!string.IsNullOrEmpty(options.ContentLayout)) + { + addTorrentParams.ContentLayout = Enum.Parse(options.ContentLayout); + } + if (string.IsNullOrEmpty(options.Cookie)) + { + addTorrentParams.Cookie = options.Cookie; + } + addTorrentParams.DownloadLimit = options.DownloadLimit; + addTorrentParams.DownloadPath = options.DownloadPath; + addTorrentParams.FirstLastPiecePriority = options.DownloadFirstAndLastPiecesFirst; + addTorrentParams.InactiveSeedingTimeLimit = options.InactiveSeedingTimeLimit; + addTorrentParams.Paused = !options.StartTorrent; + addTorrentParams.RatioLimit = options.RatioLimit; + addTorrentParams.RenameTorrent = options.RenameTorrent; + addTorrentParams.SavePath = options.SavePath; + addTorrentParams.SeedingTimeLimit = options.SeedingTimeLimit; + addTorrentParams.SequentialDownload = options.DownloadInSequentialOrder; + if (!string.IsNullOrEmpty(options.ShareLimitAction)) + { + addTorrentParams.ShareLimitAction = Enum.Parse(options.ShareLimitAction); + } + addTorrentParams.SkipChecking = options.SkipHashCheck; + if (!string.IsNullOrEmpty(options.StopCondition)) + { + addTorrentParams.StopCondition = Enum.Parse(options.StopCondition); + } + addTorrentParams.Stopped = !options.StartTorrent; + addTorrentParams.Tags = options.Tags; + addTorrentParams.UploadLimit = options.UploadLimit; + addTorrentParams.UseDownloadPath = options.UseDownloadPath; + return addTorrentParams; + } + public static async Task InvokeAddTorrentLinkDialog(this IDialogService dialogService, IApiClient apiClient, string? url = null) { var parameters = new DialogParameters @@ -94,24 +120,10 @@ namespace Lantean.QBTMud.Helpers var options = (AddTorrentLinkOptions)dialogResult.Data; - await apiClient.AddTorrent( - urls: options.Urls, - torrents: null, - options.SavePath, - options.Cookie, - options.Category, - tags: null, - options.SkipHashCheck, - !options.StartTorrent, - options.ContentLayout, - options.RenameTorrent, - options.UploadLimit, - options.DownloadLimit, - ratioLimit: null, - seedingTimeLimit: null, - options.TorrentManagementMode, - options.DownloadInSequentialOrder, - options.DownloadFirstAndLastPiecesFirst); + var addTorrentParams = CreateAddTorrentParams(options); + addTorrentParams.Urls = options.Urls; + + await apiClient.AddTorrent(addTorrentParams); } public static async Task InvokeDeleteTorrentDialog(this IDialogService dialogService, IApiClient apiClient, params string[] hashes) @@ -192,7 +204,7 @@ namespace Lantean.QBTMud.Helpers { var parameters = new DialogParameters { - //{ nameof(RenameFilesDialog.Hash), hash } + { nameof(RenameFilesDialog.Hash), hash } }; await dialogService.ShowAsync("Rename Files", parameters, FullScreenDialogOptions); diff --git a/Lantean.QBTMud/Lantean.QBTMud.csproj b/Lantean.QBTMud/Lantean.QBTMud.csproj index 7eb8098..7fbdf42 100644 --- a/Lantean.QBTMud/Lantean.QBTMud.csproj +++ b/Lantean.QBTMud/Lantean.QBTMud.csproj @@ -15,7 +15,7 @@ - + diff --git a/Lantean.QBTMud/Models/TorrentOptions.cs b/Lantean.QBTMud/Models/TorrentOptions.cs index aadbb56..32d8483 100644 --- a/Lantean.QBTMud/Models/TorrentOptions.cs +++ b/Lantean.QBTMud/Models/TorrentOptions.cs @@ -1,4 +1,6 @@ -namespace Lantean.QBTMud.Models +using Lantean.QBitTorrentClient.Models; + +namespace Lantean.QBTMud.Models { public record TorrentOptions { @@ -61,5 +63,12 @@ public long DownloadLimit { get; } public long UploadLimit { get; } + public string? DownloadPath { get; internal set; } + public int? InactiveSeedingTimeLimit { get; internal set; } + public float? RatioLimit { get; internal set; } + public int? SeedingTimeLimit { get; internal set; } + public string? ShareLimitAction { get; internal set; } + public bool? UseDownloadPath { get; internal set; } + public IEnumerable? Tags { get; internal set; } } } \ No newline at end of file diff --git a/Lantean.QBTMud/Pages/Login.razor.cs b/Lantean.QBTMud/Pages/Login.razor.cs index f238708..d986dc4 100644 --- a/Lantean.QBTMud/Pages/Login.razor.cs +++ b/Lantean.QBTMud/Pages/Login.razor.cs @@ -49,7 +49,7 @@ namespace Lantean.QBTMud.Pages protected override Task OnInitializedAsync() { - return DoLogin("admin", "AQnwFmBzV"); + return DoLogin("admin", "eBGJzbjkJ"); } #endif diff --git a/Lantean.QBTMud/wwwroot/Lantean.QBTMudBlade.lib.module.js b/Lantean.QBTMud/wwwroot/Lantean.QBTMud.lib.module.js similarity index 100% rename from Lantean.QBTMud/wwwroot/Lantean.QBTMudBlade.lib.module.js rename to Lantean.QBTMud/wwwroot/Lantean.QBTMud.lib.module.js diff --git a/Lantean.QBitTorrentClient/ApiClient.cs b/Lantean.QBitTorrentClient/ApiClient.cs index c149691..03c3864 100644 --- a/Lantean.QBitTorrentClient/ApiClient.cs +++ b/Lantean.QBitTorrentClient/ApiClient.cs @@ -305,7 +305,7 @@ namespace Lantean.QBitTorrentClient #region Torrent management - public async Task> GetTorrentList(string? filter = null, string? category = null, string? tag = null, string? sort = null, bool? reverse = null, int? limit = null, int? offset = null, params string[] hashes) + public async Task> GetTorrentList(string? filter = null, string? category = null, string? tag = null, string? sort = null, bool? reverse = null, int? limit = null, int? offset = null, bool? isPrivate = null, params string[] hashes) { var query = new QueryBuilder(); if (filter is not null) @@ -340,6 +340,10 @@ namespace Lantean.QBitTorrentClient { query.Add("hashes", string.Join('|', hashes)); } + if (isPrivate is not null) + { + query.Add("private", isPrivate.Value ? "true" : "false"); + } var response = await _httpClient.GetAsync("torrents/info", query); @@ -486,79 +490,110 @@ namespace Lantean.QBitTorrentClient await ThrowIfNotSuccessfulStatusCode(response); } - public async Task AddTorrent(IEnumerable? urls = null, Dictionary? torrents = null, string? savePath = null, string? cookie = null, string? category = null, IEnumerable? tags = null, bool? skipChecking = null, bool? paused = null, string? contentLayout = null, string? renameTorrent = null, long? uploadLimit = null, long? downloadLimit = null, float? ratioLimit = null, int? seedingTimeLimit = null, bool? autoTorrentManagement = null, bool? sequentialDownload = null, bool? firstLastPiecePriority = null) + public async Task AddTorrent(AddTorrentParams addTorrentParams) { var content = new MultipartFormDataContent(); - if (urls is not null) + if (addTorrentParams.Urls is not null) { - content.AddString("urls", string.Join('\n', urls)); + content.AddString("urls", string.Join('\n', addTorrentParams.Urls)); } - if (torrents is not null) + if (addTorrentParams.Torrents is not null) { - foreach (var (name, stream) in torrents) + foreach (var (name, stream) in addTorrentParams.Torrents) { content.Add(new StreamContent(stream), "torrents", name); } } - if (savePath is not null) + if (addTorrentParams.SkipChecking is not null) { - content.AddString("savepath", savePath); + content.AddString("skip_checking", addTorrentParams.SkipChecking.Value); } - if (cookie is not null) + if (addTorrentParams.SequentialDownload is not null) { - content.AddString("cookie", cookie); + content.AddString("sequentialDownload", addTorrentParams.SequentialDownload.Value); } - if (category is not null) + if (addTorrentParams.FirstLastPiecePriority is not null) { - content.AddString("category", category); + content.AddString("firstLastPiecePrio", addTorrentParams.FirstLastPiecePriority.Value); } - if (tags is not null) + if (addTorrentParams.AddToTopOfQueue is not null) { - content.AddString("tags", string.Join(',', tags)); + content.AddString("addToTopOfQueue", addTorrentParams.AddToTopOfQueue.Value); } - if (skipChecking is not null) + // v4 + if (addTorrentParams.Paused is not null) { - content.AddString("skip_checking", skipChecking.Value); + content.AddString("paused", addTorrentParams.Paused.Value); } - if (paused is not null) + // v5 + if (addTorrentParams.Stopped is not null) { - content.AddString("paused", paused.Value); + content.AddString("stopped", addTorrentParams.Stopped.Value); } - if (contentLayout is not null) + if (addTorrentParams.SavePath is not null) { - content.AddString("contentLayout", contentLayout); + content.AddString("savepath", addTorrentParams.SavePath); } - if (renameTorrent is not null) + if (addTorrentParams.DownloadPath is not null) { - content.AddString("rename", renameTorrent); + content.AddString("downloadPath", addTorrentParams.DownloadPath); } - if (uploadLimit is not null) + if (addTorrentParams.UseDownloadPath is not null) { - content.AddString("upLimit", uploadLimit.Value); + content.AddString("useDownloadPath", addTorrentParams.UseDownloadPath.Value); } - if (downloadLimit is not null) + if (addTorrentParams.Category is not null) { - content.AddString("dlLimit", downloadLimit.Value); + content.AddString("category", addTorrentParams.Category); } - if (ratioLimit is not null) + if (addTorrentParams.Tags is not null) { - content.AddString("ratioLimit", ratioLimit.Value); + content.AddString("tags", string.Join(',', addTorrentParams.Tags)); } - if (seedingTimeLimit is not null) + if (addTorrentParams.RenameTorrent is not null) { - content.AddString("seedingTimeLimit", seedingTimeLimit.Value); + content.AddString("rename", addTorrentParams.RenameTorrent); } - if (autoTorrentManagement is not null) + if (addTorrentParams.UploadLimit is not null) { - content.AddString("autoTMM", autoTorrentManagement.Value); + content.AddString("upLimit", addTorrentParams.UploadLimit.Value); } - if (sequentialDownload is not null) + if (addTorrentParams.DownloadLimit is not null) { - content.AddString("sequentialDownload", sequentialDownload.Value); + content.AddString("dlLimit", addTorrentParams.DownloadLimit.Value); } - if (firstLastPiecePriority is not null) + if (addTorrentParams.RatioLimit is not null) { - content.AddString("firstLastPiecePrio", firstLastPiecePriority.Value); + content.AddString("ratioLimit", addTorrentParams.RatioLimit.Value); + } + if (addTorrentParams.SeedingTimeLimit is not null) + { + content.AddString("seedingTimeLimit", addTorrentParams.SeedingTimeLimit.Value); + } + if (addTorrentParams.InactiveSeedingTimeLimit is not null) + { + content.AddString("inactiveSeedingTimeLimit", addTorrentParams.InactiveSeedingTimeLimit.Value); + } + if (addTorrentParams.ShareLimitAction is not null) + { + content.AddString("shareLimitAction", addTorrentParams.ShareLimitAction.Value); + } + if (addTorrentParams.AutoTorrentManagement is not null) + { + content.AddString("autoTMM", addTorrentParams.AutoTorrentManagement.Value); + } + if (addTorrentParams.StopCondition is not null) + { + content.AddString("stopCondition", addTorrentParams.StopCondition.Value); + } + if (addTorrentParams.ContentLayout is not null) + { + content.AddString("contentLayout", addTorrentParams.ContentLayout.Value); + } + + if (addTorrentParams.Cookie is not null) + { + content.AddString("cookie", addTorrentParams.Cookie); } var response = await _httpClient.PostAsync("torrents/add", content); @@ -606,7 +641,7 @@ namespace Lantean.QBitTorrentClient public async Task AddPeers(IEnumerable hashes, IEnumerable peers) { var content = new FormUrlEncodedBuilder() - .AddPipeSeparated("hash", hashes) + .AddPipeSeparated("hashes", hashes) .AddPipeSeparated("urls", peers) .ToFormUrlEncodedContent(); @@ -618,7 +653,7 @@ namespace Lantean.QBitTorrentClient public async Task IncreaseTorrentPriority(bool? all = null, params string[] hashes) { var content = new FormUrlEncodedBuilder() - .AddAllOrPipeSeparated("hash", all, hashes) + .AddAllOrPipeSeparated("hashes", all, hashes) .ToFormUrlEncodedContent(); var response = await _httpClient.PostAsync("torrents/increasePrio", content); @@ -629,7 +664,7 @@ namespace Lantean.QBitTorrentClient public async Task DecreaseTorrentPriority(bool? all = null, params string[] hashes) { var content = new FormUrlEncodedBuilder() - .AddAllOrPipeSeparated("hash", all, hashes) + .AddAllOrPipeSeparated("hashes", all, hashes) .ToFormUrlEncodedContent(); var response = await _httpClient.PostAsync("torrents/decreasePrio", content); @@ -637,10 +672,10 @@ namespace Lantean.QBitTorrentClient await ThrowIfNotSuccessfulStatusCode(response); } - public async Task MaximalTorrentPriority(bool? all = null, params string[] hashes) + public async Task MaxTorrentPriority(bool? all = null, params string[] hashes) { var content = new FormUrlEncodedBuilder() - .AddAllOrPipeSeparated("hash", all, hashes) + .AddAllOrPipeSeparated("hashes", all, hashes) .ToFormUrlEncodedContent(); var response = await _httpClient.PostAsync("torrents/topPrio", content); @@ -648,10 +683,10 @@ namespace Lantean.QBitTorrentClient await ThrowIfNotSuccessfulStatusCode(response); } - public async Task MinimalTorrentPriority(bool? all = null, params string[] hashes) + public async Task MinTorrentPriority(bool? all = null, params string[] hashes) { var content = new FormUrlEncodedBuilder() - .AddAllOrPipeSeparated("hash", all, hashes) + .AddAllOrPipeSeparated("hashes", all, hashes) .ToFormUrlEncodedContent(); var response = await _httpClient.PostAsync("torrents/bottomPrio", content); diff --git a/Lantean.QBitTorrentClient/IApiClient.cs b/Lantean.QBitTorrentClient/IApiClient.cs index c21e4e0..7916055 100644 --- a/Lantean.QBitTorrentClient/IApiClient.cs +++ b/Lantean.QBitTorrentClient/IApiClient.cs @@ -74,7 +74,7 @@ namespace Lantean.QBitTorrentClient #region Torrent management - Task> GetTorrentList(string? filter = null, string? category = null, string? tag = null, string? sort = null, bool? reverse = null, int? limit = null, int? offset = null, params string[] hashes); + Task> GetTorrentList(string? filter = null, string? category = null, string? tag = null, string? sort = null, bool? reverse = null, int? limit = null, int? offset = null, bool? isPrivate = null, params string[] hashes); Task GetTorrentProperties(string hash); @@ -102,7 +102,7 @@ namespace Lantean.QBitTorrentClient Task ReannounceTorrents(bool? all = null, params string[] hashes); - Task AddTorrent(IEnumerable? urls = null, Dictionary? torrents = null, string? savePath = null, string? cookie = null, string? category = null, IEnumerable? tags = null, bool? skipChecking = null, bool? paused = null, string? contentLayout = null, string? renameTorrent = null, long? uploadLimit = null, long? downloadLimit = null, float? ratioLimit = null, int? seedingTimeLimit = null, bool? autoTorrentManagement = null, bool? sequentialDownload = null, bool? firstLastPiecePriority = null); + Task AddTorrent(AddTorrentParams addTorrentParams); Task AddTrackersToTorrent(string hash, IEnumerable urls); @@ -116,9 +116,9 @@ namespace Lantean.QBitTorrentClient Task DecreaseTorrentPriority(bool? all = null, params string[] hashes); - Task MaximalTorrentPriority(bool? all = null, params string[] hashes); + Task MaxTorrentPriority(bool? all = null, params string[] hashes); - Task MinimalTorrentPriority(bool? all = null, params string[] hashes); + Task MinTorrentPriority(bool? all = null, params string[] hashes); Task SetFilePriority(string hash, IEnumerable id, Priority priority); diff --git a/Lantean.QBitTorrentClient/Models/AddTorrentParams.cs b/Lantean.QBitTorrentClient/Models/AddTorrentParams.cs new file mode 100644 index 0000000..577d586 --- /dev/null +++ b/Lantean.QBitTorrentClient/Models/AddTorrentParams.cs @@ -0,0 +1,54 @@ +namespace Lantean.QBitTorrentClient.Models +{ + public record AddTorrentParams + { + public IEnumerable? Urls { get; set; } + + public bool? SkipChecking { get; set; } + + public bool? SequentialDownload { get; set; } + + public bool? FirstLastPiecePriority { get; set; } + + public bool? AddToTopOfQueue { get; set; } + + // v4 + public bool? Paused { get; set; } + // v5 + public bool? Stopped { get; set; } + + public string? SavePath { get; set; } + + public string? DownloadPath { get; set; } + + public bool? UseDownloadPath { get; set; } + + public string? Category { get; set; } + + public IEnumerable? Tags { get; set; } + + public string? RenameTorrent { get; set; } + + public long? UploadLimit { get; set; } + + public long? DownloadLimit { get; set; } + + public float? RatioLimit { get; set; } + + public int? SeedingTimeLimit { get; set; } + + public int? InactiveSeedingTimeLimit { get; set; } + + public ShareLimitAction? ShareLimitAction { get; set; } + + public bool? AutoTorrentManagement { get; set; } + + public StopCondition? StopCondition { get; set; } + + public TorrentContentLayout? ContentLayout { get; set; } + + public string? Cookie { get; set; } + + public Dictionary? Torrents { get; set; } + } +} \ No newline at end of file diff --git a/Lantean.QBitTorrentClient/Models/ShareLimitAction.cs b/Lantean.QBitTorrentClient/Models/ShareLimitAction.cs new file mode 100644 index 0000000..0c7c9fb --- /dev/null +++ b/Lantean.QBitTorrentClient/Models/ShareLimitAction.cs @@ -0,0 +1,12 @@ +namespace Lantean.QBitTorrentClient.Models +{ + public enum ShareLimitAction + { + Default = -1, // special value + + Stop = 0, + Remove = 1, + RemoveWithContent = 3, + EnableSuperSeeding = 2 + } +} \ No newline at end of file diff --git a/Lantean.QBitTorrentClient/Models/StopCondition.cs b/Lantean.QBitTorrentClient/Models/StopCondition.cs new file mode 100644 index 0000000..112fb51 --- /dev/null +++ b/Lantean.QBitTorrentClient/Models/StopCondition.cs @@ -0,0 +1,9 @@ +namespace Lantean.QBitTorrentClient.Models +{ + public enum StopCondition + { + None = 0, + MetadataReceived = 1, + FilesChecked = 2 + } +} \ No newline at end of file diff --git a/Lantean.QBitTorrentClient/Models/TorrentContentLayout.cs b/Lantean.QBitTorrentClient/Models/TorrentContentLayout.cs new file mode 100644 index 0000000..aacae72 --- /dev/null +++ b/Lantean.QBitTorrentClient/Models/TorrentContentLayout.cs @@ -0,0 +1,9 @@ +namespace Lantean.QBitTorrentClient.Models +{ + public enum TorrentContentLayout + { + Original, + Subfolder, + NoSubfolder + } +} \ No newline at end of file diff --git a/Lantean.QBitTorrentClient/MultipartFormDataContentExtensions.cs b/Lantean.QBitTorrentClient/MultipartFormDataContentExtensions.cs index 71eee18..23faec8 100644 --- a/Lantean.QBitTorrentClient/MultipartFormDataContentExtensions.cs +++ b/Lantean.QBitTorrentClient/MultipartFormDataContentExtensions.cs @@ -27,6 +27,11 @@ content.AddString(name, value.ToString()); } + public static void AddString(this MultipartFormDataContent content, string name, Enum value) + { + content.AddString(name, value.ToString()); + } + public static void AddString(this MultipartFormDataContent content, string name, DateTimeOffset value, bool useSeconds = true) { content.AddString(name, useSeconds ? value.ToUnixTimeSeconds() : value.ToUnixTimeMilliseconds());