| @@ -3945,6 +3945,33 @@ | |||
| A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| </returns> | |||
| </member> | |||
| <member name="M:Discord.IGuild.CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},System.String,Discord.RequestOptions)"> | |||
| <summary> | |||
| Creates a new sticker in this guild | |||
| </summary> | |||
| <param name="name">The name of the sticker.</param> | |||
| <param name="description">The description of the sticker.</param> | |||
| <param name="tags">The tags of the sticker.</param> | |||
| <param name="path">The path of the file to upload.</param> | |||
| <param name="options">The options to be used when sending the request.</param> | |||
| <returns> | |||
| A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| </returns> | |||
| </member> | |||
| <member name="M:Discord.IGuild.CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},System.IO.Stream,System.String,Discord.RequestOptions)"> | |||
| <summary> | |||
| Creates a new sticker in this guild | |||
| </summary> | |||
| <param name="name">The name of the sticker.</param> | |||
| <param name="description">The description of the sticker.</param> | |||
| <param name="tags">The tags of the sticker.</param> | |||
| <param name="stream">The stream containing the file data.</param> | |||
| <param name="filename">The name of the file <b>with</b> the extension, ex: image.png</param> | |||
| <param name="options">The options to be used when sending the request.</param> | |||
| <returns> | |||
| A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| </returns> | |||
| </member> | |||
| <member name="M:Discord.IGuild.GetStickerAsync(System.UInt64,Discord.CacheMode,Discord.RequestOptions)"> | |||
| <summary> | |||
| Gets a specific sticker within this guild. | |||
| @@ -2,6 +2,7 @@ using Discord.Audio; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Globalization; | |||
| using System.IO; | |||
| using System.Threading.Tasks; | |||
| namespace Discord | |||
| @@ -962,6 +963,33 @@ namespace Discord | |||
| /// </returns> | |||
| Task<ICustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, Image image, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Creates a new sticker in this guild | |||
| /// </summary> | |||
| /// <param name="name">The name of the sticker.</param> | |||
| /// <param name="description">The description of the sticker.</param> | |||
| /// <param name="tags">The tags of the sticker.</param> | |||
| /// <param name="path">The path of the file to upload.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| /// </returns> | |||
| Task<ICustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, string path, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Creates a new sticker in this guild | |||
| /// </summary> | |||
| /// <param name="name">The name of the sticker.</param> | |||
| /// <param name="description">The description of the sticker.</param> | |||
| /// <param name="tags">The tags of the sticker.</param> | |||
| /// <param name="stream">The stream containing the file data.</param> | |||
| /// <param name="filename">The name of the file <b>with</b> the extension, ex: image.png</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| /// </returns> | |||
| Task<ICustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, Stream stream, string filename, RequestOptions options = null); | |||
| /// <summary> | |||
| /// Gets a specific sticker within this guild. | |||
| /// </summary> | |||
| @@ -1,4 +1,4 @@ | |||
| using System.IO; | |||
| using System.IO; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| @@ -6,11 +6,13 @@ namespace Discord.Net.Rest | |||
| { | |||
| public Stream Stream { get; } | |||
| public string Filename { get; } | |||
| public string ContentType { get; } | |||
| public MultipartFile(Stream stream, string filename) | |||
| public MultipartFile(Stream stream, string filename, string contentType = null) | |||
| { | |||
| Stream = stream; | |||
| Filename = filename; | |||
| this.ContentType = contentType; | |||
| } | |||
| } | |||
| } | |||
| @@ -15,17 +15,25 @@ namespace Discord.API.Rest | |||
| public string Name { get; set; } | |||
| public string Description { get; set; } | |||
| public string Tags { get; set; } | |||
| public string FileName { get; set; } | |||
| public IReadOnlyDictionary<string, object> ToDictionary() | |||
| { | |||
| var d = new Dictionary<string, object>(); | |||
| d["file"] = new MultipartFile(File, Name + ".dat"); | |||
| d["name"] = Name; | |||
| d["name"] = $"{Name}"; | |||
| d["description"] = Description; | |||
| d["tags"] = Tags; | |||
| string contentType = "image/png"; | |||
| if (File is FileStream fileStream) | |||
| contentType = $"image/{Path.GetExtension(fileStream.Name)}"; | |||
| else if(FileName != null) | |||
| contentType = $"image/{Path.GetExtension(FileName)}"; | |||
| d["file"] = new MultipartFile(File, FileName ?? "image", contentType.Replace(".", "")); | |||
| return d; | |||
| } | |||
| } | |||
| @@ -3540,6 +3540,33 @@ | |||
| A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| </returns> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},System.String,Discord.RequestOptions)"> | |||
| <summary> | |||
| Creates a new sticker in this guild | |||
| </summary> | |||
| <param name="name">The name of the sticker.</param> | |||
| <param name="description">The description of the sticker.</param> | |||
| <param name="tags">The tags of the sticker.</param> | |||
| <param name="path">The path of the file to upload.</param> | |||
| <param name="options">The options to be used when sending the request.</param> | |||
| <returns> | |||
| A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| </returns> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},System.IO.Stream,System.String,Discord.RequestOptions)"> | |||
| <summary> | |||
| Creates a new sticker in this guild | |||
| </summary> | |||
| <param name="name">The name of the sticker.</param> | |||
| <param name="description">The description of the sticker.</param> | |||
| <param name="tags">The tags of the sticker.</param> | |||
| <param name="stream">The stream containing the file data.</param> | |||
| <param name="filename">The name of the file <b>with</b> the extension, ex: image.png</param> | |||
| <param name="options">The options to be used when sending the request.</param> | |||
| <returns> | |||
| A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| </returns> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.GetStickerAsync(System.UInt64,Discord.RequestOptions)"> | |||
| <summary> | |||
| Gets a specific sticker within this guild. | |||
| @@ -3707,6 +3734,24 @@ | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#GetApplicationCommandsAsync(Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},Discord.Image,Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},System.IO.Stream,System.String,Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#CreateStickerAsync(System.String,System.String,System.Collections.Generic.IEnumerable{System.String},System.String,Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#GetStickerAsync(System.UInt64,Discord.CacheMode,Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#GetStickersAsync(Discord.CacheMode,Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="M:Discord.Rest.RestGuild.Discord#IGuild#DeleteStickerAsync(Discord.ICustomSticker,Discord.RequestOptions)"> | |||
| <inheritdoc /> | |||
| </member> | |||
| <member name="P:Discord.Rest.RestGuildIntegration.Name"> | |||
| <inheritdoc /> | |||
| </member> | |||
| @@ -8,6 +8,7 @@ using WidgetModel = Discord.API.GuildWidget; | |||
| using Model = Discord.API.Guild; | |||
| using RoleModel = Discord.API.Role; | |||
| using ImageModel = Discord.API.Image; | |||
| using System.IO; | |||
| namespace Discord.Rest | |||
| { | |||
| @@ -559,6 +560,32 @@ namespace Discord.Rest | |||
| return await client.ApiClient.CreateGuildStickerAsync(apiArgs, guild.Id, options).ConfigureAwait(false); | |||
| } | |||
| public static async Task<API.Sticker> CreateStickerAsync(BaseDiscordClient client, IGuild guild, string name, string description, IEnumerable<string> tags, | |||
| Stream file, string filename, RequestOptions options = null) | |||
| { | |||
| Preconditions.NotNull(name, nameof(name)); | |||
| Preconditions.NotNull(description, nameof(description)); | |||
| Preconditions.NotNull(file, nameof(file)); | |||
| Preconditions.NotNull(filename, nameof(filename)); | |||
| Preconditions.AtLeast(name.Length, 2, nameof(name)); | |||
| Preconditions.AtLeast(description.Length, 2, nameof(description)); | |||
| Preconditions.AtMost(name.Length, 30, nameof(name)); | |||
| Preconditions.AtMost(description.Length, 100, nameof(name)); | |||
| var apiArgs = new CreateStickerParams() | |||
| { | |||
| Name = name, | |||
| Description = description, | |||
| File = file, | |||
| Tags = string.Join(", ", tags), | |||
| FileName = filename | |||
| }; | |||
| return await client.ApiClient.CreateGuildStickerAsync(apiArgs, guild.Id, options).ConfigureAwait(false); | |||
| } | |||
| public static async Task<API.Sticker> ModifyStickerAsync(BaseDiscordClient client, ulong guildId, ISticker sticker, Action<StickerProperties> func, | |||
| RequestOptions options = null) | |||
| { | |||
| @@ -8,6 +8,7 @@ using System.Linq; | |||
| using System.Threading.Tasks; | |||
| using WidgetModel = Discord.API.GuildWidget; | |||
| using Model = Discord.API.Guild; | |||
| using System.IO; | |||
| namespace Discord.Rest | |||
| { | |||
| @@ -946,6 +947,42 @@ namespace Discord.Rest | |||
| return CustomSticker.Create(Discord, model, this, model.User.IsSpecified ? model.User.Value.Id : null); | |||
| } | |||
| /// <summary> | |||
| /// Creates a new sticker in this guild | |||
| /// </summary> | |||
| /// <param name="name">The name of the sticker.</param> | |||
| /// <param name="description">The description of the sticker.</param> | |||
| /// <param name="tags">The tags of the sticker.</param> | |||
| /// <param name="path">The path of the file to upload.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| /// </returns> | |||
| public Task<CustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, string path, | |||
| RequestOptions options = null) | |||
| { | |||
| var fs = File.OpenRead(path); | |||
| return CreateStickerAsync(name, description, tags, fs, Path.GetFileName(fs.Name), options); | |||
| } | |||
| /// <summary> | |||
| /// Creates a new sticker in this guild | |||
| /// </summary> | |||
| /// <param name="name">The name of the sticker.</param> | |||
| /// <param name="description">The description of the sticker.</param> | |||
| /// <param name="tags">The tags of the sticker.</param> | |||
| /// <param name="stream">The stream containing the file data.</param> | |||
| /// <param name="filename">The name of the file <b>with</b> the extension, ex: image.png</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| /// </returns> | |||
| public async Task<CustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, Stream stream, | |||
| string filename, RequestOptions options = null) | |||
| { | |||
| var model = await GuildHelper.CreateStickerAsync(Discord, this, name, description, tags, stream, filename, options).ConfigureAwait(false); | |||
| return CustomSticker.Create(Discord, model, this, model.User.IsSpecified ? model.User.Value.Id : null); | |||
| } | |||
| /// <summary> | |||
| /// Gets a specific sticker within this guild. | |||
| /// </summary> | |||
| /// <param name="id">The id of the sticker to get.</param> | |||
| @@ -1262,8 +1299,16 @@ namespace Discord.Rest | |||
| /// <inheritdoc /> | |||
| async Task<IReadOnlyCollection<IApplicationCommand>> IGuild.GetApplicationCommandsAsync (RequestOptions options) | |||
| => await GetApplicationCommandsAsync(options).ConfigureAwait(false); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, Image image, RequestOptions options) | |||
| => await CreateStickerAsync(name, description, tags, image, options); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, Stream stream, string filename, RequestOptions options) | |||
| => await CreateStickerAsync(name, description, tags, stream, filename, options); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, string path, RequestOptions options) | |||
| => await CreateStickerAsync(name, description, tags, path, options); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.GetStickerAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| { | |||
| if (mode != CacheMode.AllowDownload) | |||
| @@ -1271,6 +1316,7 @@ namespace Discord.Rest | |||
| return await GetStickerAsync(id, options); | |||
| } | |||
| /// <inheritdoc /> | |||
| async Task<IReadOnlyCollection<ICustomSticker>> IGuild.GetStickersAsync(CacheMode mode, RequestOptions options) | |||
| { | |||
| if (mode != CacheMode.AllowDownload) | |||
| @@ -1278,6 +1324,7 @@ namespace Discord.Rest | |||
| return await GetStickersAsync(options); | |||
| } | |||
| /// <inheritdoc /> | |||
| Task IGuild.DeleteStickerAsync(ICustomSticker sticker, RequestOptions options) | |||
| => sticker.DeleteAsync(); | |||
| } | |||
| @@ -7,6 +7,7 @@ using System.IO; | |||
| using System.Linq; | |||
| using System.Net; | |||
| using System.Net.Http; | |||
| using System.Net.Http.Headers; | |||
| using System.Text; | |||
| using System.Threading; | |||
| using System.Threading.Tasks; | |||
| @@ -101,7 +102,7 @@ namespace Discord.Net.Rest | |||
| switch (p.Value) | |||
| { | |||
| #pragma warning disable IDISP004 | |||
| case string stringValue: { content.Add(new StringContent(stringValue), p.Key); continue; } | |||
| case string stringValue: { content.Add(new StringContent(stringValue, Encoding.UTF8, "text/plain"), p.Key); continue; } | |||
| case byte[] byteArrayValue: { content.Add(new ByteArrayContent(byteArrayValue), p.Key); continue; } | |||
| case Stream streamValue: { content.Add(new StreamContent(streamValue), p.Key); continue; } | |||
| case MultipartFile fileValue: | |||
| @@ -116,8 +117,16 @@ namespace Discord.Net.Rest | |||
| stream = memoryStream; | |||
| #pragma warning restore IDISP001 | |||
| } | |||
| content.Add(new StreamContent(stream), p.Key, fileValue.Filename); | |||
| var streamContent = new StreamContent(stream); | |||
| var extension = fileValue.Filename.Split('.').Last(); | |||
| if(fileValue.ContentType != null) | |||
| streamContent.Headers.ContentType = new MediaTypeHeaderValue(fileValue.ContentType); | |||
| content.Add(streamContent, p.Key, fileValue.Filename); | |||
| #pragma warning restore IDISP004 | |||
| continue; | |||
| } | |||
| default: throw new InvalidOperationException($"Unsupported param type \"{p.Value.GetType().Name}\"."); | |||
| @@ -20,6 +20,7 @@ using RoleModel = Discord.API.Role; | |||
| using UserModel = Discord.API.User; | |||
| using VoiceStateModel = Discord.API.VoiceState; | |||
| using StickerModel = Discord.API.Sticker; | |||
| using System.IO; | |||
| namespace Discord.WebSocket | |||
| { | |||
| @@ -1248,6 +1249,42 @@ namespace Discord.WebSocket | |||
| return AddOrUpdateSticker(model); | |||
| } | |||
| /// <summary> | |||
| /// Creates a new sticker in this guild | |||
| /// </summary> | |||
| /// <param name="name">The name of the sticker.</param> | |||
| /// <param name="description">The description of the sticker.</param> | |||
| /// <param name="tags">The tags of the sticker.</param> | |||
| /// <param name="path">The path of the file to upload.</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| /// </returns> | |||
| public Task<SocketCustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, string path, | |||
| RequestOptions options = null) | |||
| { | |||
| var fs = File.OpenRead(path); | |||
| return CreateStickerAsync(name, description, tags, fs, Path.GetFileName(fs.Name), options); | |||
| } | |||
| /// <summary> | |||
| /// Creates a new sticker in this guild | |||
| /// </summary> | |||
| /// <param name="name">The name of the sticker.</param> | |||
| /// <param name="description">The description of the sticker.</param> | |||
| /// <param name="tags">The tags of the sticker.</param> | |||
| /// <param name="stream">The stream containing the file data.</param> | |||
| /// <param name="filename">The name of the file <b>with</b> the extension, ex: image.png</param> | |||
| /// <param name="options">The options to be used when sending the request.</param> | |||
| /// <returns> | |||
| /// A task that represents the asynchronous creation operation. The task result contains the created sticker. | |||
| /// </returns> | |||
| public async Task<SocketCustomSticker> CreateStickerAsync(string name, string description, IEnumerable<string> tags, Stream stream, | |||
| string filename, RequestOptions options = null) | |||
| { | |||
| var model = await GuildHelper.CreateStickerAsync(Discord, this, name, description, tags, stream, filename, options).ConfigureAwait(false); | |||
| return AddOrUpdateSticker(model); | |||
| } | |||
| /// <summary> | |||
| /// Deletes a sticker within this guild. | |||
| /// </summary> | |||
| /// <param name="sticker">The sticker to delete.</param> | |||
| @@ -1632,12 +1669,22 @@ namespace Discord.WebSocket | |||
| /// <inheritdoc /> | |||
| async Task<IReadOnlyCollection<IApplicationCommand>> IGuild.GetApplicationCommandsAsync (RequestOptions options) | |||
| => await GetApplicationCommandsAsync(options).ConfigureAwait(false); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, Image image, RequestOptions options) | |||
| => await CreateStickerAsync(name, description, tags, image, options); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, Stream stream, string filename, RequestOptions options) | |||
| => await CreateStickerAsync(name, description, tags, stream, filename, options); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.CreateStickerAsync(string name, string description, IEnumerable<string> tags, string path, RequestOptions options) | |||
| => await CreateStickerAsync(name, description, tags, path, options); | |||
| /// <inheritdoc /> | |||
| async Task<ICustomSticker> IGuild.GetStickerAsync(ulong id, CacheMode mode, RequestOptions options) | |||
| => await GetStickerAsync(id, mode, options); | |||
| /// <inheritdoc /> | |||
| async Task<IReadOnlyCollection<ICustomSticker>> IGuild.GetStickersAsync(CacheMode mode, RequestOptions options) | |||
| => await GetStickersAsync(mode, options); | |||
| /// <inheritdoc /> | |||
| Task IGuild.DeleteStickerAsync(ICustomSticker sticker, RequestOptions options) | |||
| => DeleteStickerAsync(_stickers[sticker.Id], options); | |||