using Transmission.API.RPC; using Transmission.API.RPC.Arguments; using Transmission.API.RPC.Entity; namespace AnimeAnnouncer.Torrents { /// /// Thin wrapper around the Transmission RPC client for adding torrents to the server. /// public class TransmissionService { public Client Client { get; } private TransmissionService(Client client) { Client = client; } /// /// Creates a client and verifies the server is reachable by requesting session information. /// Throws if the server doesn't respond with a valid session. /// public static async Task ConnectAsync(String host, String? username, String? password) { var client = new Client(host, null, username, password); var sessionInformation = await client.GetSessionInformationAsync(); if (sessionInformation == null || String.IsNullOrEmpty(sessionInformation.Version)) throw new InvalidOperationException($"An error occurred while receiving session information from the rpc server at {host}"); return new TransmissionService(client); } /// /// Adds a .torrent file to the server, saving to , and applies a seed ratio limit. /// public async Task AddNewTorrentFileToServerAsync(byte[] torrentFileData, String saveLocation, bool paused = true, double seedRatioLimit = 1.0) { NewTorrent newTorrent = new() { DownloadDirectory = saveLocation, Paused = paused, Metainfo = Convert.ToBase64String(torrentFileData) }; var torrentInfo = await Client.TorrentAddAsync(newTorrent); var seedSettings = new TorrentSettings() { SeedRatioLimit = seedRatioLimit, SeedRatioMode = 1, IDs = [torrentInfo.ID] }; // TorrentSetAsync returns void in Transmission.API.RPC 2.1.2, so it can't be awaited Client.TorrentSet(seedSettings); return torrentInfo; } } }