module Text.XML.Twiml.Internal.Twiml
(
MessagingTwiml(..)
, MessagingVerbsF(..)
, VoiceTwiml(..)
, VoiceVerbsF(..)
, Base
, IsTwimlLike
, TwimlLike
, TwimlLike'
, response
, DialNoun(..)
, DialNounF(..)
, Client
, ClientF(..)
, ClientAttributes(..)
, Conference
, ConferenceF(..)
, ConferenceAttributes(..)
, Number
, NumberF(..)
, NumberAttributes(..)
, Queue
, QueueF(..)
, QueueAttributes(..)
, Sip
, SipF(..)
, SipAttributes(..)
, Dial
, DialF(..)
, DialAttributes(..)
, End
, EndF(..)
, Enqueue
, EnqueueF(..)
, EnqueueAttributes(..)
, Gather
, GatherF(..)
, GatherAttributes(..)
, Nest
, In
, Hangup
, HangupF(..)
, Leave
, LeaveF(..)
, Message
, MessageF(..)
, MessageAttributes(..)
, Pause
, PauseF(..)
, PauseAttributes(..)
, Play
, PlayF(..)
, PlayAttributes(..)
, Record
, RecordF(..)
, RecordAttributes(..)
, Redirect
, RedirectF(..)
, RedirectAttributes(..)
, Reject
, RejectF(..)
, RejectAttributes(..)
, Say
, SayF(..)
, SayAttributes(..)
, Sms
, SmsF(..)
, SmsAttributes(..)
) where
import Control.Monad
import Control.DeepSeq
import Data.Data
import Data.Default
import Data.Void
import GHC.Generics (Generic)
import Text.XML.Light
import Text.XML.Twiml.Internal
import Text.XML.Twiml.Internal.TH
import Text.XML.Twiml.Types
twimlSpecStringToData [s|
Client
required
String
attributes
url, URL
method, Method
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Conference
required
String
attributes
muted, Bool
beep, Bool
startOnEnter, Bool, startConferenceOnEnter
endOnExit, Bool, endConferenceOnExit
waitURL, URL
waitMethod, Method
maxParticipants, Natural
toXMLForGADT
toAttrsForAttributes
|]
type Digits = [Digit]
twimlSpecStringToData [s|
Number
required
String
attributes
sendDigits, Digits
url, URL
method, Method
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Queue
required
String
attributes
url, URL
method, Method
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Sip
required
URL
attributes
username, String
password, String
transport, Transport
headers, String
url, URL
method, Method
toXMLForGADT
toAttrsForAttributes
|]
data DialNoun = forall i. DialNoun (IxFree DialNounF i Void)
instance ToSomeNode DialNoun where
toSomeNode (DialNoun dialNoun) = SomeNode $ toXML dialNoun
instance ToSomeNode EitherDialNounString where
toSomeNode = either toSomeNode toSomeNode
instance ToXML DialNoun where
toXML (DialNoun dialNoun) = toXML dialNoun
instance Show DialNoun where
show = showDialNoun
showDialNoun :: DialNoun -> String
showDialNoun = concatMap ppElement . toXML
newtype DialNounF i a = DialNounF
{ getDialNounF ::
( ClientF i :+:
ConferenceF i :+:
NumberF i :+:
QueueF i :+:
SipF i ) a
} deriving (Functor, Generic, Show, Typeable)
instance (f i :<: ( ClientF i :+:
ConferenceF i :+:
NumberF i :+:
QueueF i :+:
SipF i )
) => f i :<: DialNounF i where
inj = DialNounF . inj
prj = prj . getDialNounF
instance Functor1 DialNounF where
fmap1 = fmap
instance Show1 DialNounF where
show1 = show
instance ToXML a => ToXML (DialNounF i a) where
toXML = toXML . getDialNounF
instance ToXML (IxFree DialNounF i Void) where
toXML (IxFree f) = toXML f
toXML _ = error "Impossible"
type EitherDialNounString = Either DialNoun String
twimlSpecStringToData [s|
Dial
required
EitherDialNounString
attributes
action, URL
method, Method
timeout, Natural
hangupOnStar, Bool
timeLimit, Natural
callerId, String
record', Bool, record
recursive
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
End
|]
instance ToXML (EndF i a) where
toXML EndF = []
twimlSpecStringToData [s|
Enqueue
required
String
attributes
action, URL
method, Method
waitURL, URL, waitUrl
waitMethod, Method, waitUrlMethod
recursive
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Hangup
toXMLForGADT
|]
twimlSpecStringToData [s|
Leave
toXMLForGADT
|]
twimlSpecStringToData [s|
Message
required
String
attributes
to, String
from, String
action, URL
method, Method
statusCallback, URL
recursive
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Pause
attributes
duration, Natural, length
recursive
toXMLForGADT
toAttrsForAttributes
|]
type MaybeURL = Maybe URL
twimlSpecStringToData [s|
Play
required
MaybeURL
attributes
loop, Natural
digits, Digits
recursive
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Record
attributes
action, URL
method, Method
timeout, Natural
finishOnKey, Key
maxLength, Natural
transcribe, Bool
transcribeCallback, URL
playBeep, Bool
recursive
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Redirect
required
URL
attributes
method, Method
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Reject
attributes
reason, Reason
toXMLForGADT
toAttrsForAttributes
|]
twimlSpecStringToData [s|
Say
required
String
attributes
voice, Voice
loop, Natural
recursive
toXMLForGADT
|]
lang :: Voice -> Maybe (Either Lang LangAlice)
lang (Man l) = Left <$> l
lang (Woman l) = Left <$> l
lang (Alice r) = Right <$> r
instance ToAttrs SayAttributes where
toAttrs = flip makeAttrs
[ makeAttr "voice" _sayVoice
, makeAttr "loop" _sayLoop
, makeAttr' "language" (_sayVoice >=> lang) (either toAttrValue toAttrValue)
]
twimlSpecStringToData [s|
Sms
required
String
attributes
to, String
from, String
action, URL
method, Method
statusCallback, URL
recursive
toXMLForGADT
toAttrsForAttributes
|]
data Gather
data In
type family Nest a i b where
Nest i In Gather =
( Record ∉ i
, Gather ∉ i
, Sms ∉ i
, Dial ∉ i
, Enqueue ∉ i
, Leave ∉ i
, Hangup ∉ i
, Redirect ∉ i
, Reject ∉ i
)
data GatherF i a where
GatherF :: Nest i In Gather
=> GatherAttributes
-> IxFree VoiceVerbsF i Void
-> a
-> GatherF '[Gather] a
deriving instance Functor (GatherF i)
instance Functor1 GatherF where
fmap1 = fmap
deriving instance Show a => Show (GatherF i a)
instance ToXML a => ToXML (GatherF i a) where
toXML (GatherF attrs a b) = makeElement "Gather" (toXML a) (toAttrs attrs) : toXML b
data GatherAttributes = GatherAttributes
{ _gatherAction :: Maybe URL
, _gatherMethod :: Maybe Method
, _gatherTimeout :: Maybe Natural
, _gatherFinishOnKey :: Maybe Key
, _gatherNumDigits :: Maybe Natural
} deriving (Data, Eq, Generic, NFData, Ord, Read, Show, Typeable)
instance Default GatherAttributes where
def = GatherAttributes
{ _gatherAction = def
, _gatherMethod = def
, _gatherTimeout = def
, _gatherFinishOnKey = def
, _gatherNumDigits = def
}
instance ToAttrs GatherAttributes where
toAttrs = flip makeAttrs
[ makeAttr "action" _gatherAction
, makeAttr "method" _gatherMethod
, makeAttr "timeout" _gatherTimeout
, makeAttr "finishOnKey" _gatherFinishOnKey
, makeAttr "numDigits" _gatherNumDigits
]
data VoiceTwiml = forall i. VoiceTwiml (IxFree VoiceVerbsF i Void)
instance ToElement VoiceTwiml where
toElement (VoiceTwiml twiml) = unode "Response" $ toXML twiml
instance Show VoiceTwiml where
show = showTwiml
showTwiml :: VoiceTwiml -> String
showTwiml twiml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++ ppElement (toElement twiml) ++ "\n"
newtype VoiceVerbsF i a = VoiceVerbsF
{ getVoiceVerbsF ::
( SayF i :+:
PlayF i :+:
GatherF i :+:
SmsF i :+:
DialF i :+:
EnqueueF i :+:
LeaveF i :+:
HangupF i :+:
RecordF i :+:
RedirectF i :+:
RejectF i :+:
PauseF i :+:
EndF i ) a
} deriving (Functor, Generic, Show, Typeable)
instance (f i :<: ( SayF i :+:
PlayF i :+:
GatherF i :+:
SmsF i :+:
DialF i :+:
EnqueueF i :+:
LeaveF i :+:
HangupF i :+:
RecordF i :+:
RedirectF i :+:
RejectF i :+:
PauseF i :+:
EndF i )
) => f i :<: VoiceVerbsF i where
inj = VoiceVerbsF . inj
prj = prj . getVoiceVerbsF
instance Functor1 VoiceVerbsF where
fmap1 = fmap
instance Show1 VoiceVerbsF where
show1 = show
instance ToXML a => ToXML (VoiceVerbsF i a) where
toXML = toXML . getVoiceVerbsF
instance ToXML (IxFree VoiceVerbsF i Void) where
toXML (IxFree f) = toXML f
toXML _ = error "Impossible"
data MessagingTwiml = forall i. MessagingTwiml (IxFree MessagingVerbsF i Void)
instance ToElement MessagingTwiml where
toElement (MessagingTwiml twiml) = unode "Response" $ toXML twiml
instance Show MessagingTwiml where
show = showMessagingTwiml
showMessagingTwiml :: MessagingTwiml -> String
showMessagingTwiml twiml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++ ppElement (toElement twiml) ++ "\n"
newtype MessagingVerbsF i a = MessagingVerbsF
{ getMessagingVerbsF ::
( MessageF i :+:
RedirectF i :+:
SmsF i :+:
EndF i ) a
} deriving (Functor, Generic, Show, Typeable)
instance (f i :<: ( MessageF i :+:
RedirectF i :+:
SmsF i :+:
EndF i )
) => f i :<: MessagingVerbsF i where
inj = MessagingVerbsF . inj
prj = prj . getMessagingVerbsF
instance Functor1 MessagingVerbsF where
fmap1 = fmap
instance Show1 MessagingVerbsF where
show1 = show
instance ToXML a => ToXML (MessagingVerbsF i a) where
toXML = toXML . getMessagingVerbsF
instance ToXML (IxFree MessagingVerbsF i Void) where
toXML (IxFree f) = toXML f
toXML _ = error "Impossible"
type family Base d where
Base Dial = DialF
Base End = EndF
Base Enqueue = EnqueueF
Base Gather = GatherF
Base Hangup = HangupF
Base Leave = LeaveF
Base Message = MessageF
Base Pause = PauseF
Base Play = PlayF
Base Record = RecordF
Base Redirect = RedirectF
Base Reject = RejectF
Base Say = SayF
Base Sms = SmsF
Base Client = ClientF
Base Conference = ConferenceF
Base Number = NumberF
Base Queue = QueueF
Base Sip = SipF
type IsTwimlLike f i = (Functor1 f, (Base i) '[i] :<: f '[i])
type TwimlLike f i = TwimlLike' f '[i]
type TwimlLike' f = IxFree f
response :: IxFree VoiceVerbsF i Void -> VoiceTwiml
response = VoiceTwiml