1- using System . Net ;
2- using System . Text . Json . Serialization ;
3- using Disc . NET . Client . SDK . Messages . Components ;
4- using Disc . NET . Client . SDK . Messages . Embeds ;
5- using Disc . NET . Shared . Constraints ;
6- using Disc . NET . Shared . Enums ;
7- using Disc . NET . Shared . Exceptions ;
1+ using Disc . NET . Client . SDK . Messages . Embeds ;
82
93namespace Disc . NET . Client . SDK . Messages ;
104
@@ -13,149 +7,13 @@ public class ApiMessage
137 public string ? MessageId { get ; set ; }
148 public string Content { get ; set ; } = string . Empty ;
159 public List < Embed > Embeds { get ; set ; } = [ ] ;
10+ public long Flags { get ; set ; }
1611
17- [ JsonIgnore ]
18- public List < MessageFlag > ? MessageFlags { get ; set ; }
19-
20- public long Flags => MessageFlags ? . Aggregate ( 0L , ( current , flag ) => current | ( long ) flag ) ?? 0L ;
21-
22- [ JsonIgnore ]
23- public List < IMessageComponentBuilder > MessageComponents { get ; set ; } = [ ] ;
24-
25- public List < object > Components => MountComponents ( ) ;
12+ public List < object > Components { get ; set ; } = [ ] ;
2613
2714 public int ? Type { get ; set ; }
2815
2916 public ApiMessage ? MessageReference { get ; set ; }
3017
31- private List < object > MountComponents ( )
32- {
33- if ( MessageComponents . Count > 5 )
34- throw new DiscNetGenericException ( "The message cannot contain more than 5 top-level components." ) ;
35-
36- var results = new List < object > ( ) ;
37-
38- NormalizeActionRows < ActionRowSelectMenuComponentBuilder > ( ActionRowConstraint . MAX_SELECT_MENUS_PER_ACTION_ROW , message =>
39- new ActionRowSelectMenuComponentBuilder ( ) . AddMenu ( message . First ( ) ) ) ;
40-
41- NormalizeActionRows < ActionRowButtonComponentBuilder > ( ActionRowConstraint . MAX_BUTTONS_PER_ACTION_ROW , message =>
42- new ActionRowButtonComponentBuilder ( ) . AddButtons ( message ) ) ;
43-
44- MessageComponents . ForEach ( x => results . Add ( x . Build ( ) ) ) ;
45- return results ;
46- }
47-
48- /// <summary>
49- /// Normalizes action rows of a specific component type to comply with Discord message constraints.
50- ///
51- /// This method validates the maximum number of action rows per message and the maximum number
52- /// of components allowed per action row. If an action row exceeds the allowed number of components,
53- /// it is automatically split into multiple valid action rows.
54- /// </summary>
55- /// <typeparam name="T">
56- /// The type of action row builder to process (e.g., select menu rows or button rows).
57- /// </typeparam>
58- /// <param name="quantityComponentPerActionRow">
59- /// The maximum number of components allowed per action row for the given component type.
60- /// </param>
61- /// <param name="createBuilderFunc">
62- /// A factory function responsible for creating a new action row builder from a list
63- /// of message components.
64- /// </param>
65- /// <exception cref="DiscNetClientSdkException">
66- /// Thrown when the message exceeds Discord constraints, such as:
67- /// - Maximum number of action rows per message
68- /// - Insufficient available action row slots to split invalid rows
69- /// </exception>
70- /// <remarks>
71- /// This method mutates the <see cref="MessageComponents"/> collection by:
72- /// - Removing excess components from invalid action rows
73- /// - Adding newly created action rows to the message
74- /// </remarks>
75-
76- private void NormalizeActionRows < T > ( int quantityComponentPerActionRow ,
77- Func < List < IMessageComponent > , IMessageComponentBuilder > createBuilderFunc )
78- where T : IMessageComponentBuilder
79- {
80- var actionRows = MessageComponents . Where ( x => x is T ) . ToList ( ) ;
81-
82- if ( actionRows . Count == 0 ) return ;
83- int actionRowsPerMessage = ActionRowConstraint . MAX_ACTION_ROWS_PER_MESSAGE ;
84- int actionRowsCount = actionRows . Count ;
85- if ( actionRowsCount > actionRowsPerMessage )
86- {
87- throw new DiscNetGenericException (
88- $ "The message cannot contain more than { actionRowsPerMessage } top-level components.") ;
89- }
90-
91- int availableActionRowSlots = actionRowsPerMessage - MessageComponents . Count ;
92- var invalidActionRows = actionRows . Where ( x => x . Components . Count > quantityComponentPerActionRow ) . ToList ( ) ;
93- var containsActionRowsInvalids = invalidActionRows . Count > 0 ;
94-
95- if ( ! containsActionRowsInvalids ) return ;
96- if ( availableActionRowSlots == 0 && containsActionRowsInvalids )
97- {
98- throw new DiscNetGenericException ( $ "The message cannot contain more than { actionRowsPerMessage } top-level components.") ;
99- }
100-
101- int numberNecessaryToCreateNewActionRows ;
102- if ( quantityComponentPerActionRow > 1 )
103- {
104- numberNecessaryToCreateNewActionRows = invalidActionRows
105- . Select ( x => ( int ) Math . Ceiling ( ( double ) x . Components . Count / quantityComponentPerActionRow ) - 1 )
106- . Sum ( ) ;
107- }
108- else
109- {
110- numberNecessaryToCreateNewActionRows = invalidActionRows
111- . Select ( x => x . Components . Count - 1 )
112- . Sum ( ) ;
113- }
114-
115-
116- if ( numberNecessaryToCreateNewActionRows > availableActionRowSlots )
117- {
118- throw new DiscNetGenericException (
119- $ "The message cannot contain more than { actionRowsPerMessage } top-level components.") ;
120- }
121-
122- int newActionRowsCount = 0 ;
123- foreach ( var actionRow in invalidActionRows )
124- {
125- var messageComponents = actionRow . Components
126- . OfType < IMessageComponent > ( )
127- . ToList ( ) ;
128-
129- int index = 0 ;
130- while ( messageComponents . Count - index > quantityComponentPerActionRow &&
131- newActionRowsCount < availableActionRowSlots )
132- {
133- IMessageComponentBuilder ? newActionRow ;
134-
135- if ( quantityComponentPerActionRow > 1 )
136- {
137- var components = messageComponents
138- . Skip ( index )
139- . Take ( quantityComponentPerActionRow )
140- . ToList ( ) ;
141- components . ForEach ( x => actionRow . Components . Remove ( x ) ) ;
142- index += quantityComponentPerActionRow ;
143- newActionRow = createBuilderFunc . Invoke ( components ) ;
144- }
145- else
146- {
147- var component = messageComponents [ index ] ;
148-
149- actionRow . Components . Remove ( component ) ;
150- index ++ ;
151- newActionRow = createBuilderFunc . Invoke ( [ component ] ) ;
152- }
153-
154- MessageComponents . Add ( newActionRow ) ;
155- newActionRowsCount ++ ;
156- }
157- }
158- }
159- // Colocar os outros campos depois
16018 // https://discord.com/developers/docs/resources/message#message-object
16119}
0 commit comments