use dotenvy::{from_path}; use std::env; use std::path::Path; use xml_builder::{XMLBuilder, XMLElement, XMLVersion}; use super::database as db; use super::database::{DidTargetType, Did}; pub fn url(did: Did) -> XMLElement { let mut work = XMLElement::new("work"); let mut bridge = XMLElement::new("execute"); let target = did.target.unwrap(); bridge.add_attribute("application", "bridge"); bridge.add_attribute("data", format!("sofia/external/{}", target).as_str()); work.add_child(bridge).unwrap(); work } pub fn moh(_did: Did) -> XMLElement { let mut work = XMLElement::new("work"); let mut playback = XMLElement::new("playback"); playback.add_attribute("file", "local_stream://default"); work.add_child(playback).unwrap(); work } pub fn external_number(did: Did) -> XMLElement { let mut work = XMLElement::new("work"); let mut bridge = XMLElement::new("execute"); let callee_number = did.target.unwrap(); let ds = build_dial_string(&callee_number, &did.did_number); bridge.add_attribute("application", "bridge"); bridge.add_attribute("data", &ds); work.add_child(bridge).unwrap(); work } pub fn no_service(_did: Did) -> XMLElement { let env_path = Path::new("/etc/did_router.conf"); from_path(env_path).expect("env file missed"); let sound_path = env::var("SOUND_PATH").expect("SOUND_PATH must be set"); let no_service_path = format!("{}/no_service.wav", sound_path); let mut work = XMLElement::new("work"); add_playback_element(&mut work, &no_service_path); work } pub fn night_mode(_did: Did) -> XMLElement { let env_path = Path::new("/etc/did_router.conf"); from_path(env_path).expect("env file missed"); let sound_path = env::var("SOUND_PATH").expect("SOUND_PATH must be set"); let night_mode_path = format!("{}/night_mode.wav", sound_path); let mut work = XMLElement::new("work"); add_playback_element(&mut work, &night_mode_path); work } pub fn custom_message(_did: Did) -> XMLElement { let work = XMLElement::new("work"); work } fn build_dial_string(callee_number: &str, caller_number: &str) -> String { let ds = match db::get_did_by(&caller_number) { Ok(d) => { if d.trunk == "3229" || d.trunk == "3401" { format!("{{origination_caller_id_number={} }}sofia/gateway/powernet_1/{}", caller_number, callee_number) } else { format!("{{origination_caller_id_number={} }}sofia/gateway/powernet_2/{}", caller_number, callee_number) } }, Err(..) =>{ format!("{{origination_caller_id_number={} }}sofia/gateway/powernet_1/{}", caller_number, callee_number) } }; ds } pub fn outbound(did: &str, caller_number: &str) -> XMLElement { let mut work = XMLElement::new("work"); let mut bridge = XMLElement::new("execute"); let ds = build_dial_string(did, caller_number); bridge.add_attribute("application", "bridge"); bridge.add_attribute("data", &ds); work.add_child(bridge).unwrap(); work } pub fn add_playback_element(work: &mut XMLElement ,file_path: &str) { let mut answer = XMLElement::new("execute"); answer.add_attribute("application", "answer"); work.add_child(answer).unwrap(); let mut playback = XMLElement::new("playback"); playback.add_attribute("file", &file_path); work.add_child(playback).unwrap(); } pub fn build_work_element(did: &str, caller_number: &str, caller_ipaddr: &str) -> XMLElement { if db::from_pbx(&caller_ipaddr).unwrap() == true { outbound(did, caller_number) } else { let d = db::get_did_by(&did).unwrap(); let work = match d.target_type { DidTargetType::Url => { url(d) }, DidTargetType::Moh => { moh(d) }, DidTargetType::ExternalNumber => { external_number(d) }, DidTargetType::NoService => { no_service(d) }, DidTargetType::NightMode => { night_mode(d) }, DidTargetType::CustomMessage => { custom_message(d) } }; work } } pub fn route_call(did: String, caller_number: String,caller_ipaddr: String) -> Vec { let mut xml = XMLBuilder::new() .version(XMLVersion::XML1_1) .encoding("UTF-8".into()) .build(); let mut doc = XMLElement::new("document"); doc.add_attribute("type", "xml/freeswitch-httapi"); let params = XMLElement::new("params"); let mut work = build_work_element(&did, &caller_number, &caller_ipaddr); let mut hangup = XMLElement::new("execute"); hangup.add_attribute("application", "hangup"); work.add_child(hangup).unwrap(); doc.add_child(params).unwrap(); let d = db::get_did_by(&did); match d { Ok(d) => { if d.active == true { doc.add_child(work).unwrap(); } }, Err(_) => { doc.add_child(work).unwrap(); } } xml.set_root_element(doc); let mut writer: Vec = Vec::new(); xml.generate(&mut writer).unwrap(); writer }