use std::str::FromStr;
use freeswitch_types::{BridgeDialString, DialString};
use crate::fields::processing_parts;
use crate::message::new_channel_name;
pub(super) struct DialplanContext {
pub(super) from: String,
pub(super) to: String,
pub(super) context: String,
}
pub(super) fn parse_dialplan_context(detail: &str) -> Option<&str> {
let rest = detail.strip_prefix("parsing [")?;
let bracket_end = rest.find(']')?;
let inner = &rest[..bracket_end];
let arrow = inner.find("->")?;
Some(&inner[..arrow])
}
pub(super) fn parse_processing_line(msg: &str) -> Option<DialplanContext> {
let parts = processing_parts(msg)?;
Some(DialplanContext {
from: msg[parts.head].to_string(),
to: msg[parts.dest].to_string(),
context: msg[parts.context].to_string(),
})
}
pub(super) fn parse_new_channel(detail: &str) -> Option<String> {
new_channel_name(detail).map(str::to_string)
}
pub(super) enum StateChange<'a> {
Channel(&'a str),
Call(&'a str),
}
pub(super) fn parse_state_change(detail: &str) -> Option<StateChange<'_>> {
let arrow = detail.find(" -> ")?;
let to = detail[arrow + 4..].trim();
if detail.contains("Callstate Change") {
Some(StateChange::Call(to))
} else {
Some(StateChange::Channel(to))
}
}
pub(super) fn parse_hangup(detail: &str) -> Option<String> {
if !detail.contains("Hangup ") {
return None;
}
let start = detail.rfind('[')?;
let end = detail[start..].find(']')?;
Some(detail[start + 1..start + end].to_string())
}
pub(super) fn is_answered(detail: &str) -> bool {
detail.contains("has been answered")
}
pub fn parse_bridge_args(arguments: &str) -> Option<BridgeInfo> {
let dial = BridgeDialString::from_str(arguments).ok()?;
let first_ep = dial.groups().first()?.first()?;
let origination_uuid = first_ep
.variables()
.and_then(|v| v.get("origination_uuid"))
.or_else(|| dial.variables().and_then(|v| v.get("origination_uuid")))
.map(|s| s.to_string());
let mut bare = first_ep.clone();
bare.set_variables(None);
let target_channel = bare.to_string();
Some(BridgeInfo {
origination_uuid,
target_channel,
})
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct BridgeInfo {
pub origination_uuid: Option<String>,
pub target_channel: String,
}
pub(super) fn parse_originate_success(msg: &str) -> Option<String> {
let marker = "Peer UUID: ";
let idx = msg.find(marker)?;
let uuid = msg[idx + marker.len()..].trim();
if uuid.is_empty() {
None
} else {
Some(uuid.to_string())
}
}
pub(super) fn parse_originate_channel(msg: &str) -> Option<&str> {
let start = msg.find(" [")? + 2;
let end = msg[start..].find(']')?;
let chan = &msg[start..start + end];
if chan.is_empty() {
None
} else {
Some(chan)
}
}