diff --git a/README.md b/README.md index 74719b2..719dc60 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,9 @@ bot.extend Telegram::Bot::Client::TypedResponse bot.get_me.class # => Telegram::Bot::Types::User ``` +Any API request error will raise `Telegram::Bot::Error` with description in its message. +Special `Telegram::Bot::StaleChat` is raised when bot can't post messages to the chat anymore. + ### Controller ```ruby diff --git a/lib/telegram/bot.rb b/lib/telegram/bot.rb index 27ecba5..001a8f8 100644 --- a/lib/telegram/bot.rb +++ b/lib/telegram/bot.rb @@ -7,6 +7,25 @@ module Telegram class Error < StandardError; end class NotFound < Error; end + # Error class for events when chat is not available anymore for bot. + # While Telegram has same error codes for different messages and there is no + # official docs for this error codes it uses `description` to + # check response. + class StaleChat < Error + DESCRIPTIONS = [ + 'bot was kicked', + "can't write to", + 'group chat is deactivated', + ].freeze + + class << self + def match_response?(response) + description = response['description'].to_s + DESCRIPTIONS.any? { |x| description[x] } + end + end + end + autoload :Client, 'telegram/bot/client' autoload :ClientStub, 'telegram/bot/client_stub' autoload :Middleware, 'telegram/bot/middleware' diff --git a/lib/telegram/bot/client.rb b/lib/telegram/bot/client.rb index d9a2872..1a283a4 100644 --- a/lib/telegram/bot/client.rb +++ b/lib/telegram/bot/client.rb @@ -68,14 +68,17 @@ module Telegram client.debug_dev = nil end - def request(action, body = {}) + def request(action, body = {}) # rubocop:disable PerceivedComplexity res = http_request("#{base_uri}#{action}", self.class.prepare_body(body)) status = res.status return JSON.parse(res.body) if 300 > status result = JSON.parse(res.body) rescue nil # rubocop:disable RescueModifier err_msg = "#{res.reason}: #{result && result['description'] || '-'}" - # NotFound is raised only for valid responses from Telegram - raise NotFound, err_msg if 404 == status && result + if result + # NotFound is raised only for valid responses from Telegram + raise NotFound, err_msg if 404 == status + raise StaleChat, err_msg if StaleChat.match_response?(result) + end raise Error, err_msg end diff --git a/spec/telegram/bot_spec.rb b/spec/telegram/bot_spec.rb index 19a51f4..6213036 100644 --- a/spec/telegram/bot_spec.rb +++ b/spec/telegram/bot_spec.rb @@ -2,4 +2,22 @@ RSpec.describe Telegram::Bot do it 'has a version number' do expect(described_class::VERSION).not_to be nil end + + describe described_class::StaleChat do + describe '.match_response?' do + subject { ->(val) { described_class.match_response?(val) } } + + it 'returns true for specific errors' do + expect(subject.call({})).to eq false + expect(subject.call('description' => 'test')).to eq false + expect(subject.call('description' => 'Error: bot was kicked from')).to eq true + expect(subject.call( + 'description' => "Forbidden: can't write to private chat with deleted user" + )).to eq true + expect(subject.call( + 'description' => 'Bad request: group chat is deactivated' + )).to eq true + end + end + end end