Module: Instagram::Client::Subscriptions

Included in:
Instagram::Client
Defined in:
lib/instagram/client/subscriptions.rb

Overview

Defines methods related to real-time

Instance Method Summary collapse

Instance Method Details

#create_subscription(options = {}) ⇒ Object #create_subscription(object, callback_url, aspect = "media", options = {}) ⇒ Hashie::Mash

Creates a real-time subscription

Overloads:

  • #create_subscription(options = {}) ⇒ Object

    Parameters:

    • options (Hash) (defaults to: {})

      A set of parameters

    Options Hash (options):

    • :object (String)

      The object you'd like to subscribe to (user, tag, location or geography)

    • :callback_url (String)

      The subscription callback URL

    • :aspect (String)

      The aspect of the object you'd like to subscribe to (in this case, "media").

    • :object_id (String, Integer)

      When specifying a location or tag use the location's ID or tag name respectively

    • :lat (String, Float)

      The center latitude of an area, used when subscribing to a geography object

    • :lng (String, Float)

      The center longitude of an area, used when subscribing to a geography object

    • :radius (String, Integer)

      The distance in meters you'd like to capture around a given point

  • #create_subscription(object, callback_url, aspect = "media", options = {}) ⇒ Hashie::Mash

    Returns The subscription created.

    Examples:

    Creates a new subscription to receive notifications for user media changes.

    Instagram.create_subscription("user", "http://example.com/instagram/callback")

    Parameters:

    • object (String)

      The object you'd like to subscribe to (user, tag, location or geography)

    • callback_url (String)

      The subscription callback URL

    • aspect (String) (defaults to: "media")

      he aspect of the object you'd like to subscribe to (in this case, "media").

    • options (Hash) (defaults to: {})

      Addition options and parameters

    Options Hash (options):

    • :object_id (String, Integer)

      When specifying a location or tag use the location's ID or tag name respectively

    • :lat (String, Float)

      The center latitude of an area, used when subscribing to a geography object

    • :lng (String, Float)

      The center longitude of an area, used when subscribing to a geography object

    • :radius (String, Integer)

      The distance in meters you'd like to capture around a given point

      Note that we only support "media" at this time, but we might support other types of subscriptions in the future.

    Returns:

    • (Hashie::Mash)

      The subscription created.

See Also:

Supported formats:

  • :json

Requires Authentication:

  • true

    Requires client_secret to be set on the client or passed in options

Rate Limited:

  • true


56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/instagram/client/subscriptions.rb', line 56

def create_subscription(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  object = args.shift
  callback_url = args.shift
  aspect = args.shift
  options.tap {|o|
    o[:object] = object unless object.nil?
    o[:callback_url] = callback_url unless callback_url.nil?
    o[:aspect] = aspect || o[:aspect] || "media"
  }
  response = post("subscriptions", options.merge(:client_secret => client_secret), signature=true)
  response
end

#delete_subscription(options = {}) ⇒ Object #delete_subscription(subscription_id, options = {}) ⇒ Hashie::Mash

Deletes a real-time subscription

Overloads:

  • #delete_subscription(options = {}) ⇒ Object

    Parameters:

    • options (Hash) (defaults to: {})

      Addition options and parameters

    Options Hash (options):

    • :subscription_id (Integer)

      The subscription's ID

    • :object (String)

      When specified will remove all subscriptions of this object type, unless an :object_id is also specified (user, tag, location or geography)

    • :object_id (String, Integer)

      When specifying :object, inlcude an :object_id to only remove subscriptions of that object and object_id

  • #delete_subscription(subscription_id, options = {}) ⇒ Hashie::Mash

    Examples:

    Deletes an application's user change subscription

    Instagram.delete_subscription(:object => "user")

    Parameters:

    • subscription_id (Integer)

      The subscription's ID

    • options (Hash) (defaults to: {})

      Addition options and parameters

    Options Hash (options):

    • :object (String)

      When specified will remove all subscriptions of this object type, unless an :object_id is also specified (user, tag, location or geography)

    • :object_id (String, Integer)

      When specifying :object, inlcude an :object_id to only remove subscriptions of that object and object_id

    Returns:

    • (Hashie::Mash)

See Also:

Supported formats:

  • :json

Requires Authentication:

  • true

    Requires client_secret to be set on the client or passed in options

Rate Limited:

  • true


91
92
93
94
95
96
97
# File 'lib/instagram/client/subscriptions.rb', line 91

def delete_subscription(*args)
  options = args.last.is_a?(Hash) ? args.pop : {}
  subscription_id = args.first
  options.merge!(:id => subscription_id) if subscription_id
  response = delete("subscriptions", options.merge(:client_secret => client_secret), signature=true)
  response
end

#meet_challenge(params, verify_token = nil) { ... } ⇒ Object

As a security measure (to prevent DDoS attacks), Instagram sends a verification request to your server after you request a subscription. This method parses the challenge params and makes sure the call is legitimate.

Parameters:

  • params

    the request parameters sent by Instagram. (You can pass in a Rails params hash.)

  • verify_token (defaults to: nil)

    the verify token sent in the subscription request, if you provided one

Yields:

  • verify_token if you need to compute the verification token (for instance, if your callback URL includes a record ID, which you look up and use to calculate a hash), you can pass meet_challenge a block, which will receive the verify_token received back from Instagram.

Returns:

  • the challenge string to be sent back to Instagram, or false if the request is invalid.


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/instagram/client/subscriptions.rb', line 112

def meet_challenge(params, verify_token = nil, &verification_block)
  if params["hub.mode"] == "subscribe" &&
      # you can make sure this is legitimate through two ways
      # if your store the token across the calls, you can pass in the token value
      # and we'll make sure it matches
      ((verify_token && params["hub.verify_token"] == verify_token) ||
      # alternately, if you sent a specially-constructed value (such as a hash of various secret values)
      # you can pass in a block, which we'll call with the verify_token sent by Instagram
      # if it's legit, return anything that evaluates to true; otherwise, return nil or false
      (verification_block && yield(params["hub.verify_token"])))
    params["hub.challenge"]
  else
    false
  end
end

#process_subscription(json, &block) ⇒ nil

Process a subscription notification JSON payload

Examples:

Process and handle a notification for a user media change

Instagram.process_subscription(params[:body]) do |handler|

  handler.on_user_changed do |user_id, data|

    user = User.by_instagram_id(user_id)
    @client = Instagram.client(:access_token => _access_token_for_user(user))
    latest_media = @client.user_recent_media[0]
    user.media.create_with_hash(latest_media)
  end

end

Parameters:

  • json (String)

    The JSON response received by the Instagram real-time server

  • block (Proc)

    A callable in which callbacks are defined

Returns:

  • (nil)

Raises:

  • (ArgumentError)

See Also:

Supported formats:

  • :json

Requires Authentication:

  • true

    Requires client_secret to be set on the client or passed in options

Rate Limited:

  • true


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/instagram/client/subscriptions.rb', line 177

def process_subscription(json, options={}, &block)
  raise ArgumentError, "callbacks block expected" unless block_given?

  if options.has_key?(:signature)
    if !client_secret
      raise ArgumentError, "client_secret must be set during configure"
    end
    digest = OpenSSL::Digest.new('sha1')
    verify_signature = OpenSSL::HMAC.hexdigest(digest, client_secret, json)

    if options[:signature] != verify_signature
      raise Instagram::InvalidSignature, "invalid X-Hub-Signature does not match verify signature against client_secret"
    end
  end

  payload = MultiJson.decode(json)
  @changes = Hash.new { |h,k| h[k] = [] }
  for change in payload
    @changes[change['object']] << change
  end
  block.call(self)
end

#subscriptions(options = {}) ⇒ Hashie::Mash

Returns a list of active real-time subscriptions

Returns The list of subscriptions.

Examples:

Returns a list of subscriptions for the authenticated application

Instagram.subscriptions

Returns:

  • (Hashie::Mash)

    The list of subscriptions.

See Also:

Supported formats:

  • :json

Requires Authentication:

  • true

    Requires client_secret to be set on the client or passed in options

Rate Limited:

  • true


20
21
22
23
# File 'lib/instagram/client/subscriptions.rb', line 20

def subscriptions(options={})
  response = get("subscriptions", options.merge(:client_secret => client_secret))
  response
end

#validate_update(body, headers) ⇒ Object

Public: As a security measure, all updates from Instagram are signed using X-Hub-Signature: XXXX where XXX is the sha1 of the json payload using your application secret as the key.

Example: # in Rails controller def receive_update if Instagram.validate_update(request.body, headers) ... else render text: "not authorized", status: 401 end end


141
142
143
144
145
146
147
148
149
150
# File 'lib/instagram/client/subscriptions.rb', line 141

def validate_update(body, headers)
  unless client_secret
    raise ArgumentError, "client_secret must be set during configure"
  end

  if request_signature = headers['X-Hub-Signature'] || headers['HTTP_X_HUB_SIGNATURE']
    calculated_signature = OpenSSL::HMAC.hexdigest('sha1', client_secret, body)
    calculated_signature == request_signature
  end
end