New configure calls command

Stephen Paul Weber created

Uses only v2 APIs and sets things up in the new way.

Change summary

forms/configure_calls.rb    | 48 +++++++++++++++++++++++++++++++++++++++
lib/configure_calls_form.rb | 40 ++++++++++++++++++++++++++++++++
lib/customer.rb             |  5 ++++
sgx_jmp.rb                  | 28 +++++++++++++++-------
4 files changed, 112 insertions(+), 9 deletions(-)

Detailed changes

forms/configure_calls.rb 🔗

@@ -0,0 +1,48 @@
+form!
+title "Configure Calls"
+
+field(
+	var: "fwd[timeout]",
+	type: "text-single",
+	datatype: "xs:integer",
+	label: "Seconds to ring before voicemail",
+	description: "One ring is ~5 seconds. Negative means ring forever.",
+	value: @customer.fwd.timeout.to_i.to_s
+)
+
+field(
+	var: "voicemail_transcription",
+	type: "boolean",
+	label: "Voicemail transcription",
+	value: @customer.transcription_enabled.to_s
+)
+
+field(
+	var: "fwd[uri]",
+	type: "list-single",
+	datatype: "xs:anyURI",
+	open: true,
+	label: "Forward calls to",
+	description: "List item or any custom xmpp:, sip:, or tel: URI.",
+	options: [
+		{ label: "Jabber ID", value: "xmpp:#{@customer.jid}" },
+		{ label: "SIP Account", value: @customer.sip_account.uri }
+	],
+	value: @customer.fwd.uri
+)
+
+if @customer.tndetails.dig(:features, :lidb)
+	field(
+		var: "lidb_name",
+		type: "fixed",
+		label: "CNAM",
+		value: "#{@lidb[:name]} (#{@lidb[:status]})"
+	)
+elsif @customer.tndetails[:on_net_vendor]
+	field(
+		var: "lidb_name",
+		type: "text-single",
+		label: "CNAM Name",
+		description: "or nothing/space to leave blank"
+	)
+end

lib/configure_calls_form.rb 🔗

@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require_relative "form_to_h"
+
+class ConfigureCallsForm
+	using FormToH
+
+	def initialize(customer)
+		@customer = customer
+	end
+
+	def render
+		FormTemplate.render("configure_calls", customer: @customer)
+	end
+
+	def parse(form)
+		params = form.to_h
+		{}.tap do |result|
+			result[:fwd] = parse_fwd(params["fwd"]) if params.key?("fwd")
+			if params.key?("voicemail_transcription")
+				result[:transcription_enabled] =
+					["1", "true"].include?(params["voicemail_transcription"])
+			end
+			result[:lidb_name] = params["lidb_name"] if lidb_guard(params["lidb_name"])
+		end
+	end
+
+protected
+
+	def lidb_guard(lidb_name)
+		!lidb_name.to_s.strip.empty? &&
+			!@customer.tndetails.dig(:features, :lidb)
+	end
+
+	def parse_fwd(fwd_from_form)
+		fwd_from_form.reduce(@customer.fwd) do |fwd, (var, val)|
+			fwd.with(var.to_sym => val)
+		end
+	end
+end

lib/customer.rb 🔗

@@ -83,6 +83,11 @@ class Customer
 		stanza_to(iq, &IQ_MANAGER.method(:write)).then(&:vcard)
 	end
 
+	def tndetails
+		@tndetails ||=
+			BandwidthIris::Tn.new(telephone_number: registered?.phone).get_details
+	end
+
 	def ogm(from_tel=nil)
 		CustomerOGM.for(@sgx.ogm_url, -> { fetch_vcard_temp(from_tel) })
 	end

sgx_jmp.rb 🔗

@@ -73,6 +73,7 @@ require_relative "lib/bwmsgsv2_repo"
 require_relative "lib/bandwidth_tn_order"
 require_relative "lib/btc_sell_prices"
 require_relative "lib/buy_account_credit_form"
+require_relative "lib/configure_calls_form"
 require_relative "lib/command"
 require_relative "lib/command_list"
 require_relative "lib/customer"
@@ -453,16 +454,25 @@ Command.new(
 	end
 }.register(self).then(&CommandList.method(:register))
 
-# Commands that just pass through to the SGX
-{
-	"configure-calls" => ["Configure Calls"]
-}.each do |node, args|
-	Command.new(node, *args) {
-		Command.customer.then do |customer|
-			customer.stanza_from(Command.execution.iq)
+Command.new(
+	"configure calls",
+	"Configure Calls",
+	customer_repo: CustomerRepo.new(sgx_repo: Bwmsgsv2Repo.new)
+) {
+	Command.customer.then do |customer|
+		cc_form = ConfigureCallsForm.new(customer)
+		Command.reply { |reply|
+			reply.allowed_actions = [:next]
+			reply.command << cc_form.render
+		}.then { |iq|
+			EMPromise.all(cc_form.parse(iq.form).map { |k, v|
+				Command.execution.customer_repo.public_send("put_#{k}", customer, v)
+			})
+		}.then do
+			Command.finish("Configuration saved!")
 		end
-	}.register(self, guards: [node: node]).then(&CommandList.method(:register))
-end
+	end
+}.register(self).then(&CommandList.method(:register))
 
 Command.new(
 	"ogm",