8000 feat: process Baileys-API images in message.upsert event by CayoPOliveira · Pull Request #26 · fazer-ai/chatwoot · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: process Baileys-API images in message.upsert event #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

CayoPOliveira
Copy link
Collaborator
@CayoPOliveira CayoPOliveira commented Apr 11, 2025

Pull Request Template

Description

Please include a summary of the change and issue(s) fixed. Also, mention relevant motivation, context, and any dependencies that this change requires.
Fixes # (issue)

Type of change

Please delete options that are not relevant.

  • 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?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • 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
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

This change is Reviewable

Summary by CodeRabbit

  • Bug Fixes

    • Updated error handling so that attempts to access non-existent resources now return a "Not Found" status, providing clearer and more accurate feedback.
    • Enhanced validation of file attachment metadata by ensuring filenames and content types are correctly preserved.
  • New Features

    • Introduced functionality to handle multiple message types, including images, files, videos, audio, and stickers, enhancing media attachment capabilities.
    • Improved message content extraction to support various media types, ensuring accurate message processing.
    • Extended message sending to support attachments with detailed error handling and localized unsupported message alerts.
    • Added localized error messages for unsupported message display and sending scenarios.
    • Added automatic channel disconnection logic for specific providers upon channel removal.
  • Tests

    • Expanded test coverage for image, video, file, audio, and sticker messages, validating message creation and media attachment properties.
    • Added comprehensive tests for sending messages with attachments, text messages, unsupported messages, and error handling in message sending.
    • Included tests verifying conditional channel disconnection behavior based on provider type during channel deletion.

@CayoPOliveira CayoPOliveira added enhancement New feature or request work-in-progress wip labels Apr 11, 2025
@CayoPOliveira CayoPOliveira self-assigned this Apr 11, 2025
@Copilot Copilot AI review requested due to automatic review settings April 11, 2025 01:52
Copy link
coderabbitai bot commented Apr 11, 2025

Walkthrough

This pull request modifies the HTTP response status for the MessageNotFoundError exception in the WhatsApp webhook controller. The status code returned from the perform_sync method is changed from :bad_request to :not_found, clarifying the error semantics. Additionally, functionality is introduced to handle multiple message types, including images, videos, files, audio, and stickers, in the handle_create_message method of the IncomingMessageBaileysService. New methods for content extraction, media attachment, file content type determination, and filename generation are added. Corresponding tests are extended to cover these media types and validate attachment properties. The message sending service is refactored to support sending attachments with explicit error handling. Localization files are updated with new error messages for unsupported message display and sending.

Changes

File Change Summary
app/controllers/webhooks/whatsapp_controller.rb Modified the response status in perform_sync for MessageNotFoundError from :bad_request to :not_found; added handling for AttachmentNotFoundError returning :unprocessable_entity.
app/services/whatsapp/incoming_message_baileys_service.rb Added AttachmentNotFoundError exception; extended handle_create_message to support image, file, video, audio, and sticker message types; renamed create_text_message to create_message; added attach_media, message_content, file_content_type, filename, phone_number_from_jid, contact_name, and self_message? methods; improved contact name update logic; added unsupported message handling.
app/services/whatsapp/providers/whatsapp_baileys_service.rb Introduced MessageNotSentError exception; refactored send_message to handle messages with attachments and text separately; added send_attachment_message, send_text_message, and message_content helper methods; improved error handling and message status updates.
spec/models/attachment_spec.rb Added assertions verifying filename and content type preservation for file attachments.
spec/services/whatsapp/incoming_message_baileys_service_spec.rb Added extensive tests for unsupported message handling; added contexts for image, video, file, audio, and sticker message types; verified media attachments, filenames, content types, and captions; added tests for contact name updates and self messages.
spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb Expanded tests for send_message with attachments and text; added error handling tests raising MessageNotSentError; verified request body payloads and message status updates; improved coverage for unsupported messages and provider errors.
config/locales/en.yml Added new error messages for unsupported message display and sending under errors.messages.unsupported and errors.messages.send.unsupported.
config/locales/pt_BR.yml Added Portuguese translations for unsupported message display and sending errors; changed Slack and Google Translate integration descriptions from double to single quotes without content change.

Suggested labels

approved for merge

Suggested reviewers

  • CayoPOliveira

Possibly related PRs

Poem

I hopped through lines of code so bright,
Skipping errors day and night,
When a message went astray,
I set the path a clearer way,
Now with a 404, I cheer with might 🐇!

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 RuboCop (1.73)
app/models/channel/whatsapp.rb

Error: RSpec/FactoryBot/* has been extracted to the rubocop-factory_bot gem.
(obsolete configuration found in .rubocop.yml, please update it)

spec/models/channel/whatsapp_spec.rb

Error: RSpec/FactoryBot/* has been extracted to the rubocop-factory_bot gem.
(obsolete configuration found in .rubocop.yml, please update it)

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at 8000 the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 1 out of 1 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

app/controllers/webhooks/whatsapp_controller.rb:29

  • Verify that using :not_found for MessageNotFoundError aligns with the intended API behavior. If clients are expecting a :bad_request response, consider updating the error handling logic.
head :not_found

Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
app/services/whatsapp/incoming_message_baileys_service.rb (2)

89-92: Image message handling looks good, but consider consistent save pattern

The implementation for handling image messages is correctly structured, creating the text message first, then attaching media, and finally saving the message. However, I noticed that text messages don't have an explicit save! call while image messages do. This inconsistency might indicate that text messages are saved implicitly in the create_text_message method.

Consider making the pattern consistent for all message types to improve maintainability.


172-191: Consider adding file extension based on content type

Currently, the attachment filename doesn't include a file extension, which might cause issues with some clients. Consider adding an appropriate extension ba 8000 sed on the content type.

@message.attachments.new(
  account_id: @message.account_id,
  file_type: file_content_type(message_type),
  file: {
    io: io,
-   filename: "attachment_#{message_id}",
+   filename: "attachment_#{message_id}#{file_extension(message_type)}",
    content_type: file_content_type(message_type)
  }
)

# Add this helper method
def file_extension(type)
  case type
  when 'image'
    '.jpg'
  when 'video'
    '.mp4'
  when 'audio'
    '.ogg'
  when 'document'
    '.bin'
  else
    ''
  end
end
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 066bffb and 6905d36.

📒 Files selected for processing (1)
  • app/services/whatsapp/incoming_message_baileys_service.rb (3 hunks)
🔇 Additional comments (3)
app/services/whatsapp/incoming_message_baileys_service.rb (3)

159-166: Good abstraction with message_content method

Centralizing the logic for extracting message content in a dedicated method is a good approach that makes the code more maintainable and extensible. The case statement makes it easy to add support for more message types in the future.


148-148: LGTM: Refactored to use message_content method

The refactoring to use the new message_content method is a good improvement.


172-191:

❓ Verification inconclusive

Verify the media attachment workflow with tests

This is a significant new feature that processes media attachments. Make sure to add integration or unit tests that verify:

  1. The entire flow from receiving an image message to creating and saving it with attachment
  2. Handling of missing media data
  3. Proper decoding and storage of the media file

To verify how complete the testing coverage is, you can run:


🏁 Script executed:

#!/bin/bash
# Look for tests covering the image handling functionality
rg -A 5 "def test.*image" spec/services/whatsapp/

# Check if there are tests for the new attach_media method
rg -A 5 "attach_media" spec/services/whatsapp/

Length of output: 98


Test Coverage Action Required for Media Attachments

It looks like our automated search didn’t find tests addressing the attach_media method or image-related workflows. Please manually verify whether tests exist elsewhere and, if not, add comprehensive integration or unit tests to cover:

  • The full flow from receiving an image message to creating and saving the attachment.
  • Scenarios where media data is missing.
  • Correct decoding and storage of the media file.

Comment on lines 172 to 191
def attach_media
media = @processed_params.dig(:extra, :media)
return if media.blank?

attachment_payload = media[message_id]
return if attachment_payload.blank?

decoded_data = Base64.decode64(attachment_payload)
io = StringIO.new(decoded_data)

@message.attachments.new(
account_id: @message.account_id,
file_type: file_content_type(message_type),
file: {
io: io,
filename: "attachment_#{message_id}",
content_type: file_content_type(message_type)
}
)
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Verify file_content_type method exists and fix @processed_params reference

There are a couple of potential issues in this method:

  1. The method references file_content_type(message_type) but I don't see this method defined in the class
  2. The variable @processed_params is used, but elsewhere the method processed_params is called instead

Fix the variable reference with this change:

-    media = @processed_params.dig(:extra, :media)
+    media = processed_params.dig(:extra, :media)

Also, please ensure that file_content_type method exists or implement it if missing:

def file_content_type(type)
  case type
  when 'image'
    'image/jpeg' # or use a more specific content type if available from the message
  when 'video'
    'video/mp4'
  when 'audio'
    'audio/ogg'
  when 'document'
    'application/octet-stream'
  else
    'application/octet-stream'
  end
end

🛠️ Refactor suggestion

Consider adding error handling for media processing

The media attachment code lacks error handling for potential failures during Base64 decoding or file attachment. Consider adding rescue blocks to gracefully handle any errors.

def attach_media
  media = processed_params.dig(:extra, :media)
  return if media.blank?

  attachment_payload = media[message_id]
  return if attachment_payload.blank?

  begin
    decoded_data = Base64.decode64(attachment_payload)
    io = StringIO.new(decoded_data)

    @message.attachments.new(
      account_id: @message.account_id,
      file_type: file_content_type(message_type),
      file: {
        io: io,
        filename: "attachment_#{message_id}",
        content_type: file_content_type(message_type)
      }
    )
  rescue => e
    Rails.logger.error "Failed to attach media for message #{message_id}: #{e.message}"
  end
end

Committable suggestion skipped: line range outside the PR's diff.

Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
app/services/whatsapp/incoming_message_baileys_service.rb (1)

159-177: ⚠️ Potential issue

Missing file_content_type method and incorrect variable reference

There are a couple of issues in this method:

  1. The file_content_type method is referenced but not defined
  2. The instance variable @processed_params is used, but elsewhere the method processed_params is called
  3. Missing content_type in the file hash
  4. No error handling for potential Base64 decoding failures

Fix the variable reference and implement the missing method:

def attach_media
-  media = @processed_params.dig(:extra, :media)
+  media = processed_params.dig(:extra, :media)
  return if media.blank?

  attachment_payload = media[message_id]
  return if attachment_payload.blank?

  begin
    decoded_data = Base64.decode64(attachment_payload)
    io = StringIO.new(decoded_data)

    @message.attachments.new(
      account_id: @message.account_id,
      file_type: file_content_type(message_type),
      file: {
        io: io,
-       filename: filename
+       filename: filename,
+       content_type: file_content_type(message_type)
      }
    )
  rescue => e
    Rails.logger.error "Failed to attach media for message #{message_id}: #{e.message}"
  end
end

def file_content_type(type)
  case type
  when 'image'
    'image/png'
  when 'video'
    'video/mp4'
  when 'audio'
    'audio/ogg'
  when 'file', 'document'
    'application/octet-stream'
  when 'sticker'
    'image/webp'
  else
    'application/octet-stream'
  end
end
🧹 Nitpick comments (1)
app/services/whatsapp/incoming_message_baileys_service.rb (1)

87-93: Consider making save behavior consistent across message types

For text messages, you rely on create_message to save the record (which calls create!), but for media messages you explicitly call @message.save! after attaching media. Consider making this behavior consistent to improve code maintainability.

  when 'text'
    create_message
  when 'image', 'file', 'video', 'audio', 'sticker'
    create_message
    attach_media
-   @message.save!
+   @message.save! # This is redundant if you modify attach_media to call save instead
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6905d36 and 2ea106e.

📒 Files selected for processing (3)
  • app/services/whatsapp/incoming_message_baileys_service.rb (3 hunks)
  • spec/models/attachment_spec.rb (1 hunks)
  • spec/services/whatsapp/incoming_message_baileys_service_spec.rb (1 hunks)
🔇 Additional comments (3)
spec/models/attachment_spec.rb (1)

128-129: Good addition to strengthen test validations

These new assertions enhance the test coverage by validating two additional important properties: the filename and content type of the file attachment. This helps ensure that media files processed by the service maintain the expected attributes.

spec/services/whatsapp/incoming_message_baileys_service_spec.rb (2)

323-375: Excellent test coverage for image messages

The test cases for image messages are well-structured and comprehensive. They properly test:

  1. Message creation with captions
  2. Media attachment validation including file type, presence, and filename format

This provides good coverage for the new image handling functionality.


377-429: Good test coverage for video messages

Similar to the image tests, these tests for video messages provide thorough coverage of the video handling functionality, ensuring the caption is properly set and media is correctly attached.

Comment on lines +186 to +195 8000
def message_content
case message_type
when 'text'
@raw_message.dig(:message, :conversation) || @raw_message.dig(:message, :extendedTextMessage, :text)
when 'image'
@raw_message.dig(:message, :imageMessage, :caption)
when 'video'
@raw_message.dig(:message, :videoMessage, :caption)
end
end
Copy link
@coderabbitai coderabbitai bot Apr 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Incomplete message content handling

The message_content method only handles 'text', 'image', and 'video' types, but the handle_create_message method also processes 'file', 'audio', and 'sticker' types. This could lead to nil content for those message types.

def message_content
  case message_type
  when 'text'
    @raw_message.dig(:message, :conversation) || @raw_message.dig(:message, :extendedTextMessage, :text)
  when 'image'
    @raw_message.dig(:message, :imageMessage, :caption)
  when 'video'
    @raw_message.dig(:message, :videoMessage, :caption)
+  when 'file'
+    @raw_message.dig(:message, :documentMessage, :caption)
+  when 'audio'
+    @raw_message.dig(:message, :audioMessage, :caption)
+  when 'sticker'
+    @raw_message.dig(:message, :stickerMessage, :caption)
+  else
+    nil
  end
end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def message_content
case message_type
when 'text'
@raw_message.dig(:message, :conversation) || @raw_message.dig(:message, :extendedTextMessage, :text)
when 'image'
@raw_message.dig(:message, :imageMessage, :caption)
when 'video'
@raw_message.dig(:message, :videoMessage, :caption)
end
end
def message_content
case message_type
when 'text'
@raw_message.dig(:message, :conversation) || @raw_message.dig(:message, :extendedTextMessage, :text)
when 'image'
@raw_message.dig(:message, :imageMessage, :caption)
when 'video'
@raw_message.dig(:message, :videoMessage, :caption)
when 'file'
@raw_message.dig(:message, :documentMessage, :caption)
when 'audio'
@raw_message.dig(:message, :audioMessage, :caption)
when 'sticker'
@raw_message.dig(:message, :stickerMessage, :caption)
else
nil
end
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These types don’t have captions

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@CayoPOliveira Thank you for the clarification. I apologize for the incorrect suggestion. Since these message types (file, audio, sticker) don't have captions in the WhatsApp Baileys API, should they return nil for their message content, or is there another field that should be used instead?


🏁 Script executed:

#!/bin/bash
# Look for any relevant documentation or tests that might show the structure of different message types
cd app || exit
grep -r "documentMessage\|audioMessage\|stickerMessage" --include="*.rb" .
cd ../spec || exit
grep -r "documentMessage\|audioMessage\|stickerMessage" --include="*.rb" .

Length of output: 951


🏁 Script executed:

#!/bin/bash
# Let's look for any tests that might simulate these message types
grep -r "raw_message.*documentMessage\|raw_message.*audioMessage\|raw_message.*stickerMessage" --include="*.rb" .
# Search for test files that might contain examples
find spec -name "*whatsapp*" -o -name "*baileys*" | xargs grep -l "audio\|document\|sticker"
# Let's examine the IncomingMessageBaileysService spec to see how message types are tested
cat spec/services/whatsapp/incoming_message_baileys_service_spec.rb

Length of output: 29681


🏁 Script executed:

#!/bin/bash
# Let's check the Baileys documentation or code to understand message structures
# First, try to find any imported Baileys documentation or type definitions
grep -r "Baileys" --include="*.md" --include="*.js" --include="*.ts" .
# Check if there are any relevant packages in package.json
if [ -f package.json ]; then
  grep -A 10 -B 10 "baileys\|whatsapp" package.json
fi
# Let's look for specific examples in the spec files for the message formats
grep -A 20 "raw_message.*image\|raw_message.*video" --include="*.rb" spec/

Length of output: 802


🏁 Script executed:

#!/bin/bash
# Examine a wider context around where message types are processed
grep -r -A 10 -B 10 "message_type" --include="*.rb" app/services/whatsapp/
# Look at spec file with more context
cat spec/services/whatsapp/incoming_message_baileys_service_spec.rb
# Look for examples of test messages with different types
cd spec
grep -r -B 10 -A 30 "message:" --include="*.rb" .

Length of output: 131070


@CayoPOliveira Thank you for the clarification. I apologize for the incorrect suggestion. Since these message types (file, audio, sticker) don't have captions in the WhatsApp Baileys API, should they return nil for their message content, or is there another field that should be used instead?


🧬 Code Graph Analysis Results

Relevant snippets for app/services/whatsapp/incoming_message_baileys_service.rb


File: app/jobs/webhooks/whatsapp_events_job.rb
Lines: 4-19

def perform(params = {})
  channel = find_channel(params)
  if channel_is_inactive?(channel)
    Rails.logger.warn("Inactive WhatsApp channel: #{channel&.phone_number || "unknown - #{params[:phone_number]}"}")
    return
  end

  case channel.provider
  when 'whatsapp_cloud'
    Whatsapp::IncomingMessageWhatsappCloudService.new(inbox: channel.inbox, params: params).perform
  when 'baileys'
    Whatsapp::IncomingMessageBaileysService.new(inbox: channel.inbox, params: params).perform
  else
    Whatsapp::IncomingMessageService.new(inbox: channel.inbox, params: params).perform
  end
end

This snippet shows how the Whatsapp::IncomingMessageBaileysService is invoked when the provider is baileys. It provides context on how this service fits into the webhook processing flow.


File: app/models/channel/whatsapp.rb
Lines: 65-69

def update_provider_connection!(provider_connection)
  assign_attributes(provider_connection: provider_connection)
  # NOTE: Skip `validate_provider_config?` check
  save!(validate: false)
end

This method is called from process_connection_update in the Baileys service to update the provider connection status on the WhatsApp channel.


Summary of key methods in Whatsapp::IncomingMessageBaileysService (from the provided file):

  • perform: Validates webhook token, dispatches event processing based on event type.
  • process_messages_upsert: Processes incoming messages batch, calls handle_message for each.
  • handle_message: Skips non-user JIDs, deduplicates messages, sets contact and conversation, creates message.
  • set_contact: Parses phone number and push name from JID, creates or updates contact inbox and contact.
  • handle_create_message: Creates message record, attaches media if applicable.
  • message_type: Determines message type from raw message keys (e.g., text, image, video, sticker).
  • message_content: Extracts message content or caption for text, image, video messages.
  • attach_media: Decodes base64 media payload and attaches it to the message.
  • filename: Generates filename for attachments, falling back to a timestamped name.
  • process_messages_update: Handles message updates such as status changes or content edits.
  • update_status: Maps Baileys status codes to internal statuses and updates message status.
  • status_mapper: Maps Baileys numeric status codes to string statuses.
  • status_transition_allowed?: Prevents invalid status transitions (e.g., from read back to sent).
  • Redis caching methods to prevent duplicate message processing.

Note on captions (related to user comment):
The message_content method returns captions for image and video message types by digging into :caption keys inside the raw message. Other media types like file, audio, sticker do not have caption extraction logic here, which aligns with the user comment "These types don’t have captions."


[End of relevant snippets]


✏️ Learnings added
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#26
File: app/services/whatsapp/incoming_message_baileys_service.rb:198-207
Timestamp: 2025-04-16T11:55:12.186Z
Learning: In the WhatsApp Baileys API integration, only 'image' and 'video' message types support captions. The 'file', 'aud
8000
io', and 'sticker' message types do not have caption fields.

Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#26
File: app/services/whatsapp/incoming_message_baileys_service.rb:198-207
Timestamp: 2025-04-16T11:55:12.186Z
Learning: In the WhatsApp Baileys API integration, only 'image' and 'video' message types support captions. The 'file', 'audio', and 'sticker' message types do not have caption fields.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Collaborator Author
@CayoPOliveira CayoPOliveira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-work-in-progress +(review needed)

Reviewed 1 of 3 files at r3, 2 of 2 files at r4, all commit messages.
Reviewable status: 3 of 4 files reviewed, 1 unresolved discussion (waiting on @coderabbitai[bot])

Comment on lines +186 to +195
def message_content
case message_type
when 'text'
@raw_message.dig(:message, :conversation) || @raw_message.dig(:message, :extendedTextMessage, :text)
when 'image'
@raw_message.dig(:message, :imageMessage, :caption)
when 'video'
@raw_message.dig(:message, :videoMessage, :caption)
end
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These types don’t have captions

Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the message creation flow for Baileys-API messages and expands support for processing various media types (images, videos, files, audio, stickers) associated with the messages.upsert event. Key changes include updating the test suite for media attachments, refactoring the message creation and attachment logic, and adjusting the error response code in the WhatsApp controller.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
spec/services/whatsapp/incoming_message_baileys_service_spec.rb Added test cases covering image, video, file, audio, and sticker message scenarios
spec/models/attachment_spec.rb Updated attachment tests to verify filename and content type metadata
app/services/whatsapp/incoming_message_baileys_service.rb Refactored message creation (renamed create_text_message to create_message) and added attach_media
app/controllers/webhooks/whatsapp_controller.rb Adjusted error response to return 404 instead of 400 for MessageNotFoundError

Comment on lines 184 to 188
return :image if %w[image sticker].include?(message_type)
return :audio if ['audio'].include?(message_type)
return :video if ['video'].include?(message_type)

:file
Copy link
Preview
Copilot AI Apr 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file_content_type method returns symbols (e.g., :image, :audio, :video, :file) while the tests expect string values (e.g., 'image', 'audio', 'video', 'file'). Consider converting these symbols to strings for consistency with test expectations.

Suggested change
return :image if %w[image sticker].include?(message_type)
return :audio if ['audio'].include?(message_type)
return :video if ['video'].include?(message_type)
:file
return 'image' if %w[image sticker].include?(message_type)
return 'audio' if ['audio'].include?(message_type)
return 'video' if ['video'].include?(message_type)
'file'

Copilot uses AI. Check for mistakes.

Copy link
Collaborator Author
@CayoPOliveira CayoPOliveira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 1 files at r1.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @gabrieljablonski)

Copy link
Member
@gabrieljablonski gabrieljablonski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-(review needed) +(questions/changes requested)

Reviewed 1 of 1 files at r1, 1 of 3 files at r3, 1 of 2 files at r4, 1 of 1 files at r5, all commit messages.
Dismissed @Copilot from a discussion.
Reviewable status: all files reviewed, 10 unresolved discussions (waiting on @CayoPOliveira)


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 0 at r5 (raw file):
Please attach the source files on Notion, and provide the method you used to encode it to base64.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 357 at r5 (raw file):

        end

        it 'attaches the media with expected behavior' do

NIT

Suggestion:

        it 'creates message attachment' do

spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 376 at r5 (raw file):

          expect(attachment.file.filename.to_s).to eq(filename)
          expect(attachment.file.content_type).to eq(mimetype)
        end
  1. Try using variables more sparingly (don't forget to remove let(:mimetype)
  2. Use freeze_time

Suggestion:

        it 'attaches the media with expected behavior' do
          freeze_time

          described_class.new(inbox: inbox, params: params).perform

          conversation = inbox.conversations.last
          message = conversation.messages.last
          attachment = message.attachments.last

          expect(attachment).to be_present
          expect(attachment.file).to be_present
          expect(attachment.file_type).to eq('image')

          expect(attachment.file.filename.to_s).to eq("image_#{message.id}_#{Time.current.strftime('%Y%m%d')}")
          expect(attachment.file.content_type).to eq('image/png')
        end

spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 379 at r5 (raw file):

      end

      context 'when message type is video' do

Apply suggestions to be consistent with image specs.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 435 at r5 (raw file):

      end

      context 'when message type is file' do

Keep consistent with suggestions for image type.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 477 at r5 (raw file):

      end

      context 'when message type is audio' do

Keep consistent with suggestions for image type.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 524 at r5 (raw file):

      end

      context 'when message type is sticker' do

Keep consistent with suggestions for image type.


app/services/whatsapp/incoming_message_baileys_service.rb line 163 at r5 (raw file):

    attachment_payload = media[message_id]
    return if attachment_payload.blank?

We should raise an error (and log it) and return 422. This shouldn't happen.


app/services/whatsapp/incoming_message_baileys_service.rb line 190 at r5 (raw file):

    :file
  end

NIT

Suggestion:

  def file_content_type
    return :image if message_type.in?(%w[image sticker])
    return :audio if message_type == 'audio'
    return :video if message_type == 'video'

    :file
  end

app/services/whatsapp/incoming_message_baileys_service.rb line 196 at r5 (raw file):

    return filename if filename.present?

    "#{file_content_type}_#{@message[:id]}#{Time.current.strftime('%Y%m%d%H%M%S%s')}"

This timestamp is unnecessarily complex. Date should be good enough.

Also probably best to use _ between id and timestamp.

Suggestion:

    "#{file_content_type}_#{@message[:id]}_#{Time.current.strftime('%Y%m%d')}"

Copy link
Collaborator Author
@CayoPOliveira CayoPOliveira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-(questions/changes requested) +(review needed)

Reviewed all commit messages.
Reviewable status: all files reviewed, 6 unresolved discussions (waiting on @CayoPOliveira and @gabrieljablonski)


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 376 at r5 (raw file):

Previously, gabrieljablonski (Gabriel Jablonski) wrote…
  1. Try using variables more sparingly (don't forget to remove let(:mimetype)
  2. Use freeze_time

Done.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 379 at r5 (raw file):

Previously, gabrieljablonski (Gabriel Jablonski) wrote…

Apply suggestions to be consistent with image specs.

Done.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 435 at r5 (raw file):

Previously, gabrieljablonski (Gabriel Jablonski) wrote…

Keep consistent with suggestions for image type.

Done.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 477 at r5 (raw file):

Previously, gabrieljablonski (Gabriel Jablonski) wrote…

Keep consistent with suggestions for image type.

Done.


spec/services/whatsapp/incoming_message_baileys_service_spec.rb line 524 at r5 (raw file):

Previously, gabrieljablonski (Gabriel Jablonski) wrote…

Keep consistent with suggestions for image type.

Done.

Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
spec/services/whatsapp/incoming_message_baileys_service_spec.rb (1)

323-547: Consider adding error case testing

While the happy path tests are well covered, consider adding tests for error scenarios such as invalid base64 data, missing media information, or unsupported media types to ensure robust error handling.

This could be implemented with contexts like:

context 'when media data is invalid' do
  let(:params) do
    {
      webhookVerifyToken: webhook_verify_token,
      event: 'messages.upsert',
      data: {
        type: 'notify',
        messages: [raw_message]
      },
      extra: {
        media: {
          'msg_123' => 'invalid-base64'
        }
      }
    }
  end

  it 'handles the error gracefully' do
    expect { described_class.new(inbox: inbox, params: params).perform }.not_to raise_error
    # Additional assertions for logging or fallback behavior
  end
end
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea3314a and e05be0e.

📒 Files selected for processing (3)
  • app/controllers/webhooks/whatsapp_controller.rb (1 hunks)
  • app/services/whatsapp/incoming_message_baileys_service.rb (4 hunks)
  • spec/services/whatsapp/incoming_message_baileys_service_spec.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/controllers/webhooks/whatsapp_controller.rb
  • app/services/whatsapp/incoming_message_baileys_service.rb
🔇 Additional comments (5)
spec/services/whatsapp/incoming_message_baileys_service_spec.rb (5)

323-372: Great implementation for image message processing tests!

The test cases for image message processing effectively validate both content and attachment handling. You've properly used freeze_time to ensure consistent filename generation and the assertions cover all critical aspects including file presence, type, filename format, and content type detection.


374-423: Well-structured tests for video messages!

The video message tests are comprehensive, checking both caption handling and attachment properties. The base64 sample data appears valid for testing purposes, and all necessary assertions are in place to verify correct processing.


425-464: Effective file type handling and filename preservation!

The file message tests correctly validate that original filenames are preserved and content types are accurately detected. This is important functionality for document sharing in WhatsApp.


466-506: Audio message tests look good!

The audio message test implementation is well-structured and properly verifies audio file attachment characteristics. The use of freeze_time ensures consistent test behavior for filename generation.


508-547: Correctly handling stickers as image attachments!

The test confirms that stickers are properly treated as image attachments, which aligns with how they should be displayed in the UI. All the necessary properties are verified including file type, content type and filename format.

Copy link
Member
@gabrieljablonski gabrieljablonski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-(review needed) +(questions/changes requested)

Reviewed 3 of 3 files at r6, all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @CayoPOliveira)

Copy link
Collaborator Author
@CayoPOliveira CayoPOliveira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 3 files at r6, all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @CayoPOliveira)

* feat: create alert message for unsupported message types

* chore: fail message when try send not supported type in baileys

* chore: add tests for unsupported message handling in Baileys service

* chore: correct spelling

* chore: NIT in spec name

* chore: remove unnecessary message reload in unsupported message type test

* feat: baileys support to send attachments (#28)

* feat: enhance message sending logic with support for attachments and interactive messages

* fix: update message format to use messageContent for text messages

* feat: attachment message sending

* fix: use strict encoding for attachment file download

* chore: streamline message sending logic and remove unused error classes

* chore: remove type from message sending logic

* chore: update message sending specs

* chore: raise MessageNotSentError instead of updating message status to failed

* chore: change baileys contact name preferences (#30)

* refactor: improve contact name handling and extraction from JID

* test: enhance message handling to update contact names based on pushName and verifiedBizName

* chore: update contact name condition to match phone number from JID

* chore: correct method name typo

* chore: correct variable names for phone number consistency in tests

* chore: update message payload structure and improve error handling in send_message

* test: re-add testing for error handling

* feat: enhance contact name handling and add self-message detection

* fix: ensure presence check for verified business name in contact name retrieval

* test: improve specs

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
Co-authored-by: Gabriel Jablonski <gabriel@fazer.ai>

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
Co-authored-by: Gabriel Jablonski <gabriel@fazer.ai>
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb (1)

183-191: Prefer single source of truth for unsupported-message test

See duplication note above; choose either this block or the earlier one to avoid diverging expectations in future edits.

🧹 Nitpick comments (5)
app/services/whatsapp/providers/whatsapp_baileys_service.rb (2)

40-41: Method exits without feedback to caller

When neither content nor attachments are present the code marks the DB record as failed but does not return any explicit result (nil), whereas the success path returns the WhatsApp message id.
Consider returning a boolean/identifier consistently so that upstream code can rely on it:

-  message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed')
+  message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed')
+  return false

90-111: Edge cases in message_content

  1. fileName is an ActiveStorage::Filename object; convert explicitly to string to avoid JSON serialisation surprises.
  2. If the file_type is not one of the five whitelisted values the payload will miss the actual media key – the provider will reject it but the code won’t notice. Consider guarding with an explicit else-branch:
 content = {
-  fileName: @attachment.file.filename,
+  fileName: @attachment.file.filename.to_s,
   caption:  @message.content
 }
 case @attachment.file_type
 ...
+else
+  raise MessageContentTypeNotSupported, @attachment.file_type
 end
spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb (2)

145-153: Duplicated context – already covered below

This “when message does not have content nor attachments” example is conceptually identical to the block starting at line 183. Keeping both increases test runtime without adding coverage.

Recommend deleting one of them or extracting a shared example.


225-244: Misplaced 5XX-re 10000 sponse scenario

The context “when provider responds with 5XX” lives inside the #validate_provider_config? → when response is unsuccessful branch, but it actually exercises #send_message.
Readers (and future maintainers) will look for send-message-specific failures inside the #send_message describe block.

Move this example under the describe '#send_message' group to keep the spec structure intuitive.

spec/services/whatsapp/incoming_message_baileys_service_spec.rb (1)

376-601: Spec bloating – consider shared examples to DRY up media-type tests

The five media contexts (image, video, file, audio, sticker) repeat the exact Arrange-Act-Assert pattern with only:

• the raw_message inner key
• the expected file_type
• optional caption / filename differences

Extracting a shared example:

shared_examples 'media message' do |media_key, file_type, extra_expectations = {}|
  it "creates #{file_type} attachment" do
    freeze_time
    described_class.new(inbox: inbox, params: params).perform
    attachment = inbox.conversations.last.messages.last.attachments.last
    expect(attachment.file_type).to eq(file_type)
    extra_expectations.call(attachment) if extra_expectations
  end
end

…would shrink the file substantially and improve readability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e05be0e and ec26d01.

📒 Files selected for processing (6)
  • app/services/whatsapp/incoming_message_baileys_service.rb (5 hunks)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb (3 hunks)
  • config/locales/en.yml (1 hunks)
  • config/locales/pt_BR.yml (3 hunks)
  • spec/services/whatsapp/incoming_message_baileys_service_spec.rb (4 hunks)
  • spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • config/locales/pt_BR.yml
  • config/locales/en.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/services/whatsapp/incoming_message_baileys_service.rb

Comment on lines +73 to +88
def send_attachment_message
@attachment = @message.attachments.first

response = HTTParty.post(
"#{provider_url}/connections/#{whatsapp_channel.phone_number}/send-message",
headers: api_headers,
body: {
recipient: @phone_number,
messageContent: message_content
}.to_json
)

return response.parsed_response.dig('data', 'key', 'id') if process_response(response)

raise MessageNotSentError
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Missing timeouts and large-file memory blow-up

  1. HTTParty.post calls do not specify timeout: – a slow provider can block Sidekiq workers indefinitely.
  2. Base64.strict_encode64(@attachment.file.download) loads the full blob into memory. A 20 MB video becomes ~27 MB Base64 string, which might blow the job memory limit.
 response = HTTParty.post(
   "#{provider_url}/connections/#{whatsapp_channel.phone_number}/send-message",
   headers: api_headers,
+  timeout: 15,
   body: {

For large files, stream-encode (e.g. Base64.encode64(IO.read(path, 16.kilobytes))) or enforce a max-size threshold.

Comment on lines 32 to +41
def send_message(phone_number, message)
raise MessageContentTypeNotSupported unless message.content_type == 'text'

response = HTTParty.post(
"#{provider_url}/connections/#{whatsapp_channel.phone_number}/send-message",
headers: api_headers,
body: {
type: 'text',
recipient: phone_number,
message: message.content
}.to_json
)

return unless process_response(response)

response.parsed_response.dig('data', 'key', 'id')
@message = message
@phone_number = phone_number
if message.attachments.present?
send_attachment_message
elsif message.content.present?
send_text_message
else
message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed')
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Attachment-first dispatch silently ignores additional attachments

Only the first attachment (@message.attachments.first) is considered when deciding the branch and when actually building the payload later on.
If a customer sends multiple files (fairly common on WhatsApp), the remaining files will be silently dropped.

-if message.attachments.present?
-  send_attachment_message
+if message.attachments.many?
+  # Iterate and send each attachment or switch to WhatsApp “media-collection” API once it’s supported.
+  message.attachments.each { |att| send_attachment_message(att) }
+elsif message.attachments.one?
+  send_attachment_message(message.attachments.first)

(You would also need to adapt send_attachment_message’s signature accordingly.)

Failing to deliver all media will create confusing UX and support tickets.


🏁 Script executed:

#!/bin/bash
# Locate the send_attachment_message implementation
rg -n "def send_attachment_message" -3 app/services/whatsapp/providers/whatsapp_baileys_service.rb

# See how attachments are accessed in this file
rg -n "attachments\." -n app/services/whatsapp/providers/whatsapp_baileys_service.rb

# Check for explicit use of .first on attachments
rg -n "attachments.first" -n app/services/whatsapp/providers/whatsapp_baileys_service.rb

Length of output: 816


Handle multiple attachments in WhatsApp Baileys service

The current implementation in
app/services/whatsapp/providers/whatsapp_baileys_service.rb
always picks only the first attachment (@message.attachments.first), dropping any additional files. Customers uploading multiple media will see only one file delivered, leading to confusion and extra support work.

Please update as follows:

– In send_message (around line 35), branch on the number of attachments:
many? – iterate over message.attachments and call send_attachment_message(att) for each item (or switch to WhatsApp’s media‐collection API when available)
one? – call send_attachment_message(message.attachments.first)
• else – fall back to the unsupported message error

– Change send_attachment_message to accept an attachment argument instead of relying on @message.attachments.first.

Suggested diff:

-  if message.attachments.present?
-    send_attachment_message
+  if message.attachments.many?
+    message.attachments.each { |att| send_attachment_message(att) }
+  elsif message.attachments.one?
+    send_attachment_message(message.attachments.first)
   elsif message.content.present?
     send_text_message
   else
     message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed')

• Adjust the signature of send_attachment_message to accept attachment and build the payload accordingly.
• Add specs to verify delivery of multiple attachments.

This will ensure all uploaded media reach the recipient.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def send_message(phone_number, message)
raise MessageContentTypeNotSupported unless message.content_type == 'text'
response = HTTParty.post(
"#{provider_url}/connections/#{whatsapp_channel.phone_number}/send-message",
headers: api_headers,
body: {
type: 'text',
recipient: phone_number,
message: message.content
}.to_json
)
return unless process_response(response)
response.parsed_response.dig('data', 'key', 'id')
@message = message
@phone_number = phone_number
if message.attachments.present?
send_attachment_message
elsif message.content.present?
send_text_message
else
message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed')
end
def send_message(phone_number, message)
@message = message
@phone_number = phone_number
if message.attachments.many?
message.attachments.each { |att| send_attachment_message(att) }
elsif message.attachments.one?
send_attachment_message(message.attachments.first)
elsif message.content.present?
send_text_message
else
message.update!(content: I18n.t('errors.messages.send.unsupported'), status: 'failed')
end
end

Copy link
Member
@gabrieljablonski gabrieljablonski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-(questions/changes requested) +(approved for merge)

Reviewed 6 of 6 files at r7, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @CayoPOliveira)

Copy link
Member
@gabrieljablonski gabrieljablonski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dismissed @coderabbitai[bot] from 2 discussions.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @CayoPOliveira)

* fix: ensure proper disconnection of Baileys provider on channel destruction

* test: add callback tests for disconnecting channel provider in Whatsapp spec

* refactor: simplify condition for disconnecting Baileys provider on channel destruction

* refactor: enhance disconnect_channel_provider specs for Baileys provider

* test: verify channel destruction does not call disconnect_channel_provider

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
Copy link
Member
@gabrieljablonski gabrieljablonski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 2 files at r8, all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @CayoPOliveira)

Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
spec/models/channel/whatsapp_spec.rb (1)

65-100: Well-structured and comprehensive test coverage

The tests thoroughly cover the callback behavior, including success and failure scenarios for the Baileys provider and verification that non-Baileys providers don't trigger the callback. This ensures the implementation is robust against API failures.

One suggestion: Consider adding an assertion to verify that the DELETE request is actually made when the provider is 'baileys', using expect(a_request(:delete, disconnect_url)).to have_been_made.once.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec26d01 and 4e86e88.

📒 Files selected for processing (2)
  • app/models/channel/whatsapp.rb (1 hunks)
  • spec/models/channel/whatsapp_spec.rb (1 hunks)
🔇 Additional comments (1)
app/models/channel/whatsapp.rb (1)

40-40: Good addition of provider-specific cleanup on destroy

The conditional before_destroy callback is a good practice for ensuring proper resource cleanup. It correctly targets only the Baileys provider and delegates to the existing provider service method, maintaining separation of concerns.

@gabrieljablonski gabrieljablonski merged commit 8fc1418 into fazer-ai/main Apr 25, 2025
2 checks passed
@gabrieljablonski gabrieljablonski deleted the feat/process-baileys-images-in-message-upsert branch April 25, 2025 19:39
@coderabbitai coderabbitai bot mentioned this pull request Apr 30, 2025
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved for merge enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0