using DownKyi.Core.Aria2cNet.Client.Entity; using DownKyi.Core.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; namespace DownKyi.Core.Aria2cNet.Client { /// /// http://aria2.github.io/manual/en/html/aria2c.html#methods /// public static class AriaClient { private static readonly string JSONRPC = "2.0"; private static readonly string TOKEN = "downkyi"; /// /// This method adds a new download. /// uris is an array of HTTP/FTP/SFTP/BitTorrent URIs (strings) pointing to the same resource. /// If you mix URIs pointing to different resources, /// then the download may fail or be corrupted without aria2 complaining. /// When adding BitTorrent Magnet URIs, /// uris must have only one element and it should be BitTorrent Magnet URI. /// options is a struct and its members are pairs of option name and value. /// See Options below for more details. /// If position is given, it must be an integer starting from 0. /// The new download will be inserted at position in the waiting queue. /// If position is omitted or position is larger than the current size of the queue, /// the new download is appended to the end of the queue. /// This method returns the GID of the newly registered download. /// /// /// /// /// public static async Task AddUriAsync(List uris, AriaSendOption option, int position = -1) { List ariaParams = new List { "token:" + TOKEN, uris, option }; if (position > -1) { ariaParams.Add(position); } AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.addUri", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method adds a BitTorrent download by uploading a ".torrent" file. /// If you want to add a BitTorrent Magnet URI, use the aria2.addUri() method instead. /// torrent must be a base64-encoded string containing the contents of the ".torrent" file. /// uris is an array of URIs (string). /// uris is used for Web-seeding. /// For single file torrents, the URI can be a complete URI pointing to the resource; /// if URI ends with /, name in torrent file is added. /// For multi-file torrents, name and path in torrent are added to form a URI for each file. /// options is a struct and its members are pairs of option name and value. /// See Options below for more details. /// If position is given, it must be an integer starting from 0. /// The new download will be inserted at position in the waiting queue. /// If position is omitted or position is larger than the current size of the queue, /// the new download is appended to the end of the queue. /// This method returns the GID of the newly registered download. /// If --rpc-save-upload-metadata is true, /// the uploaded data is saved as a file named as the hex string of SHA-1 hash of data plus ".torrent" in the directory specified by --dir option. /// E.g. a file name might be 0a3893293e27ac0490424c06de4d09242215f0a6.torrent. /// If a file with the same name already exists, it is overwritten! /// If the file cannot be saved successfully or --rpc-save-upload-metadata is false, /// the downloads added by this method are not saved by --save-session. /// /// /// /// /// public static async Task AddTorrentAsync(string torrent, List uris, AriaSendOption option, int position = -1) { List ariaParams = new List { "token:" + TOKEN, torrent, uris, option }; if (position > -1) { ariaParams.Add(position); } AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.addTorrent", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method adds a Metalink download by uploading a ".metalink" file. /// metalink is a base64-encoded string which contains the contents of the ".metalink" file. /// options is a struct and its members are pairs of option name and value. /// See Options below for more details. /// If position is given, it must be an integer starting from 0. /// The new download will be inserted at position in the waiting queue. /// If position is omitted or position is larger than the current size of the queue, /// the new download is appended to the end of the queue. /// This method returns an array of GIDs of newly registered downloads. /// If --rpc-save-upload-metadata is true, /// the uploaded data is saved as a file named hex string of SHA-1 hash of data plus ".metalink" in the directory specified by --dir option. /// E.g. a file name might be 0a3893293e27ac0490424c06de4d09242215f0a6.metalink. /// If a file with the same name already exists, it is overwritten! /// If the file cannot be saved successfully or --rpc-save-upload-metadata is false, /// the downloads added by this method are not saved by --save-session. /// /// /// /// /// public static async Task AddMetalinkAsync(string metalink, List uris, AriaSendOption option, int position = -1) { List ariaParams = new List { "token:" + TOKEN, metalink, uris, option }; if (position > -1) { ariaParams.Add(position); } AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.addMetalink", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method removes the download denoted by gid (string). /// If the specified download is in progress, it is first stopped. /// The status of the removed download becomes removed. /// This method returns GID of removed download. /// /// /// public static async Task RemoveAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.remove", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method removes the download denoted by gid. /// This method behaves just like aria2.remove() /// except that this method removes the download without performing any actions which take time, /// such as contacting BitTorrent trackers to unregister the download first. /// /// /// public static async Task ForceRemoveAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.forceRemove", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method pauses the download denoted by gid (string). /// The status of paused download becomes paused. /// If the download was active, the download is placed in the front of waiting queue. /// While the status is paused, the download is not started. /// To change status to waiting, use the aria2.unpause() method. /// This method returns GID of paused download. /// /// /// public static async Task PauseAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.pause", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method is equal to calling aria2.pause() for every active/waiting download. /// This methods returns OK. /// /// public static async Task PauseAllAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.pauseAll", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method pauses the download denoted by gid. /// This method behaves just like aria2.pause() /// except that this method pauses downloads without performing any actions which take time, /// such as contacting BitTorrent trackers to unregister the download first. /// /// /// public static async Task ForcePauseAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.forcePause", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method is equal to calling aria2.forcePause() for every active/waiting download. /// This methods returns OK. /// /// public static async Task ForcePauseAllAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.forcePauseAll", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method changes the status of the download denoted by gid (string) from paused to waiting, /// making the download eligible to be restarted. /// This method returns the GID of the unpaused download. /// /// /// public static async Task UnpauseAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.unpause", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method is equal to calling aria2.unpause() for every paused download. /// This methods returns OK. /// /// public static async Task UnpauseAllAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.unpauseAll", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns the progress of the download denoted by gid (string). /// keys is an array of strings. /// If specified, the response contains only keys in the keys array. /// If keys is empty or omitted, the response contains all keys. /// This is useful when you just want specific keys and avoid unnecessary transfers. /// For example, aria2.tellStatus("2089b05ecca3d829", ["gid", "status"]) returns the gid and status keys only. /// The response is a struct and contains following keys. Values are strings. /// /// /// public static async Task TellStatus(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.tellStatus", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns the URIs used in the download denoted by gid (string). /// The response is an array of structs and it contains following keys. /// Values are string. /// /// /// public static async Task GetUrisAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getUris", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns the file list of the download denoted by gid (string). /// The response is an array of structs which contain following keys. /// Values are strings. /// /// /// public static async Task GetFilesAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getFiles", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns a list peers of the download denoted by gid (string). /// This method is for BitTorrent only. /// The response is an array of structs and contains the following keys. /// Values are strings. /// /// /// public static async Task GetPeersAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getPeers", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns currently connected HTTP(S)/FTP/SFTP servers of the download denoted by gid (string). /// The response is an array of structs and contains the following keys. /// Values are strings. /// /// /// public static async Task GetServersAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getServers", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns a list of active downloads. /// The response is an array of the same structs as returned by the aria2.tellStatus() method. /// For the keys parameter, please refer to the aria2.tellStatus() method. /// /// public static async Task TellActiveAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.tellActive", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns a list of waiting downloads, including paused ones. /// offset is an integer and specifies the offset from the download waiting at the front. /// num is an integer and specifies the max. /// number of downloads to be returned. /// For the keys parameter, please refer to the aria2.tellStatus() method. ///

/// If offset is a positive integer, /// this method returns downloads in the range of [offset, offset + num). ///

/// offset can be a negative integer. /// offset == -1 points last download in the waiting queue and offset == -2 points the download before the last download, and so on. /// Downloads in the response are in reversed order then. ///

/// For example, imagine three downloads "A","B" and "C" are waiting in this order. /// aria2.tellWaiting(0, 1) returns ["A"]. /// aria2.tellWaiting(1, 2) returns ["B", "C"]. /// aria2.tellWaiting(-1, 2) returns ["C", "B"]. ///

/// The response is an array of the same structs as returned by aria2.tellStatus() method. ///
/// /// /// public static async Task TellWaitingAsync(int offset, int num) { List ariaParams = new List { "token:" + TOKEN, offset, num }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.tellWaiting", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns a list of stopped downloads. /// offset is an integer and specifies the offset from the least recently stopped download. /// num is an integer and specifies the max. /// number of downloads to be returned. /// For the keys parameter, please refer to the aria2.tellStatus() method. ///

/// offset and num have the same semantics as described in the aria2.tellWaiting() method. ///

/// The response is an array of the same structs as returned by the aria2.tellStatus() method. ///
/// /// /// public static async Task TellStoppedAsync(int offset, int num) { List ariaParams = new List { "token:" + TOKEN, offset, num }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.tellStopped", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method changes the position of the download denoted by gid in the queue. /// pos is an integer. /// how is a string. /// If how is POS_SET, it moves the download to a position relative to the beginning of the queue. /// If how is POS_CUR, it moves the download to a position relative to the current position. /// If how is POS_END, it moves the download to a position relative to the end of the queue. /// If the destination position is less than 0 or beyond the end of the queue, /// it moves the download to the beginning or the end of the queue respectively. /// The response is an integer denoting the resulting position. /// /// For example, if GID#2089b05ecca3d829 is currently in position 3, /// aria2.changePosition('2089b05ecca3d829', -1, 'POS_CUR') will change its position to 2. /// Additionally aria2.changePosition('2089b05ecca3d829', 0, 'POS_SET') will change its position to 0 (the beginning of the queue). /// /// The following examples move the download GID#2089b05ecca3d829 to the front of the queue. /// /// /// /// /// public static async Task ChangePositionAsync(string gid, int pos, HowChangePosition how) { List ariaParams = new List { "token:" + TOKEN, gid, pos, how.ToString("G") }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.changePosition", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method removes the URIs in delUris from and appends the URIs in addUris to download denoted by gid. /// delUris and addUris are lists of strings. /// A download can contain multiple files and URIs are attached to each file. /// fileIndex is used to select which file to remove/attach given URIs. /// fileIndex is 1-based. /// position is used to specify where URIs are inserted in the existing waiting URI list. /// position is 0-based. /// When position is omitted, URIs are appended to the back of the list. /// This method first executes the removal and then the addition. /// position is the position after URIs are removed, not the position when this method is called. /// When removing an URI, if the same URIs exist in download, /// only one of them is removed for each URI in delUris. /// In other words, /// if there are three URIs http://example.org/aria2 and you want remove them all, /// you have to specify (at least) 3 http://example.org/aria2 in delUris. /// This method returns a list which contains two integers. /// The first integer is the number of URIs deleted. The second integer is the number of URIs added. /// /// /// /// /// /// /// public static async Task ChangeUriAsync(string gid, int fileIndex, List delUris, List addUris, int position = -1) { List ariaParams = new List { "token:" + TOKEN, gid, fileIndex, delUris, addUris }; if (position > -1) { ariaParams.Add(position); } AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.changePosition", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns options of the download denoted by gid. /// The response is a struct where keys are the names of options. /// The values are strings. /// Note that this method does not return options which have no default value and have not been set on the command-line, /// in configuration files or RPC methods. /// /// /// public static async Task GetOptionAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getOption", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method changes options of the download denoted by gid (string) dynamically. /// options is a struct. /// The options listed in Input File subsection are available, except for following options: ///
/// dry-run metalink-base-uri parameterized-uri pause piece-length rpc-save-upload-metadata ///
/// Except for the following options, /// changing the other options of active download makes it restart /// (restart itself is managed by aria2, and no user intervention is required): ///
/// bt-max-peers bt-request-peer-speed-limit bt-remove-unselected-file force-save max-download-limit max-upload-limit ///
/// This method returns OK for success. ///
/// /// /// public static async Task ChangeOptionAsync(string gid, object option) { List ariaParams = new List { "token:" + TOKEN, gid, option }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.changeOption", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns the global options. /// The response is a struct. /// Its keys are the names of options. /// Values are strings. /// Note that this method does not return options which have no default value and have not been set on the command-line, /// in configuration files or RPC methods. /// Because global options are used as a template for the options of newly added downloads, /// the response contains keys returned by the aria2.getOption() method. /// /// public static async Task GetGlobalOptionAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getGlobalOption", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method changes global options dynamically. /// options is a struct. /// The following options are available: ///
/// bt-max-open-files download-result keep-unfinished-download-result log log-level /// max-concurrent-downloads max-download-result max-overall-download-limit max-overall-upload-limit /// optimize-concurrent-downloads save-cookies save-session server-stat-of ///
/// In addition, options listed in the Input File subsection are available, /// except for following options: checksum, index-out, out, pause and select-file. /// With the log option, you can dynamically start logging or change log file. /// To stop logging, specify an empty string("") as the parameter value. /// Note that log file is always opened in append mode. /// This method returns OK for success. ///
/// /// public static async Task ChangeGlobalOptionAsync(object option) { List ariaParams = new List { "token:" + TOKEN, option }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.changeGlobalOption", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns global statistics such as the overall download and upload speeds. /// The response is a struct and contains the following keys. Values are strings. /// /// public static async Task GetGlobalStatAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getGlobalStat", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method purges completed/error/removed downloads to free memory. /// This method returns OK. /// /// public static async Task PurgeDownloadResultAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.purgeDownloadResult", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method removes a completed/error/removed download denoted by gid from memory. /// This method returns OK for success. /// /// /// public static async Task RemoveDownloadResultAsync(string gid) { List ariaParams = new List { "token:" + TOKEN, gid }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.removeDownloadResult", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns the version of aria2 and the list of enabled features. /// The response is a struct and contains following keys. /// /// public static async Task GetAriaVersionAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getVersion", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns session information. /// The response is a struct and contains following key. ///

/// Session ID, which is generated each time when aria2 is invoked. ///
/// public static async Task GetSessionInfoAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.getSessionInfo", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method shuts down aria2. /// This method returns OK. /// /// public static async Task ShutdownAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.shutdown", Params = ariaParams }; var re = await GetRpcResponseAsync(ariaSend); return re; } /// /// This method shuts down aria2(). /// This method behaves like :func:'aria2.shutdown` without performing any actions which take time, /// such as contacting BitTorrent trackers to unregister downloads first. /// This method returns OK. /// /// public static async Task ForceShutdownAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.forceShutdown", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This method saves the current session to a file specified by the --save-session option. /// This method returns OK if it succeeds. /// /// public static async Task SaveSessionAsync() { List ariaParams = new List { "token:" + TOKEN }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "aria2.saveSession", Params = ariaParams }; return await GetRpcResponseAsync(ariaSend); } /// /// This methods encapsulates multiple method calls in a single request. /// methods is an array of structs. The structs contain two keys: methodName and params. /// methodName is the method name to call and params is array containing parameters to the method call. /// This method returns an array of responses. /// The elements will be either a one-item array containing the return value of the method call or a struct of fault element if an encapsulated method call fails. /// /// /// public static async Task> MulticallAsync(List systemMulticallMathods) { List ariaParams = new List { systemMulticallMathods }; AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "system.multicall", Params = ariaParams }; return await GetRpcResponseAsync>(ariaSend); } /// /// This method returns all the available RPC methods in an array of string. /// Unlike other methods, this method does not require secret token. /// This is safe because this method just returns the available method names. /// /// public static async Task ListMethodsAsync() { AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "system.listMethods" }; return await GetRpcResponseAsync(ariaSend); } /// /// This method returns all the available RPC notifications in an array of string. /// Unlike other methods, this method does not require secret token. /// This is safe because this method just returns the available notifications names. /// /// public static async Task ListNotificationsAsync() { AriaSendData ariaSend = new AriaSendData { Id = Guid.NewGuid().ToString("N"), Jsonrpc = JSONRPC, Method = "system.listNotifications" }; return await GetRpcResponseAsync(ariaSend); } /// /// 获取jsonrpc的地址 /// /// private static string GetRpcUri(int listenPort = 6800) { return $"http://localhost:{listenPort}/jsonrpc"; } /// /// 发送http请求,并将返回的json反序列化 /// /// /// /// private async static Task GetRpcResponseAsync(AriaSendData ariaSend) { // 去掉null var jsonSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; // 转换为json字符串 string sendJson = JsonConvert.SerializeObject(ariaSend, Formatting.Indented, jsonSetting); // 向服务器请求数据 string result = string.Empty; await Task.Run(() => { result = Request(GetRpcUri(), sendJson); }); if (result == null) { return default; } // 反序列化 var aria = JsonConvert.DeserializeObject(result); return aria; } /// /// http请求 /// /// /// /// /// private static string Request(string url, string parameters, int retry = 3) { // 重试次数 if (retry <= 0) { return null; } try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.Timeout = 5 * 1000; request.ContentType = "application/json"; byte[] postData = Encoding.UTF8.GetBytes(parameters); request.ContentLength = postData.Length; using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(postData, 0, postData.Length); reqStream.Close(); } string html = string.Empty; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { html = reader.ReadToEnd(); } } } return html; } catch (WebException e) { Utils.Debug.Console.PrintLine("Request()发生Web异常: {0}", e); LogManager.Error("AriaClient", e); //return Request(url, parameters, retry - 1); string html = string.Empty; var response = (HttpWebResponse)e.Response; if (response == null) { return null; } using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { html = reader.ReadToEnd(); } } Console.WriteLine($"本次请求使用的参数:{parameters}"); Console.WriteLine($"返回的web数据:{html}"); return html; } catch (IOException e) { Utils.Debug.Console.PrintLine("Request()发生IO异常: {0}", e); LogManager.Error("AriaClient", e); return Request(url, parameters, retry - 1); } catch (Exception e) { Utils.Debug.Console.PrintLine("Request()发生其他异常: {0}", e); LogManager.Error("AriaClient", e); return Request(url, parameters, retry - 1); } } } }