communicate_telegram_job.rb 4.4 KB

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