JSON rendering option for inbound calls

Stephen Paul Weber created

Change summary

lib/call_attempt.rb |  6 +++---
lib/customer_fwd.rb | 22 ++++++++++++++++++++++
lib/customer_ogm.rb | 22 ++++++++++++++++++++++
web.rb              | 33 ++++++++++++++++++++++++++++-----
4 files changed, 75 insertions(+), 8 deletions(-)

Detailed changes

lib/call_attempt.rb 🔗

@@ -145,7 +145,7 @@ class CallAttempt
 		def create_call(*); end
 
 		def as_json(*)
-			{ tts: tts }
+			tts.empty? ? {} : { tts: tts }
 		end
 
 		def to_json(*args)
@@ -181,7 +181,7 @@ class CallAttempt
 		def create_call(*); end
 
 		def as_json(*)
-			{ tts: tts }
+			tts.empty? ? {} : { tts: tts }
 		end
 
 		def to_json(*args)
@@ -231,7 +231,7 @@ class CallAttempt
 		def create_call(*); end
 
 		def as_json(*)
-			{ tts: tts }
+			tts.empty? ? {} : { tts: tts }
 		end
 
 		def to_json(*args)

lib/customer_fwd.rb 🔗

@@ -65,6 +65,14 @@ class CustomerFwd
 			to_i.to_s
 		end
 
+		def as_json(*)
+			to_i
+		end
+
+		def to_json(*args)
+			as_json.to_json(*args)
+		end
+
 		class Infinite < Timeout
 			def initialize; end
 
@@ -77,6 +85,10 @@ class CustomerFwd
 			end
 
 			def to_i; end
+
+			def as_json(*)
+				nil
+			end
 		end
 	end
 
@@ -104,6 +116,14 @@ class CustomerFwd
 		BANDWIDTH_VOICE.create_call(account, body: request).data.call_id
 	end
 
+	def as_json(*)
+		[to_h]
+	end
+
+	def to_json(*args)
+		as_json.to_json(*args)
+	end
+
 	class Tel < CustomerFwd
 		def initialize(values)
 			super
@@ -132,6 +152,8 @@ class CustomerFwd
 		def create_call(*); end
 
 		def to; end
+
+		def as_json(*); end
 	end
 
 	URIS = {

lib/customer_ogm.rb 🔗

@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require_relative "tts_template"
+
 module CustomerOGM
 	def self.for(url, tel, fetch_vcard)
 		return Media.new(url) if url
@@ -15,6 +17,16 @@ module CustomerOGM
 		def to_render
 			[:voicemail_ogm_media, { locals: { url: @url } }]
 		end
+
+		def as_json(*)
+			{
+				media_url: @url
+			}
+		end
+
+		def to_json(*args)
+			as_json.to_json(*args)
+		end
 	end
 
 	class TTS
@@ -50,5 +62,15 @@ module CustomerOGM
 		def to_render
 			[:voicemail_ogm_tts, { locals: { fn: fn } }]
 		end
+
+		def as_json(*)
+			{
+				tts: TTSTemplate.new(to_render.first).tts(self)
+			}
+		end
+
+		def to_json(*args)
+			as_json.to_json(*args)
+		end
 	end
 end

web.rb 🔗

@@ -206,19 +206,41 @@ class Web < Roda
 		])
 	end
 
+	def json_call(customer, fwd, call_attempt)
+		raise "Not allowed" unless params["secret"] == CONFIG[:component][:secret]
+
+		customer.ogm(params["from"]).then do |ogm|
+			call_attempt.as_json.merge(
+				fwd: Array(fwd.as_json),
+				ogm: ogm
+			).to_json
+		end
+	end
+
+	def transfer_complete_url(customer_id, call_id, tries)
+		url(
+			inbound_calls_path(:transfer_complete, customer_id, call_id: call_id)
+		) + (tries ? "&tries=#{tries}" : "")
+	end
+
 	def create_call(customer, from, call_id, application_id, tries: nil)
 		call_inputs(customer, from, call_id).then do |(customer_id, fwd, ca)|
+			request.json { json_call(customer, fwd, ca) }
 			ca.create_call(fwd, CONFIG[:creds][:account]) do |cc|
 				cc.from = from
 				cc.application_id = application_id
 				cc.answer_url = url inbound_calls_path(nil, customer_id)
-				cc.disconnect_url = url(
-					inbound_calls_path(:transfer_complete, customer_id, call_id: call_id)
-				) + (tries ? "&tries=#{tries}" : "")
+				cc.disconnect_url = transfer_complete_url(customer_id, call_id, tries)
 			end
 		end
 	end
 
+	def hangup
+		request.json { {}.to_json }
+
+		render :hangup
+	end
+
 	route do |r|
 		r.get "healthcheck" do
 			"OK"
@@ -344,7 +366,7 @@ class Web < Roda
 							).then { |c|
 								c.ogm(params["from"])
 							}.then { |ogm|
-								next render :hangup unless ogm
+								next hangup unless ogm
 
 								render :voicemail, locals: { ogm: ogm }
 							}.catch_only(CustomerRepo::NotFound) {
@@ -372,7 +394,7 @@ class Web < Roda
 						sgx_repo: Bwmsgsv2Repo.new
 					).find_by_tel(params["to"]).then { |customer|
 						reachability_repo.find(customer, params["from"]).then do |reach|
-							reach.filter(if_yes: ->(_) { render :hangup }) do
+							reach.filter(if_yes: ->(_) { hangup }) do
 								create_call(
 									customer,
 									params["from"],
@@ -390,6 +412,7 @@ class Web < Roda
 						render :forward, locals: { fwd: e.fwd, from: params["from"] }
 					}.catch { |e|
 						log_error(e) unless e == :voicemail
+						r.json { { error: e.to_s }.to_json }
 						render :redirect, locals: { to: inbound_calls_path(:voicemail) }
 					}
 				end