This repository has been archived by the owner on Oct 20, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 100
/
instagram.rb
128 lines (110 loc) · 3.42 KB
/
instagram.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
require 'faraday_middleware'
require 'hashie/mash'
module Instagram
module Configuration
attr_accessor :client_id, :client_secret, :access_token, :cache
def configure
yield self
end
end
class OAuthRequest < Faraday::Middleware
def initialize(app, options)
super(app)
@config = options[:config]
end
def call(env)
unless env[:request][:oauth] == false
params = %w[client_id client_secret access_token].each_with_object({}) do |key, hash|
value = @config.send(key)
hash[key] = value if value.present?
end
if env[:method] == :get
url = env[:url]
query_values = params.update Faraday::Utils.parse_query(url.query.to_s)
url.query = Faraday::Utils.build_query query_values
env[:url] = url
else
env[:body] = params.update(env[:body] || {})
end
end
@app.call(env)
end
end
class PreserveRawBody < Faraday::Response::Middleware
def on_complete(env)
env[:raw_body] = env[:body]
end
end
module Connection
def connection
@connection ||= Faraday.new('https://api.instagram.com/v1/') do |conn|
conn.use OAuthRequest, config: self
conn.request :url_encoded
conn.response :mashify
conn.response :json, content_type: 'application/json'
conn.use PreserveRawBody
conn.response :caching, cache, ignore_params: %w[access_token client_id client_secret] unless cache.nil?
conn.use :instrumentation
conn.adapter Faraday.default_adapter
conn.headers['User-Agent'] = 'instagram.heroku.com ruby client'
conn.options[:timeout] = 6
conn.options[:open_timeout] = 2
end
end
def get(path, params = nil)
connection.get(path) do |request|
request.params.update(params) if params
end
end
end
module OAuthMethods
def authorization_url(options)
connection.build_url '/oauth/authorize', client_id: client_id,
redirect_uri: options[:return_to], response_type: 'code'
end
def get_access_token(options)
connection.post '/oauth/access_token', code: options[:code],
grant_type: 'authorization_code', redirect_uri: options[:return_to]
end
end
class Error < RuntimeError
attr_reader :response
def initialize(response)
@response = response
super "Instagram responded with status #{response.status}"
end
end
module ApiMethods
def get(path, params = nil)
raw = params && params.delete(:raw)
response = super
raise Error.new(response) if response.status >= 500
body = raw ? response.env[:raw_body] : response.body
body.singleton_class.class_eval <<-RUBY
def body() self end
def status() #{response.status} end
def error!() raise Instagram::Error.new(self) end
RUBY
body
end
def user(user_id, *args)
get("users/#{user_id}", *args)
end
def user_recent_media(user_id, *args)
get("users/#{user_id}/media/recent", *args)
end
def media_popular(*args)
get("media/popular", *args)
end
def tag_search(query, params = {})
get("tags/search", params.merge(:q => query))
end
def tag_recent_media(tag, *args)
get("tags/#{tag}/media/recent", *args)
end
end
extend Configuration
extend Connection
extend OAuthMethods
extend ApiMethods
end