Class: FlowChat::Media

Inherits:
Object
  • Object
show all
Defined in:
lib/flow_chat/media.rb

Overview

Value object wrapping a single inbound media item parsed by a gateway. Normalizes cross-platform differences (WhatsApp media-id, Telegram file_id, Intercom/HTTP direct URL) behind #url and #download.

Constant Summary collapse

NORMALIZED_TYPES =

Maps platform-native media types to a canonical, cross-platform set. Telegram uses :photo/:voice where WhatsApp uses :image/:audio.

{photo: :image, voice: :audio}.freeze
CANONICAL_TYPES =

The canonical media types FlowChat recognizes across platforms. Gateways that accept a caller-supplied type (e.g. HTTP) validate against this set.

%i[image video audio document sticker].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data, platform:, client: nil) ⇒ Media

Returns a new instance of Media.



19
20
21
22
23
# File 'lib/flow_chat/media.rb', line 19

def initialize(data, platform:, client: nil)
  @data = data
  @platform = platform
  @client = client
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



17
18
19
# File 'lib/flow_chat/media.rb', line 17

def client
  @client
end

#platformObject (readonly)

Returns the value of attribute platform.



17
18
19
# File 'lib/flow_chat/media.rb', line 17

def platform
  @platform
end

Instance Method Details

#[](key) ⇒ Object



55
56
57
# File 'lib/flow_chat/media.rb', line 55

def [](key)
  @data[key]
end

#captionObject



39
40
41
# File 'lib/flow_chat/media.rb', line 39

def caption
  @data[:caption]
end

#downloadObject

Fetch the raw bytes of the media, or nil on failure (uniform across platforms). WhatsApp needs the client to attach auth headers; every other platform (Telegram, Intercom, HTTP) exposes a token-in-URL or public link, so we fetch the already-memoized #url directly — avoiding a second getFile round-trip on Telegram.



96
97
98
99
100
101
102
103
104
# File 'lib/flow_chat/media.rb', line 96

def download
  case platform
  when :whatsapp then client.download_media(id)
  else fetch(url)
  end
rescue => e
  FlowChat.logger.warn { "Media: download failed: #{e.message}" }
  nil
end

#file_idObject



51
52
53
# File 'lib/flow_chat/media.rb', line 51

def file_id
  @data[:file_id]
end

#filenameObject



43
44
45
# File 'lib/flow_chat/media.rb', line 43

def filename
  @data[:filename] || @data[:file_name]
end

#idObject



47
48
49
# File 'lib/flow_chat/media.rb', line 47

def id
  @data[:id]
end

#marshal_dumpObject

Serialize without the live platform client (a network object that may not marshal). This keeps a Media — and any FlowChat::Input holding it — safe to store in a session store. A deserialized Media has no client, so #url and #download degrade to nil rather than raising.



67
68
69
# File 'lib/flow_chat/media.rb', line 67

def marshal_dump
  {data: @data, platform: @platform}
end

#marshal_load(state) ⇒ Object



71
72
73
74
75
# File 'lib/flow_chat/media.rb', line 71

def marshal_load(state)
  @data = state[:data]
  @platform = state[:platform]
  @client = nil
end

#mime_typeObject



35
36
37
# File 'lib/flow_chat/media.rb', line 35

def mime_type
  @data[:mime_type]
end

#raw_typeObject

The platform-native type as parsed by the gateway (e.g. :photo, :voice on Telegram).



31
32
33
# File 'lib/flow_chat/media.rb', line 31

def raw_type
  @data[:type]
end

#to_hObject



59
60
61
# File 'lib/flow_chat/media.rb', line 59

def to_h
  @data.dup
end

#typeObject

Canonical, cross-platform media type (:image, :video, :audio, :document, :sticker).



26
27
28
# File 'lib/flow_chat/media.rb', line 26

def type
  NORMALIZED_TYPES.fetch(raw_type, raw_type)
end

#urlObject

Resolve a fetchable URL for the media. Memoized so repeated reads don't re-issue the platform lookup (WhatsApp get_media_url / Telegram getFile). Returns nil (rather than raising) if the lookup fails, matching #download.



80
81
82
83
84
85
86
87
88
89
# File 'lib/flow_chat/media.rb', line 80

def url
  @url ||= case platform
  when :whatsapp then client.get_media_url(id)
  when :telegram then client.file_url(file_id)
  else @data[:url]
  end
rescue => e
  FlowChat.logger.warn { "Media: url resolution failed: #{e.message}" }
  nil
end