mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	fix: Creates contact when Instagram returns No matching Instagram user (#11496)
				
					
				
			# Creates contact when Instagram returns `No matching Instagram user`
## Description
The error occurs when Facebook tries to validate the Facebook App
created to authorize Instagram integration.
The Facebook's agent uses a Bot to make tests on the App where is not a
valid user via API, returning `{"error"=>{"message"=>"No matching
Instagram user", "type"=>"IGApiException", "code"=>9010}}`.
Then Facebook rejects the request saying this app is still not ready
once the integration with Instagram didn't work.
We can safely create an unknown contact, making this integration work.
## Type of change
Please delete options that are not relevant.
- [X] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
There's automated test to cover.
## Checklist:
- [X] My code follows the style guidelines of this project
- [X] I have performed a self-review of my code
- [X] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [X] I have added tests that prove my fix is effective or that my
feature works
- [X] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
			
			
This commit is contained in:
		| @@ -14,10 +14,11 @@ class Instagram::MessageText < Instagram::BaseMessageText | |||||||
|  |  | ||||||
|     return process_successful_response(response) if response.success? |     return process_successful_response(response) if response.success? | ||||||
|  |  | ||||||
|     handle_error_response(response) |     handle_error_response(response, ig_scope_id) || {} | ||||||
|     {} |  | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   private | ||||||
|  |  | ||||||
|   def process_successful_response(response) |   def process_successful_response(response) | ||||||
|     result = JSON.parse(response.body).with_indifferent_access |     result = JSON.parse(response.body).with_indifferent_access | ||||||
|     { |     { | ||||||
| @@ -32,8 +33,9 @@ class Instagram::MessageText < Instagram::BaseMessageText | |||||||
|     }.with_indifferent_access |     }.with_indifferent_access | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   def handle_error_response(response) |   def handle_error_response(response, ig_scope_id) | ||||||
|     parsed_response = response.parsed_response |     parsed_response = response.parsed_response | ||||||
|  |     parsed_response = JSON.parse(parsed_response) if parsed_response.is_a?(String) | ||||||
|     error_message = parsed_response.dig('error', 'message') |     error_message = parsed_response.dig('error', 'message') | ||||||
|     error_code = parsed_response.dig('error', 'code') |     error_code = parsed_response.dig('error', 'code') | ||||||
|  |  | ||||||
| @@ -50,10 +52,17 @@ class Instagram::MessageText < Instagram::BaseMessageText | |||||||
|     # We can safely ignore this error. |     # We can safely ignore this error. | ||||||
|     return if error_code == 230 |     return if error_code == 230 | ||||||
|  |  | ||||||
|     Rails.logger.warn("[InstagramUserFetchError]: account_id #{@inbox.account_id} inbox_id #{@inbox.id}") |     # The error occurs when Facebook tries to validate the Facebook App created to authorize Instagram integration. | ||||||
|  |     # The Facebook's agent uses a Bot to make tests on the App where is not a valid user via API, | ||||||
|  |     # returning `{"error"=>{"message"=>"No matching Instagram user", "type"=>"IGApiException", "code"=>9010}}`. | ||||||
|  |     # Then Facebook rejects the request saying this app is still not ready once the integration with Instagram didn't work. | ||||||
|  |     # We can safely create an unknown contact, making this integration work. | ||||||
|  |     return unknown_user(ig_scope_id) if error_code == 9010 | ||||||
|  |  | ||||||
|  |     Rails.logger.warn("[InstagramUserFetchError]: account_id #{@inbox.account_id} inbox_id #{@inbox.id} ig_scope_id #{ig_scope_id}") | ||||||
|     Rails.logger.warn("[InstagramUserFetchError]: #{error_message} #{error_code}") |     Rails.logger.warn("[InstagramUserFetchError]: #{error_message} #{error_code}") | ||||||
|  |  | ||||||
|     exception = StandardError.new("#{error_message} (Code: #{error_code})") |     exception = StandardError.new("#{error_message} (Code: #{error_code}, IG Scope ID: #{ig_scope_id})") | ||||||
|     ChatwootExceptionTracker.new(exception, account: @inbox.account).capture_exception |     ChatwootExceptionTracker.new(exception, account: @inbox.account).capture_exception | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -66,4 +75,11 @@ class Instagram::MessageText < Instagram::BaseMessageText | |||||||
|  |  | ||||||
|     Messages::Instagram::MessageBuilder.new(@messaging, @inbox, outgoing_echo: agent_message_via_echo?).perform |     Messages::Instagram::MessageBuilder.new(@messaging, @inbox, outgoing_echo: agent_message_via_echo?).perform | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def unknown_user(ig_scope_id) | ||||||
|  |     { | ||||||
|  |       'name' => "Unknown (IG: #{ig_scope_id})", | ||||||
|  |       'id' => ig_scope_id | ||||||
|  |     }.with_indifferent_access | ||||||
|  |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -33,6 +33,16 @@ class Instagram::Messenger::MessageText < Instagram::BaseMessageText | |||||||
|       return |       return | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     # Handle error code 9010: No matching Instagram user | ||||||
|  |     # This occurs when trying to fetch an Instagram user that doesn't exist or is not accessible | ||||||
|  |     # We can safely ignore this error and return empty result | ||||||
|  |     if error.message.include?('9010') | ||||||
|  |       Rails.logger.warn("[Instagram User Not Found]: account_id #{@inbox.account_id} inbox_id #{@inbox.id}") | ||||||
|  |       Rails.logger.warn("[Instagram User Not Found]: #{error.message}") | ||||||
|  |       Rails.logger.warn("[Instagram User Not Found]: #{error}") | ||||||
|  |       return | ||||||
|  |     end | ||||||
|  |  | ||||||
|     Rails.logger.warn("[FacebookUserFetchClientError]: account_id #{@inbox.account_id} inbox_id #{@inbox.id}") |     Rails.logger.warn("[FacebookUserFetchClientError]: account_id #{@inbox.account_id} inbox_id #{@inbox.id}") | ||||||
|     Rails.logger.warn("[FacebookUserFetchClientError]: #{error.message}") |     Rails.logger.warn("[FacebookUserFetchClientError]: #{error.message}") | ||||||
|     ChatwootExceptionTracker.new(error, account: @inbox.account).capture_exception |     ChatwootExceptionTracker.new(error, account: @inbox.account).capture_exception | ||||||
|   | |||||||
| @@ -279,11 +279,29 @@ describe Webhooks::InstagramEventsJob do | |||||||
|         expect(instagram_inbox.messages.count).to be 0 |         expect(instagram_inbox.messages.count).to be 0 | ||||||
|       end |       end | ||||||
|  |  | ||||||
|       it 'handle messaging_seen callback' do |       it 'handles messaging_seen callback' do | ||||||
|         expect(Instagram::ReadStatusService).to receive(:new).with(params: message_events[:messaging_seen][:entry][0][:messaging][0], |         expect(Instagram::ReadStatusService).to receive(:new).with(params: message_events[:messaging_seen][:entry][0][:messaging][0], | ||||||
|                                                                    channel: instagram_inbox.channel).and_call_original |                                                                    channel: instagram_inbox.channel).and_call_original | ||||||
|         instagram_webhook.perform_now(message_events[:messaging_seen][:entry]) |         instagram_webhook.perform_now(message_events[:messaging_seen][:entry]) | ||||||
|       end |       end | ||||||
|  |  | ||||||
|  |       it 'creates contact when Instagram API call returns `No matching Instagram user` (9010 error code)' do | ||||||
|  |         stub_request(:get, %r{https://graph\.instagram\.com/v22\.0/.*\?.*}) | ||||||
|  |           .to_return(status: 401, body: { error: { message: 'No matching Instagram user', code: 9010 } }.to_json) | ||||||
|  |  | ||||||
|  |         instagram_webhook.perform_now(message_events[:dm][:entry]) | ||||||
|  |  | ||||||
|  |         instagram_inbox.reload | ||||||
|  |  | ||||||
|  |         expect(instagram_inbox.contacts.count).to be 1 | ||||||
|  |         expect(instagram_inbox.contacts.last.name).to eq 'Unknown (IG: Sender-id-1)' | ||||||
|  |         expect(instagram_inbox.contacts.last.contact_inboxes.count).to be 1 | ||||||
|  |         expect(instagram_inbox.contacts.last.contact_inboxes.first.source_id).to eq 'Sender-id-1' | ||||||
|  |  | ||||||
|  |         expect(instagram_inbox.conversations.count).to eq 1 | ||||||
|  |         expect(instagram_inbox.messages.count).to eq 1 | ||||||
|  |         expect(instagram_inbox.messages.last.content_attributes['is_unsupported']).to be_nil | ||||||
|  |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Victor Eduardo
					Victor Eduardo