8000 feat: messages and contacts history fetch by CayoPOliveira · Pull Request #71 · fazer-ai/chatwoot · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: messages and contacts history fetch #71

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

Open
wants to merge 49 commits into
base: main
Choose a base branch
from

Conversation

CayoPOliveira
Copy link
Collaborator
@CayoPOliveira CayoPOliveira commented Jun 20, 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

  • New Features

    • Added options in WhatsApp channel settings to sync only contacts or both messages and contacts during setup.
    • Introduced advanced synchronization controls in the WhatsApp channel creation interface, allowing for more granular data import.
    • Enabled fetching of historical WhatsApp messages to enhance conversation completeness.
  • Localization

    • Updated English and Portuguese (Brazil) translations to support new WhatsApp synchronization options in the inbox management settings.
  • Enhancements

    • Improved backend support for initial WhatsApp data synchronization, including handling of message and contact history.
    • Added functionality to fetch and process WhatsApp message history with media attachments.
    • Introduced environment variable to configure message history fetch count.
  • Bug Fixes

    • Added control to prevent message flooding validation for specific message processing scenarios.

@CayoPOliveira CayoPOliveira requested a review from Copilot June 20, 2025 12:14
@CayoPOliveira CayoPOliveira self-assigned this Jun 20, 2025
@CayoPOliveira CayoPOliveira added enhancement New feature or request review needed labels Jun 20, 2025
@gabrieljablonski
Copy link
Member

Copy link
coderabbitai bot commented Jun 20, 2025

"""

Walkthrough

This change introduces new WhatsApp synchronization options in the UI and backend, allowing users to choose between syncing only contacts or both messages and contacts. It adds localization keys, updates the Vue component for WhatsApp channel setup, implements backend logic for processing and fetching WhatsApp message history, and integrates these capabilities into the WhatsApp provider and channel models.

Changes

File(s) Change Summary
app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
app/javascript/dashboard/i18n/locale/pt_BR/inboxMgmt.json
Added localization keys for WhatsApp sync options (full history, contacts, messages) in English and Portuguese.
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/BaileysWhatsapp.vue Added UI switches for sync options; updated channel creation logic to include sync flags.
app/services/whatsapp/baileys_handlers/messaging_history_set.rb Introduced module for processing WhatsApp messaging history, contacts, and media attachments.
app/services/whatsapp/incoming_message_baileys_service.rb Included the new MessagingHistorySet module for extended message history handling.
app/services/whatsapp/providers/whatsapp_baileys_service.rb Enhanced provider setup to handle sync flags; added message history fetch method.
app/models/channel/whatsapp.rb Added method to fetch message history by querying oldest message and invoking provider fetch.
app/models/message.rb Added attribute accessor to conditionally skip message flooding prevention validation.
.env.example Added BAILEYS_MESSAGE_HISTORY_COUNT environment variable with default 50.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI (Vue)
    participant Backend (Rails)
    participant WhatsApp Provider

    User->>UI (Vue): Selects WhatsApp sync options (contacts/messages)
    UI (Vue)->>Backend (Rails): Sends channel creation with sync flags
    Backend (Rails)->>Backend (Rails): Processes sync flags in provider config
    Backend (Rails)->>WhatsApp Provider: Sends connection request (with syncFullHistory)
    WhatsApp Provider-->>Backend (Rails): Responds to connection
    Backend (Rails)->>Backend (Rails): If sync enabled, fetches and processes message/contact history
Loading

Possibly related PRs

  • chore: refactor incoming_message_baileys_service using composition and fix some failure points #53: The main PR adds new functionality for syncing full message history and contacts in WhatsApp channels, including new UI controls, provider config flags, message history fetching, and a new messaging history handler module that is included in the IncomingMessageBaileysService, while the retrieved PR refactors the IncomingMessageBaileysService by extracting existing message and connection handling logic into separate handler modules; thus, both PRs modify the IncomingMessageBaileysService by including handler modules but focus on different handler modules and features, making their changes related through the shared refactoring and modularization of message handling logic.

Suggested labels

approved for merge

Suggested reviewers

  • gabrieljablonski

Poem

In the warren of code, new features appear,
WhatsApp sync options, now crystal clear!
Contacts or messages, you get to decide,
With toggles and settings, no need to hide.
Backend and frontend, working as one,
Hopping ahead—our sync has begun!
🐇✨
"""

✨ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 8000 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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 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.

Pull Request Overview

This PR implements a feature to fetch messages and contacts history for WhatsApp using the Baileys provider. Key changes include updating the channel provider setup to support initial sync, adding a new fetch_message_history method, introducing the messaging_history_set handler, and updating the UI and i18n files to accommodate these new sync options.

Reviewed Changes

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

Show a summary per file
File Description
app/services/whatsapp/providers/whatsapp_baileys_service.rb Added initial sync logic and a new fetch_message_history method.
app/services/whatsapp/incoming_message_baileys_service.rb Included the new messaging history handler.
app/services/whatsapp/baileys_handlers/messaging_history_set.rb Introduced messaging history set functionality with several helper methods.
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/BaileysWhatsapp.vue Added UI configuration for sync contacts and full history options.
app/javascript/dashboard/i18n/locale/{pt_BR,en}/inboxMgmt.json Updated localization for new sync options.
Comments suppressed due to low confidence (4)

app/services/whatsapp/baileys_handlers/messaging_history_set.rb:31

  • [nitpick] The local variable name 'phone_number_from_jid' shadows the method name, which may cause confusion. Consider renaming the variable to something like 'contact_phone_number'.
    phone_number_from_jid = phone_number_from_jid(contact[:id])

app/services/whatsapp/providers/whatsapp_baileys_service.rb:175

  • The fetch_message_history method assigns @phone_number to phone_number, but phone_number is not defined in the method. This may lead to a runtime error; consider using the appropriate defined variable (e.g. whatsapp_channel.phone_number).
    @phone_number = phone_number

app/services/whatsapp/baileys_handlers/messaging_history_set.rb:205

  • The variable 'raw_message_id' is used in the log but is not defined in the scope. Replace it with a valid identifier such as raw_message[:key][:id] to correctly log the message ID.
    Rails.logger.error "Failed to download attachment for message #{raw_message_id}: #{e.message}"

app/services/whatsapp/baileys_handlers/messaging_history_set.rb:221

  • The usage of 'raw_message.dig' is incorrect. To safely extract the nested value, change it to raw_message.dig(:message, :documentMessage, :fileName).
    filename = raw_message.dig[:message][:documentMessage][:fileName]

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: 5

🧹 Nitpick comments (5)
app/javascript/dashboard/routes/dashboard/settings/inbox/channels/BaileysWhatsapp.vue (1)

185-211: Consider improving UX for mutually exclusive sync options.

The current implementation shows syncContacts only when syncFullHistory is false, but this might confuse users who don't understand the mutual exclusivity. Consider adding explanatory text or redesigning the UI to make the relationship clearer.

Consider this alternative approach for better UX:

-      <div
-        v-if="!syncFullHistory"
-        class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]"
-      >
-        <label>
-          <div class="flex mb-2 items-center">
-            <span class="mr-2 text-sm">
-              {{
-                $t(
-                  'INBOX_MGMT.ADD.WHATSAPP.SYNC_FULL_HISTORY.ONLY_CONTACTS_LABEL'
-                )
-              }}
-            </span>
-            <Switch id="syncContacts" v-model="syncContacts" />
-          </div>
-        </label>
-      </div>
-      <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
-        <label>
-          <div class="flex mb-2 items-center">
-            <span class="mr-2 text-sm">
-              {{ $t('INBOX_MGMT.ADD.WHATSAPP.SYNC_FULL_HISTORY.LABEL') }}
-            </span>
-            <Switch id="syncFullHistory" v-model="syncFullHistory" />
-          </div>
-        </label>
-      </div>
+      <div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
+        <span class="text-sm text-gray-600 mb-2 block">Sync Options (choose one):</span>
+        <div class="space-y-2">
+          <label class="flex items-center">
+            <input
+              type="radio"
+              :value="false"
+              v-model="syncFullHistory"
+              @change="syncContacts = !syncFullHistory"
+              class="mr-2"
+            />
+            <span class="text-sm">No sync</span>
+          </label>
+          <label class="flex items-center">
+            <input
+              type="radio"
+              :value="true"
+              v-model="syncContacts"
+              @change="if (syncContacts) syncFullHistory = false"
+              class="mr-2"
+            />
+            <span class="text-sm">{{ $t('INBOX_MGMT.ADD.WHATSAPP.SYNC_FULL_HISTORY.ONLY_CONTACTS_LABEL') }}</span>
+          </label>
+          <label class="flex items-center">
+            <input
+              type="radio"
+              :value="true"
+              v-model="syncFullHistory"
+              @change="if (syncFullHistory) syncContacts = false"
+              class="mr-2"
+            />
+            <span class="text-sm">{{ $t('INBOX_MGMT.ADD.WHATSAPP.SYNC_FULL_HISTORY.LABEL') }}</span>
+          </label>
+        </div>
+      </div>
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (4)

1-4: Consider uncommenting or removing the include statements.

The commented-out includes suggest incomplete implementation. If these modules are required for the functionality, uncomment them. Otherwise, remove these lines to avoid confusion.


63-88: Consider refactoring to reduce complexity.

This method has high cyclomatic complexity. Consider using a hash-based approach for cleaner code:

-def message_type(message_content) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength
-  if message_content.key?(:conversation) || message_content.dig(:extendedTextMessage, :text).present?
-    'text'
-  elsif message_content.key?(:imageMessage)
-    'image'
-  elsif message_content.key?(:audioMessage)
-    'audio'
-  elsif message_content.key?(:videoMessage)
-    'video'
-  elsif message_content.key?(:documentMessage) || message_content.key?(:documentWithCaptionMessage)
-    'file'
-  elsif message_content.key?(:stickerMessage)
-    'sticker'
-  elsif message_content.key?(:reactionMessage)
-    'reaction'
-  elsif message_content.key?(:editedMessage)
-    'edited'
-  elsif message_content.key?(:protocolMessage)
-    'protocol'
-  elsif message_content.key?(:messageContextInfo)
-    'context'
-  else
-    'unsupported'
-  end
-end
+MESSAGE_TYPE_MAPPING = {
+  imageMessage: 'image',
+  audioMessage: 'audio',
+  videoMessage: 'video',
+  stickerMessage: 'sticker',
+  reactionMessage: 'reaction',
+  editedMessage: 'edited',
+  protocolMessage: 'protocol',
+  messageContextInfo: 'context'
+}.freeze
+
+def message_type(message_content)
+  return 'text' if message_content.key?(:conversation) || message_content.dig(:extendedTextMessage, :text).present?
+  return 'file' if message_content.key?(:documentMessage) || message_content.key?(:documentWithCaptionMessage)
+  
+  MESSAGE_TYPE_MAPPING.each do |key, type|
+    return type if message_content.key?(key)
+  end
+  
+  'unsupported'
+end

143-149: Simplify conversation retrieval logic.

The nested return statements can be simplified for better readability.

 def get_conversation(contact_inbox)
   return contact_inbox.conversations.last if contact_inbox.inbox.lock_to_single_conversation
 
   # NOTE: if lock to single conversation is disabled, create a new conversation if previous conversation is resolved
-  return contact_inbox.conversations.where.not(status: :resolved).last.presence ||
-         ::Conversation.create!(conversation_params(contact_inbox))
+  active_conversation = contact_inbox.conversations.where.not(status: :resolved).last
+  active_conversation || ::Conversation.create!(conversation_params(contact_inbox))
 end

105-120: Consider implementing the planned refactoring.

The TODO comments indicate these Redis helper methods should be moved to a shared module. This would improve code reusability across the codebase.

Would you like me to help create a shared Redis helper module for these methods or open an issue to track this refactoring task?

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a5c0b5 and 2a33ae7.

📒 Files selected for processing (6)
  • app/javascript/dashboard/i18n/locale/en/inboxMgmt.json (2 hunks)
  • app/javascript/dashboard/i18n/locale/pt_BR/inboxMgmt.json (2 hunks)
  • app/javascript/dashboard/routes/dashboard/settings/inbox/channels/BaileysWhatsapp.vue (3 hunks)
  • app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1 hunks)
  • app/services/whatsapp/incoming_message_baileys_service.rb (1 hunks)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb (2 hunks)
🔇 Additional comments (11)
app/services/whatsapp/incoming_message_baileys_service.rb (1)

5-5: Verify the new module exists and handles messaging history correctly.

The inclusion of Whatsapp::BaileysHandlers::MessagingHistorySet extends this service with message history processing capabilities. Ensure that the module is properly implemented to handle the new sync functionality.

#!/bin/bash
# Verify that the MessagingHistorySet module exists and check its implementation
fd -t f "messaging_history_set.rb" app/services/whatsapp/baileys_handlers/

# Check if the module defines the expected methods
ast-grep --pattern $'module Whatsapp::BaileysHandlers::MessagingHistorySet
  $$$
end'
app/javascript/dashboard/i18n/locale/en/inboxMgmt.json (2)

275-278: LGTM! Well-structured localization keys for sync options.

The new sync-related localization keys follow the established naming conventions and provide clear labels for the contact and message sync functionality.


571-578: LGTM! Comprehensive localization for WhatsApp sync settings.

The settings popup keys provide proper titles, subheaders, and labels for the sync functionality, maintaining consistency with existing WhatsApp configuration options.

app/javascript/dashboard/routes/dashboard/settings/inbox/channels/BaileysWhatsapp.vue (2)

30-31: LGTM! Proper initialization of sync flags.

The boolean data properties are correctly initialized to false, ensuring that sync features are opt-in rather than enabled by default.


58-59: LGTM! Sync flags properly included in provider configuration.

The sync flags are correctly added to the providerConfig object that gets sent to the backend during channel creation.

app/javascript/dashboard/i18n/locale/pt_BR/inboxMgmt.json (2)

275-278: LGTM! Consistent Portuguese translations for sync options.

The Portuguese translations properly correspond to the English localization keys and provide clear labels for the sync functionality.


571-578: LGTM! Complete Portuguese localization for WhatsApp sync settings.

The settings popup translations maintain consistency with the English version and provide appropriate Portuguese text for all sync-related configuration options.

app/services/whatsapp/providers/whatsapp_baileys_service.rb (2)

11-26: LGTM! Well-implemented sync configuration logic.

The sync setup logic correctly:

  • Reads sync flags from provider configuration
  • Determines the sync type based on user selection
  • Resets flags after initial setup to prevent repeated syncing
  • Updates the channel configuration appropriately

The mutual exclusivity is handled properly where sync_contacts takes precedence when both flags are true.


33-36: LGTM! Optimized webhook token access and proper sync parameter.

Good optimization to use the cached provider_config for the webhook verify token instead of accessing whatsapp_channel.provider_config repeatedly. The syncFullHistory parameter correctly reflects the sync requirements.

app/services/whatsapp/baileys_handlers/messaging_history_set.rb (2)

166-174: Well-structured content extraction.

The method effectively handles multiple message types with appropriate fallbacks using the dig method.


19-28: JID parsing methods are correctly implemented.

The methods properly handle WhatsApp JID formats. The planned refactoring to shared helpers will improve code reusability.

Comment on lines 220 to 226
def filename(raw_message, message_mimetype, file_content_type)
filename = raw_message.dig[:message][:documentMessage][:fileName]
return filename if filename.present?

ext = ".#{message_mimetype.split(';').first.split('/').last}" if message_mimetype.present?
"#{file_content_type}_#{raw_message[:key][:id]}_#{Time.current.strftime('%Y%m%d')}#{ext}"
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

Fix syntax error in dig method call.

The dig method is called incorrectly with bracket notation instead of parentheses.

 def filename(raw_message, message_mimetype, file_content_type)
-  filename = raw_message.dig[:message][:documentMessage][:fileName]
+  filename = raw_message.dig(:message, :documentMessage, :fileName)
   return filename if filename.present?
 
   ext = ".#{message_mimetype.split(';').first.split('/').last}" if message_mimetype.present?
   "#{file_content_type}_#{raw_message[:key][:id]}_#{Time.current.strftime('%Y%m%d')}#{ext}"
 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 filename(raw_message, message_mimetype, file_content_type)
filename = raw_message.dig[:message][:documentMessage][:fileName]
return filename if filename.present?
ext = ".#{message_mimetype.split(';').first.split('/').last}" if message_mimetype.present?
"#{file_content_type}_#{raw_message[:key][:id]}_#{Time.current.strftime('%Y%m%d')}#{ext}"
end
def filename(raw_message, message_mimetype, file_content_type)
filename = raw_message.dig(:message, :documentMessage, :fileName)
return filename if filename.present?
ext = ".#{message_mimetype.split(';').first.split('/').last}" if message_mimetype.present?
"#{file_content_type}_#{raw_message[:key][:id]}_#{Time.current.strftime('%Y%m%d')}#{ext}"
end
🤖 Prompt for AI Agents
In app/services/whatsapp/baileys_handlers/messaging_history_set.rb around lines
220 to 226, the dig method is incorrectly called using bracket notation instead
of parentheses. Replace the square brackets after dig with parenthese
8000
s to
correctly access nested hash keys, changing
raw_message.dig[:message][:documentMessage][:fileName] to
raw_message.dig(:message, :documentMessage, :fileName).

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: 1

♻️ Duplicate comments (1)
app/services/whatsapp/baileys_handlers/messaging_h 628C istory_set.rb (1)

221-221: Fix incorrect key name for document filename.

The key :history_filename appears to be incorrect based on WhatsApp Baileys API structure.

The key should be :fileName according to the WhatsApp Baileys API:

-filename = raw_message[:message][:documentMessage][:history_filename]
+filename = raw_message.dig(:message, :documentMessage, :fileName)
🧹 Nitpick comments (5)
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (5)

1-1: Module complexity could be reduced through better separation of concerns.

This module is quite large and handles multiple responsibilities (contact creation, message processing, media handling, Redis caching). Consider splitting into smaller, focused modules.


16-25: Consider consolidating JID handling methods.

The TODO comments indicate these methods will be moved to helpers, but they're currently duplicated across the codebase.

Would you like me to help create a shared JID utilities module to consolidate these methods?


61-85: Refactor complex message type detection method.

The method has high cyclomatic complexity and could benefit from refactoring into a lookup table or strategy pattern.

Consider using a hash-based lookup for better maintainability:

-def history_message_type(message_content)
-  if message_content.key?(:conversation) || message_content.dig(:extendedTextMessage, :text).present?
-    'text'
-  elsif message_content.key?(:imageMessage)
-    'image'
-  # ... more conditions
-  else
-    'unsupported'
-  end
-end
+def history_message_type(message_content)
+  MESSAGE_TYPE_MAPPINGS.each do |key, type|
+    return type if message_content.key?(key)
+  end
+  return 'text' if message_content.dig(:extendedTextMessage, :text).present?
+  'unsupported'
+end
+
+MESSAGE_TYPE_MAPPINGS = {
+  conversation: 'text',
+  imageMessage: 'image',
+  audioMessage: 'audio',
+  # ... etc
+}.freeze

198-199: Fix parameter naming inconsistency.

The parameter name history_filename in the hash conflicts with the method name, creating confusion.

-file: { io: attachment_file, history_filename: history_filename(raw_message, message_mimetype, file_type),
+file: { io: attachment_file, filename: history_filename(raw_message, message_mimetype, file_type),

102-118: Redis key operations could be optimized.

The Redis operations for message caching could be consolidated to reduce the number of Redis calls.

Consider using Redis transactions or pipelining for better performance:

def history_process_message_with_redis(source_id)
  key = format(Redis::RedisKeys::MESSAGE_SOURCE_KEY, id: source_id)
  
  Redis::Alfred.multi do |multi|
    multi.setex(key, true)
    yield if block_given?
    multi.delete(key)
  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 2a33ae7 and a584148.

📒 Files selected for processing (3)
  • .env.example (1 hunks)
  • app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1 hunks)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .env.example
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (6)
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_update.rb:61-61
Timestamp: 2025-05-26T20:14:34.814Z
Learning: In Whatsapp::BaileysHandlers::MessagesUpdate#handle_edited_content, reassigning @raw_message to the nested edited message data is acceptable because this method executes at the end of the corresponding flow, with no subsequent operations depending on the original @raw_message structure.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#20
File: app/services/whatsapp/incoming_message_baileys_service.rb:0-0
Timestamp: 2025-04-08T21:26:26.063Z
Learning: Chatwoot message model (app/models/message.rb) only supports four status states: sent (0), delivered (1), read (2), and failed (3). When mapping from Baileys WhatsApp statuses, only ERROR (0), SERVER_ACK (2), DELIVERY_ACK (3), and READ (4) can be mapped to Chatwoot's statuses. Baileys statuses like PENDING (1) and PLAYED (5) don't have Chatwoot equivalents and should be handled as special cases or logged as unsupported.
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.231Z
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.
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.231Z
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.
🔇 Additional comments (3)
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (3)

135-136: LGTM - Parameter order issue has been resolved.

The method call now correctly matches the parameter order in the method definition.


165-173: Message content extraction aligns with learned patterns.

The content extraction correctly handles only message types that support text content, consistent with previous learnings about WhatsApp Baileys message handling.


209-209: ```shell
#!/bin/bash

Locate the media_url definition and usages for verification

rg -n "def media_url" -C3
rg -n "media_url(" -C3


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

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: 5

🧹 Nitpick comments (1)
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1)

108-110: Remove redundant .presence call on find_by result.

The .presence method is redundant when called on find_by since find_by already returns nil when no record is found.

 def history_find_message_by_source_id(source_id)
   return unless source_id

-  Message.find_by(source_id: source_id).presence
+  Message.find_by(source_id: source_id)
 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 a584148 and 471b441.

📒 Files selected for processing (5)
  • app/javascript/dashboard/i18n/locale/en/inboxMgmt.json (1 hunks)
  • app/javascript/dashboard/i18n/locale/pt_BR/inboxMgmt.json (1 hunks)
  • app/models/channel/whatsapp.rb (1 hunks)
  • app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1 hunks)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/javascript/dashboard/i18n/locale/pt_BR/inboxMgmt.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/javascript/dashboard/i18n/locale/en/inboxMgmt.json
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
app/models/channel/whatsapp.rb (2)
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#20
File: app/services/whatsapp/incoming_message_baileys_service.rb:0-0
Timestamp: 2025-04-08T21:26:26.063Z
Learning: Chatwoot message model (app/models/message.rb) only supports four status states: sent (0), delivered (1), read (2), and failed (3). When mapping from Baileys WhatsApp statuses, only ERROR (0), SERVER_ACK (2), DELIVERY_ACK (3), and READ (4) can be mapped to Chatwoot's statuses. Baileys statuses like PENDING (1) and PLAYED (5) don't have Chatwoot equivalents and should be handled as special cases or logged as unsupported.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_update.rb:61-61
Timestamp: 2025-05-26T20:14:34.814Z
Learning: In Whatsapp::BaileysHandlers::MessagesUpdate#handle_edited_content, reassigning @raw_message to the nested edited message data is acceptable because this method executes at the end of the corresponding flow, with no subsequent operations depending on the original @raw_message structure.
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (4)
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_update.rb:61-61
Timestamp: 2025-05-26T20:14:34.814Z
Learning: In Whatsapp::BaileysHandlers::MessagesUpdate#handle_edited_content, reassigning @raw_message to the nested edited message data is acceptable because this method executes at the end of the corresponding flow, with no subsequent operations depending on the original @raw_message structure.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#20
File: app/services/whatsapp/incoming_message_baileys_service.rb:0-0
Timestamp: 2025-04-08T21:26:26.063Z
Learning: Chatwoot message model (app/models/message.rb) only supports four status states: sent (0), delivered (1), read (2), and failed (3). When mapping from Baileys WhatsApp statuses, only ERROR (0), SERVER_ACK (2), DELIVERY_ACK (3), and READ (4) can be mapped to Chatwoot's statuses. Baileys statuses like PENDING (1) and PLAYED (5) don't have Chatwoot equivalents and should be handled as special cases or logged as unsupported.
🧬 Code Graph Analysis (1)
app/models/channel/whatsapp.rb (1)
app/services/whatsapp/providers/whatsapp_baileys_service.rb (1)
  • fetch_message_history (161-175)
🔇 Additional comments (1)
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1)

194-194: ```shell
#!/bin/bash

Check if MessagingHistorySet class includes the BaileysHelper module

echo "Inspecting the top of messaging_history_set.rb for includes:"
sed -n '1,200p' app/services/whatsapp/baileys_handlers/messaging_history_set.rb

echo -e "\nLooking for explicit inclusion of BaileysHelper across the codebase:"
rg -n "include .*BaileysHelper"


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment on lines 120 to 130
def fetch_message_history
return unless provider_service.respond_to?(:fetch_message_history)

oldest_message = inbox.messages
.where(message_type: %w[incoming outgoing])
.order(Arel.sql("CAST(content_attributes->>'external_created_at' AS BIGINT) ASC"))
.first
return unless oldest_message&.content_attributes&.dig('external_created_at')

provider_service.fetch_message_history(oldest_message)
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

Add error handling for CAST operation and optimize query performance.

The method implementation looks good overall, but consider these improvements:

  1. The CAST(content_attributes->>'external_created_at' AS BIGINT) operation could fail if external_created_at contains non-numeric values, causing a database error.

  2. The query might be slow on large datasets without proper indexing on the JSON field.

 def fetch_message_history
   return unless provider_service.respond_to?(:fetch_message_history)

-  oldest_message = inbox.messages
-                        .where(message_type: %w[incoming outgoing])
-                        .order(Arel.sql("CAST(content_attributes->>'external_created_at' AS BIGINT) ASC"))
-                        .first
+  oldest_message = inbox.messages
+                        .where(message_type: %w[incoming outgoing])
+                        .where.not("content_attributes->>'external_created_at' IS NULL OR content_attributes->>'external_created_at' = ''")
+                        .order(Arel.sql("CAST(content_attributes->>'external_created_at' AS BIGINT) ASC"))
+                        .first

   return unless oldest_message&.content_attributes&.dig('external_created_at')

   provider_service.fetch_message_history(oldest_message)
 end

Consider adding a database index on the JSON field for better performance:

CREATE INDEX idx_messages_external_created_at ON messages 
USING GIN ((content_attributes->>'external_created_at')) 
WHERE message_type IN ('incoming', 'outgoing');
🤖 Prompt for AI Agents
In app/models/channel/whatsapp.rb around lines 120 to 130, the CAST operation on
content_attributes->>'external_created_at' may fail if the value is non-numeric,
causing a database error. To fix this, add error handling to safely handle or
skip invalid values during the query. Additionally, improve query performance on
large datasets by creating a partial GIN index on the JSON field
content_attributes->>'external_created_at' filtered by message_type 'incoming'
and 'outgoing' as suggested, to speed up the ordering and filtering operations.

account_id: inbox.account_id,
inbox_id: inbox.id,
source_id: raw_message[:key][:id],
sender: history_incoming?(raw_message) ? contact_inbox.contact : inbox.account.account_users.first.user,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add safety check for account users to prevent nil reference error.

The code assumes inbox.account.account_users.first.user will always exist, but this could return nil if no account users are present.

 message = conversation.messages.build(
   content: history_message_content(raw_message),
   account_id: inbox.account_id,
   inbox_id: inbox.id,
   source_id: raw_message[:key][:id],
-  sender: history_incoming?(raw_message) ? contact_inbox.contact : inbox.account.account_users.first.user,
+  sender: history_incoming?(raw_message) ? contact_inbox.contact : (inbox.account.account_users.first&.user || contact_inbox.contact),
   sender_type: history_incoming?(raw_message) ? 'Contact' : 'User',
   message_type: history_incoming?(raw_message) ? :incoming : :outgoing,
   content_attributes: history_message_content_attributes(raw_message),
   status: process_status(raw_message[:status]) || 'sent'
 )
🤖 Prompt for AI Agents
In app/services/whatsapp/baileys_handlers/messaging_history_set.rb at line 148,
the code assumes inbox.account.account_users.first.user always exists, which can
cause a nil reference error if account_users is empty. Add a safety check to
verify that account_users.first and its user are present before accessing user,
and provide a fallback value or handle the nil case appropriately to prevent
errors.

Rails.logger.error e.backtrace.join("\n")
end

inbox.channel.fetch_message_history if has_created_new_message
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent potential infinite recursion in message history fetching.

The line inbox.channel.fetch_message_history if has_created_new_message could lead to infinite recursion if the history fetch continues to create new messages that trigger additional history fetches.

Add a mechanism to prevent recursive calls:

- inbox.channel.fetch_message_history if has_created_new_message
+ # Prevent recursive history fetching
+ return if @fetching_history
+ 
+ @fetching_history = true
+ inbox.channel.fetch_message_history if has_created_new_message
+ @fetching_history = false

Or consider using a different approach like queuing the history fetch or adding a cooldown period.

📝 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
inbox.channel.fetch_message_history if has_created_new_message
# Prevent recursive history fetching
return if @fetching_history
@fetching_history = true
inbox.channel.fetch_message_history if has_created_new_message
@fetching_history = false
🤖 Prompt for AI Agents
In app/services/whatsapp/baileys_handlers/messaging_history_set.rb at line 29,
the call to inbox.channel.fetch_message_history if has_created_new_message may
cause infinite recursion by repeatedly triggering new message creations and
subsequent fetches. To fix this, implement a guard mechanism such as a flag or
state variable to track if a fetch is already in progress and prevent re-entry,
or introduce a cooldown timer or queue system to delay or serialize fetch calls,
ensuring fetch_message_history is not called recursively without control.

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

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

147-158: Add safety check for account users to prevent potential nil reference

The code assumes inbox.account.account_users.first.user will always exist, but this could cause a nil reference error if no account users are present.

 message = conversation.messages.build(
   skip_prevent_message_flooding: true,
   content: history_message_content(raw_message),
   account_id: inbox.account_id,
   inbox_id: inbox.id,
   source_id: raw_message[:key][:id],
-  sender: history_incoming?(raw_message) ? contact_inbox.contact : inbox.account.account_users.first.user,
+  sender: history_incoming?(raw_message) ? contact_inbox.contact : (inbox.account.account_users.first&.user || contact_inbox.contact),
   sender_type: history_incoming?(raw_message) ? 'Contact' : 'User',
   message_type: history_incoming?(raw_message) ? :incoming : :outgoing,
   content_attributes: history_message_content_attributes(raw_message),
   status: 'read'
 )
🧹 Nitpick comments (2)
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (2)

45-56: Consider adding phone number validation

The method correctly validates for blank contact ID, but could benefit from additional validation of the extracted phone number to ensure it's valid before creating the contact.

 def create_contact(contact)
   return if contact[:id].blank?

   phone_number = history_phone_number_from_jid(contact[:id])
+  return if phone_number.blank? || phone_number.length < 10
+  
   name = contact[:verifiedName].presence || contact[:notify].presence || contact[:name].presence || phone_number
   ::ContactInboxWithContactBuilder.new(
     # FIXME: update the source_id to complete jid in future
     source_id: phone_number,
     inbox: inbox,
     contact_attributes: { name: name, phone_number: "+#{phone_number}" }
   ).perform
 end

204-210: Status mapping could be more comprehensive

The status mapping only handles three statuses but according to the retrieved learning, Chatwoot supports four status states (sent, delivered, read, failed). Consider adding error status handling.

 def process_status(status)
   {
     'PENDING' => 'sent',
+    'ERROR' => 'failed',
     'DELIVERY_ACK' => 'delivered',
     'READ' => 'read'
-  }[status]
+  }[status] || 'sent'
 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 456ff17 and ffcc625.

📒 Files selected for processing (1)
  • app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (4)
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_update.rb:61-61
Timestamp: 2025-05-26T20:14:34.814Z
Learning: In Whatsapp::BaileysHandlers::MessagesUpdate#handle_edited_content, reassigning @raw_message to the nested edited message data is acceptable because this method executes at the end of the corresponding flow, with no subsequent operations depending on the original @raw_message structure.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#20
File: app/services/whatsapp/incoming_message_baileys_service.rb:0-0
Timestamp: 2025-04-08T21:26:26.063Z
Learning: Chatwoot message model (app/models/message.rb) only supports four status states: sent (0), delivered (1), read (2), and failed (3). When mapping from Baileys WhatsApp statuses, only ERROR (0), SERVER_ACK (2), DELIVERY_ACK (3), and READ (4) can be mapped to Chatwoot's statuses. Baileys statuses like PENDING (1) and PLAYED (5) don't have Chatwoot equivalents and should be handled as special cases or logged as unsupported.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
🔇 Additional comments (5)
app/services/whatsapp/baileys_handlers/messaging_history_set.rb (5)

4-32: LGTM: Well-structured history processing with proper error handling

The main processing method correctly handles both contact sync and message history sync based on provider configuration. The error handling for contact processing is robust, and the conditional logic follows the expected flow.

The commented-out lines at the end appear to be intentionally disabled, likely for testing or gradual rollout purposes.


58-80: Excellent message validation and deduplication logic

The message handling method has comprehensive validation checks and proper Redis-based deduplication. The early returns prevent unnecessary processing and the error handling with Redis cleanup is well implemented.


83-107: Message type detection aligns with content extraction patterns

The message type detection correctly handles all WhatsApp message types and properly categorizes protocol, context, and unsupported messages that should be filtered out. This aligns well with the retrieved learning about content extraction.


133-136: Improved Redis usage with proper options

Good improvement using set with nx and ex options instead of the problematic setex call. This provides proper atomic operation with expiration handling.


187-195: Content extraction follows established patterns correctly

The message content extraction method correctly handles only the message types that have extractable text content, following the retrieved learning about which message types support content extraction (text, image captions, video captions, document captions, and reaction text).

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 2 of 6 files at r1, 1 of 3 files at r2, 2 of 5 files at r3, 4 of 4 files at r5, 1 of 1 files at r6, all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (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.

-work-in-progress +(review needed)

Reviewable status: 7 of 12 files reviewed, all discussions resolved

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)

836-836: Fix the typo in the test description.

-        it 'does not creat contact if do not have id' do
+        it 'does not create contact if it does not have id' do
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ffcc625 and dde9ed4.

📒 Files selected for processing (5)
  • app/services/whatsapp/baileys_handlers/messaging_history_set.rb (1 hunks)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb (3 hunks)
  • spec/models/message_spec.rb (1 hunks)
  • spec/services/whatsapp/incoming_message_baileys_service_spec.rb (1 hunks)
  • spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/services/whatsapp/providers/whatsapp_baileys_service.rb
  • app/services/whatsapp/baileys_handlers/messaging_history_set.rb
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb (4)
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_update.rb:61-61
Timestamp: 2025-05-26T20:14:34.814Z
Learning: In Whatsapp::BaileysHandlers::MessagesUpdate#handle_edited_content, reassigning @raw_message to the nested edited message data is acceptable because this method executes at the end of the corresponding flow, with no subsequent operations depending on the original @raw_message structure.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#20
File: app/services/whatsapp/incoming_message_baileys_service.rb:0-0
Timestamp: 2025-04-08T21:26:26.063Z
Learning: Chatwoot message model (app/models/message.rb) only supports four status states: sent (0), delivered (1), read (2), and failed (3). When mapping from Baileys WhatsApp statuses, only ERROR (0), SERVER_ACK (2), DELIVERY_ACK (3), and READ (4) can be mapped to Chatwoot's statuses. Baileys statuses like PENDING (1) and PLAYED (5) don't have Chatwoot equivalents and should be handled as special cases or logged as unsupported.
spec/services/whatsapp/incoming_message_baileys_service_spec.rb (4)
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_update.rb:61-61
Timestamp: 2025-05-26T20:14:34.814Z
Learning: In Whatsapp::BaileysHandlers::MessagesUpdate#handle_edited_content, reassigning @raw_message to the nested edited message data is acceptable because this method executes at the end of the corresponding flow, with no subsequent operations depending on the original @raw_message structure.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/helpers.rb:59-70
Timestamp: 2025-05-26T20:14:33.151Z
Learning: In WhatsApp Baileys message handling, audio, file, sticker, protocol, and unsupported message types don't have extractable text content. Only text messages, image captions, video captions, and reaction text should be handled in message_content extraction methods.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#20
File: app/services/whatsapp/incoming_message_baileys_service.rb:0-0
Timestamp: 2025-04-08T21:26:26.063Z
Learning: Chatwoot message model (app/models/message.rb) only supports four status states: sent (0), delivered (1), read (2), and failed (3). When mapping from Baileys WhatsApp statuses, only ERROR (0), SERVER_ACK (2), DELIVERY_ACK (3), and READ (4) can be mapped to Chatwoot's statuses. Baileys statuses like PENDING (1) and PLAYED (5) don't have Chatwoot equivalents and should be handled as special cases or logged as unsupported.
Learnt from: CayoPOliveira
PR: fazer-ai/chatwoot#53
File: app/services/whatsapp/baileys_handlers/messages_upsert.rb:7-16
Timestamp: 2025-05-26T20:14:33.177Z
Learning: In the Whatsapp Baileys handlers for this codebase, errors should propagate to the WhatsappController level rather than being caught and handled individually within message processing methods. The user prefers centralized error handling at the controller level over individual message-level error handling.
🧬 Code Graph Analysis (2)
spec/models/message_spec.rb (1)
spec/spec_helper.rb (1)
  • with_modified_env (18-20)
spec/services/whatsapp/incoming_message_baileys_service_spec.rb (3)
app/services/whatsapp/incoming_message_baileys_service.rb (1)
  • perform (9-21)
app/jobs/webhooks/whatsapp_events_job.rb (1)
  • perform (4-19)
db/migrate/20250314185939_add_provider_connection_to_whatsapp.rb (2)
  • change (1-5)
  • change (2-4)
🔇 Additional comments (7)
spec/models/message_spec.rb (1)

42-50: LGTM!

The test correctly verifies that the message flooding validation can be bypassed when skip_prevent_message_flooding is set to true. This is essential for the message history synchronization feature.

spec/services/whatsapp/providers/whatsapp_baileys_service_spec.rb (3)

37-58: LGTM!

The test correctly verifies that when sync_full_history is enabled in the provider config, the request includes syncFullHistory: true.


60-81: Consistent behavior for both sync flags.

The test correctly shows that enabling sync_contacts also triggers syncFullHistory: true in the request, which aligns with the implementation logic.


487-513: Well-structured test for message history fetching.

The test properly mocks the environment variabl 9129 e and verifies that the correct parameters (count, oldestMsgKey, oldestMsgTimestamp) are sent in the request.

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

807-844: Comprehensive tests for contact synchronization.

The tests properly cover the behavior of the sync_contacts flag, including edge cases for non-user JIDs and contacts without IDs. Good test coverage!


846-862: LGTM!

The tests correctly verify that no contacts or messages are created when sync_full_history is disabled.


864-974: Excellent test coverage for full history synchronization!

The tests comprehensively cover:

  • Contact and message creation from history
  • Proper handling of incoming/outgoing messages
  • Unsupported message type handling
  • Filtering of protocol and context messages
  • Duplicate prevention

The decision to set historical messages with status 'read' is appropriate for synced history.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request review needed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0