Browse Source

Merge remote-tracking branch 'origin/release/2.x' into release/3.x

pull/1923/head
quin lynch 3 years ago
parent
commit
1caca93b30
27 changed files with 259 additions and 73 deletions
  1. +18
    -0
      src/Discord.Net.Core/CDN.cs
  2. +5
    -0
      src/Discord.Net.Core/Discord.Net.Core.xml
  3. +19
    -14
      src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
  4. +59
    -42
      src/Discord.Net.Core/Entities/Roles/Color.cs
  5. +27
    -5
      src/Discord.Net.Core/Entities/Users/IUser.cs
  6. +6
    -1
      src/Discord.Net.Core/Entities/Webhooks/IWebhook.cs
  7. +4
    -0
      src/Discord.Net.Rest/API/Common/User.cs
  8. +2
    -0
      src/Discord.Net.Rest/API/Common/Webhook.cs
  9. +2
    -0
      src/Discord.Net.Rest/API/Rest/ModifyWebhookMessageParams.cs
  10. +3
    -0
      src/Discord.Net.Rest/Discord.Net.Rest.xml
  11. +2
    -2
      src/Discord.Net.Rest/Entities/Users/RestThreadUser.cs
  12. +12
    -0
      src/Discord.Net.Rest/Entities/Users/RestUser.cs
  13. +4
    -0
      src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs
  14. +1
    -0
      src/Discord.Net.Rest/Extensions/EntityExtensions.cs
  15. +3
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs
  16. +4
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs
  17. +6
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs
  18. +4
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
  19. +15
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs
  20. +8
    -1
      src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs
  21. +18
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs
  22. +17
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs
  23. +6
    -1
      src/Discord.Net.Webhook/Discord.Net.Webhook.xml
  24. +2
    -2
      src/Discord.Net.Webhook/DiscordWebhookClient.cs
  25. +4
    -0
      src/Discord.Net.Webhook/Entities/Messages/WebhookMessageProperties.cs
  26. +3
    -0
      src/Discord.Net.Webhook/Entities/Webhooks/RestInternalWebhook.cs
  27. +5
    -2
      src/Discord.Net.Webhook/WebhookClientHelper.cs

+ 18
- 0
src/Discord.Net.Core/CDN.cs View File

@@ -46,6 +46,24 @@ namespace Discord
string extension = FormatToExtension(format, avatarId);
return $"{DiscordConfig.CDNUrl}avatars/{userId}/{avatarId}.{extension}?size={size}";
}

/// <summary>
/// Returns a user banner URL.
/// </summary>
/// <param name="userId">The user snowflake identifier.</param>
/// <param name="bannerId">The banner identifier.</param>
/// <param name="size">The size of the image to return in horizontal pixels. This can be any power of two between 16 and 2048.</param>
/// <param name="format">The format to return.</param>
/// <returns>
/// A URL pointing to the user's banner in the specified size.
/// </returns>
public static string GetUserBannerUrl(ulong userId, string bannerId, ushort size, ImageFormat format)
{
if (bannerId == null)
return null;
string extension = FormatToExtension(format, bannerId);
return $"{DiscordConfig.CDNUrl}banners/{userId}/{bannerId}.{extension}?size={size}";
}
/// <summary>
/// Returns the default user avatar URL.
/// </summary>


+ 5
- 0
src/Discord.Net.Core/Discord.Net.Core.xml View File

@@ -10144,6 +10144,11 @@
Gets the user that created this webhook.
</summary>
</member>
<member name="P:Discord.IWebhook.ApplicationId">
<summary>
Gets the ID of the application owning this webhook.
</summary>
</member>
<member name="M:Discord.IWebhook.ModifyAsync(System.Action{Discord.WebhookProperties},Discord.RequestOptions)">
<summary>
Modifies this webhook.


+ 19
- 14
src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs View File

@@ -10,11 +10,6 @@ namespace Discord
/// </summary>
public class ComponentBuilder
{
/// <summary>
/// The max length of a <see cref="ButtonComponent.Label"/>.
/// </summary>
public const int MaxLabelLength = 80;

/// <summary>
/// The max length of a <see cref="ButtonComponent.CustomId"/>.
/// </summary>
@@ -307,17 +302,22 @@ namespace Discord
/// </summary>
public class ButtonBuilder
{
/// <summary>
/// The max length of a <see cref="ButtonComponent.Label"/>.
/// </summary>
public const int MaxLabelLength = 80;

/// <summary>
/// Gets or sets the label of the current button.
/// </summary>
/// <exception cref="ArgumentException" accessor="set"><see cref="Label"/> length exceeds <see cref="ComponentBuilder.MaxLabelLength"/>.</exception>
/// <exception cref="ArgumentException" accessor="set"><see cref="Label"/> length exceeds <see cref="MaxLabelLength"/>.</exception>
public string Label
{
get => _label;
set
{
if (value != null && value.Length > ComponentBuilder.MaxLabelLength)
throw new ArgumentException(message: $"Button label must be {ComponentBuilder.MaxLabelLength} characters or less!", paramName: nameof(Label));
if (value != null && value.Length > MaxLabelLength)
throw new ArgumentException(message: $"Button label must be {MaxLabelLength} characters or less!", paramName: nameof(Label));

_label = value;
}
@@ -539,8 +539,8 @@ namespace Discord
if (string.IsNullOrEmpty(this.Url))
throw new InvalidOperationException("Link buttons must have a link associated with them");
else
UrlValidation.Validate(this.Url);
}
UrlValidation.Validate(this.Url);
}
else if (string.IsNullOrEmpty(this.CustomId))
throw new InvalidOperationException("Non-link buttons must have a custom id associated with them");

@@ -831,23 +831,28 @@ namespace Discord
/// </summary>
public class SelectMenuOptionBuilder
{
/// <summary>
/// The maximum length of a <see cref="SelectMenuOption.Label"/>.
/// </summary>
public const int MaxLabelLength = 100;

/// <summary>
/// The maximum length of a <see cref="SelectMenuOption.Description"/>.
/// </summary>
public const int MaxDescriptionLength = 50;
public const int MaxDescriptionLength = 100;

/// <summary>
/// Gets or sets the label of the current select menu.
/// </summary>
/// <exception cref="ArgumentException" accessor="set"><see cref="Label"/> length exceeds <see cref="ComponentBuilder.MaxLabelLength"/></exception>
/// <exception cref="ArgumentException" accessor="set"><see cref="Label"/> length exceeds <see cref="MaxLabelLength"/></exception>
public string Label
{
get => _label;
set
{
if (value != null)
if (value.Length > ComponentBuilder.MaxLabelLength)
throw new ArgumentException(message: $"Button label must be {ComponentBuilder.MaxLabelLength} characters or less!", paramName: nameof(Label));
if (value.Length > MaxLabelLength)
throw new ArgumentException(message: $"Button label must be {MaxLabelLength} characters or less!", paramName: nameof(Label));

_label = value;
}


+ 59
- 42
src/Discord.Net.Core/Entities/Roles/Color.cs View File

@@ -10,68 +10,70 @@ namespace Discord
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public struct Color
{
/// <summary> Gets the max decimal value of color. </summary>
public const uint MaxDecimalValue = 0xFFFFFF;
/// <summary> Gets the default user color value. </summary>
public static readonly Color Default = new Color(0);
public static readonly Color Default = new(0);
/// <summary> Gets the teal color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/1ABC9C">1ABC9C</see>.</returns>
public static readonly Color Teal = new Color(0x1ABC9C);
public static readonly Color Teal = new(0x1ABC9C);
/// <summary> Gets the dark teal color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/11806A">11806A</see>.</returns>
public static readonly Color DarkTeal = new Color(0x11806A);
public static readonly Color DarkTeal = new(0x11806A);
/// <summary> Gets the green color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/2ECC71">2ECC71</see>.</returns>
public static readonly Color Green = new Color(0x2ECC71);
public static readonly Color Green = new(0x2ECC71);
/// <summary> Gets the dark green color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/1F8B4C">1F8B4C</see>.</returns>
public static readonly Color DarkGreen = new Color(0x1F8B4C);
public static readonly Color DarkGreen = new(0x1F8B4C);
/// <summary> Gets the blue color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/3498DB">3498DB</see>.</returns>
public static readonly Color Blue = new Color(0x3498DB);
public static readonly Color Blue = new(0x3498DB);
/// <summary> Gets the dark blue color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/206694">206694</see>.</returns>
public static readonly Color DarkBlue = new Color(0x206694);
public static readonly Color DarkBlue = new(0x206694);
/// <summary> Gets the purple color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/9B59B6">9B59B6</see>.</returns>
public static readonly Color Purple = new Color(0x9B59B6);
public static readonly Color Purple = new(0x9B59B6);
/// <summary> Gets the dark purple color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/71368A">71368A</see>.</returns>
public static readonly Color DarkPurple = new Color(0x71368A);
public static readonly Color DarkPurple = new(0x71368A);
/// <summary> Gets the magenta color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/E91E63">E91E63</see>.</returns>
public static readonly Color Magenta = new Color(0xE91E63);
public static readonly Color Magenta = new(0xE91E63);
/// <summary> Gets the dark magenta color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/AD1457">AD1457</see>.</returns>
public static readonly Color DarkMagenta = new Color(0xAD1457);
public static readonly Color DarkMagenta = new(0xAD1457);
/// <summary> Gets the gold color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/F1C40F">F1C40F</see>.</returns>
public static readonly Color Gold = new Color(0xF1C40F);
public static readonly Color Gold = new(0xF1C40F);
/// <summary> Gets the light orange color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/C27C0E">C27C0E</see>.</returns>
public static readonly Color LightOrange = new Color(0xC27C0E);
public static readonly Color LightOrange = new(0xC27C0E);
/// <summary> Gets the orange color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/E67E22">E67E22</see>.</returns>
public static readonly Color Orange = new Color(0xE67E22);
public static readonly Color Orange = new(0xE67E22);
/// <summary> Gets the dark orange color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/A84300">A84300</see>.</returns>
public static readonly Color DarkOrange = new Color(0xA84300);
public static readonly Color DarkOrange = new(0xA84300);
/// <summary> Gets the red color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/E74C3C">E74C3C</see>.</returns>
public static readonly Color Red = new Color(0xE74C3C);
public static readonly Color Red = new(0xE74C3C);
/// <summary> Gets the dark red color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/992D22">992D22</see>.</returns>
public static readonly Color DarkRed = new Color(0x992D22);
public static readonly Color DarkRed = new(0x992D22);
/// <summary> Gets the light grey color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/979C9F">979C9F</see>.</returns>
public static readonly Color LightGrey = new Color(0x979C9F);
public static readonly Color LightGrey = new(0x979C9F);
/// <summary> Gets the lighter grey color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/95A5A6">95A5A6</see>.</returns>
public static readonly Color LighterGrey = new Color(0x95A5A6);
public static readonly Color LighterGrey = new(0x95A5A6);
/// <summary> Gets the dark grey color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/607D8B">607D8B</see>.</returns>
public static readonly Color DarkGrey = new Color(0x607D8B);
public static readonly Color DarkGrey = new(0x607D8B);
/// <summary> Gets the darker grey color value. </summary>
/// <returns> A color struct with the hex value of <see href="http://www.color-hex.com/color/546E7A">546E7A</see>.</returns>
public static readonly Color DarkerGrey = new Color(0x546E7A);
public static readonly Color DarkerGrey = new(0x546E7A);

/// <summary> Gets the encoded value for this color. </summary>
/// <remarks>
@@ -91,22 +93,27 @@ namespace Discord
/// Initializes a <see cref="Color"/> struct with the given raw value.
/// </summary>
/// <example>
/// The following will create a color that has a hex value of
/// The following will create a color that has a hex value of
/// <see href="http://www.color-hex.com/color/607d8b">#607D8B</see>.
/// <code language="cs">
/// Color darkGrey = new Color(0x607D8B);
/// </code>
/// </example>
/// <param name="rawValue">The raw value of the color (e.g. <c>0x607D8B</c>).</param>
/// <exception cref="ArgumentException">Value exceeds <see cref="MaxDecimalValue"/>.</exception>
public Color(uint rawValue)
{
if (rawValue > MaxDecimalValue)
throw new ArgumentException($"{nameof(RawValue)} of color cannot be greater than {MaxDecimalValue}!", nameof(rawValue));

RawValue = rawValue;
}

/// <summary>
/// Initializes a <see cref="Color" /> struct with the given RGB bytes.
/// </summary>
/// <example>
/// The following will create a color that has a value of
/// The following will create a color that has a value of
/// <see href="http://www.color-hex.com/color/607d8b">#607D8B</see>.
/// <code language="cs">
/// Color darkGrey = new Color((byte)0b_01100000, (byte)0b_01111101, (byte)0b_10001011);
@@ -115,19 +122,24 @@ namespace Discord
/// <param name="r">The byte that represents the red color.</param>
/// <param name="g">The byte that represents the green color.</param>
/// <param name="b">The byte that represents the blue color.</param>
/// <exception cref="ArgumentException">Value exceeds <see cref="MaxDecimalValue"/>.</exception>
public Color(byte r, byte g, byte b)
{
RawValue =
((uint)r << 16) |
((uint)g << 8) |
(uint)b;
uint value = ((uint)r << 16)
| ((uint)g << 8)
| (uint)b;

if (value > MaxDecimalValue)
throw new ArgumentException($"{nameof(RawValue)} of color cannot be greater than {MaxDecimalValue}!");

RawValue = value;
}

/// <summary>
/// Initializes a <see cref="Color"/> struct with the given RGB value.
/// </summary>
/// <example>
/// The following will create a color that has a value of
/// The following will create a color that has a value of
/// <see href="http://www.color-hex.com/color/607d8b">#607D8B</see>.
/// <code language="cs">
/// Color darkGrey = new Color(96, 125, 139);
@@ -145,16 +157,15 @@ namespace Discord
throw new ArgumentOutOfRangeException(nameof(g), "Value must be within [0,255].");
if (b < 0 || b > 255)
throw new ArgumentOutOfRangeException(nameof(b), "Value must be within [0,255].");
RawValue =
((uint)r << 16) |
((uint)g << 8) |
(uint)b;
RawValue = ((uint)r << 16)
| ((uint)g << 8)
| (uint)b;
}
/// <summary>
/// Initializes a <see cref="Color"/> struct with the given RGB float value.
/// </summary>
/// <example>
/// The following will create a color that has a value of
/// The following will create a color that has a value of
/// <see href="http://www.color-hex.com/color/607c8c">#607c8c</see>.
/// <code language="cs">
/// Color darkGrey = new Color(0.38f, 0.49f, 0.55f);
@@ -172,10 +183,9 @@ namespace Discord
throw new ArgumentOutOfRangeException(nameof(g), "Value must be within [0,1].");
if (b < 0.0f || b > 1.0f)
throw new ArgumentOutOfRangeException(nameof(b), "Value must be within [0,1].");
RawValue =
((uint)(r * 255.0f) << 16) |
((uint)(g * 255.0f) << 8) |
(uint)(b * 255.0f);
RawValue = ((uint)(r * 255.0f) << 16)
| ((uint)(g * 255.0f) << 8)
| (uint)(b * 255.0f);
}

public static bool operator ==(Color lhs, Color rhs)
@@ -184,15 +194,22 @@ namespace Discord
public static bool operator !=(Color lhs, Color rhs)
=> lhs.RawValue != rhs.RawValue;

public static implicit operator Color(uint rawValue)
=> new(rawValue);

public static implicit operator uint(Color color)
=> color.RawValue;

public override bool Equals(object obj)
=> (obj is Color c && RawValue == c.RawValue);
=> obj is Color c && RawValue == c.RawValue;

public override int GetHashCode() => RawValue.GetHashCode();

public static implicit operator StandardColor(Color color) =>
StandardColor.FromArgb((int)color.RawValue);
public static explicit operator Color(StandardColor color) =>
new Color((uint)color.ToArgb() << 8 >> 8);
public static implicit operator StandardColor(Color color)
=> StandardColor.FromArgb((int)color.RawValue);

public static explicit operator Color(StandardColor color)
=> new((uint)color.ToArgb() << 8 >> 8);

/// <summary>
/// Gets the hexadecimal representation of the color (e.g. <c>#000ccc</c>).


+ 27
- 5
src/Discord.Net.Core/Entities/Users/IUser.cs View File

@@ -12,17 +12,29 @@ namespace Discord
/// </summary>
string AvatarId { get; }
/// <summary>
/// Gets the identifier of this user's banner.
/// </summary>
string BannerId { get; }
/// <summary>
/// Gets the user's banner color.
/// </summary>
/// <returns>
/// A <see cref="Color"/> struct representing the accent color of this user's banner.
/// </returns>
Color? AccentColor { get; }
/// <summary>
/// Gets the avatar URL for this user.
/// </summary>
/// <remarks>
/// This property retrieves a URL for this user's avatar. In event that the user does not have a valid avatar
/// (i.e. their avatar identifier is not set), this property will return <c>null</c>. If you wish to
/// (i.e. their avatar identifier is not set), this method will return <c>null</c>. If you wish to
/// retrieve the default avatar for this user, consider using <see cref="IUser.GetDefaultAvatarUrl"/> (see
/// example).
/// </remarks>
/// <example>
/// <para>The following example attempts to retrieve the user's current avatar and send it to a channel; if one is
/// not set, a default avatar for this user will be returned instead.</para>
/// <para
/// >The following example attempts to retrieve the user's current avatar and send it to a channel; if one is
/// not set, a default avatar for this user will be returned instead.</para>
/// <code language="cs" region="GetAvatarUrl"
/// source="..\..\..\Discord.Net.Examples\Core\Entities\Users\IUser.Examples.cs"/>
/// </example>
@@ -34,6 +46,16 @@ namespace Discord
/// </returns>
string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128);
/// <summary>
/// Gets the banner URL for this user.
/// </summary>
/// <param name="format">The format to return.</param>
/// <param name="size">The size of the image to return in. This can be any power of two between 16 and 2048.
/// </param>
/// <returns>
/// A string representing the user's avatar URL; <c>null</c> if the user does not have an banner in place.
/// </returns>
string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size = 256);
/// <summary>
/// Gets the default avatar URL for this user.
/// </summary>
/// <remarks>
@@ -93,8 +115,8 @@ namespace Discord
/// This method is used to obtain or create a channel used to send a direct message.
/// <note type="warning">
/// In event that the current user cannot send a message to the target user, a channel can and will
/// still be created by Discord. However, attempting to send a message will yield a
/// <see cref="Discord.Net.HttpException"/> with a 403 as its
/// still be created by Discord. However, attempting to send a message will yield a
/// <see cref="Discord.Net.HttpException"/> with a 403 as its
/// <see cref="Discord.Net.HttpException.HttpCode"/>. There are currently no official workarounds by
/// Discord.
/// </note>


+ 6
- 1
src/Discord.Net.Core/Entities/Webhooks/IWebhook.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;

namespace Discord
@@ -49,6 +49,11 @@ namespace Discord
/// </summary>
IUser Creator { get; }

/// <summary>
/// Gets the ID of the application owning this webhook.
/// </summary>
ulong? ApplicationId { get; }

/// <summary>
/// Modifies this webhook.
/// </summary>


+ 4
- 0
src/Discord.Net.Rest/API/Common/User.cs View File

@@ -15,6 +15,10 @@ namespace Discord.API
public Optional<bool> Bot { get; set; }
[JsonProperty("avatar")]
public Optional<string> Avatar { get; set; }
[JsonProperty("banner")]
public Optional<string> Banner { get; set; }
[JsonProperty("accent_color")]
public Optional<uint?> AccentColor { get; set; }

//CurrentUser
[JsonProperty("verified")]


+ 2
- 0
src/Discord.Net.Rest/API/Common/Webhook.cs View File

@@ -21,5 +21,7 @@ namespace Discord.API

[JsonProperty("user")]
public Optional<User> Creator { get; set; }
[JsonProperty("application_id")]
public Optional<ulong> ApplicationId { get; set; }
}
}

+ 2
- 0
src/Discord.Net.Rest/API/Rest/ModifyWebhookMessageParams.cs View File

@@ -12,5 +12,7 @@ namespace Discord.API.Rest
public Optional<Embed[]> Embeds { get; set; }
[JsonProperty("allowed_mentions")]
public Optional<AllowedMentions> AllowedMentions { get; set; }
[JsonProperty("components")]
public Optional<API.ActionRowComponent[]> Components { get; set; }
}
}

+ 3
- 0
src/Discord.Net.Rest/Discord.Net.Rest.xml View File

@@ -4778,6 +4778,9 @@
<member name="P:Discord.Rest.RestWebhook.Creator">
<inheritdoc />
</member>
<member name="P:Discord.Rest.RestWebhook.ApplicationId">
<inheritdoc />
</member>
<member name="P:Discord.Rest.RestWebhook.CreatedAt">
<inheritdoc />
</member>


+ 2
- 2
src/Discord.Net.Rest/Entities/Users/RestThreadUser.cs View File

@@ -9,7 +9,7 @@ using Model = Discord.API.ThreadMember;
namespace Discord.Rest
{
/// <summary>
/// Represents a thread user recieved over the REST api.
/// Represents a thread user received over the REST api.
/// </summary>
public class RestThreadUser : RestEntity<ulong>
{
@@ -51,7 +51,7 @@ namespace Discord.Rest
/// Gets the guild user for this thread user.
/// </summary>
/// <returns>
/// A task representing the asyncronous get operation. The task returns a
/// A task representing the asynchronous get operation. The task returns a
/// <see cref="IGuildUser"/> that represents the current thread user.
/// </returns>
public Task<IGuildUser> GetGuildUser()


+ 12
- 0
src/Discord.Net.Rest/Entities/Users/RestUser.cs View File

@@ -22,6 +22,10 @@ namespace Discord.Rest
/// <inheritdoc />
public string AvatarId { get; private set; }
/// <inheritdoc />
public string BannerId { get; private set; }
/// <inheritdoc />
public Color? AccentColor { get; private set; }
/// <inheritdoc />
public UserProperties? PublicFlags { get; private set; }

/// <inheritdoc />
@@ -61,6 +65,10 @@ namespace Discord.Rest
{
if (model.Avatar.IsSpecified)
AvatarId = model.Avatar.Value;
if (model.Banner.IsSpecified)
BannerId = model.Banner.Value;
if (model.AccentColor.IsSpecified)
AccentColor = model.AccentColor.Value;
if (model.Discriminator.IsSpecified)
DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
if (model.Bot.IsSpecified)
@@ -92,6 +100,10 @@ namespace Discord.Rest
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format);

/// <inheritdoc />
public string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size = 256)
=> CDN.GetUserBannerUrl(Id, BannerId, size, format);

/// <inheritdoc />
public string GetDefaultAvatarUrl()
=> CDN.GetDefaultUserAvatarUrl(DiscriminatorValue);


+ 4
- 0
src/Discord.Net.Rest/Entities/Webhooks/RestWebhook.cs View File

@@ -24,6 +24,8 @@ namespace Discord.Rest
public ulong? GuildId { get; private set; }
/// <inheritdoc />
public IUser Creator { get; private set; }
/// <inheritdoc />
public ulong? ApplicationId { get; private set; }

/// <inheritdoc />
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
@@ -66,6 +68,8 @@ namespace Discord.Rest
GuildId = model.GuildId.Value;
if (model.Name.IsSpecified)
Name = model.Name.Value;
if (model.ApplicationId.IsSpecified)
ApplicationId = model.ApplicationId.Value;
}

/// <inheritdoc />


+ 1
- 0
src/Discord.Net.Rest/Extensions/EntityExtensions.cs View File

@@ -68,6 +68,7 @@ namespace Discord.Rest
model.Video = entity.Video.Value.ToModel();
return model;
}

public static API.AllowedMentions ToModel(this AllowedMentions entity)
{
return new API.AllowedMentions()


+ 3
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs View File

@@ -12,6 +12,8 @@ namespace Discord.WebSocket
public override string Username { get; internal set; }
public override ushort DiscriminatorValue { get; internal set; }
public override string AvatarId { get; internal set; }
public override string BannerId { get; internal set; }
public override Color? AccentColor { get; internal set; }
internal override SocketPresence Presence { get; set; }

public override bool IsWebhook => false;
@@ -47,7 +49,7 @@ namespace Discord.WebSocket
discord.RemoveUser(Id);
}
}
internal void Update(ClientState state, PresenceModel model)
{
Presence = SocketPresence.Create(model);


+ 4
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs View File

@@ -29,6 +29,10 @@ namespace Discord.WebSocket
/// <inheritdoc />
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
/// <inheritdoc />
public override string BannerId { get { return GlobalUser.BannerId; } internal set { GlobalUser.BannerId = value; } }
/// <inheritdoc />
public override Color? AccentColor { get { return GlobalUser.AccentColor; } internal set { GlobalUser.AccentColor = value; } }
/// <inheritdoc />
internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } }

/// <inheritdoc />


+ 6
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs View File

@@ -38,6 +38,11 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get { return GlobalUser.DiscriminatorValue; } internal set { GlobalUser.DiscriminatorValue = value; } }
/// <inheritdoc />
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
/// <inheritdoc />
public override string BannerId { get { return GlobalUser.BannerId; } internal set { GlobalUser.BannerId = value; } }
/// <inheritdoc />
public override Color? AccentColor { get { return GlobalUser.AccentColor; } internal set { GlobalUser.AccentColor = value; } }

/// <inheritdoc />
public GuildPermissions GuildPermissions => new GuildPermissions(Permissions.ResolveGuild(Guild, this));
internal override SocketPresence Presence { get; set; }
@@ -91,7 +96,7 @@ namespace Discord.WebSocket
/// Returns the position of the user within the role hierarchy.
/// </summary>
/// <remarks>
/// The returned value equal to the position of the highest role the user has, or
/// The returned value equal to the position of the highest role the user has, or
/// <see cref="int.MaxValue"/> if user is the server owner.
/// </remarks>
public int Hierarchy


+ 4
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs View File

@@ -29,6 +29,10 @@ namespace Discord.WebSocket
/// <inheritdoc />
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
/// <inheritdoc />
public override string BannerId { get { return GlobalUser.BannerId; } internal set { GlobalUser.BannerId = value; } }
/// <inheritdoc />
public override Color? AccentColor { get { return GlobalUser.AccentColor; } internal set { GlobalUser.AccentColor = value; } }
/// <inheritdoc />
internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } }
/// <inheritdoc />
public UserProperties Flags { get; internal set; }


+ 15
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketThreadUser.cs View File

@@ -36,7 +36,7 @@ namespace Discord.WebSocket

/// <inheritdoc/>
public string Nickname
=> GuildUser.Nickname;
=> GuildUser.Nickname;

/// <inheritdoc/>
public DateTimeOffset? PremiumSince
@@ -53,6 +53,20 @@ namespace Discord.WebSocket
internal set => GuildUser.AvatarId = value;
}

/// <inheritdoc/>
public override string BannerId
{
get => GuildUser.BannerId;
internal set => GuildUser.BannerId = value;
}

/// <inheritdoc/>
public override Color? AccentColor
{
get => GuildUser.AccentColor;
internal set => GuildUser.AccentColor = value;
}

/// <inheritdoc/>
public override ushort DiscriminatorValue
{


+ 8
- 1
src/Discord.Net.WebSocket/Entities/Users/SocketUnknownUser.cs View File

@@ -19,9 +19,16 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get; internal set; }
/// <inheritdoc />
public override string AvatarId { get; internal set; }

/// <inheritdoc />
public override string BannerId { get; internal set; }

/// <inheritdoc />
public override Color? AccentColor { get; internal set; }

/// <inheritdoc />
public override bool IsBot { get; internal set; }
/// <inheritdoc />
public override bool IsWebhook => false;
/// <inheritdoc />


+ 18
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs View File

@@ -25,6 +25,10 @@ namespace Discord.WebSocket
/// <inheritdoc />
public abstract string AvatarId { get; internal set; }
/// <inheritdoc />
public abstract string BannerId { get; internal set; }
/// <inheritdoc />
public abstract Color? AccentColor { get; internal set; }
/// <inheritdoc />
public abstract bool IsWebhook { get; }
/// <inheritdoc />
public UserProperties? PublicFlags { get; private set; }
@@ -64,6 +68,16 @@ namespace Discord.WebSocket
AvatarId = model.Avatar.Value;
hasChanges = true;
}
if (model.Banner.IsSpecified && model.Banner.Value != BannerId)
{
BannerId = model.Banner.Value;
hasChanges = true;
}
if (model.AccentColor.IsSpecified && model.AccentColor.Value != AccentColor?.RawValue)
{
AccentColor = model.AccentColor.Value;
hasChanges = true;
}
if (model.Discriminator.IsSpecified)
{
var newVal = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
@@ -99,6 +113,10 @@ namespace Discord.WebSocket
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)
=> CDN.GetUserAvatarUrl(Id, AvatarId, size, format);

/// <inheritdoc />
public string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size = 256)
=> CDN.GetUserBannerUrl(Id, BannerId, size, format);

/// <inheritdoc />
public string GetDefaultAvatarUrl()
=> CDN.GetDefaultUserAvatarUrl(DiscriminatorValue);


+ 17
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketWebhookUser.cs View File

@@ -24,6 +24,23 @@ namespace Discord.WebSocket
public override ushort DiscriminatorValue { get; internal set; }
/// <inheritdoc />
public override string AvatarId { get; internal set; }

/// <inheritdoc />
/// <exception cref="NotSupportedException">Webhook users does not support banners.</exception>
public override string BannerId
{
get => throw new NotSupportedException("Webhook users does not support banners.");
internal set => throw new NotSupportedException("Webhook users does not support banners.");
}

/// <inheritdoc />
/// <exception cref="NotSupportedException">Webhook users does not support accent colors.</exception>
public override Color? AccentColor
{
get => throw new NotSupportedException("Webhook users does not support accent colors.");
internal set => throw new NotSupportedException("Webhook users does not support accent colors.");
}

/// <inheritdoc />
public override bool IsBot { get; internal set; }



+ 6
- 1
src/Discord.Net.Webhook/Discord.Net.Webhook.xml View File

@@ -31,7 +31,7 @@
<exception cref="T:System.ArgumentException">Thrown if the <paramref name="webhookUrl"/> is an invalid format.</exception>
<exception cref="T:System.ArgumentNullException">Thrown if the <paramref name="webhookUrl"/> is null or whitespace.</exception>
</member>
<member name="M:Discord.Webhook.DiscordWebhookClient.SendMessageAsync(System.String,System.Boolean,System.Collections.Generic.IEnumerable{Discord.Embed},System.String,System.String,Discord.RequestOptions,Discord.AllowedMentions)">
<member name="M:Discord.Webhook.DiscordWebhookClient.SendMessageAsync(System.String,System.Boolean,System.Collections.Generic.IEnumerable{Discord.Embed},System.String,System.String,Discord.RequestOptions,Discord.AllowedMentions,Discord.MessageComponent)">
<summary> Sends a message to the channel for this webhook. </summary>
<returns> Returns the ID of the created message. </returns>
</member>
@@ -99,6 +99,11 @@
Gets or sets the allowed mentions of the message.
</summary>
</member>
<member name="P:Discord.Webhook.WebhookMessageProperties.Components">
<summary>
Gets or sets the components that the message should display.
</summary>
</member>
<member name="M:Discord.Webhook.WebhookClientHelper.GetWebhookAsync(Discord.Webhook.DiscordWebhookClient,System.UInt64)">
<exception cref="T:System.InvalidOperationException">Could not find a webhook with the supplied credentials.</exception>
</member>


+ 2
- 2
src/Discord.Net.Webhook/DiscordWebhookClient.cs View File

@@ -88,8 +88,8 @@ namespace Discord.Webhook
/// <summary> Sends a message to the channel for this webhook. </summary>
/// <returns> Returns the ID of the created message. </returns>
public Task<ulong> SendMessageAsync(string text = null, bool isTTS = false, IEnumerable<Embed> embeds = null,
string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null)
=> WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, allowedMentions, options);
string username = null, string avatarUrl = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageComponent component = null)
=> WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, allowedMentions, options, component);

/// <summary>
/// Modifies a message posted using this webhook.


+ 4
- 0
src/Discord.Net.Webhook/Entities/Messages/WebhookMessageProperties.cs View File

@@ -22,5 +22,9 @@ namespace Discord.Webhook
/// Gets or sets the allowed mentions of the message.
/// </summary>
public Optional<AllowedMentions> AllowedMentions { get; set; }
/// <summary>
/// Gets or sets the components that the message should display.
/// </summary>
public Optional<MessageComponent> Components { get; set; }
}
}

+ 3
- 0
src/Discord.Net.Webhook/Entities/Webhooks/RestInternalWebhook.cs View File

@@ -17,6 +17,7 @@ namespace Discord.Webhook
public string Name { get; private set; }
public string AvatarId { get; private set; }
public ulong? GuildId { get; private set; }
public ulong? ApplicationId { get; private set; }

public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);

@@ -44,6 +45,8 @@ namespace Discord.Webhook
GuildId = model.GuildId.Value;
if (model.Name.IsSpecified)
Name = model.Name.Value;
if (model.ApplicationId.IsSpecified)
ApplicationId = model.ApplicationId.Value;
}

public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)


+ 5
- 2
src/Discord.Net.Webhook/WebhookClientHelper.cs View File

@@ -21,7 +21,7 @@ namespace Discord.Webhook
return RestInternalWebhook.Create(client, model);
}
public static async Task<ulong> SendMessageAsync(DiscordWebhookClient client,
string text, bool isTTS, IEnumerable<Embed> embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options)
string text, bool isTTS, IEnumerable<Embed> embeds, string username, string avatarUrl, AllowedMentions allowedMentions, RequestOptions options, MessageComponent component)
{
var args = new CreateWebhookMessageParams
{
@@ -37,6 +37,8 @@ namespace Discord.Webhook
args.AvatarUrl = avatarUrl;
if (allowedMentions != null)
args.AllowedMentions = allowedMentions.ToModel();
if (component != null)
args.Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray();

var model = await client.ApiClient.CreateWebhookMessageAsync(client.Webhook.Id, args, options: options).ConfigureAwait(false);
return model.Id;
@@ -83,7 +85,8 @@ namespace Discord.Webhook
: Optional.Create<API.Embed[]>(),
AllowedMentions = args.AllowedMentions.IsSpecified
? args.AllowedMentions.Value.ToModel()
: Optional.Create<API.AllowedMentions>()
: Optional.Create<API.AllowedMentions>(),
Components = args.Components.IsSpecified ? args.Components.Value?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() : Optional<API.ActionRowComponent[]>.Unspecified,
};

await client.ApiClient.ModifyWebhookMessageAsync(client.Webhook.Id, messageId, apiArgs, options)


Loading…
Cancel
Save