diff --git a/app/jobs/voice_otp_sender_job.rb b/app/jobs/voice_otp_sender_job.rb index b06aa9f1c45..94bdd7ffc77 100644 --- a/app/jobs/voice_otp_sender_job.rb +++ b/app/jobs/voice_otp_sender_job.rb @@ -20,15 +20,37 @@ def send_otp(twilio_service, code, phone) ) end - def twimlet_url(code) - "https://twimlets.com/message?#{twimlet_query_string(code)}" + def twimlet_url(code) # rubocop:disable Metrics/MethodLength + repeat = message_repeat(code) + + twimlet_menu( + repeat, + 1 => twimlet_menu( + repeat, + 1 => twimlet_menu( + repeat, + 1 => twimlet_menu(repeat, 1 => twimlet_message(message_final(code))) + ) + ) + ) + end + + def message_repeat(code) + I18n.t('jobs.voice_otp_sender_job.message_repeat', code: code) + end + + def message_final(code) + I18n.t('jobs.voice_otp_sender_job.message_final', code: code) end - def twimlet_query_string(code) - "Message%5B0%5D=#{URI.escape(otp_message(code))}" + def twimlet_message(message) + 'https://twimlets.com/message?' + { Message: { 0 => message } }.to_query end - def otp_message(code) - I18n.t('jobs.voice_otp_sender_job.message', code: code) + def twimlet_menu(message, options) + 'https://twimlets.com/menu?' + { + Message: message, + Options: options.to_h + }.to_query end end diff --git a/config/locales/jobs/en.yml b/config/locales/jobs/en.yml index c771e786046..fa04381e561 100644 --- a/config/locales/jobs/en.yml +++ b/config/locales/jobs/en.yml @@ -6,6 +6,9 @@ en: If you did not request this change, please contact %{app} at %{support_url} voice_otp_sender_job: - message: > + message_repeat: > + Hello! Your login.gov one time passcode is, %{code}, + again, your passcode is, %{code}. Press 1 to repeat your code. + message_final: > Hello! Your login.gov one time passcode is, %{code}, again, your passcode is, %{code}, goodbye! diff --git a/spec/jobs/voice_otp_sender_job_spec.rb b/spec/jobs/voice_otp_sender_job_spec.rb index c659a80c144..5e1e20cca85 100644 --- a/spec/jobs/voice_otp_sender_job_spec.rb +++ b/spec/jobs/voice_otp_sender_job_spec.rb @@ -14,15 +14,22 @@ calls = FakeVoiceCall.calls - code = '1234'.scan(/\d/).join(', ') - message = t('jobs.voice_otp_sender_job.message', code: code) - url_message = URI.escape(message) - expect(calls.size).to eq(1) call = calls.first expect(call.to).to eq('555-5555') - expect(call.url).to include(url_message) expect(call.from).to match(/(\+19999999999|\+12222222222)/) + + code = '1234'.scan(/\d/).join(', ') + query = Rack::Utils.parse_nested_query(URI(call.url).query) + expect(query['Message']).to eq(t('jobs.voice_otp_sender_job.message_repeat', code: code)) + + nested_query = query + while nested_query['Options'] + nested_url = URI(nested_query['Options']['1']) + nested_query = Rack::Utils.parse_nested_query(nested_url.query) + end + expect(nested_query['Message']['0']). + to eq(t('jobs.voice_otp_sender_job.message_final', code: code)) end it 'does not send if the OTP code is expired' do