diff --git a/README.md b/README.md index 13ddaa0..ee58842 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Transmission-RPC-API [Official Transmission RPC specs](https://github.com/transmission/transmission/blob/master/extras/rpc-spec.txt) C# implementation of the Transmission RPC API. +Up to date with Transmission RPC specification as of Transmission 4.1.0 (rpc-version-semver 5.4.0, rpc-version: 18) | Command | Not Implemented | Implemented| | -------------------- |:-:|:-:| @@ -32,6 +33,9 @@ C# implementation of the Transmission RPC API. | queue-move-down | | x | | queue-move-bottom | | x | | free-space | | x | +| group-set | | x | +| group-get | | x | + How to use ------------- diff --git a/Transmission.API.RPC.Test/MethodsTest.cs b/Transmission.API.RPC.Test/MethodsTest.cs index ccf2cee..8a1e342 100644 --- a/Transmission.API.RPC.Test/MethodsTest.cs +++ b/Transmission.API.RPC.Test/MethodsTest.cs @@ -44,7 +44,7 @@ public void AddTorrent_Test() var newTorrentInfo = client.TorrentAdd(torrent); Assert.IsNotNull(newTorrentInfo); - Assert.IsTrue(newTorrentInfo.ID != 0); + Assert.IsTrue(newTorrentInfo.Id != 0); } [TestMethod] @@ -59,7 +59,7 @@ public void AddTorrent_Magnet_Test() var newTorrentInfo = client.TorrentAdd(torrent); Assert.IsNotNull(newTorrentInfo); - Assert.IsTrue(newTorrentInfo.ID != 0); + Assert.IsTrue(newTorrentInfo.Id != 0); } [TestMethod] @@ -84,13 +84,13 @@ public void SetTorrentSettings_Test() var trackerCount = torrentInfo.Trackers.Length; TorrentSettings settings = new TorrentSettings() { - IDs = new object[] { torrentInfo.HashString }, - TrackerRemove = new int[] { trackerInfo.ID } + Ids = new object[] { torrentInfo.HashString }, + TrackerRemove = new long[] { trackerInfo.Id } }; client.TorrentSet(settings); - torrentsInfo = client.TorrentGet(TorrentFields.ALL_FIELDS, torrentInfo.ID); + torrentsInfo = client.TorrentGet(TorrentFields.ALL_FIELDS, torrentInfo.Id); torrentInfo = torrentsInfo.Torrents.FirstOrDefault(); Assert.IsFalse(trackerCount == torrentInfo.Trackers.Length); @@ -103,10 +103,10 @@ public void RenamePathTorrent_Test() var torrentInfo = torrentsInfo.Torrents.FirstOrDefault(); Assert.IsNotNull(torrentInfo, "Torrent not found"); - var result = client.TorrentRenamePath(torrentInfo.ID, torrentInfo.Files[0].Name, "test_" + torrentInfo.Files[0].Name); + var result = client.TorrentRenamePath(torrentInfo.Id, torrentInfo.Files[0].Name, "test_" + torrentInfo.Files[0].Name); Assert.IsNotNull(result, "Torrent not found"); - Assert.IsTrue(result.ID != 0); + Assert.IsTrue(result.Id != 0); } [TestMethod] @@ -116,11 +116,11 @@ public void RemoveTorrent_Test() var torrentInfo = torrentsInfo.Torrents.FirstOrDefault(); Assert.IsNotNull(torrentInfo, "Torrent not found"); - client.TorrentRemove(new int[] { torrentInfo.ID }); + client.TorrentRemove(new long[] { torrentInfo.Id }); torrentsInfo = client.TorrentGet(TorrentFields.ALL_FIELDS); - Assert.IsFalse(torrentsInfo.Torrents.Any(t => t.ID == torrentInfo.ID)); + Assert.IsFalse(torrentsInfo.Torrents.Any(t => t.Id == torrentInfo.Id)); } #endregion @@ -142,7 +142,7 @@ public void ChangeSessionTest() var sessionInformation = client.GetSessionInformation(); //Save old speed limit up - var oldSpeedLimit = sessionInformation.SpeedLimitUp; + var oldSpeedLimit = (long)sessionInformation.SpeedLimitUp; //Set new session settings client.SetSessionSettings(new SessionSettings() { SpeedLimitUp = 100 }); diff --git a/Transmission.API.RPC.Test/Transmission.API.RPC.Test.csproj b/Transmission.API.RPC.Test/Transmission.API.RPC.Test.csproj index 818fab3..cb17e6e 100644 --- a/Transmission.API.RPC.Test/Transmission.API.RPC.Test.csproj +++ b/Transmission.API.RPC.Test/Transmission.API.RPC.Test.csproj @@ -1,7 +1,7 @@  - netcoreapp2.0 + netcoreapp3.1 diff --git a/Transmission.API.RPC/Arguments/BandwidthGroupSettings.cs b/Transmission.API.RPC/Arguments/BandwidthGroupSettings.cs new file mode 100644 index 0000000..8bbabc1 --- /dev/null +++ b/Transmission.API.RPC/Arguments/BandwidthGroupSettings.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Transmission.API.RPC.Common; + +namespace Transmission.API.RPC.Arguments +{ + /// + /// Bandwidth group settings for editing bandwidth groups + /// + public class BandwidthGroupSettings : ArgumentsBase + { + /// + /// Session limits are honored + /// + public bool HonorsSessionLimits { get { return GetValue("honorsSessionLimits"); } set { this["honorsSessionLimits"] = value; } } + + /// + /// Name of the bandwidth group + /// + public string Name { get { return GetValue("name"); } set { this["name"] = value; } } + + /// + /// Max global download speed of this bandwidth group (KBps) + /// + public long SpeedLimitDown { get { return GetValue("speed-limit-down"); } set { this["speed-limit-down"] = value; } } + + /// + /// True means enabled + /// + public bool SpeedLimitDownEnabled { get { return GetValue("speed-limit-down-enabled"); } set { this["speed-limit-down-enabled"] = value; } } + + /// + /// Max global upload speed of this bandwidth group (KBps) + /// + public long SpeedLimitUp { get { return GetValue("speed-limit-up"); } set { this["speed-limit-up"] = value; } } + + /// + /// True means enabled + /// + public bool SpeedLimitUpEnabled { get { return GetValue("speed-limit-up-enabled"); } set { this["speed-limit-up-enabled"] = value; } } + } +} diff --git a/Transmission.API.RPC/Arguments/NewTorrent.cs b/Transmission.API.RPC/Arguments/NewTorrent.cs index f367434..0ebc44f 100644 --- a/Transmission.API.RPC/Arguments/NewTorrent.cs +++ b/Transmission.API.RPC/Arguments/NewTorrent.cs @@ -28,6 +28,11 @@ public class NewTorrent : ArgumentsBase /// public string Filename { get { return GetValue("filename"); } set { this["filename"] = value; } } + /// + /// Array of labels applied to the torrent + /// + public string[] Labels { get { return GetValue("labels"); } set { this["labels"] = value; } } + /// /// base64-encoded .torrent content /// @@ -41,36 +46,36 @@ public class NewTorrent : ArgumentsBase /// /// maximum number of peers /// - public int? PeerLimit { get { return GetValue("peer-limit"); } set { this["peer-limit"] = value; } } + public long PeerLimit { get { return GetValue("peer-limit"); } set { this["peer-limit"] = value; } } /// /// Torrent's bandwidth priority /// - public int? BandwidthPriority { get { return GetValue("bandwidthPriority"); } set { this["bandwidthPriority"] = value; } } + public long BandwidthPriority { get { return GetValue("bandwidthPriority"); } set { this["bandwidthPriority"] = value; } } /// /// Indices of file(s) to download /// - public int[] FilesWanted { get { return GetValue("files-wanted"); } set { this["files-wanted"] = value; } } + public long[] FilesWanted { get { return GetValue("files-wanted"); } set { this["files-wanted"] = value; } } /// /// Indices of file(s) to download /// - public int[] FilesUnwanted { get { return GetValue("files-unwanted"); } set { this["files-unwanted"] = value; } } + public long[] FilesUnwanted { get { return GetValue("files-unwanted"); } set { this["files-unwanted"] = value; } } /// /// Indices of high-priority file(s) /// - public int[] PriorityHigh { get { return GetValue("priority-high"); } set { this["priority-high"] = value; } } + public long[] PriorityHigh { get { return GetValue("priority-high"); } set { this["priority-high"] = value; } } /// /// Indices of low-priority file(s) /// - public int[] PriorityLow { get { return GetValue("priority-low"); } set { this["priority-low"] = value; } } + public long[] PriorityLow { get { return GetValue("priority-low"); } set { this["priority-low"] = value; } } /// /// Indices of normal-priority file(s) /// - public int[] PriorityNormal { get { return GetValue("priority-normal"); } set { this["priority-normal"] = value; } } + public long[] PriorityNormal { get { return GetValue("priority-normal"); } set { this["priority-normal"] = value; } } } } diff --git a/Transmission.API.RPC/Arguments/PortTestProtocol.cs b/Transmission.API.RPC/Arguments/PortTestProtocol.cs new file mode 100644 index 0000000..d923140 --- /dev/null +++ b/Transmission.API.RPC/Arguments/PortTestProtocol.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Transmission.API.RPC.Arguments +{ + /// + /// Which protocol was used for the port test + /// + public enum PortTestProtocol + { + /// + /// IPv4 + /// + IPv4 = 0, + /// + /// IPv6 + /// + IPV6, + /// + /// Could not be determined + /// + Unknown, + } +} diff --git a/Transmission.API.RPC/Arguments/SessionFields.cs b/Transmission.API.RPC/Arguments/SessionFields.cs new file mode 100644 index 0000000..5f095b5 --- /dev/null +++ b/Transmission.API.RPC/Arguments/SessionFields.cs @@ -0,0 +1,309 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Transmission.API.RPC.Arguments +{ + /// + /// Session fields + /// + public sealed class SessionFields + { + private SessionFields() { } + /// + /// alt-speed-down + /// + public const string ALT_SPEED_DOWN = "alt-speed-down"; + /// + /// alt-speed-enabled + /// + public const string ALT_SPEED_ENABLED = "alt-speed-enabled"; + /// + /// alt-speed-time-begin + /// + public const string ALT_SPEED_TIME_BEGIN = "alt-speed-time-begin"; + /// + /// alt-speed-time-enabled + /// + public const string ALT_SPEED_TIME_ENABLED = "alt-speed-time-enabled"; + /// + /// alt-speed-time-end + /// + public const string ALT_SPEED_TIME_END = "alt-speed-time-end"; + /// + /// alt-speed-time-day + /// + public const string ALT_SPEED_TIME_DAY = "alt-speed-time-day"; + /// + /// alt-speed-up + /// + public const string ALT_SPEED_UP = "alt-speed-up"; + /// + /// blocklist-url + /// + public const string BLOCKLIST_URL = "blocklist-url"; + /// + /// blocklist-enabled + /// + public const string BLOCKLIST_ENABLED = "blocklist-enabled"; + /// + /// blocklist-size + /// + public const string BLOCKLIST_SIZE = "blocklist-size"; + /// + /// cache-size-mb + /// + public const string CACHE_SIZE_MB = "cache-size-mb"; + /// + /// default-trackers + /// + public const string DEFAULT_TRACKERS = "default-trackers"; + /// + /// dht-enabled + /// + public const string DHT_ENABLED = "dht-enabled"; + /// + /// download-dir + /// + public const string DOWNLOAD_DIR = "download-dir"; + /// + /// download-dir-free-space + /// + public const string DOWNLOAD_DIR_FREE_SPACE = "download-dir-free-space"; + /// + /// download-queue-size + /// + public const string DOWNLOAD_QUEUE_SIZE = "download-queue-size"; + /// + /// download-queue-enabled + /// + public const string DOWNLOAD_QUEUE_ENABLED = "download-queue-enabled"; + /// + /// encryption + /// + public const string ENCRYPTION = "encryption"; + /// + /// idle-seeding-limit + /// + public const string IDLE_SEEDING_LIMIT = "idle-seeding-limit"; + /// + /// idle-seeding-limit-enabled + /// + public const string IDLE_SEEDING_LIMIT_ENABLED = "idle-seeding-limit-enabled"; + /// + /// incomplete-dir + /// + public const string INCOMPLETE_DIR = "incomplete-dir"; + /// + /// incomplete-dir-enabled + /// + public const string INCOMPLETE_DIR_ENABLED = "incomplete-dir-enabled"; + /// + /// lpd-enabled + /// + public const string LPD_ENABLED = "lpd-enabled"; + /// + /// peer-limit-global + /// + public const string PEER_LIMIT_GLOBAL = "peer-limit-global"; + /// + /// peer-limit-per-torrent + /// + public const string PEER_LIMIT_PER_TORRENT = "peer-limit-per-torrent"; + /// + /// pex-enabled + /// + public const string PEX_ENABLED = "pex-enabled"; + /// + /// peer-port + /// + public const string PEER_PORT = "peer-port"; + /// + /// peer-port-random-on-start + /// + public const string PEER_PORT_RANDOM_ON_START = "peer-port-random-on-start"; + /// + /// port-forwarding-enabled + /// + public const string PORT_FORWARDING_ENABLED = "port-forwarding-enabled"; + /// + /// queue-stalled-enabled + /// + public const string QUEUE_STALLED_ENABLED = "queue-stalled-enabled"; + /// + /// queue-stalled-minutes + /// + public const string QUEUE_STALLED_MINUTES = "queue-stalled-minutes"; + /// + /// rename-partial-files + /// + public const string RENAME_PARTIAL_FILES = "rename-partial-files"; + /// + /// session-id + /// + public const string SESSION_ID = "session-id"; + /// + /// script-torrent-added-filename + /// + public const string SCRIPT_TORRENT_ADDED_FILENAME = "script-torrent-added-filename"; + /// + /// script-torrent-added-enabled + /// + public const string SCRIPT_TORRENT_ADDED_ENABLED = "script-torrent-added-enabled"; + /// + /// script-torrent-done-filename + /// + public const string SCRIPT_TORRENT_DONE_FILENAME = "script-torrent-done-filename"; + /// + /// script-torrent-done-enabled + /// + public const string SCRIPT_TORRENT_DONE_ENABLED = "script-torrent-done-enabled"; + /// + /// script-torrent-done-seeding-filename + /// + public const string SCRIPT_TORRENT_DONE_SEEDING_FILENAME = "script-torrent-done-seeding-filename"; + /// + /// script-torrent-done-seeding-enabled + /// + public const string SCRIPT_TORRENT_DONE_SEEDING_ENABLED = "script-torrent-done-seeding-enabled"; + /// + /// seedRatioLimit + /// + public const string SEED_RATIO_LIMIT = "seedRatioLimit"; + /// + /// seedRatioLimited + /// + public const string SEED_RATIO_LIMITED = "seedRatioLimited"; + /// + /// seed-queue-size + /// + public const string SEED_QUEUE_SIZE = "seed-queue-size"; + /// + /// seed-queue-enabled + /// + public const string SEED_QUEUE_ENABLED = "seed-queue-enabled"; + /// + /// speed-limit-down + /// + public const string SPEED_LIMIT_DOWN = "speed-limit-down"; + /// + /// speed-limit-down-enabled + /// + public const string SPEED_LIMIT_DOWN_ENABLED = "speed-limit-down-enabled"; + /// + /// speed-limit-up + /// + public const string SPEED_LIMIT_UP = "speed-limit-up"; + /// + /// speed-limit-up-enabled + /// + public const string SPEED_LIMIT_UP_ENABLED = "speed-limit-up-enabled"; + /// + /// start-added-torrents + /// + public const string START_ADDED_TORRENTS = "start-added-torrents"; + /// + /// trash-original-torrent-files + /// + public const string TRASH_ORIGINAL_TORRENT_FILES = "trash-original-torrent-files"; + /// + /// units + /// + public const string UNITS = "units"; + /// + /// utp-enabled + /// + public const string UTP_ENABLED = "utp-enabled"; + /// + /// config-dir + /// + public const string CONFIG_DIR = "config-dir"; + /// + /// rpc-version + /// + public const string RPC_VERSION = "rpc-version"; + /// + /// rpc-version-minimum + /// + public const string RPC_VERSION_MINIMUM = "rpc-version-minimum"; + /// + /// rpc-version-semver + /// + public const string RPC_VERSION_SEMVER = "rpc-version-semver"; + /// + /// version + /// + public const string VERSION = "version"; + + /// + /// All fields + /// + public static string[] ALL_FIELDS + { + get + { + return new string[] + { + #region ALL FIELDS + ALT_SPEED_DOWN, + ALT_SPEED_ENABLED, + ALT_SPEED_TIME_BEGIN, + ALT_SPEED_TIME_ENABLED, + ALT_SPEED_TIME_END, + ALT_SPEED_TIME_DAY, + ALT_SPEED_UP, + BLOCKLIST_URL, + BLOCKLIST_ENABLED, + BLOCKLIST_SIZE, + CACHE_SIZE_MB, + DEFAULT_TRACKERS, + DHT_ENABLED, + DOWNLOAD_DIR, + //DOWNLOAD_DIR_FREE_SPACE, // Deprecated + DOWNLOAD_QUEUE_SIZE, + DOWNLOAD_QUEUE_ENABLED, + ENCRYPTION, + IDLE_SEEDING_LIMIT, + IDLE_SEEDING_LIMIT_ENABLED, + INCOMPLETE_DIR, + INCOMPLETE_DIR_ENABLED, + LPD_ENABLED, + PEER_LIMIT_GLOBAL, + PEER_LIMIT_PER_TORRENT, + PEX_ENABLED, + PEER_PORT, + PEER_PORT_RANDOM_ON_START, + PORT_FORWARDING_ENABLED, + QUEUE_STALLED_ENABLED, + QUEUE_STALLED_MINUTES, + RENAME_PARTIAL_FILES, + SESSION_ID, + SCRIPT_TORRENT_ADDED_FILENAME, + SCRIPT_TORRENT_ADDED_ENABLED, + SCRIPT_TORRENT_DONE_FILENAME, + SCRIPT_TORRENT_DONE_ENABLED, + SCRIPT_TORRENT_DONE_SEEDING_FILENAME, + SCRIPT_TORRENT_DONE_SEEDING_ENABLED, + SEED_RATIO_LIMIT, + SEED_RATIO_LIMITED, + SEED_QUEUE_SIZE, + SEED_QUEUE_ENABLED, + SPEED_LIMIT_DOWN, + SPEED_LIMIT_DOWN_ENABLED, + SPEED_LIMIT_UP, + SPEED_LIMIT_UP_ENABLED, + START_ADDED_TORRENTS, + TRASH_ORIGINAL_TORRENT_FILES, + UNITS, + UTP_ENABLED, + CONFIG_DIR, + RPC_VERSION, + RPC_VERSION_MINIMUM, + RPC_VERSION_SEMVER, + VERSION, + #endregion + }; + } + } + } +} diff --git a/Transmission.API.RPC/Arguments/SessionSettings.cs b/Transmission.API.RPC/Arguments/SessionSettings.cs index 33bec06..318ccf1 100644 --- a/Transmission.API.RPC/Arguments/SessionSettings.cs +++ b/Transmission.API.RPC/Arguments/SessionSettings.cs @@ -17,72 +17,77 @@ public class SessionSettings : ArgumentsBase /// /// Max global download speed (KBps) /// - public int? AlternativeSpeedDown { get { return GetValue("alt-speed-down"); } set { this["alt-speed-down"] = value; } } + public long AlternativeSpeedDown { get { return GetValue("alt-speed-down"); } set { this["alt-speed-down"] = value; } } /// /// True means use the alt speeds /// - public bool? AlternativeSpeedEnabled { get { return GetValue("alt-speed-enabled"); } set { this["alt-speed-enabled"] = value; } } + public bool AlternativeSpeedEnabled { get { return GetValue("alt-speed-enabled"); } set { this["alt-speed-enabled"] = value; } } /// /// When to turn on alt speeds (units: minutes after midnight) /// - public int? AlternativeSpeedTimeBegin { get { return GetValue("alt-speed-time-begin"); } set { this["alt-speed-time-begin"] = value; } } + public long AlternativeSpeedTimeBegin { get { return GetValue("alt-speed-time-begin"); } set { this["alt-speed-time-begin"] = value; } } /// /// True means the scheduled on/off times are used /// - public bool? AlternativeSpeedTimeEnabled { get { return GetValue("alt-speed-time-enabled"); } set { this["bandwidthPriority"] = value; } } + public bool AlternativeSpeedTimeEnabled { get { return GetValue("alt-speed-time-enabled"); } set { this["bandwidthPriority"] = value; } } /// /// When to turn off alt speeds /// - public int? AlternativeSpeedTimeEnd { get { return GetValue("alt-speed-time-end"); } set { this["alt-speed-time-end"] = value; } } + public long AlternativeSpeedTimeEnd { get { return GetValue("alt-speed-time-end"); } set { this["alt-speed-time-end"] = value; } } /// /// What day(s) to turn on alt speeds /// - public int? AlternativeSpeedTimeDay { get { return GetValue("alt-speed-time-day"); } set { this["alt-speed-time-day"] = value; } } + public long AlternativeSpeedTimeDay { get { return GetValue("alt-speed-time-day"); } set { this["alt-speed-time-day"] = value; } } /// /// Max global upload speed (KBps) /// - public int? AlternativeSpeedUp { get { return GetValue("alt-speed-up"); } set { this["alt-speed-up"] = value; } } + public long AlternativeSpeedUp { get { return GetValue("alt-speed-up"); } set { this["alt-speed-up"] = value; } } /// /// Location of the blocklist to use for "blocklist-update" /// - public string BlocklistURL { get { return GetValue("blocklist-url"); } set { this["blocklist-url"] = value; } } + public string BlocklistUrl { get { return GetValue("blocklist-url"); } set { this["blocklist-url"] = value; } } /// /// True means enabled /// - public bool? BlocklistEnabled { get { return GetValue("blocklist-enabled"); } set { this["blocklist-enabled"] = value; } } + public bool BlocklistEnabled { get { return GetValue("blocklist-enabled"); } set { this["blocklist-enabled"] = value; } } /// /// Maximum size of the disk cache (MB) /// - public int? CacheSizeMB { get { return GetValue("cache-size-mb"); } set { this["cache-size-mb"] = value; } } + public long CacheSizeMb { get { return GetValue("cache-size-mb"); } set { this["cache-size-mb"] = value; } } /// - /// Default path to download torrents + /// Announce URLs, one per line, and a blank line between tiers + /// + public string DefaultTrackers { get { return GetValue("default-trackers"); } set { this["default-trackers"] = value; } } + + /// + /// Default path to download torrents to /// public string DownloadDirectory { get { return GetValue("download-dir"); } set { this["download-dir"] = value; } } /// /// Max number of torrents to download at once (see download-queue-enabled) /// - public int? DownloadQueueSize { get { return GetValue("download-queue-size"); } set { this["download-queue-size"] = value; } } + public long DownloadQueueSize { get { return GetValue("download-queue-size"); } set { this["download-queue-size"] = value; } } /// /// If true, limit how many torrents can be downloaded at once /// - public bool? DownloadQueueEnabled { get { return GetValue("download-queue-enabled"); } set { this["download-queue-enabled"] = value; } } + public bool DownloadQueueEnabled { get { return GetValue("download-queue-enabled"); } set { this["download-queue-enabled"] = value; } } /// /// True means allow dht in public torrents /// - public bool? DHTEnabled { get { return GetValue("dht-enabled"); } set { this["dht-enabled"] = value; } } + public bool DhtEnabled { get { return GetValue("dht-enabled"); } set { this["dht-enabled"] = value; } } /// /// "required", "preferred", "tolerated" @@ -92,12 +97,12 @@ public class SessionSettings : ArgumentsBase /// /// Torrents we're seeding will be stopped if they're idle for this long /// - public int? IdleSeedingLimit { get { return GetValue("idle-seeding-limit"); } set { this["idle-seeding-limit"] = value; } } + public long IdleSeedingLimit { get { return GetValue("idle-seeding-limit"); } set { this["idle-seeding-limit"] = value; } } /// /// True if the seeding inactivity limit is honored by default /// - public bool? IdleSeedingLimitEnabled { get { return GetValue("idle-seeding-limit-enabled"); } set { this["idle-seeding-limit-enabled"] = value; } } + public bool IdleSeedingLimitEnabled { get { return GetValue("idle-seeding-limit-enabled"); } set { this["idle-seeding-limit-enabled"] = value; } } /// /// Path for incomplete torrents, when enabled @@ -107,57 +112,67 @@ public class SessionSettings : ArgumentsBase /// /// True means keep torrents in incomplete-dir until done /// - public bool? IncompleteDirectoryEnabled { get { return GetValue("incomplete-dir-enabled"); } set { this["incomplete-dir-enabled"] = value; } } + public bool IncompleteDirectoryEnabled { get { return GetValue("incomplete-dir-enabled"); } set { this["incomplete-dir-enabled"] = value; } } /// /// True means allow Local Peer Discovery in public torrents /// - public bool? LPDEnabled { get { return GetValue("lpd-enabled"); } set { this["lpd-enabled"] = value; } } + public bool LpdEnabled { get { return GetValue("lpd-enabled"); } set { this["lpd-enabled"] = value; } } /// /// Maximum global number of peers /// - public int? PeerLimitGlobal { get { return GetValue("peer-limit-global"); } set { this["peer-limit-global"] = value; } } + public long PeerLimitGlobal { get { return GetValue("peer-limit-global"); } set { this["peer-limit-global"] = value; } } /// /// Maximum global number of peers /// - public int? PeerLimitPerTorrent { get { return GetValue("peer-limit-per-torrent"); } set { this["peer-limit-per-torrent"] = value; } } + public long PeerLimitPerTorrent { get { return GetValue("peer-limit-per-torrent"); } set { this["peer-limit-per-torrent"] = value; } } /// /// True means allow pex in public torrents /// - public bool? PexEnabled { get { return GetValue("pex-enabled"); } set { this["pex-enabled"] = value; } } + public bool PexEnabled { get { return GetValue("pex-enabled"); } set { this["pex-enabled"] = value; } } /// /// Port number /// - public int? PeerPort { get { return GetValue("peer-port"); } set { this["peer-port"] = value; } } + public long PeerPort { get { return GetValue("peer-port"); } set { this["peer-port"] = value; } } /// /// True means pick a random peer port on launch /// - public bool? PeerPortRandomOnStart { get { return GetValue("peer-port-random-on-start"); } set { this["peer-port-random-on-start"] = value; } } + public bool PeerPortRandomOnStart { get { return GetValue("peer-port-random-on-start"); } set { this["peer-port-random-on-start"] = value; } } /// /// true means enabled /// - public bool? PortForwardingEnabled { get { return GetValue("port-forwarding-enabled"); } set { this["port-forwarding-enabled"] = value; } } + public bool PortForwardingEnabled { get { return GetValue("port-forwarding-enabled"); } set { this["port-forwarding-enabled"] = value; } } /// /// Whether or not to consider idle torrents as stalled /// - public bool? QueueStalledEnabled { get { return GetValue("queue-stalled-enabled"); } set { this["queue-stalled-enabled"] = value; } } + public bool QueueStalledEnabled { get { return GetValue("queue-stalled-enabled"); } set { this["queue-stalled-enabled"] = value; } } /// /// Torrents that are idle for N minuets aren't counted toward seed-queue-size or download-queue-size /// - public int? QueueStalledMinutes { get { return GetValue("queue-stalled-minutes"); } set { this["queue-stalled-minutes"] = value; } } + public long QueueStalledMinutes { get { return GetValue("queue-stalled-minutes"); } set { this["queue-stalled-minutes"] = value; } } /// /// True means append ".part" to incomplete files /// - public bool? RenamePartialFiles { get { return GetValue("rename-partial-files"); } set { this["rename-partial-files"] = value; } } + public bool RenamePartialFiles { get { return GetValue("rename-partial-files"); } set { this["rename-partial-files"] = value; } } + + /// + /// Filename of the script to run + /// + public string ScriptTorrentAddedFilename { get { return GetValue("script-torrent-added-filename"); } set { this["script-torrent-added-filename"] = value; } } + + /// + /// Whether or not to call the "added" script + /// + public bool ScriptTorrentAddedEnabled { get { return GetValue("script-torrent-added-enabled"); } set { this["script-torrent-added-enabled"] = value; } } /// /// Filename of the script to run @@ -167,67 +182,72 @@ public class SessionSettings : ArgumentsBase /// /// Whether or not to call the "done" script /// - public bool? ScriptTorrentDoneEnabled { get { return GetValue("script-torrent-done-enabled"); } set { this["script-torrent-done-enabled"] = value; } } + public bool ScriptTorrentDoneEnabled { get { return GetValue("script-torrent-done-enabled"); } set { this["script-torrent-done-enabled"] = value; } } + + /// + /// Filename of the script to run + /// + public string ScriptTorrentDoneSeedingFilename { get { return GetValue("script-torrent-done-seeding-filename"); } set { this["script-torrent-done-seeding-filename"] = value; } } + + /// + /// Whether or not to call the "done seeding" script + /// + public bool ScriptTorrentDoneSeedingEnabled { get { return GetValue("script-torrent-done-seeding-enabled"); } set { this["script-torrent-done-seeding-enabled"] = value; } } /// /// The default seed ratio for torrents to use /// - public double? SeedRatioLimit { get { return GetValue("seedRatioLimit"); } set { this["seedRatioLimit"] = value; } } + public double SeedRatioLimit { get { return GetValue("seedRatioLimit"); } set { this["seedRatioLimit"] = value; } } /// /// True if seedRatioLimit is honored by default /// - public bool? SeedRatioLimited { get { return GetValue("seedRatioLimited"); } set { this["seedRatioLimited"] = value; } } + public bool SeedRatioLimited { get { return GetValue("seedRatioLimited"); } set { this["seedRatioLimited"] = value; } } /// /// Max number of torrents to uploaded at once (see seed-queue-enabled) /// - public int? SeedQueueSize { get { return GetValue("seed-queue-size"); } set { this["seed-queue-size"] = value; } } + public long SeedQueueSize { get { return GetValue("seed-queue-size"); } set { this["seed-queue-size"] = value; } } /// /// If true, limit how many torrents can be uploaded at once /// - public bool? SeedQueueEnabled { get { return GetValue("seed-queue-enabled"); } set { this["seed-queue-enabled"] = value; } } + public bool SeedQueueEnabled { get { return GetValue("seed-queue-enabled"); } set { this["seed-queue-enabled"] = value; } } /// /// Max global download speed (KBps) /// - public int? SpeedLimitDown { get { return GetValue("speed-limit-down"); } set { this["speed-limit-down"] = value; } } + public long SpeedLimitDown { get { return GetValue("speed-limit-down"); } set { this["speed-limit-down"] = value; } } /// /// True means enabled /// - public bool? SpeedLimitDownEnabled { get { return GetValue("speed-limit-down-enabled"); } set { this["speed-limit-down-enabled"] = value; } } + public bool SpeedLimitDownEnabled { get { return GetValue("speed-limit-down-enabled"); } set { this["speed-limit-down-enabled"] = value; } } /// /// max global upload speed (KBps) /// - public int? SpeedLimitUp { get { return GetValue("speed-limit-up"); } set { this["speed-limit-up"] = value; } } + public long SpeedLimitUp { get { return GetValue("speed-limit-up"); } set { this["speed-limit-up"] = value; } } /// /// True means enabled /// - public bool? SpeedLimitUpEnabled { get { return GetValue("speed-limit-up-enabled"); } set { this["speed-limit-up-enabled"] = value; } } + public bool SpeedLimitUpEnabled { get { return GetValue("speed-limit-up-enabled"); } set { this["speed-limit-up-enabled"] = value; } } /// /// True means added torrents will be started right away /// - public bool? StartAddedTorrents { get { return GetValue("start-added-torrents"); } set { this["start-added-torrents"] = value; } } + public bool StartAddedTorrents { get { return GetValue("start-added-torrents"); } set { this["start-added-torrents"] = value; } } /// /// True means the .torrent file of added torrents will be deleted /// - public bool? TrashOriginalTorrentFiles { get { return GetValue("trash-original-torrent-files"); } set { this["trash-original-torrent-files"] = value; } } - - /// - /// Units - /// - public Units Units { get { return GetValue("units"); } set { this["units"] = value; } } + public bool TrashOriginalTorrentFiles { get { return GetValue("trash-original-torrent-files"); } set { this["trash-original-torrent-files"] = value; } } /// /// True means allow utp /// - public bool? UtpEnabled { get { return GetValue ("utp-enabled"); } set { this["utp-enabled"] = value; } } + public bool UtpEnabled { get { return GetValue("utp-enabled"); } set { this["utp-enabled"] = value; } } } } diff --git a/Transmission.API.RPC/Arguments/TorrentFields.cs b/Transmission.API.RPC/Arguments/TorrentFields.cs index dd69edd..cbc2be9 100644 --- a/Transmission.API.RPC/Arguments/TorrentFields.cs +++ b/Transmission.API.RPC/Arguments/TorrentFields.cs @@ -23,6 +23,11 @@ private TorrentFields() { } /// public const string ADDED_DATE = "addedDate"; + /// + /// availability + /// + public const string AVAILABILITY = "availability"; + /// /// bandwidthPriority /// @@ -82,7 +87,7 @@ private TorrentFields() { } /// editDate /// public const string EDIT_DATE = "editDate"; - + /// /// error /// @@ -118,6 +123,11 @@ private TorrentFields() { } /// public const string FILE_STATS = "fileStats"; + /// + /// group + /// + public const string GROUP = "group"; + /// /// hashString /// @@ -308,6 +318,11 @@ private TorrentFields() { } /// public const string SEED_RATIO_MODE = "seedRatioMode"; + /// + /// sequentialDownload + /// + public const string SEQUENTIAL_DOWNLOAD = "sequentialDownload"; + /// /// sizeWhenDone /// @@ -390,11 +405,12 @@ public static string[] ALL_FIELDS { get { - return new string[] + return new string[] { #region ALL FIELDS ACTIVITY_DATE, ADDED_DATE, + AVAILABILITY, BANDWIDTH_PRIORITY, COMMENT, CORRUPT_EVER, @@ -414,6 +430,7 @@ public static string[] ALL_FIELDS FILE_COUNT, FILES, FILE_STATS, + GROUP, HASH_STRING, HAVE_UNCHECKED, HAVE_VALID, @@ -452,6 +469,7 @@ public static string[] ALL_FIELDS SEED_IDLE_MODE, SEED_RATIO_LIMIT, SEED_RATIO_MODE, + SEQUENTIAL_DOWNLOAD, SIZE_WHEN_DONE, START_DATE, STATUS, diff --git a/Transmission.API.RPC/Arguments/TorrentSettings.cs b/Transmission.API.RPC/Arguments/TorrentSettings.cs index 5b1c8a3..3a2ec1f 100644 --- a/Transmission.API.RPC/Arguments/TorrentSettings.cs +++ b/Transmission.API.RPC/Arguments/TorrentSettings.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -16,27 +17,37 @@ public class TorrentSettings : ArgumentsBase /// /// This torrent's bandwidth tr_priority_t /// - public int? BandwidthPriority { get { return GetValue("bandwidthPriority"); } set { this["bandwidthPriority"] = value; } } + public long BandwidthPriority { get { return GetValue("bandwidthPriority"); } set { this["bandwidthPriority"] = value; } } /// /// Maximum download speed (KBps) /// - public int? DownloadLimit { get { return GetValue("downloadLimit"); } set { this["downloadLimit"] = value; } } + public long DownloadLimit { get { return GetValue("downloadLimit"); } set { this["downloadLimit"] = value; } } /// /// Download limit is honored /// - public bool? DownloadLimited { get { return GetValue("downloadLimited"); } set { this["downloadLimited"] = value; } } + public bool DownloadLimited { get { return GetValue("downloadLimited"); } set { this["downloadLimited"] = value; } } + + /// + /// The name of this torrent's bandwidth group + /// + public string Group { get { return GetValue("group"); } set { this["group"] = value; } } /// /// Session upload limits are honored /// - public bool? HonorsSessionLimits { get { return GetValue("honorsSessionLimits"); } set { this["honorsSessionLimits"] = value; } } + public bool HonorsSessionLimits { get { return GetValue("honorsSessionLimits"); } set { this["honorsSessionLimits"] = value; } } /// /// Torrent id array /// - public object[] IDs { get { return GetValue("ids"); } set { this["ids"] = value; } } + public object[] Ids { get { return GetValue("ids"); } set { this["ids"] = value; } } + + /// + /// Array of strings containing the labels assigned to the torrent + /// + public string[] Labels { get { return GetValue("labels"); } set { this["labels"] = value; } } /// /// New location of the torrent's content @@ -46,45 +57,50 @@ public class TorrentSettings : ArgumentsBase /// /// Maximum number of peers /// - public int? PeerLimit { get { return GetValue("peer-limit"); } set { this["peer-limit"] = value; } } + public long PeerLimit { get { return GetValue("peer-limit"); } set { this["peer-limit"] = value; } } /// /// Position of this torrent in its queue [0...n) /// - public int? QueuePosition { get { return GetValue("queuePosition"); } set { this["queuePosition"] = value; } } + public long QueuePosition { get { return GetValue("queuePosition"); } set { this["queuePosition"] = value; } } /// /// Torrent-level number of minutes of seeding inactivity /// - public int? SeedIdleLimit { get { return GetValue("seedIdleLimit"); } set { this["seedIdleLimit"] = value; } } + public long SeedIdleLimit { get { return GetValue("seedIdleLimit"); } set { this["seedIdleLimit"] = value; } } /// - /// Which seeding inactivity to use + /// Which seeding inactivity mode to use. 0=Global 1=Single 2=Unlimited /// - public int? SeedIdleMode { get { return GetValue("seedIdleMode"); } set { this["seedIdleMode"] = value; } } + public long SeedIdleMode { get { return GetValue("seedIdleMode"); } set { this["seedIdleMode"] = value; } } /// /// Torrent-level seeding ratio /// - public double? SeedRatioLimit { get { return GetValue("seedRatioLimit"); } set { this["seedRatioLimit"] = value; } } + public double SeedRatioLimit { get { return GetValue("seedRatioLimit"); } set { this["seedRatioLimit"] = value; } } + + /// + /// Which ratio mode to use. 0=Global 1=Single 2=Unlimited + /// + public long SeedRatioMode { get { return GetValue("seedRatioMode"); } set { this["seedRatioMode"] = value; } } /// - /// Which ratio to use. + /// Whether to download the torrent sequentially /// - public int? SeedRatioMode { get { return GetValue("seedRatioMode"); } set { this["seedRatioMode"] = value; } } + public bool SequentialDownload { get { return GetValue("sequentialDownload"); } set { this["sequentialDownload"] = value; } } /// /// Maximum upload speed (KBps) /// - public int? UploadLimit { get { return GetValue("uploadLimit"); } set { this["uploadLimit"] = value; } } + public long UploadLimit { get { return GetValue("uploadLimit"); } set { this["uploadLimit"] = value; } } /// /// Upload limit is honored /// - public bool? UploadLimited { get { return GetValue("uploadLimited"); } set { this["uploadLimited"] = value; } } + public bool UploadLimited { get { return GetValue("uploadLimited"); } set { this["uploadLimited"] = value; } } /// - /// Strings of announce URLs to add + /// strings of announce URLs to add /// [Obsolete("TrackerAdd is obsolete since Transmission 4.0.0, use TrackerList instead.")] public string[] TrackerAdd { get { return GetValue("trackerAdd"); } set { this["trackerAdd"] = value; } } @@ -93,12 +109,18 @@ public class TorrentSettings : ArgumentsBase /// Ids of trackers to remove /// [Obsolete("TrackerRemove is obsolete since Transmission 4.0.0, use TrackerList instead.")] - public int[] TrackerRemove { get { return GetValue("trackerRemove"); } set { this["trackerRemove"] = value; } } + public long[] TrackerRemove { get { return GetValue("trackerRemove"); } set { this["trackerRemove"] = value; } } /// - /// String of announce URLs, one per line, with a blank line between tiers + /// Pairs of IDs of announce URLs to replace along with their new value /// - public string[] TrackerList { get { return GetValue("trackerList"); } set { this["trackerAdd"] = value; } } + [Obsolete("TrackerReplace is obsolete since Transmission 4.0.0, use TrackerList instead.")] + public KeyValuePair[] TrackerReplace { get { return GetValue[]>("trackerReplace"); } set { this["trackerReplace"] = value; } } + + /// + /// string of announce URLs, one per line, with a blank line between tiers + /// + public string[] TrackerList { get { return GetValue("trackerList"); } set { this["trackerList"] = value; } } /// /// Files wanted @@ -124,10 +146,5 @@ public class TorrentSettings : ArgumentsBase /// Normal priority files /// public string[] PriorityNormal { get { return GetValue("priority-normal"); } set { this["priority-normal"] = value; } } - - //TODO: Add and test - //"trackerReplace" | array pairs of - //public [] trackerReplace; - } } diff --git a/Transmission.API.RPC/Client.Async.cs b/Transmission.API.RPC/Client.Async.cs index f1c96c8..17a2d40 100644 --- a/Transmission.API.RPC/Client.Async.cs +++ b/Transmission.API.RPC/Client.Async.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -11,373 +12,490 @@ using Newtonsoft.Json.Linq; using Transmission.API.RPC.Common; using Transmission.API.RPC.Arguments; +using System.Runtime; namespace Transmission.API.RPC { - public partial class Client - { - #region Session methods - - /// - /// Close current session (API: session-close) - /// - public async Task CloseSessionAsync() - { - var request = new TransmissionRequest("session-close"); - var response = await SendRequestAsync(request); - } - - /// - /// Set information to current session (API: session-set) - /// - /// New session settings - public async Task SetSessionSettingsAsync(SessionSettings settings) - { - var request = new TransmissionRequest("session-set", settings); - var response = await SendRequestAsync(request); - } - - /// - /// Get session stat - /// - /// Session stat - public async Task GetSessionStatisticAsync() - { - var request = new TransmissionRequest("session-stats"); - var response = await SendRequestAsync(request); - var result = response.Deserialize(); - return result; - } + public partial class Client + { + #region Session methods + + /// + /// Close current session (API: session-close) + /// + public async Task CloseSessionAsync() + { + var request = new TransmissionRequest("session-close"); + var response = await SendRequestAsync(request); + } + + /// + /// Set information to current session (API: session-set) + /// + /// New session settings + public async Task SetSessionSettingsAsync(SessionSettings settings) + { + var request = new TransmissionRequest("session-set", settings); + var response = await SendRequestAsync(request); + } + + /// + /// Get session stat + /// + /// Session stat + public async Task GetSessionStatisticAsync() + { + var request = new TransmissionRequest("session-stats"); + var response = await SendRequestAsync(request); + var result = response?.Arguments.ToObject(); + return result; + } /// /// Get information of current session (API: session-get) /// /// Session information - //TODO: support optional "fields" argument - public async Task GetSessionInformationAsync() - { - var request = new TransmissionRequest("session-get"); - var response = await SendRequestAsync(request); - var result = response.Deserialize(); - return result; - } + public async Task GetSessionInformationAsync() + { + var request = new TransmissionRequest("session-get"); + var response = await SendRequestAsync(request); + var result = response?.Arguments.ToObject(); + return result; + } - #endregion - #region Torrents methods - /// - /// Add torrent (API: torrent-add) - /// - /// Torrent info (ID, Name and HashString) - public async Task TorrentAddAsync(NewTorrent torrent) - { - if (String.IsNullOrWhiteSpace(torrent.Metainfo) && String.IsNullOrWhiteSpace(torrent.Filename)) - throw new Exception("Either \"filename\" or \"metainfo\" must be included."); + /// + /// Get information of current session (API: session-get) + /// + /// Optional fields of session information + /// Session information + public async Task GetSessionInformationAsync(string[] fields) + { + var arguments = new Dictionary(); + arguments.Add("fields", fields); - var request = new TransmissionRequest("torrent-add", torrent); - var response = await SendRequestAsync(request); - var jObject = response.Deserialize(); + var request = new TransmissionRequest("session-get", arguments); + var response = await SendRequestAsync(request); + var result = response?.Arguments.ToObject(); + return result; + } + #endregion - if (jObject == null || jObject.First == null) - return null; + #region Torrents methods - NewTorrentInfo result = null; - JToken value = null; + /// + /// Add torrent (API: torrent-add) + /// + /// Torrent info (ID, Name and HashString) + public async Task TorrentAddAsync(NewTorrent torrent) + { + if (String.IsNullOrWhiteSpace(torrent.Metainfo) && String.IsNullOrWhiteSpace(torrent.Filename)) + throw new ArgumentException("Either \"filename\" or \"metainfo\" must be included."); + + var request = new TransmissionRequest("torrent-add", torrent); + var response = await SendRequestAsync(request); + var jObject = response?.Arguments; + + if (jObject == null || jObject.First == null) + return null; - if (jObject.TryGetValue("torrent-duplicate", out value)) - result = JsonConvert.DeserializeObject(value.ToString()); - else if (jObject.TryGetValue("torrent-added", out value)) - result = JsonConvert.DeserializeObject(value.ToString()); + NewTorrentInfo? result = null; + JToken? value = null; + + if (jObject.TryGetValue("torrent-duplicate", out value)) + { + result = JsonConvert.DeserializeObject(value.ToString()); + if (result != null) result.Duplicate = true; + } + else if (jObject.TryGetValue("torrent-added", out value)) + { + result = JsonConvert.DeserializeObject(value.ToString()); + if (result != null) result.Duplicate = false; + } - return result; - } + return result; + } /// /// Set torrent params (API: torrent-set) /// /// Torrent settings public async Task TorrentSetAsync(TorrentSettings settings) - { - var request = new TransmissionRequest("torrent-set", settings); - var response = await SendRequestAsync(request); - } + { + var request = new TransmissionRequest("torrent-set", settings); + var response = await SendRequestAsync(request); + } - /// - /// Get fields of torrents from ids (API: torrent-get) - /// - /// Fields of torrents - /// IDs of torrents (null or empty for get all torrents) - /// Torrents info - public async Task TorrentGetAsync(string[] fields, params int[] ids) - { - var arguments = new Dictionary(); - arguments.Add("fields", fields); + /// + /// Get fields of recently active torrents (API: torrent-get) + /// + /// Fields of torrents + /// Torrents info + public async Task TorrentGetRecentlyActiveAsync(string[] fields) + { + var arguments = new Dictionary(); + arguments.Add("fields", fields); + arguments.Add("ids", "recently-active"); - if (ids != null && ids.Length > 0) - arguments.Add("ids", ids); + var request = new TransmissionRequest("torrent-get", arguments); + var response = await SendRequestAsync(request); - var request = new TransmissionRequest("torrent-get", arguments); + if (response == null) return null; - var response = await SendRequestAsync(request); - var result = response.Deserialize(); + TransmissionTorrents? torrents = response.Arguments.ToObject(); + + return torrents; + } - return result; - } + /// + /// Get fields of torrents from ids (API: torrent-get) + /// + /// Fields of torrents + /// IDs of torrents (null or empty for get all torrents) + /// Torrents info + public async Task TorrentGetAsync(string[] fields, params long[] ids) + { + var arguments = new Dictionary(); + arguments.Add("fields", fields); + + if (ids != null && ids.Length > 0) + arguments.Add("ids", ids); + + var request = new TransmissionRequest("torrent-get", arguments); + var response = await SendRequestAsync(request); + + if (response == null) return null; + + TransmissionTorrents? torrents = response?.Arguments.ToObject(); + + return torrents; + } /// /// Remove torrents /// /// Torrents id /// Remove data - public async Task TorrentRemoveAsync(int[] ids, bool deleteData = false) - { - var arguments = new Dictionary(); - - arguments.Add("ids", ids); - arguments.Add("delete-local-data", deleteData); - - var request = new TransmissionRequest("torrent-remove", arguments); - var response = await SendRequestAsync(request); - } - - #region Torrent Start - - /// - /// Start torrents (API: torrent-start) - /// - /// A list of torrent id numbers, sha1 hash strings, or both - public async Task TorrentStartAsync(object[] ids) - { - var request = new TransmissionRequest("torrent-start", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Start recently active torrents (API: torrent-start) - /// - public async Task TorrentStartAsync() - { - var request = new TransmissionRequest("torrent-start", new Dictionary { { "ids", "recently-active" } }); - var response = await SendRequestAsync(request); - } - - #endregion - - #region Torrent Start Now - - /// - /// Start now torrents (API: torrent-start-now) - /// - /// A list of torrent id numbers, sha1 hash strings, or both - public async Task TorrentStartNowAsync(object[] ids) - { - var request = new TransmissionRequest("torrent-start-now", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Start now recently active torrents (API: torrent-start-now) - /// - public async Task TorrentStartNowAsync() - { - var request = new TransmissionRequest("torrent-start-now", new Dictionary { { "ids", "recently-active" } }); - var response = await SendRequestAsync(request); - } - - #endregion - - #region Torrent Stop - - /// - /// Stop torrents (API: torrent-stop) - /// - /// A list of torrent id numbers, sha1 hash strings, or both - public async Task TorrentStopAsync(object[] ids) - { - var request = new TransmissionRequest("torrent-stop", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Stop recently active torrents (API: torrent-stop) - /// - public async Task TorrentStopAsync() - { - var request = new TransmissionRequest("torrent-stop", new Dictionary { { "ids", "recently-active" } }); - var response = await SendRequestAsync(request); - } - - #endregion - - #region Torrent Verify - - /// - /// Verify torrents (API: torrent-verify) - /// - /// A list of torrent id numbers, sha1 hash strings, or both - public async Task TorrentVerifyAsync(object[] ids) - { - var request = new TransmissionRequest("torrent-verify", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Verify recently active torrents (API: torrent-verify) - /// - public async Task TorrentVerifyAsync() - { - var request = new TransmissionRequest("torrent-verify", new Dictionary { { "ids", "recently-active" } }); - var response = await SendRequestAsync(request); - } - #endregion - - /// - /// Move torrents in queue on top (API: queue-move-top) - /// - /// Torrents id - public async Task TorrentQueueMoveTopAsync(int[] ids) - { - var request = new TransmissionRequest("queue-move-top", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Move up torrents in queue (API: queue-move-up) - /// - /// - public async Task TorrentQueueMoveUpAsync(int[] ids) - { - var request = new TransmissionRequest("queue-move-up", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Move down torrents in queue (API: queue-move-down) - /// - /// - public async Task TorrentQueueMoveDownAsync(int[] ids) - { - var request = new TransmissionRequest("queue-move-down", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Move torrents to bottom in queue (API: queue-move-bottom) - /// - /// - public async Task TorrentQueueMoveBottomAsync(int[] ids) - { - var request = new TransmissionRequest("queue-move-bottom", new Dictionary { { "ids", ids } }); - var response = await SendRequestAsync(request); - } - - /// - /// Set new location for torrents files (API: torrent-set-location) - /// - /// Torrent ids - /// The new torrent location - /// Move from previous location - public async Task TorrentSetLocationAsync(int[] ids, string location, bool move) - { - var arguments = new Dictionary(); - arguments.Add("ids", ids); - arguments.Add("location", location); - arguments.Add("move", move); - - var request = new TransmissionRequest("torrent-set-location", arguments); - var response = await SendRequestAsync(request); - } - - /// - /// Rename a file or directory in a torrent (API: torrent-rename-path) - /// - /// The torrent whose path will be renamed - /// The path to the file or folder that will be renamed - /// The file or folder's new name - public async Task TorrentRenamePathAsync(int id, string path, string name) - { - var arguments = new Dictionary(); - arguments.Add("ids", new int[] { id }); - arguments.Add("path", path); - arguments.Add("name", name); - - var request = new TransmissionRequest("torrent-rename-path", arguments); - var response = await SendRequestAsync(request); - - var result = response.Deserialize(); - - return result; - } - - //method name not recognized - ///// - ///// Reannounce torrent (API: torrent-reannounce) - ///// - ///// - //public void ReannounceTorrents(object[] ids) - //{ - // var arguments = new Dictionary(); - // arguments.Add("ids", ids); - - // var request = new TransmissionRequest("torrent-reannounce", arguments); - // var response = SendRequest(request); - //} - - #endregion - - #region System - - /// - /// See if your incoming peer port is accessible from the outside world (API: port-test) - /// - /// Accessible state - public async Task PortTestAsync() - { - var request = new TransmissionRequest("port-test"); - var response = await SendRequestAsync(request); - - var data = response.Deserialize(); - var result = (bool)data.GetValue("port-is-open"); - return result; - } - - /// - /// Update blocklist (API: blocklist-update) - /// - /// Blocklist size - public async Task BlocklistUpdateAsync() - { - var request = new TransmissionRequest("blocklist-update"); - var response = await SendRequestAsync(request); - - var data = response.Deserialize(); - var result = (int)data.GetValue("blocklist-size"); - return result; - } - - /// - /// Get free space is available in a client-specified folder. - /// - /// The directory to query - public async Task FreeSpaceAsync(string path) - { - var arguments = new Dictionary(); - arguments.Add("path", path); - - var request = new TransmissionRequest("free-space", arguments); - var response = await SendRequestAsync(request); - - var data = response.Deserialize(); - var result = (long)data.GetValue("size-bytes"); - return result; - } + public async Task TorrentRemoveAsync(long[] ids, bool deleteData = false) + { + var arguments = new Dictionary(); + + arguments.Add("ids", ids); + arguments.Add("delete-local-data", deleteData); + + var request = new TransmissionRequest("torrent-remove", arguments); + var response = await SendRequestAsync(request); + } + + #region Torrent Start + + /// + /// Start torrents (API: torrent-start) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + public async Task TorrentStartAsync(object[] ids) + { + var request = new TransmissionRequest("torrent-start", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Start recently active torrents (API: torrent-start) + /// + public async Task TorrentStartRecentlyActiveAsync() + { + var request = new TransmissionRequest("torrent-start", new Dictionary { { "ids", "recently-active" } }); + var response = await SendRequestAsync(request); + } + + #endregion + + #region Torrent Start Now + + /// + /// Start now torrents (API: torrent-start-now) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + public async Task TorrentStartNowAsync(object[] ids) + { + var request = new TransmissionRequest("torrent-start-now", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Start now recently active torrents (API: torrent-start-now) + /// + public async Task TorrentStartNowRecentlyActiveAsync() + { + var request = new TransmissionRequest("torrent-start-now", new Dictionary { { "ids", "recently-active" } }); + var response = await SendRequestAsync(request); + } + + #endregion + + #region Torrent Stop + + /// + /// Stop torrents (API: torrent-stop) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + public async Task TorrentStopAsync(object[] ids) + { + var request = new TransmissionRequest("torrent-stop", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Stop recently active torrents (API: torrent-stop) + /// + public async Task TorrentStopRecentlyActiveAsync() + { + var request = new TransmissionRequest("torrent-stop", new Dictionary { { "ids", "recently-active" } }); + var response = await SendRequestAsync(request); + } + + #endregion + + #region Torrent Verify + + /// + /// Verify torrents (API: torrent-verify) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + public async Task TorrentVerifyAsync(object[] ids) + { + var request = new TransmissionRequest("torrent-verify", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Verify recently active torrents (API: torrent-verify) + /// + public async Task TorrentVerifyRecentlyActiveAsync() + { + var request = new TransmissionRequest("torrent-verify", new Dictionary { { "ids", "recently-active" } }); + var response = await SendRequestAsync(request); + } + + #endregion + + #region Torrent Reannounce + + /// + /// Reannounce torrents (API: torrent-reannounce) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + public async Task TorrentReannounceAsync(object[] ids) + { + var request = new TransmissionRequest("torrent-reannounce", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Reannounce recently active torrents (API: torrent-reannounce) + /// + public async Task TorrentReannounceRecentlyActiveAsync() + { + var request = new TransmissionRequest("torrent-reannounce", new Dictionary { { "ids", "recently-active" } }); + var response = await SendRequestAsync(request); + } + + #endregion + + #region Torrent Queue + + /// + /// Move torrents in queue on top (API: queue-move-top) + /// + /// Torrents id + public async Task TorrentQueueMoveTopAsync(long[] ids) + { + var request = new TransmissionRequest("queue-move-top", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Move up torrents in queue (API: queue-move-up) + /// + /// + public async Task TorrentQueueMoveUpAsync(long[] ids) + { + var request = new TransmissionRequest("queue-move-up", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Move down torrents in queue (API: queue-move-down) + /// + /// + public async Task TorrentQueueMoveDownAsync(long[] ids) + { + var request = new TransmissionRequest("queue-move-down", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + /// + /// Move torrents to bottom in queue (API: queue-move-bottom) + /// + /// + public async Task TorrentQueueMoveBottomAsync(long[] ids) + { + var request = new TransmissionRequest("queue-move-bottom", new Dictionary { { "ids", ids } }); + var response = await SendRequestAsync(request); + } + + #endregion + + /// + /// Set new location for torrents files (API: torrent-set-location) + /// + /// Torrent ids + /// The new torrent location + /// Move from previous location + public async Task TorrentSetLocationAsync(long[] ids, string location, bool move) + { + var arguments = new Dictionary(); + arguments.Add("ids", ids); + arguments.Add("location", location); + arguments.Add("move", move); + + var request = new TransmissionRequest("torrent-set-location", arguments); + var response = await SendRequestAsync(request); + } + + /// + /// Rename a file or directory in a torrent (API: torrent-rename-path) + /// + /// The torrent whose path will be renamed + /// The path to the file or folder that will be renamed + /// The file or folder's new name + public async Task TorrentRenamePathAsync(long id, string path, string name) + { + var arguments = new Dictionary(); + arguments.Add("ids", new long[] { id }); + arguments.Add("path", path); + arguments.Add("name", name); + + var request = new TransmissionRequest("torrent-rename-path", arguments); + var response = await SendRequestAsync(request); + + var result = response?.Arguments.ToObject(); + + return result; + } + + #endregion + + #region Bandwidth Groups + + /// + /// Get bandwidth groups (API: group-get) + /// + /// + public async Task BandwidthGroupGetAsync() + { + var request = new TransmissionRequest("group-get"); + + var response = await SendRequestAsync(request); + var result = response?.Arguments.ToObject(); + + return result; + } + + /// + /// Get bandwidth groups (API: group-get) + /// + /// Optional names of groups to get + /// + public async Task BandwidthGroupGetAsync(string[] groups) + { + var arguments = new Dictionary(); + arguments.Add("group", groups); + + var request = new TransmissionRequest("group-get", arguments); + + var response = await SendRequestAsync(request); + var result = response?.Arguments.ToObject(); + + return result; + } + + /// + /// Set bandwidth groups (API: group-set) + /// + /// A bandwidth group to set + public async Task BandwidthGroupSetAsync(BandwidthGroupSettings group) + { + var request = new TransmissionRequest("group-set", group); + var response = await SendRequestAsync(request); + } + + #endregion + + #region System + + /// + /// See if your incoming peer port is accessible from the outside world (API: port-test) + /// + /// A Tuple with a boolean of whether the port test succeeded, and a PortTestProtocol enum of which protocol was used for the test + public async Task> PortTestAsync() + { + var request = new TransmissionRequest("port-test"); + var response = await SendRequestAsync(request); + + var data = response?.Arguments; + var result = (bool?)data?.GetValue("port-is-open"); + PortTestProtocol protocol = PortTestProtocol.Unknown; + if (data?.TryGetValue("ipProtocol", out var protocolValue) == true) + { + if (protocolValue != null) + { + switch ((string?)protocolValue) + { + case "ipv4": protocol = PortTestProtocol.IPv4; break; + case "ipv6": protocol = PortTestProtocol.IPV6; break; + } + } + } + return new Tuple(result, protocol); + } + + /// + /// Update blocklist (API: blocklist-update) + /// + /// Blocklist size + public async Task BlocklistUpdateAsync() + { + var request = new TransmissionRequest("blocklist-update"); + var response = await SendRequestAsync(request); + + var data = response?.Arguments; + var result = (long?)data?.GetValue("blocklist-size"); + return result; + } + + /// + /// Get free space is available in a client-specified folder. + /// + /// The directory to query + public async Task FreeSpaceAsync(string path) + { + var arguments = new Dictionary(); + arguments.Add("path", path); + + var request = new TransmissionRequest("free-space", arguments); + var response = await SendRequestAsync(request); + + var data = response?.Arguments.ToObject(); + return data; + } #endregion - private async Task SendRequestAsync(TransmissionRequest request) + private async Task SendRequestAsync(TransmissionRequest request) { - TransmissionResponse result = new TransmissionResponse(); + TransmissionResponse? result = null; request.Tag = ++CurrentTag; @@ -398,10 +516,10 @@ private async Task SendRequestAsync(TransmissionRequest re if (httpResponse.IsSuccessStatusCode) { var responseString = await httpResponse.Content.ReadAsStringAsync(); - result = JsonConvert.DeserializeObject(responseString); + result = new TransmissionResponse(responseString); if (result.Result != "success") - throw new Exception(result.Result); + throw new RequestFailedException(result.Result); } else if (httpResponse.StatusCode == HttpStatusCode.Conflict) { @@ -411,7 +529,7 @@ private async Task SendRequestAsync(TransmissionRequest re if (httpResponse.Headers.TryGetValues("X-Transmission-Session-Id", out var values)) SessionID = values.First(); else - throw new Exception("Session ID Error"); + throw new SessionIdException(); result = await SendRequestAsync(request); } diff --git a/Transmission.API.RPC/Client.cs b/Transmission.API.RPC/Client.cs index fa2f484..dbe8018 100644 --- a/Transmission.API.RPC/Client.cs +++ b/Transmission.API.RPC/Client.cs @@ -2,6 +2,8 @@ using System.Text; using Transmission.API.RPC.Entity; using Transmission.API.RPC.Arguments; +using System.IO; +using System.Xml.Linq; namespace Transmission.API.RPC { @@ -34,7 +36,7 @@ public string SessionID /// /// Current Tag /// - public int CurrentTag + public long CurrentTag { get; private set; @@ -108,6 +110,18 @@ public SessionInfo GetSessionInformation() return task.Result; } + /// + /// Get information of current session (API: session-get) + /// + /// Optional fields of session information + /// Session information + public SessionInfo GetSessionInformation(string[] fields) + { + var task = GetSessionInformationAsync(fields); + task.WaitAndUnwrapException(); + return task.Result; + } + #endregion #region Torrents methods @@ -132,13 +146,25 @@ public void TorrentSet(TorrentSettings settings) TorrentSetAsync(settings).WaitAndUnwrapException(); } + /// + /// Get fields of recently active torrents (API: torrent-get) + /// + /// Fields of torrents + /// Torrents info + public TransmissionTorrents TorrentGetRecentlyActive(string[] fields) + { + var task = TorrentGetRecentlyActiveAsync(fields); + task.WaitAndUnwrapException(); + return task.Result; + } + /// /// Get fields of torrents from ids (API: torrent-get) /// /// Fields of torrents /// IDs of torrents (null or empty for get all torrents) /// Torrents info - public TransmissionTorrents TorrentGet(string[] fields, params int[] ids) + public TransmissionTorrents TorrentGet(string[] fields, params long[] ids) { var task = TorrentGetAsync(fields, ids); task.WaitAndUnwrapException(); @@ -150,7 +176,7 @@ public TransmissionTorrents TorrentGet(string[] fields, params int[] ids) /// /// Torrents id /// Remove data - public void TorrentRemove(int[] ids, bool deleteData = false) + public void TorrentRemove(long[] ids, bool deleteData = false) { TorrentRemoveAsync(ids, deleteData).WaitAndUnwrapException(); } @@ -168,9 +194,9 @@ public void TorrentStart(object[] ids) /// /// Start recently active torrents (API: torrent-start) /// - public void TorrentStart() + public void TorrentStartRecentlyActive() { - TorrentStartAsync().WaitAndUnwrapException(); + TorrentStartRecentlyActiveAsync().WaitAndUnwrapException(); } #endregion @@ -188,9 +214,9 @@ public void TorrentStartNow(object[] ids) /// /// Start now recently active torrents (API: torrent-start-now) /// - public void TorrentStartNow() + public void TorrentStartNowRecentlyActive() { - TorrentStartNowAsync().WaitAndUnwrapException(); + TorrentStartNowRecentlyActiveAsync().WaitAndUnwrapException(); } #endregion @@ -207,13 +233,14 @@ public void TorrentStop(object[] ids) /// /// Stop recently active torrents (API: torrent-stop) /// - public void TorrentStop() + public void TorrentStopRecentlyActive() { - TorrentStopAsync().WaitAndUnwrapException(); + TorrentStopRecentlyActiveAsync().WaitAndUnwrapException(); } #endregion #region Torrent Verify + /// /// Verify torrents (API: torrent-verify) /// @@ -226,17 +253,41 @@ public void TorrentVerify(object[] ids) /// /// Verify recently active torrents (API: torrent-verify) /// - public void TorrentVerify() + public void TorrentVerifyRecentlyActive() { - TorrentVerifyAsync().WaitAndUnwrapException(); + TorrentVerifyRecentlyActiveAsync().WaitAndUnwrapException(); } + #endregion + #region Torrent Reannounce + + /// + /// Reannounce torrents (API: torrent-reannounce) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + public void TorrentReannounce(object[] ids) + { + TorrentReannounceAsync(ids).WaitAndUnwrapException(); + } + + /// + /// Reannounce recently active torrents (API: torrent-reannounce) + /// + public void TorrentReannounceRecentlyActive() + { + TorrentReannounceRecentlyActiveAsync().WaitAndUnwrapException(); + } + + #endregion + + #region Torrent Queue + /// /// Move torrents in queue on top (API: queue-move-top) /// /// Torrents id - public void TorrentQueueMoveTop(int[] ids) + public void TorrentQueueMoveTop(long[] ids) { TorrentQueueMoveTopAsync(ids).WaitAndUnwrapException(); } @@ -245,7 +296,7 @@ public void TorrentQueueMoveTop(int[] ids) /// Move up torrents in queue (API: queue-move-up) /// /// - public void TorrentQueueMoveUp(int[] ids) + public void TorrentQueueMoveUp(long[] ids) { TorrentQueueMoveUpAsync(ids).WaitAndUnwrapException(); } @@ -254,7 +305,7 @@ public void TorrentQueueMoveUp(int[] ids) /// Move down torrents in queue (API: queue-move-down) /// /// - public void TorrentQueueMoveDown(int[] ids) + public void TorrentQueueMoveDown(long[] ids) { TorrentQueueMoveDownAsync(ids).WaitAndUnwrapException(); } @@ -263,18 +314,20 @@ public void TorrentQueueMoveDown(int[] ids) /// Move torrents to bottom in queue (API: queue-move-bottom) /// /// - public void TorrentQueueMoveBottom(int[] ids) + public void TorrentQueueMoveBottom(long[] ids) { TorrentQueueMoveBottomAsync(ids).WaitAndUnwrapException(); } + #endregion + /// /// Set new location for torrents files (API: torrent-set-location) /// /// Torrent ids /// The new torrent location /// Move from previous location - public void TorrentSetLocation(int[] ids, string location, bool move) + public void TorrentSetLocation(long[] ids, string location, bool move) { TorrentSetLocationAsync(ids, location, move).WaitAndUnwrapException(); } @@ -285,22 +338,48 @@ public void TorrentSetLocation(int[] ids, string location, bool move) /// The torrent whose path will be renamed /// The path to the file or folder that will be renamed /// The file or folder's new name - public RenameTorrentInfo TorrentRenamePath(int id, string path, string name) + public RenameTorrentInfo TorrentRenamePath(long id, string path, string name) { var task = TorrentRenamePathAsync(id, path, name); task.WaitAndUnwrapException(); return task.Result; } - //method name not recognized - ///// - ///// Reannounce torrent (API: torrent-reannounce) - ///// - ///// - //public void ReannounceTorrents(object[] ids) - //{ - // ReannounceTorrentsAsync(ids).WaitAndUnwrapException(); - //} + #endregion + + #region Bandwidth Groups + + /// + /// Get bandwidth groups (API: group-get) + /// + /// + public BandwidthGroup[] BandwidthGroupGet() + { + var task = BandwidthGroupGetAsync(); + task.WaitAndUnwrapException(); + return task.Result; + } + + /// + /// Get bandwidth groups (API: group-get) + /// + /// Optional names of groups to get + /// + public BandwidthGroup[] BandwidthGroupGet(string[] groups) + { + var task = BandwidthGroupGetAsync(groups); + task.WaitAndUnwrapException(); + return task.Result; + } + + /// + /// Set bandwidth groups (API: group-set) + /// + /// A bandwidth group to set + public void BandwidthGroupSet(BandwidthGroupSettings group) + { + BandwidthGroupGetAsync().WaitAndUnwrapException(); + } #endregion @@ -309,7 +388,7 @@ public RenameTorrentInfo TorrentRenamePath(int id, string path, string name) /// See if your incoming peer port is accessible from the outside world (API: port-test) /// /// Accessible state - public bool PortTest() + public Tuple PortTest() { var task = PortTestAsync(); task.WaitAndUnwrapException(); @@ -320,7 +399,7 @@ public bool PortTest() /// Update blocklist (API: blocklist-update) /// /// Blocklist size - public int BlocklistUpdate() + public long? BlocklistUpdate() { var task = BlocklistUpdateAsync(); task.WaitAndUnwrapException(); @@ -331,12 +410,13 @@ public int BlocklistUpdate() /// Get free space is available in a client-specified folder. /// /// The directory to query - public long FreeSpace(string path) + public FreeSpace FreeSpace(string path) { var task = FreeSpaceAsync(path); task.WaitAndUnwrapException(); return task.Result; } + #endregion } } diff --git a/Transmission.API.RPC/Common/CommunicateBase.cs b/Transmission.API.RPC/Common/CommunicateBase.cs deleted file mode 100644 index ed999fa..0000000 --- a/Transmission.API.RPC/Common/CommunicateBase.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Transmission.API.RPC.Common -{ - /// - /// Base class for request/response - /// - public abstract class CommunicateBase - { - /// - /// Data - /// - [JsonProperty("arguments")] - public Dictionary Arguments; - - /// - /// Number (id) - /// - [JsonProperty("tag")] - public int Tag; - - /// - /// Convert to JSON string - /// - /// - public virtual string ToJson() - { - return JsonConvert.SerializeObject(this, Formatting.Indented); - } - - /// - /// Deserialize to class - /// - /// - public T Deserialize() - { - var argumentsString = JsonConvert.SerializeObject(this.Arguments); - return JsonConvert.DeserializeObject(argumentsString); - } - } -} diff --git a/Transmission.API.RPC/Common/TransmissionRequest.cs b/Transmission.API.RPC/Common/TransmissionRequest.cs index 6396a8a..597a52c 100644 --- a/Transmission.API.RPC/Common/TransmissionRequest.cs +++ b/Transmission.API.RPC/Common/TransmissionRequest.cs @@ -10,7 +10,7 @@ namespace Transmission.API.RPC.Common /// /// Transmission request /// - public class TransmissionRequest : CommunicateBase + public class TransmissionRequest { /// /// Name of the method to invoke @@ -18,6 +18,18 @@ public class TransmissionRequest : CommunicateBase [JsonProperty("method")] public string Method; + /// + /// Data + /// + [JsonProperty("arguments")] + public Dictionary Arguments; + + /// + /// Number (id) + /// + [JsonProperty("tag")] + public long Tag; + /// /// Initialize request /// @@ -48,5 +60,14 @@ public TransmissionRequest(string method, Dictionary arguments) this.Method = method; this.Arguments = arguments; } - } + + /// + /// Convert to JSON string + /// + /// + public virtual string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + } } diff --git a/Transmission.API.RPC/Common/TransmissionResponse.cs b/Transmission.API.RPC/Common/TransmissionResponse.cs index 9fde714..1fbe997 100644 --- a/Transmission.API.RPC/Common/TransmissionResponse.cs +++ b/Transmission.API.RPC/Common/TransmissionResponse.cs @@ -1,6 +1,8 @@ using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,12 +12,51 @@ namespace Transmission.API.RPC.Common /// /// Transmission response /// - public class TransmissionResponse : CommunicateBase + public class TransmissionResponse { /// /// Contains "success" on success, or an error string on failure. /// - [JsonProperty("result")] - public string Result; - } + public string Result { get; } + + /// + /// Uniquely identifies which request this is a response to + /// + public int? Tag { get; } + + /// + /// Data + /// + public JObject Arguments { get; } + + public TransmissionResponse(string json) + { + using var stringReader = new StringReader(json); + using var jsonReader = new JsonTextReader(stringReader); + + while (jsonReader.Read()) + { + if (jsonReader.TokenType == JsonToken.PropertyName) + { + if (jsonReader.Value.ToString() == "result") + { + jsonReader.Read(); + Result = jsonReader.Value.ToString(); + } + + else if (jsonReader.Value.ToString() == "tag") + { + jsonReader.Read(); + Tag = jsonReader.Value != null ? (int?)Convert.ToInt32(jsonReader.Value) : null; + } + + else if (jsonReader.Value.ToString() == "arguments") + { + jsonReader.Read(); + Arguments = JObject.Load(jsonReader); + } + } + } + } + } } diff --git a/Transmission.API.RPC/Entity/BandwidthGroup.cs b/Transmission.API.RPC/Entity/BandwidthGroup.cs new file mode 100644 index 0000000..3ad96de --- /dev/null +++ b/Transmission.API.RPC/Entity/BandwidthGroup.cs @@ -0,0 +1,50 @@ +#nullable enable +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Transmission.API.RPC.Entity +{ + /// + /// Contains settings for a bandwidth group + /// + public class BandwidthGroup + { + /// + /// Session limits are honored + /// + [JsonProperty("honorsSessionLimits")] + public bool? HonorsSessionLimits { get; set; } + + /// + /// Name of the bandwidth group + /// + [JsonProperty("name")] + public string? Name { get; set; } + + /// + /// Max global download speed of this bandwidth group (KBps) + /// + [JsonProperty("speed-limit-down")] + public long? SpeedLimitDown { get; set; } + + /// + /// True means enabled + /// + [JsonProperty("speed-limit-down-enabled")] + public bool? SpeedLimitDownEnabled { get; set; } + + /// + /// Max global upload speed of this bandwidth group (KBps) + /// + [JsonProperty("speed-limit-up")] + public long? SpeedLimitUp { get; set; } + + /// + /// True means enabled + /// + [JsonProperty("speed-limit-up-enabled")] + public bool? SpeedLimitUpEnabled { get; set; } + } +} diff --git a/Transmission.API.RPC/Entity/FreeSpace.cs b/Transmission.API.RPC/Entity/FreeSpace.cs new file mode 100644 index 0000000..5addb32 --- /dev/null +++ b/Transmission.API.RPC/Entity/FreeSpace.cs @@ -0,0 +1,34 @@ +#nullable enable +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Transmission.API.RPC.Entity +{ + /// + /// FreeSpace + /// + public class FreeSpace + { + /// + /// Path of the queried directory + /// + [JsonProperty("path")] + public string? Path { get; set; } + + /// + /// The size, in bytes, of the free space in that directory + /// + [JsonProperty("size-bytes")] + public long? SizeBytes { get; set; } + + /// + /// the total capacity, in bytes, of that directory + /// + [JsonProperty("total_size")] + public long? TotalSize { get; set; } + } +} diff --git a/Transmission.API.RPC/Entity/IntOrArrayConverter.cs b/Transmission.API.RPC/Entity/IntOrArrayConverter.cs new file mode 100644 index 0000000..9175648 --- /dev/null +++ b/Transmission.API.RPC/Entity/IntOrArrayConverter.cs @@ -0,0 +1,81 @@ +#nullable enable +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRemote.Backends.Transmission +{ + /// + /// JSON type converter for type long[] or long or int[] or int + /// This is needed because the Availability field was introduced in Transmission 4.0.0 + /// On earlier versions, the field defaults to "0" and decoding to an array fails. + /// + public class IntOrArrayConverter : JsonConverter + { + /// + /// Returns true whether the object is of type long[] or long or int[] or int + /// + /// + /// + public override bool CanConvert(Type objectType) + { + return objectType == typeof(long?[]) || objectType == typeof(long[]) || objectType == typeof(int?[]) || objectType == typeof(int[]) || objectType == typeof(long?) || objectType == typeof(long) || objectType == typeof(int?) || objectType == typeof(int); + } + + /// + /// Read long[] or single long (not array) from json + /// + /// + /// + /// + /// + /// + /// + public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) + { + JToken token = JToken.Load(reader); + + if (token.Type == JTokenType.Integer) + { + // Return an array with one element if it's a single integer + if (objectType == typeof(long[])) return new long[] { (long)token }; + if (objectType == typeof(long?[])) return new long?[] { (long?)token }; + } + else if (token.Type == JTokenType.Array) + { + // Return the integer array if it's a JSON array + if (objectType == typeof(long[])) return token.ToObject(); + if (objectType == typeof(long?[])) return token.ToObject(); + } + + throw new JsonSerializationException("Unexpected token type"); + } + + /// + /// Write long[] to json + /// + /// + /// + /// + public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) + { + if (value != null) + { + long[] longArray = (long[])value; + if (longArray.Length == 1) + { + writer.WriteValue(longArray[0]); + } + else + { + JArray array = new JArray(longArray); + array.WriteTo(writer); + } + } + } + } +} diff --git a/Transmission.API.RPC/Entity/NewTorrentInfo.cs b/Transmission.API.RPC/Entity/NewTorrentInfo.cs index ee5ac79..9be24bf 100644 --- a/Transmission.API.RPC/Entity/NewTorrentInfo.cs +++ b/Transmission.API.RPC/Entity/NewTorrentInfo.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +#nullable enable +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -16,19 +17,24 @@ public class NewTorrentInfo /// Torrent ID /// [JsonProperty("id")] - public int ID { get; set; } + public int Id { get; set; } /// /// Torrent name /// [JsonProperty("name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Torrent Hash /// [JsonProperty("hashString")] - public string HashString { get; set; } + public string? HashString { get; set; } + + /// + /// Whether the torrent is a duplicate of an existing torrent (add failed) + /// + public bool? Duplicate { get; set; } } } diff --git a/Transmission.API.RPC/Entity/RenameTorrentInfo.cs b/Transmission.API.RPC/Entity/RenameTorrentInfo.cs index 7365f4e..e26ecf8 100644 --- a/Transmission.API.RPC/Entity/RenameTorrentInfo.cs +++ b/Transmission.API.RPC/Entity/RenameTorrentInfo.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +#nullable enable +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -16,18 +17,18 @@ public class RenameTorrentInfo /// The torrent's unique Id. /// [JsonProperty("id")] - public int ID { get; set; } + public int Id { get; set; } /// /// File path. /// [JsonProperty("path")] - public string Path { get; set; } + public string? Path { get; set; } /// /// File name. /// [JsonProperty("name")] - public string Name { get; set; } + public string? Name { get; set; } } } diff --git a/Transmission.API.RPC/Entity/SessionInfo.cs b/Transmission.API.RPC/Entity/SessionInfo.cs index f5137d4..c75eb04 100644 --- a/Transmission.API.RPC/Entity/SessionInfo.cs +++ b/Transmission.API.RPC/Entity/SessionInfo.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +#nullable enable +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -18,7 +19,7 @@ public class SessionInfo /// Max global download speed (KBps) /// [JsonProperty("alt-speed-down")] - public int? AlternativeSpeedDown { get; set; } + public long? AlternativeSpeedDown { get; set; } /// /// True means use the alt speeds @@ -30,7 +31,7 @@ public class SessionInfo /// When to turn on alt speeds (units: minutes after midnight) /// [JsonProperty("alt-speed-time-begin")] - public int? AlternativeSpeedTimeBegin { get; set; } + public long? AlternativeSpeedTimeBegin { get; set; } /// /// True means the scheduled on/off times are used @@ -42,25 +43,25 @@ public class SessionInfo /// When to turn off alt speeds /// [JsonProperty("alt-speed-time-end")] - public int? AlternativeSpeedTimeEnd { get; set; } + public long? AlternativeSpeedTimeEnd { get; set; } /// /// What day(s) to turn on alt speeds /// [JsonProperty("alt-speed-time-day")] - public int? AlternativeSpeedTimeDay { get; set; } + public long? AlternativeSpeedTimeDay { get; set; } /// /// Max global upload speed (KBps) /// [JsonProperty("alt-speed-up")] - public int? AlternativeSpeedUp { get; set; } + public long? AlternativeSpeedUp { get; set; } /// /// Location of the blocklist to use for "blocklist-update" /// [JsonProperty("blocklist-url")] - public string BlocklistURL { get; set; } + public string? BlocklistUrl { get; set; } /// /// True means enabled @@ -68,30 +69,48 @@ public class SessionInfo [JsonProperty("blocklist-enabled")] public bool? BlocklistEnabled { get; set; } + /// + /// Number of rules in the blocklist + /// + [JsonProperty("blocklist-size")] + public long? BlocklistSize { get; set; } + /// /// Maximum size of the disk cache (MB) /// [JsonProperty("cache-size-mb")] - public int? CacheSizeMB { get; set; } + public long? CacheSizeMb { get; set; } + + /// + /// Default announce URLs, one per line, and a blank line between tiers + /// + [JsonProperty("default-trackers")] + public string? DefaultTrackers { get; set; } + + /// + /// Allow DHT in public torrents + /// + [JsonProperty("dht-enabled")] + public bool? DhtEnabled { get; set; } /// /// Default path to download torrents /// [JsonProperty("download-dir")] - public string DownloadDirectory { get; set; } + public string? DownloadDirectory { get; set; } /// /// Free space in download dir /// [JsonProperty("download-dir-free-space")] [Obsolete("Obsolete since Transmission 4.0.0. Use the free-space method instead.")] - public string DownloadDirectoryFreeSpace { get; set; } + public string? DownloadDirectoryFreeSpace { get; set; } /// /// Max number of torrents to download at once (see download-queue-enabled) /// [JsonProperty("download-queue-size")] - public int? DownloadQueueSize { get; set; } + public long? DownloadQueueSize { get; set; } /// /// If true, limit how many torrents can be downloaded at once @@ -99,23 +118,17 @@ public class SessionInfo [JsonProperty("download-queue-enabled")] public bool? DownloadQueueEnabled { get; set; } - /// - /// True means allow dht in public torrents - /// - [JsonProperty("dht-enabled")] - public bool? DHTEnabled { get; set; } - /// /// "required", "preferred", "tolerated" /// [JsonProperty("encryption")] - public string Encryption { get; set; } + public string? Encryption { get; set; } /// /// Torrents we're seeding will be stopped if they're idle for this long /// [JsonProperty("idle-seeding-limit")] - public int? IdleSeedingLimit { get; set; } + public long? IdleSeedingLimit { get; set; } /// /// True if the seeding inactivity limit is honored by default @@ -127,7 +140,7 @@ public class SessionInfo /// Path for incomplete torrents, when enabled /// [JsonProperty("incomplete-dir")] - public string IncompleteDirectory { get; set; } + public string? IncompleteDirectory { get; set; } /// /// True means keep torrents in incomplete-dir until done @@ -139,19 +152,19 @@ public class SessionInfo /// True means allow Local Peer Discovery in public torrents /// [JsonProperty("lpd-enabled")] - public bool? LPDEnabled { get; set; } + public bool? LpdEnabled { get; set; } /// /// Maximum global number of peers /// [JsonProperty("peer-limit-global")] - public int? PeerLimitGlobal { get; set; } + public long? PeerLimitGlobal { get; set; } /// /// Maximum global number of peers /// [JsonProperty("peer-limit-per-torrent")] - public int? PeerLimitPerTorrent { get; set; } + public long? PeerLimitPerTorrent { get; set; } /// /// True means allow pex in public torrents @@ -163,7 +176,7 @@ public class SessionInfo /// Port number /// [JsonProperty("peer-port")] - public int? PeerPort { get; set; } + public long? PeerPort { get; set; } /// /// True means pick a random peer port on launch @@ -187,25 +200,37 @@ public class SessionInfo /// Torrents that are idle for N minuets aren't counted toward seed-queue-size or download-queue-size /// [JsonProperty("queue-stalled-minutes")] - public int? QueueStalledMinutes { get; set; } + public long? QueueStalledMinutes { get; set; } /// /// True means append ".part" to incomplete files /// [JsonProperty("rename-partial-files")] public bool? RenamePartialFiles { get; set; } - + /// /// Session ID /// [JsonProperty("session-id")] - public string SessionID { get; set; } + public string? SessionId { get; set; } + + /// + /// Filename of the script to run + /// + [JsonProperty("script-torrent-added-filename")] + public string? ScriptTorrentAddedFilename { get; set; } + + /// + /// Whether or not to call the "added" script + /// + [JsonProperty("script-torrent-added-enabled")] + public bool? ScriptTorrentAddedEnabled { get; set; } /// /// Filename of the script to run /// [JsonProperty("script-torrent-done-filename")] - public string ScriptTorrentDoneFilename { get; set; } + public string? ScriptTorrentDoneFilename { get; set; } /// /// Whether or not to call the "done" script @@ -213,6 +238,18 @@ public class SessionInfo [JsonProperty("script-torrent-done-enabled")] public bool? ScriptTorrentDoneEnabled { get; set; } + /// + /// Filename of the script to run + /// + [JsonProperty("script-torrent-done-seeding-filename")] + public string? ScriptTorrentDoneSeedingFilename { get; set; } + + /// + /// Whether or not to call the "done seeding" script + /// + [JsonProperty("script-torrent-done-seeding-enabled")] + public bool? ScriptTorrentDoneSeedingEnabled { get; set; } + /// /// The default seed ratio for torrents to use /// @@ -229,7 +266,7 @@ public class SessionInfo /// Max number of torrents to uploaded at once (see seed-queue-enabled) /// [JsonProperty("seed-queue-size")] - public int? SeedQueueSize { get; set; } + public long? SeedQueueSize { get; set; } /// /// If true, limit how many torrents can be uploaded at once @@ -241,7 +278,7 @@ public class SessionInfo /// Max global download speed (KBps) /// [JsonProperty("speed-limit-down")] - public int? SpeedLimitDown { get; set; } + public long? SpeedLimitDown { get; set; } /// /// True means enabled @@ -253,7 +290,7 @@ public class SessionInfo /// max global upload speed (KBps) /// [JsonProperty("speed-limit-up")] - public int? SpeedLimitUp { get; set; } + public long? SpeedLimitUp { get; set; } /// /// True means enabled @@ -277,7 +314,7 @@ public class SessionInfo /// Units /// [JsonProperty("units")] - public Units Units { get; set; } + public Units? Units { get; set; } /// /// True means allow utp @@ -285,34 +322,34 @@ public class SessionInfo [JsonProperty("utp-enabled")] public bool? UtpEnabled { get; set; } - /// - /// Number of rules in the blocklist - /// - [JsonProperty("blocklist-size")] - public int BlocklistSize{ get; set; } - /// /// Location of transmission's configuration directory /// [JsonProperty("config-dir")] - public string ConfigDirectory{ get; set; } + public string? ConfigDirectory{ get; set; } /// /// The current RPC API version /// [JsonProperty("rpc-version")] - public int RpcVersion{ get; set; } + public long? RpcVersion{ get; set; } /// /// The minimum RPC API version supported /// [JsonProperty("rpc-version-minimum")] - public int RpcVersionMinimum{ get; set; } + public long? RpcVersionMinimum { get; set; } + + /// + /// Current RPC API version in a semver-compatible string + /// + [JsonProperty("rpc-version-semver")] + public string? RpcVersionSemver { get; set; } /// - /// Long version string "$version ($revision)" + /// long? version string "$version ($revision)" /// [JsonProperty("version")] - public string Version{ get; set; } + public string? Version{ get; set; } } } diff --git a/Transmission.API.RPC/Entity/Statistic.cs b/Transmission.API.RPC/Entity/Statistic.cs index 22668bf..b63ca66 100644 --- a/Transmission.API.RPC/Entity/Statistic.cs +++ b/Transmission.API.RPC/Entity/Statistic.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +#nullable enable +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -16,43 +17,43 @@ public class Statistic /// Active torrent count /// [JsonProperty("activeTorrentCount")] - public int ActiveTorrentCount { get; set; } + public long? ActiveTorrentCount { get; set; } /// /// Download speed /// [JsonProperty("downloadSpeed")] - public int downloadSpeed{ get; set; } + public long? downloadSpeed{ get; set; } /// /// Paused torrent count /// [JsonProperty("pausedTorrentCount")] - public int pausedTorrentCount{ get; set; } + public long? pausedTorrentCount{ get; set; } /// /// Torrent count /// [JsonProperty("torrentCount")] - public int torrentCount{ get; set; } + public long? torrentCount{ get; set; } /// /// Upload speed /// [JsonProperty("uploadSpeed")] - public int uploadSpeed{ get; set; } + public long? uploadSpeed{ get; set; } /// /// Cumulative stats /// [JsonProperty("cumulative-stats")] - public CommonStatistic CumulativeStats { get; set; } + public CommonStatistic? CumulativeStats { get; set; } /// /// Current stats /// [JsonProperty("current-stats")] - public CommonStatistic CurrentStats { get; set; } + public CommonStatistic? CurrentStats { get; set; } } /// @@ -64,30 +65,30 @@ public class CommonStatistic /// Uploaded bytes /// [JsonProperty("uploadedBytes")] - public double uploadedBytes{ get; set; } + public long? UploadedBytes{ get; set; } /// /// Downloaded bytes /// [JsonProperty("downloadedBytes")] - public double DownloadedBytes{ get; set; } + public long? DownloadedBytes{ get; set; } /// /// Files added /// [JsonProperty("filesAdded")] - public int FilesAdded{ get; set; } + public long? FilesAdded{ get; set; } /// /// Session count /// [JsonProperty("SessionCount")] - public int SessionCount{ get; set; } + public long? SessionCount{ get; set; } /// /// Seconds active /// [JsonProperty("SecondsActive")] - public int SecondsActive{ get; set; } + public long? SecondsActive{ get; set; } } } diff --git a/Transmission.API.RPC/Entity/TorrentInfo.cs b/Transmission.API.RPC/Entity/TorrentInfo.cs index 3a8cfef..4907b25 100644 --- a/Transmission.API.RPC/Entity/TorrentInfo.cs +++ b/Transmission.API.RPC/Entity/TorrentInfo.cs @@ -1,4 +1,6 @@ -using Newtonsoft.Json; +#nullable enable +using JDRemote.Backends.Transmission; +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -16,379 +18,398 @@ public class TorrentInfo /// The torrent's unique Id. /// [JsonProperty("id")] - public int ID { get; set; } + public long Id { get; set; } /// /// Activity date /// [JsonProperty("activityDate")] - public long ActivityDate { get; set; } + public long? ActivityDate { get; set; } /// /// Added date /// [JsonProperty("addedDate")] - public long AddedDate { get; set; } + public long? AddedDate { get; set; } + + /// + /// Availability + /// + [JsonProperty("availability")] + [JsonConverter(typeof(IntOrArrayConverter))] // Without this converter, Transmission < 4.0.0 leads to an error. + public long[]? Availability { get; set; } /// /// Torrents bandwidth priority /// [JsonProperty("bandwidthPriority")] - public int BandwidthPriority { get; set; } + public long? BandwidthPriority { get; set; } /// /// Comment /// [JsonProperty("comment")] - public string Comment { get; set; } + public string? Comment { get; set; } /// /// Corrupt ever /// [JsonProperty("corruptEver")] - public int CorruptEver { get; set; } + public long? CorruptEver { get; set; } /// /// Creator /// [JsonProperty("creator")] - public string Creator { get; set; } + public string? Creator { get; set; } /// /// Date created /// [JsonProperty("dateCreated")] - public long DateCreated { get; set; } + public long? DateCreated { get; set; } /// /// Desired available /// [JsonProperty("desiredAvailable")] - public long DesiredAvailable { get; set; } + public long? DesiredAvailable { get; set; } /// /// Done date /// [JsonProperty("doneDate")] - public long DoneDate { get; set; } + public long? DoneDate { get; set; } /// /// Download directory /// [JsonProperty("downloadDir")] - public string DownloadDir { get; set; } + public string? DownloadDir { get; set; } /// /// Downloaded ever /// [JsonProperty("downloadedEver")] - public string DownloadedEver { get; set; } + public long? DownloadedEver { get; set; } /// /// Download limit /// [JsonProperty("downloadLimit")] - public string DownloadLimit { get; set; } + public long? DownloadLimit { get; set; } /// /// Download limited /// [JsonProperty("downloadLimited")] - public string DownloadLimited { get; set; } + public bool? DownloadLimited { get; set; } /// /// Edit date /// [JsonProperty("editDate")] - public long EditDate { get; set; } + public long? EditDate { get; set; } /// /// Error /// [JsonProperty("error")] - public int Error { get; set; } + public long? Error { get; set; } /// /// Error string /// [JsonProperty("errorString")] - public string ErrorString { get; set; } + public string? ErrorString { get; set; } /// /// ETA /// [JsonProperty("eta")] - public int ETA { get; set; } + public long? Eta { get; set; } /// /// ETA idle /// [JsonProperty("etaIdle")] - public int ETAIdle { get; set; } + public long? EtaIdle { get; set; } /// /// File count /// [JsonProperty("file-count")] - public int FileCount { get; set; } + public long? FileCount { get; set; } /// /// Files /// [JsonProperty("files")] - public TransmissionTorrentFiles[] Files { get; set; } + public TransmissionTorrentFiles[]? Files { get; set; } /// /// File stats /// [JsonProperty("fileStats")] - public TransmissionTorrentFileStats[] FileStats { get; set; } + public TransmissionTorrentFileStats[]? FileStats { get; set; } + + /// + /// Group + /// + [JsonProperty("group")] + public string? Group { get; set; } /// /// Hash string /// [JsonProperty("hashString")] - public string HashString { get; set; } + public string? HashString { get; set; } /// /// Have unchecked /// [JsonProperty("haveUnchecked")] - public int HaveUnchecked { get; set; } + public long? HaveUnchecked { get; set; } /// /// Have valid /// [JsonProperty("haveValid")] - public long HaveValid { get; set; } + public long? HaveValid { get; set; } /// /// Honors session limits /// [JsonProperty("honorsSessionLimits")] - public bool HonorsSessionLimits { get; set; } + public bool? HonorsSessionLimits { get; set; } /// /// Is finished /// [JsonProperty("isFinished")] - public bool IsFinished { get; set; } + public bool? IsFinished { get; set; } /// /// Is private /// [JsonProperty("isPrivate")] - public bool IsPrivate { get; set; } + public bool? IsPrivate { get; set; } /// /// Is stalled /// [JsonProperty("isStalled")] - public bool IsStalled { get; set; } + public bool? IsStalled { get; set; } /// /// Labels /// [JsonProperty("labels")] - public string[] Labels { get; set; } + public string[]? Labels { get; set; } /// /// Left until done /// [JsonProperty("leftUntilDone")] - public long LeftUntilDone { get; set; } + public long? LeftUntilDone { get; set; } /// /// Magnet link /// [JsonProperty("magnetLink")] - public string MagnetLink { get; set; } + public string? MagnetLink { get; set; } /// /// Manual announce time /// [JsonProperty("manualAnnounceTime")] - public int ManualAnnounceTime { get; set; } + public long? ManualAnnounceTime { get; set; } /// /// Max connected peers /// [JsonProperty("maxConnectedPeers")] - public int MaxConnectedPeers { get; set; } + public long? MaxConnectedPeers { get; set; } /// /// Metadata percent complete /// [JsonProperty("metadataPercentComplete")] - public double MetadataPercentComplete { get; set; } + public double? MetadataPercentComplete { get; set; } /// /// Name /// [JsonProperty("name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Peer limit /// [JsonProperty("peer-limit")] - public int PeerLimit { get; set; } + public long? PeerLimit { get; set; } /// /// Peers /// [JsonProperty("peers")] - public TransmissionTorrentPeers[] Peers { get; set; } + public TransmissionTorrentPeers[]? Peers { get; set; } /// /// Peers connected /// [JsonProperty("peersConnected")] - public int PeersConnected { get; set; } + public long? PeersConnected { get; set; } /// /// Peers from /// [JsonProperty("peersFrom")] - public TransmissionTorrentPeersFrom PeersFrom { get; set; } + public TransmissionTorrentPeersFrom? PeersFrom { get; set; } /// /// Peers getting from us /// [JsonProperty("peersGettingFromUs")] - public int PeersGettingFromUs { get; set; } + public long? PeersGettingFromUs { get; set; } /// /// Peers sending to us /// [JsonProperty("peersSendingToUs")] - public int PeersSendingToUs { get; set; } + public long? PeersSendingToUs { get; set; } /// /// Percent complete /// [JsonProperty("percentComplete")] - public double PercentComplete { get; set; } + public double? PercentComplete { get; set; } /// /// Percent done /// [JsonProperty("percentDone")] - public double PercentDone { get; set; } + public double? PercentDone { get; set; } /// /// Pieces /// [JsonProperty("pieces")] - public string Pieces { get; set; } + public string? Pieces { get; set; } /// /// Piece count /// [JsonProperty("pieceCount")] - public int PieceCount { get; set; } + public long? PieceCount { get; set; } /// /// Piece size /// [JsonProperty("pieceSize")] - public long PieceSize { get; set; } + public long? PieceSize { get; set; } /// /// Priorities /// [JsonProperty("priorities")] - public int[] Priorities { get; set; } + public long[]? Priorities { get; set; } /// /// Primary mime type /// [JsonProperty("primary-mime-type")] - public string PrimaryMimeType { get; set; } + public string? PrimaryMimeType { get; set; } /// /// Queue position /// [JsonProperty("queuePosition")] - public int QueuePosition { get; set; } + public long? QueuePosition { get; set; } /// /// Rate download /// [JsonProperty("rateDownload")] - public int RateDownload { get; set; } + public long? RateDownload { get; set; } /// /// Rate upload /// [JsonProperty("rateUpload")] - public int RateUpload { get; set; } + public long? RateUpload { get; set; } /// /// Recheck progress /// [JsonProperty("recheckProgress")] - public double RecheckProgress { get; set; } + public double? RecheckProgress { get; set; } /// /// Seconds downloading /// [JsonProperty("secondsDownloading")] - public int SecondsDownloading { get; set; } + public long? SecondsDownloading { get; set; } /// /// Seconds seeding /// [JsonProperty("secondsSeeding")] - public int SecondsSeeding { get; set; } + public long? SecondsSeeding { get; set; } /// /// Seed idle limit /// [JsonProperty("seedIdleLimit")] - public int SeedIdleLimit { get; set; } + public long? SeedIdleLimit { get; set; } /// /// Seed idle mode /// [JsonProperty("seedIdleMode")] - public int SeedIdleMode { get; set; } + public long? SeedIdleMode { get; set; } /// /// Seed ratio limit /// [JsonProperty("seedRatioLimit")] - public double SeedRatioLimit { get; set; } + public double? SeedRatioLimit { get; set; } /// /// Seed ratio mode /// [JsonProperty("seedRatioMode")] - public int SeedRatioMode { get; set; } + public long? SeedRatioMode { get; set; } + + /// + /// Sequential Download + /// + [JsonProperty("sequentialDownload")] + public bool? SequentialDownload { get; set; } /// /// Size when done /// [JsonProperty("sizeWhenDone")] - public long SizeWhenDone { get; set; } + public long? SizeWhenDone { get; set; } /// /// Start date /// [JsonProperty("startDate")] - public long StartDate { get; set; } + public long? StartDate { get; set; } /// /// Status /// [JsonProperty("status")] - public int Status { get; set; } + public long? Status { get; set; } /// /// Trackers /// [JsonProperty("trackers")] - public TransmissionTorrentTrackers[] Trackers { get; set; } + public TransmissionTorrentTrackers[]? Trackers { get; set; } /// /// Tracker list: @@ -396,67 +417,67 @@ public class TorrentInfo /// line between tiers /// [JsonProperty("trackerList")] - public string TrackerList { get; set; } + public string? TrackerList { get; set; } /// /// Tracker stats /// [JsonProperty("trackerStats")] - public TransmissionTorrentTrackerStats[] TrackerStats { get; set; } + public TransmissionTorrentTrackerStats[]? TrackerStats { get; set; } /// /// Total size /// [JsonProperty("totalSize")] - public long TotalSize { get; set; } + public long? TotalSize { get; set; } /// /// Torrent file /// [JsonProperty("torrentFile")] - public string TorrentFile { get; set; } + public string? TorrentFile { get; set; } /// /// Uploaded ever /// [JsonProperty("uploadedEver")] - public long UploadedEver { get; set; } + public long? UploadedEver { get; set; } /// /// Upload limit /// [JsonProperty("uploadLimit")] - public int UploadLimit { get; set; } + public long? UploadLimit { get; set; } /// /// Upload limited /// [JsonProperty("uploadLimited")] - public bool UploadLimited { get; set; } + public bool? UploadLimited { get; set; } /// /// Upload ratio /// [JsonProperty("uploadRatio")] - public double uploadRatio { get; set; } + public double? uploadRatio { get; set; } /// /// Wanted /// [JsonProperty("wanted")] - public bool[] Wanted { get; set; } + public bool[]? Wanted { get; set; } /// /// Web seeds /// [JsonProperty("webseeds")] - public string[] Webseeds { get; set; } + public string[]? Webseeds { get; set; } /// /// Web seeds sending to us /// [JsonProperty("webseedsSendingToUs")] - public int WebseedsSendingToUs { get; set; } + public long? WebseedsSendingToUs { get; set; } } /// @@ -468,19 +489,31 @@ public class TransmissionTorrentFiles /// Bytes completed /// [JsonProperty("bytesCompleted")] - public double BytesCompleted{ get; set; } + public long? BytesCompleted{ get; set; } /// /// Length /// [JsonProperty("length")] - public double Length{ get; set; } + public long? Length{ get; set; } /// /// Name /// [JsonProperty("name")] - public string Name{ get; set; } + public string? Name{ get; set; } + + /// + /// First piece index of file + /// + [JsonProperty("beginPiece")] + public long? BeginPiece { get; set; } + + /// + /// Last piece index of file + /// + [JsonProperty("endPiece")] + public long? EndPiece { get; set; } } /// @@ -492,19 +525,19 @@ public class TransmissionTorrentFileStats /// Bytes completed /// [JsonProperty("bytesCompleted")] - public double BytesCompleted{ get; set; } + public long? BytesCompleted{ get; set; } /// /// Wanted /// [JsonProperty("wanted")] - public bool Wanted{ get; set; } + public bool? Wanted{ get; set; } /// /// Priority /// [JsonProperty("priority")] - public int Priority{ get; set; } + public long? Priority{ get; set; } } /// @@ -516,91 +549,97 @@ public class TransmissionTorrentPeers /// Address /// [JsonProperty("address")] - public string Address{ get; set; } + public string? Address{ get; set; } /// /// Client name /// [JsonProperty("clientName")] - public string ClientName{ get; set; } + public string? ClientName{ get; set; } /// /// Client is choked /// [JsonProperty("clientIsChoked")] - public bool ClientIsChoked{ get; set; } + public bool? ClientIsChoked{ get; set; } /// - /// Client is interested + /// Client is Interested /// [JsonProperty("clientIsInterested")] - public bool ClientIsInterested{ get; set; } + public bool? ClientIsInterested{ get; set; } /// /// Flag string /// [JsonProperty("flagStr")] - public string FlagStr{ get; set; } + public string? FlagStr{ get; set; } /// /// Is downloading from /// [JsonProperty("isDownloadingFrom")] - public bool IsDownloadingFrom{ get; set; } + public bool? IsDownloadingFrom{ get; set; } /// /// Is encrypted /// [JsonProperty("isEncrypted")] - public bool IsEncrypted{ get; set; } + public bool? IsEncrypted { get; set; } + + /// + /// Is incoming + /// + [JsonProperty("isIncoming")] + public bool? IsIncoming { get; set; } /// /// Is uploading to /// [JsonProperty("isUploadingTo")] - public bool IsUploadingTo{ get; set; } + public bool? IsUploadingTo{ get; set; } /// /// Is UTP /// [JsonProperty("isUTP")] - public bool IsUTP{ get; set; } + public bool? IsUtp{ get; set; } /// /// Peer is choked /// [JsonProperty("peerIsChoked")] - public bool PeerIsChoked{ get; set; } + public bool? PeerIsChoked{ get; set; } /// - /// Peer is interested + /// Peer is Interested /// [JsonProperty("peerIsInterested")] - public bool PeerIsInterested{ get; set; } + public bool? PeerIsInterested{ get; set; } /// /// Port /// [JsonProperty("port")] - public int Port{ get; set; } + public long? Port{ get; set; } /// /// Progress /// [JsonProperty("progress")] - public double Progress{ get; set; } + public double? Progress{ get; set; } /// /// Rate to client /// [JsonProperty("rateToClient")] - public int RateToClient{ get; set; } + public long? RateToClient{ get; set; } /// /// Rate to peer /// [JsonProperty("rateToPeer")] - public int RateToPeer{ get; set; } + public long? RateToPeer{ get; set; } } /// @@ -608,41 +647,47 @@ public class TransmissionTorrentPeers /// public class TransmissionTorrentPeersFrom { + /// + /// From cache + /// + [JsonProperty("fromCache")] + public long? FromCache { get; set; } + /// /// From DHT /// [JsonProperty("fromDht")] - public int FromDHT{ get; set; } + public long? FromDht { get; set; } /// /// From incoming /// [JsonProperty("fromIncoming")] - public int FromIncoming{ get; set; } + public long? FromIncoming{ get; set; } /// /// From LPD /// [JsonProperty("fromLpd")] - public int FromLPD{ get; set; } + public long? FromLpd{ get; set; } /// /// From LTEP /// [JsonProperty("fromLtep")] - public int FromLTEP{ get; set; } + public long? FromLtep{ get; set; } /// /// From PEX /// [JsonProperty("fromPex")] - public int FromPEX{ get; set; } + public long? FromPex{ get; set; } /// /// From tracker /// [JsonProperty("fromTracker")] - public int FromTracker{ get; set; } + public long? FromTracker{ get; set; } } /// @@ -654,25 +699,31 @@ public class TransmissionTorrentTrackers /// Announce /// [JsonProperty("announce")] - public string announce{ get; set; } + public string? Announce{ get; set; } /// /// Id /// [JsonProperty("id")] - public int ID{ get; set; } + public long Id{ get; set; } /// /// Scrape /// [JsonProperty("scrape")] - public string Scrape{ get; set; } + public string? Scrape{ get; set; } + + /// + /// Site name + /// + [JsonProperty("sitename")] + public string? SiteName { get; set; } /// /// Tier /// [JsonProperty("tier")] - public int Tier{ get; set; } + public long? Tier{ get; set; } } /// @@ -684,161 +735,167 @@ public class TransmissionTorrentTrackerStats /// Announce /// [JsonProperty("announce")] - public string announce{ get; set; } + public string? Announce{ get; set; } /// /// Announce state /// [JsonProperty("announceState")] - public int AnnounceState{ get; set; } + public long? AnnounceState{ get; set; } /// /// Download count /// [JsonProperty("downloadCount")] - public int DownloadCount{ get; set; } + public long? DownloadCount{ get; set; } /// /// Has announced /// [JsonProperty("hasAnnounced")] - public bool HasAnnounced{ get; set; } + public bool? HasAnnounced{ get; set; } /// /// Has scraped /// [JsonProperty("hasScraped")] - public bool HasScraped{ get; set; } + public bool? HasScraped{ get; set; } /// /// Host /// [JsonProperty("host")] - public string Host{ get; set; } + public string? Host{ get; set; } /// /// Is backup /// [JsonProperty("isBackup")] - public bool IsBackup{ get; set; } + public bool? IsBackup{ get; set; } /// /// Last announce peer count /// [JsonProperty("lastAnnouncePeerCount")] - public int LastAnnouncePeerCount{ get; set; } + public long? LastAnnouncePeerCount{ get; set; } /// /// Id /// [JsonProperty("id")] - public int ID{ get; set; } + public long? Id{ get; set; } /// /// Last announce result /// [JsonProperty("lastAnnounceResult")] - public string LastAnnounceResult{ get; set; } + public string? LastAnnounceResult{ get; set; } /// /// Last announce succeeded /// [JsonProperty("lastAnnounceSucceeded")] - public bool LastAnnounceSucceeded{ get; set; } + public bool? LastAnnounceSucceeded{ get; set; } /// /// Last announce start time /// [JsonProperty("lastAnnounceStartTime")] - public int LastAnnounceStartTime{ get; set; } + public long? LastAnnounceStartTime{ get; set; } /// /// Last scrape result /// [JsonProperty("lastScrapeResult")] - public string LastScrapeResult{ get; set; } + public string? LastScrapeResult{ get; set; } /// /// Last announce timed out /// [JsonProperty("lastAnnounceTimedOut")] - public bool LastAnnounceTimedOut{ get; set; } + public bool? LastAnnounceTimedOut{ get; set; } /// /// Last announce time /// [JsonProperty("lastAnnounceTime")] - public int LastAnnounceTime{ get; set; } + public long? LastAnnounceTime{ get; set; } /// /// Last scrape scceeded /// [JsonProperty("lastScrapeSucceeded")] - public bool LastScrapeSucceeded{ get; set; } + public bool? LastScrapeSucceeded{ get; set; } /// /// Last scrape start time /// [JsonProperty("lastScrapeStartTime")] - public int LastScrapeStartTime{ get; set; } + public long? LastScrapeStartTime{ get; set; } /// /// Last scrape timed out /// [JsonProperty("lastScrapeTimedOut")] - public bool LastScrapeTimedOut{ get; set; } + public bool? LastScrapeTimedOut{ get; set; } /// /// Last scrape time /// [JsonProperty("lastScrapeTime")] - public int LastScrapeTime{ get; set; } + public long? LastScrapeTime{ get; set; } /// /// Scrape /// [JsonProperty("scrape")] - public string Scrape{ get; set; } + public string? Scrape{ get; set; } /// /// Tier /// [JsonProperty("tier")] - public int Tier{ get; set; } + public long? Tier{ get; set; } /// /// Leecher count /// [JsonProperty("leecherCount")] - public int LeecherCount{ get; set; } + public long? LeecherCount{ get; set; } /// /// Next announce time /// [JsonProperty("nextAnnounceTime")] - public int NextAnnounceTime{ get; set; } + public long? NextAnnounceTime{ get; set; } /// /// Next scrape time /// [JsonProperty("nextScrapeTime")] - public int NextScrapeTime{ get; set; } + public long? NextScrapeTime{ get; set; } /// /// Scrape state /// [JsonProperty("scrapeState")] - public int ScrapeState{ get; set; } + public long? ScrapeState{ get; set; } /// /// Seeder count /// [JsonProperty("seederCount")] - public int SeederCount{ get; set; } + public long? SeederCount{ get; set; } + + /// + /// Site name + /// + [JsonProperty("sitename")] + public string? SiteName { get; set; } } /// - /// Contains arrays of torrents and removed torrents + /// Contains arrays of torrents, and removed torrents in an integer array /// public class TransmissionTorrents { @@ -846,12 +903,12 @@ public class TransmissionTorrents /// Array of torrents /// [JsonProperty("torrents")] - public TorrentInfo[] Torrents{ get; set; } + public TorrentInfo[]? Torrents{ get; set; } /// /// Array of torrent-id numbers of recently-removed torrents /// [JsonProperty("removed")] - public TorrentInfo[] Removed{ get; set; } + public long[]? Removed{ get; set; } } } diff --git a/Transmission.API.RPC/Entity/Units.cs b/Transmission.API.RPC/Entity/Units.cs index 50d402c..faf6766 100644 --- a/Transmission.API.RPC/Entity/Units.cs +++ b/Transmission.API.RPC/Entity/Units.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +#nullable enable +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; @@ -16,36 +17,36 @@ public class Units /// Speed units /// [JsonProperty("speed-units")] - public string[] SpeedUnits { get; set; } + public string[]? SpeedUnits { get; set; } /// /// Speed bytes /// [JsonProperty("speed-bytes")] - public int? SpeedBytes { get; set; } + public long? SpeedBytes { get; set; } /// /// Size units /// [JsonProperty("size-units")] - public string[] SizeUnits { get; set; } + public string[]? SizeUnits { get; set; } /// /// Size bytes /// [JsonProperty("size-bytes")] - public int? SizeBytes { get; set; } + public long? SizeBytes { get; set; } /// /// Memory units /// [JsonProperty("memory-units")] - public string[] MemoryUnits { get; set; } + public string[]? MemoryUnits { get; set; } /// /// Memory bytes /// [JsonProperty("memory-bytes")] - public int? MemoryBytes { get; set; } + public long? MemoryBytes { get; set; } } } diff --git a/Transmission.API.RPC/Exceptions.cs b/Transmission.API.RPC/Exceptions.cs new file mode 100644 index 0000000..b8ce25e --- /dev/null +++ b/Transmission.API.RPC/Exceptions.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Transmission.API.RPC +{ + public class RequestFailedException : Exception + { + public RequestFailedException(string description) : base(description) { } + } + + public class SessionIdException : Exception + { + public SessionIdException() : base("Session ID Error") { } + } +} diff --git a/Transmission.API.RPC/ITransmissionClient.cs b/Transmission.API.RPC/ITransmissionClient.cs index b978ca0..ef46539 100644 --- a/Transmission.API.RPC/ITransmissionClient.cs +++ b/Transmission.API.RPC/ITransmissionClient.cs @@ -1,4 +1,7 @@ -using Transmission.API.RPC.Arguments; +#nullable enable +using System.Threading.Tasks; +using System; +using Transmission.API.RPC.Arguments; using Transmission.API.RPC.Entity; namespace Transmission.API.RPC @@ -11,7 +14,7 @@ public interface ITransmissionClient /// /// Current tag /// - int CurrentTag { get; } + long CurrentTag { get; } /// /// Session ID @@ -27,7 +30,7 @@ public interface ITransmissionClient /// Update blocklist (API: blocklist-update) /// /// Blocklist size - int BlocklistUpdate(); + long? BlocklistUpdate(); /// /// Close current session (API: session-close) @@ -38,25 +41,32 @@ public interface ITransmissionClient /// Get free space is available in a client-specified folder. /// /// The directory to query - long FreeSpace(string path); + FreeSpace? FreeSpace(string path); /// /// Get information of current session (API: session-get) /// /// Session information - SessionInfo GetSessionInformation(); + SessionInfo? GetSessionInformation(); + + /// + /// Get information of current session (API: session-get) + /// + /// Optional fields of session information + /// Session information + SessionInfo? GetSessionInformation(string[] fields); /// /// Get session stat /// /// Session stat - Statistic GetSessionStatistic(); + Statistic? GetSessionStatistic(); /// /// See if your incoming peer port is accessible from the outside world (API: port-test) /// - /// Accessible state - bool PortTest(); + /// A Tuple with a boolean of whether the port test succeeded, and a PortTestProtocol enum of which protocol was used for the test + Tuple PortTest(); /// /// Set information to current session (API: session-set) @@ -68,7 +78,14 @@ public interface ITransmissionClient /// Add torrent (API: torrent-add) /// /// Torrent info (ID, Name and HashString) - NewTorrentInfo TorrentAdd(NewTorrent torrent); + NewTorrentInfo? TorrentAdd(NewTorrent torrent); + + /// + /// Get fields of recently active torrents (API: torrent-get) + /// + /// Fields of torrents + /// Torrents info + TransmissionTorrents? TorrentGetRecentlyActive(string[] fields); /// /// Get fields of torrents from ids (API: torrent-get) @@ -76,38 +93,38 @@ public interface ITransmissionClient /// Fields of torrents /// IDs of torrents (null or empty for get all torrents) /// Torrents info - TransmissionTorrents TorrentGet(string[] fields, params int[] ids); + TransmissionTorrents? TorrentGet(string[] fields, params long[] ids); /// /// Move torrents to bottom in queue (API: queue-move-bottom) /// /// - void TorrentQueueMoveBottom(int[] ids); + void TorrentQueueMoveBottom(long[] ids); /// /// Move down torrents in queue (API: queue-move-down) /// /// - void TorrentQueueMoveDown(int[] ids); + void TorrentQueueMoveDown(long[] ids); /// /// Move torrents in queue on top (API: queue-move-top) /// /// Torrents id - void TorrentQueueMoveTop(int[] ids); + void TorrentQueueMoveTop(long[] ids); /// /// Move up torrents in queue (API: queue-move-up) /// /// - void TorrentQueueMoveUp(int[] ids); + void TorrentQueueMoveUp(long[] ids); /// /// Remove torrents (API: torrent-remove) /// /// Torrents id /// Remove local data - void TorrentRemove(int[] ids, bool deleteData = false); + void TorrentRemove(long[] ids, bool deleteData = false); /// /// Rename a file or directory in a torrent (API: torrent-rename-path) @@ -115,7 +132,7 @@ public interface ITransmissionClient /// The torrent whose path will be renamed /// The path to the file or folder that will be renamed /// The file or folder's new name - RenameTorrentInfo TorrentRenamePath(int id, string path, string name); + RenameTorrentInfo? TorrentRenamePath(long id, string path, string name); /// /// Set torrent params (API: torrent-set) @@ -129,12 +146,12 @@ public interface ITransmissionClient /// Torrent ids /// The new torrent location /// Move from previous location - void TorrentSetLocation(int[] ids, string location, bool move); + void TorrentSetLocation(long[] ids, string location, bool move); /// /// Start recently active torrents (API: torrent-start) /// - void TorrentStart(); + void TorrentStartRecentlyActive(); /// /// Start torrents (API: torrent-start) @@ -145,7 +162,7 @@ public interface ITransmissionClient /// /// Start now recently active torrents (API: torrent-start-now) /// - void TorrentStartNow(); + void TorrentStartNowRecentlyActive(); /// /// Start now torrents (API: torrent-start-now) @@ -156,7 +173,7 @@ public interface ITransmissionClient /// /// Stop recently active torrents (API: torrent-stop) /// - void TorrentStop(); + void TorrentStopRecentlyActive(); /// /// Stop torrents (API: torrent-stop) @@ -167,12 +184,42 @@ public interface ITransmissionClient /// /// Verify recently active torrents (API: torrent-verify) /// - void TorrentVerify(); + void TorrentVerifyRecentlyActive(); /// /// Verify torrents (API: torrent-verify) /// /// A list of torrent id numbers, sha1 hash strings, or both void TorrentVerify(object[] ids); + + /// + /// Reannounce recently active torrents (API: torrent-reannounce) + /// + void TorrentReannounceRecentlyActive(); + + /// + /// Reannounce torrents (API: torrent-reannounce) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + void TorrentReannounce(object[] ids); + + /// + /// Get bandwidth groups (API: group-get) + /// + /// + BandwidthGroup[]? BandwidthGroupGet(); + + /// + /// Get bandwidth groups (API: group-get) + /// + /// Optional names of groups to get + /// + BandwidthGroup[]? BandwidthGroupGet(string[] groups); + + /// + /// Set bandwidth groups (API: group-set) + /// + /// A bandwidth group to set + void BandwidthGroupSet(BandwidthGroupSettings group); } } diff --git a/Transmission.API.RPC/ITransmissionClientAsync.cs b/Transmission.API.RPC/ITransmissionClientAsync.cs index dbf91c6..6b51880 100644 --- a/Transmission.API.RPC/ITransmissionClientAsync.cs +++ b/Transmission.API.RPC/ITransmissionClientAsync.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +#nullable enable +using System; +using System.Threading.Tasks; using Transmission.API.RPC.Arguments; using Transmission.API.RPC.Entity; @@ -14,7 +16,7 @@ public interface ITransmissionClientAsync /// Update blocklist (API: blocklist-update) /// /// Blocklist size - Task BlocklistUpdateAsync(); + Task BlocklistUpdateAsync(); /// /// Close current session (API: session-close) @@ -25,25 +27,32 @@ public interface ITransmissionClientAsync /// Get free space is available in a client-specified folder. /// /// The directory to query - Task FreeSpaceAsync(string path); + Task FreeSpaceAsync(string path); /// /// Get information of current session (API: session-get) /// /// Session information - Task GetSessionInformationAsync(); + Task GetSessionInformationAsync(); + + /// + /// Get information of current session (API: session-get) + /// + /// Optional fields of session information + /// Session information + Task GetSessionInformationAsync(string[] fields); /// /// Get session stat /// /// Session stat - Task GetSessionStatisticAsync(); + Task GetSessionStatisticAsync(); /// /// See if your incoming peer port is accessible from the outside world (API: port-test) /// - /// Accessible state - Task PortTestAsync(); + /// A Tuple with a boolean of whether the port test succeeded, and a PortTestProtocol enum of which protocol was used for the test + Task> PortTestAsync(); /// /// Set information to current session (API: session-set) @@ -55,7 +64,14 @@ public interface ITransmissionClientAsync /// Add torrent (API: torrent-add) /// /// Torrent info (ID, Name and HashString) - Task TorrentAddAsync(NewTorrent torrent); + Task TorrentAddAsync(NewTorrent torrent); + + /// + /// Get fields of recently active torrents (API: torrent-get) + /// + /// Fields of torrents + /// Torrents info + Task TorrentGetRecentlyActiveAsync(string[] fields); /// /// Get fields of torrents from ids (API: torrent-get) @@ -63,38 +79,38 @@ public interface ITransmissionClientAsync /// Fields of torrents /// IDs of torrents (null or empty for get all torrents) /// Torrents info - Task TorrentGetAsync(string[] fields, params int[] ids); + Task TorrentGetAsync(string[] fields, params long[] ids); /// /// Move torrents to bottom in queue (API: queue-move-bottom) /// /// - Task TorrentQueueMoveBottomAsync(int[] ids); + Task TorrentQueueMoveBottomAsync(long[] ids); /// /// Move down torrents in queue (API: queue-move-down) /// /// - Task TorrentQueueMoveDownAsync(int[] ids); + Task TorrentQueueMoveDownAsync(long[] ids); /// /// Move torrents in queue on top (API: queue-move-top) /// /// Torrents id - Task TorrentQueueMoveTopAsync(int[] ids); + Task TorrentQueueMoveTopAsync(long[] ids); /// /// Move up torrents in queue (API: queue-move-up) /// /// - Task TorrentQueueMoveUpAsync(int[] ids); + Task TorrentQueueMoveUpAsync(long[] ids); /// /// Remove torrents /// /// Torrents id /// Remove local data - Task TorrentRemoveAsync(int[] ids, bool deleteData = false); + Task TorrentRemoveAsync(long[] ids, bool deleteData = false); /// /// Rename a file or directory in a torrent (API: torrent-rename-path) @@ -102,7 +118,7 @@ public interface ITransmissionClientAsync /// The torrent whose path will be renamed /// The path to the file or folder that will be renamed /// The file or folder's new name - Task TorrentRenamePathAsync(int id, string path, string name); + Task TorrentRenamePathAsync(long id, string path, string name); /// /// Set torrent params (API: torrent-set) @@ -116,12 +132,12 @@ public interface ITransmissionClientAsync /// Torrent ids /// The new torrent location /// Move from previous location - Task TorrentSetLocationAsync(int[] ids, string location, bool move); + Task TorrentSetLocationAsync(long[] ids, string location, bool move); /// /// Start recently active torrents (API: torrent-start) /// - Task TorrentStartAsync(); + Task TorrentStartRecentlyActiveAsync(); /// /// Start torrents (API: torrent-start) @@ -132,7 +148,7 @@ public interface ITransmissionClientAsync /// /// Start now recently active torrents (API: torrent-start-now) /// - Task TorrentStartNowAsync(); + Task TorrentStartNowRecentlyActiveAsync(); /// /// Start now torrents (API: torrent-start-now) @@ -143,7 +159,7 @@ public interface ITransmissionClientAsync /// /// Stop recently active torrents (API: torrent-stop) /// - Task TorrentStopAsync(); + Task TorrentStopRecentlyActiveAsync(); /// /// Stop torrents (API: torrent-stop) @@ -154,12 +170,42 @@ public interface ITransmissionClientAsync /// /// Verify recently active torrents (API: torrent-verify) /// - Task TorrentVerifyAsync(); + Task TorrentVerifyRecentlyActiveAsync(); /// /// Verify torrents (API: torrent-verify) /// /// A list of torrent id numbers, sha1 hash strings, or both Task TorrentVerifyAsync(object[] ids); + + /// + /// Reannounce recently active torrents (API: torrent-reannounce) + /// + Task TorrentReannounceRecentlyActiveAsync(); + + /// + /// Reannounce torrents (API: torrent-reannounce) + /// + /// A list of torrent id numbers, sha1 hash strings, or both + Task TorrentReannounceAsync(object[] ids); + + /// + /// Get bandwidth groups (API: group-get) + /// + /// + Task BandwidthGroupGetAsync(); + + /// + /// Get bandwidth groups (API: group-get) + /// + /// Optional names of groups to get + /// + Task BandwidthGroupGetAsync(string[] groups); + + /// + /// Set bandwidth groups (API: group-set) + /// + /// A bandwidth group to set + Task BandwidthGroupSetAsync(BandwidthGroupSettings group); } } diff --git a/Transmission.API.RPC/Transmission.API.RPC.csproj b/Transmission.API.RPC/Transmission.API.RPC.csproj index f020772..9dca373 100644 --- a/Transmission.API.RPC/Transmission.API.RPC.csproj +++ b/Transmission.API.RPC/Transmission.API.RPC.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 true Library @@ -25,7 +25,7 @@ - +