using Maki.Structures.Rest; using Newtonsoft.Json; using System; using System.IO; using System.Linq; using System.Net; using System.Text; namespace Maki.Rest { /// /// Handles requests to Discord's REST API /// internal class RestClient { /// /// User agent that is send alongside requests /// private const string USER_AGENT = @"DiscordBot (https://github.com/flashwave/maki, 1.0.0.0)"; /// /// Container for parent DiscordClient instance /// private readonly Discord client; /// /// Request types that should be handled as data requests /// private readonly RestRequestMethod[] dataRequestTypes = new RestRequestMethod[] { RestRequestMethod.POST, RestRequestMethod.PUT, RestRequestMethod.PATCH, }; /// /// Constructor /// /// Parent DiscordClient instance public RestClient(Discord c) { client = c; } /// /// Creates a base HttpWebRequest /// /// Request method /// Endpoint url /// Prepared HttpWebRequest private HttpWebRequest BaseRequest(RestRequestMethod method, string url) { Uri uri = new Uri(RestEndpoints.BASE_URL + RestEndpoints.BASE_PATH + url); HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest; request.Method = method.ToString(); request.UserAgent = USER_AGENT; if (!string.IsNullOrEmpty(client.Token)) request.Headers[HttpRequestHeader.Authorization] = (client.IsBot ? "Bot " : string.Empty) + client.Token; return request; } /// /// Gets a response string from HttpWebRequest /// /// HttpWebRequest instance /// string output private RestResponse HandleResponse(HttpWebRequest request) { HttpWebResponse webResponse; RestResponse response = new RestResponse(); try { webResponse = request.GetResponse() as HttpWebResponse; } catch (WebException ex) { webResponse = ex.Response as HttpWebResponse; } Enum.TryParse(webResponse.Method, out response.Method); response.Uri = webResponse.ResponseUri; response.Status = (ushort)webResponse.StatusCode; using (Stream httpResponseStream = webResponse.GetResponseStream()) using (StreamReader streamReader = new StreamReader(httpResponseStream)) response.RawResponse = streamReader.ReadToEnd(); webResponse.Close(); Error error = default(Error); try { error = JsonConvert.DeserializeObject(response.RawResponse); } catch { } if (error.Equals(default(Error))) { response.ErrorCode = RestErrorCode.Ok; response.ErrorMessage = string.Empty; } else { response.ErrorCode = (RestErrorCode)error.Code; response.ErrorMessage = error.Message; } if (client.LogRest) Console.WriteLine(response.RawResponse); if (response.Status == 200) response.Response = JsonConvert.DeserializeObject(response.RawResponse); return response; } /// /// Make a json request /// /// Type to use when deserialising the JSON object /// Request method /// Endpoint url /// Request data /// Deserialised JSON object public RestResponse Request(RestRequestMethod method, string url, object data = null) { HttpWebRequest request = BaseRequest(method, url); request.ContentType = "application/json;charset=utf-8"; request.ContentLength = 0; if (dataRequestTypes.Contains(method) && data != null) { byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)); request.ContentLength = bytes.LongLength; using (Stream requestStream = request.GetRequestStream()) requestStream.Write(bytes, 0, bytes.Length); } return HandleResponse(request); } } }