Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 477 lines (404 sloc) 14.045 kb
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
1 # encoding: utf-8
2 require 'sinatra'
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
3 require 'instagram'
7c38422 Mislav Marohnić lookup an Instagram user from Twitter screen name
authored
4 require 'active_support/core_ext/object/blank'
04ba3fe Mislav Marohnić extract Instagram::Cached (with instrumentation) and FailsafeStore
authored
5 require 'active_support/notifications'
0f2647b Mislav Marohnić switch from official lib to a micro-client for Instagram API
authored
6 require 'active_support/cache'
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
7 require 'active_support/core_ext/numeric/time'
8 require 'active_support/core_ext/integer/time'
9 require 'active_support/core_ext/time/acts_like'
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
10 require 'addressable/uri'
81f94f0 Mislav Marohnić more HTTP caching headers
authored
11 require 'digest/md5'
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
12 require 'haml'
49e8b6b Mislav Marohnić improve styles with compass
authored
13 require 'sass'
14 require 'compass'
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
15 require 'models'
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
16 require 'choices'
17
18 Choices.load_settings(File.join(settings.root, 'config.yml'), settings.environment.to_s).each do |key, value|
19 set key.to_sym, value
20 end
49e8b6b Mislav Marohnić improve styles with compass
authored
21
22 Compass.configuration do |config|
23 config.project_path = settings.root
24 config.sass_dir = 'views'
25 end
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
26
27 set :haml, format: :html5
f91eb56 Mislav Marohnić compress CSS in production
authored
28 set :scss do
29 Compass.sass_engine_options.merge style: settings.production? ? :compressed : :nested,
30 cache_location: File.join(ENV['TMPDIR'], 'sass-cache')
31 end
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
32
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
33 set(:search_index) {
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
34 search_client = IndexTank::Client.new(settings.indextank.api_url)
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
35 search_client.indexes('idx')
36 }
37
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
38 set(:cache_dir) { File.join(ENV['TMPDIR'], 'cache') }
39
0f2647b Mislav Marohnić switch from official lib to a micro-client for Instagram API
authored
40 Instagram.configure do |config|
41 for key, value in settings.instagram
42 config.send("#{key}=", value)
43 end
44
45 config.cache = ActiveSupport::Cache::FileStore.new settings.cache_dir,
46 namespace: 'instagram',
47 expires_in: settings.production? ? 3.minutes : 1.hour
48 end
49
04ba3fe Mislav Marohnić extract Instagram::Cached (with instrumentation) and FailsafeStore
authored
50 configure :development, :production do
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
51 Mingo.connect settings.mongodb.url
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
52 User.collection.create_index(:username, :unique => true)
53
04ba3fe Mislav Marohnić extract Instagram::Cached (with instrumentation) and FailsafeStore
authored
54 ActiveSupport::Cache::Store.instrument = true
55
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
56 ActiveSupport::Notifications.subscribe('search.indextank') do |name, start, ending, _, payload|
57 $stderr.puts 'IndexTank search for "%s" (%.3f s)' % [payload[:query], ending - start]
58 end
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
59
42de457 Mislav Marohnić login functionality
authored
60 strip_params = %w[access_token client_id client_secret]
0f2647b Mislav Marohnić switch from official lib to a micro-client for Instagram API
authored
61
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
62 ActiveSupport::Notifications.subscribe('request.faraday') do |name, start, ending, _, payload|
63 url = payload[:url]
42de457 Mislav Marohnić login functionality
authored
64 if url.query_values and (url.query_values.keys & strip_params).any?
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
65 url = url.dup
0f2647b Mislav Marohnić switch from official lib to a micro-client for Instagram API
authored
66 url.query_values = url.query_values.reject { |k,| strip_params.include? k }
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
67 end
68 $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, payload[:method].to_s.upcase, url.request_uri, ending - start]
69 end
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
70
04ba3fe Mislav Marohnić extract Instagram::Cached (with instrumentation) and FailsafeStore
authored
71 ActiveSupport::Notifications.subscribe(/^cache_(\w+).active_support$/) do |name, start, ending, _, payload|
72 case name.split('.').first
73 when 'cache_reuse_stale'
74 $stderr.puts "Error rebuilding cache: %s (%s)" % [payload[:key], payload[:exception].message]
75 when 'cache_generate'
76 $stderr.puts "Cache rebuild: %s (%.3f s)" % [payload[:key], ending - start]
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
77 when 'cache_read'
78 $stderr.puts "Cache hit: %s" % payload[:key] if payload[:hit]
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
79 end
80 end
04ba3fe Mislav Marohnić extract Instagram::Cached (with instrumentation) and FailsafeStore
authored
81 end
82
83 configure :development do
84 set :logging, false
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
85 end
86
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
87 FILTERS = {
88 1 => 'X-Pro II',
89 2 => 'Lomo-fi',
90 3 => 'Earlybird',
91 4 => 'Apollo',
92 5 => 'Poprocket',
93 10 => 'Inkwell',
94 13 => 'Gotham',
95 14 => '1977',
96 15 => 'Nashville',
97 16 => 'Lord Kelvin',
98 17 => 'Lily',
99 18 => 'Sutro',
100 19 => 'Toaster',
101 20 => 'Walden',
102 21 => 'Hefe'
103 }
104
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
105 helpers do
da36b34 Mislav Marohnić link back to instagr.am
authored
106 def instalink(text)
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
107 text.sub(/\b(on instagram)\b/i, '<span>\1</span>').
108 sub(/\b(instagram)\b/i, '<a href="http://instagr.am">\1</a>')
da36b34 Mislav Marohnić link back to instagr.am
authored
109 end
249322a Mislav Marohnić pagination
authored
110
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
111 def photo_url(photo)
112 absolute_url "/users/#{photo.user.username}#p#{photo.id}"
113 end
114
115 def user_url(user_id)
116 absolute_url "/users/#{user_id}"
a006a7e Mislav Marohnić user's atom feed
authored
117 end
d982194 Mislav Marohnić add atom feed for popular items
authored
118
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
119 def atom_path(user)
120 "/users/#{user.user_id}.atom"
d982194 Mislav Marohnić add atom feed for popular items
authored
121 end
122
123 def absolute_url(path)
124 abs_uri = "#{request.scheme}://#{request.host}"
125
126 if request.scheme == 'https' && request.port != 443 ||
127 request.scheme == 'http' && request.port != 80
128 abs_uri << ":#{request.port}"
129 end
130
131 abs_uri << path
132 end
c3c70e7 Mislav Marohnić fix pagination after page 2
authored
133
134 def root_path?
135 request.path == '/'
136 end
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
137
138 def user_path?
139 request.path.index('/users/') == 0
140 end
141
142 def search_path?
143 request.path.index('/search') == 0
144 end
145
146 def search_page(page)
147 Addressable::URI.parse(request.path).tap do |url|
148 url.query_values = params.merge('page' => page.to_s)
149 end
150 end
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
151
152 def last_modified_from_photos(photos)
153 if photos.any?
154 last_modified Time.at(photos.first.created_time.to_i)
155 end
156 end
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
157 end
158
159 get '/' do
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
160 @photos = Instagram::media_popular
d982194 Mislav Marohnić add atom feed for popular items
authored
161 @title = "Instagram popular photos"
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
162
e3207b3 Mislav Marohnić longer cache times
authored
163 expires 15.minutes, :public
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
164 haml :index
165 end
166
d982194 Mislav Marohnić add atom feed for popular items
authored
167 get '/popular.atom' do
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
168 @photos = Instagram::media_popular
d982194 Mislav Marohnić add atom feed for popular items
authored
169 @title = "Instagram popular photos"
170
171 content_type 'application/atom+xml', charset: 'utf-8'
e3207b3 Mislav Marohnić longer cache times
authored
172 expires 1.hour, :public
d982194 Mislav Marohnić add atom feed for popular items
authored
173 builder :feed, layout: false
174 end
175
42de457 Mislav Marohnić login functionality
authored
176 get '/login' do
177 return_url = request.url.split('?').first
178 begin
179 if params[:code]
180 token_response = Instagram::get_access_token(return_to: return_url, code: params[:code])
181 user = User.from_token token_response.body
182 redirect user_url(user.username)
183 elsif params[:error]
184 status 401
185 haml "%h1 Can't login: #{params[:error_description]}"
186 else
187 redirect Instagram::authorization_url(return_to: return_url).to_s
188 end
189 rescue Faraday::Error::ClientError => error
190 status 500
191 haml "%h1 Instagram error: #{error.response[:body]['error_message']}"
192 end
193 end
194
a006a7e Mislav Marohnić user's atom feed
authored
195 get '/users/:id.atom' do
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
196 @user = User[params[:id]]
197 @photos = @user.photos params[:max_id]
198 @title = "Photos by #{@user.username} on Instagram"
a006a7e Mislav Marohnić user's atom feed
authored
199
49e8b6b Mislav Marohnić improve styles with compass
authored
200 content_type 'application/atom+xml', charset: 'utf-8'
e3207b3 Mislav Marohnić longer cache times
authored
201 expires 1.hour, :public
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
202 last_modified_from_photos(@photos)
ab8a0e1 Mislav Marohnić serve JSONP at "/users/42.json?_callback=foo"
authored
203 builder :feed, layout: false
204 end
205
206 get '/users/:id.json' do
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
207 user = User[params[:id]]
208 callback = params['_callback']
209 raw_json = user.photos(params[:max_id], true)
ab8a0e1 Mislav Marohnić serve JSONP at "/users/42.json?_callback=foo"
authored
210
81f94f0 Mislav Marohnić more HTTP caching headers
authored
211 content_type "application/#{callback ? 'javascript' : 'json'}", charset: 'utf-8'
e3207b3 Mislav Marohnić longer cache times
authored
212 expires 1.hour, :public
81f94f0 Mislav Marohnić more HTTP caching headers
authored
213 etag Digest::MD5.hexdigest(raw_json)
ab8a0e1 Mislav Marohnić serve JSONP at "/users/42.json?_callback=foo"
authored
214
215 if callback
216 "#{callback}(#{raw_json.strip})"
217 else
218 raw_json
219 end
a006a7e Mislav Marohnić user's atom feed
authored
220 end
221
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
222 get '/users/:id' do
d09698d Mislav Marohnić more error handling; correct HTTP response codes
authored
223 begin
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
224 @user = User.lookup params[:id]
225 # redirect from numeric ID to username
226 redirect user_url(@user.username) unless params[:id] =~ /\D/
227 @photos = @user.photos params[:max_id]
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
228 @per_page = 20
d09698d Mislav Marohnić more error handling; correct HTTP response codes
authored
229 rescue Net::HTTPServerException => e
230 if 404 == e.response.code.to_i
231 status 404
232 haml "%h1 No such user\n%p Instagram couldn't resolve this user ID"
233 else
234 status 500
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
235 haml "%h1 Error fetching data from Instagram"
d09698d Mislav Marohnić more error handling; correct HTTP response codes
authored
236 end
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
237 rescue User::NotFound
238 status 404
239 haml "%h1 Unrecognized username\n%p We don't know user “#{params[:id]}”.\n" +
240 "%p If this is your Instagram username, please go through the <a href='/help'>user discovery process</a>"
241 else
242 @title = "Photos by #{@user.username} on Instagram"
243
244 expires 30.minutes, :public
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
245 last_modified_from_photos(@photos)
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
246 haml(request.xhr? ? :photos : :index)
d09698d Mislav Marohnić more error handling; correct HTTP response codes
authored
247 end
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
248 end
249
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
250 get '/search' do
251 @query = params[:q]
252 @title = "#{@query}” on Instagram"
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
253 @tags = Instagram::tag_search(@query)
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
254
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
255 @filter_name = FILTERS[params[:filter].to_i]
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
256 @photos = IndexedPhoto.paginate(@query, :page => params[:page], :filter => @filter_name)
257
258 expires 10.minutes, :public
259 haml(request.xhr? ? :photos : :index)
260 end
261
ec6362a Mislav Marohnić integrate Instagram hashtags with search
authored
262 get '/tags/:tag' do
263 @tag = params[:tag]
264 @title = "Photos tagged ##{@tag} on Instagram"
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
265 @photos = Instagram::tag_recent_media(@tag, max_id: params[:max_id], count: 20)
266 @per_page = 20
ec6362a Mislav Marohnić integrate Instagram hashtags with search
authored
267
268 expires 10.minutes, :public
269 haml(request.xhr? ? :photos : :index)
270 end
271
eea1cdc Mislav Marohnić help page + user ID discovery
authored
272 get '/help' do
273 @title = "Help page"
e3207b3 Mislav Marohnić longer cache times
authored
274 expires 1.month, :public
eea1cdc Mislav Marohnić help page + user ID discovery
authored
275 haml :help
276 end
277
278 post '/users/discover' do
279 begin
7c38422 Mislav Marohnić lookup an Instagram user from Twitter screen name
authored
280 url = params[:url].presence
281 twitter = params[:twitter].presence
282 twitter_id = nil
283
284 if twitter and not url
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
285 url, twitter_id = Instagram::Discovery.search_twitter(params[:twitter])
7c38422 Mislav Marohnić lookup an Instagram user from Twitter screen name
authored
286 end
287
288 user = User.find_by_instagram_url(url)
289
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
290 if user
7c38422 Mislav Marohnić lookup an Instagram user from Twitter screen name
authored
291 if twitter_id
292 user.twitter = twitter
293 user.twitter_id = twitter_id
294 user.save
295 end
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
296 redirect user_url(user.username)
eea1cdc Mislav Marohnić help page + user ID discovery
authored
297 else
d09698d Mislav Marohnić more error handling; correct HTTP response codes
authored
298 status 500
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
299 haml "%h1 Sorry\n%p The user ID couldn't be discovered on this page.\n" +
300 "%p <strong>Note:</strong> you <em>must</em> have a profile picture on Instagram."
eea1cdc Mislav Marohnić help page + user ID discovery
authored
301 end
302 rescue
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
303 raise unless settings.production?
d09698d Mislav Marohnić more error handling; correct HTTP response codes
authored
304 status 500
eea1cdc Mislav Marohnić help page + user ID discovery
authored
305 haml "%h1 Error\n%p The user ID couldn't be discovered because of an error"
306 end
307 end
308
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
309 get '/screen.css' do
e3207b3 Mislav Marohnić longer cache times
authored
310 expires 1.month, :public
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
311 scss :style
312 end
313
314 __END__
315 @@ layout
316 !!!
317 %title&= @title
318 %meta{ 'http-equiv' => 'content-type', content: 'text/html; charset=utf-8' }
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
319 %meta{ name: 'viewport', content: 'initial-scale=1.0; maximum-scale=1.0; user-scalable=0;' }
320 %link{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }
88a829e Mislav Marohnić favicon
authored
321 %link{ rel: 'favicon', href: '/favicon.ico' }
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
322 / %meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }
323 / %meta{ name: 'apple-mobile-web-app-status-bar-style', content: 'black' }
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
324 %link{ href: "/screen.css", rel: "stylesheet" }
a006a7e Mislav Marohnić user's atom feed
authored
325 - if @user
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
326 %link{ href: atom_path(@user), rel: 'alternate', title: "#{@user.username}'s photos", type: 'application/atom+xml' }
c3c70e7 Mislav Marohnić fix pagination after page 2
authored
327 - elsif root_path?
d982194 Mislav Marohnić add atom feed for popular items
authored
328 %link{ href: "/popular.atom", rel: 'alternate', title: @title, type: 'application/atom+xml' }
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
329
330 = yield
331
87fe71d Mislav Marohnić start Analytics
authored
332 - if settings.production?
333 :javascript
334 var _gaq = _gaq || [];
335 _gaq.push(['_setAccount', 'UA-87067-8']);
e690a13 Mislav Marohnić advanced Analytics tracking
authored
336 _gaq.push(['_setDetectFlash', false]);
87fe71d Mislav Marohnić start Analytics
authored
337 _gaq.push(['_trackPageview']);
338
339 (function() {
340 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
341 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
342 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
343 })();
344
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
345 @@ index
346 %header
347 %h1
348 - if @user
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
349 %img{ src: @user.instagram_info.profile_picture, class: 'avatar' }
da36b34 Mislav Marohnić link back to instagr.am
authored
350 = instalink @title
c3c70e7 Mislav Marohnić fix pagination after page 2
authored
351 - if root_path?
d982194 Mislav Marohnić add atom feed for popular items
authored
352 %a{ href: "/popular.atom", class: 'feed' }
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
353 %img{ src: '/feed.png', alt: 'feed', width: 14, height: 14 }
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
354
355 - if root_path? or search_path?
356 %form{ action: '/search', method: 'get' }
357 %p
358 %input{ type: 'search', name: 'q', placeholder: 'search photos', value: @query }
359 %select{ name: 'filter' }
c5973c5 Mislav Marohnić improve search form
authored
360 %option{ value: '' } any filter
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
361 - FILTERS.each do |code, name|
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
362 %option{ value: code, selected: @filter_name == name }&= name
363 %input{ type: 'submit', value: 'Search' }
364 - elsif @user
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
365 %p.stats
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
366 &= @user.instagram_info.full_name
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
367 &#8226;
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
368 = @user.instagram_info.counts.followed_by
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
369 followers
0bc4b70 Mislav Marohnić expose the Atom feed on user page
authored
370 &#8226;
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
371 %a{ href: atom_path(@user), class: 'feed' }
0bc4b70 Mislav Marohnić expose the Atom feed on user page
authored
372 %span photo feed
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
373 %img{ src: '/feed.png', alt: '', width: 14, height: 14 }
ec6362a Mislav Marohnić integrate Instagram hashtags with search
authored
374
375 - if @tags and @tags.any?
376 %ol.tags
377 - for tag in @tags.sort_by(&:media_count).reverse[0, 6]
378 %li
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
379 %a{ href: "/tags/#{tag.name}" }== ##{tag.name}
ec6362a Mislav Marohnić integrate Instagram hashtags with search
authored
380 %span== (#{tag.media_count})
381
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
382 - if search_path?
383 %p.stats
384 == Found <b>#{@photos.total_entries}</b> items
385 - if @filter_name
386 == using the “#{@filter_name}” filter
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
387
388 %ol#photos
249322a Mislav Marohnić pagination
authored
389 = haml :photos
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
390
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
391 - if search_path?
392 %p.footnote
393 <strong>Note:</strong> search is limited &mdash; not all photos appear in the results.
394
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
395 %footer
396 %p
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
397 - unless root_path?
d588bb2 Mislav Marohnić link home
authored
398 &larr; <a href="/">Home</a> &#8226;
eea1cdc Mislav Marohnić help page + user ID discovery
authored
399 <a href="/help">Help</a> &#8226;
da36b34 Mislav Marohnić link back to instagr.am
authored
400 App made by <a href="http://twitter.com/mislav">@mislav</a>
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
401 (<a href="/users/mislav" title="Mislav's photos">photos</a>)
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
402
403 :javascript
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
404 var src, script
405 if (navigator.userAgent.match(/WebKit\b/)) src = '/zepto.min.js'
406 else src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'
407 script = document.createElement('script')
408 script.src = src
409 script.async = 'async'
410 document.body.appendChild(script)
411
412 %script{ src: '/app.js' }
249322a Mislav Marohnić pagination
authored
413
414 @@ photos
415 - for photo in @photos
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
416 %li{ id: "media_#{photo.id}" }
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
417 %a{ href: photo.images.standard_resolution.url, class: 'thumb' }
418 %img{ src: photo.images.thumbnail.url, width: 150, height: 150 }
249322a Mislav Marohnić pagination
authored
419 .full{ style: 'display:none' }
420 %img{ width: 480, height: 480 }
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
421 .caption
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
422 - if photo.caption
423 %h2= photo.caption.text
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
424 .author
425 by
6ad5238 Mislav Marohnić fix user name
authored
426 - user_name = photo.user.full_name.presence || photo.user.username
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
427 - if photo.user.id
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
428 %a{ href: "/users/#{photo.user.id}" }&= user_name
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
429 - else
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
430 &= user_name
ef09f42 Mislav Marohnić iPhone & iPad styles, loading indicators, back button
authored
431 .close
432 %a{ href: "#close" } close
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
433
ec6362a Mislav Marohnić integrate Instagram hashtags with search
authored
434 - if @photos.respond_to?(:next_page) ? @photos.next_page : (@photos.length >= (@per_page || 20) and not root_path?)
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
435 - href = search_path? ? search_page(@photos.next_page) : request.path + "?max_id=#{@photos.last.id}"
249322a Mislav Marohnić pagination
authored
436 %li.pagination
feb0cea Mislav Marohnić search functionality (made possible by @dbasch)
authored
437 %a{ href: href } <span>Load more &rarr;</span>
a0a5168 Mislav Marohnić mini app to display popular/per-user photos
authored
438
a006a7e Mislav Marohnić user's atom feed
authored
439 @@ feed
440 schema_date = 2010
d982194 Mislav Marohnić add atom feed for popular items
authored
441 popular = request.path.include? 'popular'
a006a7e Mislav Marohnić user's atom feed
authored
442
4a80fdf Mislav Marohnić fix atom feed
authored
443 xml.feed "xml:lang" => "en-US", xmlns: 'http://www.w3.org/2005/Atom' do
444 xml.id "tag:#{request.host},#{schema_date}:#{request.path.split(".")[0]}"
d982194 Mislav Marohnić add atom feed for popular items
authored
445 xml.link rel: 'alternate', type: 'text/html', href: request.url.split(popular ? 'popular' : '.')[0]
4a80fdf Mislav Marohnić fix atom feed
authored
446 xml.link rel: 'self', type: 'application/atom+xml', href: request.url
a006a7e Mislav Marohnić user's atom feed
authored
447
448 xml.title @title
4a80fdf Mislav Marohnić fix atom feed
authored
449
450 if @photos.any?
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
451 xml.updated Time.at(@photos.first.created_time.to_i).xmlschema
d982194 Mislav Marohnić add atom feed for popular items
authored
452 xml.author { xml.name @photos.first.user.full_name } unless popular
4a80fdf Mislav Marohnić fix atom feed
authored
453 end
a006a7e Mislav Marohnić user's atom feed
authored
454
455 for photo in @photos
456 xml.entry do
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
457 xml.title((photo.caption && photo.caption.text) || 'Photo')
4a80fdf Mislav Marohnić fix atom feed
authored
458 xml.id "tag:#{request.host},#{schema_date}:Instagram::Media/#{photo.id}"
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
459 xml.published Time.at(photo.created_time.to_i).xmlschema
d982194 Mislav Marohnić add atom feed for popular items
authored
460
461 if popular
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
462 xml.link rel: 'alternate', type: 'text/html', href: user_url(photo.user.id)
d982194 Mislav Marohnić add atom feed for popular items
authored
463 xml.author { xml.name photo.user.full_name }
80cdad6 Mislav Marohnić allow known Instagram usernames in URLs
authored
464 else
465 xml.link rel: 'alternate', type: 'text/html', href: photo_url(photo)
d982194 Mislav Marohnić add atom feed for popular items
authored
466 end
467
4a80fdf Mislav Marohnić fix atom feed
authored
468 xml.content type: 'xhtml' do |content|
469 content.div xmlns: "http://www.w3.org/1999/xhtml" do
57ef16d Mislav Marohnić switch to public API and official ruby client
authored
470 content.img src: photo.images.low_resolution.url, width: 306, height: 306, alt: photo.caption && photo.caption.text
471 content.p "#{photo.likes.count} likes" if popular
4a80fdf Mislav Marohnić fix atom feed
authored
472 end
a006a7e Mislav Marohnić user's atom feed
authored
473 end
474 end
475 end
476 end
Something went wrong with that request. Please try again.