background_job.rb 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. class Observer::Ticket::Article::CommunicateTwitter::BackgroundJob
  2. def initialize(id)
  3. @article_id = id
  4. end
  5. def perform
  6. article = Ticket::Article.find(@article_id)
  7. # set retry count
  8. article.preferences['delivery_retry'] ||= 0
  9. article.preferences['delivery_retry'] += 1
  10. ticket = Ticket.lookup(id: article.ticket_id)
  11. log_error(article, "Can't find ticket.preferences for Ticket.find(#{article.ticket_id})") if !ticket.preferences
  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].match?(/\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?(Hash)
  46. tweet_type = 'DirectMessage'
  47. article.message_id = tweet[:event][:id].to_s
  48. if tweet[:event] && tweet[:event][:type] == 'message_create'
  49. #article.from = "@#{tweet.sender.screen_name}"
  50. #article.to = "@#{tweet.recipient.screen_name}"
  51. article.preferences['twitter'] = {
  52. recipient_id: tweet[:event][:message_create][:target][:recipient_id],
  53. sender_id: tweet[:event][:message_create][:sender_id],
  54. }
  55. article.preferences['links'] = [
  56. {
  57. url: "https://twitter.com/messages/#{article.preferences[:twitter][:recipient_id]}-#{article.preferences[:twitter][:sender_id]}",
  58. target: '_blank',
  59. name: 'on Twitter',
  60. },
  61. ]
  62. end
  63. # regular tweet
  64. elsif tweet.class == Twitter::Tweet
  65. tweet_type = 'Tweet'
  66. article.from = "@#{tweet.user.screen_name}"
  67. if tweet.user_mentions
  68. to = ''
  69. mention_ids = []
  70. tweet.user_mentions.each do |user|
  71. if to != ''
  72. to += ' '
  73. end
  74. to += "@#{user.screen_name}"
  75. mention_ids.push user.id
  76. end
  77. article.to = to
  78. article.preferences['twitter'] = TwitterSync.preferences_cleanup(
  79. mention_ids: mention_ids,
  80. geo: tweet.geo,
  81. retweeted: tweet.retweeted?,
  82. possibly_sensitive: tweet.possibly_sensitive?,
  83. in_reply_to_user_id: tweet.in_reply_to_user_id,
  84. place: tweet.place,
  85. retweet_count: tweet.retweet_count,
  86. source: tweet.source,
  87. favorited: tweet.favorited?,
  88. truncated: tweet.truncated?,
  89. created_at: tweet.created_at,
  90. )
  91. end
  92. article.message_id = tweet.id.to_s
  93. article.preferences['links'] = [
  94. {
  95. url: TwitterSync::STATUS_URL_TEMPLATE % tweet.id,
  96. target: '_blank',
  97. name: 'on Twitter',
  98. },
  99. ]
  100. else
  101. raise "Unknown tweet type '#{tweet.class}'"
  102. end
  103. # set delivery status
  104. article.preferences['delivery_status_message'] = nil
  105. article.preferences['delivery_status'] = 'success'
  106. article.preferences['delivery_status_date'] = Time.zone.now
  107. article.save!
  108. Rails.logger.info "Send twitter (#{tweet_type}) to: '#{article.to}' (from #{article.from})"
  109. article
  110. end
  111. def log_error(local_record, message)
  112. local_record.preferences['delivery_status'] = 'fail'
  113. local_record.preferences['delivery_status_message'] = message.encode!('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
  114. local_record.preferences['delivery_status_date'] = Time.zone.now
  115. local_record.save
  116. Rails.logger.error message
  117. if local_record.preferences['delivery_retry'] > 3
  118. Ticket::Article.create(
  119. ticket_id: local_record.ticket_id,
  120. content_type: 'text/plain',
  121. body: "Unable to send tweet: #{message}",
  122. internal: true,
  123. sender: Ticket::Article::Sender.find_by(name: 'System'),
  124. type: Ticket::Article::Type.find_by(name: 'note'),
  125. preferences: {
  126. delivery_article_id_related: local_record.id,
  127. delivery_message: true,
  128. },
  129. updated_by_id: 1,
  130. created_by_id: 1,
  131. )
  132. end
  133. raise message
  134. end
  135. def max_attempts
  136. 4
  137. end
  138. def reschedule_at(current_time, attempts)
  139. if Rails.env.production?
  140. return current_time + attempts * 120.seconds
  141. end
  142. current_time + 5.seconds
  143. end
  144. end