use crate::accounting::Address;
use crate::core::*;
use crate::device::device::{Connector, Device, DeviceStruct};
use crate::utils::*;
use crate::RecordReference;
use bson::DateTime;
use phonenumber::country;
use phonenumber::country::Id;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
#[cfg(feature = "openapi")]
use utoipa::ToSchema;
#[derive(Serialize, Deserialize, Clone, Debug)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct AccountLite {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub name: String,
pub mbn: String,
pub domain: String,
#[serde(default = "crate::shared::build_timestamp")]
pub created: DateTime,
pub organisation: RecordReference,
#[serde(default)]
pub teams: TeamsAccount,
#[serde(default)]
pub environment: Environment,
#[serde(default)]
pub spend_cap: SpendCap,
#[serde(default)]
pub concurrency: Concurrency,
#[serde(default)]
pub class_of_service: ClassOfService,
pub cluster_settings: Cluster,
}
impl AccountLite {
pub fn country_code(&self) -> &str {
self.environment.country_code.as_str()
}
pub fn country_code_parsed(&self) -> Id {
self.environment.country_code_parsed()
}
pub fn clean_str(&self, str: &str) -> String {
clean_str(self.environment.country_code_parsed(), str)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct Account {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub name: String,
pub mbn: String,
pub domain: String,
#[serde(default = "crate::shared::build_timestamp")]
pub created: DateTime,
pub organisation: RecordReference,
#[serde(default)]
pub ddis: Vec<DDI>,
#[serde(default)]
pub trunks: Vec<Trunk>,
#[serde(default)]
#[serde(rename = "callbackURLS")]
pub hooks: Vec<Hook>,
#[serde(default)]
pub devices: Vec<DeviceStruct>,
#[serde(default)]
pub assets: Vec<Asset>,
#[serde(default)]
pub address: Address,
#[serde(default)]
pub addresses: Vec<Address>,
#[serde(default)]
pub teams: TeamsAccount,
#[serde(default)]
pub environment: Environment,
#[serde(default)]
pub spend_cap: SpendCap,
#[serde(default)]
pub concurrency: Concurrency,
#[serde(default)]
pub class_of_service: ClassOfService,
pub cluster_settings: Cluster,
#[serde(default)]
pub api_keys: APIKeys,
}
impl From<Account> for AccountLite {
fn from(account: Account) -> Self {
AccountLite {
id: account.id,
name: account.name,
mbn: account.mbn,
domain: account.domain,
created: account.created,
organisation: account.organisation,
teams: account.teams,
environment: account.environment,
spend_cap: account.spend_cap,
concurrency: account.concurrency,
class_of_service: account.class_of_service,
cluster_settings: account.cluster_settings,
}
}
}
impl From<&Account> for AccountLite {
fn from(account: &Account) -> Self {
AccountLite {
id: account.id.clone(),
name: account.name.clone(),
mbn: account.mbn.clone(),
domain: account.domain.clone(),
created: account.created.clone(),
organisation: account.organisation.clone(),
teams: account.teams.clone(),
environment: account.environment.clone(),
spend_cap: account.spend_cap.clone(),
concurrency: account.concurrency.clone(),
class_of_service: account.class_of_service.clone(),
cluster_settings: account.cluster_settings.clone(),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Cluster {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub name: String,
pub server_a: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct APIKeys {
#[serde(default)]
keys: Vec<APIKey>,
}
impl Default for APIKeys {
fn default() -> Self {
Self { keys: Vec::new() }
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct APIKey {
key: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Environment {
#[serde(default = "build_logger")]
pub logger: LoggerLevel,
#[serde(rename = "dialTimeLimit")]
#[serde(default = "build_call_time")]
pub max_call_time: u16,
#[serde(rename = "dialTimeout")]
#[serde(default = "build_ring_time")]
pub ring_time: u8,
#[serde(default = "build_tts_vendor")]
pub tts_vendor: String,
#[serde(default = "build_tts_language")]
#[serde(rename = "ttsLanguageV2")]
pub tts_language: String,
#[serde(default = "build_tts_voice")]
pub tts_voice: String,
#[serde(default = "build_asr_vendor")]
pub asr_vendor: AsrVendor,
#[serde(default = "build_asr_language")]
pub asr_language: String,
#[serde(default = "build_default_timezone")]
pub time_zone: String,
#[serde(default = "build_country_code")]
pub country_code: String,
#[serde(default = "build_record_retention")]
pub recording_retention: String,
pub ingress_script: Option<String>,
}
impl Environment {
pub fn country_code_parsed(&self) -> Id {
self.country_code.parse().unwrap_or_else(|_| country::GB)
}
}
impl Default for Environment {
fn default() -> Self {
Self {
logger: LoggerLevel::Warn,
max_call_time: DEFAULT_CALL_TIME,
ring_time: DEFAULT_RING_TIME,
tts_vendor: DEFAULT_TTS_VENDOR.to_string(),
tts_language: DEFAULT_TTS_LANGUAGE.to_string(),
tts_voice: DEFAULT_TTS_VOICE.to_string(),
asr_vendor: AsrVendor::Google,
asr_language: DEFAULT_ASR_LANGUAGE.to_string(),
time_zone: DEFAULT_TIMEZONE.to_string(),
country_code: DEFAULT_COUNTRY_CODE.to_string(),
recording_retention: DEFAULT_RECORDING_RETENTION.to_string(),
ingress_script: None,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct SpendCap {
#[serde(default = "build_spend_cap_value")]
value: u16,
#[serde(default = "build_spend_cap_level")]
warn: u8,
#[serde(default = "build_spend_cap_action")]
action: RouteAction,
#[serde(default)]
email_recipients: Vec<String>,
}
impl Default for SpendCap {
fn default() -> Self {
Self {
value: 100,
warn: 80,
action: RouteAction::Warn,
email_recipients: Vec::new(),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Concurrency {
#[serde(rename = "type")]
#[serde(default = "build_license")]
license: Licence,
#[serde(default = "build_concurrency_action")]
action: RouteAction,
#[serde(default)]
email_recipients: Vec<String>,
}
impl Default for Concurrency {
fn default() -> Self {
Concurrency {
license: Licence::Standard,
action: RouteAction::Warn,
email_recipients: vec![],
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ClassOfService {
#[serde(rename = "type")]
#[serde(default = "build_cos_action")]
license: COSAction,
#[serde(default)]
countries: Vec<String>,
#[serde(default)]
prefix_exceptions: String,
#[serde(rename = "maxPPM")]
#[serde(default = "build_cos_ppm")]
max_ppm: f32,
#[serde(rename = "maxPPC")]
#[serde(default = "build_cos_ppc")]
max_ppc: f32,
}
impl Default for ClassOfService {
fn default() -> Self {
Self {
license: COSAction::Allow,
countries: Vec::new(),
prefix_exceptions: String::from(""),
max_ppc: 10.00,
max_ppm: 10.00,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub enum LoggerLevel {
Debug,
Info,
Warn,
Error,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub enum Licence {
Standard,
Professional,
Enterprise,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum COSAction {
#[serde(alias = "DENY")]
#[serde(rename = "deny")]
Deny,
#[serde(alias = "ALLOW")]
#[serde(rename = "allow")]
Allow,
#[serde(alias = "WARN")]
#[serde(rename = "warn")]
Warn,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum RouteAction {
#[serde(rename = "warn")]
Warn,
#[serde(rename = "restrict")]
Restrict,
#[serde(rename = "deny")]
Deny,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct TeamsAccount {
#[serde(rename = "type")]
pub domain_type: TeamsDomainType,
#[serde(default)]
pub domain: String,
pub txt: Option<String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub enum TeamsDomainType {
Callable,
Legacy,
}
impl Default for TeamsAccount {
fn default() -> Self {
Self {
domain_type: TeamsDomainType::Callable,
domain: String::from(""),
txt: None,
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Asset {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub bucket: String,
pub key: String,
pub filename: String,
pub name: String,
pub mime_type: String,
pub size: u32,
#[serde(default = "crate::shared::build_timestamp")]
pub created: DateTime,
#[serde(default)]
pub meta: HashMap<String, String>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Setting {
#[serde(default)]
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub key: String,
#[serde(rename = "type")]
pub setting_type: String,
pub value: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
#[serde(rename_all = "camelCase")]
pub struct DDI {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub name: String,
#[serde(default)]
pub meta: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub classification: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ticket_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub global_id: Option<String>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub ddi_type: Option<String>,
#[serde(default)]
pub features: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dialog_channel: Option<DialogChannel>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dialog_key: Option<DialogKey>,
#[serde(skip_serializing_if = "Option::is_none")]
pub whats_app_account: Option<WhatsAppAccount>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DialogChannel {
#[serde(rename = "_id")]
pub id: String,
pub setup_info: SetupInfo,
pub status: String,
pub account_mode: String,
pub created_at: String,
pub client_id: String,
pub client: DialogClient,
pub waba_account: WabaAccount,
pub integration: Integration,
pub current_limit: Option<String>,
pub current_quality_rating: String,
pub hub_status: String,
pub is_migrated: bool,
pub is_oba: bool,
pub version: i32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SetupInfo {
pub phone_number: String,
pub phone_name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DialogClient {
#[serde(rename = "_id")]
pub id: String,
pub name: String,
pub contact_info: ContactInfo,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ContactInfo {
pub email: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WabaAccount {
#[serde(rename = "_id")]
pub id: String,
pub on_behalf_of_business_info: OnBehalfOfBusinessInfo,
pub fb_account_status: String,
pub external_id: String,
pub fb_business_id: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct OnBehalfOfBusinessInfo {
#[serde(rename = "_id")]
pub id: String,
pub name: String,
#[serde(rename = "type")]
pub business_type: String,
pub status: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Integration {
pub app_id: String,
pub hosting_platform_type: String,
pub enabled: bool,
pub state: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DialogKey {
#[serde(rename = "_id")]
pub id: String,
pub address: String,
pub api_key: String,
pub app_id: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WhatsAppAccount {
pub account: WhatsAppAccountDetails,
pub phone_number: WhatsAppPhoneNumber,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WhatsAppAccountDetails {
#[serde(rename = "_id")]
pub id: String,
pub name: String,
pub timezone_id: String,
pub message_template_namespace: String,
pub on_behalf_of: Option<OnBehalfOf>,
pub phone_numbers: PhoneNumbers,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct OnBehalfOf {
#[serde(rename = "_id")]
pub id: String,
pub name: String,
pub status: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PhoneNumbers {
pub data: Vec<WhatsAppPhoneNumber>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct WhatsAppPhoneNumber {
#[serde(rename = "_id")]
pub id: String,
pub verified_name: String,
pub code_verification_status: String,
pub display_phone_number: String,
pub quality_rating: String,
pub last_onboarded_time: Option<String>,
pub platform_type: String,
pub throughput: Throughput,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Throughput {
pub level: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Trunk {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub ip: String,
#[serde(default = "build_trunk_description")]
pub description: String,
#[serde(deserialize_with = "crate::shared::from_str", default = "build_trunk_port")]
pub port: u16,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Hook {
#[serde(deserialize_with = "crate::shared::object_id_as_string", rename = "_id")]
pub id: String,
pub app: String,
pub url: String,
#[serde(default = "AuthType::default_method")]
pub auth_type: AuthType,
#[serde(default = "HookMethod::default_method")]
pub method: HookMethod,
#[serde(default)]
pub meta: HashMap<String, String>,
#[serde(default)]
pub api_key_name: String,
#[serde(default)]
pub api_key_value: String,
#[serde(default)]
pub api_secret_name: String,
#[serde(default)]
pub api_secret_value: String,
}
#[derive(Serialize, Deserialize, Clone)]
pub enum HookMethod {
#[serde(rename = "POST")]
Post,
#[serde(rename = "GET")]
Get,
}
impl Debug for HookMethod {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
HookMethod::Post => write!(f, "HookMethod::Post"),
HookMethod::Get => write!(f, "HookMethod::Get"),
}
}
}
impl HookMethod {
fn default_method() -> Self {
HookMethod::Post
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum AuthType {
#[serde(rename = "DISABLED")]
Disabled,
#[serde(rename = "KEY")]
Key,
#[serde(rename = "KEY_SECRET")]
KeySecret,
#[serde(rename = "BASIC_AUTH")]
BasicAuth,
#[serde(rename = "OAUTH")]
OAuth,
}
impl AuthType {
fn default_method() -> Self {
AuthType::Disabled
}
}
impl Connector for Device {
fn get_connect_to(&mut self, state: &mut FlowState) -> ConnectState {
match self {
Device::InboundFlow(value) => value.get_connect_to(state),
Device::OutboundFlow(value) => value.get_connect_to(state),
Device::AppFlow(value) => value.get_connect_to(state),
Device::WhatsAppFlow(value) => value.get_connect_to(state),
Device::AniRouter(value) => value.get_connect_to(state),
Device::DnisRouter(value) => value.get_connect_to(state),
Device::DigitRouter(value) => value.get_connect_to(state),
Device::TimeRangeRouter(value) => value.get_connect_to(state),
Device::DayOfWeekRouter(value) => value.get_connect_to(state),
Device::DateRangeRouter(value) => value.get_connect_to(state),
Device::Play(value) => value.get_connect_to(state),
Device::Say(value) => value.get_connect_to(state),
Device::Voicemail(value) => value.get_connect_to(state),
Device::Script(value) => value.get_connect_to(state),
Device::Queue(value) => value.get_connect_to(state),
Device::Sms(value) => value.get_connect_to(state),
Device::Email(value) => value.get_connect_to(state),
Device::Tag(value) => value.get_connect_to(state),
Device::TagRouter(value) => value.get_connect_to(state),
Device::Service(value) => value.get_connect_to(state),
Device::Client(value) => value.get_connect_to(state),
Device::Teams(value) => value.get_connect_to(state),
Device::Remote(value) => value.get_connect_to(state),
Device::HuntGroup(value) => value.get_connect_to(state),
Device::SipGateway(value) => value.get_connect_to(state),
Device::SipExtension(value) => value.get_connect_to(state),
_ => ConnectState::device_error(HANG_UP_CONNECT),
}
}
}
#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub enum AsrVendor {
Deepgram,
Google,
Aws,
Ibm,
Microsoft,
Nuance,
Nvidia,
Soniox,
}
fn build_asr_vendor() -> AsrVendor {
AsrVendor::Google
}
fn build_asr_language() -> String {
String::from(DEFAULT_ASR_LANGUAGE)
}
fn build_tts_vendor() -> String {
String::from(DEFAULT_TTS_VENDOR)
}
fn build_tts_language() -> String {
String::from(DEFAULT_TTS_LANGUAGE)
}
fn build_tts_voice() -> String {
String::from(DEFAULT_TTS_VOICE)
}
fn build_default_timezone() -> String {
String::from(DEFAULT_TIMEZONE)
}
fn build_trunk_description() -> String {
String::from(DEFAULT_TRUNK_DESCRIPTION)
}
fn build_trunk_port() -> u16 {
DEFAULT_TRUNK_PORT
}
fn build_country_code() -> String {
String::from(DEFAULT_COUNTRY_CODE)
}
fn build_logger() -> LoggerLevel {
LoggerLevel::Warn
}
fn build_call_time() -> u16 {
DEFAULT_CALL_TIME
}
fn build_ring_time() -> u8 {
DEFAULT_RING_TIME
}
fn build_spend_cap_value() -> u16 {
100
}
fn build_spend_cap_level() -> u8 {
80
}
fn build_spend_cap_action() -> RouteAction {
RouteAction::Warn
}
fn build_concurrency_action() -> RouteAction {
RouteAction::Warn
}
fn build_cos_action() -> COSAction {
COSAction::Allow
}
fn build_cos_ppm() -> f32 {
15.00
}
fn build_cos_ppc() -> f32 {
15.00
}
fn build_license() -> Licence {
Licence::Standard
}
fn build_record_retention() -> String {
String::from(DEFAULT_RECORDING_RETENTION)
}