mirror of
https://github.com/lantean-code/qbtmud.git
synced 2025-10-22 20:42:24 +00:00
Add project files.
This commit is contained in:
951
Lantean.QBitTorrentClient/ApiClient.cs
Normal file
951
Lantean.QBitTorrentClient/ApiClient.cs
Normal file
@@ -0,0 +1,951 @@
|
||||
using Lantean.QBitTorrentClient.Models;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public class ApiClient : IApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
private readonly JsonSerializerOptions _options = SerializerOptions.Options;
|
||||
|
||||
public ApiClient(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
#region Authentication
|
||||
|
||||
public async Task<bool> CheckAuthState()
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.GetAsync("app/version");
|
||||
return response.StatusCode == HttpStatusCode.OK;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Login(string username, string password)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("username", username)
|
||||
.Add("password", password)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("auth/login", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
if (responseContent == "Fails.")
|
||||
{
|
||||
throw new HttpRequestException(null, null, HttpStatusCode.BadRequest);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Logout()
|
||||
{
|
||||
var response = await _httpClient.PostAsync("auth/logout", null);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
#endregion Authentication
|
||||
|
||||
#region Application
|
||||
|
||||
public async Task<string> GetApplicationVersion()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("app/version");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
public async Task<string> GetAPIVersion()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("app/webapiVersion");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
public async Task<BuildInfo> GetBuildInfo()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("app/buildInfo");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJson<BuildInfo>(response.Content);
|
||||
}
|
||||
|
||||
public async Task Shutdown()
|
||||
{
|
||||
var response = await _httpClient.PostAsync("app/shutdown", null);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<Preferences> GetApplicationPreferences()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("app/preferences");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJson<Preferences>(response.Content);
|
||||
}
|
||||
|
||||
public async Task SetApplicationPreferences(UpdatePreferences preferences)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(preferences, _options);
|
||||
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("json", json)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("app/setPreferences", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<string> GetDefaultSavePath()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("app/defaultSavePath");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
#endregion Application
|
||||
|
||||
#region Log
|
||||
|
||||
public async Task<IReadOnlyList<Log>> GetLog(bool? normal = null, bool? info = null, bool? warning = null, bool? critical = null, int? lastKnownId = null)
|
||||
{
|
||||
var query = new QueryBuilder();
|
||||
if (normal is not null)
|
||||
{
|
||||
query.Add("normal", normal.Value);
|
||||
}
|
||||
if (info is not null)
|
||||
{
|
||||
query.Add("info", info.Value);
|
||||
}
|
||||
if (warning is not null)
|
||||
{
|
||||
query.Add("warning", warning.Value);
|
||||
}
|
||||
if (critical is not null)
|
||||
{
|
||||
query.Add("critical", critical.Value);
|
||||
}
|
||||
if (lastKnownId is not null)
|
||||
{
|
||||
query.Add("last_known_id", lastKnownId.Value);
|
||||
}
|
||||
|
||||
var response = await _httpClient.GetAsync($"log/main", query);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<Log>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<PeerLog>> GetPeerLog(int? lastKnownId = null)
|
||||
{
|
||||
var query = new QueryBuilder();
|
||||
if (lastKnownId is not null)
|
||||
{
|
||||
query.Add("last_known_id", lastKnownId.Value);
|
||||
}
|
||||
|
||||
var response = await _httpClient.GetAsync($"log/peers", query);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<PeerLog>(response.Content);
|
||||
}
|
||||
|
||||
#endregion Log
|
||||
|
||||
#region Sync
|
||||
|
||||
public async Task<MainData> GetMainData(int requestId)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"sync/maindata?rid={requestId}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJson<MainData>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<TorrentPeers> GetTorrentPeersData(string hash, int requestId)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"sync/torrentPeers?hash={hash}&rid={requestId}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJson<TorrentPeers>(response.Content);
|
||||
}
|
||||
|
||||
#endregion Sync
|
||||
|
||||
#region Transfer info
|
||||
|
||||
public async Task<GlobalTransferInfo> GetGlobalTransferInfo()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("transfer/info");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJson<GlobalTransferInfo>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<bool> GetAlternativeSpeedLimitsState()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("transfer/speedLimitsMode");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var value = await response.Content.ReadAsStringAsync();
|
||||
|
||||
return value == "1";
|
||||
}
|
||||
|
||||
public async Task ToggleAlternativeSpeedLimits()
|
||||
{
|
||||
var response = await _httpClient.PostAsync("transfer/toggleSpeedLimitsMode", null);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<long> GetGlobalDownloadLimit()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("transfer/downloadLimit");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var value = await response.Content.ReadAsStringAsync();
|
||||
|
||||
return long.Parse(value);
|
||||
}
|
||||
|
||||
public async Task SetGlobalDownloadLimit(long limit)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("limit", limit)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("transfer/setDownloadLimit", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<long> GetGlobalUploadLimit()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("transfer/uploadLimit");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var value = await response.Content.ReadAsStringAsync();
|
||||
|
||||
return long.Parse(value);
|
||||
}
|
||||
|
||||
public async Task SetGlobalUploadLimit(long limit)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("limit", limit)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("transfer/setUploadLimit", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task BanPeers(IEnumerable<PeerId> peers)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddPipeSeparated("peers", peers)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("transfer/banPeers", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
#endregion Transfer info
|
||||
|
||||
#region Torrent management
|
||||
|
||||
public async Task<IReadOnlyList<Torrent>> 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)
|
||||
{
|
||||
var query = new QueryBuilder();
|
||||
if (filter is not null)
|
||||
{
|
||||
query.Add("filter", filter);
|
||||
}
|
||||
if (category is not null)
|
||||
{
|
||||
query.Add("category", category);
|
||||
}
|
||||
if (tag is not null)
|
||||
{
|
||||
query.Add("tag", tag);
|
||||
}
|
||||
if (sort is not null)
|
||||
{
|
||||
query.Add("sort", sort);
|
||||
}
|
||||
if (reverse is not null)
|
||||
{
|
||||
query.Add("reverse", reverse.Value);
|
||||
}
|
||||
if (limit is not null)
|
||||
{
|
||||
query.Add("limit", limit.Value);
|
||||
}
|
||||
if (offset is not null)
|
||||
{
|
||||
query.Add("offset", offset.Value);
|
||||
}
|
||||
if (hashes.Length > 0)
|
||||
{
|
||||
query.Add("hashes", string.Join('|', hashes));
|
||||
}
|
||||
|
||||
var response = await _httpClient.GetAsync("torrents/info", query);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<Torrent>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<TorrentProperties> GetTorrentProperties(string hash)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"torrents/properties?hash={hash}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJson<TorrentProperties>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<TorrentTrackers>> GetTorrentTrackers(string hash)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"torrents/trackers?hash={hash}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<TorrentTrackers>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<WebSeed>> GetTorrentWebSeeds(string hash)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"torrents/webseeds?hash={hash}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<WebSeed>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<FileData>> GetTorrentContents(string hash, params int[] indexes)
|
||||
{
|
||||
var query = new QueryBuilder();
|
||||
query.Add("hash", hash);
|
||||
if (indexes.Length > 0)
|
||||
{
|
||||
query.Add("indexes", string.Join('|', indexes));
|
||||
}
|
||||
var response = await _httpClient.GetAsync("torrents/files", query);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<FileData>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<PieceState>> GetTorrentPieceStates(string hash)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"torrents/pieceStates?hash={hash}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<PieceState>(response.Content);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<string>> GetTorrentPieceHashes(string hash)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"torrents/pieceHashes?hash={hash}");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<string>(response.Content);
|
||||
}
|
||||
|
||||
public async Task PauseTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/pause", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task ResumeTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/resume", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task DeleteTorrents(bool? all = null, bool deleteFiles = false, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("deleteFiles", deleteFiles)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/delete", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task RecheckTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/recheck", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task ReannounceTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/reannounce", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task AddTorrent(IEnumerable<string>? urls = null, Dictionary<string, Stream>? torrents = null, string? savePath = null, string? cookie = null, string? category = null, IEnumerable<string>? 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)
|
||||
{
|
||||
var content = new MultipartFormDataContent();
|
||||
if (urls is not null)
|
||||
{
|
||||
content.AddString("urls", string.Join('\n', urls));
|
||||
}
|
||||
if (torrents is not null)
|
||||
{
|
||||
foreach (var (name, stream) in torrents)
|
||||
{
|
||||
content.Add(new StreamContent(stream), name);
|
||||
}
|
||||
}
|
||||
if (savePath is not null)
|
||||
{
|
||||
content.AddString("savepath", savePath);
|
||||
}
|
||||
if (cookie is not null)
|
||||
{
|
||||
content.AddString("cookie", cookie);
|
||||
}
|
||||
if (category is not null)
|
||||
{
|
||||
content.AddString("category", category);
|
||||
}
|
||||
if (tags is not null)
|
||||
{
|
||||
content.AddString("tags", string.Join(',', tags));
|
||||
}
|
||||
if (skipChecking is not null)
|
||||
{
|
||||
content.AddString("skip_checking", skipChecking.Value);
|
||||
}
|
||||
if (paused is not null)
|
||||
{
|
||||
content.AddString("paused", paused.Value);
|
||||
}
|
||||
if (contentLayout is not null)
|
||||
{
|
||||
content.AddString("contentLayout", contentLayout);
|
||||
}
|
||||
if (renameTorrent is not null)
|
||||
{
|
||||
content.AddString("rename", renameTorrent);
|
||||
}
|
||||
if (uploadLimit is not null)
|
||||
{
|
||||
content.AddString("upLimit", uploadLimit.Value);
|
||||
}
|
||||
if (downloadLimit is not null)
|
||||
{
|
||||
content.AddString("dlLimit", downloadLimit.Value);
|
||||
}
|
||||
if (ratioLimit is not null)
|
||||
{
|
||||
content.AddString("ratioLimit", ratioLimit.Value);
|
||||
}
|
||||
if (seedingTimeLimit is not null)
|
||||
{
|
||||
content.AddString("seedingTimeLimit", seedingTimeLimit.Value);
|
||||
}
|
||||
if (autoTorrentManagement is not null)
|
||||
{
|
||||
content.AddString("autoTMM", autoTorrentManagement.Value);
|
||||
}
|
||||
if (sequentialDownload is not null)
|
||||
{
|
||||
content.AddString("sequentialDownload", sequentialDownload.Value);
|
||||
}
|
||||
if (firstLastPiecePriority is not null)
|
||||
{
|
||||
content.AddString("firstLastPiecePrio", firstLastPiecePriority.Value);
|
||||
}
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/add", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task AddTrackersToTorrent(string hash, IEnumerable<string> urls)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.Add("urls", string.Join('\n', urls))
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/addTrackers", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task EditTracker(string hash, string originalUrl, string newUrl)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.Add("originalUrl", originalUrl)
|
||||
.Add("newUrl", newUrl)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/editTracker", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task RemoveTrackers(string hash, IEnumerable<string> urls)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.AddPipeSeparated("urls", urls)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/removeTrackers", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task AddPeers(IEnumerable<string> hashes, IEnumerable<PeerId> peers)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddPipeSeparated("hash", hashes)
|
||||
.AddPipeSeparated("urls", peers)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/addPeers", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task IncreaseTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hash", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/increasePrio", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task DecreaseTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hash", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/decreasePrio", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task MaximalTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hash", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/topPrio", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task MinimalTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hash", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/bottomPrio", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetFilePriority(string hash, IEnumerable<int> id, Priority priority)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.AddPipeSeparated("id", id)
|
||||
.Add("priority", priority)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/filePrio", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyDictionary<string, long>> GetTorrentDownloadLimit(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/downloadLimit", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonDictionary<string, long>(response.Content);
|
||||
}
|
||||
|
||||
public async Task SetTorrentDownloadLimit(long limit, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("limit", limit)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setDownloadLimit", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetTorrentShareLimit(float ratioLimit, float seedingTimeLimit, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("ratioLimit", ratioLimit)
|
||||
.Add("seedingTimeLimit", seedingTimeLimit)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setShareLimits", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyDictionary<string, long>> GetTorrentUploadLimit(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/uploadLimit", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonDictionary<string, long>(response.Content);
|
||||
}
|
||||
|
||||
public async Task SetTorrentUploadLimit(long limit, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("limit", limit)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setUploadLimit", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetTorrentLocation(string location, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("location", location)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setLocation", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetTorrentName(string name, string hash)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.Add("name", name)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/rename", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetTorrentCategory(string category, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("category", category)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setCategory", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyDictionary<string, Category>> GetAllCategories()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("torrents/categories");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonDictionary<string, Category>(response.Content);
|
||||
}
|
||||
|
||||
public async Task AddCategory(string category, string savePath)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("category", category)
|
||||
.Add("savePath", savePath)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/createCategory", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task EditCategory(string category, string savePath)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("category", category)
|
||||
.Add("savePath", savePath)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/editCategory", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task RemoveCategories(params string[] categories)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("categories", string.Join('\n', categories))
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/removeCategories", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task AddTorrentTags(IEnumerable<string> tags, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.AddPipeSeparated("tags", tags)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/addTags", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task RemoveTorrentTags(IEnumerable<string> tags, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.AddPipeSeparated("tags", tags)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/removeTags", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<string>> GetAllTags()
|
||||
{
|
||||
var response = await _httpClient.GetAsync("torrents/tags");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await GetJsonList<string>(response.Content);
|
||||
}
|
||||
|
||||
public async Task CreateTags(IEnumerable<string> tags)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddPipeSeparated("tags", tags)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/createTags", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task DeleteTags(IEnumerable<string> tags)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddPipeSeparated("tags", tags)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/deleteTags", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetAutomaticTorrentManagement(bool enable, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("enable", enable)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setAutoManagement", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task ToggleSequentialDownload(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/toggleSequentialDownload", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetFirstLastPiecePriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/toggleFirstLastPiecePrio", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetForceStart(bool value, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("enable", value)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setFOrceStart", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task SetSuperSeeding(bool value, bool? all = null, params string[] hashes)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.AddAllOrPipeSeparated("hashes", all, hashes)
|
||||
.Add("enable", value)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/setSuperSeeding", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task RenameFile(string hash, string oldPath, string newPath)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.Add("oldPath", oldPath)
|
||||
.Add("newPath", newPath)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/renameFile", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
public async Task RenameFolder(string hash, string oldPath, string newPath)
|
||||
{
|
||||
var content = new FormUrlEncodedBuilder()
|
||||
.Add("hash", hash)
|
||||
.Add("oldPath", oldPath)
|
||||
.Add("newPath", newPath)
|
||||
.ToFormUrlEncodedContent();
|
||||
|
||||
var response = await _httpClient.PostAsync("torrents/renameFolder", content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
#endregion Torrent management
|
||||
|
||||
#region RSS
|
||||
|
||||
// not implementing RSS right now
|
||||
|
||||
#endregion RSS
|
||||
|
||||
#region Search
|
||||
|
||||
// not implementing Search right now
|
||||
|
||||
#endregion Search
|
||||
|
||||
private async Task<T> GetJson<T>(HttpContent content)
|
||||
{
|
||||
return await content.ReadFromJsonAsync<T>(_options) ?? throw new InvalidOperationException($"Unable to deserialize response as {typeof(T).Name}");
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyList<T>> GetJsonList<T>(HttpContent content)
|
||||
{
|
||||
var items = await GetJson<IEnumerable<T>>(content);
|
||||
|
||||
return items.ToList().AsReadOnly();
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyDictionary<TKey, TValue>> GetJsonDictionary<TKey, TValue>(HttpContent content) where TKey : notnull
|
||||
{
|
||||
var items = await GetJson<IDictionary<TKey, TValue>>(content);
|
||||
|
||||
return items.AsReadOnly();
|
||||
}
|
||||
}
|
||||
}
|
109
Lantean.QBitTorrentClient/ApiClientExtensions.cs
Normal file
109
Lantean.QBitTorrentClient/ApiClientExtensions.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Lantean.QBitTorrentClient.Models;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public static class ApiClientExtensions
|
||||
{
|
||||
public static Task PauseTorrent(this IApiClient apiClient, string hash)
|
||||
{
|
||||
return apiClient.PauseTorrents(null, hash);
|
||||
}
|
||||
|
||||
public static Task PauseTorrents(this IApiClient apiClient, IEnumerable<string> hashes)
|
||||
{
|
||||
return apiClient.PauseTorrents(null, hashes.ToArray());
|
||||
}
|
||||
|
||||
public static Task PauseAllTorrents(this IApiClient apiClient)
|
||||
{
|
||||
return apiClient.PauseTorrents(true);
|
||||
}
|
||||
|
||||
public static Task ResumeTorrent(this IApiClient apiClient, string hash)
|
||||
{
|
||||
return apiClient.ResumeTorrents(null, hash);
|
||||
}
|
||||
|
||||
public static Task ResumeTorrents(this IApiClient apiClient, IEnumerable<string> hashes)
|
||||
{
|
||||
return apiClient.ResumeTorrents(null, hashes.ToArray());
|
||||
}
|
||||
|
||||
public static Task ResumeAllTorrents(this IApiClient apiClient)
|
||||
{
|
||||
return apiClient.ResumeTorrents(true);
|
||||
}
|
||||
|
||||
public static Task DeleteTorrent(this IApiClient apiClient, string hash, bool deleteFiles)
|
||||
{
|
||||
return apiClient.DeleteTorrents(null, deleteFiles, hash);
|
||||
}
|
||||
|
||||
public static Task DeleteTorrents(this IApiClient apiClient, IEnumerable<string> hashes, bool deleteFiles)
|
||||
{
|
||||
return apiClient.DeleteTorrents(null, deleteFiles, hashes.ToArray());
|
||||
}
|
||||
|
||||
public static Task DeleteAllTorrents(this IApiClient apiClient, bool deleteFiles)
|
||||
{
|
||||
return apiClient.DeleteTorrents(true, deleteFiles);
|
||||
}
|
||||
|
||||
public static async Task<Torrent?> GetTorrent(this IApiClient apiClient, string hash)
|
||||
{
|
||||
var torrents = await apiClient.GetTorrentList(hashes: hash);
|
||||
|
||||
if (torrents.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return torrents[0];
|
||||
}
|
||||
|
||||
public static Task SetTorrentCategory(this IApiClient apiClient, string category, string hash)
|
||||
{
|
||||
return apiClient.SetTorrentCategory(category, null, hash);
|
||||
}
|
||||
|
||||
public static Task RemoveTorrentTags(this IApiClient apiClient, IEnumerable<string> tags, string hash)
|
||||
{
|
||||
return apiClient.RemoveTorrentTags(tags, null, hash);
|
||||
}
|
||||
|
||||
public static Task RemoveTorrentTag(this IApiClient apiClient, string tag, string hash)
|
||||
{
|
||||
return apiClient.RemoveTorrentTags([tag], hash);
|
||||
}
|
||||
|
||||
public static Task RemoveTorrentTag(this IApiClient apiClient, string tag, IEnumerable<string> hashes)
|
||||
{
|
||||
return apiClient.RemoveTorrentTags([tag], null, hashes.ToArray());
|
||||
}
|
||||
|
||||
public static Task AddTorrentTags(this IApiClient apiClient, IEnumerable<string> tags, string hash)
|
||||
{
|
||||
return apiClient.AddTorrentTags(tags, null, hash);
|
||||
}
|
||||
|
||||
public static Task AddTorrentTag(this IApiClient apiClient, string tag, string hash)
|
||||
{
|
||||
return apiClient.AddTorrentTags([tag], hash);
|
||||
}
|
||||
|
||||
public static Task AddTorrentTag(this IApiClient apiClient, string tag, IEnumerable<string> hashes)
|
||||
{
|
||||
return apiClient.AddTorrentTags([tag], null, hashes.ToArray());
|
||||
}
|
||||
|
||||
public static Task RecheckTorrent(this IApiClient apiClient, string hash)
|
||||
{
|
||||
return apiClient.RecheckTorrents(null, hash);
|
||||
}
|
||||
|
||||
public static Task ReannounceTorrent(this IApiClient apiClient, string hash)
|
||||
{
|
||||
return apiClient.ReannounceTorrents(null, hash);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Converters
|
||||
{
|
||||
internal class CommaSeparatedJsonConverter : JsonConverter<IReadOnlyList<string>>
|
||||
{
|
||||
public override IReadOnlyList<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.String)
|
||||
{
|
||||
throw new JsonException("Must be of type string.");
|
||||
}
|
||||
|
||||
List<string> list;
|
||||
var value = reader.GetString();
|
||||
if (value is null)
|
||||
{
|
||||
list = [];
|
||||
}
|
||||
else
|
||||
{
|
||||
var values = value.Split(',');
|
||||
list = [.. values];
|
||||
}
|
||||
|
||||
return list.AsReadOnly();
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, IReadOnlyList<string> value, JsonSerializerOptions options)
|
||||
{
|
||||
var output = string.Join(',', value);
|
||||
|
||||
writer.WriteStringValue(output);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
using Lantean.QBitTorrentClient.Models;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Converters
|
||||
{
|
||||
public class SaveLocationJsonConverter : JsonConverter<SaveLocation>
|
||||
{
|
||||
public override SaveLocation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
return SaveLocation.Create(reader.GetString());
|
||||
}
|
||||
|
||||
if (reader.TokenType == JsonTokenType.Number)
|
||||
{
|
||||
return SaveLocation.Create(reader.GetInt32());
|
||||
}
|
||||
|
||||
throw new JsonException($"Unsupported token type {reader.TokenType}");
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, SaveLocation value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value.IsWatchedFolder)
|
||||
{
|
||||
writer.WriteNumberValue(0);
|
||||
}
|
||||
else if (value.IsDefaltFolder)
|
||||
{
|
||||
writer.WriteNumberValue(1);
|
||||
}
|
||||
else if (value.SavePath is not null)
|
||||
{
|
||||
writer.WriteStringValue(value.SavePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Converters
|
||||
{
|
||||
internal class StringFloatJsonConverter : JsonConverter<float>
|
||||
{
|
||||
public override float Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.String)
|
||||
{
|
||||
if (float.TryParse(reader.GetString(), out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reader.TokenType == JsonTokenType.Number)
|
||||
{
|
||||
if (reader.TryGetSingle(out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStringValue(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
38
Lantean.QBitTorrentClient/FormUrlEncodedBuilder.cs
Normal file
38
Lantean.QBitTorrentClient/FormUrlEncodedBuilder.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public class FormUrlEncodedBuilder
|
||||
{
|
||||
private readonly IList<KeyValuePair<string, string>> _parameters;
|
||||
|
||||
public FormUrlEncodedBuilder()
|
||||
{
|
||||
_parameters = [];
|
||||
}
|
||||
|
||||
public FormUrlEncodedBuilder(IList<KeyValuePair<string, string>> parameters)
|
||||
{
|
||||
_parameters = parameters;
|
||||
}
|
||||
|
||||
public FormUrlEncodedBuilder Add(string key, string value)
|
||||
{
|
||||
_parameters.Add(new KeyValuePair<string, string>(key, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormUrlEncodedBuilder AddIfNotNullOrEmpty(string key, string value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
_parameters.Add(new KeyValuePair<string, string>(key, value));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public FormUrlEncodedContent ToFormUrlEncodedContent()
|
||||
{
|
||||
return new FormUrlEncodedContent(_parameters);
|
||||
}
|
||||
}
|
||||
}
|
52
Lantean.QBitTorrentClient/FormUrlEncodedBuilderExtensions.cs
Normal file
52
Lantean.QBitTorrentClient/FormUrlEncodedBuilderExtensions.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public static class FormUrlEncodedBuilderExtensions
|
||||
{
|
||||
public static FormUrlEncodedBuilder Add(this FormUrlEncodedBuilder builder, string key, bool value)
|
||||
{
|
||||
return builder.Add(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder Add(this FormUrlEncodedBuilder builder, string key, int value)
|
||||
{
|
||||
return builder.Add(key, value.ToString());
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder Add(this FormUrlEncodedBuilder builder, string key, long value)
|
||||
{
|
||||
return builder.Add(key, value.ToString());
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder Add(this FormUrlEncodedBuilder builder, string key, DateTimeOffset value, bool useSeconds = true)
|
||||
{
|
||||
return builder.Add(key, useSeconds ? value.ToUnixTimeSeconds() : value.ToUnixTimeMilliseconds());
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder Add(this FormUrlEncodedBuilder builder, string key, float value)
|
||||
{
|
||||
return builder.Add(key, value.ToString());
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder Add<T>(this FormUrlEncodedBuilder builder, string key, T value) where T : struct, IConvertible
|
||||
{
|
||||
return builder.Add(key, value.ToInt32(CultureInfo.InvariantCulture).ToString());
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder AddAllOrPipeSeparated(this FormUrlEncodedBuilder builder, string key, bool? all = null, params string[] values)
|
||||
{
|
||||
return builder.Add(key, all.GetValueOrDefault() ? "all" : string.Join('|', values));
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder AddPipeSeparated<T>(this FormUrlEncodedBuilder builder, string key, IEnumerable<T> values)
|
||||
{
|
||||
return builder.Add(key, string.Join('|', values));
|
||||
}
|
||||
|
||||
public static FormUrlEncodedBuilder AddCommaSeparated<T>(this FormUrlEncodedBuilder builder, string key, IEnumerable<T> values)
|
||||
{
|
||||
return builder.Add(key, string.Join(',', values));
|
||||
}
|
||||
}
|
||||
}
|
15
Lantean.QBitTorrentClient/HttpClientExtensions.cs
Normal file
15
Lantean.QBitTorrentClient/HttpClientExtensions.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
internal static class HttpClientExtensions
|
||||
{
|
||||
public static Task<HttpResponseMessage> PostAsync(this HttpClient httpClient, string requestUrl, FormUrlEncodedBuilder builder)
|
||||
{
|
||||
return httpClient.PostAsync(requestUrl, builder.ToFormUrlEncodedContent());
|
||||
}
|
||||
|
||||
public static Task<HttpResponseMessage> GetAsync(this HttpClient httpClient, string requestUrl, QueryBuilder builder)
|
||||
{
|
||||
return httpClient.GetAsync($"{requestUrl}{builder.ToQueryString()}");
|
||||
}
|
||||
}
|
||||
}
|
179
Lantean.QBitTorrentClient/IApiClient.cs
Normal file
179
Lantean.QBitTorrentClient/IApiClient.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
using Lantean.QBitTorrentClient.Models;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public interface IApiClient
|
||||
{
|
||||
#region Authentication
|
||||
|
||||
Task<bool> CheckAuthState();
|
||||
|
||||
Task Login(string username, string password);
|
||||
|
||||
Task Logout();
|
||||
|
||||
#endregion Authentication
|
||||
|
||||
#region Application
|
||||
|
||||
Task<string> GetApplicationVersion();
|
||||
|
||||
Task<string> GetAPIVersion();
|
||||
|
||||
Task<BuildInfo> GetBuildInfo();
|
||||
|
||||
Task Shutdown();
|
||||
|
||||
Task<Preferences> GetApplicationPreferences();
|
||||
|
||||
Task SetApplicationPreferences(UpdatePreferences preferences);
|
||||
|
||||
Task<string> GetDefaultSavePath();
|
||||
|
||||
#endregion Application
|
||||
|
||||
#region Log
|
||||
|
||||
Task<IReadOnlyList<Log>> GetLog(bool? normal = null, bool? info = null, bool? warning = null, bool? critical = null, int? lastKnownId = null);
|
||||
|
||||
Task<IReadOnlyList<PeerLog>> GetPeerLog(int? lastKnownId = null);
|
||||
|
||||
#endregion Log
|
||||
|
||||
#region Sync
|
||||
|
||||
Task<MainData> GetMainData(int requestId);
|
||||
|
||||
Task<TorrentPeers> GetTorrentPeersData(string hash, int requestId);
|
||||
|
||||
#endregion Sync
|
||||
|
||||
#region Transfer info
|
||||
|
||||
Task<GlobalTransferInfo> GetGlobalTransferInfo();
|
||||
|
||||
Task<bool> GetAlternativeSpeedLimitsState();
|
||||
|
||||
Task ToggleAlternativeSpeedLimits();
|
||||
|
||||
Task<long> GetGlobalDownloadLimit();
|
||||
|
||||
Task SetGlobalDownloadLimit(long limit);
|
||||
|
||||
Task<long> GetGlobalUploadLimit();
|
||||
|
||||
Task SetGlobalUploadLimit(long limit);
|
||||
|
||||
Task BanPeers(IEnumerable<PeerId> peers);
|
||||
|
||||
#endregion Transfer info
|
||||
|
||||
#region Torrent management
|
||||
|
||||
Task<IReadOnlyList<Torrent>> 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<TorrentProperties> GetTorrentProperties(string hash);
|
||||
|
||||
Task<IReadOnlyList<TorrentTrackers>> GetTorrentTrackers(string hash);
|
||||
|
||||
Task<IReadOnlyList<WebSeed>> GetTorrentWebSeeds(string hash);
|
||||
|
||||
Task<IReadOnlyList<FileData>> GetTorrentContents(string hash, params int[] indexes);
|
||||
|
||||
Task<IReadOnlyList<PieceState>> GetTorrentPieceStates(string hash);
|
||||
|
||||
Task<IReadOnlyList<string>> GetTorrentPieceHashes(string hash);
|
||||
|
||||
Task PauseTorrents(bool? all = null, params string[] hashes);
|
||||
|
||||
Task ResumeTorrents(bool? all = null, params string[] hashes);
|
||||
|
||||
Task DeleteTorrents(bool? all = null, bool deleteFiles = false, params string[] hashes);
|
||||
|
||||
Task RecheckTorrents(bool? all = null, params string[] hashes);
|
||||
|
||||
Task ReannounceTorrents(bool? all = null, params string[] hashes);
|
||||
|
||||
Task AddTorrent(IEnumerable<string>? urls = null, Dictionary<string, Stream>? torrents = null, string? savePath = null, string? cookie = null, string? category = null, IEnumerable<string>? 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 AddTrackersToTorrent(string hash, IEnumerable<string> urls);
|
||||
|
||||
Task EditTracker(string hash, string originalUrl, string newUrl);
|
||||
|
||||
Task RemoveTrackers(string hash, IEnumerable<string> urls);
|
||||
|
||||
Task AddPeers(IEnumerable<string> hashes, IEnumerable<PeerId> peers);
|
||||
|
||||
Task IncreaseTorrentPriority(bool? all = null, params string[] hashes);
|
||||
|
||||
Task DecreaseTorrentPriority(bool? all = null, params string[] hashes);
|
||||
|
||||
Task MaximalTorrentPriority(bool? all = null, params string[] hashes);
|
||||
|
||||
Task MinimalTorrentPriority(bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetFilePriority(string hash, IEnumerable<int> id, Priority priority);
|
||||
|
||||
Task<IReadOnlyDictionary<string, long>> GetTorrentDownloadLimit(bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetTorrentDownloadLimit(long limit, bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetTorrentShareLimit(float ratioLimit, float seedingTimeLimit, bool? all = null, params string[] hashes);
|
||||
|
||||
Task<IReadOnlyDictionary<string, long>> GetTorrentUploadLimit(bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetTorrentUploadLimit(long limit, bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetTorrentLocation(string location, bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetTorrentName(string name, string hash);
|
||||
|
||||
Task SetTorrentCategory(string category, bool? all = null, params string[] hashes);
|
||||
|
||||
Task<IReadOnlyDictionary<string, Category>> GetAllCategories();
|
||||
|
||||
Task AddCategory(string category, string savePath);
|
||||
|
||||
Task EditCategory(string category, string savePath);
|
||||
|
||||
Task RemoveCategories(params string[] categories);
|
||||
|
||||
Task AddTorrentTags(IEnumerable<string> tags, bool? all = null, params string[] hashes);
|
||||
|
||||
Task RemoveTorrentTags(IEnumerable<string> tags, bool? all = null, params string[] hashes);
|
||||
|
||||
Task<IReadOnlyList<string>> GetAllTags();
|
||||
|
||||
Task CreateTags(IEnumerable<string> tags);
|
||||
|
||||
Task DeleteTags(IEnumerable<string> tags);
|
||||
|
||||
Task SetAutomaticTorrentManagement(bool enable, bool? all = null, params string[] hashes);
|
||||
|
||||
Task ToggleSequentialDownload(bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetFirstLastPiecePriority(bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetForceStart(bool value, bool? all = null, params string[] hashes);
|
||||
|
||||
Task SetSuperSeeding(bool value, bool? all = null, params string[] hashes);
|
||||
|
||||
Task RenameFile(string hash, string oldPath, string newPath);
|
||||
|
||||
Task RenameFolder(string hash, string oldPath, string newPath);
|
||||
|
||||
#endregion Torrent management
|
||||
|
||||
#region RSS
|
||||
|
||||
// not implementing RSS right now
|
||||
|
||||
#endregion RSS
|
||||
|
||||
#region Search
|
||||
|
||||
// not implementing Search right now
|
||||
|
||||
#endregion Search
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
9
Lantean.QBitTorrentClient/Limits.cs
Normal file
9
Lantean.QBitTorrentClient/Limits.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public static class Limits
|
||||
{
|
||||
public const long GlobalLimit = -2;
|
||||
|
||||
public const long NoLimit = -1;
|
||||
}
|
||||
}
|
367
Lantean.QBitTorrentClient/MockApiClient.cs
Normal file
367
Lantean.QBitTorrentClient/MockApiClient.cs
Normal file
@@ -0,0 +1,367 @@
|
||||
using Lantean.QBitTorrentClient.Models;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public class MockApiClient : IApiClient
|
||||
{
|
||||
private readonly ApiClient _apiClient;
|
||||
|
||||
public MockApiClient(ApiClient apiClient)
|
||||
{
|
||||
_apiClient = apiClient;
|
||||
}
|
||||
|
||||
public Task AddCategory(string category, string savePath)
|
||||
{
|
||||
return _apiClient.AddCategory(category, savePath);
|
||||
}
|
||||
|
||||
public Task AddPeers(IEnumerable<string> hashes, IEnumerable<PeerId> peers)
|
||||
{
|
||||
return _apiClient.AddPeers(hashes, peers);
|
||||
}
|
||||
|
||||
public Task AddTorrent(IEnumerable<string>? urls = null, Dictionary<string, Stream>? torrents = null, string? savePath = null, string? cookie = null, string? category = null, IEnumerable<string>? 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)
|
||||
{
|
||||
return _apiClient.AddTorrent(urls, torrents, savePath, cookie, category, tags, skipChecking, paused, contentLayout, renameTorrent, uploadLimit, downloadLimit, ratioLimit, seedingTimeLimit, autoTorrentManagement, sequentialDownload, firstLastPiecePriority);
|
||||
}
|
||||
|
||||
public Task AddTorrentTags(IEnumerable<string> tags, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.AddTorrentTags(tags, all, hashes);
|
||||
}
|
||||
|
||||
public Task AddTrackersToTorrent(string hash, IEnumerable<string> urls)
|
||||
{
|
||||
return _apiClient.AddTrackersToTorrent(hash, urls);
|
||||
}
|
||||
|
||||
public Task BanPeers(IEnumerable<PeerId> peers)
|
||||
{
|
||||
return _apiClient.BanPeers(peers);
|
||||
}
|
||||
|
||||
public Task<bool> CheckAuthState()
|
||||
{
|
||||
return _apiClient.CheckAuthState();
|
||||
}
|
||||
|
||||
public Task CreateTags(IEnumerable<string> tags)
|
||||
{
|
||||
return _apiClient.CreateTags(tags);
|
||||
}
|
||||
|
||||
public Task DecreaseTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.DecreaseTorrentPriority(all, hashes);
|
||||
}
|
||||
|
||||
public Task DeleteTags(IEnumerable<string> tags)
|
||||
{
|
||||
return _apiClient.DeleteTags(tags);
|
||||
}
|
||||
|
||||
public Task DeleteTorrents(bool? all = null, bool deleteFiles = false, params string[] hashes)
|
||||
{
|
||||
return _apiClient.DeleteTorrents(all, deleteFiles, hashes);
|
||||
}
|
||||
|
||||
public Task EditCategory(string category, string savePath)
|
||||
{
|
||||
return _apiClient.EditCategory(category, savePath);
|
||||
}
|
||||
|
||||
public Task EditTracker(string hash, string originalUrl, string newUrl)
|
||||
{
|
||||
return _apiClient.EditTracker(hash, originalUrl, newUrl);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyDictionary<string, Category>> GetAllCategories()
|
||||
{
|
||||
return _apiClient.GetAllCategories();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> GetAllTags()
|
||||
{
|
||||
return _apiClient.GetAllTags();
|
||||
}
|
||||
|
||||
public Task<bool> GetAlternativeSpeedLimitsState()
|
||||
{
|
||||
return _apiClient.GetAlternativeSpeedLimitsState();
|
||||
}
|
||||
|
||||
public Task<string> GetAPIVersion()
|
||||
{
|
||||
return _apiClient.GetAPIVersion();
|
||||
}
|
||||
|
||||
public Task<Preferences> GetApplicationPreferences()
|
||||
{
|
||||
return _apiClient.GetApplicationPreferences();
|
||||
}
|
||||
|
||||
public Task<string> GetApplicationVersion()
|
||||
{
|
||||
return _apiClient.GetApplicationVersion();
|
||||
}
|
||||
|
||||
public Task<BuildInfo> GetBuildInfo()
|
||||
{
|
||||
return _apiClient.GetBuildInfo();
|
||||
}
|
||||
|
||||
public Task<string> GetDefaultSavePath()
|
||||
{
|
||||
return _apiClient.GetDefaultSavePath();
|
||||
}
|
||||
|
||||
public Task<long> GetGlobalDownloadLimit()
|
||||
{
|
||||
return _apiClient.GetGlobalDownloadLimit();
|
||||
}
|
||||
|
||||
public Task<GlobalTransferInfo> GetGlobalTransferInfo()
|
||||
{
|
||||
return _apiClient.GetGlobalTransferInfo();
|
||||
}
|
||||
|
||||
public Task<long> GetGlobalUploadLimit()
|
||||
{
|
||||
return _apiClient.GetGlobalUploadLimit();
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<Log>> GetLog(bool? normal = null, bool? info = null, bool? warning = null, bool? critical = null, int? lastKnownId = null)
|
||||
{
|
||||
return _apiClient.GetLog(normal, info, warning, critical, lastKnownId);
|
||||
}
|
||||
|
||||
public Task<MainData> GetMainData(int requestId)
|
||||
{
|
||||
return _apiClient.GetMainData(requestId);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<PeerLog>> GetPeerLog(int? lastKnownId = null)
|
||||
{
|
||||
return _apiClient.GetPeerLog(lastKnownId);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<FileData>> GetTorrentContents(string hash, params int[] indexes)
|
||||
{
|
||||
var list = new List<FileData>();
|
||||
list.Add(new FileData(2, "slackware-14.2-iso/slackware-14.2-source-d6.iso", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(3, "slackware-14.2-iso/slackware-14.2-source-d6.iso.asc", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(4, "slackware-14.2-iso/slackware-14.2-source-d6.iso.md5", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(5, "slackware-14.2-iso/slackware-14.2-source-d6.iso.txt", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(6, "slackware-14.2-iso/temp/slackware-14.2-source-d6.iso.md5", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(7, "slackware-14.2-iso/temp/slackware-14.2-source-d6.iso.txt", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(8, "slackware-14.2-iso2/slackware-14.2-source-d6.iso2", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(9, "slackware-14.2-iso2/slackware-14.2-source-d6.iso2.asc", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(10, "slackware-14.2-iso2/slackware-14.2-source-d6.iso2.md5", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(11, "slackware-14.2-iso2/slackware-14.2-source-d6.iso2.txt", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(12, "really/long/directory/path/is/here/file.txt", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
list.Add(new FileData(13, "other.txt", 500, 0f, Priority.Normal, false, [1, 2], 0f));
|
||||
return Task.FromResult<IReadOnlyList<FileData>>(list);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyDictionary<string, long>> GetTorrentDownloadLimit(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.GetTorrentDownloadLimit(all, hashes);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<Torrent>> 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)
|
||||
{
|
||||
return _apiClient.GetTorrentList(filter, category, tag, sort, reverse, limit, offset, hashes);
|
||||
}
|
||||
|
||||
public Task<TorrentPeers> GetTorrentPeersData(string hash, int requestId)
|
||||
{
|
||||
return _apiClient.GetTorrentPeersData(hash, requestId);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<string>> GetTorrentPieceHashes(string hash)
|
||||
{
|
||||
return _apiClient.GetTorrentPieceHashes(hash);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<PieceState>> GetTorrentPieceStates(string hash)
|
||||
{
|
||||
return _apiClient.GetTorrentPieceStates(hash);
|
||||
}
|
||||
|
||||
public Task<TorrentProperties> GetTorrentProperties(string hash)
|
||||
{
|
||||
return _apiClient.GetTorrentProperties(hash);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<TorrentTrackers>> GetTorrentTrackers(string hash)
|
||||
{
|
||||
return _apiClient.GetTorrentTrackers(hash);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyDictionary<string, long>> GetTorrentUploadLimit(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.GetTorrentUploadLimit(all, hashes);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<WebSeed>> GetTorrentWebSeeds(string hash)
|
||||
{
|
||||
return _apiClient.GetTorrentWebSeeds(hash);
|
||||
}
|
||||
|
||||
public Task IncreaseTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.IncreaseTorrentPriority(all, hashes);
|
||||
}
|
||||
|
||||
public Task Login(string username, string password)
|
||||
{
|
||||
return _apiClient.Login(username, password);
|
||||
}
|
||||
|
||||
public Task Logout()
|
||||
{
|
||||
return _apiClient.Logout();
|
||||
}
|
||||
|
||||
public Task MaximalTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.MaximalTorrentPriority(all, hashes);
|
||||
}
|
||||
|
||||
public Task MinimalTorrentPriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.MinimalTorrentPriority(all, hashes);
|
||||
}
|
||||
|
||||
public Task PauseTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.PauseTorrents(all, hashes);
|
||||
}
|
||||
|
||||
public Task ReannounceTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.ReannounceTorrents(all, hashes);
|
||||
}
|
||||
|
||||
public Task RecheckTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.ReannounceTorrents(all, hashes);
|
||||
}
|
||||
|
||||
public Task RemoveCategories(params string[] categories)
|
||||
{
|
||||
return _apiClient.RemoveCategories(categories);
|
||||
}
|
||||
|
||||
public Task RemoveTorrentTags(IEnumerable<string> tags, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.RemoveTorrentTags(tags, all, hashes);
|
||||
}
|
||||
|
||||
public Task RemoveTrackers(string hash, IEnumerable<string> urls)
|
||||
{
|
||||
return _apiClient.RemoveTrackers(hash, urls);
|
||||
}
|
||||
|
||||
public Task RenameFile(string hash, string oldPath, string newPath)
|
||||
{
|
||||
return _apiClient.RenameFile(hash, oldPath, newPath);
|
||||
}
|
||||
|
||||
public Task RenameFolder(string hash, string oldPath, string newPath)
|
||||
{
|
||||
return _apiClient.RenameFolder(hash, oldPath, newPath);
|
||||
}
|
||||
|
||||
public Task ResumeTorrents(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.ResumeTorrents(all, hashes);
|
||||
}
|
||||
|
||||
public Task SetApplicationPreferences(UpdatePreferences preferences)
|
||||
{
|
||||
return _apiClient.SetApplicationPreferences(preferences);
|
||||
}
|
||||
|
||||
public Task SetAutomaticTorrentManagement(bool enable, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetAutomaticTorrentManagement(enable, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetFilePriority(string hash, IEnumerable<int> id, Priority priority)
|
||||
{
|
||||
return _apiClient.SetFilePriority(hash, id, priority);
|
||||
}
|
||||
|
||||
public Task SetFirstLastPiecePriority(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetFirstLastPiecePriority(all, hashes);
|
||||
}
|
||||
|
||||
public Task SetForceStart(bool value, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetForceStart(value, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetGlobalDownloadLimit(long limit)
|
||||
{
|
||||
return _apiClient.SetGlobalDownloadLimit(limit);
|
||||
}
|
||||
|
||||
public Task SetGlobalUploadLimit(long limit)
|
||||
{
|
||||
return _apiClient.SetGlobalDownloadLimit(limit);
|
||||
}
|
||||
|
||||
public Task SetSuperSeeding(bool value, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetSuperSeeding(value, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetTorrentCategory(string category, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetTorrentCategory(category, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetTorrentDownloadLimit(long limit, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetTorrentDownloadLimit(limit, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetTorrentLocation(string location, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetTorrentLocation(location, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetTorrentName(string name, string hash)
|
||||
{
|
||||
return _apiClient.SetTorrentName(name, hash);
|
||||
}
|
||||
|
||||
public Task SetTorrentShareLimit(float ratioLimit, float seedingTimeLimit, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetTorrentShareLimit(ratioLimit, seedingTimeLimit, all, hashes);
|
||||
}
|
||||
|
||||
public Task SetTorrentUploadLimit(long limit, bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.SetTorrentUploadLimit(limit, all, hashes);
|
||||
}
|
||||
|
||||
public Task Shutdown()
|
||||
{
|
||||
return _apiClient.Shutdown();
|
||||
}
|
||||
|
||||
public Task ToggleAlternativeSpeedLimits()
|
||||
{
|
||||
return _apiClient.ToggleAlternativeSpeedLimits();
|
||||
}
|
||||
|
||||
public Task ToggleSequentialDownload(bool? all = null, params string[] hashes)
|
||||
{
|
||||
return _apiClient.ToggleSequentialDownload(all, hashes);
|
||||
}
|
||||
}
|
||||
}
|
37
Lantean.QBitTorrentClient/Models/BuildInfo.cs
Normal file
37
Lantean.QBitTorrentClient/Models/BuildInfo.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record BuildInfo
|
||||
{
|
||||
[JsonConstructor]
|
||||
public BuildInfo(
|
||||
string qTVersion,
|
||||
string libTorrentVersion,
|
||||
string boostVersion,
|
||||
string openSSLVersion,
|
||||
int bitness)
|
||||
{
|
||||
QTVersion = qTVersion;
|
||||
LibTorrentVersion = libTorrentVersion;
|
||||
BoostVersion = boostVersion;
|
||||
OpenSSLVersion = openSSLVersion;
|
||||
Bitness = bitness;
|
||||
}
|
||||
|
||||
[JsonPropertyName("qt")]
|
||||
public string QTVersion { get; }
|
||||
|
||||
[JsonPropertyName("libtorrent")]
|
||||
public string LibTorrentVersion { get; }
|
||||
|
||||
[JsonPropertyName("boost")]
|
||||
public string BoostVersion { get; }
|
||||
|
||||
[JsonPropertyName("openssl")]
|
||||
public string OpenSSLVersion { get; }
|
||||
|
||||
[JsonPropertyName("bitness")]
|
||||
public int Bitness { get; }
|
||||
}
|
||||
}
|
22
Lantean.QBitTorrentClient/Models/Category.cs
Normal file
22
Lantean.QBitTorrentClient/Models/Category.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record Category
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Category(
|
||||
string name,
|
||||
string? savePath)
|
||||
{
|
||||
Name = name;
|
||||
SavePath = savePath;
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; }
|
||||
|
||||
[JsonPropertyName("savePath")]
|
||||
public string? SavePath { get; }
|
||||
}
|
||||
}
|
52
Lantean.QBitTorrentClient/Models/FileData.cs
Normal file
52
Lantean.QBitTorrentClient/Models/FileData.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record FileData
|
||||
{
|
||||
[JsonConstructor]
|
||||
public FileData(
|
||||
int index,
|
||||
string name,
|
||||
long size,
|
||||
float progress,
|
||||
Priority priority,
|
||||
bool isSeed,
|
||||
IReadOnlyList<int> pieceRange,
|
||||
float availability)
|
||||
{
|
||||
Index = index;
|
||||
Name = name;
|
||||
Size = size;
|
||||
Progress = progress;
|
||||
Priority = priority;
|
||||
IsSeed = isSeed;
|
||||
PieceRange = pieceRange ?? [];
|
||||
Availability = availability;
|
||||
}
|
||||
|
||||
[JsonPropertyName("index")]
|
||||
public int Index { get; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; }
|
||||
|
||||
[JsonPropertyName("size")]
|
||||
public long Size { get; }
|
||||
|
||||
[JsonPropertyName("progress")]
|
||||
public float Progress { get; }
|
||||
|
||||
[JsonPropertyName("priority")]
|
||||
public Priority Priority { get; }
|
||||
|
||||
[JsonPropertyName("is_seed")]
|
||||
public bool IsSeed { get; }
|
||||
|
||||
[JsonPropertyName("piece_range")]
|
||||
public IReadOnlyList<int> PieceRange { get; }
|
||||
|
||||
[JsonPropertyName("availability")]
|
||||
public float Availability { get; }
|
||||
}
|
||||
}
|
52
Lantean.QBitTorrentClient/Models/GlobalTransferInfo.cs
Normal file
52
Lantean.QBitTorrentClient/Models/GlobalTransferInfo.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record GlobalTransferInfo
|
||||
{
|
||||
[JsonConstructor]
|
||||
public GlobalTransferInfo(
|
||||
string? connectionStatus,
|
||||
int? dHTNodes,
|
||||
long? downloadInfoData,
|
||||
long? downloadInfoSpeed,
|
||||
long? downloadRateLimit,
|
||||
long? uploadInfoData,
|
||||
long? uploadInfoSpeed,
|
||||
long? uploadRateLimit)
|
||||
{
|
||||
ConnectionStatus = connectionStatus;
|
||||
DHTNodes = dHTNodes;
|
||||
DownloadInfoData = downloadInfoData;
|
||||
DownloadInfoSpeed = downloadInfoSpeed;
|
||||
DownloadRateLimit = downloadRateLimit;
|
||||
UploadInfoData = uploadInfoData;
|
||||
UploadInfoSpeed = uploadInfoSpeed;
|
||||
UploadRateLimit = uploadRateLimit;
|
||||
}
|
||||
|
||||
[JsonPropertyName("connection_status")]
|
||||
public string? ConnectionStatus { get; }
|
||||
|
||||
[JsonPropertyName("dht_nodes")]
|
||||
public int? DHTNodes { get; }
|
||||
|
||||
[JsonPropertyName("dl_info_data")]
|
||||
public long? DownloadInfoData { get; }
|
||||
|
||||
[JsonPropertyName("dl_info_speed")]
|
||||
public long? DownloadInfoSpeed { get; }
|
||||
|
||||
[JsonPropertyName("dl_rate_limit")]
|
||||
public long? DownloadRateLimit { get; }
|
||||
|
||||
[JsonPropertyName("up_info_data")]
|
||||
public long? UploadInfoData { get; }
|
||||
|
||||
[JsonPropertyName("up_info_speed")]
|
||||
public long? UploadInfoSpeed { get; }
|
||||
|
||||
[JsonPropertyName("up_rate_limit")]
|
||||
public long? UploadRateLimit { get; }
|
||||
}
|
||||
}
|
32
Lantean.QBitTorrentClient/Models/Log.cs
Normal file
32
Lantean.QBitTorrentClient/Models/Log.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record Log
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Log(
|
||||
int id,
|
||||
string message,
|
||||
long timestamp,
|
||||
LogType type)
|
||||
{
|
||||
Id = id;
|
||||
Message = message;
|
||||
Timestamp = timestamp;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; }
|
||||
|
||||
[JsonPropertyName("message")]
|
||||
public string Message { get; }
|
||||
|
||||
[JsonPropertyName("timestamp")]
|
||||
public long Timestamp { get; }
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public LogType Type { get; }
|
||||
}
|
||||
}
|
10
Lantean.QBitTorrentClient/Models/LogType.cs
Normal file
10
Lantean.QBitTorrentClient/Models/LogType.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public enum LogType
|
||||
{
|
||||
Normal = 1,
|
||||
Info = 2,
|
||||
Warning = 4,
|
||||
Critical = 8
|
||||
}
|
||||
}
|
65
Lantean.QBitTorrentClient/Models/MainData.cs
Normal file
65
Lantean.QBitTorrentClient/Models/MainData.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record MainData
|
||||
{
|
||||
[JsonConstructor]
|
||||
public MainData(
|
||||
int responseId,
|
||||
bool fullUpdate,
|
||||
IReadOnlyDictionary<string, Torrent>? torrents,
|
||||
IReadOnlyList<string>? torrentsRemoved,
|
||||
IReadOnlyDictionary<string, Category>? categories,
|
||||
IReadOnlyList<string>? categoriesRemoved,
|
||||
IReadOnlyList<string>? tags,
|
||||
IReadOnlyList<string>? tagsRemoved,
|
||||
IReadOnlyDictionary<string, IReadOnlyList<string>> trackers,
|
||||
ServerState? serverState)
|
||||
{
|
||||
ResponseId = responseId;
|
||||
FullUpdate = fullUpdate;
|
||||
Torrents = torrents;
|
||||
TorrentsRemoved = torrentsRemoved;
|
||||
Categories = categories;
|
||||
CategoriesRemoved = categoriesRemoved;
|
||||
Tags = tags;
|
||||
TagsRemoved = tagsRemoved;
|
||||
Trackers = trackers;
|
||||
ServerState = serverState;
|
||||
}
|
||||
|
||||
[JsonPropertyName("rid")]
|
||||
public int ResponseId { get; }
|
||||
|
||||
[JsonPropertyName("full_update")]
|
||||
public bool FullUpdate { get; }
|
||||
|
||||
[JsonPropertyName("torrents")]
|
||||
public IReadOnlyDictionary<string, Torrent>? Torrents { get; }
|
||||
|
||||
[JsonPropertyName("torrents_removed")]
|
||||
public IReadOnlyList<string>? TorrentsRemoved { get; }
|
||||
|
||||
[JsonPropertyName("categories")]
|
||||
public IReadOnlyDictionary<string, Category>? Categories { get; }
|
||||
|
||||
[JsonPropertyName("categories_removed")]
|
||||
public IReadOnlyList<string>? CategoriesRemoved { get; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public IReadOnlyList<string>? Tags { get; }
|
||||
|
||||
[JsonPropertyName("tags_removed")]
|
||||
public IReadOnlyList<string>? TagsRemoved { get; }
|
||||
|
||||
[JsonPropertyName("trackers")]
|
||||
public IReadOnlyDictionary<string, IReadOnlyList<string>>? Trackers { get; }
|
||||
|
||||
[JsonPropertyName("trackers_removed")]
|
||||
public IReadOnlyList<string>? TrackersRemoved { get; }
|
||||
|
||||
[JsonPropertyName("server_state")]
|
||||
public ServerState? ServerState { get; }
|
||||
}
|
||||
}
|
92
Lantean.QBitTorrentClient/Models/Peer.cs
Normal file
92
Lantean.QBitTorrentClient/Models/Peer.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record Peer
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Peer(
|
||||
string? client,
|
||||
string? connection,
|
||||
string? country,
|
||||
string? countryCode,
|
||||
long? downloadSpeed,
|
||||
long? downloaded,
|
||||
string? files,
|
||||
string? flags,
|
||||
string? flagsDescription,
|
||||
string? iPAddress,
|
||||
string? clientId,
|
||||
int? port,
|
||||
float? progress,
|
||||
float? relevance,
|
||||
long? uploadSpeed,
|
||||
long? uploaded)
|
||||
{
|
||||
Client = client;
|
||||
Connection = connection;
|
||||
Country = country;
|
||||
CountryCode = countryCode;
|
||||
DownloadSpeed = downloadSpeed;
|
||||
Downloaded = downloaded;
|
||||
Files = files;
|
||||
Flags = flags;
|
||||
FlagsDescription = flagsDescription;
|
||||
IPAddress = iPAddress;
|
||||
ClientId = clientId;
|
||||
Port = port;
|
||||
Progress = progress;
|
||||
Relevance = relevance;
|
||||
UploadSpeed = uploadSpeed;
|
||||
Uploaded = uploaded;
|
||||
}
|
||||
|
||||
[JsonPropertyName("client")]
|
||||
public string? Client { get; }
|
||||
|
||||
[JsonPropertyName("connection")]
|
||||
public string? Connection { get; }
|
||||
|
||||
[JsonPropertyName("country")]
|
||||
public string? Country { get; }
|
||||
|
||||
[JsonPropertyName("country_code")]
|
||||
public string? CountryCode { get; }
|
||||
|
||||
[JsonPropertyName("dl_speed")]
|
||||
public long? DownloadSpeed { get; }
|
||||
|
||||
[JsonPropertyName("downloaded")]
|
||||
public long? Downloaded { get; }
|
||||
|
||||
[JsonPropertyName("files")]
|
||||
public string? Files { get; }
|
||||
|
||||
[JsonPropertyName("flags")]
|
||||
public string? Flags { get; }
|
||||
|
||||
[JsonPropertyName("flags_desc")]
|
||||
public string? FlagsDescription { get; }
|
||||
|
||||
[JsonPropertyName("ip")]
|
||||
public string? IPAddress { get; }
|
||||
|
||||
[JsonPropertyName("peer_id_client")]
|
||||
public string? ClientId { get; }
|
||||
|
||||
[JsonPropertyName("port")]
|
||||
public int? Port { get; }
|
||||
|
||||
[JsonPropertyName("progress")]
|
||||
public float? Progress { get; }
|
||||
|
||||
[JsonPropertyName("relevance")]
|
||||
public float? Relevance { get; }
|
||||
|
||||
[JsonPropertyName("up_speed")]
|
||||
public long? UploadSpeed { get; }
|
||||
|
||||
[JsonPropertyName("uploaded")]
|
||||
public long? Uploaded { get; }
|
||||
}
|
||||
}
|
14
Lantean.QBitTorrentClient/Models/PeerId.cs
Normal file
14
Lantean.QBitTorrentClient/Models/PeerId.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public readonly struct PeerId(string host, int port)
|
||||
{
|
||||
public string Host { get; } = host;
|
||||
|
||||
public int Port { get; } = port;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Host}:{Port}";
|
||||
}
|
||||
}
|
||||
}
|
37
Lantean.QBitTorrentClient/Models/PeerLog.cs
Normal file
37
Lantean.QBitTorrentClient/Models/PeerLog.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record PeerLog
|
||||
{
|
||||
[JsonConstructor]
|
||||
public PeerLog(
|
||||
int id,
|
||||
string iPAddress,
|
||||
long timestamp,
|
||||
bool blocked,
|
||||
string reason)
|
||||
{
|
||||
Id = id;
|
||||
IPAddress = iPAddress;
|
||||
Timestamp = timestamp;
|
||||
Blocked = blocked;
|
||||
Reason = reason;
|
||||
}
|
||||
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; }
|
||||
|
||||
[JsonPropertyName("ip")]
|
||||
public string IPAddress { get; }
|
||||
|
||||
[JsonPropertyName("timestamp")]
|
||||
public long Timestamp { get; }
|
||||
|
||||
[JsonPropertyName("blocked")]
|
||||
public bool Blocked { get; }
|
||||
|
||||
[JsonPropertyName("reason")]
|
||||
public string Reason { get; }
|
||||
}
|
||||
}
|
9
Lantean.QBitTorrentClient/Models/PieceState.cs
Normal file
9
Lantean.QBitTorrentClient/Models/PieceState.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public enum PieceState
|
||||
{
|
||||
NotDownloaded = 0,
|
||||
Downloading = 1,
|
||||
Downloaded = 2,
|
||||
}
|
||||
}
|
1023
Lantean.QBitTorrentClient/Models/Preferences.cs
Normal file
1023
Lantean.QBitTorrentClient/Models/Preferences.cs
Normal file
File diff suppressed because it is too large
Load Diff
10
Lantean.QBitTorrentClient/Models/Priority.cs
Normal file
10
Lantean.QBitTorrentClient/Models/Priority.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public enum Priority
|
||||
{
|
||||
DoNotDownload = 0,
|
||||
Normal = 1,
|
||||
High = 6,
|
||||
Maximum = 7
|
||||
}
|
||||
}
|
82
Lantean.QBitTorrentClient/Models/SaveLocation.cs
Normal file
82
Lantean.QBitTorrentClient/Models/SaveLocation.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public class SaveLocation
|
||||
{
|
||||
public bool IsWatchedFolder { get; set; }
|
||||
|
||||
public bool IsDefaltFolder { get; set; }
|
||||
|
||||
public string? SavePath { get; set; }
|
||||
|
||||
public static SaveLocation Create(object? value)
|
||||
{
|
||||
if (value is int intValue)
|
||||
{
|
||||
if (intValue == 0)
|
||||
{
|
||||
return new SaveLocation
|
||||
{
|
||||
IsWatchedFolder = true
|
||||
};
|
||||
}
|
||||
else if (intValue == 1)
|
||||
{
|
||||
return new SaveLocation
|
||||
{
|
||||
IsDefaltFolder = true
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (value is string stringValue)
|
||||
{
|
||||
if (stringValue == "0")
|
||||
{
|
||||
return new SaveLocation
|
||||
{
|
||||
IsWatchedFolder = true
|
||||
};
|
||||
}
|
||||
else if (stringValue == "1")
|
||||
{
|
||||
return new SaveLocation
|
||||
{
|
||||
IsDefaltFolder = true
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SaveLocation
|
||||
{
|
||||
SavePath = stringValue
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(value));
|
||||
}
|
||||
|
||||
public object ToValue()
|
||||
{
|
||||
if (IsWatchedFolder)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (IsDefaltFolder)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (SavePath is not null)
|
||||
{
|
||||
return SavePath;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Invalid value.");
|
||||
}
|
||||
|
||||
public override string? ToString()
|
||||
{
|
||||
return ToValue().ToString();
|
||||
}
|
||||
}
|
||||
}
|
105
Lantean.QBitTorrentClient/Models/ServerState.cs
Normal file
105
Lantean.QBitTorrentClient/Models/ServerState.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record ServerState : GlobalTransferInfo
|
||||
{
|
||||
[JsonConstructor]
|
||||
public ServerState(
|
||||
long? allTimeDownloaded,
|
||||
long? allTimeUploaded,
|
||||
int? averageTimeQueue,
|
||||
string? connectionStatus,
|
||||
int? dHTNodes,
|
||||
long? downloadInfoData,
|
||||
long? downloadInfoSpeed,
|
||||
long? downloadRateLimit,
|
||||
long? freeSpaceOnDisk,
|
||||
float? globalRatio,
|
||||
int? queuedIOJobs,
|
||||
bool? queuing,
|
||||
float? readCacheHits,
|
||||
float? readCacheOverload,
|
||||
int? refreshInterval,
|
||||
int? totalBuffersSize,
|
||||
int? totalPeerConnections,
|
||||
int? totalQueuedSize,
|
||||
long? totalWastedSession,
|
||||
long? uploadInfoData,
|
||||
long? uploadInfoSpeed,
|
||||
long? uploadRateLimit,
|
||||
bool? useAltSpeedLimits,
|
||||
bool? useSubcategories,
|
||||
float? writeCacheOverload) : base(connectionStatus, dHTNodes, downloadInfoData, downloadInfoSpeed, downloadRateLimit, uploadInfoData, uploadInfoSpeed, uploadRateLimit)
|
||||
{
|
||||
AllTimeDownloaded = allTimeDownloaded;
|
||||
AllTimeUploaded = allTimeUploaded;
|
||||
AverageTimeQueue = averageTimeQueue;
|
||||
FreeSpaceOnDisk = freeSpaceOnDisk;
|
||||
GlobalRatio = globalRatio;
|
||||
QueuedIOJobs = queuedIOJobs;
|
||||
Queuing = queuing;
|
||||
ReadCacheHits = readCacheHits;
|
||||
ReadCacheOverload = readCacheOverload;
|
||||
RefreshInterval = refreshInterval;
|
||||
TotalBuffersSize = totalBuffersSize;
|
||||
TotalPeerConnections = totalPeerConnections;
|
||||
TotalQueuedSize = totalQueuedSize;
|
||||
TotalWastedSession = totalWastedSession;
|
||||
UseAltSpeedLimits = useAltSpeedLimits;
|
||||
UseSubcategories = useSubcategories;
|
||||
WriteCacheOverload = writeCacheOverload;
|
||||
}
|
||||
|
||||
[JsonPropertyName("alltime_dl")]
|
||||
public long? AllTimeDownloaded { get; }
|
||||
|
||||
[JsonPropertyName("alltime_ul")]
|
||||
public long? AllTimeUploaded { get; }
|
||||
|
||||
[JsonPropertyName("average_time_queue")]
|
||||
public int? AverageTimeQueue { get; }
|
||||
|
||||
[JsonPropertyName("free_space_on_disk")]
|
||||
public long? FreeSpaceOnDisk { get; }
|
||||
|
||||
[JsonPropertyName("global_ratio")]
|
||||
public float? GlobalRatio { get; }
|
||||
|
||||
[JsonPropertyName("queued_io_jobs")]
|
||||
public int? QueuedIOJobs { get; }
|
||||
|
||||
[JsonPropertyName("queueing")]
|
||||
public bool? Queuing { get; }
|
||||
|
||||
[JsonPropertyName("read_cache_hits")]
|
||||
public float? ReadCacheHits { get; }
|
||||
|
||||
[JsonPropertyName("read_cache_overload")]
|
||||
public float? ReadCacheOverload { get; }
|
||||
|
||||
[JsonPropertyName("refresh_interval")]
|
||||
public int? RefreshInterval { get; }
|
||||
|
||||
[JsonPropertyName("total_buffers_size")]
|
||||
public int? TotalBuffersSize { get; }
|
||||
|
||||
[JsonPropertyName("total_peer_connections")]
|
||||
public int? TotalPeerConnections { get; }
|
||||
|
||||
[JsonPropertyName("total_queued_size")]
|
||||
public int? TotalQueuedSize { get; }
|
||||
|
||||
[JsonPropertyName("total_wasted_session")]
|
||||
public long? TotalWastedSession { get; }
|
||||
|
||||
[JsonPropertyName("use_alt_speed_limits")]
|
||||
public bool? UseAltSpeedLimits { get; }
|
||||
|
||||
[JsonPropertyName("use_subcategories")]
|
||||
public bool? UseSubcategories { get; }
|
||||
|
||||
[JsonPropertyName("write_cache_overload")]
|
||||
public float? WriteCacheOverload { get; }
|
||||
}
|
||||
}
|
249
Lantean.QBitTorrentClient/Models/Torrent.cs
Normal file
249
Lantean.QBitTorrentClient/Models/Torrent.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using Lantean.QBitTorrentClient.Converters;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record Torrent
|
||||
{
|
||||
[JsonConstructor]
|
||||
public Torrent(
|
||||
long? addedOn,
|
||||
long? amountLeft,
|
||||
bool? automaticTorrentManagement,
|
||||
float? availability,
|
||||
string? category,
|
||||
long? completed,
|
||||
long? completionOn,
|
||||
string? contentPath,
|
||||
long? downloadLimit,
|
||||
long? downloadSpeed,
|
||||
long? downloaded,
|
||||
long? downloadedSession,
|
||||
long? estimatedTimeOfArrival,
|
||||
bool? firstLastPiecePriority,
|
||||
bool? forceStart,
|
||||
string? infoHashV1,
|
||||
string? infoHashV2,
|
||||
long? lastActivity,
|
||||
string? magnetUri,
|
||||
float? maxRatio,
|
||||
int? maxSeedingTime,
|
||||
string? name,
|
||||
int? numberComplete,
|
||||
int? numberIncomplete,
|
||||
int? numberLeeches,
|
||||
int? numberSeeds,
|
||||
int? priority,
|
||||
float? progress,
|
||||
float? ratio,
|
||||
float? ratioLimit,
|
||||
string? savePath,
|
||||
long? seedingTime,
|
||||
int? seedingTimeLimit,
|
||||
long? seenComplete,
|
||||
bool? sequentialDownload,
|
||||
long? size,
|
||||
string? state,
|
||||
bool? superSeeding,
|
||||
IReadOnlyList<string>? tags,
|
||||
int? timeActive,
|
||||
long? totalSize,
|
||||
string? tracker,
|
||||
long? uploadLimit,
|
||||
long? uploaded,
|
||||
long? uploadedSession,
|
||||
long? uploadSpeed,
|
||||
long? reannounce)
|
||||
{
|
||||
AddedOn = addedOn;
|
||||
AmountLeft = amountLeft;
|
||||
AutomaticTorrentManagement = automaticTorrentManagement;
|
||||
Availability = availability;
|
||||
Category = category;
|
||||
Completed = completed;
|
||||
CompletionOn = completionOn;
|
||||
ContentPath = contentPath;
|
||||
DownloadLimit = downloadLimit;
|
||||
DownloadSpeed = downloadSpeed;
|
||||
Downloaded = downloaded;
|
||||
DownloadedSession = downloadedSession;
|
||||
EstimatedTimeOfArrival = estimatedTimeOfArrival;
|
||||
FirstLastPiecePriority = firstLastPiecePriority;
|
||||
ForceStart = forceStart;
|
||||
InfoHashV1 = infoHashV1;
|
||||
InfoHashV2 = infoHashV2;
|
||||
LastActivity = lastActivity;
|
||||
MagnetUri = magnetUri;
|
||||
MaxRatio = maxRatio;
|
||||
MaxSeedingTime = maxSeedingTime;
|
||||
Name = name;
|
||||
NumberComplete = numberComplete;
|
||||
NumberIncomplete = numberIncomplete;
|
||||
NumberLeeches = numberLeeches;
|
||||
NumberSeeds = numberSeeds;
|
||||
Priority = priority;
|
||||
Progress = progress;
|
||||
Ratio = ratio;
|
||||
RatioLimit = ratioLimit;
|
||||
SavePath = savePath;
|
||||
SeedingTime = seedingTime;
|
||||
SeedingTimeLimit = seedingTimeLimit;
|
||||
SeenComplete = seenComplete;
|
||||
SequentialDownload = sequentialDownload;
|
||||
Size = size;
|
||||
State = state;
|
||||
SuperSeeding = superSeeding;
|
||||
Tags = tags ?? [];
|
||||
TimeActive = timeActive;
|
||||
TotalSize = totalSize;
|
||||
Tracker = tracker;
|
||||
UploadLimit = uploadLimit;
|
||||
Uploaded = uploaded;
|
||||
UploadedSession = uploadedSession;
|
||||
UploadSpeed = uploadSpeed;
|
||||
Reannounce = reannounce;
|
||||
}
|
||||
|
||||
[JsonPropertyName("added_on")]
|
||||
public long? AddedOn { get; }
|
||||
|
||||
[JsonPropertyName("amount_left")]
|
||||
public long? AmountLeft { get; }
|
||||
|
||||
[JsonPropertyName("auto_tmm")]
|
||||
public bool? AutomaticTorrentManagement { get; }
|
||||
|
||||
[JsonPropertyName("availability")]
|
||||
public float? Availability { get; }
|
||||
|
||||
[JsonPropertyName("category")]
|
||||
public string? Category { get; }
|
||||
|
||||
[JsonPropertyName("completed")]
|
||||
public long? Completed { get; }
|
||||
|
||||
[JsonPropertyName("completion_on")]
|
||||
public long? CompletionOn { get; }
|
||||
|
||||
[JsonPropertyName("content_path")]
|
||||
public string? ContentPath { get; }
|
||||
|
||||
[JsonPropertyName("dl_limit")]
|
||||
public long? DownloadLimit { get; }
|
||||
|
||||
[JsonPropertyName("dlspeed")]
|
||||
public long? DownloadSpeed { get; }
|
||||
|
||||
[JsonPropertyName("downloaded")]
|
||||
public long? Downloaded { get; }
|
||||
|
||||
[JsonPropertyName("downloaded_session")]
|
||||
public long? DownloadedSession { get; }
|
||||
|
||||
[JsonPropertyName("eta")]
|
||||
public long? EstimatedTimeOfArrival { get; }
|
||||
|
||||
[JsonPropertyName("f_l_piece_prio")]
|
||||
public bool? FirstLastPiecePriority { get; }
|
||||
|
||||
[JsonPropertyName("force_start")]
|
||||
public bool? ForceStart { get; }
|
||||
|
||||
[JsonPropertyName("infohash_v1")]
|
||||
public string? InfoHashV1 { get; }
|
||||
|
||||
[JsonPropertyName("infohash_v2")]
|
||||
public string? InfoHashV2 { get; }
|
||||
|
||||
[JsonPropertyName("last_activity")]
|
||||
public long? LastActivity { get; }
|
||||
|
||||
[JsonPropertyName("magnet_uri")]
|
||||
public string? MagnetUri { get; }
|
||||
|
||||
[JsonPropertyName("max_ratio")]
|
||||
public float? MaxRatio { get; }
|
||||
|
||||
[JsonPropertyName("max_seeding_time")]
|
||||
public int? MaxSeedingTime { get; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; }
|
||||
|
||||
[JsonPropertyName("num_complete")]
|
||||
public int? NumberComplete { get; }
|
||||
|
||||
[JsonPropertyName("num_incomplete")]
|
||||
public int? NumberIncomplete { get; }
|
||||
|
||||
[JsonPropertyName("num_leechs")]
|
||||
public int? NumberLeeches { get; }
|
||||
|
||||
[JsonPropertyName("num_seeds")]
|
||||
public int? NumberSeeds { get; }
|
||||
|
||||
[JsonPropertyName("priority")]
|
||||
public int? Priority { get; }
|
||||
|
||||
[JsonPropertyName("progress")]
|
||||
public float? Progress { get; }
|
||||
|
||||
[JsonPropertyName("ratio")]
|
||||
public float? Ratio { get; }
|
||||
|
||||
[JsonPropertyName("ratio_limit")]
|
||||
public float? RatioLimit { get; }
|
||||
|
||||
[JsonPropertyName("save_path")]
|
||||
public string? SavePath { get; }
|
||||
|
||||
[JsonPropertyName("seeding_time")]
|
||||
public long? SeedingTime { get; }
|
||||
|
||||
[JsonPropertyName("seeding_time_limit")]
|
||||
public int? SeedingTimeLimit { get; }
|
||||
|
||||
[JsonPropertyName("seen_complete")]
|
||||
public long? SeenComplete { get; }
|
||||
|
||||
[JsonPropertyName("seq_dl")]
|
||||
public bool? SequentialDownload { get; }
|
||||
|
||||
[JsonPropertyName("size")]
|
||||
public long? Size { get; }
|
||||
|
||||
[JsonPropertyName("state")]
|
||||
public string? State { get; }
|
||||
|
||||
[JsonPropertyName("super_seeding")]
|
||||
public bool? SuperSeeding { get; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
[JsonConverter(typeof(CommaSeparatedJsonConverter))]
|
||||
public IReadOnlyList<string>? Tags { get; }
|
||||
|
||||
[JsonPropertyName("time_active")]
|
||||
public int? TimeActive { get; }
|
||||
|
||||
[JsonPropertyName("total_size")]
|
||||
public long? TotalSize { get; }
|
||||
|
||||
[JsonPropertyName("tracker")]
|
||||
public string? Tracker { get; }
|
||||
|
||||
[JsonPropertyName("up_limit")]
|
||||
public long? UploadLimit { get; }
|
||||
|
||||
[JsonPropertyName("uploaded")]
|
||||
public long? Uploaded { get; }
|
||||
|
||||
[JsonPropertyName("uploaded_session")]
|
||||
public long? UploadedSession { get; }
|
||||
|
||||
[JsonPropertyName("upspeed")]
|
||||
public long? UploadSpeed { get; }
|
||||
|
||||
[JsonPropertyName("reannounce")]
|
||||
public long? Reannounce { get; }
|
||||
}
|
||||
}
|
37
Lantean.QBitTorrentClient/Models/TorrentPeers.cs
Normal file
37
Lantean.QBitTorrentClient/Models/TorrentPeers.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record TorrentPeers
|
||||
{
|
||||
[JsonConstructor]
|
||||
public TorrentPeers(
|
||||
bool fullUpdate,
|
||||
IReadOnlyDictionary<string, Peer>? peers,
|
||||
IReadOnlyList<string>? peersRemoved,
|
||||
int requestId,
|
||||
bool? showFlags)
|
||||
{
|
||||
FullUpdate = fullUpdate;
|
||||
Peers = peers;
|
||||
PeersRemoved = peersRemoved;
|
||||
RequestId = requestId;
|
||||
ShowFlags = showFlags;
|
||||
}
|
||||
|
||||
[JsonPropertyName("full_update")]
|
||||
public bool FullUpdate { get; }
|
||||
|
||||
[JsonPropertyName("peers")]
|
||||
public IReadOnlyDictionary<string, Peer>? Peers { get; }
|
||||
|
||||
[JsonPropertyName("peers_removed")]
|
||||
public IReadOnlyList<string>? PeersRemoved { get; }
|
||||
|
||||
[JsonPropertyName("rid")]
|
||||
public int RequestId { get; }
|
||||
|
||||
[JsonPropertyName("show_flags")]
|
||||
public bool? ShowFlags { get; }
|
||||
}
|
||||
}
|
187
Lantean.QBitTorrentClient/Models/TorrentProperties.cs
Normal file
187
Lantean.QBitTorrentClient/Models/TorrentProperties.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record TorrentProperties
|
||||
{
|
||||
[JsonConstructor]
|
||||
public TorrentProperties(
|
||||
long additionDate,
|
||||
string comment,
|
||||
long completionDate,
|
||||
string createdBy,
|
||||
long creationDate,
|
||||
long downloadLimit,
|
||||
long downloadSpeed,
|
||||
long downloadSpeedAverage,
|
||||
int estimatedTimeOfArrival,
|
||||
long lastSeen,
|
||||
int connections,
|
||||
int connectionsLimit,
|
||||
int peers,
|
||||
int peersTotal,
|
||||
int pieceSize,
|
||||
int piecesHave,
|
||||
int piecesNum,
|
||||
int reannounce,
|
||||
string savePath,
|
||||
int seedingTime,
|
||||
int seeds,
|
||||
int seedsTotal,
|
||||
float shareRatio,
|
||||
int timeElapsed,
|
||||
long totalDownloaded,
|
||||
long totalDownloadedSession,
|
||||
long totalSize,
|
||||
long totalUploaded,
|
||||
long totalUploadedSession,
|
||||
long totalWasted,
|
||||
long uploadLimit,
|
||||
long uploadSpeed,
|
||||
long uploadSpeedAverage,
|
||||
string infoHashV1,
|
||||
string infoHashV2)
|
||||
{
|
||||
AdditionDate = additionDate;
|
||||
Comment = comment;
|
||||
CompletionDate = completionDate;
|
||||
CreatedBy = createdBy;
|
||||
CreationDate = creationDate;
|
||||
DownloadLimit = downloadLimit;
|
||||
DownloadSpeed = downloadSpeed;
|
||||
DownloadSpeedAverage = downloadSpeedAverage;
|
||||
EstimatedTimeOfArrival = estimatedTimeOfArrival;
|
||||
LastSeen = lastSeen;
|
||||
Connections = connections;
|
||||
ConnectionsLimit = connectionsLimit;
|
||||
Peers = peers;
|
||||
PeersTotal = peersTotal;
|
||||
PieceSize = pieceSize;
|
||||
PiecesHave = piecesHave;
|
||||
PiecesNum = piecesNum;
|
||||
Reannounce = reannounce;
|
||||
SavePath = savePath;
|
||||
SeedingTime = seedingTime;
|
||||
Seeds = seeds;
|
||||
SeedsTotal = seedsTotal;
|
||||
ShareRatio = shareRatio;
|
||||
TimeElapsed = timeElapsed;
|
||||
TotalDownloaded = totalDownloaded;
|
||||
TotalDownloadedSession = totalDownloadedSession;
|
||||
TotalSize = totalSize;
|
||||
TotalUploaded = totalUploaded;
|
||||
TotalUploadedSession = totalUploadedSession;
|
||||
TotalWasted = totalWasted;
|
||||
UploadLimit = uploadLimit;
|
||||
UploadSpeed = uploadSpeed;
|
||||
UploadSpeedAverage = uploadSpeedAverage;
|
||||
InfoHashV1 = infoHashV1;
|
||||
InfoHashV2 = infoHashV2;
|
||||
}
|
||||
|
||||
[JsonPropertyName("addition_date")]
|
||||
public long AdditionDate { get; }
|
||||
|
||||
[JsonPropertyName("comment")]
|
||||
public string Comment { get; }
|
||||
|
||||
[JsonPropertyName("completion_date")]
|
||||
public long CompletionDate { get; }
|
||||
|
||||
[JsonPropertyName("created_by")]
|
||||
public string CreatedBy { get; }
|
||||
|
||||
[JsonPropertyName("creation_date")]
|
||||
public long CreationDate { get; }
|
||||
|
||||
[JsonPropertyName("dl_limit")]
|
||||
public long DownloadLimit { get; }
|
||||
|
||||
[JsonPropertyName("dl_speed")]
|
||||
public long DownloadSpeed { get; }
|
||||
|
||||
[JsonPropertyName("dl_speed_avg")]
|
||||
public long DownloadSpeedAverage { get; }
|
||||
|
||||
[JsonPropertyName("eta")]
|
||||
public int EstimatedTimeOfArrival { get; }
|
||||
|
||||
[JsonPropertyName("last_seen")]
|
||||
public long LastSeen { get; }
|
||||
|
||||
[JsonPropertyName("nb_connections")]
|
||||
public int Connections { get; }
|
||||
|
||||
[JsonPropertyName("nb_connections_limit")]
|
||||
public int ConnectionsLimit { get; }
|
||||
|
||||
[JsonPropertyName("peers")]
|
||||
public int Peers { get; }
|
||||
|
||||
[JsonPropertyName("peers_total")]
|
||||
public int PeersTotal { get; }
|
||||
|
||||
[JsonPropertyName("piece_size")]
|
||||
public int PieceSize { get; }
|
||||
|
||||
[JsonPropertyName("pieces_have")]
|
||||
public int PiecesHave { get; }
|
||||
|
||||
[JsonPropertyName("pieces_num")]
|
||||
public int PiecesNum { get; }
|
||||
|
||||
[JsonPropertyName("reannounce")]
|
||||
public int Reannounce { get; }
|
||||
|
||||
[JsonPropertyName("save_path")]
|
||||
public string SavePath { get; }
|
||||
|
||||
[JsonPropertyName("seeding_time")]
|
||||
public int SeedingTime { get; }
|
||||
|
||||
[JsonPropertyName("seeds")]
|
||||
public int Seeds { get; }
|
||||
|
||||
[JsonPropertyName("seeds_total")]
|
||||
public int SeedsTotal { get; }
|
||||
|
||||
[JsonPropertyName("share_ratio")]
|
||||
public float ShareRatio { get; }
|
||||
|
||||
[JsonPropertyName("time_elapsed")]
|
||||
public int TimeElapsed { get; }
|
||||
|
||||
[JsonPropertyName("total_downloaded")]
|
||||
public long TotalDownloaded { get; }
|
||||
|
||||
[JsonPropertyName("total_downloaded_session")]
|
||||
public long TotalDownloadedSession { get; }
|
||||
|
||||
[JsonPropertyName("total_size")]
|
||||
public long TotalSize { get; }
|
||||
|
||||
[JsonPropertyName("total_uploaded")]
|
||||
public long TotalUploaded { get; }
|
||||
|
||||
[JsonPropertyName("total_uploaded_session")]
|
||||
public long TotalUploadedSession { get; }
|
||||
|
||||
[JsonPropertyName("total_wasted")]
|
||||
public long TotalWasted { get; }
|
||||
|
||||
[JsonPropertyName("up_limit")]
|
||||
public long UploadLimit { get; }
|
||||
|
||||
[JsonPropertyName("up_speed")]
|
||||
public long UploadSpeed { get; }
|
||||
|
||||
[JsonPropertyName("up_speed_avg")]
|
||||
public long UploadSpeedAverage { get; }
|
||||
|
||||
[JsonPropertyName("infohash_v1")]
|
||||
public string InfoHashV1 { get; }
|
||||
|
||||
[JsonPropertyName("infohash_v2")]
|
||||
public string InfoHashV2 { get; }
|
||||
}
|
||||
}
|
52
Lantean.QBitTorrentClient/Models/TorrentTrackers.cs
Normal file
52
Lantean.QBitTorrentClient/Models/TorrentTrackers.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record TorrentTrackers
|
||||
{
|
||||
[JsonConstructor]
|
||||
public TorrentTrackers(
|
||||
string url,
|
||||
TrackerStatus status,
|
||||
int tier,
|
||||
int peers,
|
||||
int seeds,
|
||||
int leeches,
|
||||
int downloads,
|
||||
string message)
|
||||
{
|
||||
Url = url;
|
||||
Status = status;
|
||||
Tier = tier;
|
||||
Peers = peers;
|
||||
Seeds = seeds;
|
||||
Leeches = leeches;
|
||||
Downloads = downloads;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
|
||||
[JsonPropertyName("status")]
|
||||
public TrackerStatus Status { get; }
|
||||
|
||||
[JsonPropertyName("tier")]
|
||||
public int Tier { get; }
|
||||
|
||||
[JsonPropertyName("num_peers")]
|
||||
public int Peers { get; }
|
||||
|
||||
[JsonPropertyName("num_seeds")]
|
||||
public int Seeds { get; }
|
||||
|
||||
[JsonPropertyName("num_leeches")]
|
||||
public int Leeches { get; }
|
||||
|
||||
[JsonPropertyName("num_downloaded")]
|
||||
public int Downloads { get; }
|
||||
|
||||
[JsonPropertyName("msg")]
|
||||
public string Message { get; }
|
||||
}
|
||||
}
|
11
Lantean.QBitTorrentClient/Models/TrackerStatus.cs
Normal file
11
Lantean.QBitTorrentClient/Models/TrackerStatus.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public enum TrackerStatus
|
||||
{
|
||||
Disabled = 0,
|
||||
Uncontacted = 1,
|
||||
Working = 2,
|
||||
Updating = 3,
|
||||
NotWorking = 4,
|
||||
}
|
||||
}
|
613
Lantean.QBitTorrentClient/Models/UpdatePreferences.cs
Normal file
613
Lantean.QBitTorrentClient/Models/UpdatePreferences.cs
Normal file
@@ -0,0 +1,613 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record UpdatePreferences
|
||||
{
|
||||
[JsonPropertyName("add_to_top_of_queue")]
|
||||
public bool? AddToTopOfQueue { get; set; }
|
||||
|
||||
[JsonPropertyName("add_trackers")]
|
||||
public string? AddTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("add_trackers_enabled")]
|
||||
public bool? AddTrackersEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("alt_dl_limit")]
|
||||
public int? AltDlLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("alt_up_limit")]
|
||||
public int? AltUpLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("alternative_webui_enabled")]
|
||||
public bool? AlternativeWebuiEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("alternative_webui_path")]
|
||||
public string? AlternativeWebuiPath { get; set; }
|
||||
|
||||
[JsonPropertyName("announce_ip")]
|
||||
public string? AnnounceIp { get; set; }
|
||||
|
||||
[JsonPropertyName("announce_to_all_tiers")]
|
||||
public bool? AnnounceToAllTiers { get; set; }
|
||||
|
||||
[JsonPropertyName("announce_to_all_trackers")]
|
||||
public bool? AnnounceToAllTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("anonymous_mode")]
|
||||
public bool? AnonymousMode { get; set; }
|
||||
|
||||
[JsonPropertyName("async_io_threads")]
|
||||
public int? AsyncIoThreads { get; set; }
|
||||
|
||||
[JsonPropertyName("auto_delete_mode")]
|
||||
public int? AutoDeleteMode { get; set; }
|
||||
|
||||
[JsonPropertyName("auto_tmm_enabled")]
|
||||
public bool? AutoTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("autorun_enabled")]
|
||||
public bool? AutorunEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("autorun_on_torrent_added_enabled")]
|
||||
public bool? AutorunOnTorrentAddedEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("autorun_on_torrent_added_program")]
|
||||
public string? AutorunOnTorrentAddedProgram { get; set; }
|
||||
|
||||
[JsonPropertyName("autorun_program")]
|
||||
public string? AutorunProgram { get; set; }
|
||||
|
||||
[JsonPropertyName("banned_IPs")]
|
||||
public string? BannedIPs { get; set; }
|
||||
|
||||
[JsonPropertyName("bdecode_depth_limit")]
|
||||
public int? BdecodeDepthLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("bdecode_token_limit")]
|
||||
public int? BdecodeTokenLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("bittorrent_protocol")]
|
||||
public int? BittorrentProtocol { get; set; }
|
||||
|
||||
[JsonPropertyName("block_peers_on_privileged_ports")]
|
||||
public bool? BlockPeersOnPrivilegedPorts { get; set; }
|
||||
|
||||
[JsonPropertyName("bypass_auth_subnet_whitelist")]
|
||||
public string? BypassAuthSubnetWhitelist { get; set; }
|
||||
|
||||
[JsonPropertyName("bypass_auth_subnet_whitelist_enabled")]
|
||||
public bool? BypassAuthSubnetWhitelistEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("bypass_local_auth")]
|
||||
public bool? BypassLocalAuth { get; set; }
|
||||
|
||||
[JsonPropertyName("category_changed_tmm_enabled")]
|
||||
public bool? CategoryChangedTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("checking_memory_use")]
|
||||
public int? CheckingMemoryUse { get; set; }
|
||||
|
||||
[JsonPropertyName("connection_speed")]
|
||||
public int? ConnectionSpeed { get; set; }
|
||||
|
||||
[JsonPropertyName("current_interface_address")]
|
||||
public string? CurrentInterfaceAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("current_interface_name")]
|
||||
public string? CurrentInterfaceName { get; set; }
|
||||
|
||||
[JsonPropertyName("current_network_interface")]
|
||||
public string? CurrentNetworkInterface { get; set; }
|
||||
|
||||
[JsonPropertyName("dht")]
|
||||
public bool? Dht { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_cache")]
|
||||
public int? DiskCache { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_cache_ttl")]
|
||||
public int? DiskCacheTtl { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_io_read_mode")]
|
||||
public int? DiskIoReadMode { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_io_type")]
|
||||
public int? DiskIoType { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_io_write_mode")]
|
||||
public int? DiskIoWriteMode { get; set; }
|
||||
|
||||
[JsonPropertyName("disk_queue_size")]
|
||||
public int? DiskQueueSize { get; set; }
|
||||
|
||||
[JsonPropertyName("dl_limit")]
|
||||
public int? DlLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("dont_count_slow_torrents")]
|
||||
public bool? DontCountSlowTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_domain")]
|
||||
public string? DyndnsDomain { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_enabled")]
|
||||
public bool? DyndnsEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_password")]
|
||||
public string? DyndnsPassword { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_service")]
|
||||
public int? DyndnsService { get; set; }
|
||||
|
||||
[JsonPropertyName("dyndns_username")]
|
||||
public string? DyndnsUsername { get; set; }
|
||||
|
||||
[JsonPropertyName("embedded_tracker_port")]
|
||||
public int? EmbeddedTrackerPort { get; set; }
|
||||
|
||||
[JsonPropertyName("embedded_tracker_port_forwarding")]
|
||||
public bool? EmbeddedTrackerPortForwarding { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_coalesce_read_write")]
|
||||
public bool? EnableCoalesceReadWrite { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_embedded_tracker")]
|
||||
public bool? EnableEmbeddedTracker { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_multi_connections_from_same_ip")]
|
||||
public bool? EnableMultiConnectionsFromSameIp { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_piece_extent_affinity")]
|
||||
public bool? EnablePieceExtentAffinity { get; set; }
|
||||
|
||||
[JsonPropertyName("enable_upload_suggestions")]
|
||||
public bool? EnableUploadSuggestions { get; set; }
|
||||
|
||||
[JsonPropertyName("encryption")]
|
||||
public int? Encryption { get; set; }
|
||||
|
||||
[JsonPropertyName("excluded_file_names")]
|
||||
public string? ExcludedFileNames { get; set; }
|
||||
|
||||
[JsonPropertyName("excluded_file_names_enabled")]
|
||||
public bool? ExcludedFileNamesEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("export_dir")]
|
||||
public string? ExportDir { get; set; }
|
||||
|
||||
[JsonPropertyName("export_dir_fin")]
|
||||
public string? ExportDirFin { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_age")]
|
||||
public int? FileLogAge { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_age_type")]
|
||||
public int? FileLogAgeType { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_backup_enabled")]
|
||||
public bool? FileLogBackupEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_delete_old")]
|
||||
public bool? FileLogDeleteOld { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_enabled")]
|
||||
public bool? FileLogEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_max_size")]
|
||||
public int? FileLogMaxSize { get; set; }
|
||||
|
||||
[JsonPropertyName("file_log_path")]
|
||||
public string? FileLogPath { get; set; }
|
||||
|
||||
[JsonPropertyName("file_pool_size")]
|
||||
public int? FilePoolSize { get; set; }
|
||||
|
||||
[JsonPropertyName("hashing_threads")]
|
||||
public int? HashingThreads { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_address")]
|
||||
public string? I2pAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_enabled")]
|
||||
public bool? I2pEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_inbound_length")]
|
||||
public int? I2pInboundLength { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_inbound_quantity")]
|
||||
public int? I2pInboundQuantity { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_mixed_mode")]
|
||||
public bool? I2pMixedMode { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_outbound_length")]
|
||||
public int? I2pOutboundLength { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_outbound_quantity")]
|
||||
public int? I2pOutboundQuantity { get; set; }
|
||||
|
||||
[JsonPropertyName("i2p_port")]
|
||||
public int? I2pPort { get; set; }
|
||||
|
||||
[JsonPropertyName("idn_support_enabled")]
|
||||
public bool? IdnSupportEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("incomplete_files_ext")]
|
||||
public bool? IncompleteFilesExt { get; set; }
|
||||
|
||||
[JsonPropertyName("ip_filter_enabled")]
|
||||
public bool? IpFilterEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("ip_filter_path")]
|
||||
public string? IpFilterPath { get; set; }
|
||||
|
||||
[JsonPropertyName("ip_filter_trackers")]
|
||||
public bool? IpFilterTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("limit_lan_peers")]
|
||||
public bool? LimitLanPeers { get; set; }
|
||||
|
||||
[JsonPropertyName("limit_tcp_overhead")]
|
||||
public bool? LimitTcpOverhead { get; set; }
|
||||
|
||||
[JsonPropertyName("limit_utp_rate")]
|
||||
public bool? LimitUtpRate { get; set; }
|
||||
|
||||
[JsonPropertyName("listen_port")]
|
||||
public int? ListenPort { get; set; }
|
||||
|
||||
[JsonPropertyName("locale")]
|
||||
public string? Locale { get; set; }
|
||||
|
||||
[JsonPropertyName("lsd")]
|
||||
public bool? Lsd { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_auth_enabled")]
|
||||
public bool? MailNotificationAuthEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_email")]
|
||||
public string? MailNotificationEmail { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_enabled")]
|
||||
public bool? MailNotificationEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_password")]
|
||||
public string? MailNotificationPassword { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_sender")]
|
||||
public string? MailNotificationSender { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_smtp")]
|
||||
public string? MailNotificationSmtp { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_ssl_enabled")]
|
||||
public bool? MailNotificationSslEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("mail_notification_username")]
|
||||
public string? MailNotificationUsername { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_checking_torrents")]
|
||||
public int? MaxActiveCheckingTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_downloads")]
|
||||
public int? MaxActiveDownloads { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_torrents")]
|
||||
public int? MaxActiveTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("max_active_uploads")]
|
||||
public int? MaxActiveUploads { get; set; }
|
||||
|
||||
[JsonPropertyName("max_concurrent_http_announces")]
|
||||
public int? MaxConcurrentHttpAnnounces { get; set; }
|
||||
|
||||
[JsonPropertyName("max_connec")]
|
||||
public int? MaxConnec { get; set; }
|
||||
|
||||
[JsonPropertyName("max_connec_per_torrent")]
|
||||
public int? MaxConnecPerTorrent { get; set; }
|
||||
|
||||
[JsonPropertyName("max_inactive_seeding_time")]
|
||||
public int? MaxInactiveSeedingTime { get; set; }
|
||||
|
||||
[JsonPropertyName("max_inactive_seeding_time_enabled")]
|
||||
public bool? MaxInactiveSeedingTimeEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio")]
|
||||
public int? MaxRatio { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio_act")]
|
||||
public int? MaxRatioAct { get; set; }
|
||||
|
||||
[JsonPropertyName("max_ratio_enabled")]
|
||||
public bool? MaxRatioEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("max_seeding_time")]
|
||||
public int? MaxSeedingTime { get; set; }
|
||||
|
||||
[JsonPropertyName("max_seeding_time_enabled")]
|
||||
public bool? MaxSeedingTimeEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("max_uploads")]
|
||||
public int? MaxUploads { get; set; }
|
||||
|
||||
[JsonPropertyName("max_uploads_per_torrent")]
|
||||
public int? MaxUploadsPerTorrent { get; set; }
|
||||
|
||||
[JsonPropertyName("memory_working_set_limit")]
|
||||
public int? MemoryWorkingSetLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("merge_trackers")]
|
||||
public bool? MergeTrackers { get; set; }
|
||||
|
||||
[JsonPropertyName("outgoing_ports_max")]
|
||||
public int? OutgoingPortsMax { get; set; }
|
||||
|
||||
[JsonPropertyName("outgoing_ports_min")]
|
||||
public int? OutgoingPortsMin { get; set; }
|
||||
|
||||
[JsonPropertyName("peer_tos")]
|
||||
public int? PeerTos { get; set; }
|
||||
|
||||
[JsonPropertyName("peer_turnover")]
|
||||
public int? PeerTurnover { get; set; }
|
||||
|
||||
[JsonPropertyName("peer_turnover_cutoff")]
|
||||
public int? PeerTurnoverCutoff { get; set; }
|
||||
|
||||
[JsonPropertyName("peer_turnover_interval")]
|
||||
public int? PeerTurnoverInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("performance_warning")]
|
||||
public bool? PerformanceWarning { get; set; }
|
||||
|
||||
[JsonPropertyName("pex")]
|
||||
public bool? Pex { get; set; }
|
||||
|
||||
[JsonPropertyName("preallocate_all")]
|
||||
public bool? PreallocateAll { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_auth_enabled")]
|
||||
public bool? ProxyAuthEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_bittorrent")]
|
||||
public bool? ProxyBittorrent { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_hostname_lookup")]
|
||||
public bool? ProxyHostnameLookup { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_ip")]
|
||||
public string? ProxyIp { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_misc")]
|
||||
public bool? ProxyMisc { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_password")]
|
||||
public string? ProxyPassword { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_peer_connections")]
|
||||
public bool? ProxyPeerConnections { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_port")]
|
||||
public int? ProxyPort { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_rss")]
|
||||
public bool? ProxyRss { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_type")]
|
||||
public string? ProxyType { get; set; }
|
||||
|
||||
[JsonPropertyName("proxy_username")]
|
||||
public string? ProxyUsername { get; set; }
|
||||
|
||||
[JsonPropertyName("queueing_enabled")]
|
||||
public bool? QueueingEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("random_port")]
|
||||
public bool? RandomPort { get; set; }
|
||||
|
||||
[JsonPropertyName("reannounce_when_address_changed")]
|
||||
public bool? ReannounceWhenAddressChanged { get; set; }
|
||||
|
||||
[JsonPropertyName("recheck_completed_torrents")]
|
||||
public bool? RecheckCompletedTorrents { get; set; }
|
||||
|
||||
[JsonPropertyName("refresh_interval")]
|
||||
public int? RefreshInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("request_queue_size")]
|
||||
public int? RequestQueueSize { get; set; }
|
||||
|
||||
[JsonPropertyName("resolve_peer_countries")]
|
||||
public bool? ResolvePeerCountries { get; set; }
|
||||
|
||||
[JsonPropertyName("resume_data_storage_type")]
|
||||
public string? ResumeDataStorageType { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_auto_downloading_enabled")]
|
||||
public bool? RssAutoDownloadingEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_download_repack_proper_episodes")]
|
||||
public bool? RssDownloadRepackProperEpisodes { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_max_articles_per_feed")]
|
||||
public int? RssMaxArticlesPerFeed { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_processing_enabled")]
|
||||
public bool? RssProcessingEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_refresh_interval")]
|
||||
public int? RssRefreshInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("rss_smart_episode_filters")]
|
||||
public string? RssSmartEpisodeFilters { get; set; }
|
||||
|
||||
[JsonPropertyName("save_path")]
|
||||
public string? SavePath { get; set; }
|
||||
|
||||
[JsonPropertyName("save_path_changed_tmm_enabled")]
|
||||
public bool? SavePathChangedTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("save_resume_data_interval")]
|
||||
public int? SaveResumeDataInterval { get; set; }
|
||||
|
||||
[JsonPropertyName("scan_dirs")]
|
||||
public Dictionary<string, SaveLocation>? ScanDirs { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_from_hour")]
|
||||
public int? ScheduleFromHour { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_from_min")]
|
||||
public int? ScheduleFromMin { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_to_hour")]
|
||||
public int? ScheduleToHour { get; set; }
|
||||
|
||||
[JsonPropertyName("schedule_to_min")]
|
||||
public int? ScheduleToMin { get; set; }
|
||||
|
||||
[JsonPropertyName("scheduler_days")]
|
||||
public int? SchedulerDays { get; set; }
|
||||
|
||||
[JsonPropertyName("scheduler_enabled")]
|
||||
public bool? SchedulerEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("send_buffer_low_watermark")]
|
||||
public int? SendBufferLowWatermark { get; set; }
|
||||
|
||||
[JsonPropertyName("send_buffer_watermark")]
|
||||
public int? SendBufferWatermark { get; set; }
|
||||
|
||||
[JsonPropertyName("send_buffer_watermark_factor")]
|
||||
public int? SendBufferWatermarkFactor { get; set; }
|
||||
|
||||
[JsonPropertyName("slow_torrent_dl_rate_threshold")]
|
||||
public int? SlowTorrentDlRateThreshold { get; set; }
|
||||
|
||||
[JsonPropertyName("slow_torrent_inactive_timer")]
|
||||
public int? SlowTorrentInactiveTimer { get; set; }
|
||||
|
||||
[JsonPropertyName("slow_torrent_ul_rate_threshold")]
|
||||
public int? SlowTorrentUlRateThreshold { get; set; }
|
||||
|
||||
[JsonPropertyName("socket_backlog_size")]
|
||||
public int? SocketBacklogSize { get; set; }
|
||||
|
||||
[JsonPropertyName("socket_receive_buffer_size")]
|
||||
public int? SocketReceiveBufferSize { get; set; }
|
||||
|
||||
[JsonPropertyName("socket_send_buffer_size")]
|
||||
public int? SocketSendBufferSize { get; set; }
|
||||
|
||||
[JsonPropertyName("ssrf_mitigation")]
|
||||
public bool? SsrfMitigation { get; set; }
|
||||
|
||||
[JsonPropertyName("start_paused_enabled")]
|
||||
public bool? StartPausedEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("stop_tracker_timeout")]
|
||||
public int? StopTrackerTimeout { get; set; }
|
||||
|
||||
[JsonPropertyName("temp_path")]
|
||||
public string? TempPath { get; set; }
|
||||
|
||||
[JsonPropertyName("temp_path_enabled")]
|
||||
public bool? TempPathEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("torrent_changed_tmm_enabled")]
|
||||
public bool? TorrentChangedTmmEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("torrent_content_layout")]
|
||||
public string? TorrentContentLayout { get; set; }
|
||||
|
||||
[JsonPropertyName("torrent_file_size_limit")]
|
||||
public int? TorrentFileSizeLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("torrent_stop_condition")]
|
||||
public string? TorrentStopCondition { get; set; }
|
||||
|
||||
[JsonPropertyName("up_limit")]
|
||||
public int? UpLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_choking_algorithm")]
|
||||
public int? UploadChokingAlgorithm { get; set; }
|
||||
|
||||
[JsonPropertyName("upload_slots_behavior")]
|
||||
public int? UploadSlotsBehavior { get; set; }
|
||||
|
||||
[JsonPropertyName("upnp")]
|
||||
public bool? Upnp { get; set; }
|
||||
|
||||
[JsonPropertyName("upnp_lease_duration")]
|
||||
public int? UpnpLeaseDuration { get; set; }
|
||||
|
||||
[JsonPropertyName("use_category_paths_in_manual_mode")]
|
||||
public bool? UseCategoryPathsInManualMode { get; set; }
|
||||
|
||||
[JsonPropertyName("use_https")]
|
||||
public bool? UseHttps { get; set; }
|
||||
|
||||
[JsonPropertyName("use_subcategories")]
|
||||
public bool? UseSubcategories { get; set; }
|
||||
|
||||
[JsonPropertyName("utp_tcp_mixed_mode")]
|
||||
public int? UtpTcpMixedMode { get; set; }
|
||||
|
||||
[JsonPropertyName("validate_https_tracker_certificate")]
|
||||
public bool? ValidateHttpsTrackerCertificate { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_address")]
|
||||
public string? WebUiAddress { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_ban_duration")]
|
||||
public int? WebUiBanDuration { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_clickjacking_protection_enabled")]
|
||||
public bool? WebUiClickjackingProtectionEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_csrf_protection_enabled")]
|
||||
public bool? WebUiCsrfProtectionEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_custom_http_headers")]
|
||||
public string? WebUiCustomHttpHeaders { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_domain_list")]
|
||||
public string? WebUiDomainList { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_host_header_validation_enabled")]
|
||||
public bool? WebUiHostHeaderValidationEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_https_cert_path")]
|
||||
public string? WebUiHttpsCertPath { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_https_key_path")]
|
||||
public string? WebUiHttpsKeyPath { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_max_auth_fail_count")]
|
||||
public int? WebUiMaxAuthFailCount { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_port")]
|
||||
public int? WebUiPort { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_reverse_proxies_list")]
|
||||
public string? WebUiReverseProxiesList { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_reverse_proxy_enabled")]
|
||||
public bool? WebUiReverseProxyEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_secure_cookie_enabled")]
|
||||
public bool? WebUiSecureCookieEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_session_timeout")]
|
||||
public int? WebUiSessionTimeout { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_upnp")]
|
||||
public bool? WebUiUpnp { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_use_custom_http_headers_enabled")]
|
||||
public bool? WebUiUseCustomHttpHeadersEnabled { get; set; }
|
||||
|
||||
[JsonPropertyName("web_ui_username")]
|
||||
public string? WebUiUsername { get; set; }
|
||||
}
|
||||
}
|
16
Lantean.QBitTorrentClient/Models/WebSeed.cs
Normal file
16
Lantean.QBitTorrentClient/Models/WebSeed.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient.Models
|
||||
{
|
||||
public record WebSeed
|
||||
{
|
||||
[JsonConstructor]
|
||||
public WebSeed(string url)
|
||||
{
|
||||
Url = url;
|
||||
}
|
||||
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public static class MultipartFormDataContentExtensions
|
||||
{
|
||||
public static void AddString(this MultipartFormDataContent content, string name, string value)
|
||||
{
|
||||
content.Add(new StringContent(value), name);
|
||||
}
|
||||
|
||||
public static void AddString(this MultipartFormDataContent content, string name, bool value)
|
||||
{
|
||||
content.AddString(name, value ? "true" : "false");
|
||||
}
|
||||
|
||||
public static void AddString(this MultipartFormDataContent content, string name, int value)
|
||||
{
|
||||
content.AddString(name, value.ToString());
|
||||
}
|
||||
|
||||
public static void AddString(this MultipartFormDataContent content, string name, long value)
|
||||
{
|
||||
content.AddString(name, value.ToString());
|
||||
}
|
||||
|
||||
public static void AddString(this MultipartFormDataContent content, string name, float 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());
|
||||
}
|
||||
}
|
||||
}
|
67
Lantean.QBitTorrentClient/QueryBuilder.cs
Normal file
67
Lantean.QBitTorrentClient/QueryBuilder.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public class QueryBuilder
|
||||
{
|
||||
private readonly IList<KeyValuePair<string, string>> _parameters;
|
||||
|
||||
public QueryBuilder()
|
||||
{
|
||||
_parameters = [];
|
||||
}
|
||||
|
||||
public QueryBuilder(IList<KeyValuePair<string, string>> parameters)
|
||||
{
|
||||
_parameters = parameters;
|
||||
}
|
||||
|
||||
public QueryBuilder Add(string key, string value)
|
||||
{
|
||||
_parameters.Add(new KeyValuePair<string, string>(key, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBuilder AddIfNotNullOrEmpty(string key, string value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
_parameters.Add(new KeyValuePair<string, string>(key, value));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public string ToQueryString()
|
||||
{
|
||||
if (_parameters.Count == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var queryString = new StringBuilder();
|
||||
for (int i = 0; i < _parameters.Count; i++)
|
||||
{
|
||||
var kvp = _parameters[i];
|
||||
if (i == 0)
|
||||
{
|
||||
queryString.Append('?');
|
||||
}
|
||||
else
|
||||
{
|
||||
queryString.Append('&');
|
||||
}
|
||||
queryString.Append(Uri.EscapeDataString(kvp.Key));
|
||||
queryString.Append('=');
|
||||
queryString.Append(Uri.EscapeDataString(kvp.Value));
|
||||
}
|
||||
|
||||
return queryString.ToString();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToQueryString();
|
||||
}
|
||||
}
|
||||
}
|
40
Lantean.QBitTorrentClient/QueryBuilderExtensions.cs
Normal file
40
Lantean.QBitTorrentClient/QueryBuilderExtensions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public static class QueryBuilderExtensions
|
||||
{
|
||||
public static QueryBuilder Add(this QueryBuilder builder, string key, bool value)
|
||||
{
|
||||
return builder.Add(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
public static QueryBuilder Add(this QueryBuilder builder, string key, int value)
|
||||
{
|
||||
return builder.Add(key, value.ToString());
|
||||
}
|
||||
|
||||
public static QueryBuilder Add(this QueryBuilder builder, string key, long value)
|
||||
{
|
||||
return builder.Add(key, value.ToString());
|
||||
}
|
||||
|
||||
public static QueryBuilder Add(this QueryBuilder builder, string key, DateTimeOffset value, bool useSeconds = true)
|
||||
{
|
||||
return builder.Add(key, useSeconds ? value.ToUnixTimeSeconds() : value.ToUnixTimeMilliseconds());
|
||||
}
|
||||
|
||||
public static QueryBuilder Add(this QueryBuilder builder, string key, Enum value)
|
||||
{
|
||||
return builder.Add(key, value.ToString());
|
||||
}
|
||||
|
||||
public static QueryBuilder AddPipeSeparated<T>(this QueryBuilder builder, string key, IEnumerable<T> values)
|
||||
{
|
||||
return builder.Add(key, string.Join('|', values));
|
||||
}
|
||||
|
||||
public static QueryBuilder AddCommaSeparated<T>(this QueryBuilder builder, string key, IEnumerable<T> values)
|
||||
{
|
||||
return builder.Add(key, string.Join(',', values));
|
||||
}
|
||||
}
|
||||
}
|
19
Lantean.QBitTorrentClient/SerializerOptions.cs
Normal file
19
Lantean.QBitTorrentClient/SerializerOptions.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Lantean.QBitTorrentClient.Converters;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Lantean.QBitTorrentClient
|
||||
{
|
||||
public static class SerializerOptions
|
||||
{
|
||||
public static JsonSerializerOptions Options { get; }
|
||||
|
||||
static SerializerOptions()
|
||||
{
|
||||
Options = new JsonSerializerOptions();
|
||||
Options.Converters.Add(new StringFloatJsonConverter());
|
||||
Options.Converters.Add(new SaveLocationJsonConverter());
|
||||
Options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user