Skip to content

Commit d2b66ca

Browse files
committed
implement predicate to hide attribute and enum modalcomponent typeconverter
1 parent fa4d7a1 commit d2b66ca

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

src/Discord.Net.Interactions/Attributes/HideAttribute.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,20 @@ namespace Discord.Interactions;
66
/// Enum values tagged with this attribute will not be displayed as a parameter choice
77
/// </summary>
88
/// <remarks>
9-
/// This attribute must be used along with the default <see cref="EnumConverter{T}"/>
9+
/// This attribute must be used along with the default <see cref="EnumConverter{T}"/> and <see cref="DefaultEntityTypeConverter{T}"/>.
1010
/// </remarks>
1111
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
12-
public sealed class HideAttribute : Attribute { }
12+
public class HideAttribute : Attribute
13+
{
14+
/// <summary>
15+
/// Can be optionally implemented by inherited types to conditionally hide an enum value.
16+
/// </summary>
17+
/// <remarks>
18+
/// Only runs on prior to modal construction. For slash command parameters, this method is ignored.
19+
/// </remarks>
20+
/// <param name="interaction">Interaction that <see cref="IDiscordInteractionExtentions.RespondWithModalAsync{T}(IDiscordInteraction, string, T, RequestOptions, Action{ModalBuilder})"/> is called on.</param>
21+
/// <returns>
22+
/// <see cref="true"/> if the attribute should be active and hide the value.
23+
/// </returns>
24+
public virtual bool Predicate(IDiscordInteraction interaction) => true;
25+
}

src/Discord.Net.Interactions/TypeConverters/ModalComponents/EnumModalComponentConverter.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,21 @@ internal sealed class EnumModalComponentConverter<T> : ModalComponentTypeConvert
1010
where T : struct, Enum
1111
{
1212
private readonly bool _isFlags;
13-
private readonly ImmutableArray<SelectMenuOptionBuilder> _options;
13+
private readonly ImmutableArray<(SelectMenuOptionBuilder Option, Predicate<IDiscordInteraction> Predicate)> _options;
1414

1515
public EnumModalComponentConverter()
1616
{
1717
var names = Enum.GetNames(typeof(T));
18-
var members = names.SelectMany(x => typeof(T).GetMember(x)).Where(x => !x.IsDefined(typeof(HideAttribute), true));
19-
20-
if (members.Count() > SelectMenuBuilder.MaxOptionCount)
21-
throw new InvalidOperationException($"Enum type {typeof(T).FullName} has too many visible members to be used in a select menu. Maximum visible members is {SelectMenuBuilder.MaxOptionCount}, but {members.Count()} are visible.");
18+
var members = names.SelectMany(x => typeof(T).GetMember(x));
2219

2320
_isFlags = typeof(T).GetCustomAttribute<FlagsAttribute>() is not null;
2421

2522
_options = members.Select(x =>
2623
{
2724
var selectMenuOptionAttr = x.GetCustomAttribute<SelectMenuOptionAttribute>();
28-
return new SelectMenuOptionBuilder(x.GetCustomAttribute<ChoiceDisplayAttribute>()?.Name ?? x.Name, x.Name, selectMenuOptionAttr?.Description, selectMenuOptionAttr?.Emote != null ? Emote.Parse(selectMenuOptionAttr?.Emote) : null, selectMenuOptionAttr?.IsDefault);
25+
var hideAttr = x.GetCustomAttribute<HideAttribute>();
26+
Predicate<IDiscordInteraction> predicate = hideAttr != null ? hideAttr.Predicate : null;
27+
return (new SelectMenuOptionBuilder(x.GetCustomAttribute<ChoiceDisplayAttribute>()?.Name ?? x.Name, x.Name, selectMenuOptionAttr?.Description, selectMenuOptionAttr?.Emote != null ? Emote.Parse(selectMenuOptionAttr?.Emote) : null, selectMenuOptionAttr?.IsDefault), predicate);
2928
}).ToImmutableArray();
3029
}
3130

@@ -55,7 +54,7 @@ public override Task WriteAsync<TBuilder>(TBuilder builder, IDiscordInteraction
5554
if (selectMenu.MaxValues > 1 && !_isFlags)
5655
throw new InvalidOperationException($"Enum type {typeof(T).FullName} is not a [Flags] enum, so it cannot be used in a multi-select menu.");
5756

58-
selectMenu.WithOptions(_options.ToList());
57+
selectMenu.WithOptions([.. _options.Where(x => !x.Predicate?.Invoke(interaction) ?? true).Select(x => x.Option)]);
5958

6059
return Task.CompletedTask;
6160
}

0 commit comments

Comments
 (0)