Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
mgomes committed Mar 8, 2022
0 parents commit ae9d822
Show file tree
Hide file tree
Showing 16 changed files with 474 additions and 0 deletions.
60 changes: 60 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/ruby:2.4.1-node-browsers
environment:
STEALTH_ENV: test

# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4

working_directory: ~/repo

steps:
- checkout

# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-

- run:
name: install dependencies
command: |
bundle install --jobs=4 --retry=3 --path vendor/bundle
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}

# run tests!
- run:
name: run tests
command: |
mkdir /tmp/test-results
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec --format progress \
--format RspecJunitFormatter \
--out /tmp/test-results/rspec.xml \
--format progress \
-- \
$TEST_FILES
# collect reports
- store_test_results:
path: /tmp/test-results
- store_artifacts:
path: /tmp/test-results
destination: test-results
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# please add general patterns to your global ignore list
# see https://github.com/github/gitignore#readme
.DS_STORE
*.swp
*.rbc
*.sass-cache
/pkg
/doc/api
/coverage
.yardoc
doc/
*.gem
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source 'https://rubygems.org'

gemspec
117 changes: 117 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
PATH
remote: .
specs:
stealth-twilio_voice (1.3.1)
stealth (>= 2.0.0.beta4)
twilio-ruby (~> 5.65)

GEM
remote: https://rubygems.org/
specs:
activesupport (6.1.4.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
concurrent-ruby (1.1.9)
connection_pool (2.2.5)
diff-lcs (1.3)
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
jwt (2.3.0)
mini_portile2 (2.8.0)
minitest (5.15.0)
multi_json (1.15.0)
multipart-post (2.1.1)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
nio4r (2.5.8)
nokogiri (1.13.3)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
puma (5.6.2)
nio4r (~> 2.0)
racc (1.6.0)
rack (2.2.2)
rack-protection (2.2.0)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
redis (4.6.0)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-support (3.9.2)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
ruby2_keywords (0.0.5)
sidekiq (6.4.1)
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
sinatra (2.2.0)
mustermann (~> 1.0)
rack (~> 2.2)
rack-protection (= 2.2.0)
tilt (~> 2.0)
stealth (2.0.0.beta4)
activesupport (~> 6.0)
multi_json (~> 1.12)
puma (>= 4.2, < 6.0)
sidekiq (~> 6.0)
sinatra (~> 2.0)
thor (~> 1.0)
thor (1.2.1)
tilt (2.0.10)
twilio-ruby (5.65.0)
faraday (>= 0.9, < 2.0)
jwt (>= 1.5, <= 2.5)
nokogiri (>= 1.6, < 2.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
zeitwerk (2.5.4)

PLATFORMS
ruby

DEPENDENCIES
rack-test (~> 1.1)
rspec (~> 3.6)
rspec_junit_formatter (~> 0.3)
stealth-twilio_voice!

BUNDLED WITH
2.2.32
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Stealth Twilio Phone

The [Stealth](https://github.com/hellostealth/stealth) Twilio phone driver adds the ability to build your bot using voice over a standard phone call.

[![Gem Version](https://badge.fury.io/rb/stealth-twilio.svg)](https://badge.fury.io/rb/stealth-twilio)
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.3.1
1 change: 1 addition & 0 deletions lib/stealth-twilio_voice.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'stealth/twilio_voice'
32 changes: 32 additions & 0 deletions lib/stealth/services/twilio_voice/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

require 'twilio-ruby'

require 'stealth/services/twilio_voice/message_handler'
require 'stealth/services/twilio_voice/reply_handler'
require 'stealth/services/twilio_voice/setup'

module Stealth
module Services
module TwilioVoice
class Client < Stealth::Services::BaseClient

attr_reader :reply

def initialize(reply:)
@reply = reply
end

def transmit
Thread.current[:voice_reply] = reply[:msg]

Stealth::Logger.l(
topic: :twilio_voice,
message: "Audio reply sent."
)
end

end
end
end
end
72 changes: 72 additions & 0 deletions lib/stealth/services/twilio_voice/message_handler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# frozen_string_literal: true

require 'twilio-ruby'

module Stealth
module Services
module TwilioVoice
class MessageHandler < Stealth::Services::BaseMessageHandler
attr_reader :service_message, :params, :headers

def initialize(params:, headers:)
@service = "twilio_voice"
@params = params
@headers = headers
end

def coordinate
dispatcher = Stealth::Dispatcher.new(
service: @service,
params: params,
headers: headers
)

dispatcher.process

puts "SENDING: #{Thread.current[:voice_reply]}"

send_voice_reply
end

def process
@service_message = ServiceMessage.new(service: 'twilio_voice')
service_message.sender_id = params['From']
service_message.target_id = params['To']
if params["Digits"].present?
service_message.message = parse_int(params["Digits"])
elsif params["SpeechResult"].present?
service_message.message = params["SpeechResult"]
service_message.confidence = parse_float(params["Confidence"])
end

puts "Webhook from Twilio: #{params.inspect}"

service_message
end

private

def send_voice_reply
response_headers = { 'Content-Type' => 'text/xml' }
[200, response_headers, Thread.current[:voice_reply]]
end

def parse_int(int)
Integer(int)
rescue TypeError
return nil
rescue ArgumentError
return nil
end

def parse_float(float)
Float(float)
rescue TypeError
return nil
rescue ArgumentError
return nil
end
end
end
end
end
73 changes: 73 additions & 0 deletions lib/stealth/services/twilio_voice/reply_handler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# coding: utf-8
# frozen_string_literal: true

module Stealth
module Services
module TwilioVoice
class ReplyHandler < Stealth::Services::BaseReplyHandler

attr_reader :recipient_id, :replies

def initialize(recipient_id: nil, replies: nil)
@recipient_id = recipient_id
@replies = replies
end

def build_reply
voice_reply = ::Twilio::TwiML::VoiceResponse.new do |r|
replies.each do |reply|
case reply["reply_type"]
when "speech"
# Say options: https://www.twilio.com/docs/voice/twiml/say
r.say(
message: reply["speech"],
voice: Stealth.config.twilio_voice.voice
)
when "delay"
# Pause options: https://www.twilio.com/docs/voice/twiml/pause
r.pause(length: reply["duration"])
when "play"
# Play options: https://www.twilio.com/docs/voice/twiml/play
loop_val = reply["loop"] || 1
r.play(loop: loop_val, url: reply["url"])
when "gather"
# Gather options: https://www.twilio.com/docs/voice/twiml/gather
finish_key = reply["finish_key"] || "#"
timeout = reply["timeout"] || 5
speech_timeout = reply["speech_timeout"] || "auto"
num_digits = reply["num_digits"] || 5
profanity_filter = reply["profanity_filter"] || true
language = reply["language"] || "en-US"
hints = reply["hints"]&.join(",") || ""
# dtmf, speech, dtmf speech
input = reply["input"] || "dtmf"
# Must utilize speech_model "phone_call"
enhanced = reply["enhanced"] || false
# default, number_and_commands, phone_call
speech_model = reply["speech_model"] || "default"

r.gather(
input: input,
finish_on_key: finish_key,
timeout: timeout,
speech_timeout: speech_timeout,
num_digits: num_digits,
profanity_filter: profanity_filter,
language: language,
hints: hints,
enhanced: enhanced,
speech_model: speech_model
)
end
end
end.to_s

{
type: :speech,
msg: voice_reply
}
end
end
end
end
end
Loading

0 comments on commit ae9d822

Please sign in to comment.