diff --git a/config-schema.dhall b/config-schema.dhall index 002c8195da9da23c894e89c0dc992e25e41b1276..82fe73c61c5561ceea3c95453ea80b212858edee 100644 --- a/config-schema.dhall +++ b/config-schema.dhall @@ -39,6 +39,7 @@ , monthly_price : Natural , name : Text } +, reachability_senders : List Text , rev_ai_token : Text , server : { host : Text, port : Natural } , sgx : Text diff --git a/config.dhall.sample b/config.dhall.sample index 33e1d2c9327b7a837a81ffd0d3b9d292aa04f2d9..52686a7fbe41dbc8c173715de26d35fba85621e2 100644 --- a/config.dhall.sample +++ b/config.dhall.sample @@ -87,6 +87,7 @@ in approved_domains = toMap { `example.com` = Some "customer_id" }, keepgo = Some { api_key = "", access_token = "" }, simpleswap_api_key = "", + reachability_senders = [ "+14445556666" ], support_link = \(customer_jid: Text) -> "http://localhost:3002/app/accounts/2/contacts/custom_attributes/jid/${customer_jid}" } diff --git a/lib/reachability_repo.rb b/lib/reachability_repo.rb new file mode 100644 index 0000000000000000000000000000000000000000..f9ed9e563a3fb3182b7d2b9881ed428dc1875364 --- /dev/null +++ b/lib/reachability_repo.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require "value_semantics/monkey_patched" + +class ReachabilityRepo + value_semantics do + redis Anything(), default: LazyObject.new { REDIS } + senders ArrayOf(String), default: CONFIG[:reachability_senders] + end + + class SMS < self + def type + "sms" + end + end + + class Voice < self + def type + "voice" + end + end + + class NotTest + def filter + EMPromise.resolve(yield) + end + end + + class Test + def initialize(redis, key) + @redis = redis + @key = key + end + + def filter + @redis.incr(@key).then { nil } + end + end + + # The customer is who is being contacted + # The initiator is the phone number trying to reach them + def find(customer, initiator) + return EMPromise.resolve(NotTest.new) unless potential?(initiator) + + testing?(customer).then do |active| + active ? Test.new(redis, key(customer)) : NotTest.new + end + end + +protected + + # This is basically an optimization to bail early without hitting a + # datastore for 99% of all messages + def potential?(tel) + senders.include?(tel) + end + + # This checks if this particular customer has reachability turned on + def testing?(customer) + redis.exists(key(customer)).then { |v| v == 1 } + end + + # This gets the particular key for this check + def key(customer) + "jmp_customer_reachability_#{type}-#{customer.customer_id}" + end +end diff --git a/sgx_jmp.rb b/sgx_jmp.rb index 9622812ec8c16a4e56db063250aa856b6a7e69ff..7f8d1b02ec9c6c541b42cf6d737f8350c2bbf732 100644 --- a/sgx_jmp.rb +++ b/sgx_jmp.rb @@ -96,6 +96,7 @@ require_relative "lib/patches_for_sentry" require_relative "lib/payment_methods" require_relative "lib/paypal_done" require_relative "lib/postgres" +require_relative "lib/reachability_repo" require_relative "lib/registration" require_relative "lib/transaction" require_relative "lib/tel_selections" @@ -279,7 +280,13 @@ before nil, to: /\Acustomer_/, from: /(\A|@)#{CONFIG[:sgx]}(\/|\Z)/ do |s| Sentry.get_current_scope.set_transaction_name("stanza_customer") CustomerRepo.new(set_user: Sentry.method(:set_user)).find( s.to.node.delete_prefix("customer_") - ).then { |customer| customer.stanza_to(s) } + ).then do |customer| + ReachabilityRepo::SMS.new.find(customer, s.from.node).then do |reach| + reach.filter do + customer.stanza_to(s) + end + end + end halt end