# Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ class CommunicateTelegramJob < 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 for Ticket.find(#{article.ticket_id})") if !ticket.preferences log_error(article, "Can't find ticket.preferences['telegram'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['telegram'] log_error(article, "Can't find ticket.preferences['telegram']['chat_id'] for Ticket.find(#{article.ticket_id})") if !ticket.preferences['telegram']['chat_id'] if ticket.preferences['telegram'] && ticket.preferences['telegram']['bid'] channel = TelegramHelper.bot_by_bot_id(ticket.preferences['telegram']['bid']) end if !channel channel = Channel.lookup(id: ticket.preferences['channel_id']) end log_error(article, "No such channel for bot #{ticket.preferences['bid']} or channel id #{ticket.preferences['channel_id']}") if !channel # log_error(article, "Channel.find(#{channel.id}) isn't a telegram channel!") if channel.options[:adapter] !~ /\Atelegram/i log_error(article, "Channel.find(#{channel.id}) has not telegram api token!") if channel.options[:api_token].blank? result = nil begin Telegram::Bot::Client.run(channel.options[:api_token]) do |bot| chat_id = ticket.preferences[:telegram][:chat_id] result = bot.api.sendMessage(chat_id: chat_id, text: article.body) article.attachments.each do |file| parts = file.filename.split(%r{^(.*)(\..+?)$}) t = Tempfile.new([parts[1], parts[2]]) t.binmode t.write(file.content) t.rewind upload = Faraday::UploadIO.new( t.path, file.preferences['Content-Type'], file.filename ) bot.api.sendDocument(chat_id: chat_id, document: upload) end end rescue => e log_error(article, e.message) return end Rails.logger.debug { "result info: #{result}" } # only private, group messages. channel messages do not have from key if result.from && result.chat # fill article with message info article.from = "@#{result.from.username}" article.to = "@#{result.chat.username}" article.preferences['telegram'] = { date: result.date, from_id: result.from.id, chat_id: result.chat.id, message_id: result.message_id } else # fill article with message info (telegram channel) article.from = "@#{me['username']}" article.to = "#{result.chat.title} Channel" article.preferences['telegram'] = { date: result.date, from_id: me['id'], chat_id: result.chat.id, message_id: result.message_id } end # set delivery status article.preferences['delivery_status_message'] = nil article.preferences['delivery_status'] = 'success' article.preferences['delivery_status_date'] = Time.zone.now article.message_id = "telegram.#{result.message_id}.#{result.chat.id}" article.save! Rails.logger.info "Send telegram message 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 telegram message: #{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