diff --git a/src/Discord.Net.Core/CDN.cs b/src/Discord.Net.Core/CDN.cs
index 0fefc9a0d..32ffbba90 100644
--- a/src/Discord.Net.Core/CDN.cs
+++ b/src/Discord.Net.Core/CDN.cs
@@ -23,7 +23,7 @@ namespace Discord
///
/// The user snowflake identifier.
/// The avatar identifier.
- /// The size of the image to return in. This can be any power of two between 16 and 2048.
+ /// The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048.
/// The format to return.
///
/// A URL pointing to the user's avatar in the specified size.
@@ -76,6 +76,22 @@ namespace Discord
///
public static string GetChannelIconUrl(ulong channelId, string iconId)
=> iconId != null ? $"{DiscordConfig.CDNUrl}channel-icons/{channelId}/{iconId}.jpg" : null;
+
+ ///
+ /// Returns a guild banner URL.
+ ///
+ /// The guild snowflake identifier.
+ /// The banner image identifier.
+ /// The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048 inclusive.
+ ///
+ /// A URL pointing to the guild's banner image.
+ ///
+ public static string GetGuildBannerUrl(ulong guildId, string bannerId, ushort? size = null)
+ {
+ if (!string.IsNullOrEmpty(bannerId))
+ return $"{DiscordConfig.CDNUrl}banners/{guildId}/{bannerId}.jpg" + (size.HasValue ? $"?size={size}" : string.Empty);
+ return null;
+ }
///
/// Returns an emoji URL.
///
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs b/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
index e6d21a463..e13536a97 100644
--- a/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
@@ -70,5 +70,19 @@ namespace Discord
/// Gets or sets the explicit content filter level of this guild.
///
public Optional ExplicitContentFilter { get; set; }
+ ///
+ /// Gets or sets the flags that DISABLE types of system channel messages.
+ ///
+ ///
+ /// These flags are inverted. Setting a flag will disable that system channel message from being sent.
+ /// A value of will allow all system channel message types to be sent,
+ /// given that the has also been set.
+ /// A value of will deny guild boost messages from being sent, and allow all
+ /// other types of messages.
+ /// Refer to the extension methods and
+ /// to check if these system channel message types
+ /// are enabled, without the need to manipulate the logic of the flag.
+ ///
+ public Optional SystemChannelFlags { get; set; }
}
}
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
index 571afef15..378ca069b 100644
--- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
@@ -196,6 +196,58 @@ namespace Discord
/// A read-only collection of roles found within this guild.
///
IReadOnlyCollection Roles { get; }
+ ///
+ /// Gets the tier of guild boosting in this guild.
+ ///
+ ///
+ /// The tier of guild boosting in this guild.
+ ///
+ PremiumTier PremiumTier { get; }
+ ///
+ /// Gets the identifier for this guilds banner image.
+ ///
+ ///
+ /// An identifier for the banner image; null if none is set.
+ ///
+ string BannerId { get; }
+ ///
+ /// Gets the URL of this guild's banner image.
+ ///
+ ///
+ /// A URL pointing to the guild's banner image; null if none is set.
+ ///
+ string BannerUrl { get; }
+ ///
+ /// Gets the code for this guild's vanity invite URL.
+ ///
+ ///
+ /// A string containing the vanity invite code for this guild; null if none is set.
+ ///
+ string VanityURLCode { get; }
+ ///
+ /// Gets the flags for the types of system channel messages that are disabled.
+ ///
+ ///
+ /// The flags for the types of system channel messages that are disabled.
+ ///
+ SystemChannelMessageDeny SystemChannelFlags { get; }
+ ///
+ /// Gets the description for the guild.
+ ///
+ ///
+ /// The description for the guild; null if none is set.
+ ///
+ string Description { get; }
+ ///
+ /// 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.
+ ///
+ int PremiumSubscriptionCount { get; }
///
/// Modifies this guild.
diff --git a/src/Discord.Net.Core/Entities/Guilds/PremiumTier.cs b/src/Discord.Net.Core/Entities/Guilds/PremiumTier.cs
new file mode 100644
index 000000000..b7e4c9323
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/PremiumTier.cs
@@ -0,0 +1,22 @@
+namespace Discord
+{
+ public enum PremiumTier
+ {
+ ///
+ /// Used for guilds that have no guild boosts.
+ ///
+ None = 0,
+ ///
+ /// Used for guilds that have Tier 1 guild boosts.
+ ///
+ Tier1 = 1,
+ ///
+ /// Used for guilds that have Tier 2 guild boosts.
+ ///
+ Tier2 = 2,
+ ///
+ /// Used for guilds that have Tier 3 guild boosts.
+ ///
+ Tier3 = 3
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs b/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs
new file mode 100644
index 000000000..3f69693d0
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Discord
+{
+ [Flags]
+ public enum SystemChannelMessageDeny
+ {
+ ///
+ /// Deny none of the system channel messages.
+ /// This will enable all of the system channel messages.
+ ///
+ None = 0,
+ ///
+ /// Deny the messages that are sent when a user joins the guild.
+ ///
+ WelcomeMessage = 0b1,
+ ///
+ /// Deny the messages that are sent when a user boosts the guild.
+ ///
+ GuildBoost = 0b10
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Messages/MessageType.cs b/src/Discord.Net.Core/Entities/Messages/MessageType.cs
index 8f3af843b..66b49e557 100644
--- a/src/Discord.Net.Core/Entities/Messages/MessageType.cs
+++ b/src/Discord.Net.Core/Entities/Messages/MessageType.cs
@@ -36,6 +36,22 @@ namespace Discord
///
/// The message when a new member joined.
///
- GuildMemberJoin = 7
+ GuildMemberJoin = 7,
+ ///
+ /// The message for when a user boosts a guild.
+ ///
+ UserPremiumGuildSubscription = 8,
+ ///
+ /// The message for when a guild reaches Tier 1 of Nitro boosts.
+ ///
+ UserPremiumGuildSubscriptionTier1 = 9,
+ ///
+ /// The message for when a guild reaches Tier 2 of Nitro boosts.
+ ///
+ UserPremiumGuildSubscriptionTier2 = 10,
+ ///
+ /// The message for when a guild reaches Tier 3 of Nitro boosts.
+ ///
+ UserPremiumGuildSubscriptionTier3 = 11
}
}
diff --git a/src/Discord.Net.Core/Entities/Users/IGuildUser.cs b/src/Discord.Net.Core/Entities/Users/IGuildUser.cs
index 718587ae4..d162b5164 100644
--- a/src/Discord.Net.Core/Entities/Users/IGuildUser.cs
+++ b/src/Discord.Net.Core/Entities/Users/IGuildUser.cs
@@ -48,6 +48,13 @@ namespace Discord
///
ulong GuildId { get; }
///
+ /// Gets the date and time for when this user's guild boost began.
+ ///
+ ///
+ /// A for when the user began boosting this guild; null if they are not boosting the guild.
+ ///
+ DateTimeOffset? PremiumSince { get; }
+ ///
/// Gets a collection of IDs for the roles that this user currently possesses in the guild.
///
///
diff --git a/src/Discord.Net.Core/Extensions/GuildExtensions.cs b/src/Discord.Net.Core/Extensions/GuildExtensions.cs
new file mode 100644
index 000000000..58b749cc4
--- /dev/null
+++ b/src/Discord.Net.Core/Extensions/GuildExtensions.cs
@@ -0,0 +1,24 @@
+namespace Discord
+{
+ ///
+ /// An extension class for .
+ ///
+ public static class GuildExtensions
+ {
+ ///
+ /// Gets if welcome system messages are enabled.
+ ///
+ /// The guild to check.
+ /// A bool indicating if the welcome messages are enabled in the system channel.
+ public static bool GetWelcomeMessagesEnabled(this IGuild guild)
+ => !guild.SystemChannelFlags.HasFlag(SystemChannelMessageDeny.WelcomeMessage);
+
+ ///
+ /// Gets if guild boost system messages are enabled.
+ ///
+ /// The guild to check.
+ /// A bool indicating if the guild boost messages are enabled in the system channel.
+ public static bool GetGuildBoostMessagesEnabled(this IGuild guild)
+ => !guild.SystemChannelFlags.HasFlag(SystemChannelMessageDeny.GuildBoost);
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/Guild.cs b/src/Discord.Net.Rest/API/Common/Guild.cs
index a84b55a93..343d5b12c 100644
--- a/src/Discord.Net.Rest/API/Common/Guild.cs
+++ b/src/Discord.Net.Rest/API/Common/Guild.cs
@@ -45,5 +45,18 @@ namespace Discord.API
public ulong? ApplicationId { get; set; }
[JsonProperty("system_channel_id")]
public ulong? SystemChannelId { get; set; }
+ [JsonProperty("premium_tier")]
+ public PremiumTier PremiumTier { get; set; }
+ [JsonProperty("vanity_url_code")]
+ public string VanityURLCode { get; set; }
+ [JsonProperty("banner")]
+ public string Banner { get; set; }
+ [JsonProperty("description")]
+ public string Description { get; set; }
+ // this value is inverted, flags set will turn OFF features
+ [JsonProperty("system_channel_flags")]
+ public SystemChannelMessageDeny SystemChannelFlags { get; set; }
+ [JsonProperty("premium_subscription_count")]
+ public int? PremiumSubscriptionCount { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Common/GuildMember.cs b/src/Discord.Net.Rest/API/Common/GuildMember.cs
index 24ad17c14..940eb925a 100644
--- a/src/Discord.Net.Rest/API/Common/GuildMember.cs
+++ b/src/Discord.Net.Rest/API/Common/GuildMember.cs
@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591
using Newtonsoft.Json;
using System;
@@ -18,5 +18,7 @@ namespace Discord.API
public Optional Deaf { get; set; }
[JsonProperty("mute")]
public Optional Mute { get; set; }
+ [JsonProperty("premium_since")]
+ public Optional PremiumSince { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
index ba70c58d6..9c519d3a8 100644
--- a/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
@@ -30,5 +30,7 @@ namespace Discord.API.Rest
public Optional OwnerId { get; set; }
[JsonProperty("explicit_content_filter")]
public Optional ExplicitContentFilter { get; set; }
+ [JsonProperty("system_channel_flags")]
+ public Optional SystemChannelFlags { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
index cfb7c4ff7..a9b51c113 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
@@ -33,7 +33,8 @@ namespace Discord.Rest
Name = args.Name,
Splash = args.Splash.IsSpecified ? args.Splash.Value?.ToModel() : Optional.Create(),
VerificationLevel = args.VerificationLevel,
- ExplicitContentFilter = args.ExplicitContentFilter
+ ExplicitContentFilter = args.ExplicitContentFilter,
+ SystemChannelFlags = args.SystemChannelFlags
};
if (args.AfkChannel.IsSpecified)
@@ -64,6 +65,9 @@ namespace Discord.Rest
if (args.ExplicitContentFilter.IsSpecified)
apiArgs.ExplicitContentFilter = args.ExplicitContentFilter.Value;
+ if (args.SystemChannelFlags.IsSpecified)
+ apiArgs.SystemChannelFlags = args.SystemChannelFlags.Value;
+
return await client.ApiClient.ModifyGuildAsync(guild.Id, apiArgs, options).ConfigureAwait(false);
}
/// is null.
diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
index 902d2c9a8..7ed258155 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
@@ -52,6 +52,18 @@ namespace Discord.Rest
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 DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
@@ -62,6 +74,8 @@ namespace Discord.Rest
public string IconUrl => CDN.GetGuildIconUrl(Id, IconId);
///
public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId);
+ ///
+ public string BannerUrl => CDN.GetGuildBannerUrl(Id, BannerId);
///
/// Gets the built-in role containing all users in this guild.
@@ -104,6 +118,12 @@ namespace Discord.Rest
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();
if (model.Emojis != null)
{
diff --git a/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs b/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
index e59d92407..27a910576 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
@@ -14,6 +14,7 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGuildUser : RestUser, IGuildUser
{
+ private long? _premiumSinceTicks;
private long? _joinedAtTicks;
private ImmutableArray _roleIds;
@@ -24,7 +25,8 @@ namespace Discord.Rest
public bool IsDeafened { get; private set; }
///
public bool IsMuted { get; private set; }
-
+ ///
+ public DateTimeOffset? PremiumSince => DateTimeUtils.FromTicks(_premiumSinceTicks);
///
public ulong GuildId => Guild.Id;
@@ -69,6 +71,8 @@ namespace Discord.Rest
IsMuted = model.Mute.Value;
if (model.Roles.IsSpecified)
UpdateRoles(model.Roles.Value);
+ if (model.PremiumSince.IsSpecified)
+ _premiumSinceTicks = model.PremiumSince.Value?.UtcTicks;
}
private void UpdateRoles(ulong[] roleIds)
{
diff --git a/src/Discord.Net.Rest/Entities/Users/RestWebhookUser.cs b/src/Discord.Net.Rest/Entities/Users/RestWebhookUser.cs
index bee4892fe..67914e873 100644
--- a/src/Discord.Net.Rest/Entities/Users/RestWebhookUser.cs
+++ b/src/Discord.Net.Rest/Entities/Users/RestWebhookUser.cs
@@ -13,6 +13,8 @@ namespace Discord.Rest
///
public ulong WebhookId { get; }
internal IGuild Guild { get; }
+ ///
+ public DateTimeOffset? PremiumSince { get; private set; }
///
public override bool IsWebhook => true;
diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
index d952b3d92..d5cbfdd64 100644
--- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
+++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
@@ -93,6 +93,18 @@ namespace Discord.WebSocket
public string IconId { get; private set; }
///
public string SplashId { 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 DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
@@ -100,6 +112,8 @@ namespace Discord.WebSocket
public string IconUrl => CDN.GetGuildIconUrl(Id, IconId);
///
public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId);
+ ///
+ public string BannerUrl => CDN.GetGuildBannerUrl(Id, BannerId);
/// Indicates whether the client has all the members downloaded to the local guild cache.
public bool HasAllMembers => MemberCount == DownloadedMemberCount;// _downloaderPromise.Task.IsCompleted;
/// Indicates whether the guild cache is synced to this guild.
@@ -354,6 +368,12 @@ namespace Discord.WebSocket
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();
if (model.Emojis != null)
{
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
index 659a2eeea..dee450cdd 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
@@ -18,6 +18,7 @@ namespace Discord.WebSocket
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketGuildUser : SocketUser, IGuildUser
{
+ private long? _premiumSinceTicks;
private long? _joinedAtTicks;
private ImmutableArray _roleIds;
@@ -75,6 +76,8 @@ namespace Discord.WebSocket
///
public SocketVoiceState? VoiceState => Guild.GetVoiceState(Id);
public AudioInStream AudioStream => Guild.GetAudioStream(Id);
+ ///
+ public DateTimeOffset? PremiumSince => DateTimeUtils.FromTicks(_premiumSinceTicks);
///
/// Returns the position of the user within the role hierarchy.
@@ -135,6 +138,8 @@ namespace Discord.WebSocket
Nickname = model.Nick.Value;
if (model.Roles.IsSpecified)
UpdateRoles(model.Roles.Value);
+ if (model.PremiumSince.IsSpecified)
+ _premiumSinceTicks = model.PremiumSince.Value?.UtcTicks;
}
internal void Update(ClientState state, PresenceModel model, bool updatePresence)
{
diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
index 3169be682..2d701ef64 100644
--- a/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
+++ b/src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
@@ -63,6 +63,8 @@ namespace Discord.WebSocket
///
string IGuildUser.Nickname => null;
///
+ DateTimeOffset? IGuildUser.PremiumSince => null;
+ ///
GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook;
///