diff --git a/src/Discord.Net/API/Endpoints.cs b/src/Discord.Net/API/Endpoints.cs index 0cb3848f8..9efc906e2 100644 --- a/src/Discord.Net/API/Endpoints.cs +++ b/src/Discord.Net/API/Endpoints.cs @@ -45,7 +45,6 @@ public const string Voice = "voice"; public const string VoiceRegions = "voice/regions"; - //public const string VoiceIce = "voice/ice"; public const string StatusActiveMaintenance = "scheduled-maintenances/active.json"; public const string StatusUpcomingMaintenance = "scheduled-maintenances/upcoming.json"; diff --git a/src/Discord.Net/DiscordAPIClient.cs b/src/Discord.Net/DiscordAPIClient.cs index 942409fe4..955ba1ebb 100644 --- a/src/Discord.Net/DiscordAPIClient.cs +++ b/src/Discord.Net/DiscordAPIClient.cs @@ -2,6 +2,7 @@ using Discord.Net.Rest; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -198,12 +199,13 @@ namespace Discord var request = new SendMessageRequest { Content = message, Mentions = mentionedUserIds ?? new long[0], Nonce = nonce, IsTTS = isTTS ? true : false }; return _rest.Post(Endpoints.ChannelMessages(channelId), request); } - public Task SendFile(long channelId, string filePath) + public Task SendFile(long channelId, string filename, Stream stream) { if (channelId <= 0) throw new ArgumentOutOfRangeException(nameof(channelId)); - if (filePath == null) throw new ArgumentNullException(nameof(filePath)); + if (filename == null) throw new ArgumentNullException(nameof(filename)); + if (stream == null) throw new ArgumentNullException(nameof(stream)); - return _rest.PostFile(Endpoints.ChannelMessages(channelId), filePath); + return _rest.PostFile(Endpoints.ChannelMessages(channelId), filename, stream); } public Task DeleteMessage(long messageId, long channelId) { @@ -301,38 +303,39 @@ namespace Discord return _rest.Delete(Endpoints.Server(serverId)); } - public Task EditServer(long serverId, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null) + public Task EditServer(long serverId, string name = null, string region = null, Stream icon = null, ImageType iconType = ImageType.Png) { if (serverId <= 0) throw new ArgumentOutOfRangeException(nameof(serverId)); - var request = new EditServerRequest { Name = name, Region = region, Icon = Base64Picture(iconType, icon) }; + var request = new EditServerRequest { Name = name, Region = region, Icon = Base64Picture(icon, iconType) }; return _rest.Patch(Endpoints.Server(serverId), request); } //User - public Task EditUser(string currentPassword = "", + public Task EditProfile(string currentPassword = "", string username = null, string email = null, string password = null, - ImageType avatarType = ImageType.Png, byte[] avatar = null) + Stream avatar = null, ImageType avatarType = ImageType.Png) { if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword)); - var request = new EditUserRequest { CurrentPassword = currentPassword, Username = username, Email = email, Password = password, Avatar = Base64Picture(avatarType, avatar) }; + var request = new EditUserRequest { CurrentPassword = currentPassword, Username = username, Email = email, Password = password, Avatar = Base64Picture(avatar, avatarType) }; return _rest.Patch(Endpoints.UserMe, request); } //Voice public Task GetVoiceRegions() => _rest.Get(Endpoints.VoiceRegions); - /*public Task GetVoiceIce() - => _rest.Get(Endpoints.VoiceIce);*/ - private string Base64Picture(ImageType type, byte[] data) + private string Base64Picture(Stream stream, ImageType type) { if (type == ImageType.None) return ""; - else if (data != null) + else if (stream != null) { - string base64 = Convert.ToBase64String(data); + byte[] bytes = new byte[stream.Length - stream.Position]; + stream.Read(bytes, 0, bytes.Length); + + string base64 = Convert.ToBase64String(bytes); string imageType = type == ImageType.Jpeg ? "image/jpeg;base64" : "image/png;base64"; return $"data:{imageType},{base64}"; } diff --git a/src/Discord.Net/DiscordClient.Messages.cs b/src/Discord.Net/DiscordClient.Messages.cs index f8fa09eb8..63c998a36 100644 --- a/src/Discord.Net/DiscordClient.Messages.cs +++ b/src/Discord.Net/DiscordClient.Messages.cs @@ -170,8 +170,18 @@ namespace Discord if (channel == null) throw new ArgumentNullException(nameof(channel)); if (filePath == null) throw new ArgumentNullException(nameof(filePath)); CheckReady(); + + return _api.SendFile(channel.Id, Path.GetFileName(filePath), File.OpenRead(filePath)); + } + /// Sends a file to the provided channel. + public Task SendFile(Channel channel, string filename, Stream stream) + { + if (channel == null) throw new ArgumentNullException(nameof(channel)); + if (filename == null) throw new ArgumentNullException(nameof(filename)); + if (stream == null) throw new ArgumentNullException(nameof(stream)); + CheckReady(); - return _api.SendFile(channel.Id, filePath); + return _api.SendFile(channel.Id, filename, stream); } /// Edits the provided message, changing only non-null attributes. diff --git a/src/Discord.Net/DiscordClient.Servers.cs b/src/Discord.Net/DiscordClient.Servers.cs index af81ab07b..69bc5d488 100644 --- a/src/Discord.Net/DiscordClient.Servers.cs +++ b/src/Discord.Net/DiscordClient.Servers.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -93,12 +94,12 @@ namespace Discord } /// Edits the provided server, changing only non-null attributes. - public async Task EditServer(Server server, string name = null, string region = null, ImageType iconType = ImageType.Png, byte[] icon = null) + public async Task EditServer(Server server, string name = null, string region = null, Stream icon = null, ImageType iconType = ImageType.Png) { if (server == null) throw new ArgumentNullException(nameof(server)); CheckReady(); - var response = await _api.EditServer(server.Id, name: name ?? server.Name, region: region, iconType: iconType, icon: icon).ConfigureAwait(false); + var response = await _api.EditServer(server.Id, name: name ?? server.Name, region: region, icon: icon, iconType: iconType).ConfigureAwait(false); server.Update(response); } diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index ba379acc8..78c961f16 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Threading.Tasks; @@ -282,14 +283,14 @@ namespace Discord public Task EditProfile(string currentPassword = "", string username = null, string email = null, string password = null, - ImageType avatarType = ImageType.Png, byte[] avatar = null) + Stream avatar = null, ImageType avatarType = ImageType.Png) { if (currentPassword == null) throw new ArgumentNullException(nameof(currentPassword)); CheckReady(); - return _api.EditUser(currentPassword: currentPassword, + return _api.EditProfile(currentPassword: currentPassword, username: username ?? _privateUser?.Name, email: email ?? _privateUser?.Global.Email, password: password, - avatarType: avatarType, avatar: avatar); + avatar: avatar, avatarType: avatarType); } public Task SetStatus(UserStatus status) diff --git a/src/Discord.Net/Net/Rest/IRestEngine.cs b/src/Discord.Net/Net/Rest/IRestEngine.cs index c72863de7..faba37086 100644 --- a/src/Discord.Net/Net/Rest/IRestEngine.cs +++ b/src/Discord.Net/Net/Rest/IRestEngine.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.IO; +using System.Threading; using System.Threading.Tasks; namespace Discord.Net.Rest @@ -7,6 +8,6 @@ namespace Discord.Net.Rest { void SetToken(string token); Task Send(string method, string path, string json, CancellationToken cancelToken); - Task SendFile(string method, string path, string filePath, CancellationToken cancelToken); + Task SendFile(string method, string path, string filename, Stream stream, CancellationToken cancelToken); } } diff --git a/src/Discord.Net/Net/Rest/RestClient.cs b/src/Discord.Net/Net/Rest/RestClient.cs index cf33c6451..68b220241 100644 --- a/src/Discord.Net/Net/Rest/RestClient.cs +++ b/src/Discord.Net/Net/Rest/RestClient.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using System; using System.Diagnostics; +using System.IO; using System.Threading; using System.Threading.Tasks; @@ -65,15 +66,15 @@ namespace Discord.Net.Rest internal Task Put(string path) => Send("PUT", path); - internal Task PostFile(string path, string filePath) where ResponseT : class - => SendFile("POST", path, filePath); - internal Task PostFile(string path, string filePath) - => SendFile("POST", path, filePath); + internal Task PostFile(string path, string filename, Stream stream) where ResponseT : class + => SendFile("POST", path, filename, stream); + internal Task PostFile(string path, string filename, Stream stream) + => SendFile("POST", path, filename, stream); - internal Task PutFile(string path, string filePath) where ResponseT : class - => SendFile("PUT", path, filePath); - internal Task PutFile(string path, string filePath) - => SendFile("PUT", path, filePath); + internal Task PutFile(string path, string filename, Stream stream) where ResponseT : class + => SendFile("PUT", path, filename, stream); + internal Task PutFile(string path, string filename, Stream stream) + => SendFile("PUT", path, filename, stream); private async Task Send(string method, string path, object content = null) where ResponseT : class @@ -117,22 +118,22 @@ namespace Discord.Net.Rest return responseJson; } - private async Task SendFile(string method, string path, string filePath) + private async Task SendFile(string method, string path, string filename, Stream stream) where ResponseT : class { - string responseJson = await SendFile(method, path, filePath, true).ConfigureAwait(false); + string responseJson = await SendFile(method, path, filename, stream, true).ConfigureAwait(false); return DeserializeResponse(responseJson); } - private Task SendFile(string method, string path, string filePath) - => SendFile(method, path, filePath, false); - private async Task SendFile(string method, string path, string filePath, bool hasResponse) + private Task SendFile(string method, string path, string filename, Stream stream) + => SendFile(method, path, filename, stream, false); + private async Task SendFile(string method, string path, string filename, Stream stream, bool hasResponse) { Stopwatch stopwatch = null; if (_config.LogLevel >= LogMessageSeverity.Verbose) stopwatch = Stopwatch.StartNew(); - string responseJson = await _engine.SendFile(method, path, filePath, _cancelToken).ConfigureAwait(false); + string responseJson = await _engine.SendFile(method, path, filename, stream, _cancelToken).ConfigureAwait(false); #if TEST_RESPONSES if (!hasResponse && !string.IsNullOrEmpty(responseJson)) @@ -143,7 +144,7 @@ namespace Discord.Net.Rest { stopwatch.Stop(); if (_config.LogLevel >= LogMessageSeverity.Debug) - RaiseOnRequest(method, path, filePath, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond); + RaiseOnRequest(method, path, filename, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond); else RaiseOnRequest(method, path, null, stopwatch.ElapsedTicks / (double)TimeSpan.TicksPerMillisecond); } diff --git a/src/Discord.Net/Net/Rest/SharpRestEngine.cs b/src/Discord.Net/Net/Rest/SharpRestEngine.cs index 2dfc0780d..4300e68e8 100644 --- a/src/Discord.Net/Net/Rest/SharpRestEngine.cs +++ b/src/Discord.Net/Net/Rest/SharpRestEngine.cs @@ -2,6 +2,7 @@ using Discord.API; using RestSharp; using System; +using System.IO; using System.Net; using System.Threading; using System.Threading.Tasks; @@ -44,10 +45,10 @@ namespace Discord.Net.Rest request.AddParameter("application/json", json, ParameterType.RequestBody); return Send(request, cancelToken); } - public Task SendFile(string method, string path, string filePath, CancellationToken cancelToken) + public Task SendFile(string method, string path, string filename, Stream stream, CancellationToken cancelToken) { var request = new RestRequest(path, Method.POST); - request.AddFile("file", filePath); + request.AddFile("file", x => stream.CopyTo(x), filename); return Send(request, cancelToken); } private async Task Send(RestRequest request, CancellationToken cancelToken) diff --git a/src/Discord.Net/project.json b/src/Discord.Net/project.json index 5ec5a8a8d..b91eb58e2 100644 --- a/src/Discord.Net/project.json +++ b/src/Discord.Net/project.json @@ -45,6 +45,7 @@ "System.Collections": "4.0.11-beta-23516", "System.Collections.Concurrent": "4.0.11-beta-23516", "System.Dynamic.Runtime": "4.0.11-beta-23516", + "System.IO.FileSystem": "4.0.1-beta-23516", "System.IO.Compression": "4.1.0-beta-23516", "System.Linq": "4.0.1-beta-23516", "System.Net.NameResolution": "4.0.0-beta-23516",