crowdflower-rtfm 0.0.2

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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "rest-client"
6
+ gem "multi_json"
7
+
8
+ # Add dependencies to develop your gem here.
9
+ # Include everything needed to run rake, tests, features, etc.
10
+ group :development do
11
+ gem "minitest", ">= 0"
12
+ gem "bundler", "~> 1.0.0"
13
+ gem "jeweler", "~> 1.8.3"
14
+ gem "simplecov", ">= 0"
15
+ gem "webmock", ">= 0"
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,39 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.2.7)
5
+ crack (0.3.1)
6
+ git (1.2.5)
7
+ jeweler (1.8.3)
8
+ bundler (~> 1.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rdoc
12
+ json (1.7.0)
13
+ mime-types (1.18)
14
+ minitest (2.12.1)
15
+ multi_json (1.3.4)
16
+ rake (0.9.2.2)
17
+ rdoc (3.12)
18
+ json (~> 1.4)
19
+ rest-client (1.6.7)
20
+ mime-types (>= 1.16)
21
+ simplecov (0.6.2)
22
+ multi_json (~> 1.3)
23
+ simplecov-html (~> 0.5.3)
24
+ simplecov-html (0.5.3)
25
+ webmock (1.8.6)
26
+ addressable (>= 2.2.7)
27
+ crack (>= 0.1.7)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ bundler (~> 1.0.0)
34
+ jeweler (~> 1.8.3)
35
+ minitest
36
+ multi_json
37
+ rest-client
38
+ simplecov
39
+ webmock
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 CrowdFlower
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # RTFM - Real Time Foto Moderator
2
+
3
+ Real Time Foto Moderator (RTFM) is Crowdsourced Image Moderation, learn more at http://crowdflower.com/rtfm. This gem is a simple wrapper for interacting with the API. Keep your app clean!
4
+
5
+ ## Usage
6
+
7
+ ```shell
8
+ gem install crowdflower-rtfm
9
+ ```
10
+
11
+ ```ruby
12
+ require 'rubygems'
13
+ require 'crowdflower-rtfm'
14
+
15
+ RTFM.api_key = "a1b2c3d4e5f6g7h8i9j0..."
16
+ #moderate_image accepts an optional metadata hash
17
+ res = RTFM.moderate_image("http://mysite.com/images/moderateme.jpg", {:id => 123})
18
+ RTFM.retrieve_image(res["image"]["id"])
19
+ ```
20
+
21
+ ## Exceptions
22
+
23
+ All exceptions thrown by the gem itself inherit from `RTFM::Error`. Below are the possible exceptions:
24
+
25
+ * RateLimitError - (rate limit exceeded)
26
+ * PaymentError - (account is out of money)
27
+ * AccountError - (your account is not authorized for this service)
28
+ * AuthenticationError - (your API key is invalid)
29
+ * InvalidRequestError - (one of your parameters is invalid, usually url)
30
+ * APIError - (a non 200 response code was returned, see the docs)
31
+ * APIConnectionError - (a network error occured)
32
+
33
+ ## Webhook example
34
+
35
+ We've also included an example Sinatra server to consume webhooks from RTFM. You can find it at https://github.com/dolores/rtfm-ruby/tree/master/examples
36
+
37
+ # Acknowledgements
38
+
39
+ The implementation of this wrapper was inspired heavily by Stripes Ruby implementation (https://github.com/stripe/stripe-ruby). Thanks to Ross Boucher & Greg Brockman for bending RestClient to their will.
40
+
41
+ # Copyright
42
+
43
+ Copyright (c) 2012 CrowdFlower. See LICENSE.txt for
44
+ further details.
45
+
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "crowdflower-rtfm"
18
+ gem.homepage = "http://dolores.github.com/rtfm-api"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Simple Ruby wrapper for the RTFM API}
21
+ gem.description = %Q{Real Time Foto Moderator (RTFM) is Crowdsourced Image Moderation. Keep your app clean!}
22
+ gem.email = "vanpelt@crowdflower.com"
23
+ gem.authors = ["Chris Van Pelt"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "crowdflower-rtfm"
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Chris Van Pelt"]
12
+ s.date = "2012-05-07"
13
+ s.description = "Real Time Foto Moderator (RTFM) is Crowdsourced Image Moderation. Keep your app clean!"
14
+ s.email = "vanpelt@crowdflower.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "crowdflower-rtfm.gemspec",
28
+ "examples/Gemfile",
29
+ "examples/README.md",
30
+ "examples/config.ru",
31
+ "examples/webhook.rb",
32
+ "examples/webhook_public.pem",
33
+ "lib/crowdflower-rtfm.rb",
34
+ "test/helper.rb",
35
+ "test/test_rtfm.rb"
36
+ ]
37
+ s.homepage = "http://dolores.github.com/rtfm-api"
38
+ s.licenses = ["MIT"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = "1.8.10"
41
+ s.summary = "Simple Ruby wrapper for the RTFM API"
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<rest-client>, [">= 0"])
48
+ s.add_runtime_dependency(%q<multi_json>, [">= 0"])
49
+ s.add_development_dependency(%q<minitest>, [">= 0"])
50
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
51
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
52
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
53
+ s.add_development_dependency(%q<webmock>, [">= 0"])
54
+ else
55
+ s.add_dependency(%q<rest-client>, [">= 0"])
56
+ s.add_dependency(%q<multi_json>, [">= 0"])
57
+ s.add_dependency(%q<minitest>, [">= 0"])
58
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
60
+ s.add_dependency(%q<simplecov>, [">= 0"])
61
+ s.add_dependency(%q<webmock>, [">= 0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<rest-client>, [">= 0"])
65
+ s.add_dependency(%q<multi_json>, [">= 0"])
66
+ s.add_dependency(%q<minitest>, [">= 0"])
67
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
68
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
69
+ s.add_dependency(%q<simplecov>, [">= 0"])
70
+ s.add_dependency(%q<webmock>, [">= 0"])
71
+ end
72
+ end
73
+
data/examples/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem "sinatra", ">= 1.3.0"
4
+ gem "multi_json"
@@ -0,0 +1,10 @@
1
+ #Sample webhook consumer
2
+
3
+ You can take the contents of this folder and put them into a new git repo. This will allows you to push the repo to heroku and have a functioning webhook.
4
+
5
+ ##Debugging
6
+
7
+ ```bash
8
+ heroku config:add LOG_LEVEL=DEBUG
9
+ heroku logs -t
10
+ ```
@@ -0,0 +1,2 @@
1
+ require './webhook'
2
+ run Sinatra::Application
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require 'multi_json'
4
+ require 'openssl'
5
+ require 'base64'
6
+
7
+ PKey = OpenSSL::PKey::RSA.new(File.read(File.join(File.dirname(__FILE__), "webhook_public.pem")))
8
+
9
+ post "/rtfm_webhook" do
10
+ signature = env['X-CrowdFlower-Signature']
11
+ body = request.body.read
12
+ if(@public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(signature), body))
13
+ payload = MultiJson.load(body)
14
+ #Do something meaningful with the payload here
15
+ logger.debug "SUCCESS"
16
+ logger.debug payload
17
+ 200
18
+ else
19
+ logger.debug "FAILURE #{signature}"
20
+ logger.debug body
21
+ 401
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0I0daumhUqIn4nIFcWEb
3
+ bTtL7F9a0d/a5d09/bnHNZcxOALjHir8iBKe3nSLRaKZDWd+MmxseD90dEbRtsvM
4
+ 9lZ5bfFnXga43IAonnTZmLbqMsUNMByLLrfthlkUsU9arRJxEWK5I4eCON2JVm9E
5
+ ruQLaNi8RqitHwGvsfiOQm2gchoMj8kOyrVvdoUldSu3VZN7AbJ+mrsmFwEfQd5h
6
+ LzqLfHBCx7YlnWVFoNC3mOzxqpzJKdL+t1mXi7ewZSsCZzEL1LdeqJ3UTpSrNIRA
7
+ DU1UB+Pi7aybUIIDWC04jmRAPRiMSg87zK9bL+oXM0QWT7Zi8/EF76ZdeIaH2YrL
8
+ cQIDAQAB
9
+ -----END PUBLIC KEY-----
@@ -0,0 +1,135 @@
1
+ require 'rubygems'
2
+ require 'openssl'
3
+ require 'rest_client'
4
+ require 'multi_json'
5
+
6
+ module RTFM
7
+ VERSION = File.read(File.join(File.dirname(__FILE__),"..","VERSION"))
8
+ @@api_key = nil
9
+ @@api_base = "https://rtfm.crowdflower.com/v1"
10
+
11
+ def self.api_key=(api_key); @@api_key = api_key; end
12
+ def self.api_key; @@api_key; end
13
+ def self.api_base=(api_base); @@api_base = api_base; end
14
+ def self.api_base; @@api_base; end
15
+ def self.api_url(url=''); @@api_base + url; end
16
+
17
+ def self.moderate_image(url, metadata = nil)
18
+ params = {:url => url}
19
+ params.merge!(:metadata => metadata) if metadata
20
+ request("/images", :post, params)
21
+ end
22
+
23
+ def self.retrieve_image(id)
24
+ request("/images/#{id}")
25
+ end
26
+
27
+ def self.request(url, method = :get, params = nil, api_key = nil, headers = {})
28
+ api_key ||= @@api_key
29
+ raise AuthenticationError.new("Please provide an API key (RTFM.api_key = <API-KEY>, your API key can be found by clicking \"APISettings\" @ http://crowdflower.com/rtfm)") unless api_key
30
+
31
+ #RestClient appends get parameters by looking for params in headers... lame
32
+ if method == :get && params
33
+ headers.merge!(:params => params)
34
+ params = nil
35
+ end
36
+
37
+ opts = {
38
+ :user => api_key,
39
+ :timeout => 30,
40
+ :url => api_url(url),
41
+ :method => method,
42
+ :headers => {
43
+ :user_agent => "RTFM/v1 RubyGem/#{VERSION}",
44
+ :accept => "application/json"
45
+ }.merge(headers),
46
+ :payload => params
47
+ }
48
+
49
+ response = RestClient::Request.execute(opts)
50
+ MultiJson.load(response.body, :symbolize_keys => true)
51
+ rescue SocketError => e
52
+ self.handle_restclient_error(e)
53
+ rescue RestClient::ExceptionWithResponse => e
54
+ rcode = e.http_code
55
+ rbody = e.http_body
56
+ if rcode && rbody
57
+ self.handle_api_error(rcode, rbody)
58
+ else
59
+ self.handle_restclient_error(e)
60
+ end
61
+ rescue RestClient::Exception, Errno::ECONNREFUSED => e
62
+ self.handle_restclient_error(e)
63
+ rescue MultiJson::DecodeError
64
+ raise APIError.new("Invalid response body: #{response.body.inspect}. (HTTP response code of #{response.code})", response.code, response.body)
65
+ end
66
+
67
+ class Error < StandardError
68
+ attr_reader :message
69
+ attr_reader :http_status
70
+ attr_reader :http_body
71
+ attr_reader :json_body
72
+
73
+ def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
74
+ @message = message
75
+ @http_status = http_status
76
+ @http_body = http_body
77
+ @json_body = json_body
78
+ end
79
+
80
+ def to_s
81
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
82
+ "#{status_string}#{@message}"
83
+ end
84
+ end
85
+
86
+ class RateLimitError < Error; end
87
+ class APIError < Error; end
88
+ class PaymentError < Error; end
89
+ class AccountError < Error; end
90
+ class AuthenticationError < Error; end
91
+ class InvalidRequestError < Error; end
92
+ class APIConnectionError < Error; end
93
+
94
+ def self.error(klass = Error, error, rcode, rbody, error_obj); klass.new(error, rcode, rbody, error_obj); end
95
+
96
+ def self.handle_api_error(rcode, rbody)
97
+ begin
98
+ error_obj = MultiJson.load(rbody, :symbolize_keys => true)
99
+ error = error_obj[:error] or raise Error.new # escape from parsing
100
+ rescue MultiJson::DecodeError, Error
101
+ raise APIError.new("Invalid response object from API: #{rbody.inspect} (HTTP response code was #{rcode})", rcode, rbody)
102
+ end
103
+
104
+ case rcode
105
+ when 503
106
+ raise error(RateLimitError, error, rcode, rbody, error_obj)
107
+ when 400, 404 then
108
+ raise error(InvalidRequestError, error, rcode, rbody, error_obj)
109
+ when 401
110
+ raise error(AuthenticationError, error, rcode, rbody, error_obj)
111
+ when 402
112
+ raise error(PaymentError, error, rcode, rbody, error_obj)
113
+ when 403
114
+ raise error(AccountError, error, rcode, rbody, error_obj)
115
+ else
116
+ raise error(APIError, error, rcode, rbody, error_obj)
117
+ end
118
+ end
119
+
120
+ def self.handle_restclient_error(e)
121
+ case e
122
+ when RestClient::ServerBrokeConnection, RestClient::RequestFailed
123
+ message = "Could not connect to RTFM (#{@@api_base}). Please check your internet connection and try again. If this problem persists, you should check RTFM's service status at https://twitter.com/cfstatus, or let us know at rtfm@crowdflower.com."
124
+ when RestClient::SSLCertificateNotVerified
125
+ message = "Could not verify RTFM's SSL certificate. Please make sure that your network is not intercepting certificates. If this problem persists, let us know at rtfm@crowdflower.com."
126
+ when SocketError
127
+ message = "Unexpected error communicating when trying to connect to RTFM. HINT: You may be seeing this message because your DNS is not working. To check, try running 'host stripe.com' from the command line."
128
+ else
129
+ message = "Unexpected error communicating with RTFM. If this problem persists, let us know at rtfm@crowdflower.com"
130
+ end
131
+ message += "\n\n(Network error: #{e.message})"
132
+ raise APIConnectionError.new(message)
133
+ end
134
+ end
135
+
data/test/helper.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+ require 'minitest/spec'
14
+ require 'minitest/autorun'
15
+ require 'webmock/minitest'
16
+
17
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
18
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
19
+ require 'rtfm'
20
+
21
+ def moderate_success_body(url, metadata = {})
22
+ MultiJson.dump(
23
+ "image" => {
24
+ "id" => 1,
25
+ "url" => url,
26
+ "metadata" => metadata
27
+ }
28
+ )
29
+ end
30
+
31
+ def retrieve_success_body(id)
32
+ MultiJson.dump(
33
+ "image" => {
34
+ "id" => id,
35
+ "url" => "http://vanpe.lt/fake.jpg",
36
+ "score" => 0.6,
37
+ "rating" => "accepted",
38
+ "state" => "completed",
39
+ "metadata" => {}
40
+ }
41
+ )
42
+ end
43
+
44
+ class MiniTest::Spec::TestCase
45
+ end
data/test/test_rtfm.rb ADDED
@@ -0,0 +1,153 @@
1
+ require 'helper'
2
+
3
+ describe RTFM do
4
+ before do
5
+ @url = "http://vanpe.lt/awesome.jpg"
6
+ RTFM.api_key = "1234"
7
+ end
8
+
9
+ describe "makes successful requests" do
10
+ it "moderates without metadata" do
11
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").with(
12
+ :body => /awesome/,
13
+ :headers => {'User-Agent'=>"RTFM/v1 RubyGem/#{RTFM::VERSION}"}
14
+ ).to_return(:status => 200, :body => moderate_success_body(@url))
15
+ res = RTFM.moderate_image(@url)
16
+ res[:image][:id].must_equal(1)
17
+ res[:image][:metadata].must_equal({})
18
+ end
19
+
20
+ it "moderates with metadata" do
21
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").with(
22
+ :body => /metadata\[foo\]=123/
23
+ ).to_return(:status => 200, :body => moderate_success_body(@url, {:foo => 123}))
24
+ res = RTFM.moderate_image(@url, {:foo => 123})
25
+ res[:image][:metadata].must_equal({:foo => 123})
26
+ end
27
+
28
+ it "retrieves analysis" do
29
+ stub_request(:get, "https://1234:@rtfm.crowdflower.com/v1/images/1").to_return(:status => 200, :body => retrieve_success_body(1))
30
+ res = RTFM.retrieve_image(1)
31
+ res[:image][:url].must_equal("http://vanpe.lt/fake.jpg")
32
+ res[:image][:id].must_equal(1)
33
+ end
34
+ end
35
+
36
+ describe "handles network errors" do
37
+ it "catches ERRNO" do
38
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_raise(Errno::ECONNREFUSED)
39
+ error = lambda {
40
+ RTFM.moderate_image(@url)
41
+ }.must_raise(RTFM::APIConnectionError)
42
+ error.to_s.must_match /Connection refused/
43
+ end
44
+
45
+ it "catches timeout" do
46
+ #The struct is a hack to prevent an infinite loop in RestClient
47
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_raise(RestClient::RequestFailed.new(OpenStruct.new(:net_http_res => nil)))
48
+ error = lambda {
49
+ RTFM.moderate_image(@url)
50
+ }.must_raise(RTFM::APIConnectionError)
51
+ error.to_s.must_match /Could not connect/
52
+ end
53
+
54
+ it "catches SocketError" do
55
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_raise(SocketError)
56
+ error = lambda {
57
+ RTFM.moderate_image(@url)
58
+ }.must_raise(RTFM::APIConnectionError)
59
+ error.to_s.must_match /Network error/
60
+ end
61
+
62
+ it "handles SSL errors"
63
+ end
64
+
65
+ describe "handles API errors" do
66
+ it "prevents no API key" do
67
+ RTFM.api_key = nil
68
+ lambda {
69
+ RTFM.moderate_image(@url)
70
+ }.must_raise(RTFM::AuthenticationError)
71
+ end
72
+
73
+ it "handles bad API key" do
74
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
75
+ :status => 401, :body => MultiJson.dump({:error => "You're not authorized"})
76
+ )
77
+ error = lambda {
78
+ puts RTFM.moderate_image(@url)
79
+ }.must_raise(RTFM::AuthenticationError)
80
+ error.to_s.must_match /not authorized/
81
+ end
82
+
83
+ it "handles no money" do
84
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
85
+ :status => 402, :body => MultiJson.dump({:error => "You have no money"})
86
+ )
87
+ error = lambda {
88
+ puts RTFM.moderate_image(@url)
89
+ }.must_raise(RTFM::PaymentError)
90
+ error.to_s.must_match /no money/
91
+ end
92
+
93
+ it "handles bad account" do
94
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
95
+ :status => 403, :body => MultiJson.dump({:error => "You have no account"})
96
+ )
97
+ error = lambda {
98
+ puts RTFM.moderate_image(@url)
99
+ }.must_raise(RTFM::AccountError)
100
+ error.to_s.must_match /no account/
101
+ end
102
+
103
+ it "handles not found" do
104
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
105
+ :status => 404, :body => MultiJson.dump({:error => "Not Found"})
106
+ )
107
+ error = lambda {
108
+ puts RTFM.moderate_image(@url)
109
+ }.must_raise(RTFM::InvalidRequestError)
110
+ error.to_s.must_match /Not Found/
111
+ end
112
+
113
+ it "handles ratelimit" do
114
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
115
+ :status => 503, :body => MultiJson.dump({:error => "Too fast"})
116
+ )
117
+ error = lambda {
118
+ puts RTFM.moderate_image(@url)
119
+ }.must_raise(RTFM::RateLimitError)
120
+ error.to_s.must_match /Too fast/
121
+ end
122
+
123
+ it "handles malformed response on success" do
124
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
125
+ :status => 200, :body => "bullshit"
126
+ )
127
+ error = lambda {
128
+ puts RTFM.moderate_image(@url)
129
+ }.must_raise(RTFM::APIError)
130
+ error.to_s.must_match /bullshit/
131
+ end
132
+
133
+ it "handles malformed response on error" do
134
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
135
+ :status => 500, :body => "bullshit"
136
+ )
137
+ error = lambda {
138
+ puts RTFM.moderate_image(@url)
139
+ }.must_raise(RTFM::APIError)
140
+ error.to_s.must_match /bullshit/
141
+ end
142
+
143
+ it "handles malformed request" do
144
+ stub_request(:post, "https://1234:@rtfm.crowdflower.com/v1/images").to_return(
145
+ :status => 422, :body => MultiJson.dump({:error => "Bad url"})
146
+ )
147
+ error = lambda {
148
+ puts RTFM.moderate_image(@url)
149
+ }.must_raise(RTFM::APIError)
150
+ error.to_s.must_match /Bad url/
151
+ end
152
+ end
153
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crowdflower-rtfm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Van Pelt
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: &70210985936740 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70210985936740
25
+ - !ruby/object:Gem::Dependency
26
+ name: multi_json
27
+ requirement: &70210985936140 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70210985936140
36
+ - !ruby/object:Gem::Dependency
37
+ name: minitest
38
+ requirement: &70210985935640 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70210985935640
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: &70210985935140 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70210985935140
58
+ - !ruby/object:Gem::Dependency
59
+ name: jeweler
60
+ requirement: &70210985934580 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.8.3
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70210985934580
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: &70210985933940 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70210985933940
80
+ - !ruby/object:Gem::Dependency
81
+ name: webmock
82
+ requirement: &70210985933220 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70210985933220
91
+ description: Real Time Foto Moderator (RTFM) is Crowdsourced Image Moderation. Keep
92
+ your app clean!
93
+ email: vanpelt@crowdflower.com
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files:
97
+ - LICENSE.txt
98
+ - README.md
99
+ files:
100
+ - .document
101
+ - Gemfile
102
+ - Gemfile.lock
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - VERSION
107
+ - crowdflower-rtfm.gemspec
108
+ - examples/Gemfile
109
+ - examples/README.md
110
+ - examples/config.ru
111
+ - examples/webhook.rb
112
+ - examples/webhook_public.pem
113
+ - lib/crowdflower-rtfm.rb
114
+ - test/helper.rb
115
+ - test/test_rtfm.rb
116
+ homepage: http://dolores.github.com/rtfm-api
117
+ licenses:
118
+ - MIT
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ segments:
130
+ - 0
131
+ hash: -2682891135621693422
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 1.8.10
141
+ signing_key:
142
+ specification_version: 3
143
+ summary: Simple Ruby wrapper for the RTFM API
144
+ test_files: []