background_job.rb 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. class Observer::Ticket::Article::CommunicateTelegram::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['telegram'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['telegram']
  13. log_error(article, "Can't find ticket.preferences['telegram']['chat_id'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['telegram']['chat_id']
  14. if ticket.preferences['telegram'] && ticket.preferences['telegram']['bid']
  15. channel = Telegram.bot_by_bot_id(ticket.preferences['telegram']['bid'])
  16. end
  17. if !channel
  18. channel = Channel.lookup(id: ticket.preferences['channel_id'])
  19. end
  20. log_error(article, "No such channel for bot #{ticket.preferences['bid']} or channel id #{ticket.preferences['channel_id']}") if !channel
  21. #log_error(article, "Channel.find(#{channel.id}) isn't a telegram channel!") if channel.options[:adapter] !~ /\Atelegram/i
  22. log_error(article, "Channel.find(#{channel.id}) has not telegram api token!") if channel.options[:api_token].blank?
  23. begin
  24. api = TelegramAPI.new(channel.options[:api_token])
  25. chat_id = ticket.preferences[:telegram][:chat_id]
  26. result = api.sendMessage(chat_id, article.body)
  27. me = api.getMe()
  28. article.attachments.each do |file|
  29. parts = file.filename.split(/^(.*)(\..+?)$/)
  30. t = Tempfile.new([parts[1], parts[2]])
  31. t.binmode
  32. t.write(file.content)
  33. t.rewind
  34. api.sendDocument(chat_id, t.path.to_s)
  35. end
  36. rescue => e
  37. log_error(article, e.message)
  38. return
  39. end
  40. Rails.logger.debug { "result info: #{result}" }
  41. # only private, group messages. channel messages do not have from key
  42. if result['from'] && result['chat']
  43. # fill article with message info
  44. article.from = "@#{result['from']['username']}"
  45. article.to = "@#{result['chat']['username']}"
  46. article.preferences['telegram'] = {
  47. date: result['date'],
  48. from_id: result['from']['id'],
  49. chat_id: result['chat']['id'],
  50. message_id: result['message_id']
  51. }
  52. else
  53. # fill article with message info (telegram channel)
  54. article.from = "@#{me['username']}"
  55. article.to = "#{result['chat']['title']} Channel"
  56. article.preferences['telegram'] = {
  57. date: result['date'],
  58. from_id: me['id'],
  59. chat_id: result['chat']['id'],
  60. message_id: result['message_id']
  61. }
  62. end
  63. # set delivery status
  64. article.preferences['delivery_status_message'] = nil
  65. article.preferences['delivery_status'] = 'success'
  66. article.preferences['delivery_status_date'] = Time.zone.now
  67. article.message_id = "telegram.#{result['message_id']}.#{result['chat']['id']}"
  68. article.save!
  69. Rails.logger.info "Send telegram message to: '#{article.to}' (from #{article.from})"
  70. article
  71. end
  72. def log_error(local_record, message)
  73. local_record.preferences['delivery_status'] = 'fail'
  74. local_record.preferences['delivery_status_message'] = message.encode!('UTF-8', 'UTF-8', invalid: :replace, replace: '?')
  75. local_record.preferences['delivery_status_date'] = Time.zone.now
  76. local_record.save
  77. Rails.logger.error message
  78. if local_record.preferences['delivery_retry'] > 3
  79. Ticket::Article.create(
  80. ticket_id: local_record.ticket_id,
  81. content_type: 'text/plain',
  82. body: "Unable to send telegram message: #{message}",
  83. internal: true,
  84. sender: Ticket::Article::Sender.find_by(name: 'System'),
  85. type: Ticket::Article::Type.find_by(name: 'note'),
  86. preferences: {
  87. delivery_article_id_related: local_record.id,
  88. delivery_message: true,
  89. },
  90. updated_by_id: 1,
  91. created_by_id: 1,
  92. )
  93. end
  94. raise message
  95. end
  96. def max_attempts
  97. 4
  98. end
  99. def reschedule_at(current_time, attempts)
  100. if Rails.env.production?
  101. return current_time + attempts * 120.seconds
  102. end
  103. current_time + 5.seconds
  104. end
  105. end