M forms/configure_calls.rb => forms/configure_calls.rb +21 -12
@@ 2,21 2,30 @@ 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",
+ var: "fwd[voicemail_enabled]",
type: "boolean",
- label: "Voicemail transcription",
- value: @customer.transcription_enabled.to_s
+ label: "Voicemail enabled",
+ value: @customer.fwd.voicemail_enabled?
)
+if @customer.fwd.voicemail_enabled?
+ 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
+ )
+end
+
field(
var: "fwd[uri]",
type: "list-single",
M lib/configure_calls_form.rb => lib/configure_calls_form.rb +4 -3
@@ 33,8 33,9 @@ protected
end
def parse_fwd(fwd_from_form)
- fwd_from_form.reduce(@customer.fwd) do |fwd, (var, val)|
- fwd.with(var.to_sym => val.strip)
- end
+ @customer.fwd.with(fwd_from_form.each_with_object({}) { |(var, val), args|
+ args[var.to_sym] =
+ var == "voicemail_enabled" ? ["1", "true"].include?(val) : val&.strip
+ })
end
end
M lib/customer_fwd.rb => lib/customer_fwd.rb +49 -6
@@ 5,8 5,17 @@ require "value_semantics/monkey_patched"
require "uri"
class CustomerFwd
- def self.for(uri:, timeout:)
- timeout = Timeout.new(timeout)
+ class InfiniteTimeout < StandardError
+ attr_reader :fwd
+
+ def initialize(fwd)
+ super "Infinite timeout"
+ @fwd = fwd
+ end
+ end
+
+ def self.for(uri:, timeout: nil, voicemail_enabled: :default)
+ timeout = Timeout.for(timeout, voicemail_enabled: voicemail_enabled)
fwd = if uri
if uri =~ /\Asip:(.*)@sip.cheogram.com\Z/
@@ 22,18 31,32 @@ class CustomerFwd
end
class Timeout
- def self.new(s)
- s.is_a?(self) ? s : super
+ def self.for(s, voicemail_enabled: :default)
+ return Infinite.new unless voicemail_enabled
+
+ if s.nil? || s.is_a?(Infinite) || s.to_i.negative?
+ return new(25) if voicemail_enabled == true # ~5s / ring, 5 rings
+
+ return Infinite.new
+ end
+
+ return s if s.is_a?(self)
+
+ new(s)
end
def initialize(s)
- @timeout = s.nil? || s.to_i.negative? || s.to_i > 300 ? 300 : s.to_i
+ @timeout = [s.to_i, 300].min
end
def zero?
@timeout.zero?
end
+ def infinite?
+ false
+ end
+
def to_i
@timeout
end
@@ 41,18 64,38 @@ class CustomerFwd
def to_s
to_i.to_s
end
+
+ class Infinite < Timeout
+ def initialize; end
+
+ def zero?
+ false
+ end
+
+ def infinite?
+ 1
+ end
+
+ def to_i; end
+ end
end
value_semantics do
uri Either(/:/, NilClass)
- def_attr :timeout, Timeout, coerce: Timeout.method(:new)
+ def_attr :timeout, Timeout, coerce: Timeout.method(:for)
end
def with(new_attrs)
CustomerFwd.for(to_h.merge(new_attrs))
end
+ def voicemail_enabled?
+ !timeout.infinite?
+ end
+
def create_call(account)
+ raise InfiniteTimeout, self if timeout.infinite?
+
request = Bandwidth::ApiCreateCallRequest.new.tap { |cc|
cc.to = to
cc.call_timeout = timeout.to_i
M lib/registration.rb => lib/registration.rb +1 -1
@@ 470,7 470,7 @@ class Registration
EMPromise.all([
REDIS.del("pending_tel_for-#{@customer.jid}"),
Bwmsgsv2Repo.new.put_fwd(@customer.customer_id, @tel, CustomerFwd.for(
- uri: "xmpp:#{@customer.jid}", timeout: 25 # ~5s / ring, 5 rings
+ uri: "xmpp:#{@customer.jid}", voicemail_enabled: true
))
])
}.then do
M sgx_jmp.rb => sgx_jmp.rb +1 -1
@@ 527,7 527,7 @@ Command.new(
Command.new(
"ogm",
"Record Voicemail Greeting",
- list_for: ->(fwd: nil, **) { !!fwd },
+ list_for: ->(fwd: nil, **) { fwd&.voicemail_enabled? },
customer_repo: CustomerRepo.new(sgx_repo: Bwmsgsv2Repo.new)
) {
Command.customer.then do |customer|
A views/forward.slim => views/forward.slim +3 -0
@@ 0,0 1,3 @@
+doctype xml
+Response
+ Forward to=fwd.to from=from callTimeout=300
A views/hangup.slim => views/hangup.slim +3 -0
@@ 0,0 1,3 @@
+doctype xml
+Response
+ Hangup /
M web.rb => web.rb +5 -1
@@ 296,8 296,10 @@ class Web < Roda
sgx_repo: Bwmsgsv2Repo.new,
ogm_url: nil
).then { |c|
- c.ogm(params["from"])
+ c.ogm(params["from"]) if c.fwd.voicemail_enabled?
}.then { |ogm|
+ next render :hangup unless ogm
+
render :voicemail, locals: { ogm: ogm }
}
end
@@ 339,6 341,8 @@ class Web < Roda
outbound_transfers[params["callId"]] = call
render :ring, locals: { duration: 300 }
+ }.catch_only(CustomerFwd::InfiniteTimeout) { |e|
+ render :forward, locals: { fwd: e.fwd, from: params["from"] }
}.catch { |e|
log_error(e) unless e == :voicemail
render :redirect, locals: { to: inbound_calls_path(:voicemail) }