module Instagram::Client::Subscriptions

Defines methods related to real-time

Public Instance Methods

create_subscription(*args) click to toggle source

Creates a real-time subscription

@overload create_subscription(options={})

@param options [Hash] A set of parameters
@option options [String] :object The object you'd like to subscribe to (user, tag, location or geography)
@option options [String] :callback_url The subscription callback URL
@option options [String] :aspect The aspect of the object you'd like to subscribe to (in this case, "media").
@option options [String, Integer] :object_id When specifying a location or tag use the location's ID or tag name respectively
@option options [String, Float] :lat The center latitude of an area, used when subscribing to a geography object
@option options [String, Float] :lng The center longitude of an area, used when subscribing to a geography object
@option options [String, Integer] :radius The distance in meters you'd like to capture around a given point

@overload create_subscription(object, callback_url, aspect=“media”, options={})

@param object [String] The object you'd like to subscribe to (user, tag, location or geography)
@param callback_url [String] The subscription callback URL
@param aspect [String] he aspect of the object you'd like to subscribe to (in this case, "media").
@param options [Hash] Addition options and parameters
@option options [String, Integer] :object_id When specifying a location or tag use the location's ID or tag name respectively
@option options [String, Float] :lat The center latitude of an area, used when subscribing to a geography object
@option options [String, Float] :lng The center longitude of an area, used when subscribing to a geography object
@option options [String, Integer] :radius 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.
@return [Hashie::Mash] The subscription created.
@example Creates a new subscription to receive notifications for user media changes.
  Instagram.create_subscription("user", "http://example.com/instagram/callback")

@format :json @authenticated true

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

@rate_limited true @see api.instagram.com/developer/realtime/

# 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(*args) click to toggle source

Deletes a real-time subscription

@overload delete_subscription(options={})

@param options [Hash] Addition options and parameters
@option options [Integer] :subscription_id The subscription's ID
@option options [String] :object When specified will remove all subscriptions of this object type, unless an :object_id is also specified (user, tag, location or geography)
@option options [String, Integer] :object_id When specifying :object, inlcude an :object_id to only remove subscriptions of that object and object_id

@overload delete_subscription(subscription_id, options={})

@param subscription_id [Integer] The subscription's ID
@param options [Hash] Addition options and parameters
@option options [String] :object When specified will remove all subscriptions of this object type, unless an :object_id is also specified (user, tag, location or geography)
@option options [String, Integer] :object_id When specifying :object, inlcude an :object_id to only remove subscriptions of that object and object_id
@return [Hashie::Mash]
@example Deletes an application's user change subscription
  Instagram.delete_subscription(:object => "user")

@format :json @authenticated true

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

@rate_limited true @see api.instagram.com/developer/realtime/

# 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) { |params| ... } click to toggle source

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.

@param params the request parameters sent by Instagram. (You can pass in a Rails params hash.) @param verify_token the verify token sent in the {#subscribe subscription request}, if you provided one

@yield 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.

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

# 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, options={}, &block) click to toggle source

Process a subscription notification JSON payload

@overload process_subscription(json, &block)

@param json [String] The JSON response received by the Instagram real-time server
@param block [Proc] A callable in which callbacks are defined
@option options [String] :signature Pass in an X-Hub-Signature to use for payload validation
@return [nil]
@example 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

@format :json @authenticated true

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

@rate_limited true @see api.instagram.com/developer/realtime/

# 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={}) click to toggle source

Returns a list of active real-time subscriptions

@overload subscriptions(options={})

@return [Hashie::Mash] The list of subscriptions.
@example Returns a list of subscriptions for the authenticated application
  Instagram.subscriptions

@format :json @authenticated true

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

@rate_limited true @see api.instagram.com/developer/realtime/

# 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) click to toggle source

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
# 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