@@ -264,6 +264,271 @@ mod tests {
264264 tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
265265 }
266266
267+ // ── modal_respond ─────────────────────────────────────────────────────────
268+
269+ #[ tokio:: test]
270+ async fn test_modal_respond_command_is_consumed ( ) {
271+ use discord_types:: ModalRespondCommand ;
272+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
273+ let prefix = format ! ( "test-out-modal-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
274+ start_processor ( client. clone ( ) , & prefix) . await ;
275+ publish ( & client, & subjects:: agent:: interaction_modal_respond ( & prefix) , & ModalRespondCommand {
276+ interaction_id : 1111 ,
277+ interaction_token : "fake-token" . to_string ( ) ,
278+ custom_id : "my_modal" . to_string ( ) ,
279+ title : "Test Modal" . to_string ( ) ,
280+ inputs : vec ! [ ] ,
281+ } ) . await ;
282+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
283+ }
284+
285+ // ── autocomplete_respond ──────────────────────────────────────────────────
286+
287+ #[ tokio:: test]
288+ async fn test_autocomplete_respond_command_is_consumed ( ) {
289+ use discord_types:: { AutocompleteChoice , AutocompleteRespondCommand } ;
290+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
291+ let prefix = format ! ( "test-out-ac-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
292+ start_processor ( client. clone ( ) , & prefix) . await ;
293+ publish ( & client, & subjects:: agent:: interaction_autocomplete_respond ( & prefix) , & AutocompleteRespondCommand {
294+ interaction_id : 2222 ,
295+ interaction_token : "fake-token" . to_string ( ) ,
296+ choices : vec ! [ AutocompleteChoice { name: "Option A" . to_string( ) , value: "a" . to_string( ) } ] ,
297+ } ) . await ;
298+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
299+ }
300+
301+ // ── ban ───────────────────────────────────────────────────────────────────
302+
303+ #[ tokio:: test]
304+ async fn test_ban_user_command_is_consumed ( ) {
305+ use discord_types:: BanUserCommand ;
306+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
307+ let prefix = format ! ( "test-out-ban-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
308+ start_processor ( client. clone ( ) , & prefix) . await ;
309+ publish ( & client, & subjects:: agent:: guild_ban ( & prefix) , & BanUserCommand {
310+ guild_id : 200 ,
311+ user_id : 42 ,
312+ reason : Some ( "spam" . to_string ( ) ) ,
313+ delete_message_seconds : 0 ,
314+ } ) . await ;
315+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
316+ }
317+
318+ // ── kick ──────────────────────────────────────────────────────────────────
319+
320+ #[ tokio:: test]
321+ async fn test_kick_user_command_is_consumed ( ) {
322+ use discord_types:: KickUserCommand ;
323+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
324+ let prefix = format ! ( "test-out-kick-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
325+ start_processor ( client. clone ( ) , & prefix) . await ;
326+ publish ( & client, & subjects:: agent:: guild_kick ( & prefix) , & KickUserCommand {
327+ guild_id : 200 ,
328+ user_id : 42 ,
329+ reason : None ,
330+ } ) . await ;
331+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
332+ }
333+
334+ // ── timeout ───────────────────────────────────────────────────────────────
335+
336+ #[ tokio:: test]
337+ async fn test_timeout_user_command_is_consumed ( ) {
338+ use discord_types:: TimeoutUserCommand ;
339+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
340+ let prefix = format ! ( "test-out-timeout-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
341+ start_processor ( client. clone ( ) , & prefix) . await ;
342+ publish ( & client, & subjects:: agent:: guild_timeout ( & prefix) , & TimeoutUserCommand {
343+ guild_id : 200 ,
344+ user_id : 42 ,
345+ duration_secs : 3600 ,
346+ reason : Some ( "cooling off" . to_string ( ) ) ,
347+ } ) . await ;
348+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
349+ }
350+
351+ // ── create_channel ────────────────────────────────────────────────────────
352+
353+ #[ tokio:: test]
354+ async fn test_create_channel_command_is_consumed ( ) {
355+ use discord_types:: { ChannelType , CreateChannelCommand } ;
356+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
357+ let prefix = format ! ( "test-out-ch-create-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
358+ start_processor ( client. clone ( ) , & prefix) . await ;
359+ publish ( & client, & subjects:: agent:: channel_create ( & prefix) , & CreateChannelCommand {
360+ guild_id : 200 ,
361+ name : "new-channel" . to_string ( ) ,
362+ channel_type : ChannelType :: GuildText ,
363+ category_id : None ,
364+ topic : None ,
365+ } ) . await ;
366+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
367+ }
368+
369+ // ── edit_channel ──────────────────────────────────────────────────────────
370+
371+ #[ tokio:: test]
372+ async fn test_edit_channel_command_is_consumed ( ) {
373+ use discord_types:: EditChannelCommand ;
374+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
375+ let prefix = format ! ( "test-out-ch-edit-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
376+ start_processor ( client. clone ( ) , & prefix) . await ;
377+ publish ( & client, & subjects:: agent:: channel_edit ( & prefix) , & EditChannelCommand {
378+ channel_id : 300 ,
379+ name : Some ( "renamed" . to_string ( ) ) ,
380+ topic : None ,
381+ } ) . await ;
382+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
383+ }
384+
385+ // ── delete_channel ────────────────────────────────────────────────────────
386+
387+ #[ tokio:: test]
388+ async fn test_delete_channel_command_is_consumed ( ) {
389+ use discord_types:: DeleteChannelCommand ;
390+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
391+ let prefix = format ! ( "test-out-ch-del-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
392+ start_processor ( client. clone ( ) , & prefix) . await ;
393+ publish ( & client, & subjects:: agent:: channel_delete ( & prefix) , & DeleteChannelCommand { channel_id : 300 } ) . await ;
394+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
395+ }
396+
397+ // ── create_role ───────────────────────────────────────────────────────────
398+
399+ #[ tokio:: test]
400+ async fn test_create_role_command_is_consumed ( ) {
401+ use discord_types:: CreateRoleCommand ;
402+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
403+ let prefix = format ! ( "test-out-role-create-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
404+ start_processor ( client. clone ( ) , & prefix) . await ;
405+ publish ( & client, & subjects:: agent:: role_create ( & prefix) , & CreateRoleCommand {
406+ guild_id : 200 ,
407+ name : "VIP" . to_string ( ) ,
408+ color : Some ( 0xFFD700 ) ,
409+ hoist : true ,
410+ mentionable : false ,
411+ } ) . await ;
412+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
413+ }
414+
415+ // ── assign_role ───────────────────────────────────────────────────────────
416+
417+ #[ tokio:: test]
418+ async fn test_assign_role_command_is_consumed ( ) {
419+ use discord_types:: AssignRoleCommand ;
420+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
421+ let prefix = format ! ( "test-out-role-assign-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
422+ start_processor ( client. clone ( ) , & prefix) . await ;
423+ publish ( & client, & subjects:: agent:: role_assign ( & prefix) , & AssignRoleCommand {
424+ guild_id : 200 , user_id : 42 , role_id : 111 ,
425+ } ) . await ;
426+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
427+ }
428+
429+ // ── remove_role ───────────────────────────────────────────────────────────
430+
431+ #[ tokio:: test]
432+ async fn test_remove_role_command_is_consumed ( ) {
433+ use discord_types:: RemoveRoleCommand ;
434+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
435+ let prefix = format ! ( "test-out-role-remove-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
436+ start_processor ( client. clone ( ) , & prefix) . await ;
437+ publish ( & client, & subjects:: agent:: role_remove ( & prefix) , & RemoveRoleCommand {
438+ guild_id : 200 , user_id : 42 , role_id : 111 ,
439+ } ) . await ;
440+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
441+ }
442+
443+ // ── delete_role ───────────────────────────────────────────────────────────
444+
445+ #[ tokio:: test]
446+ async fn test_delete_role_command_is_consumed ( ) {
447+ use discord_types:: DeleteRoleCommand ;
448+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
449+ let prefix = format ! ( "test-out-role-del-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
450+ start_processor ( client. clone ( ) , & prefix) . await ;
451+ publish ( & client, & subjects:: agent:: role_delete ( & prefix) , & DeleteRoleCommand {
452+ guild_id : 200 , role_id : 111 ,
453+ } ) . await ;
454+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
455+ }
456+
457+ // ── pin ───────────────────────────────────────────────────────────────────
458+
459+ #[ tokio:: test]
460+ async fn test_pin_message_command_is_consumed ( ) {
461+ use discord_types:: PinMessageCommand ;
462+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
463+ let prefix = format ! ( "test-out-pin-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
464+ start_processor ( client. clone ( ) , & prefix) . await ;
465+ publish ( & client, & subjects:: agent:: message_pin ( & prefix) , & PinMessageCommand {
466+ channel_id : 100 , message_id : 50 ,
467+ } ) . await ;
468+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
469+ }
470+
471+ // ── unpin ─────────────────────────────────────────────────────────────────
472+
473+ #[ tokio:: test]
474+ async fn test_unpin_message_command_is_consumed ( ) {
475+ use discord_types:: UnpinMessageCommand ;
476+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
477+ let prefix = format ! ( "test-out-unpin-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
478+ start_processor ( client. clone ( ) , & prefix) . await ;
479+ publish ( & client, & subjects:: agent:: message_unpin ( & prefix) , & UnpinMessageCommand {
480+ channel_id : 100 , message_id : 50 ,
481+ } ) . await ;
482+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
483+ }
484+
485+ // ── bulk_delete ───────────────────────────────────────────────────────────
486+
487+ #[ tokio:: test]
488+ async fn test_bulk_delete_messages_command_is_consumed ( ) {
489+ use discord_types:: BulkDeleteMessagesCommand ;
490+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
491+ let prefix = format ! ( "test-out-bulk-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
492+ start_processor ( client. clone ( ) , & prefix) . await ;
493+ publish ( & client, & subjects:: agent:: message_bulk_delete ( & prefix) , & BulkDeleteMessagesCommand {
494+ channel_id : 100 ,
495+ message_ids : vec ! [ 1 , 2 , 3 ] ,
496+ } ) . await ;
497+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
498+ }
499+
500+ // ── create_thread ─────────────────────────────────────────────────────────
501+
502+ #[ tokio:: test]
503+ async fn test_create_thread_command_is_consumed ( ) {
504+ use discord_types:: CreateThreadCommand ;
505+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
506+ let prefix = format ! ( "test-out-thread-create-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
507+ start_processor ( client. clone ( ) , & prefix) . await ;
508+ publish ( & client, & subjects:: agent:: thread_create ( & prefix) , & CreateThreadCommand {
509+ channel_id : 100 ,
510+ name : "Discussion" . to_string ( ) ,
511+ message_id : None ,
512+ auto_archive_mins : 1440 ,
513+ } ) . await ;
514+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
515+ }
516+
517+ // ── archive_thread ────────────────────────────────────────────────────────
518+
519+ #[ tokio:: test]
520+ async fn test_archive_thread_command_is_consumed ( ) {
521+ use discord_types:: ArchiveThreadCommand ;
522+ let Some ( client) = try_connect ( ) . await else { eprintln ! ( "SKIP: NATS not available" ) ; return ; } ;
523+ let prefix = format ! ( "test-out-thread-archive-{}" , uuid:: Uuid :: new_v4( ) . simple( ) ) ;
524+ start_processor ( client. clone ( ) , & prefix) . await ;
525+ publish ( & client, & subjects:: agent:: thread_archive ( & prefix) , & ArchiveThreadCommand {
526+ channel_id : 100 ,
527+ locked : false ,
528+ } ) . await ;
529+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 300 ) ) . await ;
530+ }
531+
267532 // ── multiple commands in sequence ─────────────────────────────────────────
268533
269534 #[ tokio:: test]
0 commit comments