appilf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +15 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +36 -0
  4. data/.travis.yml +17 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +72 -0
  7. data/LICENSE +21 -0
  8. data/README.md +191 -0
  9. data/Rakefile +8 -0
  10. data/appilf.gemspec +32 -0
  11. data/lib/appilf.rb +29 -0
  12. data/lib/appilf/api_actions.rb +49 -0
  13. data/lib/appilf/appilf_object.rb +52 -0
  14. data/lib/appilf/authentication.rb +38 -0
  15. data/lib/appilf/client.rb +42 -0
  16. data/lib/appilf/client/alerts.rb +21 -0
  17. data/lib/appilf/client/domain_traits.rb +20 -0
  18. data/lib/appilf/client/saved_searches.rb +25 -0
  19. data/lib/appilf/client/users.rb +20 -0
  20. data/lib/appilf/client/watched_items.rb +30 -0
  21. data/lib/appilf/domain_trait.rb +11 -0
  22. data/lib/appilf/error.rb +22 -0
  23. data/lib/appilf/listing.rb +29 -0
  24. data/lib/appilf/resource_page.rb +62 -0
  25. data/lib/appilf/saved_search.rb +11 -0
  26. data/lib/appilf/user.rb +11 -0
  27. data/lib/appilf/util.rb +63 -0
  28. data/lib/appilf/version.rb +3 -0
  29. data/lib/appilf/watched_item.rb +12 -0
  30. data/spec/client/alerts_spec.rb +30 -0
  31. data/spec/client/client_spec.rb +58 -0
  32. data/spec/client/domain_traits_spec.rb +22 -0
  33. data/spec/client/saved_searches_spec.rb +35 -0
  34. data/spec/client/users_spec.rb +18 -0
  35. data/spec/client/watched_items_spec.rb +42 -0
  36. data/spec/domain_trait_spec.rb +17 -0
  37. data/spec/listing_spec.rb +190 -0
  38. data/spec/mocked_responses/client/alerts.json +7 -0
  39. data/spec/mocked_responses/client/authentication_token.json +4 -0
  40. data/spec/mocked_responses/client/domain_trait/domain_trait.json +6 -0
  41. data/spec/mocked_responses/client/domain_trait/domain_traits.json +16 -0
  42. data/spec/mocked_responses/client/saved_search/saved_search.json +7 -0
  43. data/spec/mocked_responses/client/saved_search/saved_searches.json +23 -0
  44. data/spec/mocked_responses/client/user.json +12 -0
  45. data/spec/mocked_responses/client/watched_item.json +29 -0
  46. data/spec/mocked_responses/listing/listing.json +48 -0
  47. data/spec/mocked_responses/listing/listing_page_1.json +1393 -0
  48. data/spec/mocked_responses/listing/listing_page_2.json +1393 -0
  49. data/spec/mocked_responses/listing/listing_page_5.json +4622 -0
  50. data/spec/saved_search_spec.rb +21 -0
  51. data/spec/spec_helper.rb +57 -0
  52. data/spec/user_spec.rb +26 -0
  53. metadata +215 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzJlODYzOWIzZDUwZTc1ZGMxZGFkMjA0NTI0NWJiMjFkMWMwOWUzNg==
5
+ data.tar.gz: !binary |-
6
+ MTVjZGRhYjE4MTg2ZWY0NjU4YTFjMGY0MGI4YmM2NWRmOWY0OWIxZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZDdhZWQyM2MwZjkyYThkNDdkMjkzNjFlMTZmOTBkMzg5YjcyMzQ1NWJiMjk4
10
+ MWJkYjA4MjJlN2EzYjAwOTU3ODQ3ZjY2OTkxMGU1NDRkOWZlZDY4Zjg0YzNm
11
+ NDNhNGI1YTQ1NTJmMzkxZTViZTMzNzkyZGNlMzg3ZTI1OWEyZjc=
12
+ data.tar.gz: !binary |-
13
+ MmQ0ZjFmZWZlY2Y3NzExNTQ4NjM5Y2I4ZDg5MmZhNWU5YzdhMjU2ZGFjZWQx
14
+ YWNiYmUwNmFlYjc4NmYwYWIyODIwYmVlMzA4ZDI4N2JlNTJmNDNiMWRhZGQ5
15
+ NDA5MWIxNGY2MjNjOWNiZDk4MTlkOTU1OThiODUzOThkOGU5MzQ=
@@ -0,0 +1 @@
1
+ service_name: travis-ci
@@ -0,0 +1,36 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalization:
25
+ /.bundle/
26
+ /vendor/bundle
27
+ /lib/bundler/man/
28
+
29
+ # for a library or gem, you might want to ignore these files since the code is
30
+ # intended to run in multiple environments; otherwise, check them in:
31
+ # Gemfile.lock
32
+ # .ruby-version
33
+ # .ruby-gemset
34
+
35
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
+ .rvmrc
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ cache: bundler
3
+
4
+ rvm:
5
+ - 2.2.0
6
+ - 2.1.0
7
+ - 2.0.0
8
+ - 1.9.3
9
+
10
+ script: 'bundle exec rake spec'
11
+
12
+ notifications:
13
+ email:
14
+ recipients:
15
+ - rogelio.sevilla1@gmail.com
16
+ on_failure: change
17
+ on_success: never
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in appilf.gemspec
4
+ gemspec
@@ -0,0 +1,72 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ appilf (0.1.0)
5
+ json (~> 1.8)
6
+ methodize (~> 0.3)
7
+ rest-client (~> 1.4)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.4.0)
13
+ coveralls (0.8.10)
14
+ json (~> 1.8)
15
+ rest-client (>= 1.6.8, < 2)
16
+ simplecov (~> 0.11.0)
17
+ term-ansicolor (~> 1.3)
18
+ thor (~> 0.19.1)
19
+ tins (~> 1.6.0)
20
+ crack (0.4.3)
21
+ safe_yaml (~> 1.0.0)
22
+ diff-lcs (1.2.5)
23
+ docile (1.1.5)
24
+ domain_name (0.5.25)
25
+ unf (>= 0.0.5, < 1.0.0)
26
+ hashdiff (0.2.3)
27
+ http-cookie (1.0.2)
28
+ domain_name (~> 0.5)
29
+ json (1.8.3)
30
+ methodize (0.3.1)
31
+ mime-types (2.99)
32
+ netrc (0.11.0)
33
+ rake (0.9.6)
34
+ rest-client (1.8.0)
35
+ http-cookie (>= 1.0.2, < 2.0)
36
+ mime-types (>= 1.16, < 3.0)
37
+ netrc (~> 0.7)
38
+ rspec (2.99.0)
39
+ rspec-core (~> 2.99.0)
40
+ rspec-expectations (~> 2.99.0)
41
+ rspec-mocks (~> 2.99.0)
42
+ rspec-core (2.99.2)
43
+ rspec-expectations (2.99.2)
44
+ diff-lcs (>= 1.1.3, < 2.0)
45
+ rspec-mocks (2.99.4)
46
+ safe_yaml (1.0.4)
47
+ simplecov (0.11.1)
48
+ docile (~> 1.1.0)
49
+ json (~> 1.8)
50
+ simplecov-html (~> 0.10.0)
51
+ simplecov-html (0.10.0)
52
+ term-ansicolor (1.3.2)
53
+ tins (~> 1.0)
54
+ thor (0.19.1)
55
+ tins (1.6.0)
56
+ unf (0.1.4)
57
+ unf_ext
58
+ unf_ext (0.0.7.1)
59
+ webmock (1.22.6)
60
+ addressable (>= 2.3.6)
61
+ crack (>= 0.3.2)
62
+ hashdiff
63
+
64
+ PLATFORMS
65
+ ruby
66
+
67
+ DEPENDENCIES
68
+ appilf!
69
+ coveralls (~> 0.8)
70
+ rake (~> 0.9)
71
+ rspec (~> 2.11)
72
+ webmock (~> 1.22)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Rogelio Sevilla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,191 @@
1
+ # Appilf (╯°□°)╯︵ ┻━┻
2
+
3
+ [![Build Status](https://travis-ci.org/rogeliosevilla1/appilf.svg?branch=master)](https://travis-ci.org/rogeliosevilla1/appilf)
4
+
5
+ [![Coverage Status](https://coveralls.io/repos/github/rogeliosevilla1/appilf/badge.svg?branch=master)](https://coveralls.io/github/rogeliosevilla1/appilf?branch=master)
6
+
7
+ Appilf is a simple Ruby wrapper for Flippa's API (https://developers.flippa.com/),
8
+ currently covering the following resources:
9
+
10
+
11
+ ##Authentication not required
12
+
13
+ * Listings
14
+
15
+ ##Authentication required
16
+
17
+ * Users
18
+ * Domain Traits
19
+ * Alerts
20
+ * Saved Searches
21
+ * Watched Items
22
+
23
+
24
+ ##Authentication
25
+
26
+ As of now, Appilf only supports authentication through Password Grant
27
+ (https://developers.flippa.com/#client-credentials-grant). There are 2 ways to initialize the client:
28
+
29
+ ```ruby
30
+ client = Appilf::Client.new(username: 'fat@dog.com', password: 'some_password')
31
+ client.access_token => 'token used to make authorized requests'
32
+ ```
33
+
34
+ If you already have a token...
35
+
36
+ ```ruby
37
+ client = Appilf::Client.new(access_token: 'sometoken')
38
+ ```
39
+
40
+
41
+ ##Paginated Resources
42
+
43
+ When calling a resource paginated by Flippa, Appilf will return an instance of `Appilf::ResourcePage`.
44
+ You can use the `next` and `prev` methods to retrieve another page using the current page as reference.
45
+ You can access the loaded items through its `items` array or iterate it directly with `each` (e.g.)
46
+
47
+ ```ruby
48
+ resource_page = Appilf::Listing.list
49
+ resource_page.each do |item|
50
+ item.id
51
+ end
52
+ next_page = resource_page.next
53
+ ```
54
+
55
+ The object will return `nil` if you try to navigate to a non existent page.
56
+
57
+ You can use the `:page_number` and `:page_size` modifiers when calling a paginated resource
58
+ to increase the default page size or to retrieve an specific page. (e.g.)
59
+
60
+ ```ruby
61
+ resource_page = Appilf::Listing.list(page_size: 100, page_number: 3)
62
+ ```
63
+
64
+ Be aware that Flippa limits all paginated resources to the first 200 pages, after that, you will get
65
+ an `Appilf::BadRequest` error (https://developers.flippa.com/#pagination) (e.g)
66
+
67
+ ```ruby
68
+ #this raises an Appilf::BadRequest error
69
+ Appilf::Listing.list(page_number: 201)
70
+ ```
71
+
72
+
73
+ ##Listings
74
+
75
+ Listings are for now the only resource that does not require authentication and it's paginated by
76
+ Flippa. You can retrieve the first page of Listings by doing:
77
+
78
+ ```
79
+ Appilf::Listing.list
80
+ ```
81
+
82
+ ###Sorting
83
+
84
+ Per Flippa's documentation, you can send a query parameter to sort the results...
85
+
86
+ ```
87
+ Appilf::Listing.list(sort_alias: 'most active')
88
+ ```
89
+
90
+ To see all the supported values please refer to the "SORT ALIAS PARAMETERS" section
91
+ within Flippa's documentation on Listings (https://developers.flippa.com/#list-all-listings)
92
+
93
+
94
+
95
+ ###Search Templates
96
+
97
+ Per Flippa's documentation, you can send a query parameter to do a custom search using their
98
+ predefined templates.
99
+
100
+ ```
101
+ Appilf::Listing.list(search_template: 'apps_ending_soon')
102
+ ```
103
+
104
+ To see all the supported values please refer to the "SEARCH TEMPLATES" section
105
+ within Flippa's documentation on Listings (https://developers.flippa.com/#list-all-listings)
106
+
107
+ ###Relationships
108
+
109
+ Per Flippa's documentation, you can send a query parameter to include additional
110
+ Listing relationships, so far only one value is accepted `tags_site_type` , Flippa may
111
+ return additional relationships without needing explicit request.
112
+
113
+ ```ruby
114
+ listing = Appilf::Listing.list(include: 'tags_site_type').first
115
+ listing.seller => Appilf::User
116
+ listing.tags_site_type => Array of Appilf::Object
117
+ ```
118
+
119
+
120
+ ##Alerts
121
+
122
+ You can retrieve the alerts from the authenticated user by using the `list_alerts` method within
123
+ an authenticated client. The result is contained within the meta field as returned by Flippa
124
+
125
+ ```ruby
126
+ alerts = client.list_alerts
127
+ alerts.meta.pending_bids_count
128
+ ```
129
+
130
+
131
+ ##Domain Traits
132
+
133
+ You can retrieve the domain_traits of a certain listing by using the `list_domain_traits` method
134
+ within an authenticated client
135
+
136
+ ```ruby
137
+ client.list_domain_traits(some_listing_id) => Array of Appilf::DomainTrait
138
+ ```
139
+
140
+
141
+ ##Users
142
+
143
+ You can retrieve the current authenticated user by doing
144
+
145
+ ```ruby
146
+ client.retrieve_user => Appilf:User
147
+ ```
148
+
149
+ You can also retrieve a different user by specifying an id during the call
150
+
151
+ ```ruby
152
+ client.retrieve_user(some_user_id) => Appilf:User
153
+ ```
154
+
155
+
156
+ ##Saved Searches
157
+
158
+ To retrieve the list of saved searches that belong to the current user, use the
159
+ `list_saved_searches` method. (This is a paginated resource) (e.g.)
160
+
161
+ ```ruby
162
+ client.list_saved_searches => Appilf:ResourcePage
163
+ ```
164
+
165
+ You can also delete a saved search entry by using the `delete_saved_search` method. (e.g.)
166
+
167
+ ```ruby
168
+ client.delete_saved_search(saved_search_id) => :success
169
+ ```
170
+
171
+
172
+ ##Watched Items
173
+
174
+ To create a watched_item, use the `create_watched_item` method, providing the item_type and item_id
175
+ arguments. (e.g)
176
+
177
+ ```ruby
178
+ client.create_watched_item('listing', 123) => Appilf::WatchedItem
179
+ ```
180
+
181
+ You can also delete a watched item through the `delete_watched_item` method
182
+ by passing the same arguments as the previous method. (e.g.)
183
+
184
+ ```ruby
185
+ client.delete_watched_item('listing', 123) => :success
186
+ ```
187
+
188
+
189
+ ##TODO's
190
+ * Handle pagination correctly for resources that require authentication (affects only Saved Searches for now)
191
+ * Improve the testing suite by adding test cases involving bad requests
@@ -0,0 +1,8 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ # Default directory to look in is `/specs`
5
+ # Run with `rake spec`
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.rspec_opts = ['--color', '--format', 'nested']
8
+ end
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'appilf/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "appilf"
9
+ s.version = Appilf::VERSION
10
+ s.required_ruby_version = '>= 1.9.3'
11
+ s.summary = "A simple Ruby wrapper for Flippa's API"
12
+ s.description = "Provides quick access to Flippa's API methods exposed to the public"
13
+ s.license = 'MIT'
14
+
15
+ s.author = "Rogelio Alejandro Sevilla"
16
+ s.email = "rogelio.sevilla1@gmail.com"
17
+ s.homepage = "https://github.com/rogeliosevilla1/appilf"
18
+
19
+ s.require_path = "lib"
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- spec/*`.split("\n")
22
+
23
+
24
+ s.add_dependency('rest-client', '~> 1.4')
25
+ s.add_dependency('json', '~> 1.8')
26
+ s.add_dependency('methodize', '~> 0.3')
27
+
28
+ s.add_development_dependency "webmock", "~> 1.22"
29
+ s.add_development_dependency "rake", "~> 0.9"
30
+ s.add_development_dependency "rspec", "~> 2.11"
31
+ s.add_development_dependency "coveralls", "~> 0.8"
32
+ end
@@ -0,0 +1,29 @@
1
+ # third parties
2
+ require 'rest-client'
3
+ require 'json'
4
+ require 'methodize/hash'
5
+
6
+ # base class
7
+ require 'appilf/appilf_object'
8
+
9
+ # appilf's core
10
+ require 'appilf/version'
11
+ require 'appilf/error'
12
+ require 'appilf/api_actions'
13
+ require 'appilf/authentication'
14
+ require 'appilf/resource_page'
15
+ require 'appilf/client'
16
+
17
+ # flippa objects
18
+ require 'appilf/listing'
19
+ require 'appilf/user'
20
+ require 'appilf/domain_trait'
21
+ require 'appilf/watched_item'
22
+ require 'appilf/saved_search'
23
+
24
+ # util methods
25
+ require 'appilf/util'
26
+
27
+ module Appilf
28
+
29
+ end
@@ -0,0 +1,49 @@
1
+ module Appilf
2
+
3
+ module APIActions
4
+ BASE_API_URL = 'https://api.flippa.com/v3'
5
+
6
+ def api_post(path, payload, headers = {})
7
+ response = RestClient::Request.execute(method: :post, url: path,
8
+ payload: payload, headers: headers)
9
+ JSON.parse(response)
10
+ rescue RestClient::RequestFailed => e
11
+ handle_from_response(e)
12
+ end
13
+
14
+ def api_delete(path, payload, headers = {})
15
+ RestClient::Request.execute(method: :delete, url: path,
16
+ payload: payload, headers: headers)
17
+ :success
18
+ rescue RestClient::RequestFailed => e
19
+ handle_from_response(e)
20
+ end
21
+
22
+ def api_get(path, headers = {})
23
+ response = RestClient::Request.execute(method: :get, url: path, headers: headers)
24
+ JSON.parse(response)
25
+ rescue RestClient::RequestFailed => e
26
+ handle_from_response(e)
27
+ end
28
+
29
+ def handle_from_response(response_error)
30
+ message = JSON.parse(response_error.response)['error']
31
+ case response_error.http_code
32
+ when 400
33
+ raise BadRequest.new(message)
34
+ when 401
35
+ raise Unauthorized.new(message)
36
+ when 403
37
+ raise Forbidden.new(message)
38
+ when 404
39
+ raise NotFound.new(message)
40
+ when 500
41
+ raise InternalServerError.new(message)
42
+ else
43
+ raise response_error
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end