@@ -118,7 +118,7 @@ pub struct Message {
118118 /// The thread that was started from this message, includes thread member object.
119119 pub thread : Option < GuildChannel > ,
120120 /// The components of this message
121- #[ serde( default ) ]
121+ #[ serde( default , deserialize_with = "deserialize_components" ) ]
122122 pub components : Vec < ActionRow > ,
123123 /// Array of message sticker item objects.
124124 #[ serde( default ) ]
@@ -151,6 +151,60 @@ pub struct Message {
151151 pub poll : Option < Box < Poll > > ,
152152}
153153
154+ // Custom deserialize function to deserialize components safely without knocking the whole message
155+ // out when new components are found but not supported.
156+ fn deserialize_components < ' de , D > ( deserializer : D ) -> Result < Vec < ActionRow > , D :: Error >
157+ where
158+ D : Deserializer < ' de > ,
159+ {
160+ #[ derive( Deserialize ) ]
161+ struct MinComponent {
162+ #[ serde( rename = "type" ) ]
163+ kind : u8 ,
164+ }
165+
166+ struct ComponentsVisitor ;
167+
168+ impl < ' de > Visitor < ' de > for ComponentsVisitor {
169+ type Value = Vec < ActionRow > ;
170+
171+ fn expecting ( & self , formatter : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
172+ formatter. write_str ( "a sequence of ActionRow elements" )
173+ }
174+
175+ fn visit_seq < A > ( self , mut seq : A ) -> Result < Self :: Value , A :: Error >
176+ where
177+ A : serde:: de:: SeqAccess < ' de > ,
178+ {
179+ let mut components = Vec :: with_capacity ( seq. size_hint ( ) . unwrap_or_default ( ) ) ;
180+
181+ while let Some ( raw) = seq. next_element :: < & serde_json:: value:: RawValue > ( ) ? {
182+ // We deserialize only the `kind` field to determine the component type.
183+ // We later use this to check if its a supported component before deserializing the
184+ // entire payload.
185+ let min_component =
186+ MinComponent :: deserialize ( raw) . map_err ( serde:: de:: Error :: custom) ?;
187+
188+ // Action rows are the only top level component supported in serenity at this time.
189+ if min_component. kind == 1 {
190+ components. push ( ActionRow :: deserialize ( raw) . map_err ( serde:: de:: Error :: custom) ?) ;
191+ } else {
192+ // Top level component is not an action row and cannot be supported on
193+ // serenity@current without breaking changes, so we skip them.
194+ tracing:: debug!(
195+ "Skipping component with unsupported kind: {}" ,
196+ min_component. kind
197+ ) ;
198+ }
199+ }
200+
201+ Ok ( components)
202+ }
203+ }
204+
205+ deserializer. deserialize_seq ( ComponentsVisitor )
206+ }
207+
154208#[ cfg( feature = "model" ) ]
155209impl Message {
156210 /// Crossposts this message.
@@ -1211,7 +1265,7 @@ pub struct MessageSnapshot {
12111265 #[ serde( rename = "type" ) ]
12121266 pub kind : MessageType ,
12131267 pub flags : Option < MessageFlags > ,
1214- #[ serde( default ) ]
1268+ #[ serde( default , deserialize_with = "deserialize_components" ) ]
12151269 pub components : Vec < ActionRow > ,
12161270 #[ serde( default ) ]
12171271 pub sticker_items : Vec < StickerItem > ,
0 commit comments