communicate_twitter_job.rb 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class CommunicateTwitterJob < ApplicationJob
  3. retry_on StandardError, attempts: 4, wait: lambda { |executions|
  4. executions * 120.seconds
  5. }
  6. def perform(article_id)
  7. article = Ticket::Article.find(article_id)
  8. # set retry count
  9. article.preferences['delivery_retry'] ||= 0
  10. article.preferences['delivery_retry'] += 1
  11. ticket = Ticket.lookup(id: article.ticket_id)
  12. log_error(article, "Can't find ticket.preferences['channel_id'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['channel_id']
  13. channel = Channel.lookup(id: ticket.preferences['channel_id'])
  14. # search for same channel channel_screen_name, in case the channel got re-added
  15. if !channel
  16. Channel.where(area: 'Twitter::Account', active: true).each do |local_channel|
  17. next if ticket.preferences[:channel_screen_name].blank?
  18. next if !local_channel.options
  19. next if local_channel.options[:user].blank?
  20. next if local_channel.options[:user][:screen_name].blank?
  21. next if local_channel.options[:user][:screen_name] != ticket.preferences[:channel_screen_name]
  22. channel = local_channel
  23. break
  24. end
  25. end
  26. log_error(article, "No such channel id #{ticket.preferences['channel_id']}") if !channel
  27. log_error(article, "Channel.find(#{channel.id}) isn't a twitter channel!") if !channel.options[:adapter].try(:match?, %r{\Atwitter}i)
  28. begin
  29. tweet = channel.deliver(
  30. type: article.type.name,
  31. to: article.to,
  32. body: article.body,
  33. in_reply_to: article.in_reply_to
  34. )
  35. rescue => e
  36. log_error(article, e.message)
  37. return
  38. end
  39. if !tweet
  40. log_error(article, 'Got no tweet!')
  41. return
  42. end
  43. # fill article with tweet info
  44. # direct message
  45. if tweet.is_a?(Twitter::DirectMessage)
  46. tweet_type = 'DirectMessage'
  47. article.message_id = tweet.id.to_s
  48. article.preferences['twitter'] = {
  49. recipient_id: tweet.recipient_id.to_s,
  50. sender_id: tweet.sender_id.to_s,
  51. }
  52. article.preferences['links'] = [
  53. {
  54. url: TwitterSync::DM_URL_TEMPLATE % article.preferences[:twitter].slice(:recipient_id, :sender_id).values.map(&:to_i).sort.join('-'),
  55. target: '_blank',
  56. name: 'on Twitter',
  57. },
  58. ]
  59. # regular tweet
  60. elsif tweet.instance_of?(Twitter::Tweet)
  61. tweet_type = 'Tweet'
  62. article.from = "@#{tweet.user.screen_name}"
  63. to = ''
  64. mention_ids = []
  65. tweet.user_mentions.each do |user|
  66. if to != ''
  67. to += ' '
  68. end
  69. to += "@#{user.screen_name}"
  70. mention_ids.push user.id
  71. end
  72. article.to = to
  73. article.preferences['twitter'] = TwitterSync.preferences_cleanup(
  74. mention_ids: mention_ids,
  75. geo: tweet.geo,
  76. retweeted: tweet.retweeted?,
  77. possibly_sensitive: tweet.possibly_sensitive?,
  78. in_reply_to_user_id: tweet.in_reply_to_user_id,
  79. place: tweet.place,
  80. retweet_count: tweet.retweet_count,
  81. source: tweet.source,
  82. favorited: tweet.favorited?,
  83. truncated: tweet.truncated?,
  84. created_at: tweet.created_at,
  85. )
  86. article.message_id = tweet.id.to_s
  87. article.preferences['links'] = [
  88. {
  89. url: TwitterSync::STATUS_URL_TEMPLATE % tweet.id,
  90. target: '_blank',
  91. name: 'on Twitter',
  92. },
  93. ]
  94. else
  95. raise "Unknown tweet type '#{tweet.class}'"
  96. end
  97. # set delivery status
  98. article.preferences['delivery_status_message'] = nil
  99. article.preferences['delivery_status'] = 'success'
  100. article.preferences['delivery_status_date'] = Time.zone.now
  101. article.save!
  102. Rails.logger.info "Send twitter (#{tweet_type}) to: '#{article.to}' (from #{article.from})"
  103. article
  104. end
  105. def log_error(local_record, message)
  106. local_record.preferences['delivery_status'] = 'fail'
  107. local_record.preferences['delivery_status_message'] = message.encode!('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
  108. local_record.preferences['delivery_status_date'] = Time.zone.now
  109. local_record.save
  110. Rails.logger.error message
  111. if local_record.preferences['delivery_retry'] > 3
  112. Ticket::Article.create(
  113. ticket_id: local_record.ticket_id,
  114. content_type: 'text/plain',
  115. body: "Unable to send tweet: #{message}",
  116. internal: true,
  117. sender: Ticket::Article::Sender.find_by(name: 'System'),
  118. type: Ticket::Article::Type.find_by(name: 'note'),
  119. preferences: {
  120. delivery_article_id_related: local_record.id,
  121. delivery_message: true,
  122. },
  123. updated_by_id: 1,
  124. created_by_id: 1,
  125. )
  126. end
  127. raise message
  128. end
  129. end