Lines of
src/utils.rs
from check-in bf99298edf
that are changed by the sequence of edits moving toward
check-in 997fb1cff4:
1: use crate::Cursor;
2:
bf99298edf 2026-07-31 3: use std::borrow::Cow;
4:
5: use html_escape::encode_text;
bf99298edf 2026-07-31 6: use lazy_static::lazy_static;
7: use regex::{
8: Regex,
9: RegexBuilder,
10: };
11: use stacked_errors::{
12: bail,
13: Result,
14: };
15:
bf99298edf 2026-07-31 16: lazy_static! {
bf99298edf 2026-07-31 17: pub static ref RE_DOMAIN: Regex = 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");
bf99298edf 2026-07-31 18: pub static ref RE_CLOSING: Regex = RegexBuilder::new(r"</[ \t]*(pre|code)[ \t]*>")
bf99298edf 2026-07-31 19: .case_insensitive(true).build().expect("Invalid closing tag regex");
bf99298edf 2026-07-31 20: }
21:
22: /// Stores binary attachment data and metadata for Telegram messages.
23: /// The data is wrapped in a `Cursor<Vec<u8>>` for efficient streaming,
24: /// while `name` holds the filename or display name of the attachment.
25: #[derive(Debug)]
26: pub struct Attachment {
27: pub data: Cursor<Vec<u8>>,
28: pub name: String,
29: }
30:
31: /// Pass any text here to be validated as not breaking from Telegram preformatted blocks
32: /// escape all HTML chars afterwards
33: pub fn validate <'a>(text: &'a str) -> Result<Cow<'a, str>> {
34: if RE_CLOSING.is_match(text) {
35: bail!("Telegram closing tag found.");
36: } else {
37: Ok(encode_text(text))
38: }
39: }