# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ class CommunicateTwitterJob < ApplicationJob retry_on StandardError, attempts: 4, wait: lambda { |executions| executions * 120.seconds } def perform(article_id) article = Ticket::Article.find(article_id) # set retry count article.preferences['delivery_retry'] ||= 0 article.preferences['delivery_retry'] += 1 ticket = Ticket.lookup(id: article.ticket_id) log_error(article, "Can't find ticket.preferences['channel_id'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['channel_id'] channel = Channel.lookup(id: ticket.preferences['channel_id']) # search for same channel channel_screen_name, in case the channel got re-added if !channel Channel.where(area: 'Twitter::Account', active: true).each do |local_channel| next if ticket.preferences[:channel_screen_name].blank? next if !local_channel.options next if local_channel.options[:user].blank? next if local_channel.options[:user][:screen_name].blank? next if local_channel.options[:user][:screen_name] != ticket.preferences[:channel_screen_name] channel = local_channel break end end log_error(article, "No such channel id #{ticket.preferences['channel_id']}") if !channel log_error(article, "Channel.find(#{channel.id}) isn't a twitter channel!") if !channel.options[:adapter].try(:match?, %r{\Atwitter}i) begin tweet = channel.deliver( type: article.type.name, to: article.to, body: article.body, in_reply_to: article.in_reply_to ) rescue => e log_error(article, e.message) return end if !tweet log_error(article, 'Got no tweet!') return end # fill article with tweet info # direct message if tweet.is_a?(Twitter::DirectMessage) tweet_type = 'DirectMessage' article.message_id = tweet.id.to_s article.preferences['twitter'] = { recipient_id: tweet.recipient_id.to_s, sender_id: tweet.sender_id.to_s, } article.preferences['links'] = [ { url: TwitterSync::DM_URL_TEMPLATE % article.preferences[:twitter].slice(:recipient_id, :sender_id).values.map(&:to_i).sort.join('-'), target: '_blank', name: 'on Twitter', }, ] # regular tweet elsif tweet.instance_of?(Twitter::Tweet) tweet_type = 'Tweet' article.from = "@#{tweet.user.screen_name}" to = '' mention_ids = [] tweet.user_mentions.each do |user| if to != '' to += ' ' end to += "@#{user.screen_name}" mention_ids.push user.id end article.to = to article.preferences['twitter'] = TwitterSync.preferences_cleanup( mention_ids: mention_ids, geo: tweet.geo, retweeted: tweet.retweeted?, possibly_sensitive: tweet.possibly_sensitive?, in_reply_to_user_id: tweet.in_reply_to_user_id, place: tweet.place, retweet_count: tweet.retweet_count, source: tweet.source, favorited: tweet.favorited?, truncated: tweet.truncated?, created_at: tweet.created_at, ) article.message_id = tweet.id.to_s article.preferences['links'] = [ { url: TwitterSync::STATUS_URL_TEMPLATE % tweet.id, target: '_blank', name: 'on Twitter', }, ] else raise "Unknown tweet type '#{tweet.class}'" end # set delivery status article.preferences['delivery_status_message'] = nil article.preferences['delivery_status'] = 'success' article.preferences['delivery_status_date'] = Time.zone.now article.save! Rails.logger.info "Send twitter (#{tweet_type}) to: '#{article.to}' (from #{article.from})" article end def log_error(local_record, message) local_record.preferences['delivery_status'] = 'fail' local_record.preferences['delivery_status_message'] = message.encode!('UTF-8', 'UTF-8', invalid: :replace, replace: '?') local_record.preferences['delivery_status_date'] = Time.zone.now local_record.save Rails.logger.error message if local_record.preferences['delivery_retry'] > 3 Ticket::Article.create( ticket_id: local_record.ticket_id, content_type: 'text/plain', body: "Unable to send tweet: #{message}", internal: true, sender: Ticket::Article::Sender.find_by(name: 'System'), type: Ticket::Article::Type.find_by(name: 'note'), preferences: { delivery_article_id_related: local_record.id, delivery_message: true, }, updated_by_id: 1, created_by_id: 1, ) end raise message end end