Module: InstagramConnect::Ingest::Registry

Defined in:
lib/instagram_connect/ingest/registry.rb

Overview

Maps a webhook field to the handler that parses it, and infers the field for messaging events (Meta delivers all of them under entry.messaging regardless of which subscription triggered them, so the field has to be recovered from the event's shape).

Constant Summary collapse

HANDLERS =
{
  "messages" => Handlers::Messages,
  "message_echoes" => Handlers::Messages,
  "messaging_postbacks" => Handlers::MessagingPostbacks,
  "message_reactions" => Handlers::MessageReactions,
  "messaging_seen" => Handlers::MessagingSeen,
  "messaging_referral" => Handlers::MessagingReferral,
  "messaging_optins" => Handlers::MessagingOptins,
  "messaging_handover" => Handlers::MessagingHandover,
  "comments" => Handlers::Comments,
  "live_comments" => Handlers::Comments,
  "mentions" => Handlers::Mentions,
  "story_insights" => Handlers::StoryInsights
}.freeze
KNOWN_FIELDS =

Every field the gem knows Meta can send on the instagram object. Fields without a handler are still worth subscribing to: they bank as unhandled rows and replay once a handler ships, whereas an unsubscribed field is gone for good — Meta does not store mentions or story_insights notifications, and re-delivers nothing.

%w[
  messages
  message_echoes
  message_reactions
  messaging_postbacks
  messaging_seen
  messaging_referral
  messaging_optins
  messaging_handover
  messaging_policy_enforcement
  response_feedback
  standby
  comments
  live_comments
  mentions
  story_insights
].freeze
PAGE_FIELD_NAMES =

Meta's Page object and Instagram object use DIFFERENT names for the same webhook. POST /{page-id}/subscribed_apps takes the PAGE vocabulary and rejects the whole call — every field, not just the offender — on the first name it does not recognise:

(#100) Param subscribed_fields[4] must be one of {...} - got "messaging_seen"

That one rejection is why a correctly configured Page received nothing at all. Fields with no Page equivalent (comments, mentions, story_insights) are subscribed on the instagram object in the app dashboard instead, and must not be sent here.

{
  "messaging_seen" => "message_reads",
  "messaging_referral" => "messaging_referrals",
  "messaging_handover" => "messaging_handovers"
}.freeze
INSTAGRAM_ONLY_FIELDS =
%w[comments live_comments mentions story_insights].freeze
MESSAGING_SHAPES =

Shape tests in priority order. is_echo must be checked before the plain message case, since an echo carries a message too.

[
  [ "message_echoes", ->(e) { e["message"] && e.dig("message", "is_echo") } ],
  [ "messages", ->(e) { e["message"] } ],
  [ "message_reactions", ->(e) { e["reaction"] } ],
  [ "messaging_postbacks", ->(e) { e["postback"] } ],
  [ "messaging_seen", ->(e) { e["read"] } ],
  [ "messaging_referral", ->(e) { e["referral"] } ],
  [ "messaging_optins", ->(e) { e["optin"] } ],
  [ "messaging_handover", lambda { |e|
    e["pass_thread_control"] || e["take_thread_control"] || e["request_thread_control"]
  } ]
].freeze
UNKNOWN_FIELD =
"unknown".freeze

Class Method Summary collapse

Class Method Details

.handled?(field) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/instagram_connect/ingest/registry.rb', line 96

def handled?(field)
  HANDLERS.key?(field)
end

.handled_fieldsObject



106
107
108
# File 'lib/instagram_connect/ingest/registry.rb', line 106

def handled_fields
  HANDLERS.keys
end

.handler_for(field) ⇒ Object



92
93
94
# File 'lib/instagram_connect/ingest/registry.rb', line 92

def handler_for(field)
  HANDLERS.fetch(field, Handlers::Unknown)
end

.messaging_field_for(event) ⇒ Object

message.referral and postback.referral are nested inside their parent event and stay with it; only a standalone referral is a referral event in its own right, which is why the shape tests run in order rather than checking every key independently.



114
115
116
117
# File 'lib/instagram_connect/ingest/registry.rb', line 114

def messaging_field_for(event)
  found = MESSAGING_SHAPES.find { |(_field, test)| test.call(event) }
  found ? found.first : UNKNOWN_FIELD
end

.page_subscribable_fieldsObject

The subset of KNOWN_FIELDS that subscribed_apps accepts, translated to the names Meta uses on a Page.



67
68
69
70
71
# File 'lib/instagram_connect/ingest/registry.rb', line 67

def self.page_subscribable_fields
  (KNOWN_FIELDS - INSTAGRAM_ONLY_FIELDS)
    .map { |field| PAGE_FIELD_NAMES.fetch(field, field) }
    .uniq
end

.subscribable_fieldsObject

The fields a host should subscribe its Page to. Everything the gem knows about, handled or not — see KNOWN_FIELDS.



102
103
104
# File 'lib/instagram_connect/ingest/registry.rb', line 102

def subscribable_fields
  KNOWN_FIELDS
end