use super::kind::{MessageKind, SipInviteDirection};
use super::media::detect_media;
pub(super) fn classify_channel_prefixed(channel_part: &str, rest: &str) -> MessageKind {
if let Some(direction) = sip_invite_direction(rest) {
let profile = extract_sofia_profile(channel_part).unwrap_or_default();
let call_id = extract_call_id(rest);
return MessageKind::SipInvite {
direction,
profile,
call_id,
};
}
if rest.starts_with("SOFIA ") || rest.starts_with("Standard ") || rest.starts_with("RTC ") {
return MessageKind::StateChange {
detail: rest.to_string(),
};
}
if let Some(kind) = detect_media(rest) {
return kind;
}
MessageKind::ChannelLifecycle {
detail: rest.to_string(),
}
}
pub(crate) fn sip_invite_direction(rest: &str) -> Option<SipInviteDirection> {
if rest.starts_with("receiving invite") {
Some(SipInviteDirection::Receiving)
} else if rest.starts_with("sending invite") {
Some(SipInviteDirection::Sending)
} else {
None
}
}
fn extract_sofia_profile(channel_part: &str) -> Option<String> {
let after = channel_part.strip_prefix("sofia/")?;
let end = after.find('/').unwrap_or(after.len());
if end == 0 {
None
} else {
Some(after[..end].to_string())
}
}
pub(crate) fn call_id_token(rest: &str) -> Option<&str> {
let after = rest.split_once("call-id: ")?.1;
let token = after.split_whitespace().next()?;
if token == "(null)" {
None
} else {
Some(token)
}
}
fn extract_call_id(rest: &str) -> Option<String> {
call_id_token(rest).map(str::to_string)
}
pub(super) fn detect_channel_lifecycle(msg: &str) -> Option<MessageKind> {
let lifecycle_prefixes = [
"New Channel ",
"Close Channel ",
"Hangup ",
"Ring-Ready ",
"Ring Ready ",
"Pre-Answer ",
"Sending early media",
"Sending BYE",
"Sending CANCEL",
"Channel is hung up",
"Call appears",
"Found channel",
"3PCC ",
"Subscribed to 3PCC",
"New log started",
"Received a ",
"Session ",
"BRIDGE ",
"Originate ",
"USAGE:",
"Split into",
"Part ",
"Responding to INVITE",
"Redirecting to",
"subscribing to",
"Queue digit delay",
];
for prefix in &lifecycle_prefixes {
if msg.starts_with(prefix) {
return Some(MessageKind::ChannelLifecycle {
detail: msg.to_string(),
});
}
}
if msg.starts_with("Channel ") {
return Some(MessageKind::ChannelLifecycle {
detail: msg.to_string(),
});
}
if msg.starts_with("Application ") && msg.contains("Requires media") {
return Some(MessageKind::ChannelLifecycle {
detail: msg.to_string(),
});
}
None
}