From 4a89bab23a99b87116a9268972f5ac53921476cd Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Wed, 25 Oct 2023 21:06:31 +0530 Subject: [PATCH] feat: Handle Telegram send message/attachments errors (#8173) Co-authored-by: Pranav Raj S --- app/models/channel/telegram.rb | 31 +++++++++++++++++------- spec/models/channel/telegram_spec.rb | 36 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/app/models/channel/telegram.rb b/app/models/channel/telegram.rb index ac2f4b9be..94780cce4 100644 --- a/app/models/channel/telegram.rb +++ b/app/models/channel/telegram.rb @@ -87,9 +87,19 @@ class Channel::Telegram < ApplicationRecord def send_message(message) response = message_request(chat_id(message), message.content, reply_markup(message), reply_to_message_id(message)) + process_error(message, response) response.parsed_response['result']['message_id'] if response.success? end + def process_error(message, response) + return unless response.parsed_response['ok'] == false + + # https://github.com/TelegramBotAPI/errors/tree/master/json + message.external_error = "#{response.parsed_response['error_code']}, #{response.parsed_response['description']}" + message.status = :failed + message.save! + end + def reply_markup(message) return unless message.content_type == 'input_select' @@ -110,23 +120,26 @@ class Channel::Telegram < ApplicationRecord telegram_attachments = [] message.attachments.each do |attachment| telegram_attachment = {} - - case attachment[:file_type] - when 'audio' - telegram_attachment[:type] = 'audio' - when 'image' - telegram_attachment[:type] = 'photo' - when 'file' - telegram_attachment[:type] = 'document' - end + telegram_attachment[:type] = attachment_type(attachment[:file_type]) telegram_attachment[:media] = attachment.download_url telegram_attachments << telegram_attachment end response = attachments_request(chat_id(message), telegram_attachments, reply_to_message_id(message)) + process_error(message, response) response.parsed_response['result'].first['message_id'] if response.success? end + def attachment_type(file_type) + file_type_mappings = { + 'audio' => 'audio', + 'image' => 'photo', + 'file' => 'document', + 'video' => 'video' + } + file_type_mappings[file_type] + end + def attachments_request(chat_id, attachments, reply_to_message_id) HTTParty.post("#{telegram_api_url}/sendMediaGroup", body: { diff --git a/spec/models/channel/telegram_spec.rb b/spec/models/channel/telegram_spec.rb index 0fa5515fb..cda0b03d7 100644 --- a/spec/models/channel/telegram_spec.rb +++ b/spec/models/channel/telegram_spec.rb @@ -42,6 +42,28 @@ RSpec.describe Channel::Telegram do expect(telegram_channel.send_message_on_telegram(message)).to eq('telegram_123') end + + it 'send text message failed' do + message = create(:message, message_type: :outgoing, content: 'test', + conversation: create(:conversation, inbox: telegram_channel.inbox, additional_attributes: { 'chat_id' => '123' })) + + stub_request(:post, "https://api.telegram.org/bot#{telegram_channel.bot_token}/sendMessage") + .with( + body: 'chat_id=123&text=test&reply_markup=&reply_to_message_id=' + ) + .to_return( + status: 403, + headers: { 'Content-Type' => 'application/json' }, + body: { + ok: false, + error_code: '403', + description: 'Forbidden: bot was blocked by the user' + }.to_json + ) + telegram_channel.send_message_on_telegram(message) + expect(message.reload.status).to eq('failed') + expect(message.reload.external_error).to eq('403: Forbidden: bot was blocked by the user') + end end context 'when a empty message and valid attachments' do @@ -72,6 +94,20 @@ RSpec.describe Channel::Telegram do allow(telegram_channel).to receive(:attachments_request).and_return(telegram_attachment_response) expect(telegram_channel.send_message_on_telegram(message)).to eq('telegram_456') end + + it 'send image failed' do + telegram_attachment_response = double + attachment = message.attachments.new(account_id: message.account_id, file_type: :image) + attachment.file.attach(io: Rails.root.join('spec/assets/avatar.png').open, filename: 'avatar.png', content_type: 'image/png') + + allow(telegram_attachment_response).to receive(:success?).and_return(false) + allow(telegram_attachment_response).to receive(:parsed_response).and_return({ 'ok' => false, 'error_code' => '400', + 'description' => 'Bad Request: invalid file id' }) + allow(telegram_channel).to receive(:attachments_request).and_return(telegram_attachment_response) + telegram_channel.send_message_on_telegram(message) + expect(message.reload.status).to eq('failed') + expect(message.reload.external_error).to eq('400: Bad Request: invalid file id') + end end context 'when a valid message and valid attachment' do