twilio.rb 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. class Channel::Driver::Sms::Twilio
  2. NAME = 'sms/twilio'.freeze
  3. def fetchable?(_channel)
  4. false
  5. end
  6. def send(options, attr, _notification = false)
  7. Rails.logger.info "Sending SMS to recipient #{attr[:recipient]}"
  8. return true if Setting.get('import_mode')
  9. Rails.logger.info "Backend sending Twilio SMS to #{attr[:recipient]}"
  10. begin
  11. if Setting.get('developer_mode') != true
  12. result = api(options).messages.create(
  13. from: options[:sender],
  14. to: attr[:recipient],
  15. body: attr[:message],
  16. )
  17. raise result.error_message if result.error_code.positive?
  18. end
  19. true
  20. rescue => e
  21. Rails.logger.debug "Twilio error: #{e.inspect}"
  22. raise e
  23. end
  24. end
  25. def process(_options, attr, channel)
  26. Rails.logger.info "Receiving SMS frim recipient #{attr[:From]}"
  27. # prevent already created articles
  28. if Ticket::Article.exists?(message_id: attr[:SmsMessageSid])
  29. return ['application/xml; charset=UTF-8;', Twilio::TwiML::MessagingResponse.new.to_s]
  30. end
  31. # find sender
  32. user = User.where(mobile: attr[:From]).order(:updated_at).first
  33. if !user
  34. _from_comment, preferences = Cti::CallerId.get_comment_preferences(attr[:From], 'from')
  35. if preferences && preferences['from'] && preferences['from'][0]
  36. if preferences['from'][0]['level'] == 'known' && preferences['from'][0]['object'] == 'User'
  37. user = User.find_by(id: preferences['from'][0]['o_id'])
  38. end
  39. end
  40. end
  41. if !user
  42. user = User.create!(
  43. firstname: attr[:From],
  44. mobile: attr[:From],
  45. )
  46. end
  47. UserInfo.current_user_id = user.id
  48. # find ticket
  49. article_type_sms = Ticket::Article::Type.find_by(name: 'sms')
  50. state_ids = Ticket::State.where(name: %w[closed merged removed]).pluck(:id)
  51. ticket = Ticket.where(customer_id: user.id, create_article_type_id: article_type_sms.id).where.not(state_id: state_ids).order(:updated_at).first
  52. if ticket
  53. new_state = Ticket::State.find_by(default_create: true)
  54. if ticket.state_id != new_state.id
  55. ticket.state = Ticket::State.find_by(default_follow_up: true)
  56. ticket.save!
  57. end
  58. else
  59. if channel.group_id.blank?
  60. raise Exceptions::UnprocessableEntity, 'Group needed in channel definition!'
  61. end
  62. group = Group.find_by(id: channel.group_id)
  63. if !group
  64. raise Exceptions::UnprocessableEntity, 'Group is invalid!'
  65. end
  66. title = attr[:Body]
  67. if title.length > 40
  68. title = "#{title[0, 40]}..."
  69. end
  70. ticket = Ticket.new(
  71. group_id: channel.group_id,
  72. title: title,
  73. state_id: Ticket::State.find_by(default_create: true).id,
  74. priority_id: Ticket::Priority.find_by(default_create: true).id,
  75. customer_id: user.id,
  76. preferences: {
  77. channel_id: channel.id,
  78. sms: {
  79. AccountSid: attr['AccountSid'],
  80. From: attr['From'],
  81. To: attr['To'],
  82. }
  83. }
  84. )
  85. ticket.save!
  86. end
  87. Ticket::Article.create!(
  88. ticket_id: ticket.id,
  89. type: article_type_sms,
  90. sender: Ticket::Article::Sender.find_by(name: 'Customer'),
  91. body: attr[:Body],
  92. from: attr[:From],
  93. to: attr[:To],
  94. message_id: attr[:SmsMessageSid],
  95. content_type: 'text/plain',
  96. preferences: {
  97. channel_id: channel.id,
  98. sms: {
  99. AccountSid: attr['AccountSid'],
  100. From: attr['From'],
  101. To: attr['To'],
  102. }
  103. }
  104. )
  105. ['application/xml; charset=UTF-8;', Twilio::TwiML::MessagingResponse.new.to_s]
  106. end
  107. def self.definition
  108. {
  109. name: 'twilio',
  110. adapter: 'sms/twilio',
  111. account: [
  112. { name: 'options::webhook_token', display: 'Webhook Token', tag: 'input', type: 'text', limit: 200, null: false, default: Digest::MD5.hexdigest(rand(999_999_999_999).to_s), disabled: true, readonly: true },
  113. { name: 'options::account_id', display: 'Account SID', tag: 'input', type: 'text', limit: 200, null: false, placeholder: 'XXXXXX' },
  114. { name: 'options::token', display: 'Token', tag: 'input', type: 'text', limit: 200, null: false },
  115. { name: 'options::sender', display: 'Sender', tag: 'input', type: 'text', limit: 200, null: false, placeholder: '+491710000000' },
  116. { name: 'group_id', display: 'Destination Group', tag: 'select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
  117. ],
  118. notification: [
  119. { name: 'options::account_id', display: 'Account SID', tag: 'input', type: 'text', limit: 200, null: false, placeholder: 'XXXXXX' },
  120. { name: 'options::token', display: 'Token', tag: 'input', type: 'text', limit: 200, null: false },
  121. { name: 'options::sender', display: 'Sender', tag: 'input', type: 'text', limit: 200, null: false, placeholder: '+491710000000' },
  122. ],
  123. }
  124. end
  125. private
  126. def api(options)
  127. @api ||= ::Twilio::REST::Client.new options[:account_id], options[:token]
  128. end
  129. end