Skip to content
This repository was archived by the owner on Mar 19, 2025. It is now read-only.

Commit 79c41e1

Browse files
author
Jon Heaton
committed
update to support signed requests
1 parent e885e7d commit 79c41e1

4 files changed

Lines changed: 44 additions & 24 deletions

File tree

instagram/bind.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ def _build_path(self):
103103

104104
if self.api.format:
105105
self.path = self.path + '.%s' % self.api.format
106-
else:
107-
self.path = self.path
108106

109107
def _build_pagination_info(self, content_obj):
110108
"""Extract pagination information in the desired format."""
@@ -114,14 +112,15 @@ def _build_pagination_info(self, content_obj):
114112
if self.pagination_format == 'dict':
115113
return pagination
116114
raise Exception('Invalid value for pagination_format: %s' % self.pagination_format)
117-
115+
118116
def _do_api_request(self, url, method="GET", body=None, headers=None):
119117
headers = headers or {}
120118
if self.signature and self.api.client_ips != None and self.api.client_secret != None:
121119
secret = self.api.client_secret
122120
ips = self.api.client_ips
123121
signature = hmac.new(secret, ips, sha256).hexdigest()
124122
headers['X-Insta-Forwarded-For'] = '|'.join([ips, signature])
123+
125124
response, content = OAuth2Request(self.api).make_request(url, method=method, body=body, headers=headers)
126125
if response['status'] == '503' or response['status'] == '429':
127126
raise InstagramAPIError(response['status'], "Rate limited", "Your client is making too many request per second")

instagram/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(self, *args, **kwargs):
2626
self.format = format
2727
else:
2828
raise Exception("Unsupported format")
29-
super(InstagramAPI, self).__init__(*args, **kwargs)
29+
super(InstagramAPI, self).__init__(**kwargs)
3030

3131
media_popular = bind_method(
3232
path="/media/popular",

instagram/oauth2.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from .json_import import simplejson
22
from six.moves.urllib.parse import urlencode
33
from httplib2 import Http
4+
from hashlib import sha256
45
import mimetypes
56
import six
7+
import hmac
68

79

810
class OAuth2AuthExchangeError(Exception):
@@ -118,6 +120,12 @@ class OAuth2Request(object):
118120
def __init__(self, api):
119121
self.api = api
120122

123+
def _generate_sig(self, endpoint, params, secret):
124+
sig = endpoint
125+
for key in sorted(params.keys()):
126+
sig += '|%s=%s' % (key, params[key])
127+
return hmac.new(secret, sig, sha256).hexdigest()
128+
121129
def url_for_get(self, path, parameters):
122130
return self._full_url_with_params(path, parameters)
123131

@@ -127,15 +135,18 @@ def get_request(self, path, **kwargs):
127135
def post_request(self, path, **kwargs):
128136
return self.make_request(self.prepare_request("POST", path, kwargs))
129137

130-
def _full_url(self, path, include_secret=False):
131-
return "%s://%s%s%s%s" % (self.api.protocol,
138+
def _full_url(self, path, include_secret=False, include_signed_request=True):
139+
return "%s://%s%s%s%s%s" % (self.api.protocol,
132140
self.api.host,
133141
self.api.base_path,
134142
path,
135-
self._auth_query(include_secret))
143+
self._auth_query(include_secret),
144+
self._signed_request(path, {}, include_signed_request, include_secret))
136145

137-
def _full_url_with_params(self, path, params, include_secret=False):
138-
return (self._full_url(path, include_secret) + self._full_query_with_params(params))
146+
def _full_url_with_params(self, path, params, include_secret=False, include_signed_request=True):
147+
return (self._full_url(path, include_secret) +
148+
self._full_query_with_params(params) +
149+
self._signed_request(path, params, include_signed_request, include_secret))
139150

140151
def _full_query_with_params(self, params):
141152
params = ("&" + urlencode(params)) if params else ""
@@ -150,6 +161,18 @@ def _auth_query(self, include_secret=False):
150161
base += "&client_secret=%s" % (self.api.client_secret)
151162
return base
152163

164+
def _signed_request(self, path, params, include_signed_request, include_secret):
165+
if include_signed_request:
166+
if self.api.access_token:
167+
params['access_token'] = self.api.access_token
168+
elif self.api.client_id:
169+
params['client_id'] = self.api.client_id
170+
if include_secret and self.api.client_secret:
171+
params['client_secret'] = self.api.client_secret
172+
return "&sig=%s" % self._generate_sig(path, params, self.api.client_secret)
173+
else:
174+
return ''
175+
153176
def _post_body(self, params):
154177
return urlencode(params)
155178

sample_app.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,8 @@ def on_callback():
6464
access_token, user_info = unauthenticated_api.exchange_code_for_access_token(code)
6565
if not access_token:
6666
return 'Could not get access token'
67-
api = client.InstagramAPI(access_token=access_token)
67+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
6868
request.session['access_token'] = access_token
69-
print ("access token="+access_token)
7069
except Exception as e:
7170
print(e)
7271
return get_nav()
@@ -78,7 +77,7 @@ def on_recent():
7877
if not access_token:
7978
return 'Missing Access Token'
8079
try:
81-
api = client.InstagramAPI(access_token=access_token)
80+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
8281
recent_media, next = api.user_recent_media()
8382
photos = []
8483
for media in recent_media:
@@ -87,7 +86,6 @@ def on_recent():
8786
photos.append('<video controls width height="150"><source type="video/mp4" src="%s"/></video>' % (media.get_standard_resolution_url()))
8887
else:
8988
photos.append('<img src="%s"/>' % (media.get_low_resolution_url()))
90-
print(media)
9189
photos.append("<br/> <a href='/media_like/%s'>Like</a> <a href='/media_unlike/%s'>Un-Like</a> LikesCount=%s</div>" % (media.id,media.id,media.like_count))
9290
content += ''.join(photos)
9391
except Exception as e:
@@ -97,14 +95,14 @@ def on_recent():
9795
@route('/media_like/<id>')
9896
def media_like(id):
9997
access_token = request.session['access_token']
100-
api = client.InstagramAPI(access_token=access_token)
98+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
10199
api.like_media(media_id=id)
102100
redirect("/recent")
103101

104102
@route('/media_unlike/<id>')
105103
def media_unlike(id):
106104
access_token = request.session['access_token']
107-
api = client.InstagramAPI(access_token=access_token)
105+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
108106
api.unlike_media(media_id=id)
109107
redirect("/recent")
110108

@@ -115,7 +113,7 @@ def on_user_media_feed():
115113
if not access_token:
116114
return 'Missing Access Token'
117115
try:
118-
api = client.InstagramAPI(access_token=access_token)
116+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
119117
media_feed, next = api.user_media_feed()
120118
photos = []
121119
for media in media_feed:
@@ -138,7 +136,7 @@ def location_recent_media():
138136
if not access_token:
139137
return 'Missing Access Token'
140138
try:
141-
api = client.InstagramAPI(access_token=access_token)
139+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
142140
recent_media, next = api.location_recent_media(location_id=514276)
143141
photos = []
144142
for media in recent_media:
@@ -155,7 +153,7 @@ def media_search():
155153
if not access_token:
156154
return 'Missing Access Token'
157155
try:
158-
api = client.InstagramAPI(access_token=access_token)
156+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
159157
media_search = api.media_search(lat="37.7808851",lng="-122.3948632",distance=1000)
160158
photos = []
161159
for media in media_search:
@@ -172,7 +170,7 @@ def media_popular():
172170
if not access_token:
173171
return 'Missing Access Token'
174172
try:
175-
api = client.InstagramAPI(access_token=access_token)
173+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
176174
media_search = api.media_popular()
177175
photos = []
178176
for media in media_search:
@@ -189,7 +187,7 @@ def user_search():
189187
if not access_token:
190188
return 'Missing Access Token'
191189
try:
192-
api = client.InstagramAPI(access_token=access_token)
190+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
193191
user_search = api.user_search(q="Instagram")
194192
users = []
195193
for user in user_search:
@@ -206,7 +204,7 @@ def user_follows():
206204
if not access_token:
207205
return 'Missing Access Token'
208206
try:
209-
api = client.InstagramAPI(access_token=access_token)
207+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
210208
# 25025320 is http://instagram.com/instagram
211209
user_follows, next = api.user_follows('25025320')
212210
users = []
@@ -228,7 +226,7 @@ def location_search():
228226
if not access_token:
229227
return 'Missing Access Token'
230228
try:
231-
api = client.InstagramAPI(access_token=access_token)
229+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
232230
location_search = api.location_search(lat="37.7808851",lng="-122.3948632",distance=1000)
233231
locations = []
234232
for location in location_search:
@@ -245,8 +243,8 @@ def tag_search():
245243
if not access_token:
246244
return 'Missing Access Token'
247245
try:
248-
api = client.InstagramAPI(access_token=access_token)
249-
tag_search, next_tag = api.tag_search(q="catband")
246+
api = client.InstagramAPI(access_token=access_token, client_secret=CONFIG['client_secret'])
247+
tag_search, next_tag = api.tag_search(q="backclimateaction")
250248
tag_recent_media, next = api.tag_recent_media(tag_name=tag_search[0].name)
251249
photos = []
252250
for tag_media in tag_recent_media:

0 commit comments

Comments
 (0)