| @@ -1,8 +1,30 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify an IGuildChannel with the specified changes. | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// await (Context.Channel as ITextChannel)?.ModifyAsync(x => | |||||
| /// { | |||||
| /// x.Name = "do-not-enter"; | |||||
| /// }); | |||||
| /// </code> | |||||
| /// </example> | |||||
| public class ModifyGuildChannelParams | public class ModifyGuildChannelParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Set the channel to this name | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// When modifying an ITextChannel, the Name MUST be alphanumeric with dashes. | |||||
| /// It must match the following RegEx: [a-z0-9-_]{2,100} | |||||
| /// </remarks> | |||||
| /// <exception cref="Net.HttpException">A BadRequest will be thrown if the name does not match the above RegEx.</exception> | |||||
| public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
| /// <summary> | |||||
| /// Move the channel to the following position. This is 0-based! | |||||
| /// </summary> | |||||
| public Optional<int> Position { get; set; } | public Optional<int> Position { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,7 +1,11 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <inheritdoc /> | |||||
| public class ModifyTextChannelParams : ModifyGuildChannelParams | public class ModifyTextChannelParams : ModifyGuildChannelParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// What the topic of the channel should be set to. | |||||
| /// </summary> | |||||
| public Optional<string> Topic { get; set; } | public Optional<string> Topic { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,8 +1,15 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <inheritdoc /> | |||||
| public class ModifyVoiceChannelParams : ModifyGuildChannelParams | public class ModifyVoiceChannelParams : ModifyGuildChannelParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// The bitrate of the voice connections in this channel. Must be greater than 8000 | |||||
| /// </summary> | |||||
| public Optional<int> Bitrate { get; set; } | public Optional<int> Bitrate { get; set; } | ||||
| /// <summary> | |||||
| /// The maximum number of users that can be present in a channel. | |||||
| /// </summary> | |||||
| public Optional<int> UserLimit { get; set; } | public Optional<int> UserLimit { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,8 +1,17 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify the widget of an IGuild with the specified parameters | |||||
| /// </summary> | |||||
| public class ModifyGuildEmbedParams | public class ModifyGuildEmbedParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Should the widget be enabled? | |||||
| /// </summary> | |||||
| public Optional<bool> Enabled { get; set; } | public Optional<bool> Enabled { get; set; } | ||||
| /// <summary> | |||||
| /// What channel should the invite place users in, if not null. | |||||
| /// </summary> | |||||
| public Optional<ulong?> ChannelId { get; set; } | public Optional<ulong?> ChannelId { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,16 +1,59 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify an IGuild with the specified changes | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// await Context.Guild.ModifyAsync(async x => | |||||
| /// { | |||||
| /// x.Name = "aaaaaah"; | |||||
| /// x.RegionId = (await Context.Client.GetOptimalVoiceRegionAsync()).Id; | |||||
| /// }); | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <see cref="IGuild"/> | |||||
| public class ModifyGuildParams | public class ModifyGuildParams | ||||
| { | { | ||||
| public Optional<string> Username { get; set; } | public Optional<string> Username { get; set; } | ||||
| /// <summary> | |||||
| /// The name of the Guild | |||||
| /// </summary> | |||||
| public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
| /// <summary> | |||||
| /// The ID of the region for the Guild's voice connections | |||||
| /// </summary> | |||||
| public Optional<string> RegionId { get; set; } | public Optional<string> RegionId { get; set; } | ||||
| /// <summary> | |||||
| /// What verification level new users need to achieve before speaking | |||||
| /// </summary> | |||||
| public Optional<VerificationLevel> VerificationLevel { get; set; } | public Optional<VerificationLevel> VerificationLevel { get; set; } | ||||
| /// <summary> | |||||
| /// The default message notification state for the guild | |||||
| /// </summary> | |||||
| public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; } | public Optional<DefaultMessageNotifications> DefaultMessageNotifications { get; set; } | ||||
| /// <summary> | |||||
| /// How many seconds before a user is sent to AFK. This value MUST be one of: (60, 300, 900, 1800, 3600). | |||||
| /// </summary> | |||||
| public Optional<int> AfkTimeout { get; set; } | public Optional<int> AfkTimeout { get; set; } | ||||
| /// <summary> | |||||
| /// The icon of the guild | |||||
| /// </summary> | |||||
| public Optional<Image?> Icon { get; set; } | public Optional<Image?> Icon { get; set; } | ||||
| /// <summary> | |||||
| /// The guild's splash image | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// The guild must be partnered for this value to have any effect. | |||||
| /// </remarks> | |||||
| public Optional<Image?> Splash { get; set; } | public Optional<Image?> Splash { get; set; } | ||||
| /// <summary> | |||||
| /// The ID of the IVoiceChannel where AFK users should be sent. | |||||
| /// </summary> | |||||
| public Optional<ulong?> AfkChannelId { get; set; } | public Optional<ulong?> AfkChannelId { get; set; } | ||||
| /// <summary> | |||||
| /// The ID of the owner of this guild. | |||||
| /// </summary> | |||||
| public Optional<ulong> OwnerId { get; set; } | public Optional<ulong> OwnerId { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -2,13 +2,28 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// An image that will be uploaded to Discord. | |||||
| /// </summary> | |||||
| public struct Image | public struct Image | ||||
| { | { | ||||
| public Stream Stream { get; } | public Stream Stream { get; } | ||||
| /// <summary> | |||||
| /// Create the image with a Stream. | |||||
| /// </summary> | |||||
| /// <param name="stream">This must be some type of stream with the contents of a file in it.</param> | |||||
| /// <seealso cref="File.OpenRead(string)"/> | |||||
| public Image(Stream stream) | public Image(Stream stream) | ||||
| { | { | ||||
| Stream = stream; | Stream = stream; | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Create the image from a file path. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// This file path is NOT validated, and is passed directly into a <see cref="File.OpenRead(string)"/> | |||||
| /// </remarks> | |||||
| /// <param name="path">The path to the file.</param> | |||||
| public Image(string path) | public Image(string path) | ||||
| { | { | ||||
| Stream = File.OpenRead(path); | Stream = File.OpenRead(path); | ||||
| @@ -1,12 +1,37 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Discord | |||||
| namespace Discord | |||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify a message with the specified parameters. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// The content of a message can be cleared with String.Empty; if and only if an Embed is present. | |||||
| /// </remarks> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// var message = await ReplyAsync("abc"); | |||||
| /// await message.ModifyAsync(x => | |||||
| /// { | |||||
| /// x.Content = ""; | |||||
| /// x.Embed = new EmbedBuilder() | |||||
| /// .WithColor(new Color(40, 40, 120)) | |||||
| /// .WithAuthor(a => a.Name = "foxbot") | |||||
| /// .WithTitle("Embed!") | |||||
| /// .WithDescription("This is an embed."); | |||||
| /// }); | |||||
| /// </code> | |||||
| /// </example> | |||||
| public class ModifyMessageParams | public class ModifyMessageParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// The content of the message | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// This must be less than 2000 characters. | |||||
| /// </remarks> | |||||
| public Optional<string> Content { get; set; } | public Optional<string> Content { get; set; } | ||||
| /// <summary> | |||||
| /// The embed the message should display | |||||
| /// </summary> | |||||
| public Optional<EmbedBuilder> Embed { get; set; } | public Optional<EmbedBuilder> Embed { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,11 +1,51 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify an IRole with the specified parameters | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// await role.ModifyAsync(x => | |||||
| /// { | |||||
| /// x.Color = new Color(180, 15, 40); | |||||
| /// x.Hoist = true; | |||||
| /// }); | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <seealso cref="IRole"/> | |||||
| public class ModifyGuildRoleParams | public class ModifyGuildRoleParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// The name of the role | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If this role is the EveryoneRole, this value may not be set. | |||||
| /// </remarks> | |||||
| public Optional<string> Name { get; set; } | public Optional<string> Name { get; set; } | ||||
| public Optional<ulong> Permissions { get; set; } | |||||
| /// <summary> | |||||
| /// The role's GuildPermissions | |||||
| /// </summary> | |||||
| public Optional<GuildPermissions> Permissions { get; set; } | |||||
| /// <summary> | |||||
| /// The position of the role. This is 0-based! | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If this role is the EveryoneRole, this value may not be set. | |||||
| /// </remarks> | |||||
| public Optional<int> Position { get; set; } | public Optional<int> Position { get; set; } | ||||
| public Optional<uint> Color { get; set; } | |||||
| /// <summary> | |||||
| /// The color of the Role. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If this role is the EveryoneRole, this value may not be set. | |||||
| /// </remarks> | |||||
| public Optional<Color> Color { get; set; } | |||||
| /// <summary> | |||||
| /// Whether or not this role should be displayed independently in the userlist. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If this role is the EveryoneRole, this value may not be set. | |||||
| /// </remarks> | |||||
| public Optional<bool> Hoist { get; set; } | public Optional<bool> Hoist { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,8 +1,26 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify the current user with the specified arguments | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// await Context.Client.CurrentUser.ModifyAsync(x => | |||||
| /// { | |||||
| /// x.Avatar = new Image(File.OpenRead("avatar.jpg")); | |||||
| /// }); | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <seealso cref="ISelfUser"/> | |||||
| public class ModifyCurrentUserParams | public class ModifyCurrentUserParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Your username | |||||
| /// </summary> | |||||
| public Optional<string> Username { get; set; } | public Optional<string> Username { get; set; } | ||||
| /// <summary> | |||||
| /// Your avatar | |||||
| /// </summary> | |||||
| public Optional<Image> Avatar { get; set; } | public Optional<Image> Avatar { get; set; } | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,11 +1,54 @@ | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Modify an IGuildUser with the following parameters. | |||||
| /// </summary> | |||||
| /// <example> | |||||
| /// <code language="c#"> | |||||
| /// await (Context.User as IGuildUser)?.ModifyAsync(x => | |||||
| /// { | |||||
| /// x.Nickname = $"festive {Context.User.Username}"; | |||||
| /// }); | |||||
| /// </code> | |||||
| /// </example> | |||||
| /// <seealso cref="IGuildUser"/> | |||||
| public class ModifyGuildMemberParams | public class ModifyGuildMemberParams | ||||
| { | { | ||||
| /// <summary> | |||||
| /// Should the user be guild-muted in a voice channel? | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If this value is set to true, no user will be able to hear this user speak in the guild. | |||||
| /// </remarks> | |||||
| public Optional<bool> Mute { get; set; } | public Optional<bool> Mute { get; set; } | ||||
| /// <summary> | |||||
| /// Should the user be guild-deafened in a voice channel? | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// If this value is set to true, this user will not be able to hear anyone speak in the guild. | |||||
| /// </remarks> | |||||
| public Optional<bool> Deaf { get; set; } | public Optional<bool> Deaf { get; set; } | ||||
| /// <summary> | |||||
| /// Should the user have a nickname set? | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// To clear the user's nickname, this value can be set to null. | |||||
| /// </remarks> | |||||
| public Optional<string> Nickname { get; set; } | public Optional<string> Nickname { get; set; } | ||||
| public Optional<ulong[]> RoleIds { get; set; } | |||||
| public Optional<ulong> ChannelId { get; set; } | |||||
| /// <summary> | |||||
| /// What roles should the user have? | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// To add a role to a user: <see cref="GuildUserExtensions.AddRolesAsync(IGuildUser, IRole[])"/> | |||||
| /// To remove a role from a user: <see cref="GuildUserExtensions.RemoveRolesAsync(IGuildUser, IRole[])"/> | |||||
| /// </remarks> | |||||
| public Optional<IRole[]> Roles { get; set; } | |||||
| /// <summary> | |||||
| /// Move a user to a voice channel. | |||||
| /// </summary> | |||||
| /// <remarks> | |||||
| /// This user MUST already be in a Voice Channel for this to work. | |||||
| /// </remarks> | |||||
| public Optional<IVoiceChannel> Channel { get; set; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,4 +1,5 @@ | |||||
| using System; | using System; | ||||
| using System.Linq; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| @@ -64,7 +64,14 @@ namespace Discord.Rest | |||||
| public static async Task<IReadOnlyCollection<RoleModel>> ModifyRolesAsync(IGuild guild, BaseDiscordClient client, | public static async Task<IReadOnlyCollection<RoleModel>> ModifyRolesAsync(IGuild guild, BaseDiscordClient client, | ||||
| IEnumerable<ModifyGuildRolesParams> args, RequestOptions options) | IEnumerable<ModifyGuildRolesParams> args, RequestOptions options) | ||||
| { | { | ||||
| var apiArgs = args.Select(x => new API.Rest.ModifyGuildRolesParams(x.Id) { Color = x.Color, Hoist = x.Hoist, Name = x.Name, Permissions = x.Permissions, Position = x.Position }); | |||||
| var apiArgs = args.Select(x => new API.Rest.ModifyGuildRolesParams(x.Id) | |||||
| { | |||||
| Color = x.Color.IsSpecified ? x.Color.Value.RawValue : Optional.Create<uint>(), | |||||
| Hoist = x.Hoist, | |||||
| Name = x.Name, | |||||
| Permissions = x.Permissions.IsSpecified ? x.Permissions.Value.RawValue : Optional.Create<ulong>(), | |||||
| Position = x.Position | |||||
| }); | |||||
| return await client.ApiClient.ModifyGuildRolesAsync(guild.Id, apiArgs, options).ConfigureAwait(false); | return await client.ApiClient.ModifyGuildRolesAsync(guild.Id, apiArgs, options).ConfigureAwait(false); | ||||
| } | } | ||||
| public static async Task LeaveAsync(IGuild guild, BaseDiscordClient client, | public static async Task LeaveAsync(IGuild guild, BaseDiscordClient client, | ||||
| @@ -167,8 +174,8 @@ namespace Discord.Rest | |||||
| await role.ModifyAsync(x => | await role.ModifyAsync(x => | ||||
| { | { | ||||
| x.Name = name; | x.Name = name; | ||||
| x.Permissions = (permissions ?? role.Permissions).RawValue; | |||||
| x.Color = (color ?? Color.Default).RawValue; | |||||
| x.Permissions = (permissions ?? role.Permissions); | |||||
| x.Color = (color ?? Color.Default); | |||||
| x.Hoist = isHoisted; | x.Hoist = isHoisted; | ||||
| }, options).ConfigureAwait(false); | }, options).ConfigureAwait(false); | ||||
| @@ -20,10 +20,10 @@ namespace Discord.Rest | |||||
| func(args); | func(args); | ||||
| var apiArgs = new API.Rest.ModifyGuildRoleParams | var apiArgs = new API.Rest.ModifyGuildRoleParams | ||||
| { | { | ||||
| Color = args.Color, | |||||
| Color = args.Color.IsSpecified ? args.Color.Value.RawValue : Optional.Create<uint>(), | |||||
| Hoist = args.Hoist, | Hoist = args.Hoist, | ||||
| Name = args.Name, | Name = args.Name, | ||||
| Permissions = args.Permissions, | |||||
| Permissions = args.Permissions.IsSpecified ? args.Permissions.Value.RawValue : Optional.Create<ulong>(), | |||||
| Position = args.Position | Position = args.Position | ||||
| }; | }; | ||||
| return await client.ApiClient.ModifyGuildRoleAsync(role.Guild.Id, role.Id, apiArgs, options).ConfigureAwait(false); | return await client.ApiClient.ModifyGuildRoleAsync(role.Guild.Id, role.Id, apiArgs, options).ConfigureAwait(false); | ||||
| @@ -3,6 +3,7 @@ using System; | |||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using Model = Discord.API.User; | using Model = Discord.API.User; | ||||
| using ImageModel = Discord.API.Image; | using ImageModel = Discord.API.Image; | ||||
| using System.Linq; | |||||
| namespace Discord.Rest | namespace Discord.Rest | ||||
| { | { | ||||
| @@ -27,11 +28,11 @@ namespace Discord.Rest | |||||
| func(args); | func(args); | ||||
| var apiArgs = new API.Rest.ModifyGuildMemberParams | var apiArgs = new API.Rest.ModifyGuildMemberParams | ||||
| { | { | ||||
| ChannelId = args.ChannelId, | |||||
| ChannelId = args.Channel.IsSpecified ? args.Channel.Value.Id : Optional.Create<ulong>(), | |||||
| Deaf = args.Deaf, | Deaf = args.Deaf, | ||||
| Mute = args.Mute, | Mute = args.Mute, | ||||
| Nickname = args.Nickname, | Nickname = args.Nickname, | ||||
| RoleIds = args.RoleIds | |||||
| RoleIds = args.Roles.IsSpecified ? args.Roles.Value.Select(r => r.Id).ToArray() : Optional.Create<ulong[]>(), | |||||
| }; | }; | ||||
| await client.ApiClient.ModifyGuildMemberAsync(user.GuildId, user.Id, apiArgs, options).ConfigureAwait(false); | await client.ApiClient.ModifyGuildMemberAsync(user.GuildId, user.Id, apiArgs, options).ConfigureAwait(false); | ||||
| return args; | return args; | ||||