From f2df627e41e868bd3b9926394b08269f62302892 Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 18 Jul 2016 16:28:13 -0300 Subject: [PATCH] Fixed file uploading, Cleaned up DiscordAPIClient helper methods --- src/Discord.Net/API/DiscordAPIClient.cs | 115 ++++++++---------- src/Discord.Net/API/Rest/UploadFileParams.cs | 15 ++- .../Entities/Channels/DMChannel.cs | 8 +- .../Entities/Channels/GroupChannel.cs | 8 +- .../Entities/Channels/TextChannel.cs | 8 +- src/Discord.Net/Net/Rest/DefaultRestClient.cs | 2 +- 6 files changed, 78 insertions(+), 78 deletions(-) diff --git a/src/Discord.Net/API/DiscordAPIClient.cs b/src/Discord.Net/API/DiscordAPIClient.cs index 5f5486780..15dc0d7a5 100644 --- a/src/Discord.Net/API/DiscordAPIClient.cs +++ b/src/Discord.Net/API/DiscordAPIClient.cs @@ -250,64 +250,58 @@ namespace Discord.API ConnectionState = ConnectionState.Disconnected; } - //Core + //REST public Task SendAsync(string method, string endpoint, GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) - => SendInternalAsync(method, endpoint, null, true, bucket, options); + => SendInternalAsync(method, endpoint, null, true, BucketGroup.Global, (int)bucket, 0, options); public Task SendAsync(string method, string endpoint, object payload, GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) - => SendInternalAsync(method, endpoint, payload, true, bucket, options); - public Task SendAsync(string method, string endpoint, Stream file, IReadOnlyDictionary multipartArgs, - GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) - => SendInternalAsync(method, endpoint, multipartArgs, true, bucket, options); + => SendInternalAsync(method, endpoint, payload, true, BucketGroup.Global, (int)bucket, 0, options); public async Task SendAsync(string method, string endpoint, - GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) - where TResponse : class - => DeserializeJson(await SendInternalAsync(method, endpoint, null, false, bucket, options).ConfigureAwait(false)); + GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) where TResponse : class + => DeserializeJson(await SendInternalAsync(method, endpoint, null, false, BucketGroup.Global, (int)bucket, 0, options).ConfigureAwait(false)); public async Task SendAsync(string method, string endpoint, object payload, GlobalBucket bucket = - GlobalBucket.GeneralRest, RequestOptions options = null) - where TResponse : class - => DeserializeJson(await SendInternalAsync(method, endpoint, payload, false, bucket, options).ConfigureAwait(false)); - public async Task SendAsync(string method, string endpoint, Stream file, IReadOnlyDictionary multipartArgs, - GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) - where TResponse : class - => DeserializeJson(await SendInternalAsync(method, endpoint, multipartArgs, false, bucket, options).ConfigureAwait(false)); - + GlobalBucket.GeneralRest, RequestOptions options = null) where TResponse : class + => DeserializeJson(await SendInternalAsync(method, endpoint, payload, false, BucketGroup.Global, (int)bucket, 0, options).ConfigureAwait(false)); + public Task SendAsync(string method, string endpoint, GuildBucket bucket, ulong guildId, RequestOptions options = null) - => SendInternalAsync(method, endpoint, null, true, bucket, guildId, options); + => SendInternalAsync(method, endpoint, null, true, BucketGroup.Guild, (int)bucket, guildId, options); public Task SendAsync(string method, string endpoint, object payload, GuildBucket bucket, ulong guildId, RequestOptions options = null) - => SendInternalAsync(method, endpoint, payload, true, bucket, guildId, options); - public Task SendAsync(string method, string endpoint, Stream file, IReadOnlyDictionary multipartArgs, - GuildBucket bucket, ulong guildId, RequestOptions options = null) - => SendInternalAsync(method, endpoint, multipartArgs, true, bucket, guildId, options); + => SendInternalAsync(method, endpoint, payload, true, BucketGroup.Guild, (int)bucket, guildId, options); public async Task SendAsync(string method, string endpoint, - GuildBucket bucket, ulong guildId, RequestOptions options = null) - where TResponse : class - => DeserializeJson(await SendInternalAsync(method, endpoint, null, false, bucket, guildId, options).ConfigureAwait(false)); + GuildBucket bucket, ulong guildId, RequestOptions options = null) where TResponse : class + => DeserializeJson(await SendInternalAsync(method, endpoint, null, false, BucketGroup.Guild, (int)bucket, guildId, options).ConfigureAwait(false)); public async Task SendAsync(string method, string endpoint, object payload, + GuildBucket bucket, ulong guildId, RequestOptions options = null) where TResponse : class + => DeserializeJson(await SendInternalAsync(method, endpoint, payload, false, BucketGroup.Guild, (int)bucket, guildId, options).ConfigureAwait(false)); + + //REST - Multipart + public Task SendMultipartAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, + GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) + => SendMultipartInternalAsync(method, endpoint, multipartArgs, true, BucketGroup.Global, (int)bucket, 0, options); + public async Task SendMultipartAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, + GlobalBucket bucket = GlobalBucket.GeneralRest, RequestOptions options = null) where TResponse : class + => DeserializeJson(await SendMultipartInternalAsync(method, endpoint, multipartArgs, false, BucketGroup.Global, (int)bucket, 0, options).ConfigureAwait(false)); + + public Task SendMultipartAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, GuildBucket bucket, ulong guildId, RequestOptions options = null) - where TResponse : class - => DeserializeJson(await SendInternalAsync(method, endpoint, payload, false, bucket, guildId, options).ConfigureAwait(false)); - public async Task SendAsync(string method, string endpoint, Stream file, IReadOnlyDictionary multipartArgs, + => SendMultipartInternalAsync(method, endpoint, multipartArgs, true, BucketGroup.Guild, (int)bucket, guildId, options); + public async Task SendMultipartAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, + GuildBucket bucket, ulong guildId, RequestOptions options = null) where TResponse : class + => DeserializeJson(await SendMultipartInternalAsync(method, endpoint, multipartArgs, false, BucketGroup.Guild, (int)bucket, guildId, options).ConfigureAwait(false)); + + //Gateway + public Task SendGatewayAsync(GatewayOpCode opCode, object payload, + GlobalBucket bucket = GlobalBucket.GeneralGateway, RequestOptions options = null) + => SendGatewayInternalAsync(opCode, payload, BucketGroup.Global, (int)bucket, 0, options); + + public Task SendGatewayAsync(GatewayOpCode opCode, object payload, GuildBucket bucket, ulong guildId, RequestOptions options = null) - where TResponse : class - => DeserializeJson(await SendInternalAsync(method, endpoint, multipartArgs, false, bucket, guildId, options).ConfigureAwait(false)); - - private Task SendInternalAsync(string method, string endpoint, object payload, bool headerOnly, - GlobalBucket bucket, RequestOptions options) - => SendInternalAsync(method, endpoint, payload, headerOnly, BucketGroup.Global, (int)bucket, 0, options); - private Task SendInternalAsync(string method, string endpoint, object payload, bool headerOnly, - GuildBucket bucket, ulong guildId, RequestOptions options) - => SendInternalAsync(method, endpoint, payload, headerOnly, BucketGroup.Guild, (int)bucket, guildId, options); - private Task SendInternalAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, bool headerOnly, - GlobalBucket bucket, RequestOptions options) - => SendInternalAsync(method, endpoint, multipartArgs, headerOnly, BucketGroup.Global, (int)bucket, 0, options); - private Task SendInternalAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, bool headerOnly, - GuildBucket bucket, ulong guildId, RequestOptions options) - => SendInternalAsync(method, endpoint, multipartArgs, headerOnly, BucketGroup.Guild, (int)bucket, guildId, options); + => SendGatewayInternalAsync(opCode, payload, BucketGroup.Guild, (int)bucket, guildId, options); + //Core private async Task SendInternalAsync(string method, string endpoint, object payload, bool headerOnly, BucketGroup group, int bucketId, ulong guildId, RequestOptions options = null) { @@ -323,7 +317,7 @@ namespace Discord.API return responseStream; } - private async Task SendInternalAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, bool headerOnly, + private async Task SendMultipartInternalAsync(string method, string endpoint, IReadOnlyDictionary multipartArgs, bool headerOnly, BucketGroup group, int bucketId, ulong guildId, RequestOptions options = null) { var stopwatch = Stopwatch.StartNew(); @@ -336,14 +330,7 @@ namespace Discord.API return responseStream; } - - public Task SendGatewayAsync(GatewayOpCode opCode, object payload, - GlobalBucket bucket = GlobalBucket.GeneralGateway, RequestOptions options = null) - => SendGatewayAsync(opCode, payload, BucketGroup.Global, (int)bucket, 0, options); - public Task SendGatewayAsync(GatewayOpCode opCode, object payload, - GuildBucket bucket, ulong guildId, RequestOptions options = null) - => SendGatewayAsync(opCode, payload, BucketGroup.Guild, (int)bucket, guildId, options); - private async Task SendGatewayAsync(GatewayOpCode opCode, object payload, + private async Task SendGatewayInternalAsync(GatewayOpCode opCode, object payload, BucketGroup group, int bucketId, ulong guildId, RequestOptions options) { //TODO: Add ETF @@ -1016,31 +1003,35 @@ namespace Discord.API else return await SendAsync("POST", $"channels/{channelId}/messages", args, GlobalBucket.DirectMessage, options: options).ConfigureAwait(false); } - public Task UploadFileAsync(ulong guildId, ulong channelId, Stream file, UploadFileParams args, RequestOptions options = null) + public Task UploadFileAsync(ulong guildId, ulong channelId, UploadFileParams args, RequestOptions options = null) { Preconditions.NotEqual(guildId, 0, nameof(guildId)); - return UploadFileInternalAsync(guildId, channelId, file, args); + return UploadFileInternalAsync(guildId, channelId, args); } - public Task UploadDMFileAsync(ulong channelId, Stream file, UploadFileParams args, RequestOptions options = null) + public Task UploadDMFileAsync(ulong channelId, UploadFileParams args, RequestOptions options = null) { - return UploadFileInternalAsync(0, channelId, file, args); + return UploadFileInternalAsync(0, channelId, args); } - private async Task UploadFileInternalAsync(ulong guildId, ulong channelId, Stream file, UploadFileParams args, RequestOptions options = null) + private async Task UploadFileInternalAsync(ulong guildId, ulong channelId, UploadFileParams args, RequestOptions options = null) { Preconditions.NotNull(args, nameof(args)); Preconditions.NotEqual(channelId, 0, nameof(channelId)); - if (args.Content.IsSpecified) + + if (args.Content.GetValueOrDefault(null) == null) + args.Content = ""; + else if (args.Content.IsSpecified) { - Preconditions.NotNullOrEmpty(args.Content, nameof(args.Content)); - if (args.Content.Value.Length > DiscordConfig.MaxMessageSize) + if (args.Content.Value == null) + args.Content = ""; + if (args.Content.Value?.Length > DiscordConfig.MaxMessageSize) throw new ArgumentOutOfRangeException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content)); } if (guildId != 0) - return await SendAsync("POST", $"channels/{channelId}/messages", file, args.ToDictionary(), GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false); + return await SendMultipartAsync("POST", $"channels/{channelId}/messages", args.ToDictionary(), GuildBucket.SendEditMessage, guildId, options: options).ConfigureAwait(false); else - return await SendAsync("POST", $"channels/{channelId}/messages", file, args.ToDictionary(), GlobalBucket.DirectMessage, options: options).ConfigureAwait(false); + return await SendMultipartAsync("POST", $"channels/{channelId}/messages", args.ToDictionary(), GlobalBucket.DirectMessage, options: options).ConfigureAwait(false); } public Task DeleteMessageAsync(ulong guildId, ulong channelId, ulong messageId, RequestOptions options = null) { diff --git a/src/Discord.Net/API/Rest/UploadFileParams.cs b/src/Discord.Net/API/Rest/UploadFileParams.cs index ad3c7bf3f..c949a6990 100644 --- a/src/Discord.Net/API/Rest/UploadFileParams.cs +++ b/src/Discord.Net/API/Rest/UploadFileParams.cs @@ -1,18 +1,27 @@ -using System.Collections.Generic; +using Discord.Net.Rest; +using System.Collections.Generic; +using System.IO; namespace Discord.API.Rest { public class UploadFileParams { + public Stream File { get; set; } public string Filename { get; set; } = "unknown.dat"; public Optional Content { get; set; } public Optional Nonce { get; set; } public Optional IsTTS { get; set; } - public IReadOnlyDictionary ToDictionary() + public UploadFileParams(Stream file) { - var d = new Dictionary(); + File = file; + } + + public IReadOnlyDictionary ToDictionary() + { + var d = new Dictionary(); + d["file"] = new MultipartFile(File, Filename); if (Content.IsSpecified) d["content"] = Content.Value; if (IsTTS.IsSpecified) diff --git a/src/Discord.Net/Entities/Channels/DMChannel.cs b/src/Discord.Net/Entities/Channels/DMChannel.cs index 858adfa7f..8f79ddccd 100644 --- a/src/Discord.Net/Entities/Channels/DMChannel.cs +++ b/src/Discord.Net/Entities/Channels/DMChannel.cs @@ -73,15 +73,15 @@ namespace Discord string filename = Path.GetFileName(filePath); using (var file = File.OpenRead(filePath)) { - var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; - var model = await Discord.ApiClient.UploadDMFileAsync(Id, file, args).ConfigureAwait(false); + var args = new UploadFileParams(file) { Filename = filename, Content = text, IsTTS = isTTS }; + var model = await Discord.ApiClient.UploadDMFileAsync(Id, args).ConfigureAwait(false); return new Message(this, new User(model.Author.Value), model); } } public async Task SendFileAsync(Stream stream, string filename, string text, bool isTTS) { - var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; - var model = await Discord.ApiClient.UploadDMFileAsync(Id, stream, args).ConfigureAwait(false); + var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS }; + var model = await Discord.ApiClient.UploadDMFileAsync(Id, args).ConfigureAwait(false); return new Message(this, new User(model.Author.Value), model); } public virtual async Task GetMessageAsync(ulong id) diff --git a/src/Discord.Net/Entities/Channels/GroupChannel.cs b/src/Discord.Net/Entities/Channels/GroupChannel.cs index 0e9347166..8169bfb9c 100644 --- a/src/Discord.Net/Entities/Channels/GroupChannel.cs +++ b/src/Discord.Net/Entities/Channels/GroupChannel.cs @@ -99,15 +99,15 @@ namespace Discord string filename = Path.GetFileName(filePath); using (var file = File.OpenRead(filePath)) { - var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; - var model = await Discord.ApiClient.UploadDMFileAsync(Id, file, args).ConfigureAwait(false); + var args = new UploadFileParams(file) { Filename = filename, Content = text, IsTTS = isTTS }; + var model = await Discord.ApiClient.UploadDMFileAsync(Id, args).ConfigureAwait(false); return new Message(this, new User(model.Author.Value), model); } } public async Task SendFileAsync(Stream stream, string filename, string text, bool isTTS) { - var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; - var model = await Discord.ApiClient.UploadDMFileAsync(Id, stream, args).ConfigureAwait(false); + var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS }; + var model = await Discord.ApiClient.UploadDMFileAsync(Id, args).ConfigureAwait(false); return new Message(this, new User(model.Author.Value), model); } public virtual async Task GetMessageAsync(ulong id) diff --git a/src/Discord.Net/Entities/Channels/TextChannel.cs b/src/Discord.Net/Entities/Channels/TextChannel.cs index 6f11e6df7..a8c0d24ee 100644 --- a/src/Discord.Net/Entities/Channels/TextChannel.cs +++ b/src/Discord.Net/Entities/Channels/TextChannel.cs @@ -68,15 +68,15 @@ namespace Discord string filename = Path.GetFileName(filePath); using (var file = File.OpenRead(filePath)) { - var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; - var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, file, args).ConfigureAwait(false); + var args = new UploadFileParams(file) { Filename = filename, Content = text, IsTTS = isTTS }; + var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, args).ConfigureAwait(false); return new Message(this, new User(model.Author.Value), model); } } public async Task SendFileAsync(Stream stream, string filename, string text, bool isTTS) { - var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS }; - var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, stream, args).ConfigureAwait(false); + var args = new UploadFileParams(stream) { Filename = filename, Content = text, IsTTS = isTTS }; + var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, args).ConfigureAwait(false); return new Message(this, new User(model.Author.Value), model); } public virtual async Task GetMessageAsync(ulong id) diff --git a/src/Discord.Net/Net/Rest/DefaultRestClient.cs b/src/Discord.Net/Net/Rest/DefaultRestClient.cs index 4108859d3..bcad2ece4 100644 --- a/src/Discord.Net/Net/Rest/DefaultRestClient.cs +++ b/src/Discord.Net/Net/Rest/DefaultRestClient.cs @@ -102,7 +102,7 @@ namespace Discord.Net.Rest if (p.Value is MultipartFile) { var fileValue = (MultipartFile)p.Value; - content.Add(new StreamContent(fileValue.Stream), fileValue.Filename, p.Key); + content.Add(new StreamContent(fileValue.Stream), p.Key, fileValue.Filename); continue; }