twilio.rb 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Channel::Driver::Sms::Twilio < Channel::Driver::Sms::Base
  3. NAME = 'sms/twilio'.freeze
  4. def fetchable?(_channel)
  5. false
  6. end
  7. def deliver(options, attr, _notification = false)
  8. Rails.logger.info "Sending SMS to recipient #{attr[:recipient]}"
  9. return true if Setting.get('import_mode')
  10. Rails.logger.info "Backend sending Twilio SMS to #{attr[:recipient]}"
  11. begin
  12. send_create(options, attr)
  13. true
  14. rescue => e
  15. Rails.logger.debug { "Twilio error: #{e.inspect}" }
  16. raise e
  17. end
  18. end
  19. def send_create(options, attr)
  20. return if Setting.get('developer_mode')
  21. result = api(options).messages.create(
  22. from: options[:sender],
  23. to: attr[:recipient],
  24. body: attr[:message],
  25. )
  26. raise result.error_message if result&.error_code&.positive?
  27. end
  28. def process(_options, attr, channel)
  29. Rails.logger.info "Receiving SMS frim recipient #{attr[:From]}"
  30. # prevent already created articles
  31. if Ticket::Article.exists?(message_id: attr[:SmsMessageSid])
  32. require 'twilio-ruby' # Only load this gem when it is really used
  33. return ['application/xml; charset=UTF-8;', Twilio::TwiML::MessagingResponse.new.to_s]
  34. end
  35. user = user_by_mobile(attr[:From])
  36. UserInfo.current_user_id = user.id
  37. process_ticket(attr, channel, user)
  38. require 'twilio-ruby' # Only load this gem when it is really used
  39. ['application/xml; charset=UTF-8;', Twilio::TwiML::MessagingResponse.new.to_s]
  40. end
  41. def create_ticket(attr, channel, user)
  42. title = cut_title(attr[:Body])
  43. ticket = Ticket.new(
  44. group_id: channel.group_id,
  45. title: title,
  46. state_id: Ticket::State.find_by(default_create: true).id,
  47. priority_id: Ticket::Priority.find_by(default_create: true).id,
  48. customer_id: user.id,
  49. preferences: {
  50. channel_id: channel.id,
  51. sms: {
  52. AccountSid: attr['AccountSid'],
  53. From: attr['From'],
  54. To: attr['To'],
  55. }
  56. }
  57. )
  58. ticket.save!
  59. ticket
  60. end
  61. def create_article(attr, channel, ticket)
  62. Ticket::Article.create!(
  63. ticket_id: ticket.id,
  64. type: article_type_sms,
  65. sender: Ticket::Article::Sender.find_by(name: 'Customer'),
  66. body: attr[:Body],
  67. from: attr[:From],
  68. to: attr[:To],
  69. message_id: attr[:SmsMessageSid],
  70. content_type: 'text/plain',
  71. preferences: {
  72. channel_id: channel.id,
  73. sms: {
  74. AccountSid: attr['AccountSid'],
  75. From: attr['From'],
  76. To: attr['To'],
  77. NumMedia: attr['NumMedia'],
  78. },
  79. }
  80. )
  81. end
  82. def self.definition
  83. {
  84. name: 'Twilio',
  85. adapter: 'sms/twilio',
  86. account: [
  87. { name: 'options::webhook_token', display: __('Webhook Token'), tag: 'input', type: 'text', limit: 200, null: false, default: Digest::MD5.hexdigest(SecureRandom.uuid), disabled: true, readonly: true },
  88. { name: 'options::account_id', display: __('Account SID'), tag: 'input', type: 'text', limit: 200, null: false, placeholder: 'XXXXXX' },
  89. { name: 'options::token', display: __('Token'), tag: 'input', type: 'text', limit: 200, null: false },
  90. { name: 'options::sender', display: __('Sender'), tag: 'input', type: 'text', limit: 200, null: false, placeholder: '+491710000000' },
  91. { name: 'group_id', display: __('Destination Group'), tag: 'tree_select', null: false, relation: 'Group', nulloption: true, filter: { active: true } },
  92. ],
  93. notification: [
  94. { name: 'options::account_id', display: __('Account SID'), tag: 'input', type: 'text', limit: 200, null: false, placeholder: 'XXXXXX' },
  95. { name: 'options::token', display: __('Token'), tag: 'input', type: 'text', limit: 200, null: false },
  96. { name: 'options::sender', display: __('Sender'), tag: 'input', type: 'text', limit: 200, null: false, placeholder: '+491710000000' },
  97. ],
  98. }
  99. end
  100. private
  101. def api(options)
  102. require 'twilio-ruby' # Only load this gem when it is really used.
  103. @api ||= ::Twilio::REST::Client.new options[:account_id], options[:token]
  104. end
  105. end