Select Git revision
sms.rs 6.73 KiB
use std::{
io::Write,
hash::{Hash, Hasher},
collections::hash_map::DefaultHasher,
fs::File,
path::PathBuf,
};
use regex::Regex;
use crate::{
SmsError,
VALID_CHARACTERS,
CONFIG,
validate_and_normalize_phonenumber,
};
use serde::{Deserialize, Serialize};
use chrono::prelude::*;
use lazy_static::lazy_static;
pub use log::{info, warn, debug, error};
/// Represents an SMS that is to be sent to a phone number
#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct Sms {
pub number: String,
pub text: String,
}
impl Sms {
/// Try to create a Sms from the provided number and text
/// Return an Error if the text was too long, too short, has
/// invalid characters or if the phonenumber format is invalid
pub fn try_from(number: &str, text: &str) -> Result<Self, SmsError> {
if text.len() < CONFIG.sms.min_length {
warn!("SMS-text was too short: {} character(s)", text.len());
return Err(SmsError::TooShort);
}
if text.len() > CONFIG.sms.max_length {
warn!("SMS-text was too long: {} characters", text.len());
return Err(SmsError::TooLong);
}
if text.chars().any(|c| !VALID_CHARACTERS.contains(&c)) {
warn!("SMS-text contained illegal characters: \"{}\"", text);
return Err(SmsError::InvalidCharacters);
}
let number = validate_and_normalize_phonenumber(number)?;
Ok(Sms {
number,
text: text.to_string()
})
}
pub fn deserialize_from(body: &str) -> Result<Self, SmsError> {
lazy_static! {
// flags m: multiline, s: allow . to match \n
static ref SMS_PATTERN: Regex = Regex::new(r"(?ms)^To:\s([0-9+]+)(?:(?:\n\w*:\s?\w+))*?\n\n+(.*)").unwrap();
}
let captures = match SMS_PATTERN.captures(body) {
Some(c) => c,
None => return Err(SmsError::DeserializationError(body.to_string()))
};
let number = captures.get(1).map_or("", |m| m.as_str()).trim();