CV2 Find component by id (#3110)

* Find components by id

* i love when CI fails cuz of xmldoc
This commit is contained in:
Mihail Gribkov
2025-05-08 13:25:00 +03:00
committed by GitHub
parent 348928a065
commit cc81669d83
2 changed files with 45 additions and 1 deletions

View File

@@ -53,9 +53,14 @@ public class ComponentBuilderV2 : IStaticComponentContainer
/// <inheritdoc cref="IMessageComponentBuilder.Build" />
public MessageComponent Build()
{
Preconditions.AtLeast(Components?.Count ?? 0, 1, nameof(Components.Count), "At least 1 component must be added to this container.");
Preconditions.NotNull(Components, nameof(Components));
Preconditions.AtLeast(Components.Count, 1, nameof(Components.Count), "At least 1 component must be added to this container.");
Preconditions.AtMost(this.ComponentCount(), MaxComponents, nameof(Components.Count), $"A message must contain {MaxComponents} components or less.");
var ids = this.GetComponentIds().ToList();
if (ids.Count != ids.Distinct().Count())
throw new InvalidOperationException("Components must have unique ids.");
if (_components.Any(x =>
x is not ActionRowBuilder
and not SectionBuilder

View File

@@ -321,4 +321,43 @@ public static class ComponentContainerExtensions
=> container.WithActionRow(new ActionRowBuilder()
.WithComponents(components)
.WithId(id));
/// <summary>
/// Finds the first <see cref="IMessageComponentBuilder"/> in the <see cref="IComponentContainer"/>
/// or any of its child <see cref="IComponentContainer"/>s with matching id.
/// </summary>
/// <returns>
/// The <see cref="IMessageComponentBuilder"/> with matching id, <see langword="null"/> otherwise.
/// </returns>
public static IMessageComponentBuilder FindComponentById(this IComponentContainer container, int id)
=> container.FindComponentById<IMessageComponentBuilder>(id);
/// <summary>
/// Finds the first <c>ComponentT</c> in the <see cref="IComponentContainer"/>
/// or any of its child <see cref="IComponentContainer"/>s with matching id.
/// </summary>
/// <returns>
/// The <c>ComponentT</c> with matching id, <see langword="null"/> otherwise.
/// </returns>
public static ComponentT FindComponentById<ComponentT>(this IComponentContainer container, int id)
where ComponentT : class, IMessageComponentBuilder
=> container.Components
.OfType<ComponentT>()
.FirstOrDefault(x => x.Id == id)
?? container.Components
.OfType<IComponentContainer>()
.Select(x => x.FindComponentById<ComponentT>(id))
.FirstOrDefault(x => x is not null);
/// <summary>
/// Gets a <see cref="IEnumerable{T}">IEnumerable</see> containing ids of <see cref="IMessageComponentBuilder"/>
/// in this <see cref="IComponentContainer"/> and all child <see cref="IComponentContainer"/>s.
/// </summary>
public static IEnumerable<int> GetComponentIds(this IComponentContainer container)
=> container.Components
.Where(x => x.Id is not null)
.Select(x => x.Id.Value)
.Concat(container.Components
.OfType<IComponentContainer>()
.SelectMany(x => x.GetComponentIds()));
}