diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index d1ff7b99c..63f4a2280 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -1251,5 +1251,21 @@ namespace Discord /// Task> BulkOverwriteApplicationCommandsAsync(ApplicationCommandProperties[] properties, RequestOptions options = null); + + /// + /// Gets the welcome screen of the guild. Returns if the welcome channel is not set. + /// + /// + /// A task that represents the asynchronous creation operation. The task result contains a . + /// + Task GetWelcomeScreenAsync(RequestOptions options = null); + + /// + /// Modifies the welcome screen of the guild. Returns if welcome screen is removed. + /// + /// + /// A task that represents the asynchronous creation operation. The task result contains a . + /// + Task ModifyWelcomeScreenAsync(bool enabled, WelcomeScreenChannelProperties[] channels, string description = null, RequestOptions options = null); } } diff --git a/src/Discord.Net.Core/Entities/Guilds/WelcomeScreen.cs b/src/Discord.Net.Core/Entities/Guilds/WelcomeScreen.cs new file mode 100644 index 000000000..489256010 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Guilds/WelcomeScreen.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Discord; + +public class WelcomeScreen +{ + /// + /// Gets the server description shown in the welcome screen. if not set. + /// + public string Description { get; } + + /// + /// Gets the channels shown in the welcome screen, up to 5 channels. + /// + public IReadOnlyCollection Channels { get; } + + internal WelcomeScreen(string description, IReadOnlyCollection channels) + { + Description = description; + + Channels = channels.ToImmutableArray(); + } +} diff --git a/src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannel.cs b/src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannel.cs new file mode 100644 index 000000000..431831f6e --- /dev/null +++ b/src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannel.cs @@ -0,0 +1,41 @@ +using System; + +namespace Discord; + +public class WelcomeScreenChannel : ISnowflakeEntity +{ + /// + /// Gets the channel's id. + /// + public ulong Id { get; } + + /// + /// Gets the description shown for the channel. + /// + public string Description { get; } + + /// + /// Gets the emoji for this channel. if it is unicode emoji, if it is a custom one and if none is set. + /// + /// + /// If the emoji is only the will be populated. + /// Use to get the emoji. + /// + public IEmote Emoji { get; } + + /// + public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + + internal WelcomeScreenChannel(ulong id, string description, string emojiName = null, ulong? emoteId = null) + { + Id = id; + Description = description; + + if (emoteId.HasValue && emoteId.Value != 0) + Emoji = new Emote(emoteId.Value, emojiName, false); + else if (emojiName != null) + Emoji = new Emoji(emojiName); + else + Emoji = null; + } +} diff --git a/src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannelProperties.cs b/src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannelProperties.cs new file mode 100644 index 000000000..c35470ef3 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannelProperties.cs @@ -0,0 +1,54 @@ +using System; +using System.Xml.Linq; + +namespace Discord; + +public class WelcomeScreenChannelProperties : ISnowflakeEntity +{ + /// + /// Gets or sets the channel's id. + /// + public ulong Id { get; set; } + + /// + /// Gets or sets the description shown for the channel. + /// + public string Description { get; set; } + + /// + /// Gets or sets the emoji for this channel. if it is unicode emoji, if it is a custom one and if none is set. + /// + /// + /// If the emoji is only the will be populated. + /// Use to get the emoji. + /// + public IEmote Emoji { get; set; } + + /// + public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + + /// + /// Initializes a new instance of . + /// + /// Id if a channel. + /// Description for the channel in the welcome screen. + /// The emoji for the channel in the welcome screen. + public WelcomeScreenChannelProperties(ulong id, string description, IEmote emoji = null) + { + Id = id; + Description = description; + Emoji = emoji; + } + + /// + /// Initializes a new instance of . + /// + public WelcomeScreenChannelProperties() { } + /// + /// Initializes a new instance of . + /// + /// A welcome screen channel to modify. + /// A new instance of . + public static WelcomeScreenChannelProperties FromWelcomeScreenChannel(WelcomeScreenChannel channel) + => new (channel.Id, channel.Description, channel.Emoji); +} diff --git a/src/Discord.Net.Core/Entities/Invites/IInvite.cs b/src/Discord.Net.Core/Entities/Invites/IInvite.cs index 47ffffacb..eb1f6a243 100644 --- a/src/Discord.Net.Core/Entities/Invites/IInvite.cs +++ b/src/Discord.Net.Core/Entities/Invites/IInvite.cs @@ -60,6 +60,7 @@ namespace Discord /// A guild object representing the guild that the invite points to. /// IGuild Guild { get; } + /// /// Gets the ID of the guild this invite is linked to. /// diff --git a/src/Discord.Net.Core/Entities/Invites/InviteGuild.cs b/src/Discord.Net.Core/Entities/Invites/InviteGuild.cs new file mode 100644 index 000000000..b290716ec --- /dev/null +++ b/src/Discord.Net.Core/Entities/Invites/InviteGuild.cs @@ -0,0 +1,156 @@ +using System; + +namespace Discord; + +public class InviteGuild : ISnowflakeEntity +{ + /// + public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); + + /// + public ulong Id { get; private set; } + + /// + /// Gets the name of this guild. + /// + /// + /// A string containing the name of this guild. + /// + public string Name { get; private set; } + + /// + /// Gets the description for the guild. + /// + /// + /// The description for the guild; if none is set. + /// + public string Description { get; private set; } + + /// + /// Gets the ID of this guild's splash image. + /// + /// + /// An identifier for the splash image; if none is set. + /// + public string SplashId { get; private set; } + + /// + /// Gets the URL of this guild's splash image. + /// + /// + /// A URL pointing to the guild's splash image; if none is set. + /// + public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); + + /// + /// Gets the identifier for this guilds banner image. + /// + /// + /// An identifier for the banner image; if none is set. + /// + public string BannerId { get; private set; } + + /// + /// Gets the URL of this guild's banner image. + /// + /// + /// A URL pointing to the guild's banner image; if none is set. + /// + public string BannerUrl => CDN.GetGuildBannerUrl(Id, BannerId, ImageFormat.Auto); + + /// + /// Gets the features for this guild. + /// + /// + /// A flags enum containing all the features for the guild. + /// + public GuildFeatures Features { get; private set; } + + /// + /// Gets the ID of this guild's icon. + /// + /// + /// An identifier for the splash image; if none is set. + /// + public string IconId { get; private set; } + + /// + /// Gets the URL of this guild's icon. + /// + /// + /// A URL pointing to the guild's icon; if none is set. + /// + public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); + + /// + /// + /// Gets the level of requirements a user must fulfill before being allowed to post messages in this guild. + /// + /// + /// The level of requirements. + /// + public VerificationLevel VerificationLevel { get; private set; } + + /// + /// Gets the code for this guild's vanity invite URL. + /// + /// + /// A string containing the vanity invite code for this guild; if none is set. + /// + public string VanityURLCode { get; private set; } + + /// + /// Gets the number of premium subscribers of this guild. + /// + /// + /// This is the number of users who have boosted this guild. + /// + /// + /// The number of premium subscribers of this guild; + /// + public int PremiumSubscriptionCount { get; private set; } + + /// + /// Gets the NSFW level of this guild. + /// + /// + /// The NSFW level of this guild. + /// + public NsfwLevel NsfwLevel { get; private set; } + + /// + /// Gets the Welcome Screen of this guild + /// + /// + /// The welcome screen of this guild. if none is set. + /// + public WelcomeScreen WelcomeScreen { get; private set; } + + internal InviteGuild( + ulong id, + string name, + string description, + string splashId, + string bannerId, + GuildFeatures features, + string iconId, + VerificationLevel verificationLevel, + string vanityURLCode, + int premiumSubscriptionCount, + NsfwLevel nsfwLevel, + WelcomeScreen welcomeScreen) + { + Id = id; + Name = name; + Description = description; + SplashId = splashId; + BannerId = bannerId; + Features = features; + IconId = iconId; + VerificationLevel = verificationLevel; + VanityURLCode = vanityURLCode; + PremiumSubscriptionCount = premiumSubscriptionCount; + NsfwLevel = nsfwLevel; + WelcomeScreen = welcomeScreen; + } +} diff --git a/src/Discord.Net.Rest/API/Common/Guild.cs b/src/Discord.Net.Rest/API/Common/Guild.cs index d550c54a0..d091c26a7 100644 --- a/src/Discord.Net.Rest/API/Common/Guild.cs +++ b/src/Discord.Net.Rest/API/Common/Guild.cs @@ -83,5 +83,8 @@ namespace Discord.API public Sticker[] Stickers { get; set; } [JsonProperty("premium_progress_bar_enabled")] public Optional IsBoostProgressBarEnabled { get; set; } + + [JsonProperty("welcome_screen")] + public Optional WelcomeScreen { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Common/InviteGuild.cs b/src/Discord.Net.Rest/API/Common/InviteGuild.cs index f5c634e4e..82a17d68a 100644 --- a/src/Discord.Net.Rest/API/Common/InviteGuild.cs +++ b/src/Discord.Net.Rest/API/Common/InviteGuild.cs @@ -6,9 +6,41 @@ namespace Discord.API { [JsonProperty("id")] public ulong Id { get; set; } + [JsonProperty("name")] public string Name { get; set; } - [JsonProperty("splash_hash")] - public string SplashHash { get; set; } + + [JsonProperty("splash")] + public Optional Splash { get; set; } + + [JsonProperty("banner")] + public Optional BannerHash { get; set; } + + [JsonProperty("description")] + public Optional Description { get; set; } + + [JsonProperty("icon")] + public Optional IconHash { get; set; } + + [JsonProperty("features")] + public GuildFeatures Features { get; set; } + + [JsonProperty("verification_level")] + public VerificationLevel VerificationLevel { get; set; } + + [JsonProperty("vanity_url_code")] + public Optional VanityUrlCode { get; set; } + + [JsonProperty("premium_subscription_count")] + public Optional PremiumSubscriptionCount { get; set; } + + [JsonProperty("nsfw")] + public Optional Nsfw { get; set; } + + [JsonProperty("nsfw_level")] + public NsfwLevel NsfwLevel { get; set; } + + [JsonProperty("welcome_screen")] + public Optional WelcomeScreen { get; set; } } } diff --git a/src/Discord.Net.Rest/API/Common/WelcomeScreen.cs b/src/Discord.Net.Rest/API/Common/WelcomeScreen.cs new file mode 100644 index 000000000..a462eaec1 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/WelcomeScreen.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class WelcomeScreen +{ + [JsonProperty("description")] + public Optional Description { get; set; } + + [JsonProperty("welcome_channels")] + public WelcomeScreenChannel[] WelcomeChannels { get; set; } +} diff --git a/src/Discord.Net.Rest/API/Common/WelcomeScreenChannel.cs b/src/Discord.Net.Rest/API/Common/WelcomeScreenChannel.cs new file mode 100644 index 000000000..426883dc5 --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/WelcomeScreenChannel.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class WelcomeScreenChannel +{ + [JsonProperty("channel_id")] + public ulong ChannelId { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("emoji_id")] + public Optional EmojiId { get; set; } + + [JsonProperty("emoji_name")] + public Optional EmojiName{ get; set; } +} diff --git a/src/Discord.Net.Rest/API/Rest/ModifyGuildWelcomeScreenParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyGuildWelcomeScreenParams.cs new file mode 100644 index 000000000..cf22bd927 --- /dev/null +++ b/src/Discord.Net.Rest/API/Rest/ModifyGuildWelcomeScreenParams.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; + +namespace Discord.API.Rest; + +internal class ModifyGuildWelcomeScreenParams +{ + [JsonProperty("enabled")] + public Optional Enabled { get; set; } + + [JsonProperty("welcome_channels")] + public Optional WelcomeChannels { get; set; } + + [JsonProperty("description")] + public Optional Description { get; set; } +} diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 615e5ac12..cefffadd4 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -2097,6 +2097,35 @@ namespace Discord.API #endregion + #region Guild Welcome Screen + + public async Task GetGuildWelcomeScreenAsync(ulong guildId, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + options = RequestOptions.CreateOrClone(options); + + try + { + var ids = new BucketIds(guildId: guildId); + return await SendAsync("GET", () => $"guilds/{guildId}/welcome-screen", ids, options: options).ConfigureAwait(false); + } + catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; } + } + + public async Task ModifyGuildWelcomeScreenAsync(ModifyGuildWelcomeScreenParams args, ulong guildId, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + Preconditions.NotNull(args, nameof(args)); + + options = RequestOptions.CreateOrClone(options); + + var ids = new BucketIds(guildId: guildId); + + return await SendJsonAsync("PATCH", () => $"guilds/{guildId}/welcome-screen", args, ids, options: options).ConfigureAwait(false); + } + + #endregion + #region Users public async Task GetUserAsync(ulong userId, RequestOptions options = null) { diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 74e797fd4..530f7ce5a 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -20,7 +20,8 @@ namespace Discord.Rest public static async Task ModifyAsync(IGuild guild, BaseDiscordClient client, Action func, RequestOptions options) { - if (func == null) throw new ArgumentNullException(nameof(func)); + if (func == null) + throw new ArgumentNullException(nameof(func)); var args = new GuildProperties(); func(args); @@ -141,7 +142,7 @@ namespace Discord.Rest }; var mebibyte = Math.Pow(2, 20); - return (ulong) (tierFactor * mebibyte); + return (ulong)(tierFactor * mebibyte); } #endregion @@ -232,7 +233,8 @@ namespace Discord.Rest public static async Task CreateTextChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options, Action func = null) { - if (name == null) throw new ArgumentNullException(paramName: nameof(name)); + if (name == null) + throw new ArgumentNullException(paramName: nameof(name)); var props = new TextChannelProperties(); func?.Invoke(props); @@ -262,7 +264,8 @@ namespace Discord.Rest public static async Task CreateVoiceChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options, Action func = null) { - if (name == null) throw new ArgumentNullException(paramName: nameof(name)); + if (name == null) + throw new ArgumentNullException(paramName: nameof(name)); var props = new VoiceChannelProperties(); func?.Invoke(props); @@ -318,7 +321,8 @@ namespace Discord.Rest public static async Task CreateCategoryChannelAsync(IGuild guild, BaseDiscordClient client, string name, RequestOptions options, Action func = null) { - if (name == null) throw new ArgumentNullException(paramName: nameof(name)); + if (name == null) + throw new ArgumentNullException(paramName: nameof(name)); var props = new GuildChannelProperties(); func?.Invoke(props); @@ -448,11 +452,13 @@ namespace Discord.Rest RequestOptions options) { var vanityModel = await client.ApiClient.GetVanityInviteAsync(guild.Id, options).ConfigureAwait(false); - if (vanityModel == null) throw new InvalidOperationException("This guild does not have a vanity URL."); + if (vanityModel == null) + throw new InvalidOperationException("This guild does not have a vanity URL."); var inviteModel = await client.ApiClient.GetInviteAsync(vanityModel.Code, options).ConfigureAwait(false); inviteModel.Uses = vanityModel.Uses; return RestInviteMetadata.Create(client, guild, null, inviteModel); } + #endregion #region Roles @@ -460,7 +466,8 @@ namespace Discord.Rest public static async Task CreateRoleAsync(IGuild guild, BaseDiscordClient client, string name, GuildPermissions? permissions, Color? color, bool isHoisted, bool isMentionable, RequestOptions options) { - if (name == null) throw new ArgumentNullException(paramName: nameof(name)); + if (name == null) + throw new ArgumentNullException(paramName: nameof(name)); var createGuildRoleParams = new API.Rest.ModifyGuildRoleParams { @@ -676,7 +683,8 @@ namespace Discord.Rest public static async Task ModifyEmoteAsync(IGuild guild, BaseDiscordClient client, ulong id, Action func, RequestOptions options) { - if (func == null) throw new ArgumentNullException(paramName: nameof(func)); + if (func == null) + throw new ArgumentNullException(paramName: nameof(func)); var props = new EmoteProperties(); func(props); @@ -867,7 +875,7 @@ namespace Discord.Rest { switch (args.Status.Value) { - case GuildScheduledEventStatus.Active when guildEvent.Status != GuildScheduledEventStatus.Scheduled: + case GuildScheduledEventStatus.Active when guildEvent.Status != GuildScheduledEventStatus.Scheduled: case GuildScheduledEventStatus.Completed when guildEvent.Status != GuildScheduledEventStatus.Active: case GuildScheduledEventStatus.Cancelled when guildEvent.Status != GuildScheduledEventStatus.Scheduled: throw new ArgumentException($"Cannot set event to {args.Status.Value} when events status is {guildEvent.Status}"); @@ -909,7 +917,7 @@ namespace Discord.Rest : Optional.Unspecified }; - if(args.Location.IsSpecified) + if (args.Location.IsSpecified) { apiArgs.EntityMetadata = new API.GuildScheduledEventEntityMetadata() { @@ -949,7 +957,7 @@ namespace Discord.Rest Image? bannerImage = null, RequestOptions options = null) { - if(location != null) + if (location != null) { Preconditions.AtMost(location.Length, 100, nameof(location)); } @@ -985,7 +993,7 @@ namespace Discord.Rest Image = bannerImage.HasValue ? bannerImage.Value.ToModel() : Optional.Unspecified }; - if(location != null) + if (location != null) { apiArgs.EntityMetadata = new API.GuildScheduledEventEntityMetadata() { @@ -1004,5 +1012,53 @@ namespace Discord.Rest } #endregion + + #region Welcome Screen + + public static async Task GetWelcomeScreenAsync(IGuild guild, BaseDiscordClient client, RequestOptions options) + { + var model = await client.ApiClient.GetGuildWelcomeScreenAsync(guild.Id, options); + + if (model.WelcomeChannels.Length == 0) + return null; + + return new WelcomeScreen(model.Description.GetValueOrDefault(null), model.WelcomeChannels.Select( + x => new WelcomeScreenChannel( + x.ChannelId, x.Description, + x.EmojiName.GetValueOrDefault(null), + x.EmojiId.GetValueOrDefault(0))).ToList()); + } + + public static async Task ModifyWelcomeScreenAsync(bool enabled, string description, WelcomeScreenChannelProperties[] channels, IGuild guild, BaseDiscordClient client, RequestOptions options) + { + if (!guild.Features.HasFeature(GuildFeature.Community)) + throw new InvalidOperationException("Cannot update welcome screen in a non-community guild."); + + var args = new ModifyGuildWelcomeScreenParams + { + Enabled = enabled, + Description = description, + WelcomeChannels = channels?.Select(ch => new API.WelcomeScreenChannel + { + ChannelId = ch.Id, + Description = ch.Description, + EmojiName = ch.Emoji is Emoji emoj ? emoj.Name : Optional.Unspecified, + EmojiId = ch.Emoji is Emote emote ? emote.Id : Optional.Unspecified + }).ToArray() + }; + + var model = await client.ApiClient.ModifyGuildWelcomeScreenAsync(args, guild.Id, options); + + if(model.WelcomeChannels.Length == 0) + return null; + + return new WelcomeScreen(model.Description.GetValueOrDefault(null), model.WelcomeChannels.Select( + x => new WelcomeScreenChannel( + x.ChannelId, x.Description, + x.EmojiName.GetValueOrDefault(null), + x.EmojiId.GetValueOrDefault(0))).ToList()); + } + + #endregion } } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 24f6ae28d..79ec77c21 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -1534,6 +1534,15 @@ namespace Discord.Rest else return null; } + + /// + public Task GetWelcomeScreenAsync(RequestOptions options = null) + => GuildHelper.GetWelcomeScreenAsync(this, Discord, options); + + /// + public Task ModifyWelcomeScreenAsync(bool enabled, WelcomeScreenChannelProperties[] channels, string description = null, RequestOptions options = null) + => GuildHelper.ModifyWelcomeScreenAsync(enabled, description, channels, this, Discord, options); + #endregion } } diff --git a/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs b/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs index 95b454c20..93f79ad29 100644 --- a/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs +++ b/src/Discord.Net.Rest/Entities/Invites/RestInvite.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Immutable; using System.Diagnostics; +using System.Linq; using System.Threading.Tasks; using Model = Discord.API.Invite; @@ -27,7 +29,17 @@ namespace Discord.Rest public IUser TargetUser { get; private set; } /// public TargetUserType TargetUserType { get; private set; } + + /// + /// Gets the guild this invite is linked to. + /// + /// + /// A partial guild object representing the guild that the invite points to. + /// + public InviteGuild InviteGuild { get; private set; } + internal IChannel Channel { get; } + internal IGuild Guild { get; } /// @@ -59,6 +71,32 @@ namespace Discord.Rest Inviter = model.Inviter.IsSpecified ? RestUser.Create(Discord, model.Inviter.Value) : null; TargetUser = model.TargetUser.IsSpecified ? RestUser.Create(Discord, model.TargetUser.Value) : null; TargetUserType = model.TargetUserType.IsSpecified ? model.TargetUserType.Value : TargetUserType.Undefined; + + if (model.Guild.IsSpecified) + { + InviteGuild = new InviteGuild + (model.Guild.Value.Id, + model.Guild.Value.Name, + model.Guild.Value.Description.IsSpecified ? model.Guild.Value.Description.Value : null, + model.Guild.Value.Splash.IsSpecified ? model.Guild.Value.Splash.Value : null, + model.Guild.Value.BannerHash.IsSpecified ? model.Guild.Value.BannerHash.Value : null, + model.Guild.Value.Features, + model.Guild.Value.IconHash.IsSpecified ? model.Guild.Value.IconHash.Value : null, + model.Guild.Value.VerificationLevel, + model.Guild.Value.VanityUrlCode.IsSpecified ? model.Guild.Value.VanityUrlCode.Value : null, + model.Guild.Value.PremiumSubscriptionCount.GetValueOrDefault(0), + model.Guild.Value.NsfwLevel, + model.Guild.Value.WelcomeScreen.IsSpecified + ? new WelcomeScreen( + model.Guild.Value.WelcomeScreen.Value.Description.IsSpecified ? model.Guild.Value.WelcomeScreen.Value.Description.Value : null, + model.Guild.Value.WelcomeScreen.Value.WelcomeChannels.Select(ch => + new WelcomeScreenChannel( + ch.ChannelId, + ch.Description, + ch.EmojiName.IsSpecified ? ch.EmojiName.Value : null, + ch.EmojiId.IsSpecified ? ch.EmojiId.Value : null)).ToImmutableArray()) + : null); + } } /// diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index c2778ed1d..f23804fb6 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -2039,6 +2039,14 @@ namespace Discord.WebSocket RequestOptions options) => await BulkOverwriteApplicationCommandAsync(properties, options); + /// + public Task GetWelcomeScreenAsync(RequestOptions options = null) + => GuildHelper.GetWelcomeScreenAsync(this, Discord, options); + + /// + public Task ModifyWelcomeScreenAsync(bool enabled, WelcomeScreenChannelProperties[] channels, string description = null, RequestOptions options = null) + => GuildHelper.ModifyWelcomeScreenAsync(enabled, description, channels, this, Discord, options); + void IDisposable.Dispose() { DisconnectAudioAsync().GetAwaiter().GetResult();