diff --git a/DisCatSharp/Clients/DiscordOAuth2Client.cs b/DisCatSharp/Clients/DiscordOAuth2Client.cs index a37324a65d..48dcc46a2b 100644 --- a/DisCatSharp/Clients/DiscordOAuth2Client.cs +++ b/DisCatSharp/Clients/DiscordOAuth2Client.cs @@ -309,6 +309,35 @@ public Task> GetCurrentUserGuildsAsync(DiscordAccess public Task GetCurrentUserGuildMemberAsync(DiscordAccessToken accessToken, ulong guildId) => accessToken.Scope.Split(' ').Any(x => x == "guilds.members.read") ? this.ApiClient.GetCurrentUserGuildMemberAsync(accessToken.AccessToken, guildId) : throw new AccessViolationException("Access token does not include guilds.members.read scope"); + /// + /// Adds the current user to the given . + /// Some parameters might need additional permissions for the bot on the target guild. See https://discord.com/developers/docs/resources/guild#add-guild-member for details. + /// This methods invokes a sub-request to . + /// + /// The discord access token. + /// The guild id to add the member to. + /// The new nickname. + /// The new roles. + /// Whether this user has to be muted. + /// Whether this user has to be deafened. + public async Task AddCurrentUserToGuildAsync(DiscordAccessToken accessToken, ulong guildId, string? nickname = null, IEnumerable? roles = null, bool? muted = null, bool? deafened = null) + => accessToken.Scope.Split(' ').Any(x => x == "guilds.join") ? await this.ApiClient.AddGuildMemberAsync(guildId, (await this.GetCurrentUserAsync(accessToken)).Id, accessToken.AccessToken, nickname, roles, muted, deafened) : throw new AccessViolationException("Access token does not include guilds.join scope"); + + /// + /// Adds the given to the given . + /// Some parameters might need additional permissions for the bot on the target guild. See https://discord.com/developers/docs/resources/guild#add-guild-member for details. + /// This methods does not invoke a sub-request to . + /// + /// The discord access token. + /// The user id to add. + /// The guild id to add the member to. + /// The new nickname. + /// The new roles. + /// Whether this user has to be muted. + /// Whether this user has to be deafened. + public async Task AddCurrentUserToGuildAsync(DiscordAccessToken accessToken, ulong userId, ulong guildId, string? nickname = null, IEnumerable? roles = null, bool? muted = null, bool? deafened = null) + => accessToken.Scope.Split(' ').Any(x => x == "guilds.join") ? await this.ApiClient.AddGuildMemberAsync(guildId, userId, accessToken.AccessToken, nickname, roles, muted, deafened) : throw new AccessViolationException("Access token does not include guilds.join scope"); + /// /// Gets the current user's application role connection. /// diff --git a/DisCatSharp/Entities/Guild/DiscordGuild.cs b/DisCatSharp/Entities/Guild/DiscordGuild.cs index 39583ea729..2e06738218 100644 --- a/DisCatSharp/Entities/Guild/DiscordGuild.cs +++ b/DisCatSharp/Entities/Guild/DiscordGuild.cs @@ -749,12 +749,12 @@ public Task> SearchMembersAsync(string name, int? l /// /// Adds a new member to this guild /// - /// User to add - /// User's access token (OAuth2) - /// new nickname - /// new roles - /// whether this user has to be muted - /// whether this user has to be deafened + /// The user to add. + /// The user's access token (OAuth2). + /// The new nickname. + /// The new roles. + /// Whether this user has to be muted. + /// Whether this user has to be deafened. /// Thrown when the client does not have the permission. /// Thrown when the or is not found. /// Thrown when an invalid parameter was provided. @@ -762,10 +762,10 @@ public Task> SearchMembersAsync(string name, int? l public Task AddMemberAsync( DiscordUser user, string accessToken, - string nickname = null, - IEnumerable roles = null, - bool muted = false, - bool deaf = false + string? nickname = null, + IEnumerable? roles = null, + bool? muted = null, + bool? deaf = null ) => this.Discord.ApiClient.AddGuildMemberAsync(this.Id, user.Id, accessToken, nickname, roles, muted, deaf); diff --git a/DisCatSharp/Entities/Guild/DiscordMember.cs b/DisCatSharp/Entities/Guild/DiscordMember.cs index 9e1dd35be8..20d1befe91 100644 --- a/DisCatSharp/Entities/Guild/DiscordMember.cs +++ b/DisCatSharp/Entities/Guild/DiscordMember.cs @@ -73,7 +73,7 @@ internal DiscordMember(TransportMember mbr) /// Gets the members avatar hash. /// [JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)] - public string GuildAvatarHash { get; internal set; } + public string? GuildAvatarHash { get; internal set; } /// /// Gets the members avatar URL. @@ -86,13 +86,13 @@ public string GuildAvatarUrl /// Gets the members banner hash. /// [JsonProperty("banner", NullValueHandling = NullValueHandling.Ignore)] - public string GuildBannerHash { get; internal set; } + public string? GuildBannerHash { get; internal set; } /// /// Gets the members banner URL. /// [JsonIgnore] - public string GuildBannerUrl + public string? GuildBannerUrl => string.IsNullOrWhiteSpace(this.GuildBannerHash) ? this.User.BannerUrl : $"{DiscordDomain.GetDomain(CoreDomain.DiscordCdn).Url}{Endpoints.GUILDS}/{this.GuildId.ToString(CultureInfo.InvariantCulture)}{Endpoints.USERS}/{this.Id.ToString(CultureInfo.InvariantCulture)}{Endpoints.BANNERS}/{this.GuildBannerHash}.{(this.GuildBannerHash.StartsWith("a_", StringComparison.Ordinal) ? "gif" : "png")}?size=1024"; /// @@ -106,20 +106,20 @@ public override DiscordColor? BannerColor /// Gets this member's nickname. /// [JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)] - public string Nickname { get; internal set; } + public string? Nickname { get; internal set; } /// /// Gets the members guild bio. /// This is not available to bots tho. /// [JsonProperty("bio", NullValueHandling = NullValueHandling.Ignore)] - public string GuildBio { get; internal set; } + public string? GuildBio { get; internal set; } /// /// Gets the members's pronouns. /// [JsonProperty("pronouns", NullValueHandling = NullValueHandling.Ignore)] - public string GuildPronouns { get; internal set; } + public string? GuildPronouns { get; internal set; } /// /// Gets the members flags. @@ -127,8 +127,11 @@ public override DiscordColor? BannerColor [JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)] public MemberFlags MemberFlags { get; internal set; } + /// + /// Gets the avatar hash. + /// [JsonIgnore] - internal string AvatarHashInternal; + internal string? AvatarHashInternal; /// /// Gets this member's display name. @@ -155,7 +158,7 @@ internal IReadOnlyList RoleIds /// [JsonIgnore] public IReadOnlyList Roles - => this.RoleIds.Select(id => this.Guild.GetRole(id)).Where(x => x != null).ToList(); + => this.RoleIds.Select(id => this.Guild.GetRole(id)).Where(x => x is not null).ToList(); /// /// Gets the color associated with this user's top color-giving role, otherwise 0 (no color). @@ -165,8 +168,8 @@ public DiscordColor Color { get { - var role = this.Roles.OrderByDescending(xr => xr.Position).FirstOrDefault(xr => xr.Color.Value != 0); - return role != null ? role.Color : new(); + var role = this.Roles.OrderByDescending(xr => xr.Position).FirstOrDefault(xr => xr.Color.Value is not 0); + return role?.Color ?? new(); } } @@ -199,14 +202,14 @@ public DiscordColor Color /// [JsonIgnore] public bool IsCommunicationDisabled - => this.CommunicationDisabledUntil != null && this.CommunicationDisabledUntil.Value.ToUniversalTime() > DateTime.UtcNow; + => this.CommunicationDisabledUntil is not null && this.CommunicationDisabledUntil.Value.ToUniversalTime() > DateTime.UtcNow; /// /// Whether the user has their communication disabled. /// [JsonIgnore] public bool HasUnusualDmActivity - => this.UnusualDmActivityUntil != null && this.UnusualDmActivityUntil.Value.ToUniversalTime() > DateTime.UtcNow; + => this.UnusualDmActivityUntil is not null && this.UnusualDmActivityUntil.Value.ToUniversalTime() > DateTime.UtcNow; /// /// If the user is deafened @@ -230,9 +233,12 @@ public bool HasUnusualDmActivity /// Gets this member's voice state. /// [JsonIgnore] - public DiscordVoiceState VoiceState - => this.Discord.Guilds[this.GuildId].VoiceStates.TryGetValue(this.Id, out var voiceState) ? voiceState : null; + public DiscordVoiceState? VoiceState + => this.Discord.Guilds[this.GuildId].VoiceStates.GetValueOrDefault(this.Id); + /// + /// Gets the guild id for this member. + /// [JsonIgnore] internal ulong GuildId = 0; @@ -281,7 +287,12 @@ public Permissions Permissions /// [JsonIgnore] internal DiscordUser User - => this.Discord.UserCache[this.Id]; + => this.Discord?.UserCache.TryGetValue(this.Id, out var user) ?? false ? user : this.ManualUser; + + /// + /// Sets the user when converting a json object to while not having access to the user cache. + /// + public DiscordUser ManualUser { get; set; } /// /// Gets this member's username. @@ -321,7 +332,7 @@ public override string UsernameWithGlobalName /// Gets the member's global name. /// [JsonIgnore, DiscordInExperiment] - public override string GlobalName + public override string? GlobalName { get => this.User.GlobalName; internal set => this.User.GlobalName = value; @@ -448,13 +459,21 @@ public override UserFlags? Flags /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task SetMuteAsync(bool mute, string reason = null) + public Task SetMuteAsync(bool mute, string? reason = null) => this.Discord.ApiClient.ModifyGuildMemberAsync(this.GuildId, this.Id, default, default, mute, default, default, default, this.MemberFlags, reason); - public Task VerifyAsync(string reason = null) + /// + /// Manually verifies the member to bypass the Membership Screening requirements. + /// + /// Reason for audit logs. + public Task VerifyAsync(string? reason = null) => this.Discord.ApiClient.ModifyGuildMemberAsync(this.GuildId, this.Id, default, default, default, default, default, true, this.MemberFlags, reason); - public Task UnverifyAsync(string reason = null) + /// + /// Manually unverifies the member to not bypass the Membership Screening requirements anymore. + /// + /// Reason for audit logs. + public Task UnverifyAsync(string? reason = null) => this.Discord.ApiClient.ModifyGuildMemberAsync(this.GuildId, this.Id, default, default, default, default, default, false, this.MemberFlags, reason); /// @@ -466,7 +485,7 @@ public Task UnverifyAsync(string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task SetDeafAsync(bool deaf, string reason = null) + public Task SetDeafAsync(bool deaf, string? reason = null) => this.Discord.ApiClient.ModifyGuildMemberAsync(this.GuildId, this.Id, default, default, default, deaf, default, default, this.MemberFlags, reason); /// @@ -482,7 +501,7 @@ public async Task ModifyAsync(Action action) var mdl = new MemberEditModel(); action(mdl); - if (mdl.VoiceChannel.HasValue && mdl.VoiceChannel.Value != null && mdl.VoiceChannel.Value.Type != ChannelType.Voice && mdl.VoiceChannel.Value.Type != ChannelType.Stage) + if (mdl.VoiceChannel.HasValue && mdl.VoiceChannel.Value != null! && mdl.VoiceChannel.Value.Type is not ChannelType.Voice && mdl.VoiceChannel.Value.Type is not ChannelType.Stage) throw new ArgumentException("Given channel is not a voice or stage channel.", nameof(action)); if (mdl.Nickname.HasValue && this.Discord.CurrentUser.Id == this.Id) @@ -504,7 +523,7 @@ await this.Discord.ApiClient.ModifyGuildMemberAsync(this.Guild.Id, this.Id, mdl. /// Disconnects the member from their current voice channel. /// public async Task DisconnectFromVoiceAsync() - => await this.ModifyAsync(x => x.VoiceChannel = null).ConfigureAwait(false); + => await this.ModifyAsync(x => x.VoiceChannel = null!).ConfigureAwait(false); /// /// Adds a timeout to a member. @@ -515,7 +534,7 @@ public async Task DisconnectFromVoiceAsync() /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task TimeoutAsync(DateTimeOffset until, string reason = null) + public Task TimeoutAsync(DateTimeOffset until, string? reason = null) => until.Subtract(DateTimeOffset.UtcNow).Days > 28 ? throw new ArgumentException("Timeout can not be longer than 28 days") : this.Discord.ApiClient.ModifyTimeoutAsync(this.Guild.Id, this.Id, until, reason); /// @@ -527,7 +546,7 @@ public Task TimeoutAsync(DateTimeOffset until, string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task TimeoutAsync(TimeSpan until, string reason = null) + public Task TimeoutAsync(TimeSpan until, string? reason = null) => this.TimeoutAsync(DateTimeOffset.UtcNow + until, reason); /// @@ -539,7 +558,7 @@ public Task TimeoutAsync(TimeSpan until, string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task TimeoutAsync(DateTime until, string reason = null) + public Task TimeoutAsync(DateTime until, string? reason = null) => this.TimeoutAsync(until.ToUniversalTime() - DateTime.UtcNow, reason); /// @@ -562,7 +581,7 @@ public Task RemoveTimeoutAsync(string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task GrantRoleAsync(DiscordRole role, string reason = null) + public Task GrantRoleAsync(DiscordRole role, string? reason = null) => this.Discord.ApiClient.AddGuildMemberRoleAsync(this.Guild.Id, this.Id, role.Id, reason); /// @@ -574,7 +593,7 @@ public Task GrantRoleAsync(DiscordRole role, string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task RevokeRoleAsync(DiscordRole role, string reason = null) + public Task RevokeRoleAsync(DiscordRole role, string? reason = null) => this.Discord.ApiClient.RemoveGuildMemberRoleAsync(this.Guild.Id, this.Id, role.Id, reason); /// @@ -586,7 +605,7 @@ public Task RevokeRoleAsync(DiscordRole role, string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task ReplaceRolesAsync(IEnumerable roles, string reason = null) + public Task ReplaceRolesAsync(IEnumerable roles, string? reason = null) => this.Discord.ApiClient.ModifyGuildMemberAsync(this.Guild.Id, this.Id, default, Optional.Some(roles.Select(xr => xr.Id)), default, default, default, default, this.MemberFlags, reason); @@ -599,7 +618,7 @@ public Task ReplaceRolesAsync(IEnumerable roles, string reason = nu /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task BanAsync(int deleteMessageDays = 0, string reason = null) + public Task BanAsync(int deleteMessageDays = 0, string? reason = null) => this.Guild.BanMemberAsync(this, deleteMessageDays, reason); /// @@ -609,7 +628,7 @@ public Task BanAsync(int deleteMessageDays = 0, string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task UnbanAsync(string reason = null) + public Task UnbanAsync(string? reason = null) => this.Guild.UnbanMemberAsync(this, reason); /// @@ -621,7 +640,7 @@ public Task UnbanAsync(string reason = null) /// Thrown when the member does not exist. /// Thrown when an invalid parameter was provided. /// Thrown when Discord is unable to process the request. - public Task RemoveAsync(string reason = null) + public Task RemoveAsync(string? reason = null) => this.Discord.ApiClient.RemoveGuildMemberAsync(this.GuildId, this.Id, reason); /// @@ -660,7 +679,7 @@ public async Task UpdateVoiceStateAsync(DiscordChannel channel, bool? suppress) public async Task MakeSpeakerAsync() { var vs = this.VoiceState; - if (vs == null || vs.Channel.Type != ChannelType.Stage) + if (vs?.Channel?.Type is not ChannelType.Stage) throw new ArgumentException("Voice state can only be updated when the user is inside an stage channel."); await this.Discord.ApiClient.UpdateUserVoiceStateAsync(this.Guild.Id, this.Id, vs.Channel.Id, false).ConfigureAwait(false); @@ -677,7 +696,7 @@ public async Task MakeSpeakerAsync() public async Task MoveToAudienceAsync() { var vs = this.VoiceState; - if (vs == null || vs.Channel.Type != ChannelType.Stage) + if (vs?.Channel?.Type is not ChannelType.Stage) throw new ArgumentException("Voice state can only be updated when the user is inside an stage channel."); await this.Discord.ApiClient.UpdateUserVoiceStateAsync(this.Guild.Id, this.Id, vs.Channel.Id, true).ConfigureAwait(false); @@ -699,11 +718,9 @@ private Permissions GetPermissions() if (this.Guild.OwnerId == this.Id) return PermissionMethods.FullPerms; - Permissions perms; - // assign @everyone permissions var everyoneRole = this.Guild.EveryoneRole; - perms = everyoneRole.Permissions; + var perms = everyoneRole.Permissions; // assign permissions from member's roles (in order) perms |= this.Roles.Aggregate(Permissions.None, (c, role) => c | role.Permissions); diff --git a/DisCatSharp/Entities/User/DiscordUser.cs b/DisCatSharp/Entities/User/DiscordUser.cs index fa43d6523e..97d7586456 100644 --- a/DisCatSharp/Entities/User/DiscordUser.cs +++ b/DisCatSharp/Entities/User/DiscordUser.cs @@ -81,7 +81,7 @@ public virtual string UsernameWithGlobalName /// Only applicable if is . /// [JsonProperty("global_name", NullValueHandling = NullValueHandling.Ignore), DiscordInExperiment] - public virtual string GlobalName { get; internal set; } + public virtual string? GlobalName { get; internal set; } /// /// Whether this user account is migrated to the new username system. @@ -133,7 +133,7 @@ public virtual DiscordColor? BannerColor /// Gets the user's banner url /// [JsonIgnore] - public string BannerUrl + public string? BannerUrl => string.IsNullOrWhiteSpace(this.BannerHash) ? null : $"{DiscordDomain.GetDomain(CoreDomain.DiscordCdn).Url}{Endpoints.BANNERS}/{this.Id.ToString(CultureInfo.InvariantCulture)}/{this.BannerHash}.{(this.BannerHash.StartsWith("a_", StringComparison.Ordinal) ? "gif" : "png")}?size=4096"; /// @@ -226,7 +226,7 @@ public string DefaultAvatarUrl /// This is only present in OAuth. /// [JsonProperty("email", NullValueHandling = NullValueHandling.Ignore)] - public virtual string Email { get; internal set; } + public virtual string? Email { get; internal set; } /// /// Gets the user's premium type. @@ -256,7 +256,7 @@ public string DefaultAvatarUrl /// Gets the user's pronouns. /// [JsonProperty("pronouns", NullValueHandling = NullValueHandling.Ignore)] - public virtual string Pronouns { get; internal set; } + public virtual string? Pronouns { get; internal set; } /// /// Gets the user's mention string. @@ -369,6 +369,32 @@ public async Task OAuth2GetGuildMemberAsync(DiscordOAuth2Client o public async Task OAuth2GetGuildMemberAsync(DiscordOAuth2Client oauth2Client, ulong guildId) => await oauth2Client.GetCurrentUserGuildMemberAsync(this.AccessToken, guildId); + /// + /// Adds the user to the given . + /// Some parameters might need additional permissions for the bot on the target guild. See https://discord.com/developers/docs/resources/guild#add-guild-member for details. + /// + /// The oauth2 client. + /// The guild id to add the member to. + /// The new nickname. + /// The new roles. + /// Whether this user has to be muted. + /// Whether this user has to be deafened. + public async Task OAuth2AddToGuildAsync(DiscordOAuth2Client oauth2Client, ulong guildId, string? nickname = null, IEnumerable? roles = null, bool? muted = null, bool? deafened = null) + => await oauth2Client.AddCurrentUserToGuildAsync(this.AccessToken, this.Id, guildId, nickname, roles, muted, deafened); + + /// + /// Adds the user to the given . + /// Some parameters might need additional permissions for the bot on the target guild. See https://discord.com/developers/docs/resources/guild#add-guild-member for details. + /// + /// The oauth2 client. + /// The guild to add the member to. + /// The new nickname. + /// The new roles. + /// Whether this user has to be muted. + /// Whether this user has to be deafened. + public async Task OAuth2AddToGuildAsync(DiscordOAuth2Client oauth2Client, DiscordGuild guild, string? nickname = null, IEnumerable? roles = null, bool? muted = null, bool? deafened = null) + => await oauth2Client.AddCurrentUserToGuildAsync(this.AccessToken, this.Id, guild.Id, nickname, roles, muted, deafened); + /// /// Gets the current user's oauth2 object. /// Requires a set in . @@ -473,7 +499,7 @@ public Task UnbanAsync(DiscordGuild guild, string? reason = null) /// Gets this user's presence. /// [JsonIgnore] - public DiscordPresence Presence + public DiscordPresence? Presence => this.Discord is DiscordClient dc && dc.Presences.TryGetValue(this.Id, out var presence) ? presence : null; /// diff --git a/DisCatSharp/Net/Abstractions/Rest/RestGuildPayloads.cs b/DisCatSharp/Net/Abstractions/Rest/RestGuildPayloads.cs index 5ed0f55116..7e996f74c5 100644 --- a/DisCatSharp/Net/Abstractions/Rest/RestGuildPayloads.cs +++ b/DisCatSharp/Net/Abstractions/Rest/RestGuildPayloads.cs @@ -421,13 +421,13 @@ internal sealed class RestGuildMemberAddPayload : IOAuth2Payload /// Gets or sets the nickname. /// [JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)] - public string Nickname { get; set; } + public string? Nickname { get; set; } /// /// Gets or sets the roles. /// [JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)] - public IEnumerable Roles { get; set; } + public IEnumerable? Roles { get; set; } /// /// Gets or sets a value indicating whether mute. diff --git a/DisCatSharp/Net/Models/BaseEditModel.cs b/DisCatSharp/Net/Models/BaseEditModel.cs index fe34be4d46..3b5860310f 100644 --- a/DisCatSharp/Net/Models/BaseEditModel.cs +++ b/DisCatSharp/Net/Models/BaseEditModel.cs @@ -8,5 +8,5 @@ public class BaseEditModel /// /// Reason given in audit logs /// - public string AuditLogReason { internal get; set; } + public string? AuditLogReason { internal get; set; } } diff --git a/DisCatSharp/Net/Rest/DiscordApiClient.cs b/DisCatSharp/Net/Rest/DiscordApiClient.cs index db031457cc..26939036f5 100644 --- a/DisCatSharp/Net/Rest/DiscordApiClient.cs +++ b/DisCatSharp/Net/Rest/DiscordApiClient.cs @@ -1106,20 +1106,20 @@ internal Task LeaveGuildAsync(ulong guildId) /// /// Adds the guild member async. /// - /// The guild_id. - /// The user_id. - /// The access_token. - /// The nick. + /// The guild id. + /// The user id. + /// The user's access token. + /// The nickname. /// The roles. /// If true, muted. /// If true, deafened. - internal async Task AddGuildMemberAsync(ulong guildId, ulong userId, string accessToken, string nick, IEnumerable roles, bool muted, bool deafened) + internal async Task AddGuildMemberAsync(ulong guildId, ulong userId, string accessToken, string? nickname = null, IEnumerable? roles = null, bool? muted = null, bool? deafened = null) { var pld = new RestGuildMemberAddPayload { AccessToken = accessToken, - Nickname = nick ?? "", - Roles = roles ?? new List(), + Nickname = nickname, + Roles = roles, Deaf = deafened, Mute = muted }; @@ -1174,7 +1174,7 @@ internal async Task> ListGuildMembersAsync(ulong /// The user_id. /// The role_id. /// The reason. - internal Task AddGuildMemberRoleAsync(ulong guildId, ulong userId, ulong roleId, string reason) + internal Task AddGuildMemberRoleAsync(ulong guildId, ulong userId, ulong roleId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -1199,7 +1199,7 @@ internal Task AddGuildMemberRoleAsync(ulong guildId, ulong userId, ulong roleId, /// The user_id. /// The role_id. /// The reason. - internal Task RemoveGuildMemberRoleAsync(ulong guildId, ulong userId, ulong roleId, string reason) + internal Task RemoveGuildMemberRoleAsync(ulong guildId, ulong userId, ulong roleId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -1223,7 +1223,7 @@ internal Task RemoveGuildMemberRoleAsync(ulong guildId, ulong userId, ulong role /// The guild_id. /// The pld. /// The reason. - internal Task ModifyGuildChannelPositionAsync(ulong guildId, IEnumerable pld, string reason) + internal Task ModifyGuildChannelPositionAsync(ulong guildId, IEnumerable pld, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -1245,7 +1245,7 @@ internal Task ModifyGuildChannelPositionAsync(ulong guildId, IEnumerableThe guild_id. /// The pld. /// The reason. - internal Task ModifyGuildChannelParentAsync(ulong guildId, IEnumerable pld, string reason) + internal Task ModifyGuildChannelParentAsync(ulong guildId, IEnumerable pld, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -1267,7 +1267,7 @@ internal Task ModifyGuildChannelParentAsync(ulong guildId, IEnumerableThe guild_id. /// The pld. /// The reason. - internal Task DetachGuildChannelParentAsync(ulong guildId, IEnumerable pld, string reason) + internal Task DetachGuildChannelParentAsync(ulong guildId, IEnumerable pld, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -1289,7 +1289,7 @@ internal Task DetachGuildChannelParentAsync(ulong guildId, IEnumerableThe guild_id. /// The pld. /// The reason. - internal Task ModifyGuildRolePositionAsync(ulong guildId, IEnumerable pld, string reason) + internal Task ModifyGuildRolePositionAsync(ulong guildId, IEnumerable pld, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -1430,7 +1430,7 @@ internal async Task GetGuildWidgetSettingsAsync(ulong gui /// If true, is enabled. /// The channel id. /// The reason. - internal async Task ModifyGuildWidgetSettingsAsync(ulong guildId, bool? isEnabled, ulong? channelId, string reason) + internal async Task ModifyGuildWidgetSettingsAsync(ulong guildId, bool? isEnabled, ulong? channelId, string? reason) { var pld = new RestGuildWidgetSettingsPayload { @@ -1798,7 +1798,7 @@ internal async Task CreateAutomodRuleAsync( bool enabled = false, IEnumerable exemptRoles = null, IEnumerable exemptChannels = null, - string reason = null + string? reason = null ) { var route = $"{Endpoints.GUILDS}/:guild_id/auto-moderation/rules"; @@ -1862,7 +1862,7 @@ internal async Task ModifyAutomodRuleAsync( Optional enabled, Optional> exemptRoles, Optional> exemptChannels, - string reason = null + string? reason = null ) { var pld = new RestAutomodRuleModifyPayload @@ -1910,7 +1910,7 @@ internal async Task ModifyAutomodRuleAsync( /// The rule id. /// The reason for this deletion. /// The deleted auto mod rule. - internal async Task DeleteAutomodRuleAsync(ulong guildId, ulong ruleId, string reason = null) + internal async Task DeleteAutomodRuleAsync(ulong guildId, ulong ruleId, string? reason = null) { var route = $"{Endpoints.GUILDS}/:guild_id/auto-moderation/rules/:rule_id"; var bucket = this.Rest.GetBucket(RestRequestMethod.DELETE, route, new @@ -1944,7 +1944,7 @@ internal async Task DeleteAutomodRuleAsync(ulong guildId, ulong rul /// /// Creates a scheduled event. /// - internal async Task CreateGuildScheduledEventAsync(ulong guildId, ulong? channelId, DiscordScheduledEventEntityMetadata metadata, string name, DateTimeOffset scheduledStartTime, DateTimeOffset? scheduledEndTime, string description, ScheduledEventEntityType type, Optional coverb64, string reason = null) + internal async Task CreateGuildScheduledEventAsync(ulong guildId, ulong? channelId, DiscordScheduledEventEntityMetadata metadata, string name, DateTimeOffset scheduledStartTime, DateTimeOffset? scheduledEndTime, string description, ScheduledEventEntityType type, Optional coverb64, string? reason = null) { var pld = new RestGuildScheduledEventCreatePayload { @@ -2000,7 +2000,7 @@ internal async Task ModifyGuildScheduledEventAsync( Optional type, Optional status, Optional coverb64, - string reason = null + string? reason = null ) { var pld = new RestGuildScheduledEventModifyPayload @@ -2058,7 +2058,7 @@ internal async Task ModifyGuildScheduledEventAsync( /// /// Modifies a scheduled event. /// - internal async Task ModifyGuildScheduledEventStatusAsync(ulong guildId, ulong scheduledEventId, ScheduledEventStatus status, string reason = null) + internal async Task ModifyGuildScheduledEventStatusAsync(ulong guildId, ulong scheduledEventId, ScheduledEventStatus status, string? reason = null) { var pld = new RestGuildScheduledEventModifyPayload { @@ -2201,7 +2201,7 @@ internal async Task> ListGuild /// The guild_id. /// The scheduled event id. /// The reason. - internal Task DeleteGuildScheduledEventAsync(ulong guildId, ulong scheduledEventId, string reason) + internal Task DeleteGuildScheduledEventAsync(ulong guildId, ulong scheduledEventId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -2304,7 +2304,7 @@ internal async Task> GetGu /// The default auto archive duration. /// The channel flags. /// The reason. - internal async Task CreateGuildChannelAsync(ulong guildId, string name, ChannelType type, ulong? parent, Optional topic, int? bitrate, int? userLimit, IEnumerable overwrites, bool? nsfw, Optional perUserRateLimit, VideoQualityMode? qualityMode, ThreadAutoArchiveDuration? defaultAutoArchiveDuration, Optional flags, string reason) + internal async Task CreateGuildChannelAsync(ulong guildId, string name, ChannelType type, ulong? parent, Optional topic, int? bitrate, int? userLimit, IEnumerable overwrites, bool? nsfw, Optional perUserRateLimit, VideoQualityMode? qualityMode, ThreadAutoArchiveDuration? defaultAutoArchiveDuration, Optional flags, string? reason) { var restOverwrites = new List(); if (overwrites != null) @@ -2377,7 +2377,7 @@ internal async Task CreateForumChannelAsync( ThreadAutoArchiveDuration? defaultAutoArchiveDuration, IEnumerable permissionOverwrites, Optional flags, - string reason + string? reason ) { List restoverwrites = null; @@ -2459,7 +2459,7 @@ internal Task ModifyChannelAsync( Optional type, IEnumerable permissionOverwrites, Optional flags, - string reason + string? reason ) { List restoverwrites = null; @@ -2537,7 +2537,7 @@ internal async Task ModifyForumChannelAsync( Optional defaultAutoArchiveDuration, IEnumerable permissionOverwrites, Optional flags, - string reason + string? reason ) { List restoverwrites = null; @@ -2611,7 +2611,7 @@ internal async Task GetChannelAsync(ulong channelId) /// /// The channel_id. /// The reason. - internal Task DeleteChannelAsync(ulong channelId, string reason) + internal Task DeleteChannelAsync(ulong channelId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -2878,7 +2878,7 @@ internal Task ModifyVoiceChannelStatusAsync(ulong channelId, string? status) /// Whether everyone should be notified about the stage. /// The associated scheduled event id. /// The reason. - internal async Task CreateStageInstanceAsync(ulong channelId, string topic, bool sendStartNotification, ulong? scheduledEventId = null, string reason = null) + internal async Task CreateStageInstanceAsync(ulong channelId, string topic, bool sendStartNotification, ulong? scheduledEventId = null, string? reason = null) { var pld = new RestStageInstanceCreatePayload { @@ -2929,7 +2929,7 @@ internal async Task GetStageInstanceAsync(ulong channelId) /// The channel_id. /// The topic. /// The reason. - internal Task ModifyStageInstanceAsync(ulong channelId, Optional topic, string reason) + internal Task ModifyStageInstanceAsync(ulong channelId, Optional topic, string? reason) { var pld = new RestStageInstanceModifyPayload { @@ -2954,7 +2954,7 @@ internal Task ModifyStageInstanceAsync(ulong channelId, Optional topic, /// /// The channel_id. /// The reason. - internal Task DeleteStageInstanceAsync(ulong channelId, string reason) + internal Task DeleteStageInstanceAsync(ulong channelId, string? reason) { var route = $"{Endpoints.STAGE_INSTANCES}/:channel_id"; var bucket = this.Rest.GetBucket(RestRequestMethod.DELETE, route, new @@ -3130,7 +3130,7 @@ internal async Task EditMessageAsync(ulong channelId, ulong mess /// The channel_id. /// The message_id. /// The reason. - internal Task DeleteMessageAsync(ulong channelId, ulong messageId, string reason) + internal Task DeleteMessageAsync(ulong channelId, ulong messageId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -3153,7 +3153,7 @@ internal Task DeleteMessageAsync(ulong channelId, ulong messageId, string reason /// The channel_id. /// The message_ids. /// The reason. - internal Task DeleteMessagesAsync(ulong channelId, IEnumerable messageIds, string reason) + internal Task DeleteMessagesAsync(ulong channelId, IEnumerable messageIds, string? reason) { var pld = new RestChannelMessageBulkDeletePayload { @@ -3210,7 +3210,7 @@ internal async Task> GetChannelInvitesAsync(ulong c /// If true, temporary. /// If true, unique. /// The reason. - internal async Task CreateChannelInviteAsync(ulong channelId, int maxAge, int maxUses, TargetType? targetType, ulong? targetApplicationId, ulong? targetUser, bool temporary, bool unique, string reason) + internal async Task CreateChannelInviteAsync(ulong channelId, int maxAge, int maxUses, TargetType? targetType, ulong? targetApplicationId, ulong? targetUser, bool temporary, bool unique, string? reason) { var pld = new RestChannelInviteCreatePayload { @@ -3248,7 +3248,7 @@ internal async Task CreateChannelInviteAsync(ulong channelId, int /// The channel_id. /// The overwrite_id. /// The reason. - internal Task DeleteChannelPermissionAsync(ulong channelId, ulong overwriteId, string reason) + internal Task DeleteChannelPermissionAsync(ulong channelId, ulong overwriteId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -3274,7 +3274,7 @@ internal Task DeleteChannelPermissionAsync(ulong channelId, ulong overwriteId, s /// The deny. /// The type. /// The reason. - internal Task EditChannelPermissionsAsync(ulong channelId, ulong overwriteId, Permissions allow, Permissions deny, string type, string reason) + internal Task EditChannelPermissionsAsync(ulong channelId, ulong overwriteId, Permissions allow, Permissions deny, string type, string? reason) { var pld = new RestChannelPermissionEditPayload { @@ -3612,7 +3612,7 @@ internal async Task GetGuildMemberAsync(ulong guildId, ulong user /// The guild_id. /// The user_id. /// The reason. - internal Task RemoveGuildMemberAsync(ulong guildId, ulong userId, string reason) + internal Task RemoveGuildMemberAsync(ulong guildId, ulong userId, string? reason) { var urlParams = new Dictionary(); if (reason != null) @@ -3710,7 +3710,7 @@ internal Task ModifyGuildMemberAsync( Optional voiceChannelId, Optional verify, MemberFlags flags, - string reason + string? reason ) { var headers = Utilities.GetBaseHeaders(); @@ -3749,7 +3749,7 @@ string reason /// The user_id. /// Datetime offset. /// The reason. - internal Task ModifyTimeoutAsync(ulong guildId, ulong userId, DateTimeOffset? until, string reason) + internal Task ModifyTimeoutAsync(ulong guildId, ulong userId, DateTimeOffset? until, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -3777,7 +3777,7 @@ internal Task ModifyTimeoutAsync(ulong guildId, ulong userId, DateTimeOffset? un /// The guild_id. /// The nick. /// The reason. - internal Task ModifyCurrentMemberNicknameAsync(ulong guildId, string nick, string reason) + internal Task ModifyCurrentMemberNicknameAsync(ulong guildId, string nick, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -3839,7 +3839,7 @@ internal async Task> GetGuildRolesAsync(ulong guildId /// The icon. /// The unicode emoji icon. /// The reason. - internal async Task ModifyGuildRoleAsync(ulong guildId, ulong roleId, string name, Permissions? permissions, int? color, bool? hoist, bool? mentionable, Optional iconb64, Optional emoji, string reason) + internal async Task ModifyGuildRoleAsync(ulong guildId, ulong roleId, string name, Permissions? permissions, int? color, bool? hoist, bool? mentionable, Optional iconb64, Optional emoji, string? reason) { var pld = new RestGuildRolePayload { @@ -3886,7 +3886,7 @@ internal async Task ModifyGuildRoleAsync(ulong guildId, ulong roleI /// The guild_id. /// The role_id. /// The reason. - internal Task DeleteRoleAsync(ulong guildId, ulong roleId, string reason) + internal Task DeleteRoleAsync(ulong guildId, ulong roleId, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -3913,7 +3913,7 @@ internal Task DeleteRoleAsync(ulong guildId, ulong roleId, string reason) /// If true, hoist. /// If true, mentionable. /// The reason. - internal async Task CreateGuildRoleAsync(ulong guildId, string name, Permissions? permissions, int? color, bool? hoist, bool? mentionable, string reason) + internal async Task CreateGuildRoleAsync(ulong guildId, string name, Permissions? permissions, int? color, bool? hoist, bool? mentionable, string? reason) { var pld = new RestGuildRolePayload { @@ -3988,7 +3988,7 @@ internal async Task GetGuildPruneCountAsync(ulong guildId, int days, IEnume /// If true, compute_prune_count. /// The include_roles. /// The reason. - internal async Task BeginGuildPruneAsync(ulong guildId, int days, bool computePruneCount, IEnumerable includeRoles, string reason) + internal async Task BeginGuildPruneAsync(ulong guildId, int days, bool computePruneCount, IEnumerable includeRoles, string? reason) { if (days < 0 || days > 30) throw new ArgumentException("Prune inactivity days must be a number between 0 and 30.", nameof(days)); @@ -4256,7 +4256,7 @@ internal async Task GetInviteAsync(string inviteCode, bool? withC /// /// The invite_code. /// The reason. - internal async Task DeleteInviteAsync(string inviteCode, string reason) + internal async Task DeleteInviteAsync(string inviteCode, string? reason) { var headers = Utilities.GetBaseHeaders(); if (!string.IsNullOrWhiteSpace(reason)) @@ -4397,7 +4397,7 @@ internal async Task> ListVoiceRegionsAsync() /// The name. /// The base64_avatar. /// The reason. - internal async Task CreateWebhookAsync(ulong channelId, string name, Optional base64Avatar, string reason) + internal async Task CreateWebhookAsync(ulong channelId, string name, Optional base64Avatar, string? reason) { var pld = new RestWebhookPayload { @@ -4525,7 +4525,7 @@ internal async Task GetWebhookWithTokenAsync(ulong webhookId, st /// The name. /// The base64_avatar. /// The reason. - internal async Task ModifyWebhookAsync(ulong webhookId, ulong channelId, string name, Optional base64Avatar, string reason) + internal async Task ModifyWebhookAsync(ulong webhookId, ulong channelId, string name, Optional base64Avatar, string? reason) { var pld = new RestWebhookPayload { @@ -4562,7 +4562,7 @@ internal async Task ModifyWebhookAsync(ulong webhookId, ulong ch /// The base64_avatar. /// The webhook_token. /// The reason. - internal async Task ModifyWebhookAsync(ulong webhookId, string name, string base64Avatar, string webhookToken, string reason) + internal async Task ModifyWebhookAsync(ulong webhookId, string name, string base64Avatar, string webhookToken, string? reason) { var pld = new RestWebhookPayload { @@ -4595,7 +4595,7 @@ internal async Task ModifyWebhookAsync(ulong webhookId, string n /// /// The webhook_id. /// The reason. - internal Task DeleteWebhookAsync(ulong webhookId, string reason) + internal Task DeleteWebhookAsync(ulong webhookId, string? reason) { var headers = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) @@ -4617,7 +4617,7 @@ internal Task DeleteWebhookAsync(ulong webhookId, string reason) /// The webhook_id. /// The webhook_token. /// The reason. - internal Task DeleteWebhookAsync(ulong webhookId, string webhookToken, string reason) + internal Task DeleteWebhookAsync(ulong webhookId, string webhookToken, string? reason) { var headers = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) @@ -5032,7 +5032,7 @@ internal Task DeleteOwnReactionAsync(ulong channelId, ulong messageId, string em /// The user_id. /// The emoji. /// The reason. - internal Task DeleteUserReactionAsync(ulong channelId, ulong messageId, ulong userId, string emoji, string reason) + internal Task DeleteUserReactionAsync(ulong channelId, ulong messageId, ulong userId, string emoji, string? reason) { var headers = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) @@ -5107,7 +5107,7 @@ internal async Task> GetReactionsAsync(ulong channelI /// The channel_id. /// The message_id. /// The reason. - internal Task DeleteAllReactionsAsync(ulong channelId, ulong messageId, string reason) + internal Task DeleteAllReactionsAsync(ulong channelId, ulong messageId, string? reason) { var headers = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) @@ -5511,7 +5511,7 @@ internal async Task GetPrivateArchivedThreadsAsync(ulong ch /// The tags to add on creation. /// Whether the post is pinned. /// The reason for the modification. - internal Task ModifyThreadAsync(ulong threadId, ChannelType parentType, string name, Optional locked, Optional archived, Optional perUserRateLimit, Optional autoArchiveDuration, Optional invitable, Optional> appliedTags, Optional pinned, string reason) + internal Task ModifyThreadAsync(ulong threadId, ChannelType parentType, string name, Optional locked, Optional archived, Optional perUserRateLimit, Optional autoArchiveDuration, Optional invitable, Optional> appliedTags, Optional pinned, string? reason) { var pld = new RestThreadChannelModifyPayload { @@ -5638,7 +5638,7 @@ internal async Task GetGuildEmojiAsync(ulong guildId, ulong e /// The imageb64. /// The roles. /// The reason. - internal async Task CreateGuildEmojiAsync(ulong guildId, string name, string imageb64, IEnumerable roles, string reason) + internal async Task CreateGuildEmojiAsync(ulong guildId, string name, string imageb64, IEnumerable roles, string? reason) { var pld = new RestGuildEmojiCreatePayload { @@ -5682,7 +5682,7 @@ internal async Task CreateGuildEmojiAsync(ulong guildId, stri /// The name. /// The roles. /// The reason. - internal async Task ModifyGuildEmojiAsync(ulong guildId, ulong emojiId, string name, IEnumerable roles, string reason) + internal async Task ModifyGuildEmojiAsync(ulong guildId, ulong emojiId, string name, IEnumerable roles, string? reason) { var pld = new RestGuildEmojiModifyPayload { @@ -5723,7 +5723,7 @@ internal async Task ModifyGuildEmojiAsync(ulong guildId, ulon /// The guild_id. /// The emoji_id. /// The reason. - internal Task DeleteGuildEmojiAsync(ulong guildId, ulong emojiId, string reason) + internal Task DeleteGuildEmojiAsync(ulong guildId, ulong emojiId, string? reason) { var headers = new Dictionary(); if (!string.IsNullOrWhiteSpace(reason)) @@ -5829,7 +5829,7 @@ internal async Task GetGuildStickerAsync(ulong guildId, ulong st /// The tags. /// The file. /// The reason. - internal async Task CreateGuildStickerAsync(ulong guildId, string name, string description, string tags, DiscordMessageFile file, string reason) + internal async Task CreateGuildStickerAsync(ulong guildId, string name, string description, string tags, DiscordMessageFile file, string? reason) { var route = $"{Endpoints.GUILDS}/:guild_id{Endpoints.STICKERS}"; var bucket = this.Rest.GetBucket(RestRequestMethod.POST, route, new @@ -5857,7 +5857,7 @@ internal async Task CreateGuildStickerAsync(ulong guildId, strin /// The description. /// The tags. /// The reason. - internal async Task ModifyGuildStickerAsync(ulong guildId, ulong stickerId, Optional name, Optional description, Optional tags, string reason) + internal async Task ModifyGuildStickerAsync(ulong guildId, ulong stickerId, Optional name, Optional description, Optional tags, string? reason) { var route = $"{Endpoints.GUILDS}/:guild_id{Endpoints.STICKERS}/:sticker_id"; var bucket = this.Rest.GetBucket(RestRequestMethod.PATCH, route, new @@ -5893,7 +5893,7 @@ internal async Task ModifyGuildStickerAsync(ulong guildId, ulong /// The guild id. /// The sticker id. /// The reason. - internal async Task DeleteGuildStickerAsync(ulong guildId, ulong stickerId, string reason) + internal async Task DeleteGuildStickerAsync(ulong guildId, ulong stickerId, string? reason) { var route = $"{Endpoints.GUILDS}/:guild_id{Endpoints.STICKERS}/:sticker_id"; var bucket = this.Rest.GetBucket(RestRequestMethod.DELETE, route, new