From e5166b41e4f06f17185da4e8099eb28e83ba74e2 Mon Sep 17 00:00:00 2001 From: Manu Vasconcelos <87862340+vasconsaurus@users.noreply.github.com> Date: Thu, 19 Dec 2024 10:08:51 -0300 Subject: [PATCH] Smooch Bot should not create a relationship between Media and TiplineResource (#2160) We saw an error in Sentry where the creation of a Relationship between a ProjectMedia and a TiplineResource was attempted. The creation fails, but it should not be attempted in the first place. Error - StandardError: Unable to create new relationship as requested: Related items must exist in the same workspace - exception_class: ActiveRecord::RecordInvalid - exception_message: Related items must exist in the same workspace For this to happen - The media can't be of type text, because we do check if it's a ProjectMedia in that case, - it needs to have a caption, - there needs to be an existing ProjectMedia with the same id as the TiplineResource, - if there isn't a ProjectMedia with the same id as the TiplineResource we get a different error: #. Note on the error - The error is rescued, Sentry is notified and it's logged, - so we need to check if Sentry was notified or/and if the error was logged to confirm it happened. Solution We return early, and not even attempt to relate items if `associated` it's not a ProjectMedia, since Relationship's are only for ProjectMedia. Note There was some confusion on the difference between associated and associated_obj: - associated: is the the "first media" and will be the source of the Relationship - associated_obj: is used for TiplineRequest (smooch_resource_id field) References: CV2-5676 PR: 2160 --- app/models/concerns/smooch_messages.rb | 9 ++++++--- test/models/bot/smooch_7_test.rb | 28 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/app/models/concerns/smooch_messages.rb b/app/models/concerns/smooch_messages.rb index 88913b58c..f23daea9c 100644 --- a/app/models/concerns/smooch_messages.rb +++ b/app/models/concerns/smooch_messages.rb @@ -395,6 +395,8 @@ def default_archived_flag end def save_message(message_json, app_id, author = nil, request_type = 'default_requests', associated_id = nil, associated_class = nil) + # associated: is the the "first media" and will be the source of the Relationship + # associated_obj: is used for TiplineRequest (smooch_resource_id field) message = JSON.parse(message_json) return if TiplineRequest.where(smooch_message_id: message['_id']).exists? associated_obj = nil @@ -413,13 +415,13 @@ def save_message(message_json, app_id, author = nil, request_type = 'default_req associated = self.create_project_media_from_message(message) end unless associated.nil? - self.smoooch_post_save_message_actions(message, associated, app_id, author, request_type, associated_obj) + self.smooch_post_save_message_actions(message, associated, app_id, author, request_type, associated_obj) self.smooch_relate_items_for_same_message(message, associated, app_id, author, request_type, associated_obj) end end end - def smoooch_post_save_message_actions(message, associated, app_id, author, request_type, associated_obj) + def smooch_post_save_message_actions(message, associated, app_id, author, request_type, associated_obj) # Remember that we received this message. hash = self.message_hash(message) Rails.cache.write("smooch:message:#{hash}", associated.id) @@ -430,6 +432,7 @@ def smoooch_post_save_message_actions(message, associated, app_id, author, reque end def smooch_relate_items_for_same_message(message, associated, app_id, author, request_type, associated_obj) + return unless associated.is_a?(ProjectMedia) if !message['caption'].blank? # Check if message contains caption then create an item and force relationship self.relate_item_and_text(message, associated, app_id, author, request_type, associated_obj, Relationship.confirmed_type) @@ -455,7 +458,7 @@ def relate_item_and_text(message, associated, app_id, author, request_type, asso message.delete('mediaUrl') target = self.create_project_media_from_message(message) unless target.nil? - smoooch_post_save_message_actions(message, target, app_id, author, request_type, associated_obj) + smooch_post_save_message_actions(message, target, app_id, author, request_type, associated_obj) Relationship.create_unless_exists(associated.id, target.id, relationship_type) end end diff --git a/test/models/bot/smooch_7_test.rb b/test/models/bot/smooch_7_test.rb index 10217674c..a2f17ed9f 100644 --- a/test/models/bot/smooch_7_test.rb +++ b/test/models/bot/smooch_7_test.rb @@ -632,4 +632,32 @@ def teardown end TiplineRequest.any_instance.unstub(:save!) end + + test "should not try to create relationship between media and tipline resource" do + t2 = create_team + pm = create_project_media team: t2 + + t = create_team + tipline_resource = create_tipline_resource team: t + tipline_resource.update_column(:id, pm.id) + + # It should not try to match at all, so we should never get to this notification + CheckSentry.expects(:notify).never + Rails.logger.expects(:notify).never + + Sidekiq::Testing.inline! do + message = { + type: 'video', + source: { type: "whatsapp" }, + text: 'Something', + caption: 'For this to happen, it needs a caption', + mediaUrl: @video_url, + '_id': random_string, + language: 'en', + } + assert_no_difference 'Relationship.count' do + Bot::Smooch.save_message(message.to_json, @app_id, @bot, 'resource_requests', tipline_resource.id, 'TiplineResource') + end + end + end end