From 7c535b952a00166e3c22e3b39a68176fe52241c6 Mon Sep 17 00:00:00 2001
From: Misha133 <61027276+Misha-133@users.noreply.github.com>
Date: Sun, 25 Dec 2022 17:40:05 +0300
Subject: [PATCH] [Feature] add missing invite guild properties & welcome
screen support (#2510)
* added models
* working getter for welcome screen
*
* more changes
* modify welcome screen support
* fix some typos & remove `using` added by VS
* Working-ish state
* Resolve some reviews
* change access modifier
* forgot to add docs
* revert to InviteGuild & extend it
* resolve some reviews
* Apply suggestions from code review
Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>
Co-authored-by: Cenk Ergen <57065323+Cenngo@users.noreply.github.com>
Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com>
---
.../Entities/Guilds/IGuild.cs | 16 ++
.../Entities/Guilds/WelcomeScreen.cs | 24 +++
.../Entities/Guilds/WelcomeScreenChannel.cs | 41 +++++
.../Guilds/WelcomeScreenChannelProperties.cs | 54 ++++++
.../Entities/Invites/IInvite.cs | 1 +
.../Entities/Invites/InviteGuild.cs | 156 ++++++++++++++++++
src/Discord.Net.Rest/API/Common/Guild.cs | 3 +
.../API/Common/InviteGuild.cs | 36 +++-
.../API/Common/WelcomeScreen.cs | 12 ++
.../API/Common/WelcomeScreenChannel.cs | 18 ++
.../Rest/ModifyGuildWelcomeScreenParams.cs | 15 ++
src/Discord.Net.Rest/DiscordRestApiClient.cs | 29 ++++
.../Entities/Guilds/GuildHelper.cs | 80 +++++++--
.../Entities/Guilds/RestGuild.cs | 9 +
.../Entities/Invites/RestInvite.cs | 38 +++++
.../Entities/Guilds/SocketGuild.cs | 8 +
16 files changed, 526 insertions(+), 14 deletions(-)
create mode 100644 src/Discord.Net.Core/Entities/Guilds/WelcomeScreen.cs
create mode 100644 src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannel.cs
create mode 100644 src/Discord.Net.Core/Entities/Guilds/WelcomeScreenChannelProperties.cs
create mode 100644 src/Discord.Net.Core/Entities/Invites/InviteGuild.cs
create mode 100644 src/Discord.Net.Rest/API/Common/WelcomeScreen.cs
create mode 100644 src/Discord.Net.Rest/API/Common/WelcomeScreenChannel.cs
create mode 100644 src/Discord.Net.Rest/API/Rest/ModifyGuildWelcomeScreenParams.cs
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();