diff --git a/DisCatSharp/Entities/Guild/DiscordMember.cs b/DisCatSharp/Entities/Guild/DiscordMember.cs
index b4a598998..5b8f802d7 100644
--- a/DisCatSharp/Entities/Guild/DiscordMember.cs
+++ b/DisCatSharp/Entities/Guild/DiscordMember.cs
@@ -1,791 +1,790 @@
// This file is part of the DisCatSharp project, based off DSharpPlus.
//
// Copyright (c) 2021-2022 AITSYS
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using DisCatSharp.Enums;
using DisCatSharp.Net;
using DisCatSharp.Net.Abstractions;
using DisCatSharp.Net.Models;
using Newtonsoft.Json;
namespace DisCatSharp.Entities;
///
/// Represents a Discord guild member.
///
public class DiscordMember : DiscordUser, IEquatable
{
///
/// Initializes a new instance of the class.
///
internal DiscordMember()
{
this._roleIdsLazy = new Lazy>(() => new ReadOnlyCollection(this.RoleIdsInternal));
}
///
/// Initializes a new instance of the class.
///
/// The user.
internal DiscordMember(DiscordUser user)
{
this.Discord = user.Discord;
this.Id = user.Id;
this.RoleIdsInternal = new List();
this._roleIdsLazy = new Lazy>(() => new ReadOnlyCollection(this.RoleIdsInternal));
}
///
/// Initializes a new instance of the class.
///
/// The mbr.
internal DiscordMember(TransportMember mbr)
{
this.Id = mbr.User.Id;
this.IsDeafened = mbr.IsDeafened;
this.IsMuted = mbr.IsMuted;
this.JoinedAt = mbr.JoinedAt;
this.Nickname = mbr.Nickname;
this.PremiumSince = mbr.PremiumSince;
this.IsPending = mbr.IsPending;
this.GuildAvatarHash = mbr.GuildAvatarHash;
this.GuildBannerHash = mbr.GuildBannerHash;
this.GuildBio = mbr.GuildBio;
this.GuildPronouns = mbr.GuildPronouns;
this.CommunicationDisabledUntil = mbr.CommunicationDisabledUntil;
this.AvatarHashInternal = mbr.AvatarHash;
this.RoleIdsInternal = mbr.Roles ?? new List();
this._roleIdsLazy = new Lazy>(() => new ReadOnlyCollection(this.RoleIdsInternal));
this.MemberFlags = mbr.MemberFlags;
}
///
/// Gets the members avatar hash.
///
[JsonProperty("avatar", NullValueHandling = NullValueHandling.Ignore)]
public virtual string GuildAvatarHash { get; internal set; }
///
/// Gets the members avatar URL.
///
[JsonIgnore]
public string GuildAvatarUrl
=> string.IsNullOrWhiteSpace(this.GuildAvatarHash) ? this.User.AvatarUrl : $"{DiscordDomain.GetDomain(CoreDomain.DiscordCdn).Url}{Endpoints.GUILDS}/{this.GuildId.ToString(CultureInfo.InvariantCulture)}{Endpoints.USERS}/{this.Id.ToString(CultureInfo.InvariantCulture)}{Endpoints.AVATARS}/{this.GuildAvatarHash}.{(this.GuildAvatarHash.StartsWith("a_") ? "gif" : "png")}?size=1024";
///
/// Gets the members banner hash.
///
[JsonProperty("banner", NullValueHandling = NullValueHandling.Ignore)]
public virtual string GuildBannerHash { get; internal set; }
///
/// Gets the members banner URL.
///
[JsonIgnore]
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_") ? "gif" : "png")}?size=1024";
///
/// The color of this member's banner. Mutually exclusive with .
///
[JsonIgnore]
public override DiscordColor? BannerColor => this.User.BannerColor;
///
/// Gets this member's nickname.
///
[JsonProperty("nick", NullValueHandling = NullValueHandling.Ignore)]
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; }
///
/// Gets the members's pronouns.
///
[JsonProperty("pronouns", NullValueHandling = NullValueHandling.Ignore)]
public string GuildPronouns { get; internal set; }
///
/// Gets the members flags.
///
[JsonProperty("flags", NullValueHandling = NullValueHandling.Ignore)]
public MemberFlags MemberFlags { get; internal set; }
[JsonIgnore]
internal string AvatarHashInternal;
///
/// Gets this member's display name.
///
[JsonIgnore]
public string DisplayName
=> this.Nickname ?? this.Username;
///
/// List of role ids
///
[JsonIgnore]
internal IReadOnlyList RoleIds
=> this._roleIdsLazy.Value;
[JsonProperty("roles", NullValueHandling = NullValueHandling.Ignore)]
internal List RoleIdsInternal;
[JsonIgnore]
private readonly Lazy> _roleIdsLazy;
///
/// Gets the list of roles associated with this member.
///
[JsonIgnore]
public IEnumerable Roles
=> this.RoleIds.Select(id => this.Guild.GetRole(id)).Where(x => x != null);
///
/// Gets the color associated with this user's top color-giving role, otherwise 0 (no color).
///
[JsonIgnore]
public DiscordColor Color
{
get
{
var role = this.Roles.OrderByDescending(xr => xr.Position).FirstOrDefault(xr => xr.Color.Value != 0);
return role != null ? role.Color : new DiscordColor();
}
}
///
/// Date the user joined the guild
///
[JsonProperty("joined_at", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset JoinedAt { get; internal set; }
///
/// Date the user started boosting this server
///
[JsonProperty("premium_since", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? PremiumSince { get; internal set; }
///
/// Date until the can communicate again.
///
[JsonProperty("communication_disabled_until", NullValueHandling = NullValueHandling.Include)]
public DateTime? CommunicationDisabledUntil { get; internal set; }
///
/// If the user is deafened
///
[JsonProperty("is_deafened", NullValueHandling = NullValueHandling.Ignore)]
public bool IsDeafened { get; internal set; }
///
/// If the user is muted
///
[JsonProperty("is_muted", NullValueHandling = NullValueHandling.Ignore)]
public bool IsMuted { get; internal set; }
///
/// Whether the user has not passed the guild's Membership Screening requirements yet.
///
[JsonProperty("pending", NullValueHandling = NullValueHandling.Ignore)]
public bool? IsPending { get; internal set; }
///
/// Gets this member's voice state.
///
[JsonIgnore]
public DiscordVoiceState VoiceState
=> this.Discord.Guilds[this.GuildId].VoiceStates.TryGetValue(this.Id, out var voiceState) ? voiceState : null;
[JsonIgnore]
internal ulong GuildId = 0;
///
/// Gets the guild of which this member is a part of.
///
[JsonIgnore]
public DiscordGuild Guild
=> this.Discord.Guilds[this.GuildId];
///
/// Gets whether this member is the Guild owner.
///
[JsonIgnore]
public bool IsOwner
=> this.Id == this.Guild.OwnerId;
///
/// Gets the member's position in the role hierarchy, which is the member's highest role's position. Returns for the guild's owner.
///
[JsonIgnore]
public int Hierarchy
=> this.IsOwner ? int.MaxValue : this.RoleIds.Count == 0 ? 0 : this.Roles.Max(x => x.Position);
///
/// Gets the permissions for the current member.
///
[JsonIgnore]
public Permissions Permissions => this.GetPermissions();
#region Overridden user properties
///
/// Gets the user.
///
[JsonIgnore]
internal DiscordUser User
=> this.Discord.UserCache[this.Id];
///
/// Gets this member's username.
///
[JsonIgnore]
public override string Username
{
get => this.User.Username;
internal set => this.User.Username = value;
}
///
/// Gets the member's 4-digit discriminator.
///
[JsonIgnore]
public override string Discriminator
{
get => this.User.Discriminator;
internal set => this.User.Discriminator = value;
}
///
/// Gets the member's avatar hash.
///
[JsonIgnore]
public override string AvatarHash
{
get => this.User.AvatarHash;
internal set => this.User.AvatarHash = value;
}
///
/// Gets the member's banner hash.
///
[JsonIgnore]
public override string BannerHash
{
get => this.User.BannerHash;
internal set => this.User.BannerHash = value;
}
///
/// Gets whether the member is a bot.
///
[JsonIgnore]
public override bool IsBot
{
get => this.User.IsBot;
internal set => this.User.IsBot = value;
}
///
/// Gets the member's email address.
/// This is only present in OAuth.
///
[JsonIgnore]
public override string Email
{
get => this.User.Email;
internal set => this.User.Email = value;
}
///
/// Gets whether the member has multi-factor authentication enabled.
///
[JsonIgnore]
public override bool? MfaEnabled
{
get => this.User.MfaEnabled;
internal set => this.User.MfaEnabled = value;
}
///
/// Gets whether the member is verified.
/// This is only present in OAuth.
///
[JsonIgnore]
public override bool? Verified
{
get => this.User.Verified;
internal set => this.User.Verified = value;
}
///
/// Gets the member's chosen language
///
[JsonIgnore]
public override string Locale
{
get => this.User.Locale;
internal set => this.User.Locale = value;
}
///
/// Gets the user's flags.
///
[JsonIgnore]
public override UserFlags? OAuthFlags
{
get => this.User.OAuthFlags;
internal set => this.User.OAuthFlags = value;
}
///
/// Gets the member's flags for OAuth.
///
[JsonIgnore]
public override UserFlags? Flags
{
get => this.User.Flags;
internal set => this.User.Flags = value;
}
#endregion
///
/// Creates a direct message channel to this member.
///
/// Direct message channel to this member.
/// Thrown when the member has the bot blocked, the member is no longer in the guild, or if the member has Allow DM from server members off.
/// 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 CreateDmChannelAsync()
=> this.Discord.ApiClient.CreateDmAsync(this.Id);
///
/// Sends a direct message to this member. Creates a direct message channel if one does not exist already.
///
/// Content of the message to send.
/// The sent message.
/// Thrown when the member has the bot blocked, the member is no longer in the guild, or if the member has Allow DM from server members off.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task SendMessageAsync(string content)
{
if (this.IsBot && this.Discord.CurrentUser.IsBot)
throw new ArgumentException("Bots cannot DM each other.");
var chn = await this.CreateDmChannelAsync().ConfigureAwait(false);
return await chn.SendMessageAsync(content).ConfigureAwait(false);
}
///
/// Sends a direct message to this member. Creates a direct message channel if one does not exist already.
///
/// Embed to attach to the message.
/// The sent message.
/// Thrown when the member has the bot blocked, the member is no longer in the guild, or if the member has Allow DM from server members off.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task SendMessageAsync(DiscordEmbed embed)
{
if (this.IsBot && this.Discord.CurrentUser.IsBot)
throw new ArgumentException("Bots cannot DM each other.");
var chn = await this.CreateDmChannelAsync().ConfigureAwait(false);
return await chn.SendMessageAsync(embed).ConfigureAwait(false);
}
///
/// Sends a direct message to this member. Creates a direct message channel if one does not exist already.
///
/// Content of the message to send.
/// Embed to attach to the message.
/// The sent message.
/// Thrown when the member has the bot blocked, the member is no longer in the guild, or if the member has Allow DM from server members off.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task SendMessageAsync(string content, DiscordEmbed embed)
{
if (this.IsBot && this.Discord.CurrentUser.IsBot)
throw new ArgumentException("Bots cannot DM each other.");
var chn = await this.CreateDmChannelAsync().ConfigureAwait(false);
return await chn.SendMessageAsync(content, embed).ConfigureAwait(false);
}
///
/// Sends a direct message to this member. Creates a direct message channel if one does not exist already.
///
/// Builder to with the message.
/// The sent message.
/// Thrown when the member has the bot blocked, the member is no longer in the guild, or if the member has Allow DM from server members off.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task SendMessageAsync(DiscordMessageBuilder message)
{
if (this.IsBot && this.Discord.CurrentUser.IsBot)
throw new ArgumentException("Bots cannot DM each other.");
var chn = await this.CreateDmChannelAsync().ConfigureAwait(false);
return await chn.SendMessageAsync(message).ConfigureAwait(false);
}
///
/// Sets this member's voice mute status.
///
/// Whether the member is to be muted.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.Discord.ApiClient.ModifyGuildMemberAsync(this.GuildId, this.Id, default, default, mute, default, default, reason);
///
/// Sets this member's voice deaf status.
///
/// Whether the member is to be deafened.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.Discord.ApiClient.ModifyGuildMemberAsync(this.GuildId, this.Id, default, default, default, deaf, default, reason);
///
/// Modifies this member.
///
/// Action to perform on this member.
/// Thrown when the client does not have the permission.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
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)
throw new ArgumentException("Given channel is not a voice or stage channel.", nameof(action));
if (mdl.Nickname.HasValue && this.Discord.CurrentUser.Id == this.Id)
{
await this.Discord.ApiClient.ModifyCurrentMemberNicknameAsync(this.Guild.Id, mdl.Nickname.Value,
mdl.AuditLogReason).ConfigureAwait(false);
await this.Discord.ApiClient.ModifyGuildMemberAsync(this.Guild.Id, this.Id, Optional.None,
mdl.Roles.Map(e => e.Select(xr => xr.Id)), mdl.Muted, mdl.Deafened,
mdl.VoiceChannel.Map(e => e?.Id), mdl.AuditLogReason).ConfigureAwait(false);
}
else
{
await this.Discord.ApiClient.ModifyGuildMemberAsync(this.Guild.Id, this.Id, mdl.Nickname,
mdl.Roles.Map(e => e.Select(xr => xr.Id)), mdl.Muted, mdl.Deafened,
mdl.VoiceChannel.Map(e => e?.Id), mdl.AuditLogReason).ConfigureAwait(false);
}
}
///
/// Adds a timeout to a member.
///
/// The datetime offset to time out the user. Up to 28 days.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> 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);
///
/// Adds a timeout to a member.
///
/// The timespan to time out the user. Up to 28 days.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.TimeoutAsync(DateTimeOffset.UtcNow + until, reason);
///
/// Adds a timeout to a member.
///
/// The datetime to time out the user. Up to 28 days.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.TimeoutAsync(until.ToUniversalTime() - DateTime.UtcNow, reason);
///
/// Removes the timeout from a member.
///
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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 RemoveTimeoutAsync(string reason = null) => this.Discord.ApiClient.ModifyTimeoutAsync(this.Guild.Id, this.Id, null, reason);
///
/// Grants a role to the member.
///
/// Role to grant.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.Discord.ApiClient.AddGuildMemberRoleAsync(this.Guild.Id, this.Id, role.Id, reason);
///
/// Revokes a role from a member.
///
/// Role to revoke.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.Discord.ApiClient.RemoveGuildMemberRoleAsync(this.Guild.Id, this.Id, role.Id, reason);
///
/// Sets the member's roles to ones specified.
///
/// Roles to set.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.Discord.ApiClient.ModifyGuildMemberAsync(this.Guild.Id, this.Id, default,
Optional.Some(roles.Select(xr => xr.Id)), default, default, default, reason);
///
/// Bans this member from their guild.
///
/// How many days to remove messages from.
/// Reason for audit logs.
/// Thrown when the client does not have the permission.
/// 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)
=> this.Guild.BanMemberAsync(this, deleteMessageDays, reason);
///
/// Unbans this member from their guild.
///
/// Thrown when the client does not have the permission.
/// 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) => this.Guild.UnbanMemberAsync(this, reason);
///
/// Kicks this member from their guild.
///
/// Reason for audit logs.
///
- /// [alias="KickAsync"]
/// Thrown when the client does not have the permission.
/// 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)
=> this.Discord.ApiClient.RemoveGuildMemberAsync(this.GuildId, this.Id, reason);
///
/// Moves this member to the specified voice channel
///
///
/// Thrown when the client does not have the permission.
/// 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 PlaceInAsync(DiscordChannel channel)
=> channel.PlaceMemberAsync(this);
///
/// Updates the member's suppress state in a stage channel.
///
/// The channel the member is currently in.
/// Toggles the member's suppress state.
/// Thrown when the channel in not a voice channel.
public async Task UpdateVoiceStateAsync(DiscordChannel channel, bool? suppress)
{
if (channel.Type != ChannelType.Stage)
throw new ArgumentException("Voice state can only be updated in a stage channel.");
await this.Discord.ApiClient.UpdateUserVoiceStateAsync(this.Guild.Id, this.Id, channel.Id, suppress).ConfigureAwait(false);
}
///
/// Makes the user a speaker.
///
/// Thrown when the user is not inside an stage channel.
/// Thrown when the client does not have the permission.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task MakeSpeakerAsync()
{
var vs = this.VoiceState;
if (vs == null || vs.Channel.Type != 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);
}
///
/// Moves the user to audience.
///
/// Thrown when the user is not inside an stage channel.
/// Thrown when the client does not have the permission.
/// Thrown when the member does not exist.
/// Thrown when an invalid parameter was provided.
/// Thrown when Discord is unable to process the request.
public async Task MoveToAudienceAsync()
{
var vs = this.VoiceState;
if (vs == null || vs.Channel.Type != 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);
}
///
/// Calculates permissions in a given channel for this member.
///
/// Channel to calculate permissions for.
/// Calculated permissions for this member in the channel.
public Permissions PermissionsIn(DiscordChannel channel)
=> channel.PermissionsFor(this);
///
/// Get's the current member's roles based on the sum of the permissions of their given roles.
///
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;
// assign permissions from member's roles (in order)
perms |= this.Roles.Aggregate(Permissions.None, (c, role) => c | role.Permissions);
// Administrator grants all permissions and cannot be overridden
return (perms & Permissions.Administrator) == Permissions.Administrator ? PermissionMethods.FullPerms : perms;
}
///
/// Returns a string representation of this member.
///
/// String representation of this member.
public override string ToString()
=> $"Member {this.Id}; {this.Username}#{this.Discriminator} ({this.DisplayName})";
///
/// Checks whether this is equal to another object.
///
/// Object to compare to.
/// Whether the object is equal to this .
public override bool Equals(object obj)
=> this.Equals(obj as DiscordMember);
///
/// Checks whether this is equal to another .
///
/// to compare to.
/// Whether the is equal to this .
public bool Equals(DiscordMember e)
=> e is not null && (ReferenceEquals(this, e) || (this.Id == e.Id && this.GuildId == e.GuildId));
///
/// Gets the hash code for this .
///
/// The hash code for this .
public override int GetHashCode()
{
var hash = 13;
hash = (hash * 7) + this.Id.GetHashCode();
hash = (hash * 7) + this.GuildId.GetHashCode();
return hash;
}
///
/// Gets whether the two objects are equal.
///
/// First member to compare.
/// Second member to compare.
/// Whether the two members are equal.
public static bool operator ==(DiscordMember e1, DiscordMember e2)
{
var o1 = e1 as object;
var o2 = e2 as object;
return (o1 != null || o2 == null) && (o1 == null || o2 != null) && ((o1 == null && o2 == null) || (e1.Id == e2.Id && e1.GuildId == e2.GuildId));
}
///
/// Gets whether the two objects are not equal.
///
/// First member to compare.
/// Second member to compare.
/// Whether the two members are not equal.
public static bool operator !=(DiscordMember e1, DiscordMember e2)
=> !(e1 == e2);
}