Skip to content

feat: adiciona endpoints de status do WhatsApp para texto, imagem e vídeo#15

Open
Eduardo-gato wants to merge 3 commits intoEvolutionAPI:mainfrom
Eduardo-gato:main
Open

feat: adiciona endpoints de status do WhatsApp para texto, imagem e vídeo#15
Eduardo-gato wants to merge 3 commits intoEvolutionAPI:mainfrom
Eduardo-gato:main

Conversation

@Eduardo-gato
Copy link
Copy Markdown

@Eduardo-gato Eduardo-gato commented Apr 5, 2026

Description

This PR adds support for sending WhatsApp status (stories) to status@broadcast, including text, images, and video status updates.

Features Added:

  • POST /send/status/text - Send text status to WhatsApp
  • POST /send/status/media - Send image/video status (supports JSON with URL and multipart/form-data)
  • Proper WhatsApp upload with encryption
  • HTTP status code validation for URL downloads
  • Swagger/OpenAPI documentation

Related Issue

Closes #(issue_number)

Type of Change

  • 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 to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement

Testing

  • Manual testing completed
  • Functionality verified in development environment
  • No breaking changes introduced

Screenshots (if applicable)

N/A

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have tested my changes thoroughly
  • Any dependent changes have been merged and published

Summary by Sourcery

Add support for sending WhatsApp status (stories) as text and media messages and expose them via new HTTP endpoints.

New Features:

  • Introduce service methods and data structures to send WhatsApp text and media status messages to status@broadcast.
  • Expose POST /send/status/text and POST /send/status/media endpoints to send text and image/video status updates, supporting both URL-based and multipart file uploads.
  • Emit webhook and queue events for sent status messages using the existing messaging infrastructure.

Enhancements:

  • Extend Swagger/OpenAPI documentation with schemas and operation definitions for the new status text and media endpoints.

Build:

  • Add a docker-compose.run.yml file to simplify running the application with a Postgres dependency in a local or runtime environment.

Evolution API Dev added 2 commits April 5, 2026 11:14
- Add POST /send/status/text endpoint for sending text status
- Add POST /send/status/media endpoint for sending image/video status
- Support both JSON (URL) and multipart/form-data (file upload)
- Use Upload() with encryption for proper WhatsApp status format
- Add HTTP status code validation for URL downloads
- Add docker-compose.run.yml for local development
- Add OpenAPI docs for POST /send/status/text
- Add OpenAPI docs for POST /send/status/media (supports JSON and multipart)
- Add StatusTextStruct and StatusMediaStruct definitions
- Add Swagger annotations to handler functions
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 5, 2026

Reviewer's Guide

Adds WhatsApp Status (stories) sending support (text and image/video) via new service methods, HTTP handlers, routes, and Swagger documentation, plus a compose file to run the app locally with Postgres.

Sequence diagram for sending WhatsApp media status via URL

sequenceDiagram
    actor ApiClient
    participant GinRouter
    participant SendHandler
    participant SendService
    participant WhatsmeowClient
    participant WhatsAppServers
    participant WebhookService
    participant GlobalQueue

    ApiClient->>GinRouter: POST /send/status/media (JSON body)
    GinRouter->>SendHandler: SendStatusMedia(ctx)
    SendHandler->>SendHandler: Detect ContentType != multipart/form-data
    SendHandler->>SendHandler: ShouldBindBodyWithJSON(StatusMediaStruct)
    SendHandler->>SendHandler: Validate Url and Type (image/video)
    SendHandler->>SendService: SendStatusMediaUrl(StatusMediaStruct, Instance)

    SendService->>SendService: ensureClientConnected(instance.Id)
    SendService->>ExternalHTTP: GET media URL
    ExternalHTTP-->>SendService: 2xx + file bytes
    SendService->>SendService: sendStatusMedia(client, data, fileData, instance)

    SendService->>WhatsmeowClient: Upload(fileData, MediaImage|MediaVideo)
    WhatsmeowClient-->>SendService: Uploaded info (URL, DirectPath, keys)
    SendService->>WhatsmeowClient: SendMessage(status@broadcast, media, ID)
    WhatsmeowClient-->>WhatsAppServers: Encrypted status message
    WhatsAppServers-->>WhatsmeowClient: Ack (ServerID)
    WhatsmeowClient-->>SendService: Send response

    SendService->>SendService: Build MessageSendStruct
    SendService->>WebhookService: CallWebhook(instance, sendstatus, payload)
    alt Global queues enabled
        SendService->>GlobalQueue: SendToGlobalQueues(SendStatus, payload)
    end
    SendService-->>SendHandler: MessageSendStruct
    SendHandler-->>ApiClient: 200 OK + data
Loading

Updated class diagram for send service and status structs

classDiagram
    class SendService {
        <<interface>>
        SendContact(data *ContactStruct, instance *Instance) (*MessageSendStruct, error)
        SendButton(data *ButtonStruct, instance *Instance) (*MessageSendStruct, error)
        SendList(data *ListStruct, instance *Instance) (*MessageSendStruct, error)
        SendStatusText(data *StatusTextStruct, instance *Instance) (*MessageSendStruct, error)
        SendStatusMediaUrl(data *StatusMediaStruct, instance *Instance) (*MessageSendStruct, error)
        SendStatusMediaFile(data *StatusMediaStruct, fileData []byte, instance *Instance) (*MessageSendStruct, error)
    }

    class sendService {
        clientPointer map[string]*WhatsmeowClient
        whatsmeowService WhatsmeowService
        loggerWrapper LoggerWrapper
        config Config
        SendStatusText(data *StatusTextStruct, instance *Instance) (*MessageSendStruct, error)
        SendStatusMediaUrl(data *StatusMediaStruct, instance *Instance) (*MessageSendStruct, error)
        SendStatusMediaFile(data *StatusMediaStruct, fileData []byte, instance *Instance) (*MessageSendStruct, error)
        sendStatusMedia(client *WhatsmeowClient, data *StatusMediaStruct, fileData []byte, instance *Instance) (*MessageSendStruct, error)
    }

    class StatusTextStruct {
        string Text
        string Id
        int32 Font
        string BackgroundColor
    }

    class StatusMediaStruct {
        string Type
        string Url
        string Caption
        string Id
    }

    class MessageSendStruct {
        MessageInfo Info
        Message Message
        ContextInfo MessageContextInfo
    }

    class SendHandler {
        SendContact(ctx *Context)
        SendButton(ctx *Context)
        SendList(ctx *Context)
        SendStatusText(ctx *Context)
        SendStatusMedia(ctx *Context)
    }

    class Instance {
        string Id
        string Name
        string Token
    }

    class WhatsmeowClient {
        GenerateMessageID() string
        Upload(ctx Context, data []byte, mediaType MediaType) (UploadedMedia, error)
        SendMessage(ctx Context, jid JID, msg Message, extra SendRequestExtra) (SendResponse, error)
    }

    SendService <|.. sendService
    sendService --> StatusTextStruct
    sendService --> StatusMediaStruct
    sendService --> MessageSendStruct
    SendHandler --> SendService
    SendHandler --> StatusTextStruct
    SendHandler --> StatusMediaStruct
    sendService --> WhatsmeowClient
    MessageSendStruct --> Instance
Loading

File-Level Changes

Change Details Files
Introduce service-level support for sending WhatsApp status messages (text and media) to status@broadcast, including upload, validation, and webhook/queue integration.
  • Extend SendService interface with methods to send text status, media status via URL, and media status via file bytes
  • Define StatusTextStruct and StatusMediaStruct DTOs for status payloads
  • Implement SendStatusText to build an ExtendedTextMessage to status@broadcast, generate/fallback message IDs, and dispatch webhooks/global queue events
  • Implement SendStatusMediaUrl to fetch media via HTTP with user-agent and HTTP status validation then delegate to shared media sender
  • Implement SendStatusMediaFile and internal sendStatusMedia helper to validate type, detect and normalize MIME types, upload encrypted media via whatsmeow, construct ImageMessage/VideoMessage, and emit webhooks/queue messages with logging
pkg/sendMessage/service/send_service.go
Expose new HTTP endpoints for sending WhatsApp status text and media, supporting JSON and multipart/form-data, with validation and instance resolution.
  • Extend SendHandler interface with SendStatusText and SendStatusMedia handlers
  • Implement SendStatusText handler: resolve instance from context, bind JSON body, validate required text field, call service, and standardize JSON responses
  • Implement SendStatusMedia handler: branch by content type; for multipart/form-data read form fields and uploaded file, validate type and presence; for JSON validate URL and type, then call corresponding service method; unify success/error responses
pkg/sendMessage/handler/send_handler.go
Wire new status endpoints into the routing layer without JID validation middleware.
  • Register POST /send/status/text and /send/status/media under /message group, bypassing previous TODO for status routes
pkg/routes/routes.go
Document the new status APIs and their payload structures in the generated Swagger/OpenAPI spec.
  • Add /send/status/text and /send/status/media operations with descriptions, parameters, and responses under the Send Message tag
  • Document StatusTextStruct and StatusMediaStruct schemas with field descriptions and required properties in definitions section
  • (Also reintroduces /send/list path definition in docs template, aligning docs with existing handler)
docs/docs.go
Provide a docker-compose file to run the application with Postgres and sane defaults for local testing.
  • Add evolution-go service with environment configuration, volumes, and network, depending on a health-checked Postgres 15-alpine service
  • Configure Postgres service, volumes, ports, and healthcheck for local development
docker-compose.run.yml

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!

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

Copy link
Copy Markdown

@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 - I've found 1 issue, and left some high level feedback:

  • In both SendStatusText and SendStatusMedia handlers you declare var data *StatusTextStruct/*StatusMediaStruct and then call ShouldBindBodyWithJSON(&data), which passes a **T to the binder; switch to using a value (var data StatusTextStruct) or a pointer (data := new(StatusTextStruct)) and pass it directly to avoid incorrect or failed binding.
  • StatusTextStruct exposes font and backgroundColor fields and they are documented in Swagger, but SendStatusText ignores them when building the waE2E message; either apply those fields to the underlying WhatsApp message (if supported) or drop them from the API to avoid confusing clients.
  • The webhook/queue emission and message envelope assembly logic in SendStatusText and sendStatusMedia is almost identical; consider extracting this into a shared helper to reduce duplication and keep future changes to the event payload in one place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In both SendStatusText and SendStatusMedia handlers you declare `var data *StatusTextStruct/*StatusMediaStruct` and then call `ShouldBindBodyWithJSON(&data)`, which passes a `**T` to the binder; switch to using a value (`var data StatusTextStruct`) or a pointer (`data := new(StatusTextStruct)`) and pass it directly to avoid incorrect or failed binding.
- StatusTextStruct exposes `font` and `backgroundColor` fields and they are documented in Swagger, but SendStatusText ignores them when building the waE2E message; either apply those fields to the underlying WhatsApp message (if supported) or drop them from the API to avoid confusing clients.
- The webhook/queue emission and message envelope assembly logic in SendStatusText and sendStatusMedia is almost identical; consider extracting this into a shared helper to reduce duplication and keep future changes to the event payload in one place.

## Individual Comments

### Comment 1
<location path="pkg/sendMessage/service/send_service.go" line_range="249-253" />
<code_context>
 	Cards     []CarouselCardStruct `json:"cards"`
 }

+type StatusTextStruct struct {
+	Text            string `json:"text"`
+	Id              string `json:"id"`
+	Font            int32  `json:"font,omitempty"`
+	BackgroundColor string `json:"backgroundColor,omitempty"`
+}
+
</code_context>
<issue_to_address>
**question (bug_risk):** StatusTextStruct exposes font/backgroundColor but SendStatusText ignores them

`Font` and `BackgroundColor` are documented but never used in `SendStatusText`, which only sets `ExtendedTextMessage.Text`. This mismatch can mislead API consumers about what’s actually supported. Consider either wiring these fields through (if WhatsApp supports them) or removing them from the struct/docs to keep behavior aligned with the API surface.
</issue_to_address>

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.

- Fix binding: use new() instead of var with pointer-to-pointer
- Remove unused font and backgroundColor fields from StatusTextStruct
- Extract webhook/queue logic into shared sendStatusWebhook helper
- Update Swagger docs to reflect StatusTextStruct changes
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.

1 participant