instagram 0.3.2 → 0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +3 -0
  3. data/.yardopts +9 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE.md +20 -0
  6. data/README.md +144 -55
  7. data/Rakefile +21 -9
  8. data/instagram.gemspec +41 -0
  9. data/lib/faraday/oauth2.rb +36 -0
  10. data/lib/faraday/raise_http_4xx.rb +37 -0
  11. data/lib/faraday/raise_http_5xx.rb +29 -0
  12. data/lib/instagram.rb +21 -55
  13. data/lib/instagram/api.rb +23 -0
  14. data/lib/instagram/client.rb +19 -0
  15. data/lib/instagram/client/comments.rb +62 -0
  16. data/lib/instagram/client/likes.rb +58 -0
  17. data/lib/instagram/client/locations.rb +59 -0
  18. data/lib/instagram/client/media.rb +63 -0
  19. data/lib/instagram/client/real_time.rb +8 -0
  20. data/lib/instagram/client/subscriptions.rb +141 -0
  21. data/lib/instagram/client/tags.rb +59 -0
  22. data/lib/instagram/client/users.rb +165 -0
  23. data/lib/instagram/client/utils.rb +15 -0
  24. data/lib/instagram/configuration.rb +90 -0
  25. data/lib/instagram/connection.rb +31 -0
  26. data/lib/instagram/error.rb +16 -0
  27. data/lib/instagram/oauth.rb +27 -0
  28. data/lib/instagram/request.rb +45 -0
  29. data/lib/instagram/version.rb +3 -0
  30. data/spec/faraday/response_spec.rb +28 -0
  31. data/spec/fixtures/access_token.json +9 -0
  32. data/spec/fixtures/followed_by.json +1 -0
  33. data/spec/fixtures/follows.json +1 -0
  34. data/spec/fixtures/location.json +1 -0
  35. data/spec/fixtures/location_recent_media.json +1 -0
  36. data/spec/fixtures/location_search.json +1 -0
  37. data/spec/fixtures/media.json +1 -0
  38. data/spec/fixtures/media_comment.json +1 -0
  39. data/spec/fixtures/media_comment_deleted.json +1 -0
  40. data/spec/fixtures/media_comments.json +1 -0
  41. data/spec/fixtures/media_liked.json +1 -0
  42. data/spec/fixtures/media_likes.json +1 -0
  43. data/spec/fixtures/media_popular.json +1 -0
  44. data/spec/fixtures/media_search.json +1 -0
  45. data/spec/fixtures/media_unliked.json +1 -0
  46. data/spec/fixtures/mikeyk.json +1 -0
  47. data/spec/fixtures/recent_media.json +1 -0
  48. data/spec/fixtures/requested_by.json +12 -0
  49. data/spec/fixtures/shayne.json +1 -0
  50. data/spec/fixtures/subscription.json +12 -0
  51. data/spec/fixtures/subscription_deleted.json +1 -0
  52. data/spec/fixtures/subscription_payload.json +14 -0
  53. data/spec/fixtures/subscriptions.json +22 -0
  54. data/spec/fixtures/tag.json +1 -0
  55. data/spec/fixtures/tag_recent_media.json +1 -0
  56. data/spec/fixtures/tag_search.json +1 -0
  57. data/spec/fixtures/user_media_feed.json +1 -0
  58. data/spec/fixtures/user_search.json +1 -0
  59. data/spec/instagram/api_spec.rb +110 -0
  60. data/spec/instagram/client/comments_spec.rb +71 -0
  61. data/spec/instagram/client/likes_spec.rb +66 -0
  62. data/spec/instagram/client/locations_spec.rb +78 -0
  63. data/spec/instagram/client/media_spec.rb +78 -0
  64. data/spec/instagram/client/real_time_spec.rb +13 -0
  65. data/spec/instagram/client/subscriptions_spec.rb +118 -0
  66. data/spec/instagram/client/tags_spec.rb +78 -0
  67. data/spec/instagram/client/users_spec.rb +237 -0
  68. data/spec/instagram/client_spec.rb +23 -0
  69. data/spec/instagram_spec.rb +97 -0
  70. data/spec/spec_helper.rb +54 -0
  71. metadata +265 -33
  72. data/MIT-LICENSE +0 -18
  73. data/lib/instagram/cached.rb +0 -25
  74. data/lib/instagram/failsafe_store.rb +0 -52
  75. data/lib/instagram/models.rb +0 -163
@@ -1,18 +0,0 @@
1
- Copyright (c) 2010 Mislav Marohnić
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of
4
- this software and associated documentation files (the "Software"), to deal in
5
- the Software without restriction, including without limitation the rights to
6
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
- the Software, and to permit persons to whom the Software is furnished to do so,
8
- subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,25 +0,0 @@
1
- require 'instagram'
2
- require 'instagram/failsafe_store'
3
-
4
- module Instagram
5
- module Cached
6
- extend Instagram
7
-
8
- class << self
9
- attr_accessor :cache
10
-
11
- def setup(cache_dir, options = {})
12
- self.cache = FailsafeStore.new(cache_dir, {
13
- namespace: 'instagram',
14
- exceptions: [Net::HTTPServerException, JSON::ParserError]
15
- }.update(options))
16
- end
17
-
18
- private
19
- def get_url(url)
20
- cache.fetch(url.to_s) { super }
21
- end
22
- end
23
-
24
- end
25
- end
@@ -1,52 +0,0 @@
1
- require 'active_support/cache'
2
-
3
- module Instagram
4
- class FailsafeStore < ActiveSupport::Cache::FileStore
5
- # Reuses the stale cache if a known exception occurs while yielding to the block.
6
- # The list of exception classes is read from the ":exceptions" array.
7
- def fetch(name, options = nil)
8
- options = merged_options(options)
9
- key = namespaced_key(name, options)
10
- entry = unless options[:force]
11
- instrument(:read, name, options) do |payload|
12
- payload[:super_operation] = :fetch if payload
13
- read_entry(key, options)
14
- end
15
- end
16
-
17
- if entry and not entry.expired?
18
- instrument(:fetch_hit, name, options) { |payload| }
19
- entry.value
20
- else
21
- reusing_stale = false
22
-
23
- result = begin
24
- instrument(:generate, name, options) do |payload|
25
- yield
26
- end
27
- rescue
28
- if entry and ignore_exception?($!)
29
- reusing_stale = true
30
- instrument(:reuse_stale, name, options) do |payload|
31
- payload[:exception] = $! if payload
32
- entry.value
33
- end
34
- else
35
- # TODO: figure out if deleting entries is ever necessary
36
- # delete_entry(key, options) if entry
37
- raise
38
- end
39
- end
40
-
41
- write(name, result, options) unless reusing_stale
42
- result
43
- end
44
- end
45
-
46
- private
47
-
48
- def ignore_exception?(ex)
49
- options[:exceptions] && options[:exceptions].any? { |klass| ex.is_a? klass }
50
- end
51
- end
52
- end
@@ -1,163 +0,0 @@
1
- require 'yajl/json_gem'
2
- require 'nibbler/json'
3
-
4
- module Instagram
5
-
6
- class Base < NibblerJSON
7
- # `pk` is such a dumb property name
8
- element 'pk' => :id
9
- end
10
-
11
- class User < Base
12
- element :username
13
- element :full_name
14
- element 'profile_pic_url' => :avatar_url
15
- alias avatar avatar_url # `avatar` is deprecated
16
-
17
- # extended info
18
- element :media_count
19
- element :following_count
20
- alias following following_count # `following` will return an array of users in future!
21
- element :follower_count
22
- alias followers follower_count # `followers` will return an array of users in future!
23
-
24
- def ==(other)
25
- User === other and other.id == self.id
26
- end
27
- end
28
-
29
- class UserWrap < NibblerJSON
30
- element :user, :with => User
31
- # return user instead of self when done
32
- def parse() super.user end
33
- end
34
-
35
- class Media < Base
36
- # short string used for permalink
37
- element :code
38
- # type is always 1 (other values possibly reserved for video in the future?)
39
- element :media_type
40
- # filter code; use `filter_name` to get human name of the filter used
41
- element :filter_type
42
- # I don't know what "device timestamp" is and how it relates to `taken_at`?
43
- element :device_timestamp
44
- # timestamp of when the picture was taken
45
- element :taken_at, :with => lambda { |sec| Time.at(sec) }
46
- # user who uploaded the media
47
- element :user, :with => User
48
-
49
- # array of people who liked this media
50
- elements :likers, :with => User
51
- # user IDs of people who liked this (only if "likers" are not present)
52
- element :liker_ids
53
-
54
- elements :comments, :with => NibblerJSON do
55
- element :created_at, :with => lambda { |sec| Time.at(sec) }
56
- # content type is always "comment"
57
- element :content_type
58
- # `type` is always 1 (other values possibly reserved for comments in form of media?)
59
- element :type
60
- # the `pk` of parent media
61
- element :media_id
62
- # comment body
63
- element :text
64
- # comment author
65
- element :user, :with => User
66
- end
67
-
68
- elements 'image_versions' => :images, :with => NibblerJSON do
69
- element :url
70
- # `type` is 5 for 150px, 6 for 306px and 7 for 612px
71
- element :type
72
- element :width
73
- element :height
74
-
75
- alias to_s url
76
- end
77
-
78
- # image location
79
- element :lat
80
- element :lng
81
-
82
- def geolocated?
83
- self.lat and self.lng
84
- end
85
-
86
- element :location, :with => Base do
87
- # ID on a 3rd-party service
88
- element :external_id
89
- # name of 3rd-party service, like "foursquare"
90
- element :external_source
91
- # name of location
92
- element :name
93
- # address in the external service's database
94
- element :address
95
- element :lat
96
- element :lng
97
- end
98
-
99
- # author's caption for the image; can be nil
100
- def caption
101
- # caption is implemented as a first comment made by the owner
102
- if comments.first and self.user == comments.first.user
103
- comments.first.text
104
- end
105
- end
106
-
107
- # typical sizes: 150px / 306px / 612px square
108
- def image_url(size = 150)
109
- self.images.find { |img| img.width == size }.to_s
110
- end
111
-
112
- FILTERS = {
113
- 1 => 'X-Pro II',
114
- 2 => 'Lomo-fi',
115
- 3 => 'Earlybird',
116
- 4 => 'Apollo',
117
- 5 => 'Poprocket',
118
- 10 => 'Inkwell',
119
- 13 => 'Gotham',
120
- 14 => '1977',
121
- 15 => 'Nashville',
122
- 16 => 'Lord Kelvin',
123
- 17 => 'Lily',
124
- 18 => 'Sutro',
125
- 19 => 'Toaster',
126
- 20 => 'Walden',
127
- 21 => 'Hefe'
128
- }
129
-
130
- def filter_name
131
- FILTERS[filter_type.to_i]
132
- end
133
- end
134
-
135
- class Tag < String
136
- attr_reader :media_count
137
-
138
- def initialize(str, count)
139
- super(str)
140
- @media_count = count
141
- end
142
-
143
- def self.parse(hash)
144
- new hash['name'], hash['media_count']
145
- end
146
-
147
- def inspect
148
- "#{super} (#{media_count})"
149
- end
150
- end
151
-
152
- class SearchTagsResults < NibblerJSON
153
- elements :results, :with => Tag
154
- def parse() super.results end
155
- end
156
-
157
- class Timeline < NibblerJSON
158
- elements :items, :with => Media
159
- # return items instead of self when done
160
- def parse() super.items end
161
- end
162
-
163
- end