class Firebase::Admin::Messaging::MessageEncoder
Public Instance Methods
encode(message)
click to toggle source
Encodes a {Message}.
@param [Message] message
The message to encode.
@return [Hash]
# File lib/firebase/admin/messaging/message_encoder.rb, line 10 def encode(message) raise ArgumentError, "message must be a Message" unless message.is_a?(Message) result = { android: encode_android(message.android), apns: encode_apns(message.apns), condition: check_string("Message.condition", message.condition, non_empty: true), data: check_string_hash("Message.data", message.data), notification: encode_notification(message.notification), token: check_string("Message.token", message.token, non_empty: true), topic: check_string("Message.topic", message.topic, non_empty: true), fcm_options: encode_fcm_options(message.fcm_options) } result[:topic] = sanitize_topic_name(result[:topic]) result = remove_nil_values(result) unless result.count { |k, _| [:token, :topic, :condition].include?(k) } == 1 raise ArgumentError, "Exactly one token, topic or condition must be specified" end result end
sanitize_topic_name(topic, strip_prefix: true)
click to toggle source
@return [String, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 31 def sanitize_topic_name(topic, strip_prefix: true) return nil unless topic prefix = "/topics/" if topic.start_with?(prefix) topic = topic[prefix.length..] end unless /\A[a-zA-Z0-9\-_.~%]+\Z/.match?(topic) raise ArgumentError, "Malformed topic name." end strip_prefix ? topic : "/topics/#{topic}" end
Private Instance Methods
encode_android(v)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 46 def encode_android(v) return nil unless v raise ArgumentError, "Message.android must be an AndroidConfig." unless v.is_a?(AndroidConfig) result = { collapse_key: check_string("AndroidConfig.collapse_key", v.collapse_key), data: check_string_hash("AndroidConfig.data", v.data), notification: encode_android_notification(v.notification), priority: check_string("AndroidConfig.priority", v.priority, non_empty: true), restricted_package_name: check_string("AndroidConfig.restricted_package_name", v.restricted_package_name), ttl: encode_duration("AndroidConfig.ttl", v.ttl), fcm_options: encode_android_fcm_options(v.fcm_options) } result = remove_nil_values(result) if result.key?(:priority) && !%w[normal high].include?(result[:priority]) raise ArgumentError, "AndroidConfig.priority must be 'normal' or 'high'" end result end
encode_android_fcm_options(v)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 137 def encode_android_fcm_options(v) return nil unless v unless v.is_a?(AndroidFCMOptions) raise ArgumentError, "AndroidConfig.fcm_options must be an AndroidFCMOptions" end result = { analytics_label: check_analytics_label("AndroidFCMOptions.analytics_label", v.analytics_label) } remove_nil_values(result) end
encode_android_notification(v)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 66 def encode_android_notification(v) return nil unless v unless v.is_a?(AndroidNotification) raise ArgumentError, "AndroidConfig.notification must be an AndroidNotification" end result = { body: check_string("AndroidNotification.body", v.body), body_loc_key: check_string("AndroidNotification.body_loc_key", v.body_loc_key), body_loc_args: check_string_array("AndroidNotification.body_loc_args", v.body_loc_args), click_action: check_string("AndroidNotification.click_action", v.click_action), color: check_color("AndroidNotification.color", v.color, allow_alpha: true, required: false), icon: check_string("AndroidNotification.icon", v.icon), sound: check_string("AndroidNotification.sound", v.sound), tag: check_string("AndroidNotification.tag", v.tag), title: check_string("AndroidNotification.title", v.title), title_loc_key: check_string("AndroidNotification.title_loc_key", v.title_loc_key), title_loc_args: check_string_array("AndroidNotification.title_loc_args", v.title_loc_args), channel_id: check_string("AndroidNotification.channel_id", v.channel_id), image: check_string("AndroidNotification.image", v.image), ticker: check_string("AndroidNotification.ticker", v.ticker), sticky: v.sticky, event_time: check_time("AndroidNotification.event_time", v.event_time), local_only: v.local_only, notification_priority: check_string("AndroidNotification.priority", v.priority, non_empty: true), vibrate_timings: check_numeric_array("AndroidNotification.vibrate_timings", v.vibrate_timings), default_vibrate_timings: v.default_vibrate_timings, default_sound: v.default_sound, default_light_settings: v.default_light_settings, light_settings: encode_light_settings(v.light_settings), visibility: check_string("AndroidNotification.visibility", v.visibility, non_empty: true), notification_count: check_numeric("AndroidNotification.notification_count", v.notification_count) } result = remove_nil_values(result) if result.key?(:body_loc_args) && !result.key?(:body_loc_key) raise ArgumentError, "AndroidNotification.body_loc_key is required when specifying body_loc_args" elsif result.key?(:title_loc_args) && !result.key?(:title_loc_key) raise ArgumentError, "AndroidNotification.title_loc_key is required when specifying title_loc_args" end if (event_time = result[:event_time]) event_time = event_time.dup.utc unless event_time.utc? result[:event_time] = event_time.strftime("%Y-%m-%dT%H:%M:%S.%6NZ") end if (priority = result[:notification_priority]) unless %w[min low default high max].include?(priority) raise ArgumentError, "AndroidNotification.priority must be 'default', 'min', 'low', 'high' or 'max'." end result[:notification_priority] = "PRIORITY_#{priority.upcase}" end if (visibility = result[:visibility]) unless %w[private public secret].include?(visibility) raise ArgumentError, "AndroidNotification.visibility must be 'private', 'public' or 'secret'" end result[:visibility] = visibility.upcase end if (vibrate_timings = result[:vibrate_timings]) vibrate_timing_strings = vibrate_timings.map do |t| encode_duration("AndroidNotification.vibrate_timings", t) end result[:vibrate_timings] = vibrate_timing_strings end result end
encode_apns(apns)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 187 def encode_apns(apns) return nil unless apns raise ArgumentError, "Message.apns must be an APNSConfig" unless apns.is_a?(APNSConfig) result = { headers: check_string_hash("APNSConfig.headers", apns.headers), payload: encode_apns_payload(apns.payload), fcm_options: encode_apns_fcm_options(apns.fcm_options) } remove_nil_values(result) end
encode_apns_fcm_options(options)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 212 def encode_apns_fcm_options(options) return nil unless options raise ArgumentError, "APNSConfig.fcm_options must be an APNSFCMOptions" unless options.is_a?(APNSFCMOptions) result = { analytics_label: check_analytics_label("APNSFCMOptions.analytics_label", options.analytics_label), image: check_string("APNSFCMOptions.image", options.image) } remove_nil_values(result) end
encode_apns_payload(payload)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 199 def encode_apns_payload(payload) return nil unless payload raise ArgumentError, "APNSConfig.payload must be an APNSPayload" unless payload.is_a?(APNSPayload) result = { aps: encode_aps(payload.aps) } payload.data&.each do |k, v| result[k] = v end remove_nil_values(result) end
encode_aps(aps)
click to toggle source
@return [Hash]
# File lib/firebase/admin/messaging/message_encoder.rb, line 223 def encode_aps(aps) raise ArgumentError, "APNSPayload.aps is required" unless aps raise ArgumentError, "APNSPayload.aps must be an APS" unless aps.is_a?(APS) result = { alert: encode_aps_alert(aps.alert), badge: check_numeric("APS.badge", aps.badge), sound: encode_aps_sound(aps.sound), category: check_string("APS.category", aps.category), "thread-id": check_string("APS.thread_id", aps.thread_id) } result[:"content-available"] = 1 if aps.content_available result[:"mutable-content"] = 1 if aps.mutable_content if (custom_data = aps.custom_data) raise ArgumentError, "APS.custom_data must be a hash" unless custom_data.is_a?(Hash) custom_data.each do |k, v| unless k.is_a?(String) || k.is_a?(Symbol) raise ArgumentError, "APS.custom_data key #{k}, must be a string or symbol" end k = k.to_sym raise ArgumentError, "Multiple specifications for #{k} in APS" if result.key?(k) result[k] = v end end remove_nil_values(result) end
encode_aps_alert(alert)
click to toggle source
@return [Hash, String, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 253 def encode_aps_alert(alert) return nil unless alert return alert if alert.is_a?(String) raise ArgumentError, "APS.alert must be a string or an an APSAlert" unless alert.is_a?(APSAlert) result = { title: check_string("APSAlert.title", alert.title), subtitle: check_string("APSAlert.subtitle", alert.subtitle), body: check_string("APSAlert.body", alert.body), "title-loc-key": check_string("APSAlert.title_loc_key", alert.title_loc_key), "title-loc-args": check_string_array("APSAlert.title_loc_args", alert.title_loc_args), "subtitle-loc-key": check_string("APSAlert.subtitle_loc_key", alert.subtitle_loc_key), "subtitle-loc-args": check_string_array("APSAlert.subtitle_loc_args", alert.subtitle_loc_args), "loc-key": check_string("APSAlert.loc_key", alert.loc_key), "loc-args": check_string_array("ASPAlert.loc_args", alert.loc_args), "action-loc-key": check_string("APSAlert.action_loc_key", alert.action_loc_key), "launch-image": check_string("APSAlert.launch_image", alert.launch_image) } result = remove_nil_values(result) if result.key?(:"loc-args") && !result.key?(:"loc-key") raise ArgumentError, "APSAlert.loc_key is required when specifying loc_args" elsif result.key?(:"title-loc-args") && !result.key?(:"title-loc-key") raise ArgumentError, "APSAlert.title_loc_key is required when specifying title_loc_args" elsif result.key?(:"subtitle-loc-args") && !result.key?(:"subtitle-loc-key") raise ArgumentError, "APSAlert.subtitle_loc_key is required when specifying subtitle_loc_args" end if (custom_data = alert.custom_data) raise ArgumentError, "APSAlert.custom_data must be a hash" unless custom_data.is_a?(Hash) custom_data.each do |k, v| unless k.is_a?(String) || k.is_a?(Symbol) raise ArgumentError, "APSAlert.custom_data key #{k}, must be a string or symbol" end k = k.to_sym result[k] = v end end remove_nil_values(result) end
encode_aps_sound(sound)
click to toggle source
@return [Hash, String, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 295 def encode_aps_sound(sound) return nil unless sound return sound if sound.is_a?(String) && !sound.empty? unless sound.is_a?(CriticalSound) raise ArgumentError, "APS.sound must be a non-empty string or a CriticalSound" end result = { name: check_string("CriticalSound.name", sound.name, non_empty: true), volume: check_numeric("CriticalSound.volume", sound.volume) } result[:critical] = 1 if sound.critical raise ArgumentError, "CriticalSound.name is required" if result[:name].nil? if (volume = result[:volume]) raise ArgumentError, "CriticalSound.volume must be between [0,1]." unless volume >= 0 && volume <= 1 end remove_nil_values(result) end
encode_color(label, value, allow_alpha: false)
click to toggle source
@return [Hash]
# File lib/firebase/admin/messaging/message_encoder.rb, line 176 def encode_color(label, value, allow_alpha: false) value = check_color(label, value, allow_alpha: allow_alpha, required: true) value += "FF" if value&.length == 7 r = value[1..2].to_i(16) / 255.0 g = value[3..4].to_i(16) / 255.0 b = value[5..6].to_i(16) / 255.0 a = value[7..8].to_i(16) / 255.0 {red: r, green: g, blue: b, alpha: a} end
encode_duration(label, value)
click to toggle source
@return [String, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 149 def encode_duration(label, value) return nil unless value raise ArgumentError, "#{label} must be a numeric duration in seconds" unless value.is_a?(Numeric) raise ArgumentError, "#{label} must not be negative" if value < 0 to_seconds_string(value) end
encode_fcm_options(options)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 330 def encode_fcm_options(options) return nil unless options raise ArgumentError, "Message.fcm_options must be a FCMOptions." unless options.is_a?(FCMOptions) result = { analytics_label: check_analytics_label("Message.fcm_options", options.analytics_label) } remove_nil_values(result) end
encode_light_settings(v)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 157 def encode_light_settings(v) return nil unless v raise ArgumentError, "AndroidNotification.light_settings must be a LightSettings." unless v.is_a?(LightSettings) result = { color: encode_color("LightSettings.color", v.color, allow_alpha: true), light_on_duration: encode_duration("LightSettings.light_on_duration", v.light_on_duration), light_off_duration: encode_duration("LightSettings.light_off_duration", v.light_off_duration) } result = remove_nil_values(result) unless result.key?(:light_on_duration) raise ArgumentError, "LightSettings.light_on_duration is required" end unless result.key?(:light_off_duration) raise ArgumentError, "LightSettings.light_off_duration is required" end result end
encode_notification(v)
click to toggle source
@return [Hash, nil]
# File lib/firebase/admin/messaging/message_encoder.rb, line 318 def encode_notification(v) return nil unless v raise ArgumentError, "Message.notification must be a Notification" unless v.is_a?(Notification) result = { body: check_string("Notification.body", v.body), title: check_string("Notification.title", v.title), image: check_string("Notification.image", v.image) } remove_nil_values(result) end
remove_nil_values(hash)
click to toggle source
Remove nil values and empty collections from the specified hash. @return [Hash]
# File lib/firebase/admin/messaging/message_encoder.rb, line 341 def remove_nil_values(hash) hash.reject do |_, v| if v.is_a?(Hash) || v.is_a?(Array) v.empty? else v.nil? end end end