@@ -102,6 +102,12 @@ def parse(cls, block: Union[dict, "Block"]) -> Optional["Block"]:
102102 return TaskCardBlock (** block )
103103 elif type == PlanBlock .type :
104104 return PlanBlock (** block )
105+ elif type == CardBlock .type :
106+ return CardBlock (** block )
107+ elif type == AlertBlock .type :
108+ return AlertBlock (** block )
109+ elif type == CarouselBlock .type :
110+ return CarouselBlock (** block )
105111 else :
106112 cls .logger .warning (f"Unknown block detected and skipped ({ block } )" )
107113 return None
@@ -878,3 +884,149 @@ def __init__(
878884
879885 self .title = title
880886 self .tasks = tasks
887+
888+
889+ class AlertBlock (Block ):
890+ type = "alert"
891+ valid_levels = {"default" , "info" , "warning" , "error" , "success" }
892+
893+ @property
894+ def attributes (self ) -> Set [str ]: # type: ignore[override]
895+ return super ().attributes .union ({"text" , "level" })
896+
897+ def __init__ (
898+ self ,
899+ * ,
900+ text : Union [str , dict , TextObject ],
901+ level : Optional [str ] = None ,
902+ block_id : Optional [str ] = None ,
903+ ** others : dict ,
904+ ):
905+ """Displays alerts, warnings, and informational messages.
906+ https://docs.slack.dev/reference/block-kit/blocks/alert-block
907+
908+ Args:
909+ text (required): The alert message, using plain_text or mrkdwn formatting.
910+ level: One of "default", "info", "warning", "error", or "success".
911+ Will be "default" if omitted.
912+ block_id: A unique identifier for a block. If not specified, a block_id will be generated.
913+ """
914+ super ().__init__ (type = self .type , block_id = block_id )
915+ show_unknown_key_warning (self , others )
916+
917+ self .text = TextObject .parse (text )
918+ self .level = level
919+
920+ @JsonValidator ("text attribute must be specified" )
921+ def _validate_text (self ):
922+ return self .text is not None
923+
924+ @JsonValidator ("level must be a valid value (default, info, warning, error, success)" )
925+ def _validate_level (self ):
926+ return self .level is None or self .level in self .valid_levels
927+
928+
929+ class CardBlock (Block ):
930+ type = "card"
931+ title_max_length = 150
932+ subtitle_max_length = 150
933+ body_max_length = 200
934+
935+ @property
936+ def attributes (self ) -> Set [str ]: # type: ignore[override]
937+ return super ().attributes .union (
938+ {
939+ "hero_image" ,
940+ "icon" ,
941+ "title" ,
942+ "subtitle" ,
943+ "body" ,
944+ "actions" ,
945+ }
946+ )
947+
948+ def __init__ (
949+ self ,
950+ * ,
951+ block_id : Optional [str ] = None ,
952+ hero_image : Optional [str ] = None ,
953+ icon : Optional [str ] = None ,
954+ title : Optional [Union [str , dict , TextObject ]] = None ,
955+ subtitle : Optional [Union [str , dict , TextObject ]] = None ,
956+ body : Optional [Union [str , dict , TextObject ]] = None ,
957+ actions : Optional [Sequence [Union [dict , BlockElement ]]] = None ,
958+ ** others : dict ,
959+ ):
960+ """Displays content in a card.
961+ https://docs.slack.dev/reference/block-kit/blocks/card-block
962+
963+ Args:
964+ block_id: A unique identifier for a block. If not specified, a block_id will be generated.
965+ hero_image: Link to the top image used on the card.
966+ icon: Link to the small image used next to the card's title and subtitle.
967+ title: Title of the card. 150 characters max.
968+ subtitle: Subtitle of the card. 150 characters max.
969+ body: Content of the card. 200 characters max.
970+ actions: Action buttons shown at the bottom of the card.
971+ """
972+ super ().__init__ (type = self .type , block_id = block_id )
973+ show_unknown_key_warning (self , others )
974+
975+ self .hero_image = hero_image
976+ self .icon = icon
977+ self .title = TextObject .parse (title , default_type = MarkdownTextObject .type ) # type: ignore[arg-type]
978+ self .subtitle = TextObject .parse (subtitle , default_type = MarkdownTextObject .type ) # type: ignore[arg-type]
979+ self .body = TextObject .parse (body , default_type = MarkdownTextObject .type ) # type: ignore[arg-type]
980+ self .actions = BlockElement .parse_all (actions ) if actions else None
981+
982+ @JsonValidator ("At least one of hero_image, title, actions, or body is required" )
983+ def _validate_content (self ):
984+ return self .hero_image is not None or self .title is not None or self .actions is not None or self .body is not None
985+
986+ @JsonValidator (f"title attribute cannot exceed { title_max_length } characters" )
987+ def _validate_title_length (self ):
988+ return self .title is None or self .title .text is None or len (self .title .text ) <= self .title_max_length
989+
990+ @JsonValidator (f"subtitle attribute cannot exceed { subtitle_max_length } characters" )
991+ def _validate_subtitle_length (self ):
992+ return self .subtitle is None or self .subtitle .text is None or len (self .subtitle .text ) <= self .subtitle_max_length
993+
994+ @JsonValidator (f"body attribute cannot exceed { body_max_length } characters" )
995+ def _validate_body_length (self ):
996+ return self .body is None or self .body .text is None or len (self .body .text ) <= self .body_max_length
997+
998+
999+ class CarouselBlock (Block ):
1000+ type = "carousel"
1001+ elements_max_length = 10
1002+
1003+ @property
1004+ def attributes (self ) -> Set [str ]: # type: ignore[override]
1005+ return super ().attributes .union ({"elements" })
1006+
1007+ def __init__ (
1008+ self ,
1009+ * ,
1010+ elements : Sequence [Union [dict , CardBlock ]],
1011+ block_id : Optional [str ] = None ,
1012+ ** others : dict ,
1013+ ):
1014+ """Displays related card blocks in a horizontally-scrolling container.
1015+ https://docs.slack.dev/reference/block-kit/blocks/carousel-block
1016+
1017+ Args:
1018+ elements (required): A list of cards. Minimum 1, maximum 10 cards.
1019+ block_id: A unique identifier for a block. If not specified, a block_id will be generated.
1020+ """
1021+ super ().__init__ (type = self .type , block_id = block_id )
1022+ show_unknown_key_warning (self , others )
1023+
1024+ self .elements = Block .parse_all (elements )
1025+
1026+ @JsonValidator ("elements attribute must contain at least 1 card" )
1027+ def _validate_elements_present (self ):
1028+ return self .elements is not None and len (self .elements ) >= 1
1029+
1030+ @JsonValidator (f"elements attribute cannot exceed { elements_max_length } cards" )
1031+ def _validate_elements_length (self ):
1032+ return self .elements is None or len (self .elements ) <= self .elements_max_length
0 commit comments