diff --git a/api/debug.go b/api/debug.go index a664d622..00522a1e 100644 --- a/api/debug.go +++ b/api/debug.go @@ -1,4 +1,5 @@ package api + import ( "os" @@ -8,7 +9,9 @@ import ( func debugSaveRequest(body []byte, err error, message string) { // TODO(eliribble): avoid using a single static filename and instead securely generate // this value - log.Error().Err(err).Msg(message) + if err != nil { + log.Error().Err(err).Msg(message) + } output, err := os.OpenFile("/tmp/request.body", os.O_RDWR|os.O_CREATE, 0666) if err != nil { log.Info().Msg("Failed to open temp request.bady") diff --git a/api/routes.go b/api/routes.go index 8db2879b..dba03ec4 100644 --- a/api/routes.go +++ b/api/routes.go @@ -23,9 +23,11 @@ func AddRoutes(r chi.Router) { r.Get("/district", apiGetDistrict) r.Get("/district/{slug}/logo", apiGetDistrictLogo) r.Post("/signin", postSignin) + r.Post("/twilio/call", twilioCallPost) + r.Post("/twilio/call/status", twilioCallStatusPost) r.Post("/twilio/message", twilioMessagePost) - r.Post("/twilio/status", twilioStatusPost) r.Post("/twilio/text", twilioTextPost) + r.Post("/twilio/text/status", twilioTextStatusPost) r.Get("/webhook/fieldseeker", webhookFieldseeker) r.Post("/webhook/fieldseeker", webhookFieldseeker) } diff --git a/api/twilio.go b/api/twilio.go index ef1d205c..b823d312 100644 --- a/api/twilio.go +++ b/api/twilio.go @@ -2,8 +2,10 @@ package api import ( "fmt" + "io/ioutil" "net/http" + "github.com/Gleipnir-Technology/nidus-sync/config" "github.com/Gleipnir-Technology/nidus-sync/platform/text" "github.com/rs/zerolog/log" "github.com/twilio/twilio-go/twiml" @@ -14,11 +16,31 @@ func twilioMessagePost(w http.ResponseWriter, r *http.Request) { log.Info().Str("sid", message_sid).Msg("Twilio Message POST") fmt.Fprintf(w, "") } -func twilioStatusPost(w http.ResponseWriter, r *http.Request) { - message_sid := r.PostFormValue("MessageSid") - message_status := r.PostFormValue("MessageStatus") - log.Info().Str("sid", message_sid).Str("status", message_status).Msg("Updated message status") - text.UpdateMessageStatus(message_sid, message_status) +func twilioCallPost(w http.ResponseWriter, r *http.Request) { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Error().Err(err).Msg("failed to read request body") + } + debugSaveRequest(body, nil, "just want a look") + say := &twiml.VoiceSay{ + Message: "Thanks for calling Report Mosquitoes Online. I'll forward you to our tech support lead, Eli", + } + call := &twiml.VoiceDial{ + Number: config.PhoneNumberSupportStr, + } + twimlResult, err := twiml.Voice([]twiml.Element{say, call}) + if err != nil { + log.Error().Err(err).Msg("Failed to produce TWIML") + http.Error(w, err.Error(), http.StatusInternalServerError) + } + w.Header().Set("Content-Type", "text/xml") + fmt.Fprintf(w, "%s", twimlResult) +} + +func twilioCallStatusPost(w http.ResponseWriter, r *http.Request) { + log.Info().Msg("Call status POST") + //message_sid := r.PostFormValue("MessageSid") + //message_status := r.PostFormValue("MessageStatus") fmt.Fprintf(w, "") } func twilioTextPost(w http.ResponseWriter, r *http.Request) { @@ -47,3 +69,10 @@ func twilioTextPost(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/xml") fmt.Fprintf(w, "%s", twiml) } +func twilioTextStatusPost(w http.ResponseWriter, r *http.Request) { + message_sid := r.PostFormValue("MessageSid") + message_status := r.PostFormValue("MessageStatus") + log.Info().Str("sid", message_sid).Str("status", message_status).Msg("Updated message status") + text.UpdateMessageStatus(message_sid, message_status) + fmt.Fprintf(w, "") +} diff --git a/config/config.go b/config/config.go index e74734de..a0342663 100644 --- a/config/config.go +++ b/config/config.go @@ -28,6 +28,8 @@ var ( PGDSN string PhoneNumberReport phonenumbers.PhoneNumber PhoneNumberReportStr string + PhoneNumberSupport phonenumbers.PhoneNumber + PhoneNumberSupportStr string SentryDSN string TwilioAuthToken string TwilioAccountSID string @@ -130,9 +132,9 @@ func Parse() (err error) { if PGDSN == "" { return fmt.Errorf("You must specify a non-empty POSTGRES_DSN") } - PhoneNumberReportStr = os.Getenv("RMO_PHONE_NUMBER") + PhoneNumberReportStr = os.Getenv("PHONE_NUMBER_RMO") if PhoneNumberReportStr == "" { - return fmt.Errorf("You must specify a non-empty RMO_PHONE_NUMBER") + return fmt.Errorf("You must specify a non-empty PHONE_NUMBER_RMO") } p, err := phonenumbers.Parse(PhoneNumberReportStr, "US") if err != nil { @@ -140,6 +142,16 @@ func Parse() (err error) { } PhoneNumberReport = *p + PhoneNumberSupportStr = os.Getenv("PHONE_NUMBER_SUPPORT") + if PhoneNumberSupportStr == "" { + return fmt.Errorf("You must specify a non-empty PHONE_NUMBER_SUPPORT") + } + p, err = phonenumbers.Parse(PhoneNumberSupportStr, "US") + if err != nil { + return fmt.Errorf("Failed to parse '%s' as a valid phone number: %w", PhoneNumberSupportStr, err) + } + PhoneNumberSupport = *p + SentryDSN = os.Getenv("SENTRY_DSN") if SentryDSN == "" { return fmt.Errorf("You must specify a non-empty SENTRY_DSN")