esl.domain.FSMessage.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2017 Call Handling Services Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package esl.domain
import esl.domain.HeaderNames.Conference
import esl.util._
import scala.language.postfixOps
trait FSMessage extends FSBridgeCommand {
val headers: Map[String, String]
val body: Option[String]
val contentType: String
val contentLength: Int
}
case class NoneMessage() extends FSMessage {
override val body: Option[String] = None
override val headers: Map[String, String] = Map[String, String]()
override val contentLength: Int = 0
override val contentType: String = "none"
}
case class BasicMessage(headers: Map[String, String], body: Option[String])
extends FSMessage {
lazy val contentType: String =
headers.lift(HeaderNames.contentType).fold("")(identity)
lazy val contentLength: Int =
headers.lift(HeaderNames.contentLength).fold(0)(_.toInt)
//ToDo: Implement toString
}
case class CommandReply(basicMessage: BasicMessage) extends FSMessage {
require(
basicMessage.contentType == ContentTypes.commandReply,
s"Expected content type command/reply, got ${basicMessage.contentType} instead."
)
override val headers: Map[String, String] = basicMessage.headers
override val body: Option[String] = basicMessage.body
override val contentLength: Int = basicMessage.contentLength
override val contentType: String = basicMessage.contentType
lazy val replyText = headers.lift(HeaderNames.replyText)
//lazy val success: Boolean = replyText.exists(f => f.charAt(0) == '+' || f == "%2BOK%0A")
lazy val success: Boolean = replyText.fold(false)(rplyTxt =>
rplyTxt.startsWith("+OK") || rplyTxt.startsWith("%2BOK%0A")
)
lazy val errorMessage: String = replyText
.collect {
case text if text.startsWith("-ERR") => text.substring(5, text.length - 5)
}
.getOrElse("")
lazy val eventName: Option[String] =
headers.get(esl.domain.HeaderNames.eventName)
}
case class ApiResponse(basicMessage: BasicMessage) extends FSMessage {
val success: Boolean = basicMessage.body.isDefined
val errorMessage: Option[String] = basicMessage.body.collect {
case bodyOp if bodyOp.startsWith("-ERR") =>
bodyOp.substring(5, bodyOp.length - 5)
}
override val body: Option[String] = basicMessage.body
override val contentLength: Int = basicMessage.contentLength
override val contentType: String = basicMessage.contentType
override val headers: Map[String, String] = basicMessage.headers
}
case class EventMessage(basicMessage: BasicMessage) extends FSMessage {
private val isCommandReply: Boolean =
basicMessage.contentType == ContentTypes.commandReply &&
basicMessage.headers.contains(HeaderNames.eventName)
private val delimiterIndex: Int =
basicMessage.body.fold(-1)(_.indexOf("\n\n"))
private val hasBody: Boolean = basicMessage.body match {
case Some(bdy)
if basicMessage.headers
.getOrElse(HeaderNames.contentLength, "-1")
.toInt > -1 =>
!(delimiterIndex == -1 || delimiterIndex == bdy.length - 2)
case _ => false
}
override val headers: Map[String, String] = {
if (isCommandReply) basicMessage.headers
else
basicMessage.body.fold(basicMessage.headers) { b =>
if (hasBody)
basicMessage.headers ++ StringHelpers.parseKeyValuePairs(
b substring (0, delimiterIndex),
':'
)
else basicMessage.headers ++ StringHelpers.parseKeyValuePairs(b, ':')
}
}
override val contentLength: Int =
headers.get(HeaderNames.contentLength).fold(-1)(_.toInt)
override val body: Option[String] = {
if (isCommandReply) basicMessage.body
else
basicMessage.body.flatMap { bdy =>
if (hasBody) Some(bdy.substring(delimiterIndex + 2, bdy.length))
else None
}
}
override val contentType: String = basicMessage.contentType
lazy val callDirection: Option[String] = getHeader(HeaderNames.CallDirection)
val uuid: Option[String] = headers.get(HeaderNames.uniqueId)
val otherLegUUID: Option[String] = headers.get(HeaderNames.otherLegUniqueId)
val channelCallUUID: Option[String] =
headers.get(HeaderNames.channelCallUniqueId)
val eventName: Option[EventNames.EventName] =
headers
.get(HeaderNames.eventName)
.fold(Option.empty[EventNames.EventName])(EventNames.events.lift)
val channelState: Option[ChannelStates.ChannelState] =
headers
.get(HeaderNames.channelState)
.fold(Option.empty[ChannelStates.ChannelState])(ChannelStates.states.lift)
lazy val channelCallState: Option[AnswerStates.AnswerState] =
channelCallStateRaw
.fold(Option.empty[AnswerStates.AnswerState])(AnswerStates.states.lift)
lazy val channelCallStateRaw = headers
.get(HeaderNames.channelCallState)
val answerState: Option[AnswerStates.AnswerState] =
headers
.get(HeaderNames.answerState)
.fold(Option.empty[AnswerStates.AnswerState])(AnswerStates.states.lift)
lazy val answerStateRaw: Option[String] = headers.get(HeaderNames.answerState)
val hangupCause: Option[HangupCauses.HangupCause] =
headers
.get(HeaderNames.hangupCause)
.fold(Option.empty[HangupCauses.HangupCause])(HangupCauses.causes.lift)
val applicationUuid: Option[String] = headers
.get(HeaderNames.applicationUuid)
.flatMap({
case x if x.trim.isEmpty => None
case x => Some(x.trim)
})
val applicationName: Option[String] = headers.get(HeaderNames.application).flatMap({
case x if x.trim.isEmpty => None
case x => Some(x.trim)
})
lazy val jobUuid: Option[String] = headers.get(HeaderNames.jobUUID)
lazy val jobCommand: Option[String] = headers.get(HeaderNames.jobCommand)
lazy val jobCommandArg: Option[String] =
headers.get(HeaderNames.jobCommandArg)
val callerUniqueId: Option[String] = headers.get(HeaderNames.callerUniqueId)
val channelCallUniqueId: Option[String] = headers.get(HeaderNames.channelCallUniqueId)
val originalChannelCallState: Option[AnswerStates.AnswerState] =
headers
.get(HeaderNames.originalChannelCallState)
.fold(Option.empty[AnswerStates.AnswerState])(AnswerStates.states.lift)
val apiCommand: Option[String] = headers.get(HeaderNames.apiCommand)
lazy val action: Option[String] = headers.get(Conference.action)
lazy val conferenceName: Option[String] = headers.get(Conference.name)
def getHeader(header: String): Option[String] = headers.get(header)
def getVariable(variable: String): Option[String] =
getHeader(s"variable_$variable")
lazy val eavesdropTarget: Option[String] =
headers.get(HeaderNames.eavesdropTarget)
//ToDO implement toString for debugging
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy