use super::convert;
use crate::engine::assertion::Assertion as EngineAssertion;
use crate::engine::ctx::{CallState, Ctx, mark_pending_label};
use crate::engine::http::HttpResponse as EngineHttp;
use crate::engine::sip_user_part;
use rhai::{Dynamic, EvalAltResult};
use std::sync::Arc;
#[derive(Clone)]
pub(super) struct Agent {
pub(super) name: String,
pub(super) ctx: Arc<Ctx>,
}
type Verb<T> = Result<T, Box<EvalAltResult>>;
impl Agent {
pub(super) fn registered(&mut self) -> Verb<bool> {
self.ctx.registered(&self.name).map_err(|e| e.into())
}
pub(super) fn call_state(&mut self) -> Verb<CallState> {
self.ctx.call_state(&self.name).map_err(|e| e.into())
}
pub(super) fn reason(&mut self) -> Verb<Dynamic> {
self.ctx
.reason(&self.name)
.map(convert::opt_to_dynamic)
.map_err(|e| e.into())
}
pub(super) fn status_code(&mut self) -> Verb<Dynamic> {
self.ctx
.status_code(&self.name)
.map(|c| match c {
Some(code) => (code as i64).into(),
None => Dynamic::UNIT,
})
.map_err(|e| e.into())
}
pub(super) fn header(&mut self, name: &str) -> Verb<Dynamic> {
self.ctx
.header(&self.name, name)
.map(convert::opt_to_dynamic)
.map_err(|e| e.into())
}
pub(super) fn peer(&mut self) -> Verb<Peer> {
let (uri, name) = match self
.ctx
.peer(&self.name)
.map_err(|e| -> Box<EvalAltResult> { e.into() })?
{
Some((uri, name)) => (Some(uri), name),
None => (None, None),
};
Ok(Peer {
agent: self.name.clone(),
uri,
name,
})
}
pub(super) fn headers(&mut self) -> Verb<Dynamic> {
self.ctx
.headers(&self.name)
.map(convert::headers_to_map)
.map_err(|e| e.into())
}
pub(super) fn info(&mut self) -> Verb<Dynamic> {
self.ctx
.info(&self.name)
.map(|i| convert::info_to_map(&i))
.map_err(|e| e.into())
}
#[allow(clippy::wrong_self_convention)]
pub(super) fn to_json(&mut self) -> Verb<String> {
let i = self
.ctx
.info(&self.name)
.map_err(|e| -> Box<EvalAltResult> { e.into() })?;
let peer = i.peer.as_ref().map(|(uri, name)| {
serde_json::json!({
"uri": uri,
"number": crate::engine::sip_user_part(uri),
"name": name,
})
});
let v = serde_json::json!({
"name": i.name,
"aor": i.aor,
"registered": i.registered,
"state": i.state.to_string(),
"reason": i.reason,
"status_code": i.status_code,
"peer": peer,
"calls": i.calls,
});
serde_json::to_string(&v).map_err(|e| e.to_string().into())
}
pub(super) fn register(&mut self) -> Verb<()> {
self.ctx.register(&self.name).map_err(|e| e.into())
}
pub(super) fn accept(&mut self) -> Verb<()> {
self.ctx.accept(&self.name).map_err(|e| e.into())
}
pub(super) fn hangup(&mut self) -> Verb<()> {
self.ctx.hangup(&self.name).map_err(|e| e.into())
}
pub(super) fn hold(&mut self) -> Verb<()> {
self.ctx.hold(&self.name).map_err(|e| e.into())
}
pub(super) fn resume(&mut self) -> Verb<()> {
self.ctx.resume(&self.name).map_err(|e| e.into())
}
pub(super) fn mute(&mut self) -> Verb<()> {
self.ctx.mute(&self.name).map_err(|e| e.into())
}
pub(super) fn dtmf(&mut self, digits: &str) -> Verb<()> {
self.ctx
.dtmf(&self.name, digits, std::time::Duration::ZERO)
.map_err(|e| e.into())
}
pub(super) fn dtmf_spaced(&mut self, digits: &str, gap: &str) -> Verb<()> {
let gap = crate::engine::duration::parse_duration(gap)?;
self.ctx.dtmf(&self.name, digits, gap).map_err(|e| e.into())
}
pub(super) fn dial_agent(&mut self, target: Agent) -> Verb<()> {
self.ctx
.dial_agent(&self.name, &target.name)
.map_err(|e| e.into())
}
pub(super) fn dial_uri(&mut self, target: &str) -> Verb<()> {
self.ctx.dial_uri(&self.name, target).map_err(|e| e.into())
}
pub(super) fn transfer_agent(&mut self, target: Agent) -> Verb<()> {
self.ctx
.transfer_agent(&self.name, &target.name)
.map_err(|e| e.into())
}
pub(super) fn transfer_uri(&mut self, target: &str) -> Verb<()> {
self.ctx
.transfer_uri(&self.name, target)
.map_err(|e| e.into())
}
pub(super) fn attended_transfer_agent(&mut self, target: Agent) -> Verb<()> {
self.ctx
.attended_transfer_agent(&self.name, &target.name)
.map_err(|e| e.into())
}
pub(super) fn attended_transfer_uri(&mut self, target: &str) -> Verb<()> {
self.ctx
.attended_transfer_uri(&self.name, target)
.map_err(|e| e.into())
}
pub(super) fn complete_transfer(&mut self) -> Verb<()> {
self.ctx.complete_transfer(&self.name).map_err(|e| e.into())
}
pub(super) fn abort_transfer(&mut self) -> Verb<()> {
self.ctx.abort_transfer(&self.name).map_err(|e| e.into())
}
}
#[derive(Clone)]
pub(super) struct Peer {
agent: String,
uri: Option<String>,
name: Option<String>,
}
impl Peer {
pub(super) fn uri(&mut self) -> Dynamic {
mark_pending_label(format!("{} peer uri", self.agent));
convert::opt_to_dynamic(self.uri.clone())
}
pub(super) fn number(&mut self) -> Dynamic {
mark_pending_label(format!("{} peer number", self.agent));
convert::opt_to_dynamic(self.uri.as_deref().map(sip_user_part))
}
pub(super) fn name(&mut self) -> Dynamic {
mark_pending_label(format!("{} peer name", self.agent));
convert::opt_to_dynamic(self.name.clone())
}
pub(super) fn display(&mut self) -> String {
self.uri.clone().unwrap_or_default()
}
}
#[derive(Clone)]
pub(super) struct Assertion {
inner: EngineAssertion,
}
type Check = Result<Assertion, Box<EvalAltResult>>;
impl Assertion {
pub(super) fn new(ctx: Arc<Ctx>, actual: Dynamic) -> Self {
Self {
inner: EngineAssertion::new(ctx, convert::to_value(&actual)),
}
}
fn chain(&self, r: Result<(), String>) -> Check {
r.map(|_| self.clone()).map_err(|e| e.into())
}
pub(super) fn describe(&mut self, label: &str) -> Assertion {
self.inner.describe(label);
self.clone()
}
pub(super) fn value(&mut self) -> Dynamic {
convert::to_dynamic(self.inner.value())
}
pub(super) fn equals(&mut self, expected: Dynamic) -> Check {
self.chain(self.inner.equals(&convert::to_value(&expected)))
}
pub(super) fn not_equals(&mut self, expected: Dynamic) -> Check {
self.chain(self.inner.not_equals(&convert::to_value(&expected)))
}
pub(super) fn is_true(&mut self) -> Check {
self.chain(self.inner.is_true())
}
pub(super) fn is_false(&mut self) -> Check {
self.chain(self.inner.is_false())
}
pub(super) fn is_present(&mut self) -> Check {
self.chain(self.inner.is_present())
}
pub(super) fn is_empty(&mut self) -> Check {
self.chain(self.inner.is_empty())
}
pub(super) fn is_not_empty(&mut self) -> Check {
self.chain(self.inner.is_not_empty())
}
pub(super) fn is_absent(&mut self) -> Check {
self.chain(self.inner.is_absent())
}
pub(super) fn contains(&mut self, needle: &str) -> Check {
self.chain(self.inner.contains(needle))
}
pub(super) fn matches(&mut self, pattern: &str) -> Check {
self.chain(self.inner.matches(pattern))
}
pub(super) fn greater_than(&mut self, n: i64) -> Check {
self.chain(self.inner.greater_than(n))
}
pub(super) fn at_least(&mut self, n: i64) -> Check {
self.chain(self.inner.at_least(n))
}
pub(super) fn less_than(&mut self, n: i64) -> Check {
self.chain(self.inner.less_than(n))
}
pub(super) fn at_most(&mut self, n: i64) -> Check {
self.chain(self.inner.at_most(n))
}
}
#[derive(Clone)]
pub(super) struct HttpResponse {
pub(super) inner: EngineHttp,
}
impl HttpResponse {
pub(super) fn status(&mut self) -> i64 {
self.inner.status()
}
pub(super) fn body(&mut self) -> String {
self.inner.body()
}
pub(super) fn header(&mut self, name: &str) -> Dynamic {
convert::opt_to_dynamic(self.inner.header(name))
}
pub(super) fn json(&mut self, path: &str) -> Result<Dynamic, Box<EvalAltResult>> {
self.inner
.json(path)
.map(|v| convert::json_to_dynamic(&v))
.map_err(|e| e.into())
}
pub(super) fn json_all(&mut self) -> Result<Dynamic, Box<EvalAltResult>> {
self.inner
.json("")
.map(|v| convert::json_to_dynamic(&v))
.map_err(|e| e.into())
}
pub(super) fn expect_status(&mut self, code: i64) -> Result<(), Box<EvalAltResult>> {
self.inner.expect_status(code).map_err(|e| e.into())
}
}