twilio_receive_text_agent.rb 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. module Agents
  2. class TwilioReceiveTextAgent < Agent
  3. cannot_be_scheduled!
  4. cannot_receive_events!
  5. gem_dependency_check { defined?(Twilio) }
  6. description do
  7. <<~MD
  8. The Twilio Receive Text Agent receives text messages from Twilio and emits them as events.
  9. #{'## Include `twilio-ruby` in your Gemfile to use this Agent!' if dependencies_missing?}
  10. In order to create events with this agent, configure Twilio to send POST requests to:
  11. ```
  12. #{post_url}
  13. ```
  14. #{'The placeholder symbols above will be replaced by their values once the agent is saved.' unless id}
  15. Options:
  16. * `server_url` must be set to the URL of your
  17. Huginn installation (probably "https://#{ENV['DOMAIN']}"), which must be web-accessible. Be sure to set http/https correctly.
  18. * `account_sid` and `auth_token` are your Twilio account credentials. `auth_token` must be the primary auth token for your Twilio accout.
  19. * If `reply_text` is set, it's contents will be sent back as a confirmation text.
  20. * `expected_receive_period_in_days` - How often you expect to receive events this way. Used to determine if the agent is working.
  21. MD
  22. end
  23. def default_options
  24. {
  25. 'account_sid' => 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  26. 'auth_token' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  27. 'server_url' => "https://#{ENV['DOMAIN'].presence || 'example.com'}",
  28. 'reply_text' => '',
  29. "expected_receive_period_in_days" => 1
  30. }
  31. end
  32. def validate_options
  33. unless options['account_sid'].present? && options['auth_token'].present? && options['server_url'].present? && options['expected_receive_period_in_days'].present?
  34. errors.add(:base, 'account_sid, auth_token, server_url, and expected_receive_period_in_days are all required')
  35. end
  36. end
  37. def working?
  38. event_created_within?(interpolated['expected_receive_period_in_days']) && !recent_error_logs?
  39. end
  40. def post_url
  41. if interpolated['server_url'].present?
  42. "#{interpolated['server_url']}/users/#{user.id}/web_requests/#{id || ':id'}/sms-endpoint"
  43. else
  44. "https://#{ENV['DOMAIN']}/users/#{user.id}/web_requests/#{id || ':id'}/sms-endpoint"
  45. end
  46. end
  47. def receive_web_request(request)
  48. params = request.params.except(:action, :controller, :agent_id, :user_id, :format)
  49. method = request.method_symbol.to_s
  50. headers = request.headers
  51. # check the last url param: 'secret'
  52. secret = params.delete('secret')
  53. return ["Not Authorized", 401] unless secret == "sms-endpoint"
  54. signature = headers['HTTP_X_TWILIO_SIGNATURE']
  55. # validate from twilio
  56. @validator ||= Twilio::Security::RequestValidator.new interpolated['auth_token']
  57. if !@validator.validate(post_url, params, signature)
  58. error("Twilio Signature Failed to Validate\n\n" +
  59. "URL: #{post_url}\n\n" +
  60. "POST params: #{params.inspect}\n\n" +
  61. "Signature: #{signature}")
  62. return ["Not authorized", 401]
  63. end
  64. if create_event(payload: params)
  65. response = Twilio::TwiML::MessagingResponse.new do |r|
  66. if interpolated['reply_text'].present?
  67. r.message(body: interpolated['reply_text'])
  68. end
  69. end
  70. [response.to_s, 200, "text/xml"]
  71. else
  72. ["Bad request", 400]
  73. end
  74. end
  75. end
  76. end