using Discord.Audio; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Threading.Tasks; using WidgetModel = Discord.API.GuildWidget; using Model = Discord.API.Guild; using System.IO; namespace Discord.Rest { /// /// Represents a REST-based guild/server. /// [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestGuild : RestEntity, IGuild, IUpdateable { #region RestGuild private ImmutableDictionary _roles; private ImmutableArray _emotes; private ImmutableArray _stickers; /// public string Name { get; private set; } /// public int AFKTimeout { get; private set; } /// public bool IsWidgetEnabled { get; private set; } /// public VerificationLevel VerificationLevel { get; private set; } /// public MfaLevel MfaLevel { get; private set; } /// public DefaultMessageNotifications DefaultMessageNotifications { get; private set; } /// public ExplicitContentFilterLevel ExplicitContentFilter { get; private set; } /// public ulong? AFKChannelId { get; private set; } /// public ulong? WidgetChannelId { get; private set; } /// public ulong? SystemChannelId { get; private set; } /// public ulong? RulesChannelId { get; private set; } /// public ulong? PublicUpdatesChannelId { get; private set; } /// public ulong OwnerId { get; private set; } /// public string VoiceRegionId { get; private set; } /// public string IconId { get; private set; } /// public string SplashId { get; private set; } /// public string DiscoverySplashId { get; private set; } internal bool Available { get; private set; } /// public ulong? ApplicationId { get; private set; } /// public PremiumTier PremiumTier { get; private set; } /// public string BannerId { get; private set; } /// public string VanityURLCode { get; private set; } /// public SystemChannelMessageDeny SystemChannelFlags { get; private set; } /// public string Description { get; private set; } /// public int PremiumSubscriptionCount { get; private set; } /// public string PreferredLocale { get; private set; } /// public int? MaxPresences { get; private set; } /// public int? MaxMembers { get; private set; } /// public int? MaxVideoChannelUsers { get; private set; } /// public int? ApproximateMemberCount { get; private set; } /// public int? ApproximatePresenceCount { get; private set; } /// public int MaxBitrate { get { return PremiumTier switch { PremiumTier.Tier1 => 128000, PremiumTier.Tier2 => 256000, PremiumTier.Tier3 => 384000, _ => 96000, }; } } /// public ulong MaxUploadLimit => GuildHelper.GetUploadLimit(this); /// public NsfwLevel NsfwLevel { get; private set; } /// public bool IsBoostProgressBarEnabled { get; private set; } /// public CultureInfo PreferredCulture { get; private set; } /// public GuildFeatures Features { get; private set; } /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); /// public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); /// public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); /// public string DiscoverySplashUrl => CDN.GetGuildDiscoverySplashUrl(Id, DiscoverySplashId); /// public string BannerUrl => CDN.GetGuildBannerUrl(Id, BannerId, ImageFormat.Auto); /// /// Gets the built-in role containing all users in this guild. /// public RestRole EveryoneRole => GetRole(Id); /// /// Gets a collection of all roles in this guild. /// public IReadOnlyCollection Roles => _roles.ToReadOnlyCollection(); /// public IReadOnlyCollection Emotes => _emotes; public IReadOnlyCollection Stickers => _stickers; internal RestGuild(BaseDiscordClient client, ulong id) : base(client, id) { } internal static RestGuild Create(BaseDiscordClient discord, Model model) { var entity = new RestGuild(discord, model.Id); entity.Update(model); return entity; } internal void Update(Model model) { AFKChannelId = model.AFKChannelId; if (model.WidgetChannelId.IsSpecified) WidgetChannelId = model.WidgetChannelId.Value; SystemChannelId = model.SystemChannelId; RulesChannelId = model.RulesChannelId; PublicUpdatesChannelId = model.PublicUpdatesChannelId; AFKTimeout = model.AFKTimeout; if (model.WidgetEnabled.IsSpecified) IsWidgetEnabled = model.WidgetEnabled.Value; IconId = model.Icon; Name = model.Name; OwnerId = model.OwnerId; VoiceRegionId = model.Region; SplashId = model.Splash; DiscoverySplashId = model.DiscoverySplash; VerificationLevel = model.VerificationLevel; MfaLevel = model.MfaLevel; DefaultMessageNotifications = model.DefaultMessageNotifications; ExplicitContentFilter = model.ExplicitContentFilter; ApplicationId = model.ApplicationId; PremiumTier = model.PremiumTier; VanityURLCode = model.VanityURLCode; BannerId = model.Banner; SystemChannelFlags = model.SystemChannelFlags; Description = model.Description; PremiumSubscriptionCount = model.PremiumSubscriptionCount.GetValueOrDefault(); NsfwLevel = model.NsfwLevel; if (model.MaxPresences.IsSpecified) MaxPresences = model.MaxPresences.Value ?? 25000; if (model.MaxMembers.IsSpecified) MaxMembers = model.MaxMembers.Value; if (model.MaxVideoChannelUsers.IsSpecified) MaxVideoChannelUsers = model.MaxVideoChannelUsers.Value; PreferredLocale = model.PreferredLocale; PreferredCulture = new CultureInfo(PreferredLocale); if (model.ApproximateMemberCount.IsSpecified) ApproximateMemberCount = model.ApproximateMemberCount.Value; if (model.ApproximatePresenceCount.IsSpecified) ApproximatePresenceCount = model.ApproximatePresenceCount.Value; if (model.IsBoostProgressBarEnabled.IsSpecified) IsBoostProgressBarEnabled = model.IsBoostProgressBarEnabled.Value; if (model.Emojis != null) { var emotes = ImmutableArray.CreateBuilder(model.Emojis.Length); for (int i = 0; i < model.Emojis.Length; i++) emotes.Add(model.Emojis[i].ToEntity()); _emotes = emotes.ToImmutableArray(); } else _emotes = ImmutableArray.Create(); Features = model.Features; var roles = ImmutableDictionary.CreateBuilder(); if (model.Roles != null) { for (int i = 0; i < model.Roles.Length; i++) roles[model.Roles[i].Id] = RestRole.Create(Discord, this, model.Roles[i]); } _roles = roles.ToImmutable(); if (model.Stickers != null) { var stickers = ImmutableArray.CreateBuilder(); for (int i = 0; i < model.Stickers.Length; i++) { var sticker = model.Stickers[i]; var entity = CustomSticker.Create(Discord, sticker, this, sticker.User.IsSpecified ? sticker.User.Value.Id : null); stickers.Add(entity); } _stickers = stickers.ToImmutable(); } else _stickers = ImmutableArray.Create(); Available = true; } internal void Update(WidgetModel model) { WidgetChannelId = model.ChannelId; IsWidgetEnabled = model.Enabled; } #endregion #region General /// public async Task UpdateAsync(RequestOptions options = null) => Update(await Discord.ApiClient.GetGuildAsync(Id, false, options).ConfigureAwait(false)); /// /// Updates this object's properties with its current state. /// /// /// If true, and /// will be updated as well. /// /// The options to be used when sending the request. /// /// If is true, and /// will be updated as well. /// public async Task UpdateAsync(bool withCounts, RequestOptions options = null) => Update(await Discord.ApiClient.GetGuildAsync(Id, withCounts, options).ConfigureAwait(false)); /// public Task DeleteAsync(RequestOptions options = null) => GuildHelper.DeleteAsync(this, Discord, options); /// /// is . public async Task ModifyAsync(Action func, RequestOptions options = null) { var model = await GuildHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } /// /// is . public async Task ModifyWidgetAsync(Action func, RequestOptions options = null) { var model = await GuildHelper.ModifyWidgetAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } /// /// is . public async Task ReorderChannelsAsync(IEnumerable args, RequestOptions options = null) { var arr = args.ToArray(); await GuildHelper.ReorderChannelsAsync(this, Discord, arr, options).ConfigureAwait(false); } /// public async Task ReorderRolesAsync(IEnumerable args, RequestOptions options = null) { var models = await GuildHelper.ReorderRolesAsync(this, Discord, args, options).ConfigureAwait(false); foreach (var model in models) { var role = GetRole(model.Id); role?.Update(model); } } /// public Task LeaveAsync(RequestOptions options = null) => GuildHelper.LeaveAsync(this, Discord, options); #endregion #region Interactions /// /// Deletes all slash commands in the current guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous delete operation. /// public Task DeleteSlashCommandsAsync(RequestOptions options = null) => InteractionHelper.DeleteAllGuildCommandsAsync(Discord, Id, options); /// /// Gets a collection of slash commands created by the current user in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// slash commands created by the current user. /// public Task> GetSlashCommandsAsync(RequestOptions options = null) => GuildHelper.GetSlashCommandsAsync(this, Discord, options); /// /// Gets a slash command in the current guild. /// /// The unique identifier of the slash command. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a /// slash command created by the current user. /// public Task GetSlashCommandAsync(ulong id, RequestOptions options = null) => GuildHelper.GetSlashCommandAsync(this, id, Discord, options); #endregion #region Bans /// public IAsyncEnumerable> GetBansAsync(int limit = DiscordConfig.MaxBansPerBatch, RequestOptions options = null) => GuildHelper.GetBansAsync(this, Discord, null, Direction.Before, limit, options); /// public IAsyncEnumerable> GetBansAsync(ulong fromUserId, Direction dir, int limit = DiscordConfig.MaxBansPerBatch, RequestOptions options = null) => GuildHelper.GetBansAsync(this, Discord, fromUserId, dir, limit, options); /// public IAsyncEnumerable> GetBansAsync(IUser fromUser, Direction dir, int limit = DiscordConfig.MaxBansPerBatch, RequestOptions options = null) => GuildHelper.GetBansAsync(this, Discord, fromUser.Id, dir, limit, options); /// /// Gets a ban object for a banned user. /// /// The banned user. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a ban object, which /// contains the user information and the reason for the ban; if the ban entry cannot be found. /// public Task GetBanAsync(IUser user, RequestOptions options = null) => GuildHelper.GetBanAsync(this, Discord, user.Id, options); /// /// Gets a ban object for a banned user. /// /// The snowflake identifier for the banned user. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a ban object, which /// contains the user information and the reason for the ban; if the ban entry cannot be found. /// public Task GetBanAsync(ulong userId, RequestOptions options = null) => GuildHelper.GetBanAsync(this, Discord, userId, options); /// public Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null) => GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, reason, options); /// public Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null) => GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, reason, options); /// public Task RemoveBanAsync(IUser user, RequestOptions options = null) => GuildHelper.RemoveBanAsync(this, Discord, user.Id, options); /// public Task RemoveBanAsync(ulong userId, RequestOptions options = null) => GuildHelper.RemoveBanAsync(this, Discord, userId, options); #endregion #region Channels /// /// Gets a collection of all channels in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// generic channels found within this guild. /// public Task> GetChannelsAsync(RequestOptions options = null) => GuildHelper.GetChannelsAsync(this, Discord, options); /// /// Gets a channel in this guild. /// /// The snowflake identifier for the channel. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the generic channel /// associated with the specified ; if none is found. /// public Task GetChannelAsync(ulong id, RequestOptions options = null) => GuildHelper.GetChannelAsync(this, Discord, id, options); /// /// Gets a text channel in this guild. /// /// The snowflake identifier for the text channel. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the text channel /// associated with the specified ; if none is found. /// public async Task GetTextChannelAsync(ulong id, RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false); return channel as RestTextChannel; } /// /// Gets a collection of all text channels in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// message channels found within this guild. /// public async Task> GetTextChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.OfType().ToImmutableArray(); } /// /// Gets a thread channel in this guild. /// /// The snowflake identifier for the thread channel. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the thread channel associated /// with the specified ; if none is found. /// public async Task GetThreadChannelAsync(ulong id, RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false); return channel as RestThreadChannel; } /// /// Gets a collection of all thread in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// threads found within this guild. /// public async Task> GetThreadChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.OfType().ToImmutableArray(); } /// /// Gets a voice channel in this guild. /// /// The snowflake identifier for the voice channel. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the voice channel associated /// with the specified ; if none is found. /// public async Task GetVoiceChannelAsync(ulong id, RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false); return channel as RestVoiceChannel; } /// /// Gets a collection of all voice channels in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// voice channels found within this guild. /// public async Task> GetVoiceChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.OfType().ToImmutableArray(); } /// /// Gets a stage channel in this guild /// /// The snowflake identifier for the stage channel. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the stage channel associated /// with the specified ; if none is found. /// public async Task GetStageChannelAsync(ulong id, RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false); return channel as RestStageChannel; } /// /// Gets a collection of all stage channels in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// stage channels found within this guild. /// public async Task> GetStageChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.OfType().ToImmutableArray(); } /// /// Gets a collection of all category channels in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// category channels found within this guild. /// public async Task> GetCategoryChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.OfType().ToImmutableArray(); } /// /// Gets the AFK voice channel in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the voice channel that the /// AFK users will be moved to after they have idled for too long; if none is set. /// public async Task GetAFKChannelAsync(RequestOptions options = null) { var afkId = AFKChannelId; if (afkId.HasValue) { var channel = await GuildHelper.GetChannelAsync(this, Discord, afkId.Value, options).ConfigureAwait(false); return channel as RestVoiceChannel; } return null; } /// /// Gets the first viewable text channel in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the first viewable text /// channel in this guild; if none is found. /// public async Task GetDefaultChannelAsync(RequestOptions options = null) { var channels = await GetTextChannelsAsync(options).ConfigureAwait(false); var user = await GetCurrentUserAsync(options).ConfigureAwait(false); return channels .Where(c => user.GetPermissions(c).ViewChannel) .OrderBy(c => c.Position) .FirstOrDefault(); } /// /// Gets the widget channel (i.e. the channel set in the guild's widget settings) in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the widget channel set /// within the server's widget settings; if none is set. /// public async Task GetWidgetChannelAsync(RequestOptions options = null) { var widgetChannelId = WidgetChannelId; if (widgetChannelId.HasValue) return await GuildHelper.GetChannelAsync(this, Discord, widgetChannelId.Value, options).ConfigureAwait(false); return null; } /// /// Gets the text channel where guild notices such as welcome messages and boost events are posted. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the text channel /// where guild notices such as welcome messages and boost events are post; if none is found. /// public async Task GetSystemChannelAsync(RequestOptions options = null) { var systemId = SystemChannelId; if (systemId.HasValue) { var channel = await GuildHelper.GetChannelAsync(this, Discord, systemId.Value, options).ConfigureAwait(false); return channel as RestTextChannel; } return null; } /// /// Gets the text channel where Community guilds can display rules and/or guidelines. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the text channel /// where Community guilds can display rules and/or guidelines; if none is set. /// public async Task GetRulesChannelAsync(RequestOptions options = null) { var rulesChannelId = RulesChannelId; if (rulesChannelId.HasValue) { var channel = await GuildHelper.GetChannelAsync(this, Discord, rulesChannelId.Value, options).ConfigureAwait(false); return channel as RestTextChannel; } return null; } /// /// Gets the text channel where admins and moderators of Community guilds receive notices from Discord. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the text channel where /// admins and moderators of Community guilds receive notices from Discord; if none is set. /// public async Task GetPublicUpdatesChannelAsync(RequestOptions options = null) { var publicUpdatesChannelId = PublicUpdatesChannelId; if (publicUpdatesChannelId.HasValue) { var channel = await GuildHelper.GetChannelAsync(this, Discord, publicUpdatesChannelId.Value, options).ConfigureAwait(false); return channel as RestTextChannel; } return null; } /// /// Creates a new text channel in this guild. /// /// /// The following example creates a new text channel under an existing category named Wumpus with a set topic. /// /// var categories = await guild.GetCategoriesAsync(); /// var targetCategory = categories.FirstOrDefault(x => x.Name == "wumpus"); /// if (targetCategory == null) return; /// await Context.Guild.CreateTextChannelAsync(name, x => /// { /// x.CategoryId = targetCategory.Id; /// x.Topic = $"This channel was created at {DateTimeOffset.UtcNow} by {user}."; /// }); /// /// /// The new name for the text channel. /// The delegate containing the properties to be applied to the channel upon its creation. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains the newly created /// text channel. /// public Task CreateTextChannelAsync(string name, Action func = null, RequestOptions options = null) => GuildHelper.CreateTextChannelAsync(this, Discord, name, options, func); /// /// Creates a voice channel with the provided name. /// /// The name of the new channel. /// The delegate containing the properties to be applied to the channel upon its creation. /// The options to be used when sending the request. /// is . /// /// The created voice channel. /// public Task CreateVoiceChannelAsync(string name, Action func = null, RequestOptions options = null) => GuildHelper.CreateVoiceChannelAsync(this, Discord, name, options, func); /// /// Creates a new stage channel in this guild. /// /// The new name for the stage channel. /// The delegate containing the properties to be applied to the channel upon its creation. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains the newly created /// stage channel. /// public Task CreateStageChannelAsync(string name, Action func = null, RequestOptions options = null) => GuildHelper.CreateStageChannelAsync(this, Discord, name, options, func); /// /// Creates a category channel with the provided name. /// /// The name of the new channel. /// The delegate containing the properties to be applied to the channel upon its creation. /// The options to be used when sending the request. /// is . /// /// The created category channel. /// public Task CreateCategoryChannelAsync(string name, Action func = null, RequestOptions options = null) => GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options, func); /// /// Gets a collection of all the voice regions this guild can access. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// voice regions the guild can access. /// public Task> GetVoiceRegionsAsync(RequestOptions options = null) => GuildHelper.GetVoiceRegionsAsync(this, Discord, options); #endregion #region Integrations public Task> GetIntegrationsAsync(RequestOptions options = null) => GuildHelper.GetIntegrationsAsync(this, Discord, options); public Task DeleteIntegrationAsync(ulong id, RequestOptions options = null) => GuildHelper.DeleteIntegrationAsync(this, Discord, id, options); #endregion #region Invites /// /// Gets a collection of all invites in this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection of /// invite metadata, each representing information for an invite found within this guild. /// public Task> GetInvitesAsync(RequestOptions options = null) => GuildHelper.GetInvitesAsync(this, Discord, options); /// /// Gets the vanity invite URL of this guild. /// /// The options to be used when sending the request. /// /// A partial metadata of the vanity invite found within this guild. /// public Task GetVanityInviteAsync(RequestOptions options = null) => GuildHelper.GetVanityInviteAsync(this, Discord, options); #endregion #region Roles /// /// Gets a role in this guild. /// /// The snowflake identifier for the role. /// /// A role that is associated with the specified ; if none is found. /// public RestRole GetRole(ulong id) { if (_roles.TryGetValue(id, out RestRole value)) return value; return null; } /// /// Creates a new role with the provided name. /// /// The new name for the role. /// The guild permission that the role should possess. /// The color of the role. /// Whether the role is separated from others on the sidebar. /// The options to be used when sending the request. /// Whether the role can be mentioned. /// /// A task that represents the asynchronous creation operation. The task result contains the newly created /// role. /// public async Task CreateRoleAsync(string name, GuildPermissions? permissions = default(GuildPermissions?), Color? color = default(Color?), bool isHoisted = false, bool isMentionable = false, RequestOptions options = null) { var role = await GuildHelper.CreateRoleAsync(this, Discord, name, permissions, color, isHoisted, isMentionable, options).ConfigureAwait(false); _roles = _roles.Add(role.Id, role); return role; } #endregion #region Users /// /// Gets a collection of all users in this guild. /// /// /// This method retrieves all users found within this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a collection of guild /// users found within this guild. /// public IAsyncEnumerable> GetUsersAsync(RequestOptions options = null) => GuildHelper.GetUsersAsync(this, Discord, null, null, options); /// public Task AddGuildUserAsync(ulong id, string accessToken, Action func = null, RequestOptions options = null) => GuildHelper.AddGuildUserAsync(this, Discord, id, accessToken, func, options); /// /// Gets a user from this guild. /// /// /// This method retrieves a user found within this guild. /// /// The snowflake identifier of the user. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the guild user /// associated with the specified ; if none is found. /// public Task GetUserAsync(ulong id, RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, id, options); /// /// Gets the current user for this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the currently logged-in /// user within this guild. /// public Task GetCurrentUserAsync(RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, Discord.CurrentUser.Id, options); /// /// Gets the owner of this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the owner of this guild. /// public Task GetOwnerAsync(RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, OwnerId, options); /// /// /// Prunes inactive users. /// /// /// /// This method removes all users that have not logged on in the provided number of . /// /// /// If is true, this method will only return the number of users that /// would be removed without kicking the users. /// /// /// The number of days required for the users to be kicked. /// Whether this prune action is a simulation. /// The options to be used when sending the request. /// /// A task that represents the asynchronous prune operation. The task result contains the number of users to /// be or has been removed from this guild. /// public Task PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null, IEnumerable includeRoleIds = null) => GuildHelper.PruneUsersAsync(this, Discord, days, simulate, options, includeRoleIds); /// /// Gets a collection of users in this guild that the name or nickname starts with the /// provided at . /// /// /// The can not be higher than . /// /// The partial name or nickname to search. /// The maximum number of users to be gotten. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a collection of guild /// users that the name or nickname starts with the provided at . /// public Task> SearchUsersAsync(string query, int limit = DiscordConfig.MaxUsersPerBatch, RequestOptions options = null) => GuildHelper.SearchUsersAsync(this, Discord, query, limit, options); #endregion #region Audit logs /// /// Gets the specified number of audit log entries for this guild. /// /// The number of audit log entries to fetch. /// The options to be used when sending the request. /// The audit log entry ID to get entries before. /// The type of actions to filter. /// The user ID to filter entries for. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection /// of the requested audit log entries. /// public IAsyncEnumerable> GetAuditLogsAsync(int limit, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null, ActionType? actionType = null) => GuildHelper.GetAuditLogsAsync(this, Discord, beforeId, limit, options, userId: userId, actionType: actionType); #endregion #region Webhooks /// /// Gets a webhook found within this guild. /// /// The identifier for the webhook. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the webhook with the /// specified ; if none is found. /// public Task GetWebhookAsync(ulong id, RequestOptions options = null) => GuildHelper.GetWebhookAsync(this, Discord, id, options); /// /// Gets a collection of all webhook from this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection /// of webhooks found within the guild. /// public Task> GetWebhooksAsync(RequestOptions options = null) => GuildHelper.GetWebhooksAsync(this, Discord, options); #endregion #region Interactions /// /// Gets this guilds slash commands /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection /// of application commands found within the guild. /// public async Task> GetApplicationCommandsAsync (RequestOptions options = null) => await ClientHelper.GetGuildApplicationCommandsAsync(Discord, Id, options).ConfigureAwait(false); /// /// Gets an application command within this guild with the specified id. /// /// The id of the application command to get. /// The options to be used when sending the request. /// /// A ValueTask that represents the asynchronous get operation. The task result contains a /// if found, otherwise . /// public async Task GetApplicationCommandAsync(ulong id, RequestOptions options = null) => await ClientHelper.GetGuildApplicationCommandAsync(Discord, id, Id, options); /// /// Creates an application command within this guild. /// /// The properties to use when creating the command. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains the command that was created. /// public async Task CreateApplicationCommandAsync(ApplicationCommandProperties properties, RequestOptions options = null) { var model = await InteractionHelper.CreateGuildCommandAsync(Discord, Id, properties, options); return RestGuildCommand.Create(Discord, model, Id); } /// /// Overwrites the application commands within this guild. /// /// A collection of properties to use when creating the commands. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains a collection of commands that was created. /// public async Task> BulkOverwriteApplicationCommandsAsync(ApplicationCommandProperties[] properties, RequestOptions options = null) { var models = await InteractionHelper.BulkOverwriteGuildCommandsAsync(Discord, Id, properties, options); return models.Select(x => RestGuildCommand.Create(Discord, x, Id)).ToImmutableArray(); } /// /// Returns the name of the guild. /// /// /// The name of the guild. /// public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id})"; #endregion #region Emotes /// public Task> GetEmotesAsync(RequestOptions options = null) => GuildHelper.GetEmotesAsync(this, Discord, options); /// public Task GetEmoteAsync(ulong id, RequestOptions options = null) => GuildHelper.GetEmoteAsync(this, Discord, id, options); /// public Task CreateEmoteAsync(string name, Image image, Optional> roles = default(Optional>), RequestOptions options = null) => GuildHelper.CreateEmoteAsync(this, Discord, name, image, roles, options); /// /// is . public Task ModifyEmoteAsync(GuildEmote emote, Action func, RequestOptions options = null) => GuildHelper.ModifyEmoteAsync(this, Discord, emote.Id, func, options); /// /// Moves the user to the voice channel. /// /// The user to move. /// the channel where the user gets moved to. /// A task that represents the asynchronous operation for moving a user. public Task MoveAsync(IGuildUser user, IVoiceChannel targetChannel) => user.ModifyAsync(x => x.Channel = new Optional(targetChannel)); /// public Task DeleteEmoteAsync(GuildEmote emote, RequestOptions options = null) => GuildHelper.DeleteEmoteAsync(this, Discord, emote.Id, options); #endregion #region Stickers /// /// Creates a new sticker in this guild. /// /// The name of the sticker. /// The description of the sticker. /// The tags of the sticker. /// The image of the new emote. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains the created sticker. /// public async Task CreateStickerAsync(string name, string description, IEnumerable tags, Image image, RequestOptions options = null) { var model = await GuildHelper.CreateStickerAsync(Discord, this, name, description, tags, image, options).ConfigureAwait(false); return CustomSticker.Create(Discord, model, this, model.User.IsSpecified ? model.User.Value.Id : null); } /// /// Creates a new sticker in this guild /// /// The name of the sticker. /// The description of the sticker. /// The tags of the sticker. /// The path of the file to upload. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains the created sticker. /// public Task CreateStickerAsync(string name, string description, IEnumerable tags, string path, RequestOptions options = null) { var fs = File.OpenRead(path); return CreateStickerAsync(name, description, tags, fs, Path.GetFileName(fs.Name), options); } /// /// Creates a new sticker in this guild /// /// The name of the sticker. /// The description of the sticker. /// The tags of the sticker. /// The stream containing the file data. /// The name of the file with the extension, ex: image.png. /// The options to be used when sending the request. /// /// A task that represents the asynchronous creation operation. The task result contains the created sticker. /// public async Task CreateStickerAsync(string name, string description, IEnumerable 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); } /// /// Gets a specific sticker within this guild. /// /// The id of the sticker to get. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains the sticker found with the /// specified ; if none is found. /// public async Task GetStickerAsync(ulong id, RequestOptions options = null) { var model = await Discord.ApiClient.GetGuildStickerAsync(Id, id, options).ConfigureAwait(false); if (model == null) return null; return CustomSticker.Create(Discord, model, this, model.User.IsSpecified ? model.User.Value.Id : null); } /// /// Gets a collection of all stickers within this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a read-only collection /// of stickers found within the guild. /// public async Task> GetStickersAsync(RequestOptions options = null) { var models = await Discord.ApiClient.ListGuildStickersAsync(Id, options).ConfigureAwait(false); if (models.Length == 0) return null; List stickers = new List(); foreach(var model in models) { var entity = CustomSticker.Create(Discord, model, this, model.User.IsSpecified ? model.User.Value.Id : null); stickers.Add(entity); } return stickers.ToImmutableArray(); } /// /// Deletes a sticker within this guild. /// /// The sticker to delete. /// The options to be used when sending the request. /// /// A task that represents the asynchronous removal operation. /// public Task DeleteStickerAsync(CustomSticker sticker, RequestOptions options = null) => sticker.DeleteAsync(options); #endregion #region Guild Events /// /// Gets an event within this guild. /// /// The snowflake identifier for the event. /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. /// public Task GetEventAsync(ulong id, RequestOptions options = null) => GuildHelper.GetGuildEventAsync(Discord, id, this, options); /// /// Gets all active events within this guild. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. /// public Task> GetEventsAsync(RequestOptions options = null) => GuildHelper.GetGuildEventsAsync(Discord, this, options); /// /// Creates an event within this guild. /// /// The name of the event. /// The privacy level of the event. /// The start time of the event. /// The type of the event. /// The description of the event. /// The end time of the event. /// /// The channel id of the event. /// /// The event must have a type of or /// in order to use this property. /// /// /// A collection of speakers for the event. /// The location of the event; links are supported /// The optional banner image for the event. /// The options to be used when sending the request. /// /// A task that represents the asynchronous create operation. /// public Task CreateEventAsync( string name, DateTimeOffset startTime, GuildScheduledEventType type, GuildScheduledEventPrivacyLevel privacyLevel = GuildScheduledEventPrivacyLevel.Private, string description = null, DateTimeOffset? endTime = null, ulong? channelId = null, string location = null, Image? coverImage = null, RequestOptions options = null) => GuildHelper.CreateGuildEventAsync(Discord, this, name, privacyLevel, startTime, type, description, endTime, channelId, location, coverImage, options); #endregion #region IGuild /// bool IGuild.Available => Available; /// IAudioClient IGuild.AudioClient => null; /// IRole IGuild.EveryoneRole => EveryoneRole; /// IReadOnlyCollection IGuild.Roles => Roles; IReadOnlyCollection IGuild.Stickers => Stickers; /// async Task IGuild.CreateEventAsync(string name, DateTimeOffset startTime, GuildScheduledEventType type, GuildScheduledEventPrivacyLevel privacyLevel, string description, DateTimeOffset? endTime, ulong? channelId, string location, Image? coverImage, RequestOptions options) => await CreateEventAsync(name, startTime, type, privacyLevel, description, endTime, channelId, location, coverImage, options).ConfigureAwait(false); /// async Task IGuild.GetEventAsync(ulong id, RequestOptions options) => await GetEventAsync(id, options).ConfigureAwait(false); /// async Task> IGuild.GetEventsAsync(RequestOptions options) => await GetEventsAsync(options).ConfigureAwait(false); /// IAsyncEnumerable> IGuild.GetBansAsync(int limit, RequestOptions options) => GetBansAsync(limit, options); /// IAsyncEnumerable> IGuild.GetBansAsync(ulong fromUserId, Direction dir, int limit, RequestOptions options) => GetBansAsync(fromUserId, dir, limit, options); /// IAsyncEnumerable> IGuild.GetBansAsync(IUser fromUser, Direction dir, int limit, RequestOptions options) => GetBansAsync(fromUser, dir, limit, options); /// async Task IGuild.GetBanAsync(IUser user, RequestOptions options) => await GetBanAsync(user, options).ConfigureAwait(false); /// async Task IGuild.GetBanAsync(ulong userId, RequestOptions options) => await GetBanAsync(userId, options).ConfigureAwait(false); /// async Task> IGuild.GetChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetChannelsAsync(options).ConfigureAwait(false); else return ImmutableArray.Create(); } /// async Task IGuild.GetChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetChannelAsync(id, options).ConfigureAwait(false); else return null; } /// async Task> IGuild.GetTextChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetTextChannelsAsync(options).ConfigureAwait(false); else return ImmutableArray.Create(); } /// async Task IGuild.GetTextChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetTextChannelAsync(id, options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetThreadChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetThreadChannelAsync(id, options).ConfigureAwait(false); else return null; } /// async Task> IGuild.GetThreadChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetThreadChannelsAsync(options).ConfigureAwait(false); else return null; } /// async Task> IGuild.GetVoiceChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetVoiceChannelsAsync(options).ConfigureAwait(false); else return ImmutableArray.Create(); } /// async Task> IGuild.GetCategoriesAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetCategoryChannelsAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetStageChannelAsync(ulong id, CacheMode mode, RequestOptions options ) { if (mode == CacheMode.AllowDownload) return await GetStageChannelAsync(id, options).ConfigureAwait(false); else return null; } /// async Task> IGuild.GetStageChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetStageChannelsAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetVoiceChannelAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetVoiceChannelAsync(id, options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetAFKChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetAFKChannelAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetDefaultChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetDefaultChannelAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetWidgetChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetWidgetChannelAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetSystemChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetSystemChannelAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetRulesChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetRulesChannelAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetPublicUpdatesChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetPublicUpdatesChannelAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.CreateTextChannelAsync(string name, Action func, RequestOptions options) => await CreateTextChannelAsync(name, func, options).ConfigureAwait(false); /// async Task IGuild.CreateVoiceChannelAsync(string name, Action func, RequestOptions options) => await CreateVoiceChannelAsync(name, func, options).ConfigureAwait(false); /// async Task IGuild.CreateStageChannelAsync(string name, Action func, RequestOptions options) => await CreateStageChannelAsync(name, func, options).ConfigureAwait(false); /// async Task IGuild.CreateCategoryAsync(string name, Action func, RequestOptions options) => await CreateCategoryChannelAsync(name, func, options).ConfigureAwait(false); /// async Task> IGuild.GetVoiceRegionsAsync(RequestOptions options) => await GetVoiceRegionsAsync(options).ConfigureAwait(false); /// async Task> IGuild.GetIntegrationsAsync(RequestOptions options) => await GetIntegrationsAsync(options).ConfigureAwait(false); /// async Task IGuild.DeleteIntegrationAsync(ulong id, RequestOptions options) => await DeleteIntegrationAsync(id, options).ConfigureAwait(false); /// async Task> IGuild.GetInvitesAsync(RequestOptions options) => await GetInvitesAsync(options).ConfigureAwait(false); /// async Task IGuild.GetVanityInviteAsync(RequestOptions options) => await GetVanityInviteAsync(options).ConfigureAwait(false); /// IRole IGuild.GetRole(ulong id) => GetRole(id); /// async Task IGuild.CreateRoleAsync(string name, GuildPermissions? permissions, Color? color, bool isHoisted, RequestOptions options) => await CreateRoleAsync(name, permissions, color, isHoisted, false, options).ConfigureAwait(false); /// async Task IGuild.CreateRoleAsync(string name, GuildPermissions? permissions, Color? color, bool isHoisted, bool isMentionable, RequestOptions options) => await CreateRoleAsync(name, permissions, color, isHoisted, isMentionable, options).ConfigureAwait(false); /// async Task IGuild.AddGuildUserAsync(ulong userId, string accessToken, Action func, RequestOptions options) => await AddGuildUserAsync(userId, accessToken, func, options); /// /// Disconnects the user from its current voice channel /// /// The user to disconnect. /// A task that represents the asynchronous operation for disconnecting a user. async Task IGuild.DisconnectAsync(IGuildUser user) => await user.ModifyAsync(x => x.Channel = new Optional()); /// async Task IGuild.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetUserAsync(id, options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetCurrentUserAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetCurrentUserAsync(options).ConfigureAwait(false); else return null; } /// async Task IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetOwnerAsync(options).ConfigureAwait(false); else return null; } /// async Task> IGuild.GetUsersAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return (await GetUsersAsync(options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); else return ImmutableArray.Create(); } /// /// Downloading users is not supported for a REST-based guild. Task IGuild.DownloadUsersAsync() => throw new NotSupportedException(); /// async Task> IGuild.SearchUsersAsync(string query, int limit, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await SearchUsersAsync(query, limit, options).ConfigureAwait(false); else return ImmutableArray.Create(); } async Task> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options, ulong? beforeId, ulong? userId, ActionType? actionType) { if (cacheMode == CacheMode.AllowDownload) return (await GetAuditLogsAsync(limit, options, beforeId: beforeId, userId: userId, actionType: actionType).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); else return ImmutableArray.Create(); } /// async Task IGuild.GetWebhookAsync(ulong id, RequestOptions options) => await GetWebhookAsync(id, options).ConfigureAwait(false); /// async Task> IGuild.GetWebhooksAsync(RequestOptions options) => await GetWebhooksAsync(options).ConfigureAwait(false); /// async Task> IGuild.GetApplicationCommandsAsync (RequestOptions options) => await GetApplicationCommandsAsync(options).ConfigureAwait(false); /// async Task IGuild.CreateStickerAsync(string name, string description, IEnumerable tags, Image image, RequestOptions options) => await CreateStickerAsync(name, description, tags, image, options); /// async Task IGuild.CreateStickerAsync(string name, string description, IEnumerable tags, Stream stream, string filename, RequestOptions options) => await CreateStickerAsync(name, description, tags, stream, filename, options); /// async Task IGuild.CreateStickerAsync(string name, string description, IEnumerable tags, string path, RequestOptions options) => await CreateStickerAsync(name, description, tags, path, options); /// async Task IGuild.GetStickerAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode != CacheMode.AllowDownload) return null; return await GetStickerAsync(id, options); } /// async Task> IGuild.GetStickersAsync(CacheMode mode, RequestOptions options) { if (mode != CacheMode.AllowDownload) return null; return await GetStickersAsync(options); } /// Task IGuild.DeleteStickerAsync(ICustomSticker sticker, RequestOptions options) => sticker.DeleteAsync(); /// async Task IGuild.CreateApplicationCommandAsync(ApplicationCommandProperties properties, RequestOptions options) => await CreateApplicationCommandAsync(properties, options); /// async Task> IGuild.BulkOverwriteApplicationCommandsAsync(ApplicationCommandProperties[] properties, RequestOptions options) => await BulkOverwriteApplicationCommandsAsync(properties, options); /// async Task IGuild.GetApplicationCommandAsync(ulong id, CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) { return await GetApplicationCommandAsync(id, options); } else return null; } #endregion } }