Annotation For src/utils.rs
Logged in as anonymous

Origin for each line in src/utils.rs from check-in 78b11b0319:

78b11b0319 2026-08-01    1: //! Utility functions and types for the application.
78b11b0319 2026-08-01    2: 
f5ed284f8c 2025-06-21    3: use crate::Cursor;
f5ed284f8c 2025-06-21    4: 
78b11b0319 2026-08-01    5: use std::{
78b11b0319 2026-08-01    6: 	borrow::Cow,
78b11b0319 2026-08-01    7: 	sync::LazyLock,
78b11b0319 2026-08-01    8: };
1c10bccb4e 2026-01-18    9: 
1c10bccb4e 2026-01-18   10: use html_escape::encode_text;
f4660639ca 2026-07-31   11: use regex::{
f4660639ca 2026-07-31   12: 	Regex,
f4660639ca 2026-07-31   13: 	RegexBuilder,
f4660639ca 2026-07-31   14: };
d87e80b9be 2026-01-12   15: use stacked_errors::{
d87e80b9be 2026-01-12   16: 	bail,
d87e80b9be 2026-01-12   17: 	Result,
d87e80b9be 2026-01-12   18: };
d87e80b9be 2026-01-12   19: 
78b11b0319 2026-08-01   20: pub static RE_DOMAIN: LazyLock<Regex> = LazyLock::new(|| {
78b11b0319 2026-08-01   21: 	Regex::new(r"^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$").expect("Invalid domain regex")
78b11b0319 2026-08-01   22: });
78b11b0319 2026-08-01   23: pub static RE_CLOSING: LazyLock<Regex> = LazyLock::new(|| {
78b11b0319 2026-08-01   24: 	RegexBuilder::new(r"</[ \t]*(pre|code)[ \t]*>")
78b11b0319 2026-08-01   25: 		.case_insensitive(true).build().expect("Invalid closing tag regex")
78b11b0319 2026-08-01   26: });
d87e80b9be 2026-01-12   27: 
f4660639ca 2026-07-31   28: /// Stores binary attachment data and metadata for Telegram messages.
f4660639ca 2026-07-31   29: /// The data is wrapped in a `Cursor<Vec<u8>>` for efficient streaming,
f4660639ca 2026-07-31   30: /// while `name` holds the filename or display name of the attachment.
f5ed284f8c 2025-06-21   31: #[derive(Debug)]
f5ed284f8c 2025-06-21   32: pub struct Attachment {
f5ed284f8c 2025-06-21   33: 	pub data: Cursor<Vec<u8>>,
f5ed284f8c 2025-06-21   34: 	pub name: String,
d87e80b9be 2026-01-12   35: }
d87e80b9be 2026-01-12   36: 
78b11b0319 2026-08-01   37: /// Validates text to ensure it doesn't break Telegram's preformatted blocks.
78b11b0319 2026-08-01   38: ///
78b11b0319 2026-08-01   39: /// Escapes HTML special characters to prevent injection.
78b11b0319 2026-08-01   40: ///
78b11b0319 2026-08-01   41: /// # Arguments
78b11b0319 2026-08-01   42: /// * `text` - Text to validate and escape.
78b11b0319 2026-08-01   43: ///
78b11b0319 2026-08-01   44: /// # Returns
78b11b0319 2026-08-01   45: /// * `Result<Cow<'a, str>>` - Escaped text or error if invalid.
78b11b0319 2026-08-01   46: ///
78b11b0319 2026-08-01   47: /// # Errors
78b11b0319 2026-08-01   48: /// Returns an error if the text contains Telegram closing tags (`</pre>`, `</code>`).
f4660639ca 2026-07-31   49: pub fn validate <'a>(text: &'a str) -> Result<Cow<'a, str>> {
1c10bccb4e 2026-01-18   50: 	if RE_CLOSING.is_match(text) {
1c10bccb4e 2026-01-18   51: 		bail!("Telegram closing tag found.");
1c10bccb4e 2026-01-18   52: 	} else {
1c10bccb4e 2026-01-18   53: 		Ok(encode_text(text))
1c10bccb4e 2026-01-18   54: 	}
f5ed284f8c 2025-06-21   55: }