123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- 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
|