* fix ci/cd error (#2428) * Fix role icon & emoji assignment. (#2416) * Fix IGuild.GetBansAsync() (#2424) fix the problem of not being able to get more than 1000 bans * [DOCS] Add a note about `DontAutoRegisterAttribute` (#2430) * add a note about `DontAutoRegisterAttribute` * Remove "to to" and add punctuation Co-authored-by: MrCakeSlayer <13650699+MrCakeSlayer@users.noreply.github.com> * fix: Missing Fact attribute in ColorTests (#2425) * feat: Embed comparison (#2347) * Fix broken code snippet in dependency injection docs (#2420) * Fixed markdown formatting to show code snippet * Fixed constructor injection code snippet pointer * Added support for lottie stickers (#2359) Co-authored-by: Armano den Boef <68127614+Rozen4334@users.noreply.github.com> Co-authored-by: BokuNoPasya <49203428+1NieR@users.noreply.github.com> Co-authored-by: Misha133 <61027276+Misha-133@users.noreply.github.com> Co-authored-by: MrCakeSlayer <13650699+MrCakeSlayer@users.noreply.github.com> Co-authored-by: Ge <gehongyan1996@126.com> Co-authored-by: Charlie U <52503242+cpurules@users.noreply.github.com> Co-authored-by: Kuba_Z2 <77853483+KubaZ2@users.noreply.github.com>pull/2395/head
@@ -16,7 +16,7 @@ This can be done through property or constructor. | |||||
Services can be injected from the constructor of the class. | Services can be injected from the constructor of the class. | ||||
This is the preferred approach, because it automatically locks the readonly field in place with the provided service and isn't accessible outside of the class. | This is the preferred approach, because it automatically locks the readonly field in place with the provided service and isn't accessible outside of the class. | ||||
[!code-csharp[Property Injection(samples/property-injecting.cs)]] | |||||
[!code-csharp[Constructor Injection](samples/ctor-injecting.cs)] | |||||
## Injecting through properties | ## Injecting through properties | ||||
@@ -294,7 +294,7 @@ By nesting commands inside a module that is tagged with [GroupAttribute] you can | |||||
> [!NOTE] | > [!NOTE] | ||||
> To not use the command group's name as a prefix for component or modal interaction's custom id set `ignoreGroupNames` parameter to `true` in classes with [GroupAttribute] | > To not use the command group's name as a prefix for component or modal interaction's custom id set `ignoreGroupNames` parameter to `true` in classes with [GroupAttribute] | ||||
> | > | ||||
> However, you have to be careful to prevent overlapping ids of buttons and modals | |||||
> However, you have to be careful to prevent overlapping ids of buttons and modals. | |||||
[!code-csharp[Command Group Example](samples/intro/groupmodule.cs)] | [!code-csharp[Command Group Example](samples/intro/groupmodule.cs)] | ||||
@@ -346,10 +346,13 @@ Command registration methods can only be used after the gateway client is ready | |||||
Methods like `AddModulesToGuildAsync()`, `AddCommandsToGuildAsync()`, `AddModulesGloballyAsync()` and `AddCommandsGloballyAsync()` | Methods like `AddModulesToGuildAsync()`, `AddCommandsToGuildAsync()`, `AddModulesGloballyAsync()` and `AddCommandsGloballyAsync()` | ||||
can be used to register cherry picked modules or commands to global/guild scopes. | can be used to register cherry picked modules or commands to global/guild scopes. | ||||
> [!NOTE] | |||||
> [DontAutoRegisterAttribute] can be used on module classes to prevent `RegisterCommandsGloballyAsync()` and `RegisterCommandsToGuildAsync()` from registering them to the Discord. | |||||
> [!NOTE] | > [!NOTE] | ||||
> In debug environment, since Global commands can take up to 1 hour to register/update, | > In debug environment, since Global commands can take up to 1 hour to register/update, | ||||
> it is adviced to register your commands to a test guild for your changes to take effect immediately. | > it is adviced to register your commands to a test guild for your changes to take effect immediately. | ||||
> You can use preprocessor directives to create a simple logic for registering commands as seen above | |||||
> You can use preprocessor directives to create a simple logic for registering commands as seen above. | |||||
## Interaction Utility | ## Interaction Utility | ||||
@@ -377,6 +380,7 @@ delegate can be used to create HTTP responses from a deserialized json object st | |||||
[DependencyInjection]: xref:Guides.DI.Intro | [DependencyInjection]: xref:Guides.DI.Intro | ||||
[GroupAttribute]: xref:Discord.Interactions.GroupAttribute | [GroupAttribute]: xref:Discord.Interactions.GroupAttribute | ||||
[DontAutoRegisterAttribute]: xref:Discord.Interactions.DontAutoRegisterAttribute | |||||
[InteractionService]: xref:Discord.Interactions.InteractionService | [InteractionService]: xref:Discord.Interactions.InteractionService | ||||
[InteractionServiceConfig]: xref:Discord.Interactions.InteractionServiceConfig | [InteractionServiceConfig]: xref:Discord.Interactions.InteractionServiceConfig | ||||
[InteractionModuleBase]: xref:Discord.Interactions.InteractionModuleBase | [InteractionModuleBase]: xref:Discord.Interactions.InteractionModuleBase | ||||
@@ -16,7 +16,6 @@ | |||||
<PackageReference Include="IDisposableAnalyzers" Version="3.4.15"> | <PackageReference Include="IDisposableAnalyzers" Version="3.4.15"> | ||||
<PrivateAssets>all</PrivateAssets> | <PrivateAssets>all</PrivateAssets> | ||||
</PackageReference> | </PackageReference> | ||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' "> | <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' "> | ||||
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" /> | <PackageReference Include="System.Collections.Immutable" Version="1.3.1" /> | ||||
@@ -27,4 +26,7 @@ | |||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' "> | <ItemGroup Condition=" '$(TargetFramework)' == 'net461' "> | ||||
<PackageReference Include="System.ValueTuple" Version="4.4.0" /> | <PackageReference Include="System.ValueTuple" Version="4.4.0" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net461'"> | |||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -94,5 +94,44 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
public override string ToString() => Title; | public override string ToString() => Title; | ||||
private string DebuggerDisplay => $"{Title} ({Type})"; | private string DebuggerDisplay => $"{Title} ({Type})"; | ||||
public static bool operator ==(Embed left, Embed right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(Embed left, Embed right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="Embed"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="Embed"/>, <see cref="Equals(Embed)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="Embed"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is Embed embed && Equals(embed); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="Embed"/> is equal to the current <see cref="Embed"/> | |||||
/// </summary> | |||||
/// <param name="embed">The <see cref="Embed"/> to compare with the current <see cref="Embed"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(Embed embed) | |||||
=> GetHashCode() == embed?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
{ | |||||
unchecked | |||||
{ | |||||
var hash = 17; | |||||
hash = hash * 23 + (Type, Title, Description, Timestamp, Color, Image, Video, Author, Footer, Provider, Thumbnail).GetHashCode(); | |||||
foreach(var field in Fields) | |||||
hash = hash * 23 + field.GetHashCode(); | |||||
return hash; | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -41,5 +42,35 @@ namespace Discord | |||||
/// | /// | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Name; | public override string ToString() => Name; | ||||
public static bool operator ==(EmbedAuthor? left, EmbedAuthor? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedAuthor? left, EmbedAuthor? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedAuthor"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedAuthor"/>, <see cref="Equals(EmbedAuthor?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedAuthor"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedAuthor embedAuthor && Equals(embedAuthor); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedAuthor"/> is equal to the current <see cref="EmbedAuthor"/> | |||||
/// </summary> | |||||
/// <param name="embedAuthor">The <see cref="EmbedAuthor"/> to compare with the current <see cref="EmbedAuthor"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedAuthor? embedAuthor) | |||||
=> GetHashCode() == embedAuthor?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Name, Url, IconUrl).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -481,6 +481,55 @@ namespace Discord | |||||
return new Embed(EmbedType.Rich, Title, Description, Url, Timestamp, Color, _image, null, Author?.Build(), Footer?.Build(), null, _thumbnail, fields.ToImmutable()); | return new Embed(EmbedType.Rich, Title, Description, Url, Timestamp, Color, _image, null, Author?.Build(), Footer?.Build(), null, _thumbnail, fields.ToImmutable()); | ||||
} | } | ||||
public static bool operator ==(EmbedBuilder left, EmbedBuilder right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedBuilder left, EmbedBuilder right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedBuilder"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedBuilder"/>, <see cref="Equals(EmbedBuilder)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedBuilder"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedBuilder embedBuilder && Equals(embedBuilder); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedBuilder"/> is equal to the current <see cref="EmbedBuilder"/> | |||||
/// </summary> | |||||
/// <param name="embedBuilder">The <see cref="EmbedBuilder"/> to compare with the current <see cref="EmbedBuilder"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedBuilder embedBuilder) | |||||
{ | |||||
if (embedBuilder is null) | |||||
return false; | |||||
if (Fields.Count != embedBuilder.Fields.Count) | |||||
return false; | |||||
for (var i = 0; i < _fields.Count; i++) | |||||
if (_fields[i] != embedBuilder._fields[i]) | |||||
return false; | |||||
return _title == embedBuilder?._title | |||||
&& _description == embedBuilder?._description | |||||
&& _image == embedBuilder?._image | |||||
&& _thumbnail == embedBuilder?._thumbnail | |||||
&& Timestamp == embedBuilder?.Timestamp | |||||
&& Color == embedBuilder?.Color | |||||
&& Author == embedBuilder?.Author | |||||
&& Footer == embedBuilder?.Footer | |||||
&& Url == embedBuilder?.Url; | |||||
} | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() => base.GetHashCode(); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -597,6 +646,37 @@ namespace Discord | |||||
/// </exception> | /// </exception> | ||||
public EmbedField Build() | public EmbedField Build() | ||||
=> new EmbedField(Name, Value.ToString(), IsInline); | => new EmbedField(Name, Value.ToString(), IsInline); | ||||
public static bool operator ==(EmbedFieldBuilder left, EmbedFieldBuilder right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedFieldBuilder left, EmbedFieldBuilder right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedFieldBuilder"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedFieldBuilder"/>, <see cref="Equals(EmbedFieldBuilder)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedFieldBuilder"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedFieldBuilder embedFieldBuilder && Equals(embedFieldBuilder); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedFieldBuilder"/> is equal to the current <see cref="EmbedFieldBuilder"/> | |||||
/// </summary> | |||||
/// <param name="embedFieldBuilder">The <see cref="EmbedFieldBuilder"/> to compare with the current <see cref="EmbedFieldBuilder"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedFieldBuilder embedFieldBuilder) | |||||
=> _name == embedFieldBuilder?._name | |||||
&& _value == embedFieldBuilder?._value | |||||
&& IsInline == embedFieldBuilder?.IsInline; | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() => base.GetHashCode(); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -697,6 +777,37 @@ namespace Discord | |||||
/// </returns> | /// </returns> | ||||
public EmbedAuthor Build() | public EmbedAuthor Build() | ||||
=> new EmbedAuthor(Name, Url, IconUrl, null); | => new EmbedAuthor(Name, Url, IconUrl, null); | ||||
public static bool operator ==(EmbedAuthorBuilder left, EmbedAuthorBuilder right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedAuthorBuilder left, EmbedAuthorBuilder right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedAuthorBuilder"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedAuthorBuilder"/>, <see cref="Equals(EmbedAuthorBuilder)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedAuthorBuilder"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedAuthorBuilder embedAuthorBuilder && Equals(embedAuthorBuilder); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedAuthorBuilder"/> is equals to the current <see cref="EmbedAuthorBuilder"/> | |||||
/// </summary> | |||||
/// <param name="embedAuthorBuilder">The <see cref="EmbedAuthorBuilder"/> to compare with the current <see cref="EmbedAuthorBuilder"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedAuthorBuilder embedAuthorBuilder) | |||||
=> _name == embedAuthorBuilder?._name | |||||
&& Url == embedAuthorBuilder?.Url | |||||
&& IconUrl == embedAuthorBuilder?.IconUrl; | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() => base.GetHashCode(); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -777,5 +888,35 @@ namespace Discord | |||||
/// </returns> | /// </returns> | ||||
public EmbedFooter Build() | public EmbedFooter Build() | ||||
=> new EmbedFooter(Text, IconUrl, null); | => new EmbedFooter(Text, IconUrl, null); | ||||
public static bool operator ==(EmbedFooterBuilder left, EmbedFooterBuilder right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedFooterBuilder left, EmbedFooterBuilder right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedFooterBuilder"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedFooterBuilder"/>, <see cref="Equals(EmbedFooterBuilder)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedFooterBuilder"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedFooterBuilder embedFooterBuilder && Equals(embedFooterBuilder); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedFooterBuilder"/> is equal to the current <see cref="EmbedFooterBuilder"/> | |||||
/// </summary> | |||||
/// <param name="embedFooterBuilder">The <see cref="EmbedFooterBuilder"/> to compare with the current <see cref="EmbedFooterBuilder"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedFooterBuilder embedFooterBuilder) | |||||
=> _text == embedFooterBuilder?._text | |||||
&& IconUrl == embedFooterBuilder?.IconUrl; | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() => base.GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -36,5 +37,35 @@ namespace Discord | |||||
/// A string that resolves to <see cref="EmbedField.Name"/>. | /// A string that resolves to <see cref="EmbedField.Name"/>. | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Name; | public override string ToString() => Name; | ||||
public static bool operator ==(EmbedField? left, EmbedField? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedField? left, EmbedField? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedField"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedField"/>, <see cref="Equals(EmbedField?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current object</param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedField embedField && Equals(embedField); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedField"/> is equal to the current <see cref="EmbedField"/> | |||||
/// </summary> | |||||
/// <param name="embedField"></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedField? embedField) | |||||
=> GetHashCode() == embedField?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Name, Value, Inline).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -43,5 +44,35 @@ namespace Discord | |||||
/// A string that resolves to <see cref="Discord.EmbedFooter.Text"/>. | /// A string that resolves to <see cref="Discord.EmbedFooter.Text"/>. | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Text; | public override string ToString() => Text; | ||||
public static bool operator ==(EmbedFooter? left, EmbedFooter? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedFooter? left, EmbedFooter? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedFooter"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedFooter"/>, <see cref="Equals(EmbedFooter?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedFooter"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedFooter embedFooter && Equals(embedFooter); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedFooter"/> is equal to the current <see cref="EmbedFooter"/> | |||||
/// </summary> | |||||
/// <param name="embedFooter">The <see cref="EmbedFooter"/> to compare with the current <see cref="EmbedFooter"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedFooter? embedFooter) | |||||
=> GetHashCode() == embedFooter?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Text, IconUrl, ProxyUrl).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -53,5 +54,35 @@ namespace Discord | |||||
/// A string that resolves to <see cref="Discord.EmbedImage.Url"/> . | /// A string that resolves to <see cref="Discord.EmbedImage.Url"/> . | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Url; | public override string ToString() => Url; | ||||
public static bool operator ==(EmbedImage? left, EmbedImage? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedImage? left, EmbedImage? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedImage"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedImage"/>, <see cref="Equals(EmbedImage?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedImage"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedImage embedImage && Equals(embedImage); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedImage"/> is equal to the current <see cref="EmbedImage"/> | |||||
/// </summary> | |||||
/// <param name="embedImage">The <see cref="EmbedImage"/> to compare with the current <see cref="EmbedImage"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedImage? embedImage) | |||||
=> GetHashCode() == embedImage?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Height, Width, Url, ProxyUrl).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -35,5 +36,35 @@ namespace Discord | |||||
/// A string that resolves to <see cref="Discord.EmbedProvider.Name" />. | /// A string that resolves to <see cref="Discord.EmbedProvider.Name" />. | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Name; | public override string ToString() => Name; | ||||
public static bool operator ==(EmbedProvider? left, EmbedProvider? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedProvider? left, EmbedProvider? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedProvider"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedProvider"/>, <see cref="Equals(EmbedProvider?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedProvider"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedProvider embedProvider && Equals(embedProvider); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedProvider"/> is equal to the current <see cref="EmbedProvider"/> | |||||
/// </summary> | |||||
/// <param name="embedProvider">The <see cref="EmbedProvider"/> to compare with the current <see cref="EmbedProvider"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedProvider? embedProvider) | |||||
=> GetHashCode() == embedProvider?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Name, Url).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -53,5 +54,35 @@ namespace Discord | |||||
/// A string that resolves to <see cref="Discord.EmbedThumbnail.Url" />. | /// A string that resolves to <see cref="Discord.EmbedThumbnail.Url" />. | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Url; | public override string ToString() => Url; | ||||
public static bool operator ==(EmbedThumbnail? left, EmbedThumbnail? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedThumbnail? left, EmbedThumbnail? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedThumbnail"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedThumbnail"/>, <see cref="Equals(EmbedThumbnail?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedThumbnail"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedThumbnail embedThumbnail && Equals(embedThumbnail); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedThumbnail"/> is equal to the current <see cref="EmbedThumbnail"/> | |||||
/// </summary> | |||||
/// <param name="embedThumbnail">The <see cref="EmbedThumbnail"/> to compare with the current <see cref="EmbedThumbnail"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedThumbnail? embedThumbnail) | |||||
=> GetHashCode() == embedThumbnail?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Width, Height, Url, ProxyUrl).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,3 +1,4 @@ | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
namespace Discord | namespace Discord | ||||
@@ -47,5 +48,35 @@ namespace Discord | |||||
/// A string that resolves to <see cref="Url"/>. | /// A string that resolves to <see cref="Url"/>. | ||||
/// </returns> | /// </returns> | ||||
public override string ToString() => Url; | public override string ToString() => Url; | ||||
public static bool operator ==(EmbedVideo? left, EmbedVideo? right) | |||||
=> left is null ? right is null | |||||
: left.Equals(right); | |||||
public static bool operator !=(EmbedVideo? left, EmbedVideo? right) | |||||
=> !(left == right); | |||||
/// <summary> | |||||
/// Determines whether the specified object is equal to the current <see cref="EmbedVideo"/>. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// If the object passes is an <see cref="EmbedVideo"/>, <see cref="Equals(EmbedVideo?)"/> will be called to compare the 2 instances | |||||
/// </remarks> | |||||
/// <param name="obj">The object to compare with the current <see cref="EmbedVideo"/></param> | |||||
/// <returns></returns> | |||||
public override bool Equals(object obj) | |||||
=> obj is EmbedVideo embedVideo && Equals(embedVideo); | |||||
/// <summary> | |||||
/// Determines whether the specified <see cref="EmbedVideo"/> is equal to the current <see cref="EmbedVideo"/> | |||||
/// </summary> | |||||
/// <param name="embedVideo">The <see cref="EmbedVideo"/> to compare with the current <see cref="EmbedVideo"/></param> | |||||
/// <returns></returns> | |||||
public bool Equals(EmbedVideo? embedVideo) | |||||
=> GetHashCode() == embedVideo?.GetHashCode(); | |||||
/// <inheritdoc /> | |||||
public override int GetHashCode() | |||||
=> (Width, Height, Url).GetHashCode(); | |||||
} | } | ||||
} | } |
@@ -1,4 +1,5 @@ | |||||
using Discord.Net.Rest; | using Discord.Net.Rest; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.IO; | using System.IO; | ||||
namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
@@ -20,14 +21,21 @@ namespace Discord.API.Rest | |||||
["tags"] = Tags | ["tags"] = Tags | ||||
}; | }; | ||||
string contentType = "image/png"; | |||||
string contentType; | |||||
if (File is FileStream fileStream) | if (File is FileStream fileStream) | ||||
contentType = $"image/{Path.GetExtension(fileStream.Name)}"; | |||||
{ | |||||
var extension = Path.GetExtension(fileStream.Name).TrimStart('.'); | |||||
contentType = extension == "json" ? "application/json" : $"image/{extension}"; | |||||
} | |||||
else if (FileName != null) | else if (FileName != null) | ||||
contentType = $"image/{Path.GetExtension(FileName)}"; | |||||
{ | |||||
var extension = Path.GetExtension(FileName).TrimStart('.'); | |||||
contentType = extension == "json" ? "application/json" : $"image/{extension}"; | |||||
} | |||||
else | |||||
contentType = "image/png"; | |||||
d["file"] = new MultipartFile(File, FileName ?? "image", contentType.Replace(".", "")); | |||||
d["file"] = new MultipartFile(File, FileName ?? "image", contentType); | |||||
return d; | return d; | ||||
} | } | ||||
@@ -180,7 +180,7 @@ namespace Discord.Rest | |||||
}, | }, | ||||
nextPage: (info, lastPage) => | nextPage: (info, lastPage) => | ||||
{ | { | ||||
if (lastPage.Count != DiscordConfig.MaxMessagesPerBatch) | |||||
if (lastPage.Count != DiscordConfig.MaxBansPerBatch) | |||||
return false; | return false; | ||||
if (dir == Direction.Before) | if (dir == Direction.Before) | ||||
info.Position = lastPage.Min(x => x.User.Id); | info.Position = lastPage.Min(x => x.User.Id); | ||||
@@ -23,7 +23,7 @@ namespace Discord.Rest | |||||
{ | { | ||||
role.Guild.Features.EnsureFeature(GuildFeature.RoleIcons); | role.Guild.Features.EnsureFeature(GuildFeature.RoleIcons); | ||||
if (args.Icon.IsSpecified && args.Emoji.IsSpecified) | |||||
if ((args.Icon.IsSpecified && args.Icon.Value != null) && (args.Emoji.IsSpecified && args.Emoji.Value != null)) | |||||
{ | { | ||||
throw new ArgumentException("Emoji and Icon properties cannot be present on a role at the same time."); | throw new ArgumentException("Emoji and Icon properties cannot be present on a role at the same time."); | ||||
} | } | ||||
@@ -36,18 +36,18 @@ namespace Discord.Rest | |||||
Mentionable = args.Mentionable, | Mentionable = args.Mentionable, | ||||
Name = args.Name, | Name = args.Name, | ||||
Permissions = args.Permissions.IsSpecified ? args.Permissions.Value.RawValue.ToString() : Optional.Create<string>(), | Permissions = args.Permissions.IsSpecified ? args.Permissions.Value.RawValue.ToString() : Optional.Create<string>(), | ||||
Icon = args.Icon.IsSpecified ? args.Icon.Value.Value.ToModel() : Optional<API.Image?>.Unspecified, | |||||
Emoji = args.Emoji.GetValueOrDefault()?.Name ?? Optional<string>.Unspecified | |||||
Icon = args.Icon.IsSpecified ? args.Icon.Value?.ToModel() ?? null : Optional<API.Image?>.Unspecified, | |||||
Emoji = args.Emoji.IsSpecified ? args.Emoji.Value?.Name ?? "" : Optional.Create<string>(), | |||||
}; | }; | ||||
if (args.Icon.IsSpecified && role.Emoji != null) | |||||
if ((args.Icon.IsSpecified && args.Icon.Value != null) && role.Emoji != null) | |||||
{ | { | ||||
apiArgs.Emoji = null; | |||||
apiArgs.Emoji = ""; | |||||
} | } | ||||
if (args.Emoji.IsSpecified && !string.IsNullOrEmpty(role.Icon)) | |||||
if ((args.Emoji.IsSpecified && args.Emoji.Value != null) && !string.IsNullOrEmpty(role.Icon)) | |||||
{ | { | ||||
apiArgs.Icon = null; | |||||
apiArgs.Icon = Optional<API.Image?>.Unspecified; | |||||
} | } | ||||
var model = await client.ApiClient.ModifyGuildRoleAsync(role.Guild.Id, role.Id, apiArgs, options).ConfigureAwait(false); | var model = await client.ApiClient.ModifyGuildRoleAsync(role.Guild.Id, role.Id, apiArgs, options).ConfigureAwait(false); | ||||
@@ -10,6 +10,7 @@ namespace Discord | |||||
/// </summary> | /// </summary> | ||||
public class ColorTests | public class ColorTests | ||||
{ | { | ||||
[Fact] | |||||
public void Color_New() | public void Color_New() | ||||
{ | { | ||||
Assert.Equal(0u, new Color().RawValue); | Assert.Equal(0u, new Color().RawValue); | ||||