Improved all things HTTP related
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -9,109 +9,108 @@ namespace Discord.API
|
||||
public const int MaxMessageSize = 2000;
|
||||
|
||||
//Auth
|
||||
public static async Task<APIResponses.AuthRegister> LoginAnonymous(string username, HttpOptions options)
|
||||
public static async Task<APIResponses.AuthRegister> LoginAnonymous(string username)
|
||||
{
|
||||
var fingerprintResponse = await Http.Post<APIResponses.AuthFingerprint>(Endpoints.AuthFingerprint, options);
|
||||
var fingerprintResponse = await Http.Post<APIResponses.AuthFingerprint>(Endpoints.AuthFingerprint);
|
||||
var registerRequest = new APIRequests.AuthRegisterRequest { Fingerprint = fingerprintResponse.Fingerprint, Username = username };
|
||||
var registerResponse = await Http.Post<APIResponses.AuthRegister>(Endpoints.AuthRegister, registerRequest, options);
|
||||
var registerResponse = await Http.Post<APIResponses.AuthRegister>(Endpoints.AuthRegister, registerRequest);
|
||||
return registerResponse;
|
||||
}
|
||||
public static async Task<APIResponses.AuthLogin> Login(string email, string password, HttpOptions options)
|
||||
public static async Task<APIResponses.AuthLogin> Login(string email, string password)
|
||||
{
|
||||
var request = new APIRequests.AuthLogin { Email = email, Password = password };
|
||||
var response = await Http.Post<APIResponses.AuthLogin>(Endpoints.AuthLogin, request, options);
|
||||
options.Token = response.Token;
|
||||
var response = await Http.Post<APIResponses.AuthLogin>(Endpoints.AuthLogin, request);
|
||||
return response;
|
||||
}
|
||||
public static Task Logout(HttpOptions options)
|
||||
=> Http.Post(Endpoints.AuthLogout, options);
|
||||
public static Task Logout()
|
||||
=> Http.Post(Endpoints.AuthLogout);
|
||||
|
||||
//Servers
|
||||
public static Task<APIResponses.CreateServer> CreateServer(string name, string region, HttpOptions options)
|
||||
public static Task<APIResponses.CreateServer> CreateServer(string name, string region)
|
||||
{
|
||||
var request = new APIRequests.CreateServer { Name = name, Region = region };
|
||||
return Http.Post<APIResponses.CreateServer>(Endpoints.Servers, request, options);
|
||||
return Http.Post<APIResponses.CreateServer>(Endpoints.Servers, request);
|
||||
}
|
||||
public static Task LeaveServer(string id, HttpOptions options)
|
||||
=> Http.Delete<APIResponses.DeleteServer>(Endpoints.Server(id), options);
|
||||
public static Task LeaveServer(string id)
|
||||
=> Http.Delete<APIResponses.DeleteServer>(Endpoints.Server(id));
|
||||
|
||||
//Channels
|
||||
public static Task<APIResponses.CreateChannel> CreateChannel(string serverId, string name, string channelType, HttpOptions options)
|
||||
public static Task<APIResponses.CreateChannel> CreateChannel(string serverId, string name, string channelType)
|
||||
{
|
||||
var request = new APIRequests.CreateChannel { Name = name, Type = channelType };
|
||||
return Http.Post<APIResponses.CreateChannel>(Endpoints.ServerChannels(serverId), request, options);
|
||||
return Http.Post<APIResponses.CreateChannel>(Endpoints.ServerChannels(serverId), request);
|
||||
}
|
||||
public static Task<APIResponses.CreateChannel> CreatePMChannel(string myId, string recipientId, HttpOptions options)
|
||||
public static Task<APIResponses.CreateChannel> CreatePMChannel(string myId, string recipientId)
|
||||
{
|
||||
var request = new APIRequests.CreatePMChannel { RecipientId = recipientId };
|
||||
return Http.Post<APIResponses.CreateChannel>(Endpoints.UserChannels(myId), request, options);
|
||||
return Http.Post<APIResponses.CreateChannel>(Endpoints.UserChannels(myId), request);
|
||||
}
|
||||
public static Task<APIResponses.DestroyChannel> DestroyChannel(string channelId, HttpOptions options)
|
||||
=> Http.Delete<APIResponses.DestroyChannel>(Endpoints.Channel(channelId), options);
|
||||
public static Task<APIResponses.GetMessages[]> GetMessages(string channelId, int count, HttpOptions options)
|
||||
=> Http.Get<APIResponses.GetMessages[]>(Endpoints.ChannelMessages(channelId, count), options);
|
||||
public static Task<APIResponses.DestroyChannel> DestroyChannel(string channelId)
|
||||
=> Http.Delete<APIResponses.DestroyChannel>(Endpoints.Channel(channelId));
|
||||
public static Task<APIResponses.GetMessages[]> GetMessages(string channelId, int count)
|
||||
=> Http.Get<APIResponses.GetMessages[]>(Endpoints.ChannelMessages(channelId, count));
|
||||
|
||||
//Members
|
||||
public static Task Kick(string serverId, string memberId, HttpOptions options)
|
||||
=> Http.Delete(Endpoints.ServerMember(serverId, memberId), options);
|
||||
public static Task Ban(string serverId, string memberId, HttpOptions options)
|
||||
=> Http.Put(Endpoints.ServerBan(serverId, memberId), options);
|
||||
public static Task Unban(string serverId, string memberId, HttpOptions options)
|
||||
=> Http.Delete(Endpoints.ServerBan(serverId, memberId), options);
|
||||
public static Task Kick(string serverId, string memberId)
|
||||
=> Http.Delete(Endpoints.ServerMember(serverId, memberId));
|
||||
public static Task Ban(string serverId, string memberId)
|
||||
=> Http.Put(Endpoints.ServerBan(serverId, memberId));
|
||||
public static Task Unban(string serverId, string memberId)
|
||||
=> Http.Delete(Endpoints.ServerBan(serverId, memberId));
|
||||
|
||||
//Invites
|
||||
public static Task<APIResponses.CreateInvite> CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass, HttpOptions options)
|
||||
public static Task<APIResponses.CreateInvite> CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass)
|
||||
{
|
||||
var request = new APIRequests.CreateInvite { MaxAge = maxAge, MaxUses = maxUses, IsTemporary = isTemporary, HasXkcdPass = hasXkcdPass };
|
||||
return Http.Post<APIResponses.CreateInvite>(Endpoints.ChannelInvites(channelId), request, options);
|
||||
return Http.Post<APIResponses.CreateInvite>(Endpoints.ChannelInvites(channelId), request);
|
||||
}
|
||||
public static Task<APIResponses.GetInvite> GetInvite(string id, HttpOptions options)
|
||||
=> Http.Get<APIResponses.GetInvite>(Endpoints.Invite(id), options);
|
||||
public static Task AcceptInvite(string id, HttpOptions options)
|
||||
=> Http.Post<APIResponses.AcceptInvite>(Endpoints.Invite(id), options);
|
||||
public static Task DeleteInvite(string id, HttpOptions options)
|
||||
=> Http.Delete(Endpoints.Invite(id), options);
|
||||
public static Task<APIResponses.GetInvite> GetInvite(string id)
|
||||
=> Http.Get<APIResponses.GetInvite>(Endpoints.Invite(id));
|
||||
public static Task AcceptInvite(string id)
|
||||
=> Http.Post<APIResponses.AcceptInvite>(Endpoints.Invite(id));
|
||||
public static Task DeleteInvite(string id)
|
||||
=> Http.Delete(Endpoints.Invite(id));
|
||||
|
||||
//Chat
|
||||
public static Task<APIResponses.SendMessage> SendMessage(string channelId, string message, string[] mentions, HttpOptions options)
|
||||
public static Task<APIResponses.SendMessage> SendMessage(string channelId, string message, string[] mentions)
|
||||
{
|
||||
var request = new APIRequests.SendMessage { Content = message, Mentions = mentions };
|
||||
return Http.Post<APIResponses.SendMessage>(Endpoints.ChannelMessages(channelId), request, options);
|
||||
return Http.Post<APIResponses.SendMessage>(Endpoints.ChannelMessages(channelId), request);
|
||||
}
|
||||
public static Task<APIResponses.EditMessage> EditMessage(string channelId, string messageId, string message, string[] mentions, HttpOptions options)
|
||||
public static Task<APIResponses.EditMessage> EditMessage(string channelId, string messageId, string message, string[] mentions)
|
||||
{
|
||||
var request = new APIRequests.EditMessage { Content = message, Mentions = mentions };
|
||||
return Http.Patch<APIResponses.EditMessage>(Endpoints.ChannelMessage(channelId, messageId), request, options);
|
||||
return Http.Patch<APIResponses.EditMessage>(Endpoints.ChannelMessage(channelId, messageId), request);
|
||||
}
|
||||
public static Task SendIsTyping(string channelId, HttpOptions options)
|
||||
=> Http.Post(Endpoints.ChannelTyping(channelId), options);
|
||||
public static Task DeleteMessage(string channelId, string msgId, HttpOptions options)
|
||||
=> Http.Delete(Endpoints.ChannelMessage(channelId, msgId), options);
|
||||
public static Task SendIsTyping(string channelId)
|
||||
=> Http.Post(Endpoints.ChannelTyping(channelId));
|
||||
public static Task DeleteMessage(string channelId, string msgId)
|
||||
=> Http.Delete(Endpoints.ChannelMessage(channelId, msgId));
|
||||
|
||||
//Voice
|
||||
public static Task<APIResponses.GetRegions[]> GetVoiceRegions(HttpOptions options)
|
||||
=> Http.Get<APIResponses.GetRegions[]>(Endpoints.VoiceRegions, options);
|
||||
public static Task<APIResponses.GetIce> GetVoiceIce(HttpOptions options)
|
||||
=> Http.Get<APIResponses.GetIce>(Endpoints.VoiceIce, options);
|
||||
public static Task Mute(string serverId, string memberId, HttpOptions options)
|
||||
public static Task<APIResponses.GetRegions[]> GetVoiceRegions()
|
||||
=> Http.Get<APIResponses.GetRegions[]>(Endpoints.VoiceRegions);
|
||||
public static Task<APIResponses.GetIce> GetVoiceIce()
|
||||
=> Http.Get<APIResponses.GetIce>(Endpoints.VoiceIce);
|
||||
public static Task Mute(string serverId, string memberId)
|
||||
{
|
||||
var request = new APIRequests.SetMemberMute { Mute = true };
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId), options);
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId));
|
||||
}
|
||||
public static Task Unmute(string serverId, string memberId, HttpOptions options)
|
||||
public static Task Unmute(string serverId, string memberId)
|
||||
{
|
||||
var request = new APIRequests.SetMemberMute { Mute = false };
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId), options);
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId));
|
||||
}
|
||||
public static Task Deafen(string serverId, string memberId, HttpOptions options)
|
||||
public static Task Deafen(string serverId, string memberId)
|
||||
{
|
||||
var request = new APIRequests.SetMemberDeaf { Deaf = true };
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId), options);
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId));
|
||||
}
|
||||
public static Task Undeafen(string serverId, string memberId, HttpOptions options)
|
||||
public static Task Undeafen(string serverId, string memberId)
|
||||
{
|
||||
var request = new APIRequests.SetMemberDeaf { Deaf = false };
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId), options);
|
||||
return Http.Patch(Endpoints.ServerMember(serverId, memberId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Discord
|
||||
public const int FailedReconnectDelay = 10000; //Time in milliseconds to wait after a failed reconnect attempt
|
||||
|
||||
private DiscordWebSocket _webSocket;
|
||||
private HttpOptions _httpOptions;
|
||||
private bool _isReady;
|
||||
|
||||
public string UserId { get; private set; }
|
||||
@@ -45,8 +44,6 @@ namespace Discord
|
||||
public DiscordClient()
|
||||
{
|
||||
_isStopping = new ManualResetEventSlim(false);
|
||||
string version = typeof(DiscordClient).GetTypeInfo().Assembly.GetName().Version.ToString(2);
|
||||
_httpOptions = new HttpOptions($"Discord.Net/{version} (https://github.com/RogueException/Discord.Net)");
|
||||
|
||||
_servers = new AsyncCache<Server, API.Models.ServerReference>(
|
||||
(key, parentKey) => new Server(key, this),
|
||||
@@ -160,7 +157,7 @@ namespace Discord
|
||||
try
|
||||
{
|
||||
await Task.Delay(ReconnectDelay);
|
||||
await _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, true, _httpOptions);
|
||||
await _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, true);
|
||||
break;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -413,15 +410,26 @@ namespace Discord
|
||||
)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
public User FindChannelUser(Channel channel, string name)
|
||||
=> FindChannelUser(channel.Id, name);
|
||||
public User FindChannelUser(string channelId, string name)
|
||||
public Membership FindMember(string serverId, string name)
|
||||
=> FindMember(GetServer(serverId), name);
|
||||
public Membership FindMember(Server server, string name)
|
||||
{
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
if (name.StartsWith("<@") && name.EndsWith(">"))
|
||||
{
|
||||
var user = GetUser(name.Substring(2, name.Length - 3));
|
||||
if (user == null)
|
||||
return null;
|
||||
return server.GetMembership(user.Id);
|
||||
}
|
||||
|
||||
if (name.StartsWith("@"))
|
||||
name = name.Substring(1);
|
||||
|
||||
return _users
|
||||
.Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase))
|
||||
return server.Members
|
||||
.Where(x => string.Equals(x.User.Name, name, StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
@@ -436,9 +444,11 @@ namespace Discord
|
||||
public Channel GetChannel(string id) => _channels[id];
|
||||
public Channel FindChannel(string name)
|
||||
{
|
||||
if (name.StartsWith("<#") && name.EndsWith(">"))
|
||||
return GetChannel(name.Substring(2, name.Length - 3));
|
||||
|
||||
if (name.StartsWith("#"))
|
||||
name = name.Substring(1);
|
||||
|
||||
return _channels
|
||||
.Where(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase))
|
||||
.FirstOrDefault();
|
||||
@@ -447,9 +457,11 @@ namespace Discord
|
||||
=> FindChannel(server.Id, name);
|
||||
public Channel FindChannel(string serverId, string name)
|
||||
{
|
||||
if (name.StartsWith("<#") && name.EndsWith(">"))
|
||||
return GetChannel(name.Substring(2, name.Length - 3));
|
||||
|
||||
if (name.StartsWith("#"))
|
||||
name = name.Substring(1);
|
||||
|
||||
return _channels
|
||||
.Where(x =>
|
||||
string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase) &&
|
||||
@@ -478,7 +490,7 @@ namespace Discord
|
||||
{
|
||||
try
|
||||
{
|
||||
var msgs = await DiscordAPI.GetMessages(channel.Id, count, _httpOptions);
|
||||
var msgs = await DiscordAPI.GetMessages(channel.Id, count);
|
||||
return msgs.OrderBy(x => x.Timestamp)
|
||||
.Select(x =>
|
||||
{
|
||||
@@ -501,13 +513,13 @@ namespace Discord
|
||||
_isStopping.Reset();
|
||||
|
||||
//Open websocket while we wait for login response
|
||||
Task socketTask = _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, false, _httpOptions);
|
||||
var response = await DiscordAPI.Login(email, password, _httpOptions);
|
||||
_httpOptions.Token = response.Token;
|
||||
Task socketTask = _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, false);
|
||||
var response = await DiscordAPI.Login(email, password);
|
||||
Http.Token = response.Token;
|
||||
|
||||
//Wait for websocket to finish connecting, then send token
|
||||
await socketTask;
|
||||
_webSocket.Login(_httpOptions);
|
||||
_webSocket.Login();
|
||||
|
||||
_isReady = true;
|
||||
}
|
||||
@@ -516,13 +528,13 @@ namespace Discord
|
||||
_isStopping.Reset();
|
||||
|
||||
//Open websocket while we wait for login response
|
||||
Task socketTask = _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, false, _httpOptions);
|
||||
var response = await DiscordAPI.LoginAnonymous(username, _httpOptions);
|
||||
_httpOptions.Token = response.Token;
|
||||
Task socketTask = _webSocket.ConnectAsync(Endpoints.WebSocket_Hub, false);
|
||||
var response = await DiscordAPI.LoginAnonymous(username);
|
||||
Http.Token = response.Token;
|
||||
|
||||
//Wait for websocket to finish connecting, then send token
|
||||
await socketTask;
|
||||
_webSocket.Login(_httpOptions);
|
||||
_webSocket.Login();
|
||||
|
||||
_isReady = true;
|
||||
}
|
||||
@@ -543,7 +555,7 @@ namespace Discord
|
||||
public async Task<Server> CreateServer(string name, string region)
|
||||
{
|
||||
CheckReady();
|
||||
var response = await DiscordAPI.CreateServer(name, region, _httpOptions);
|
||||
var response = await DiscordAPI.CreateServer(name, region);
|
||||
return _servers.Update(response.Id, response);
|
||||
}
|
||||
public Task<Server> LeaveServer(Server server)
|
||||
@@ -553,7 +565,7 @@ namespace Discord
|
||||
CheckReady();
|
||||
try
|
||||
{
|
||||
await DiscordAPI.LeaveServer(serverId, _httpOptions);
|
||||
await DiscordAPI.LeaveServer(serverId);
|
||||
}
|
||||
catch (WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound) {}
|
||||
return _servers.Remove(serverId);
|
||||
@@ -565,7 +577,7 @@ namespace Discord
|
||||
public async Task<Channel> CreateChannel(string serverId, string name, string type)
|
||||
{
|
||||
CheckReady();
|
||||
var response = await DiscordAPI.CreateChannel(serverId, name, type, _httpOptions);
|
||||
var response = await DiscordAPI.CreateChannel(serverId, name, type);
|
||||
return _channels.Update(response.Id, serverId, response);
|
||||
}
|
||||
public Task<Channel> CreatePMChannel(User user)
|
||||
@@ -573,7 +585,7 @@ namespace Discord
|
||||
public async Task<Channel> CreatePMChannel(string recipientId)
|
||||
{
|
||||
CheckReady();
|
||||
var response = await DiscordAPI.CreatePMChannel(UserId, recipientId, _httpOptions);
|
||||
var response = await DiscordAPI.CreatePMChannel(UserId, recipientId);
|
||||
return _channels.Update(response.Id, response);
|
||||
}
|
||||
public Task<Channel> DestroyChannel(Channel channel)
|
||||
@@ -583,7 +595,7 @@ namespace Discord
|
||||
CheckReady();
|
||||
try
|
||||
{
|
||||
var response = await DiscordAPI.DestroyChannel(channelId, _httpOptions);
|
||||
var response = await DiscordAPI.DestroyChannel(channelId);
|
||||
}
|
||||
catch (WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound) { }
|
||||
return _channels.Remove(channelId);
|
||||
@@ -599,7 +611,7 @@ namespace Discord
|
||||
public Task Ban(string serverId, string userId)
|
||||
{
|
||||
CheckReady();
|
||||
return DiscordAPI.Ban(serverId, userId, _httpOptions);
|
||||
return DiscordAPI.Ban(serverId, userId);
|
||||
}
|
||||
public Task Unban(Server server, User user)
|
||||
=> Unban(server.Id, user.Id);
|
||||
@@ -612,7 +624,7 @@ namespace Discord
|
||||
CheckReady();
|
||||
try
|
||||
{
|
||||
await DiscordAPI.Unban(serverId, userId, _httpOptions);
|
||||
await DiscordAPI.Unban(serverId, userId);
|
||||
}
|
||||
catch (WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound) { }
|
||||
}
|
||||
@@ -629,7 +641,7 @@ namespace Discord
|
||||
public async Task<Invite> CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass)
|
||||
{
|
||||
CheckReady();
|
||||
var response = await DiscordAPI.CreateInvite(channelId, maxAge, maxUses, isTemporary, hasXkcdPass, _httpOptions);
|
||||
var response = await DiscordAPI.CreateInvite(channelId, maxAge, maxUses, isTemporary, hasXkcdPass);
|
||||
_channels.Update(response.Channel.Id, response.Server.Id, response.Channel);
|
||||
_servers.Update(response.Server.Id, response.Server);
|
||||
_users.Update(response.Inviter.Id, response.Inviter);
|
||||
@@ -648,7 +660,7 @@ namespace Discord
|
||||
public async Task<Invite> GetInvite(string id)
|
||||
{
|
||||
CheckReady();
|
||||
var response = await DiscordAPI.GetInvite(id, _httpOptions);
|
||||
var response = await DiscordAPI.GetInvite(id);
|
||||
return new Invite(response.Code, response.XkcdPass, this)
|
||||
{
|
||||
ChannelId = response.Channel.Id,
|
||||
@@ -659,14 +671,14 @@ namespace Discord
|
||||
public Task AcceptInvite(Invite invite)
|
||||
{
|
||||
CheckReady();
|
||||
return DiscordAPI.AcceptInvite(invite.Code, _httpOptions);
|
||||
return DiscordAPI.AcceptInvite(invite.Code);
|
||||
}
|
||||
public async Task AcceptInvite(string id)
|
||||
{
|
||||
CheckReady();
|
||||
//Check if this is a human-readable link and get its ID
|
||||
var response = await DiscordAPI.GetInvite(id, _httpOptions);
|
||||
await DiscordAPI.AcceptInvite(response.Code, _httpOptions);
|
||||
var response = await DiscordAPI.GetInvite(id);
|
||||
await DiscordAPI.AcceptInvite(response.Code);
|
||||
}
|
||||
public async Task DeleteInvite(string id)
|
||||
{
|
||||
@@ -674,8 +686,8 @@ namespace Discord
|
||||
try
|
||||
{
|
||||
//Check if this is a human-readable link and get its ID
|
||||
var response = await DiscordAPI.GetInvite(id, _httpOptions);
|
||||
await DiscordAPI.DeleteInvite(response.Code, _httpOptions);
|
||||
var response = await DiscordAPI.GetInvite(id);
|
||||
await DiscordAPI.DeleteInvite(response.Code);
|
||||
}
|
||||
catch (WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound) { }
|
||||
}
|
||||
@@ -693,7 +705,7 @@ namespace Discord
|
||||
|
||||
if (text.Length <= 2000)
|
||||
{
|
||||
var msg = await DiscordAPI.SendMessage(channelId, text, mentions, _httpOptions);
|
||||
var msg = await DiscordAPI.SendMessage(channelId, text, mentions);
|
||||
return new Message[] { _messages.Update(msg.Id, channelId, msg) };
|
||||
}
|
||||
else
|
||||
@@ -703,7 +715,7 @@ namespace Discord
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
int index = i * DiscordAPI.MaxMessageSize;
|
||||
var msg = await DiscordAPI.SendMessage(channelId, text.Substring(index, Math.Min(2000, text.Length - index)), mentions, _httpOptions);
|
||||
var msg = await DiscordAPI.SendMessage(channelId, text.Substring(index, Math.Min(2000, text.Length - index)), mentions);
|
||||
result[i] = _messages.Update(msg.Id, channelId, msg);
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
@@ -727,7 +739,7 @@ namespace Discord
|
||||
if (text.Length > DiscordAPI.MaxMessageSize)
|
||||
text = text.Substring(0, DiscordAPI.MaxMessageSize);
|
||||
|
||||
var msg = await DiscordAPI.EditMessage(channelId, messageId, text, mentions, _httpOptions);
|
||||
var msg = await DiscordAPI.EditMessage(channelId, messageId, text, mentions);
|
||||
_messages.Update(msg.Id, channelId, msg);
|
||||
}
|
||||
|
||||
@@ -737,7 +749,7 @@ namespace Discord
|
||||
{
|
||||
try
|
||||
{
|
||||
await DiscordAPI.DeleteMessage(channelId, msgId, _httpOptions);
|
||||
await DiscordAPI.DeleteMessage(channelId, msgId);
|
||||
return _messages.Remove(msgId);
|
||||
}
|
||||
catch (WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound) { }
|
||||
@@ -755,7 +767,7 @@ namespace Discord
|
||||
public Task Mute(string serverId, string userId)
|
||||
{
|
||||
CheckReady();
|
||||
return DiscordAPI.Mute(serverId, userId, _httpOptions);
|
||||
return DiscordAPI.Mute(serverId, userId);
|
||||
}
|
||||
|
||||
public Task Unmute(Server server, User user)
|
||||
@@ -767,7 +779,7 @@ namespace Discord
|
||||
public Task Unmute(string serverId, string userId)
|
||||
{
|
||||
CheckReady();
|
||||
return DiscordAPI.Unmute(serverId, userId, _httpOptions);
|
||||
return DiscordAPI.Unmute(serverId, userId);
|
||||
}
|
||||
|
||||
public Task Deafen(Server server, User user)
|
||||
@@ -779,7 +791,7 @@ namespace Discord
|
||||
public Task Deafen(string serverId, string userId)
|
||||
{
|
||||
CheckReady();
|
||||
return DiscordAPI.Deafen(serverId, userId, _httpOptions);
|
||||
return DiscordAPI.Deafen(serverId, userId);
|
||||
}
|
||||
|
||||
public Task Undeafen(Server server, User user)
|
||||
@@ -791,7 +803,7 @@ namespace Discord
|
||||
public Task Undeafen(string serverId, string userId)
|
||||
{
|
||||
CheckReady();
|
||||
return DiscordAPI.Undeafen(serverId, userId, _httpOptions);
|
||||
return DiscordAPI.Undeafen(serverId, userId);
|
||||
}
|
||||
|
||||
private void CheckReady()
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Discord
|
||||
private DateTime _lastHeartbeat;
|
||||
private AutoResetEvent _connectWaitOnLogin, _connectWaitOnLogin2;
|
||||
|
||||
public async Task ConnectAsync(string url, bool autoLogin, HttpOptions options)
|
||||
public async Task ConnectAsync(string url, bool autoLogin)
|
||||
{
|
||||
await DisconnectAsync();
|
||||
|
||||
@@ -58,12 +58,12 @@ namespace Discord
|
||||
});
|
||||
|
||||
if (autoLogin)
|
||||
Login(options);
|
||||
Login();
|
||||
}
|
||||
public void Login(HttpOptions options)
|
||||
public void Login()
|
||||
{
|
||||
WebSocketCommands.Login msg = new WebSocketCommands.Login();
|
||||
msg.Payload.Token = options.Token;
|
||||
msg.Payload.Token = Http.Token;
|
||||
msg.Payload.Properties["$os"] = "";
|
||||
msg.Payload.Properties["$browser"] = "";
|
||||
msg.Payload.Properties["$device"] = "Discord.Net";
|
||||
|
||||
@@ -2,23 +2,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Discord.Helpers
|
||||
{
|
||||
internal class HttpOptions
|
||||
{
|
||||
public readonly string UserAgent;
|
||||
public string Token;
|
||||
|
||||
public HttpOptions(string userAgent)
|
||||
{
|
||||
UserAgent = userAgent;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Http
|
||||
{
|
||||
#if DEBUG
|
||||
@@ -26,151 +16,120 @@ namespace Discord.Helpers
|
||||
#else
|
||||
private const bool _isDebug = false;
|
||||
#endif
|
||||
|
||||
internal static Task<ResponseT> Get<ResponseT>(string path, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("GET", path, null, options);
|
||||
internal static Task<string> Get(string path, HttpOptions options)
|
||||
=> Send("GET", path, null, options);
|
||||
|
||||
internal static Task<ResponseT> Post<ResponseT>(string path, object data, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("POST", path, data, options);
|
||||
internal static Task<string> Post(string path, object data, HttpOptions options)
|
||||
=> Send("POST", path, data, options);
|
||||
internal static Task<ResponseT> Post<ResponseT>(string path, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("POST", path, null, options);
|
||||
internal static Task<string> Post(string path, HttpOptions options)
|
||||
=> Send("POST", path, null, options);
|
||||
|
||||
internal static Task<ResponseT> Put<ResponseT>(string path, object data, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("PUT", path, data, options);
|
||||
internal static Task<string> Put(string path, object data, HttpOptions options)
|
||||
=> Send("PUT", path, data, options);
|
||||
internal static Task<ResponseT> Put<ResponseT>(string path, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("PUT", path, null, options);
|
||||
internal static Task<string> Put(string path, HttpOptions options)
|
||||
=> Send("PUT", path, null, options);
|
||||
private static readonly HttpClient _client;
|
||||
private static readonly HttpMethod _patch = new HttpMethod("PATCH"); //Not sure why this isn't a default...
|
||||
|
||||
internal static Task<ResponseT> Patch<ResponseT>(string path, object data, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("PATCH", path, data, options);
|
||||
internal static Task<string> Patch(string path, object data, HttpOptions options)
|
||||
=> Send("PATCH", path, data, options);
|
||||
internal static Task<ResponseT> Patch<ResponseT>(string path, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("PATCH", path, null, options);
|
||||
internal static Task<string> Patch(string path, HttpOptions options)
|
||||
=> Send("PATCH", path, null, options);
|
||||
static Http()
|
||||
{
|
||||
_client = new HttpClient();
|
||||
_client.DefaultRequestHeaders.Add("Accept", "*/*");
|
||||
_client.DefaultRequestHeaders.Add("Accept-language", "en-US;q=0.8");
|
||||
|
||||
internal static Task<ResponseT> Delete<ResponseT>(string path, object data, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("DELETE", path, data, options);
|
||||
internal static Task<string> Delete(string path, object data, HttpOptions options)
|
||||
=> Send("DELETE", path, data, options);
|
||||
internal static Task<ResponseT> Delete<ResponseT>(string path, HttpOptions options)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>("DELETE", path, null, options);
|
||||
internal static Task<string> Delete(string path, HttpOptions options)
|
||||
=> Send("DELETE", path, null, options);
|
||||
string version = typeof(Http).GetTypeInfo().Assembly.GetName().Version.ToString(2);
|
||||
_client.DefaultRequestHeaders.Add("User-agent", $"Discord.Net/{version} (https://github.com/RogueException/Discord.Net)");
|
||||
}
|
||||
|
||||
internal static async Task<ResponseT> Send<ResponseT>(string method, string path, object data, HttpOptions options)
|
||||
private static string _token;
|
||||
public static string Token
|
||||
{
|
||||
get { return _token; }
|
||||
set
|
||||
{
|
||||
_token = value;
|
||||
_client.DefaultRequestHeaders.Add("Authorization", _token);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Task<ResponseT> Get<ResponseT>(string path)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Get, path, null);
|
||||
internal static Task<string> Get(string path)
|
||||
=> Send(HttpMethod.Get, path, null);
|
||||
|
||||
internal static Task<ResponseT> Post<ResponseT>(string path, object data)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Post, path, data);
|
||||
internal static Task<string> Post(string path, object data)
|
||||
=> Send(HttpMethod.Post, path, data);
|
||||
internal static Task<ResponseT> Post<ResponseT>(string path)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Post, path, null);
|
||||
internal static Task<string> Post(string path)
|
||||
=> Send(HttpMethod.Post, path, null);
|
||||
|
||||
internal static Task<ResponseT> Put<ResponseT>(string path, object data)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Put, path, data);
|
||||
internal static Task<string> Put(string path, object data)
|
||||
=> Send(HttpMethod.Put, path, data);
|
||||
internal static Task<ResponseT> Put<ResponseT>(string path)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Put, path, null);
|
||||
internal static Task<string> Put(string path)
|
||||
=> Send(HttpMethod.Put, path, null);
|
||||
|
||||
internal static Task<ResponseT> Patch<ResponseT>(string path, object data)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(_patch, path, data);
|
||||
internal static Task<string> Patch(string path, object data)
|
||||
=> Send(_patch, path, data);
|
||||
internal static Task<ResponseT> Patch<ResponseT>(string path)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(_patch, path, null);
|
||||
internal static Task<string> Patch(string path)
|
||||
=> Send(_patch, path, null);
|
||||
|
||||
internal static Task<ResponseT> Delete<ResponseT>(string path, object data)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Delete, path, data);
|
||||
internal static Task<string> Delete(string path, object data)
|
||||
=> Send(HttpMethod.Delete, path, data);
|
||||
internal static Task<ResponseT> Delete<ResponseT>(string path)
|
||||
where ResponseT : class
|
||||
=> Send<ResponseT>(HttpMethod.Delete, path, null);
|
||||
internal static Task<string> Delete(string path)
|
||||
=> Send(HttpMethod.Delete, path, null);
|
||||
|
||||
internal static async Task<ResponseT> Send<ResponseT>(HttpMethod method, string path, object data)
|
||||
where ResponseT : class
|
||||
{
|
||||
string requestJson = data != null ? JsonConvert.SerializeObject(data) : null;
|
||||
string responseJson = await SendRequest(method, path, requestJson, options, true);
|
||||
string responseJson = await SendRequest(method, path, requestJson, true);
|
||||
var response = JsonConvert.DeserializeObject<ResponseT>(responseJson);
|
||||
#if DEBUG
|
||||
CheckResponse(responseJson, response);
|
||||
#endif
|
||||
return response;
|
||||
}
|
||||
internal static async Task<string> Send(string method, string path, object data, HttpOptions options)
|
||||
internal static async Task<string> Send(HttpMethod method, string path, object data)
|
||||
{
|
||||
string requestJson = data != null ? JsonConvert.SerializeObject(data) : null;
|
||||
string responseJson = await SendRequest(method, path, requestJson, options, _isDebug);
|
||||
string responseJson = await SendRequest(method, path, requestJson, _isDebug);
|
||||
#if DEBUG
|
||||
CheckEmptyResponse(responseJson);
|
||||
#endif
|
||||
return responseJson;
|
||||
}
|
||||
|
||||
private static async Task<string> SendRequest(string method, string path, string data, HttpOptions options, bool hasResponse)
|
||||
private static async Task<string> SendRequest(HttpMethod method, string path, string data, bool hasResponse)
|
||||
{
|
||||
//Create Request
|
||||
HttpWebRequest request = WebRequest.CreateHttp(path);
|
||||
request.Accept = "*/*";
|
||||
request.Method = method;
|
||||
request.Proxy = null;
|
||||
request.Headers[HttpRequestHeader.AcceptLanguage] = "en-US;q=0.8";
|
||||
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
|
||||
request.Headers[HttpRequestHeader.UserAgent] = options.UserAgent;
|
||||
request.Headers[HttpRequestHeader.Authorization] = options.Token;
|
||||
//request.UserAgent = options.UserAgent;
|
||||
HttpRequestMessage msg = new HttpRequestMessage(method, path);
|
||||
|
||||
//Add Payload
|
||||
if (data != null)
|
||||
{
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(data);
|
||||
using (var payload = await request.GetRequestStreamAsync())
|
||||
payload.Write(buffer, 0, buffer.Length);
|
||||
request.ContentType = "application/json";
|
||||
}
|
||||
msg.Content = new StringContent(data, Encoding.UTF8, "application/json");
|
||||
|
||||
//Get Response
|
||||
using (var response = (HttpWebResponse)(await request.GetResponseAsync()))
|
||||
if (!hasResponse)
|
||||
{
|
||||
if (hasResponse)
|
||||
{
|
||||
using (var stream = response.GetResponseStream())
|
||||
using (var reader = new BinaryReader(stream))
|
||||
using (var largeBuffer = new MemoryStream())
|
||||
{
|
||||
//Read the response in small chunks and add them to a larger buffer.
|
||||
//ContentLength isn't always provided, so this is safer.
|
||||
int bytesRead = 0;
|
||||
byte[] smallBuffer = new byte[4096];
|
||||
while ((bytesRead = reader.Read(smallBuffer, 0, smallBuffer.Length)) > 0)
|
||||
largeBuffer.Write(smallBuffer, 0, bytesRead);
|
||||
|
||||
//Do we need to decompress?
|
||||
string encoding = response.Headers[HttpResponseHeader.ContentEncoding];
|
||||
if (!string.IsNullOrEmpty(encoding))
|
||||
{
|
||||
largeBuffer.Position = 0;
|
||||
using (var decoder = GetDecoder(encoding, largeBuffer))
|
||||
using (var decodedStream = new MemoryStream())
|
||||
{
|
||||
decoder.CopyTo(decodedStream);
|
||||
#if !DOTNET
|
||||
return Encoding.UTF8.GetString(decodedStream.GetBuffer(), 0, (int)decodedStream.Length);
|
||||
#else
|
||||
ArraySegment<byte> buffer;
|
||||
if (!decodedStream.TryGetBuffer(out buffer))
|
||||
throw new InvalidOperationException("Failed to get response buffer.");
|
||||
return Encoding.UTF8.GetString(buffer.Array, buffer.Offset, (int)decodedStream.Length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !DOTNET
|
||||
return Encoding.UTF8.GetString(largeBuffer.GetBuffer(), 0, (int)largeBuffer.Length);
|
||||
#else
|
||||
ArraySegment<byte> buffer;
|
||||
if (!largeBuffer.TryGetBuffer(out buffer))
|
||||
throw new InvalidOperationException("Failed to get response buffer.");
|
||||
return Encoding.UTF8.GetString(buffer.Array, buffer.Offset, (int)largeBuffer.Length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return null;
|
||||
await _client.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var response = await _client.SendAsync(msg, HttpCompletionOption.ResponseContentRead);
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream GetDecoder(string contentEncoding, MemoryStream encodedStream)
|
||||
|
||||
@@ -24,5 +24,8 @@
|
||||
"Newtonsoft.Json": "7.0.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"Microsoft.Net.Http": "2.2.22"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user