Conversation
Reviewer's GuideImplements enhanced media sending by flagging MP4s sourced from GIF URLs for GIF-like video playback, extending sticker sending to support video-to-animated-WebP conversion with optional background removal via a transparentColor parameter, and updating API docs accordingly. Sequence diagram for sending animated video sticker with transparent backgroundsequenceDiagram
actor Client
participant API as HTTP_API
participant Service as sendService
participant Conv as convertToWebP
participant VidConv as convertVideoToWebP
participant FF as ffmpeg
participant WA as WhatsApp_Server
Client->>API: POST /send/sticker {number, sticker URL, transparentColor}
API->>Service: SendSticker(StickerStruct)
alt Sticker is URL
Service->>Conv: convertToWebP(stickerURL, transparentColor)
Conv->>API: http.Get(stickerURL)
API-->>Conv: Response body bytes
Conv->>Conv: Detect MIME type
alt MIME is video/mp4
Conv->>VidConv: convertVideoToWebP(data, transparentColor)
VidConv->>FF: run ffmpeg with colorkey and base filters
FF-->>VidConv: animated WebP file
VidConv-->>Conv: webpData []byte
else MIME is image (jpeg/png/jpg)
Conv->>Conv: Decode image and encode to WebP
end
Conv-->>Service: webpData []byte
end
Service->>WA: Send sticker message with WebP media
WA-->>Service: Message ID
Service-->>API: MessageSendStruct
API-->>Client: 200 OK with message info
Class diagram for enhanced media sending and sticker conversionclassDiagram
class sendService {
+sendMediaFileWithRetry(data MediaStruct, fileData []byte, instance instance_model.Instance) MessageSendStruct
+sendMediaUrlWithRetry(data MediaStruct, instance instance_model.Instance) MessageSendStruct
+SendSticker(data StickerStruct, instance instance_model.Instance) MessageSendStruct
}
class StickerStruct {
+string Number
+string Sticker
+string Id
+int32 Delay
+[]string MentionedJID
+bool MentionAll
+*bool FormatJid
+string TransparentColor
+QuotedStruct Quoted
}
class MediaStruct {
+string Filename
+string Url
+string Caption
}
class waE2EVideoMessage {
+string Caption
+string URL
+string DirectPath
+string Mimetype
+[]byte FileSHA256
+uint64 FileLength
+[]byte FileEncSHA256
+bool GifPlayback
}
class convertToWebP {
+convertToWebP(imageDataURL string, transparentColor string) []byte
}
class convertVideoToWebP {
+convertVideoToWebP(inputData []byte, transparentColor string) []byte
}
sendService --> StickerStruct : uses
sendService --> MediaStruct : uses
sendService --> waE2EVideoMessage : builds
sendService --> convertToWebP : calls
convertToWebP --> convertVideoToWebP : calls
class ffmpegProcess {
+string inputPath
+string outputPath
+string filters
}
convertVideoToWebP --> ffmpegProcess : spawns
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 security issue, 3 other issues, and left some high level feedback:
Security issues:
- Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource. (link)
General comments:
- The
isGifdetection forGifPlaybackcurrently relies only on.gifsuffix inFilename/Url; consider basing this on the actual content type (e.g., via existing upload metadata or MIME sniffing) to avoid misclassification when URLs or filenames do not reflect the true media type. - In
convertVideoToWebP/convertToWebP, thetransparentColorparameter is passed directly into thecolorkeyfilter after only stripping#; adding validation (length, hex chars, optional alpha) and normalizing to the exact format FFmpeg expects would make behavior more predictable and avoid subtle filter failures. - The
http.GetinconvertToWebPis a bare call with no timeout or context; using a sharedhttp.Clientwith sensible timeouts (or a context-aware request) would make remote sticker/video conversion more robust against slow or hanging endpoints.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `isGif` detection for `GifPlayback` currently relies only on `.gif` suffix in `Filename`/`Url`; consider basing this on the actual content type (e.g., via existing upload metadata or MIME sniffing) to avoid misclassification when URLs or filenames do not reflect the true media type.
- In `convertVideoToWebP`/`convertToWebP`, the `transparentColor` parameter is passed directly into the `colorkey` filter after only stripping `#`; adding validation (length, hex chars, optional alpha) and normalizing to the exact format FFmpeg expects would make behavior more predictable and avoid subtle filter failures.
- The `http.Get` in `convertToWebP` is a bare call with no timeout or context; using a shared `http.Client` with sensible timeouts (or a context-aware request) would make remote sticker/video conversion more robust against slow or hanging endpoints.
## Individual Comments
### Comment 1
<location path="pkg/sendMessage/service/send_service.go" line_range="1425-1434" />
<code_context>
+func convertVideoToWebP(inputData []byte, transparentColor string) ([]byte, error) {
</code_context>
<issue_to_address>
**issue (bug_risk):** Validate `transparentColor` before using it in the `colorkey` filter to avoid ffmpeg failures.
Currently any `transparentColor` is interpolated directly into `colorkey=0x%s:0.1:0.0`. If the value isn’t a valid hex color (length or characters), ffmpeg will likely fail at runtime. Please validate the cleaned hex (e.g., only `[0-9a-fA-F]`, length 6/8) and either normalize or return a clear error instead of relying on ffmpeg’s failure message.
</issue_to_address>
### Comment 2
<location path="pkg/sendMessage/service/send_service.go" line_range="1493-1499" />
<code_context>
+
+ if mime.Is("image/webp") {
+ return data, nil
+ } else if mime.Is("video/mp4") {
+ return convertVideoToWebP(data, transparentColor)
+ } else if mime.Is("image/jpeg") || mime.Is("image/png") || mime.Is("image/jpg") {
</code_context>
<issue_to_address>
**suggestion:** Consider handling additional common formats (e.g. GIF) or documenting the new "unsupported format" behavior.
This change narrows supported formats to WebP, MP4, and a few image types, and now returns "unsupported format" for everything else. For sticker URLs served as `image/gif`, this is a behavior change from "try to decode whatever `image.Decode` supports" to an explicit failure. If GIF stickers are expected, consider adding GIF support (e.g., via ffmpeg or `image/gif`) or clearly documenting that GIF and similar formats are not supported so callers can handle that case.
```suggestion
mime := mimetype.Detect(data)
// Supported sticker formats:
// - image/webp: returned as-is
// - video/mp4: converted to WebP
// - image/jpeg, image/jpg, image/png, image/gif: decoded and re-encoded as WebP
// Any other MIME type will result in an "unsupported format" error so callers can handle it explicitly.
if mime.Is("image/webp") {
return data, nil
} else if mime.Is("video/mp4") {
return convertVideoToWebP(data, transparentColor)
} else if mime.Is("image/jpeg") || mime.Is("image/png") || mime.Is("image/jpg") || mime.Is("image/gif") {
```
</issue_to_address>
### Comment 3
<location path="pkg/sendMessage/service/send_service.go" line_range="937-939" />
<code_context>
}
mediaType = "ImageMessage"
case "video":
+ isGif := strings.HasSuffix(strings.ToLower(data.Filename), ".gif") || strings.HasSuffix(strings.ToLower(data.Url), ".gif")
if isNewsletter {
media = &waE2E.Message{VideoMessage: &waE2E.VideoMessage{
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Deriving `GifPlayback` from filename/URL extension may be fragile; consider using a more reliable signal.
`isGif` is derived only from `.gif` suffixes on `data.Filename`/`data.Url`, which can fail when filenames are absent, URLs contain query strings, or the extension doesn’t match the actual content type. Since you already have `mimeType` (or can use upload metadata), prefer inferring `GifPlayback` from a trusted MIME/content-type source rather than the path suffix.
```suggestion
case "video":
lowerMimeType := strings.ToLower(mimeType)
isGif := strings.HasPrefix(lowerMimeType, "image/gif") || strings.HasPrefix(lowerMimeType, "video/gif")
if isNewsletter {
```
</issue_to_address>
### Comment 4
<location path="docs/wiki/guias-api/api-messages.md" line_range="380-382" />
<code_context>
SUA-CHAVE-API
</code_context>
<issue_to_address>
**security (curl-auth-header):** Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
*Source: gitleaks*
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Consistently use MIME type for GifPlayback detection. - Add hex color validation for transparent stickers. - Implement timeouts and size limits for sticker conversion. - Use http.Client with timeouts instead of bare http.Get. - Use exec.CommandContext with timeouts for ffmpeg. - Fix security placeholder in docs. - Consolidate changes from fix/sticker-image-decoding branch.
|
This update consolidates the work from the 🛠 Improvements & Fixes:
📁 Branch Consolidation:The |
Introduces several enhancements to media handling:
transparentColorparameter to the sticker endpoint, allowing background removal via FFmpeg colorkey filter.These changes have been in effect in my codebase since december (early acess) - throughly tested.
Related Issue
Closes #5
Type of Change
Testing
Checklist
Summary by Sourcery
Enhance media sending to support GIF-like video playback and richer sticker generation options.
New Features:
Documentation: