1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use serde::{Deserialize, Serialize}; use validator::Validate; use crate::compose::Compose; use crate::val_helpr::ValidationResult; /// # Context Block /// /// _[slack api docs 🔗][context_docs]_ /// /// Displays message context, which can include both images and text. /// /// [context_docs]: https://api.slack.com/reference/block-kit/blocks#context #[derive(Clone, Debug, Default, Deserialize, Hash, PartialEq, Serialize, Validate)] pub struct Contents { /// A collection of [image elements 🔗] and [text objects 🔗]. /// /// Maximum number of items is 10 /// [image elements 🔗]: https://api.slack.com/reference/messaging/block-elements#image /// [text objects 🔗]: https://api.slack.com/reference/messaging/composition-objects#text #[validate(length(max = 10))] elements: Vec<Compose>, /// A string acting as a unique identifier for a block. /// /// You can use this `block_id` when you receive an /// interaction payload to [identify the source of the action 🔗]. /// /// If not specified, a `block_id` will be generated. /// /// Maximum length for this field is 255 characters. /// /// [identify the source of the action 🔗]: https://api.slack.com/interactivity/handling#payloads #[validate(length(max = 255))] block_id: Option<String>, } impl Contents { /// Construct a new empty Context block /// (uses `Default`) pub fn new() -> Self { Default::default() } /// Set the `block_id` for interactions on an existing `context::Contents` /// /// ``` /// use slack_blocks::blocks::{Block, context}; /// /// pub fn main() { /// let context = context::Contents::new().with_block_id("tally_ho"); /// let block: Block = context.into(); /// // < send block to slack's API > /// } /// ``` pub fn with_block_id<StrIsh: AsRef<str>>(mut self, block_id: StrIsh) -> Self { self.block_id = Some(block_id.as_ref().to_string()); self } /// Construct a new `context::Contents` from a bunch of /// composition objects /// /// ``` /// use slack_blocks::blocks::{Block, context}; /// use slack_blocks::compose; /// /// pub fn main() { /// let text = compose::Text::markdown("*s i c k*"); /// let context = context::Contents::from_elements(vec![text]); /// let block: Block = context.into(); /// // < send block to slack's API > /// } /// ``` pub fn from_elements<Els: IntoIterator<Item = impl Into<Compose>>>(elements: Els) -> Self { elements .into_iter() .map(Into::<Compose>::into) .collect::<Vec<_>>() .into() } /// Validate that the model agrees with slack's validation /// requirements pub fn validate(&self) -> ValidationResult { Validate::validate(self) } } // From impl backing the `from_elements` constructor impl From<Vec<Compose>> for Contents { fn from(elements: Vec<Compose>) -> Self { Self { elements, ..Default::default() } } }