Skip to content

Conversation

@mbap-dev
Copy link
Contributor

No description provided.

joaosouz4dev and others added 26 commits December 27, 2024 10:40
- Update Docker image repository to evoapicloud/evolution-api
- Modify contact email to contato@evolution-api.com
- Update Docker Compose, Dockerfile, and workflow files
- Add Docker image badge to README
- Include additional content creator in README
- Implement message deduplication cache in Baileys service
…leys service

- Refactor edited message detection logic
- Prevent duplicate message processing for edited messages
- Optimize message key caching mechanism
…{baseUrl}}/chat/fetchCatalogs' and '{{baseUrl}}/chat/fetchCollections'
Refactor edit and delete message functionality in BaileyStartupService
Feat: Adicionei suporte para obter o Catálogos de Produtos e as Coleções de Produtos para a versão 2.2.3
…gos de produtos e Coleções evitando alterações desnecessárias em arquivos do repositório
Adicionado suporte para obter Catálogos e Coleções no WhatsApp Business
feat: notconvertsticket for animated stickers
Fix instance creation on v2.2.3
…-location

feat: add message location support whatsapp meta
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 14, 2025

Reviewer's Guide by Sourcery

This pull request introduces several new features and improvements, including message duplication handling, message editing support, fetching product catalogs and collections from WhatsApp Business accounts, location messages, and updates to the Baileys library and Docker configurations. It also adds a new parameter to disable sticker conversion.

Sequence diagram for editing a message

sequenceDiagram
    participant User
    participant Client
    participant PrismaRepository
    participant WhatsApp

    User->>Client: Sends edit message request with data.key
    Client->>WhatsApp: client.sendMessage(jid, options, data.key)
    activate WhatsApp
    WhatsApp-->>Client: Response (success or error)
    deactivate WhatsApp
    alt Response is successful
        Client->>PrismaRepository: Find message by key.id
        activate PrismaRepository
        PrismaRepository-->>Client: Message
        deactivate PrismaRepository

        Client->>PrismaRepository: Update message with edited content and status
        activate PrismaRepository
        PrismaRepository-->>Client: Updated Message
        deactivate PrismaRepository

        Client->>PrismaRepository: Create message update
        activate PrismaRepository
        PrismaRepository-->>Client: Message Update
        deactivate PrismaRepository

        Client->>Client: Send data webhook (Events.MESSAGES_EDITED)
    else Response is an error
        Client-->>User: Error
    end
Loading

Sequence diagram for fetching catalog

sequenceDiagram
    participant Client
    participant WhatsApp

    Client->>WhatsApp: getCatalog({ jid, limit, cursor })
    activate WhatsApp
    WhatsApp-->>Client: Catalog data (products, nextPageCursor)
    deactivate WhatsApp

    loop While fetcherHasMore and countLoops < 4
        Client->>WhatsApp: getCatalog({ jid, limit, cursor: nextPageCursor })
        activate WhatsApp
        WhatsApp-->>Client: Catalog data (products, nextPageCursor)
        deactivate WhatsApp
    end

    Client-->>Client: Returns catalog data
Loading

Sequence diagram for fetching collections

sequenceDiagram
    participant Client
    participant WhatsApp

    Client->>WhatsApp: getCollections(jid, limit)
    activate WhatsApp
    WhatsApp-->>Client: Collections data
    deactivate WhatsApp

    Client-->>Client: Returns collections data
Loading

Class diagram for getCatalogDto

classDiagram
    class getCatalogDto {
        +number?: string
        +limit?: number
        +cursor?: string
    }
Loading

Class diagram for getCollectionsDto

classDiagram
    class getCollectionsDto {
        +number?: string
        +limit?: number
    }
Loading

File-Level Changes

Change Details Files
Implements message duplication handling using a cache to prevent processing the same message multiple times.
  • Adds caching logic to prevent duplicate message processing.
  • Implements caching for message updates to avoid redundant processing.
  • Adds cache keys for messages and message updates using instance ID and message ID.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Adds support for editing messages, including updating the message in the database and sending a webhook event.
  • Implements logic to edit messages via WhatsApp.
  • Updates the message in the database with the edited content and status.
  • Sends a webhook event when a message is edited.
  • Adds validation to prevent editing messages from others or deleted messages.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Adds support for fetching product catalogs and collections from WhatsApp Business accounts.
  • Implements methods to fetch product catalogs and collections.
  • Adds logic to handle pagination for large catalogs.
  • Creates new DTOs for business catalog and collection requests.
  • Introduces a new router and controller for handling business-related requests.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
src/api/routes/business.router.ts
src/validate/business.schema.ts
src/api/controllers/business.controller.ts
src/api/dto/business.dto.ts
Adds support for location messages in the Meta Business Service.
  • Adds a method to process location messages and extract relevant information.
  • Updates the message processing logic to handle location messages.
  • Adds location message type to the renderMessageType method.
src/api/integrations/channel/meta/whatsapp.business.service.ts
Updates the Baileys library version and modifies the Dockerfile and related configurations.
  • Updates the Baileys dependency to a specific commit.
  • Updates the Dockerfile to use a non-cached apk add command and updates the maintainer email.
  • Updates the Docker image names in the GitHub Actions workflows and Docker Swarm configuration.
  • Updates the maintainer email in package.json.
package.json
Dockerfile
.github/workflows/publish_docker_image.yml
.github/workflows/publish_docker_image_homolog.yml
.github/workflows/publish_docker_image_latest.yml
Docker/swarm/evolution_api_v2.yaml
Adds a new parameter to disable sticker conversion.
  • Adds a new parameter to disable sticker conversion.
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
src/api/dto/sendMessage.dto.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@mbap-dev mbap-dev closed this Mar 14, 2025
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @mbap-dev - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a description to the PR to explain the changes made and the purpose of the pull request.
  • It looks like you're adding a lot of new functionality - consider breaking this PR up into smaller chunks.
Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +3960 to +3963
if (!(message.key.valueOf() as any).fromMe) {
new BadRequestException('You cannot edit others messages');
}
if ((message.key.valueOf() as any)?.deleted) {
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): Exceptions for editing non-owned or deleted messages are created but not thrown.

Since these exceptions are merely instantiated without being thrown, the subsequent logic will continue executing. Ensure to throw the exceptions (e.g., using 'throw new BadRequestException(...)') to properly halt execution when needed.


<div align="center">

[![Docker Image (https://img.shields.io/badge/Docker-Image-blue)](https://hub.docker.com/r/evoapicloud/evolution-api)]
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (typo): Typo in Docker Image badge link.

The link text for the Docker Image badge contains a tab character ('\t'). It should be removed.

Suggested change
[![Docker Image (https://img.shields.io/badge/Docker-Image-blue)](https://hub.docker.com/r/evoapicloud/evolution-api)]
[![Docker Image (https://img.shields.io/badge/Docker-Image-blue)](https://hub.docker.com/r/evoapicloud/evolution-api)]

const editedMessage =
received?.message?.protocolMessage || received?.message?.editedMessage?.message?.protocolMessage;

if (received.message?.protocolMessage?.editedMessage || received.message?.editedMessage?.message) {
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (complexity): Consider extracting common logic into helper functions to reduce code duplication and improve readability by centralizing caching and cursor decoding operations.

Consider extracting some common logic into small helper functions. For example, the duplicated caching logic for duplicate messages can be centralized. Instead of repeatedly doing:

  const messageKey = `${this.instance.id}_${received.key.id}`;
  const cached = await this.baileysCache.get(messageKey);
  if (cached && !editedMessage) {
    this.logger.info(`Message duplicated ignored: ${received.key.id}`);
    continue;
  }
  await this.baileysCache.set(messageKey, true, 30 * 60);

You could extract it into a helper:

```ts
private async isDuplicateMessage(key: string, editedMessage?: any): Promise<boolean> {
  const messageKey = `${this.instance.id}_${key}`;
  const cached = await this.baileysCache.get(messageKey);
  if (cached && !editedMessage) return true;
  await this.baileysCache.set(messageKey, true, 30 * 60);
  return false;
}

And then use it as:

if (await this.isDuplicateMessage(received.key.id, editedMessage)) {
  this.logger.info(`Message duplicated ignored: ${received.key.id}`);
  continue;
}

Similarly, for the catalog fetching while-loop where JSON parsing and Base64 decoding are intertwined, extract the cursor decoding into its own method:

private decodeCursor(cursor?: string): any {
  if (!cursor) return null;
  try {
    const jsonCursor = JSON.parse(atob(cursor));
    return jsonCursor.pagination_cursor ? JSON.parse(atob(jsonCursor.pagination_cursor)) : null;
  } catch (error) {
    this.logger.error("Error decoding cursor", error);
    return null;
  }
}

Then in your loop:

let nextPageCursorJson = nextPageCursor ? JSON.parse(atob(nextPageCursor)) : null;
let pagination = this.decodeCursor(nextPageCursor);

These refactorings keep the main flow clearer while preserving functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants