using Discord.Audio; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using EmbedModel = Discord.API.GuildEmbed; using Model = Discord.API.Guild; namespace Discord.Rest { [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class RestGuild : RestEntity, IGuild, IUpdateable { private ImmutableDictionary _roles; private ImmutableArray _emotes; private ImmutableArray _features; public string Name { get; private set; } public int AFKTimeout { get; private set; } public bool IsEmbeddable { get; private set; } public VerificationLevel VerificationLevel { get; private set; } public MfaLevel MfaLevel { get; private set; } public DefaultMessageNotifications DefaultMessageNotifications { get; private set; } public ulong? AFKChannelId { get; private set; } public ulong? EmbedChannelId { 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; } internal bool Available { get; private set; } public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); public ulong DefaultChannelId => Id; public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); public RestRole EveryoneRole => GetRole(Id); public IReadOnlyCollection Roles => _roles.ToReadOnlyCollection(); public IReadOnlyCollection Emotes => _emotes; public IReadOnlyCollection Features => _features; 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; EmbedChannelId = model.EmbedChannelId; AFKTimeout = model.AFKTimeout; IsEmbeddable = model.EmbedEnabled; IconId = model.Icon; Name = model.Name; OwnerId = model.OwnerId; VoiceRegionId = model.Region; SplashId = model.Splash; VerificationLevel = model.VerificationLevel; MfaLevel = model.MfaLevel; DefaultMessageNotifications = model.DefaultMessageNotifications; 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(); if (model.Features != null) _features = model.Features.ToImmutableArray(); else _features = ImmutableArray.Create(); 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(); Available = true; } internal void Update(EmbedModel model) { EmbedChannelId = model.ChannelId; IsEmbeddable = model.Enabled; } //General public async Task UpdateAsync(RequestOptions options = null) => Update(await Discord.ApiClient.GetGuildAsync(Id, options).ConfigureAwait(false)); public Task DeleteAsync(RequestOptions options = null) => GuildHelper.DeleteAsync(this, Discord, options); public async Task ModifyAsync(Action func, RequestOptions options = null) { var model = await GuildHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } public async Task ModifyEmbedAsync(Action func, RequestOptions options = null) { var model = await GuildHelper.ModifyEmbedAsync(this, Discord, func, options).ConfigureAwait(false); Update(model); } public async Task ReorderChannelsAsync(IEnumerable args, RequestOptions options = null) { var arr = args.ToArray(); await GuildHelper.ReorderChannelsAsync(this, Discord, arr, options); } 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); if (role != null) role.Update(model); } } public Task LeaveAsync(RequestOptions options = null) => GuildHelper.LeaveAsync(this, Discord, options); //Bans public Task> GetBansAsync(RequestOptions options = null) => GuildHelper.GetBansAsync(this, Discord, options); public Task AddBanAsync(IUser user, int pruneDays = 0, RequestOptions options = null) => GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, options); public Task AddBanAsync(ulong userId, int pruneDays = 0, RequestOptions options = null) => GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, 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); //Channels public Task> GetChannelsAsync(RequestOptions options = null) => GuildHelper.GetChannelsAsync(this, Discord, options); public Task GetChannelAsync(ulong id, RequestOptions options = null) => GuildHelper.GetChannelAsync(this, Discord, id, options); public async Task GetTextChannelAsync(ulong id, RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false); return channel as RestTextChannel; } public async Task> GetTextChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.Select(x => x as RestTextChannel).Where(x => x != null).ToImmutableArray(); } public async Task GetVoiceChannelAsync(ulong id, RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false); return channel as RestVoiceChannel; } public async Task> GetVoiceChannelsAsync(RequestOptions options = null) { var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false); return channels.Select(x => x as RestVoiceChannel).Where(x => x != null).ToImmutableArray(); } 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; } public async Task GetDefaultChannelAsync(RequestOptions options = null) { var channel = await GuildHelper.GetChannelAsync(this, Discord, DefaultChannelId, options).ConfigureAwait(false); return channel as RestTextChannel; } public async Task GetEmbedChannelAsync(RequestOptions options = null) { var embedId = EmbedChannelId; if (embedId.HasValue) return await GuildHelper.GetChannelAsync(this, Discord, embedId.Value, options).ConfigureAwait(false); return null; } public Task CreateTextChannelAsync(string name, RequestOptions options = null) => GuildHelper.CreateTextChannelAsync(this, Discord, name, options); public Task CreateVoiceChannelAsync(string name, RequestOptions options = null) => GuildHelper.CreateVoiceChannelAsync(this, Discord, name, options); //Integrations public Task> GetIntegrationsAsync(RequestOptions options = null) => GuildHelper.GetIntegrationsAsync(this, Discord, options); public Task CreateIntegrationAsync(ulong id, string type, RequestOptions options = null) => GuildHelper.CreateIntegrationAsync(this, Discord, id, type, options); //Invites public Task> GetInvitesAsync(RequestOptions options = null) => GuildHelper.GetInvitesAsync(this, Discord, options); //Roles public RestRole GetRole(ulong id) { if (_roles.TryGetValue(id, out RestRole value)) return value; return null; } public async Task CreateRoleAsync(string name, GuildPermissions? permissions = default(GuildPermissions?), Color? color = default(Color?), bool isHoisted = false, RequestOptions options = null) { var role = await GuildHelper.CreateRoleAsync(this, Discord, name, permissions, color, isHoisted, options).ConfigureAwait(false); _roles = _roles.Add(role.Id, role); return role; } //Users public IAsyncEnumerable GetUsersAsync(RequestOptions options = null) => GuildHelper.GetUsersAsync(this, Discord, null, null, options); public Task GetUserAsync(ulong id, RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, id, options); public Task GetCurrentUserAsync(RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, Discord.CurrentUser.Id, options); public Task GetOwnerAsync(RequestOptions options = null) => GuildHelper.GetUserAsync(this, Discord, OwnerId, options); public Task PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null) => GuildHelper.PruneUsersAsync(this, Discord, days, simulate, options); public override string ToString() => Name; private string DebuggerDisplay => $"{Name} ({Id})"; //IGuild bool IGuild.Available => Available; IAudioClient IGuild.AudioClient => null; IRole IGuild.EveryoneRole => EveryoneRole; IReadOnlyCollection IGuild.Roles => Roles; async Task> IGuild.GetBansAsync(RequestOptions options) => await GetBansAsync(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.GetVoiceChannelsAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetVoiceChannelsAsync(options).ConfigureAwait(false); else return ImmutableArray.Create(); } 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.GetEmbedChannelAsync(CacheMode mode, RequestOptions options) { if (mode == CacheMode.AllowDownload) return await GetEmbedChannelAsync(options).ConfigureAwait(false); else return null; } async Task IGuild.CreateTextChannelAsync(string name, RequestOptions options) => await CreateTextChannelAsync(name, options).ConfigureAwait(false); async Task IGuild.CreateVoiceChannelAsync(string name, RequestOptions options) => await CreateVoiceChannelAsync(name, options).ConfigureAwait(false); async Task> IGuild.GetIntegrationsAsync(RequestOptions options) => await GetIntegrationsAsync(options).ConfigureAwait(false); async Task IGuild.CreateIntegrationAsync(ulong id, string type, RequestOptions options) => await CreateIntegrationAsync(id, type, options).ConfigureAwait(false); async Task> IGuild.GetInvitesAsync(RequestOptions options) => await GetInvitesAsync(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, options).ConfigureAwait(false); 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).ToArray().ConfigureAwait(false)).ToImmutableArray(); else return ImmutableArray.Create(); } Task IGuild.DownloadUsersAsync() { throw new NotSupportedException(); } } }