app/models/agents/twilio_receive_text_agent.rb
module Agents
class TwilioReceiveTextAgent < Agent
cannot_be_scheduled!
cannot_receive_events!
gem_dependency_check { defined?(Twilio) }
description do
<<~MD
The Twilio Receive Text Agent receives text messages from Twilio and emits them as events.
#{'## Include `twilio-ruby` in your Gemfile to use this Agent!' if dependencies_missing?}
In order to create events with this agent, configure Twilio to send POST requests to:
```
#{post_url}
```
#{'The placeholder symbols above will be replaced by their values once the agent is saved.' unless id}
Options:
* `server_url` must be set to the URL of your
Huginn installation (probably "https://#{ENV['DOMAIN']}"), which must be web-accessible. Be sure to set http/https correctly.
* `account_sid` and `auth_token` are your Twilio account credentials. `auth_token` must be the primary auth token for your Twilio accout.
* If `reply_text` is set, it's contents will be sent back as a confirmation text.
* `expected_receive_period_in_days` - How often you expect to receive events this way. Used to determine if the agent is working.
MD
end
def default_options
{
'account_sid' => 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'auth_token' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'server_url' => "https://#{ENV['DOMAIN'].presence || 'example.com'}",
'reply_text' => '',
"expected_receive_period_in_days" => 1
}
end
def validate_options
unless options['account_sid'].present? && options['auth_token'].present? && options['server_url'].present? && options['expected_receive_period_in_days'].present?
errors.add(:base, 'account_sid, auth_token, server_url, and expected_receive_period_in_days are all required')
end
end
def working?
event_created_within?(interpolated['expected_receive_period_in_days']) && !recent_error_logs?
end
def post_url
if interpolated['server_url'].present?
"#{interpolated['server_url']}/users/#{user.id}/web_requests/#{id || ':id'}/sms-endpoint"
else
"https://#{ENV['DOMAIN']}/users/#{user.id}/web_requests/#{id || ':id'}/sms-endpoint"
end
end
def receive_web_request(request)
params = request.params.except(:action, :controller, :agent_id, :user_id, :format)
method = request.method_symbol.to_s
headers = request.headers
# check the last url param: 'secret'
secret = params.delete('secret')
return ["Not Authorized", 401] unless secret == "sms-endpoint"
signature = headers['HTTP_X_TWILIO_SIGNATURE']
# validate from twilio
@validator ||= Twilio::Security::RequestValidator.new interpolated['auth_token']
if !@validator.validate(post_url, params, signature)
error("Twilio Signature Failed to Validate\n\n" +
"URL: #{post_url}\n\n" +
"POST params: #{params.inspect}\n\n" +
"Signature: #{signature}")
return ["Not authorized", 401]
end
if create_event(payload: params)
response = Twilio::TwiML::MessagingResponse.new do |r|
if interpolated['reply_text'].present?
r.message(body: interpolated['reply_text'])
end
end
[response.to_s, 200, "text/xml"]
else
["Bad request", 400]
end
end
end
end