fix(media): fix video file_type fallback and persist fallback_title on attachments (EVO-999)#47
Merged
Conversation
…tachments (EVO-999) - message_type_from_media: fall back to structure-based message_type when Info.MediaType is absent, preventing videos from being stored as file_type=file - create_attachment (evolution_go + evolution handlers): persist fallback_title from generate_filename_with_extension so document filenames are displayed instead of the i18n fallback string Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewer's GuideUpdates WhatsApp Evolution media handling to infer message_type from existing structure when MediaType is missing, and ensures generated filenames are persisted as attachment fallback titles for both Evolution Go and Evolution handlers. Sequence diagram for updated WhatsApp Evolution Go media handling and attachment creationsequenceDiagram
actor WhatsAppUser
participant WhatsAppAPI
participant EvolutionGo
participant MessagesUpsertHandler
participant ActiveStorageBlob
participant AttachmentRecord
WhatsAppUser->>WhatsAppAPI: Send media message (image/video/audio/document)
WhatsAppAPI->>EvolutionGo: Deliver inbound message payload
EvolutionGo->>MessagesUpsertHandler: Call handle_message with info and media
MessagesUpsertHandler->>MessagesUpsertHandler: message_type = message_type
MessagesUpsertHandler->>MessagesUpsertHandler: media_type = evolution_go_info.dig(MediaType)
alt MediaType missing or blank
MessagesUpsertHandler->>MessagesUpsertHandler: struct_type = message_type
MessagesUpsertHandler->>MessagesUpsertHandler: media_type = struct_type == file ? document : struct_type
end
MessagesUpsertHandler->>MessagesUpsertHandler: normalized_type = message_type_from_media(media_type.downcase)
MessagesUpsertHandler->>ActiveStorageBlob: create_before_direct_upload
ActiveStorageBlob-->>MessagesUpsertHandler: blob
MessagesUpsertHandler->>MessagesUpsertHandler: filename = generate_filename_with_extension
MessagesUpsertHandler->>AttachmentRecord: attachments.build(file_type: file_content_type, fallback_title: filename)
AttachmentRecord->>ActiveStorageBlob: file.attach(blob)
Note over AttachmentRecord,WhatsAppUser: Attachment stored with accurate file_type and fallback_title used as UI filename
AttachmentRecord-->>MessagesUpsertHandler: attachment
MessagesUpsertHandler-->>EvolutionGo: message persisted with correct media rendering
EvolutionGo-->>WhatsAppUser: Media appears as image/video/audio/file with filename instead of generic label
Sequence diagram for updated Evolution attachment processor create_attachment flowsequenceDiagram
actor WhatsAppUser
participant EvolutionBackend
participant AttachmentProcessor
participant ActiveStorageBlob
participant AttachmentRecord
WhatsAppUser->>EvolutionBackend: Send media message
EvolutionBackend->>AttachmentProcessor: Process attachment_file
AttachmentProcessor->>ActiveStorageBlob: create_before_direct_upload
ActiveStorageBlob-->>AttachmentProcessor: blob
AttachmentProcessor->>AttachmentProcessor: filename = generate_filename_with_extension
AttachmentProcessor->>AttachmentRecord: attachments.build(file_type: file_content_type, fallback_title: filename)
AttachmentRecord->>ActiveStorageBlob: file.attach(blob)
AttachmentRecord-->>AttachmentProcessor: attachment with fallback_title
AttachmentProcessor-->>EvolutionBackend: attachment ready for message
EvolutionBackend-->>WhatsAppUser: UI shows media bubble with generated filename
Class diagram for updated WhatsApp Evolution media handlersclassDiagram
class MessagesUpsertHandler {
- evolution_go_info
+ file_content_type() String
+ message_type() String
+ message_type_from_media() String
+ generate_filename_with_extension() String
+ create_attachment(attachment_file) Attachment
}
class AttachmentProcessor {
- message
+ file_content_type() String
+ generate_filename_with_extension() String
+ create_attachment(attachment_file) Attachment
}
class Attachment {
+ file_type String
+ fallback_title String
+ file Blob
}
class Message {
+ attachments Attachment[*]
}
class ActiveStorageBlob {
+ create_before_direct_upload(filename, byte_size, checksum, content_type) ActiveStorageBlob
}
MessagesUpsertHandler --> Message : builds
AttachmentProcessor --> Message : builds
Message "1" --> "*" Attachment : has_many
Attachment --> ActiveStorageBlob : attaches file
MessagesUpsertHandler ..> ActiveStorageBlob : uses
AttachmentProcessor ..> ActiveStorageBlob : uses
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 left some high level feedback:
- In
create_attachment,generate_filename_with_extensionis now used forfallback_title; if this method has any non-determinism (timestamps, random suffixes), consider computing it once and reusing the same value for both blob filename and fallback title to avoid mismatches. - In
message_type_from_media, thestruct_type == 'file' ? 'document' : struct_typereassignment is later normalized back to'file'in the case statement; if this distinction is important for other callers it might be worth adding a brief comment explaining why the intermediate'document'value is needed, otherwise it could be simplified.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `create_attachment`, `generate_filename_with_extension` is now used for `fallback_title`; if this method has any non-determinism (timestamps, random suffixes), consider computing it once and reusing the same value for both blob filename and fallback title to avoid mismatches.
- In `message_type_from_media`, the `struct_type == 'file' ? 'document' : struct_type` reassignment is later normalized back to `'file'` in the case statement; if this distinction is important for other callers it might be worth adding a brief comment explaining why the intermediate `'document'` value is needed, otherwise it could be simplified.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Propagate fallback_title to Z-API, Notificame, and conversation sync handlers - Fix nil guard in audio_voice_note? to prevent NoMethodError when evolution_go_info is nil - Fix Notificame fallback_title to strip query params via URI.parse - Add spec for message_type_from_media with nil/blank MediaType (all struct types) - Update attachment_processor_spec to assert fallback_title in build call Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
message_type_from_media(Evolution Go handler): falls back to structure-basedmessage_typewhenInfo.MediaTypeis absent, preventing inbound videos from being stored asfile_type=fileand rendering as a generic file bubblecreate_attachment(Evolution Go + Evolution API handlers): persistsfallback_titlefromgenerate_filename_with_extensionso that document/video filenames are displayed in the UI instead of the i18n fallback string "file"Validation
evo-ai-crm-community: ruby -c app/services/whatsapp/evolution_go_handlers/messages_upsert.rb→ Syntax OKevo-ai-crm-community: ruby -c app/services/whatsapp/evolution_handlers/attachment_processor.rb→ Syntax OKChanged Files
app/services/whatsapp/evolution_go_handlers/messages_upsert.rbapp/services/whatsapp/evolution_handlers/attachment_processor.rbRelated PRs
Linked Issue