-
Notifications
You must be signed in to change notification settings - Fork 8
/
handler.go
138 lines (128 loc) · 3.66 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package main
import (
"fmt"
"log"
"net/http"
"github.com/BTBurke/twiml"
)
// CallRequest will return XML to connect to the forwarding number
func CallRequest(cfg Config) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var cr twiml.VoiceRequest
if err := twiml.Bind(&cr, r); err != nil {
http.Error(w, http.StatusText(400), 400)
return
}
res := twiml.NewResponse()
switch status := cr.CallStatus; status {
case twiml.InProgress:
w.WriteHeader(200)
return
case twiml.Ringing, twiml.Queued:
d := twiml.Dial{
Number: cfg.ForwardingNumber,
Action: "action/",
Timeout: 15,
CallerID: cr.To,
}
res.Add(&d)
b, err := res.Encode()
if err != nil {
http.Error(w, http.StatusText(502), 502)
return
}
if _, err := w.Write(b); err != nil {
http.Error(w, http.StatusText(502), 502)
return
}
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(200)
return
default:
res.Add(&twiml.Hangup{})
b, err := res.Encode()
if err != nil {
http.Error(w, http.StatusText(502), 502)
return
}
if _, err := w.Write(b); err != nil {
http.Error(w, http.StatusText(502), 502)
return
}
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(200)
return
}
}
}
// DialAction will forward to voicemail if the call is not connected
func DialAction(cfg Config) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var ca twiml.DialActionRequest
if err := twiml.Bind(&ca, r); err != nil {
log.Printf("%v", err)
http.Error(w, http.StatusText(400), 400)
return
}
res := twiml.NewResponse()
switch status := ca.DialCallStatus; status {
case twiml.NoAnswer, twiml.Failed, twiml.Busy:
if cfg.EnableCustomPrompt {
p := twiml.Play{URL: fmt.Sprintf("/prompt/%s", cfg.VoiceFileName)}
res.Add(&p)
} else {
s := twiml.Say{
Voice: "woman",
Text: cfg.VoicemailScript,
}
res.Add(&s)
}
rec := twiml.Record{
Transcribe: true,
TranscribeCallback: "/voicemail",
MaxLength: 30,
}
res.Add(&rec)
b, err := res.Encode()
if err != nil {
http.Error(w, http.StatusText(502), 502)
return
}
if _, err := w.Write(b); err != nil {
http.Error(w, http.StatusText(502), 502)
return
}
w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(200)
return
default:
w.WriteHeader(200)
return
}
}
}
// Voicemail handles the TranscriptionCallback which lets you know that transcription is done and the
// voicemail is available. If Mailgun is set, it will email a copy of the transcription text and
// a link to the voicemail to your email address
func Voicemail(cfg Config) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var tcb twiml.TranscribeCallbackRequest
if err := twiml.Bind(&tcb, r); err != nil {
log.Printf("%v", err)
http.Error(w, http.StatusText(400), 400)
return
}
log.Printf("Call from: %s\n\nTranscription follows:\n%s\n\nVoicemail Link: %s\n", tcb.From, tcb.TranscriptionText, tcb.RecordingURL)
if err := Send(cfg, tcb); err != nil {
log.Printf("Unable to send notification email due to error: %s\n\nVoicemail available at: %s", err, tcb.RecordingURL)
}
w.WriteHeader(200)
}
}
// Status receives in-progress status events. It is outside the mail control loop. In this case,
// acknowledging the status to continue the call is the right thing to do.
func Status(cfg Config) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
}
}