Commit Graph

79 Commits

Author SHA1 Message Date
Rodrigo Borba
118f52e239 feat: lead attribution tracking - landing page origin detection
- Cria modelo LeadClick para registrar cliques das landing pages
- Cria modelo LandingHost para mapear hostname → inbox_id
- Endpoint público POST /track/click para receber eventos de clique
- Leads::AttributionMatcherService para correlacionar clique com conversa
- Integração com IncomingMessageWuzapiService para atribuição automática
- API REST para gerenciar LandingHosts por inbox (index/create/destroy)
- UI: nova aba 'Landing Pages' nas configurações da caixa de entrada
- Dashboard API client dedicado (landingHosts.js)
- RuboCop: refatora shift_signature_name, TrackingController, AttributionMatcherService e WuzapiService
2026-03-02 14:40:35 -03:00
Rodrigo Borba
ec6cfc317d fix(whatsapp): restaura attachment_params no PayloadParser para mídia funcionar
O refactoring c48047ba5 removeu attachment_params acidentalmente sem mover
para outro lugar, quebrando o download de áudio, imagem, vídeo e documento.
O método é chamado por incoming_message_wuzapi_service.rb#attach_files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:47:33 -03:00
Rodrigo Borba
e6e4c36525 fix(whatsapp): adiciona método text_content ao PayloadParser e ignora UndecryptableMessage
Corrige NoMethodError que impedia todas as mensagens de texto de chegarem
ao front. O método text_content era chamado mas não existia na classe.

Também adiciona UndecryptableMessage à lista de eventos ignorados para
evitar tentativa de processar mensagens sem conteúdo descriptografável.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:00:52 -03:00
Rodrigo Borba
c48047ba50 refactor(whatsapp): modulariza processamento de mídias e payloads para conformidade com RuboCop 2026-02-28 15:42:50 -03:00
Rodrigo Borba
6b214b38db feat: Adiciona configuração Active Storage proxy, refatora serviço de decriptografia WhatsApp para processar bytes diretamente e ajusta componentes de mídia. 2026-02-28 12:48:17 -03:00
Rodrigo Borba
0e7dc282c4 chore(style): fix rubocop offenses and update typing indicators 2026-02-25 15:06:58 -03:00
Gabriel Jablonski
72354a4459
fix: normalize audio/opus content type to audio/ogg for WhatsApp attachments (#223) 2026-02-24 22:01:18 -03:00
Gabriel Jablonski
ce39e54308
feat: add audio transcoding support for WhatsApp Cloud API (#220)
* feat: add audio transcoding support for WhatsApp Cloud API

- Introduced `Audio::TranscodeService` to handle audio transcoding to OGG/Opus format.
- Updated `Messages::MessageBuilder` to transcode audio attachments based on `transcode_audio` parameter.
- Enhanced `WhatsappCloudService` to normalize audio content types and send voice flag for recorded audio in OGG format.
- Added utility functions for audio conversion in JavaScript.
- Updated Dockerfile to include FFmpeg for audio processing.
- Added tests for audio transcoding and WhatsApp Cloud service interactions.

* feat: enhance audio handling with transcoding support and error management

* feat: improve audio transcoding error handling and enhance audio recording features

* feat: enhance audio transcoding process and error handling for better reliability

* feat: update recorded audio handling to support boolean and array formats
2026-02-22 16:21:50 -03:00
Gabriel Jablonski
b5d3250a2a
feat(baileys): add reply context handling (#196) 2026-01-24 23:37:21 -03:00
Gabriel Jablonski
0de6001b97
feat: add message editing functionality with UI support (#195)
* feat: add message editing functionality with UI support

* feat: enhance message editing with content length validation and context menu adjustments
2026-01-24 23:25:11 -03:00
Gabriel Jablonski
77c90a69ca
feat(whatsapp): delete messages on baileys/zapi providers (#194)
* feat(baileys): implement message deletion functionality

* feat(zapi): add message deletion functionality and corresponding tests

* feat(whatsapp): update message deletion logic for provider compatibility

* feat(whatsapp): enhance message deletion logic to handle missing phone numbers
2026-01-24 22:37:50 -03:00
Muhsin Keloth
990201f697 fix: Remove phone_number_id param from WhatsApp media retrieval for incoming messages (#13319)
Fixes https://github.com/chatwoot/chatwoot/issues/13317
Fixes an issue where WhatsApp attachment messages (images, audio, video,
documents) were failing to download. Messages were being created but
without attachments.

The `phone_number_id` parameter was being passed to the `GET
/<MEDIA_ID>` endpoint when downloading incoming media. According to
Meta's documentation:

> "Note that `phone_number_id` is optional. If included, the request
will only be processed if the business phone number ID included in the
query matches the ID of the business
  phone number **that the media was uploaded on**."

For incoming messages, media is uploaded by the customer, not by the
business phone number. Passing the business's `phone_number_id` causes
validation to fail with error: `Param phone_number_id is not a valid
whatsapp business phone number id ID`

This PR removes the `phone_number_id` parameter from the media URL
request for incoming messages.
2026-01-20 13:38:46 -03:00
Gabriel Jablonski
d94d4370b5
fix: update send_attachment_message to address transcoding requirement (#191) 2026-01-19 15:51:12 -03:00
gabrieljablonski
6ab1898992 Merge branch 'main' into chore/merge-upstream-4.10 2026-01-16 14:01:53 -03:00
Gabriel Jablonski
24d348cdd3
feat: whastapp cloud provider voice notes (#186) 2026-01-15 23:00:30 -03:00
Muhsin Keloth
c483034a07
feat: Add support for sending CSAT surveys via templates (Whatsapp Twilio) (#13143)
Fixes
https://linear.app/chatwoot/issue/CW-6189/support-for-sending-csat-surveys-via-approved-whatsapp

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-13 16:32:02 +04:00
gabrieljablonski
549214e96d Merge branch main into chore/merge-upstream 2025-12-20 12:44:31 -03:00
Gabriel Jablonski
34b5b58d72
fix: improve error handling for Baileys API unavailability (#166) 2025-12-12 11:29:15 -03:00
Gabriel Jablonski
774c168d94
fix: z-api read message (#165)
* fix: z-api read messages

* fix: use threads for parallel requests

* feat: use jobs instead

* fix: refactor ZapiReadMessageJob to use service method for sending read messages
2025-12-12 09:58:12 -03:00
Muhsin Keloth
2bd8e76886
feat: Add backend changes for whatsapp csat template (#12984)
This PR add the backend changes for the feature [sending CSAT surveys
via WhatsApp message templates
](https://github.com/chatwoot/chatwoot/pull/12787)

---------

Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
2025-12-11 16:36:37 +05:30
Gabriel Jablonski
0f56c51e68
fix: log error message when Baileys API is unavailable (#164) 2025-12-09 13:04:50 -03:00
Gabriel Jablonski
797bde6566
feat: implement CSAT message handling in WhatsApp services (#161) 2025-12-02 16:05:39 -03:00
Gabriel Jablonski
c041090675
feat(baileys): upgrade to v7 (#143)
* feat(baileys): upgrade to v7 (#139)

* feat(baileys): v7

* chore(zapi): match baileys changes

* test: fix send on whatsapp spec

* chore: simplify logic and minor fixes

* fix: ensure contact avatar updates when profile picture changes

* chore: add beta release workflow

* feat: enhance contact update logic to handle conflicts in inbox updates (#140)

* feat: update GitHub Actions workflow to trigger on release events and adjust GIT_REF handling

* fix: prevent unique constraint error when LID contact inbox already exists (#141)

* fix: prevent unique constraint error when LID contact inbox already exists

* feat(baileys): handle ephemeral messages
2025-11-13 20:42:08 -03:00
Gabriel Jablonski
63a2c70667
fix(zapi): first connection issues, and merge existing contact on received message (#138)
* fix(zapi): pairing issues on first connection

* fix(zapi): handle existing contact when receiving new message

* refactor: simplify logic
2025-11-06 23:41:58 -03:00
Gabriel Jablonski
8ff5834ee8
fix(zapi): support for LID-only conversations (#123)
* fix: ignore action events

* feat(zapi): allow updating instance ID

* feat: handle `chatLid` field

* test: break down handler specs into separate files

* feat: update send_message method to use recipient_id logic for zapi provider

* fix: use identifier instead of source_id for zapi

* test: fix specs

* feat: prioritize senderName over chatName for contact naming in received callback
2025-10-23 10:12:38 -03:00
gabrieljablonski
8d4a6b856a Merge branch main into chore/merge-upstream-4.7.0 2025-10-16 12:08:20 -03:00
Gabriel Jablonski
4fc80ba4ee
feat(zapi): Z-API integration (#115)
* feat(zapi): connect flow and UI updates

* fix(zapi): re-add manage connection section

* feat(zapi): reply

* feat: send message

* fix: qrcode job logic

* test: qr code job specs

* chore: concurrent index

* chore: whatsapp model minor

* test: message window service specs

* chore: service refactor

* test: zapi service

* chore: zapi beta

* chore: minor fixes

* test: incoming message specs

* chore: minor fixes

* feat: handle status transitions

* test: refactor spec

* test: refactor spec

* chore(z-api): use feature flag

* chore: fix migration name
2025-10-15 16:23:04 -03:00
Gabriel Jablonski
6b7f96dd68
fix: include mimetype in document messages (#116) 2025-09-30 22:38:13 -03:00
Eduardo Policarpo
46b75e1b03
feat(whatsapp): add optional phone_number_id parameter to media retrieval API (#11823)
## Description

This pull request introduces an optional parameter, `phone_number_id`,
to the WhatsApp API call responsible for retrieving media. The addition
of this parameter allows for greater flexibility when interacting with
the WhatsApp API, as it can now accommodate scenarios where specifying a
particular phone number ID is necessary. This change is backward
compatible and does not affect existing functionality if the parameter
is not provided.

Fixes # (issue)

## Type of change

- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

The changes were tested locally by invoking the WhatsApp media retrieval
API with and without the `phone_number_id` parameter. Both scenarios
were verified to ensure that:

- When `phone_number_id` is provided, the API call includes the
parameter and functions as expected.
- When `phone_number_id` is omitted, the API call continues to work as
before, maintaining backward compatibility.

No errors or warnings were observed during testing, and all relevant
unit tests passed successfully.

## Checklist

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-23 09:16:59 +05:30
gabrieljablonski
18c672c204 Merge branch 'main' into chore/merge-upstream-4.6.0 2025-09-19 19:37:28 -03:00
Aguinaldo Tupy
f03a52bd77
feat: Add media_name support for WhatsApp templates document files (#12462)
## Description

This implementation adds support for the `media_name` parameter for
WhatsApp document templates, resolving the issue where documents appear
as "untitled" when sent via templates.

**Problem solved:** Documents sent via WhatsApp templates always
appeared as "untitled" because Chatwoot didn't process the `filename`
field required by the WhatsApp API.

**Solution:** Added support for the `media_name` parameter that maps to
the WhatsApp API's `filename` field.

## Type of change

- [x] New feature (non-breaking change which adds functionality)
- [x] This change requires a documentation update

## How Has This Been Tested?

Created and executed **7 comprehensive test scenarios**:

1.  Document without `media_name` (backward compatibility)
2.  Document with valid `media_name`
3.  Document with blank `media_name`
4.  Document with null `media_name`
5.  Image with `media_name` (ignored as expected)
6.  Video with `media_name` (ignored as expected)
7.  Blank URL (returns nil appropriately)

**All tests passed** and confirmed **100% backward compatibility**.

## Technical Implementation

**Backend Changes:**
- `PopulateTemplateParametersService`: Added `media_name` parameter
support
- `TemplateProcessorService`: Pass `media_name` to parameter builder
- `WhatsappCloudService`: Updated documentation with `media_name`
example

**Frontend Changes:**
- `WhatsAppTemplateParser.vue`: Added UI field for document filename
input
- `templateHelper.js`: Include `media_name` for document templates
- `whatsappTemplates.json`: Added translation key for document name
placeholder

**Key Features:**
- 🔄 **100% Backward Compatible** - Existing templates continue working
- 📝 **Document Filename Support** - Users can specify custom filenames
- 🎯 **Document-Only Feature** - Only affects document media types
-  **Comprehensive Testing** - All edge cases covered

## Expected Behavior

**Before:**
```ruby
# All documents appear as "untitled"
{
  type: 'document',
  document: { link: 'https://example.com/document.pdf' }
}
```

**After:**
```ruby
# With media_name - displays custom filename
{
  type: 'document',
  document: {
    link: 'https://example.com/document.pdf',
    filename: 'Invoice_2025.pdf'
  }
}

# Without media_name - works as before
{
  type: 'document',
  document: { link: 'https://example.com/document.pdf' }
}
```

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-09-18 15:25:31 +05:30
Gabriel Jablonski
6cd0a3bf7f
feat(wa-cloud): reaction messages and meta is_record_audio for voice messages (#111)
* feat: add send_reaction_message method and corresponding tests

* chore: useless comment from previous PR

* feat(wa-cloud): set is_recorded_audio for voice message
2025-09-10 09:02:06 -03:00
Gabriel Jablonski
0b6d943faf
fix(wa-cloud): send status read for typing indicator (#107)
* fix(wa-cloud): send status read for typing indicator

* test(wa-cloud): send status read for typing indicator
2025-09-03 13:36:20 -03:00
Gabriel Jablonski
eaf2f99520
feat: whatsapp cloud service typing status and read messages (#106) 2025-09-02 15:20:13 -03:00
Gabriel Jablonski
9f5c62c724
feat(baileys): add status method to fetch Baileys API version and availability (#104)
* feat(baileys): add status method to fetch Baileys API version and availability

* test: specs

* chore: raise error instead of returning error in version
2025-08-27 13:56:06 -03:00
Gabriel Coelho
d2a0d53fab
feat(whatsapp): get contact profile picture when using Baileys service (#98)
* feat(whatsapp): add profile picture fetching for Baileys provider

- Add `get_profile_pic` method to `WhatsappBaileysService` for fetching contact avatars
- Include `avatar_url` in contact attributes during contact creation
- Update `MessagesUpsert` handler to fetch and set profile pictures
- Add proper error handling and graceful degradation when avatar fetching fails

* test(whatsapp): add test coverage for Baileys profile picture fetching

- Add test suite for `get_profile_pic` method
- Include test scenarios for successful responses, missing avatars, and error handling
- Add profile picture HTTP stubbing and avatar job expectations to message processing tests

* feat(whatsapp): optimize Baileys avatar fetching and update avatar for existing inboxes

Previously, the profile picture was fetched on every incoming message and avatar updates were only attempted for new inboxes.

This change optimizes the process by:
- Only fetching the WhatsApp profile picture if the contact does not already have an avatar.
- Attempting to update the avatar for both new and existing inboxes.

This logic is based on Telegram's version (app/services/telegram/incoming_message_service.rb).

* refactor(whatsapp): remove unnecessary safe navigation when accessing contact

This reverts an unnecessary change introduced in b918a92.

* refactor(whatsapp): manually rollback change introduced in b918a92

* refactor(whatsapp): rename endpoint to profile-picture-url

* refactor(whatsapp): simplify profile picture response handling

Replaced manual JSON parsing with HTTParty's parsed_response and removed redundant JSON parsing tests.

* test(whatsapp): separate avatar processing test from message creation test

* test(whatsapp): update profile picture test to match actual API behavior

Change test to expect a 404 response when no profile picture exists, instead of a 200 response with partial data.

* refactor: move new functions to helper module

* test: more specs

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2025-08-27 13:02:04 -03:00
gabrieljablonski
801033bd5f Merge branch 'main' into chore/merge-upstream-4.5.0 2025-08-20 11:20:31 -03:00
Gabriel Jablonski
99255c199f
feat: on whatsapp baileys check (#95)
* feat: on whatsapp baileys check

* chore: refactoring

* chore: refactoring
2025-08-18 12:41:06 -03:00
Muhsin Keloth
dbb164a37d
fix: Improve WhatsApp template message error handling (#12168)
WhatsApp template message errors were not being properly handled because
the `@message instance` variable was only set in the `send_message`
method but not in `send_template`. When template sending failed, the
`handle_error` method couldn't update the message status due to the
missing @message reference, resulting in silent failures with no user
feedback.
2025-08-12 16:31:56 +05:30
Muhsin Keloth
6784eb9b3d
feat: Enhanced WhatsApp template support with media headers (#11997) 2025-08-11 18:49:05 +05:30
Gabriel Jablonski
11f8aac294
feat: allow non-admin to refresh baileys connection, and automatically setup connection provider on error (#89)
* feat: allow non-admin to refresh baileys connection, and automatically setup connection provider on error

* Update app/javascript/dashboard/components/widgets/conversation/MessagesView.vue

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore: ignore console lint

* feat: handle disconnect errors gracefully and update tests accordingly

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-28 20:20:32 -03:00
gabrieljablonski
4f0b5cd595 Merge branch 'main' into chatwoot/develop 2025-07-16 09:37:08 -03:00
Cayo P. R. Oliveira
6a5c0b515d
fix: send receipt to received messages (#70)
* feat: add received messages handling in WhatsApp services

* feat: ensure received messages are processed in the conversation

* tests: add received messages specs

* tests: add spec for call provider received_messages after save incoming message

* test: add spec to prevent calling received_messages for outgoing messages

* feat: add received_messages to error handling methods

* test: add spec for sending received messages request in WhatsappBaileysService

* fix: update fromMe flag in WhatsappBaileysService

* test: add spec to verify received_messages is not called for protocol messages

* test: improve received_messages stub

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2025-06-17 11:05:28 -03:00
Gabriel Jablonski
3cd273d2d0
chore: fix issues with specs and provider disconnect (#67)
* chore: fix issues with specs and provider disconnect

* test: add expects
2025-06-12 12:14:54 -03:00
João Gabriel Franco
d52f4267ba
feat: Add i18n on whatsapp list button (#10852)
Fixes #10862

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
2025-06-11 22:19:36 -04:00
Muhsin Keloth
f627dbe42d
feat: hide CSAT survey URLs from agents in dashboard (#11622) 2025-06-11 23:39:47 +05:30
Gabriel Jablonski
b7a316fafa
fix: reconnecting deadlock (#66)
* fix: fill whatsapp provider url with value from inbox provider config

* chore: compact blank on setup channel provider

* fix: deadlock on `reconnecting` state
2025-06-11 00:21:19 -03:00
Gabriel Jablonski
6e1da287a2
chore: fix v4.2.0 deployment (#64)
* chore: fix docker compose healthcheck

* fix: compact setup channel provider request
2025-06-09 22:17:54 -03:00
Gabriel Jablonski
e188262877
fix(baileys): race condition send_message/incoming message (#51)
* fix: race condition send_message/incoming message

* fix: handle update race condition as well
2025-05-29 10:43:42 -03:00
Cayo P. R. Oliveira
548c0351ec
Fix/baileys unread message (#50)
* fix: correct structure of lastMessages in message content

* fix: update send_message to store external_created_at timestamp with result from request

* fix: filter incoming messages for unread conversation logic

* fix: improve extraction of message timestamp in send_message method

* feat: enhance message timestamp extraction and update logic in send_message method

* refactor: send_message to improve error handling and update external_created_at timestamp

* chore: move message timestamp extraction to helper

* fix: use message timestamp extract on incoming

* fix: update unread_conversation to handle last message correctly for Baileys provider

---------

Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2025-05-23 17:19:01 -03:00