thounds 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ *.gem
2
+ *.rbc
3
+ .DS_Store
4
+ .bundle
5
+ .rvmrc
6
+ .yardoc
7
+ Gemfile.lock
8
+ coverage/*
9
+ doc/*
10
+ log/*
11
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format=nested
3
+ --backtrace
@@ -0,0 +1,9 @@
1
+ --no-private
2
+ --protected
3
+ --tag format:"Supported formats"
4
+ --tag authenticated:"Requires Authentication"
5
+ --tag rate_limited:"Rate Limited"
6
+ --markup markdown
7
+ -
8
+ HISTORY.mkd
9
+ LICENSE.mkd
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,3 @@
1
+ 0.0.1 - November 26, 2006
2
+ -------------------------
3
+ * [Initial release](https://github.com/potomak/thounds/commit/7983a15b694856048a6ad84bf362d039af0f7d4a)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Giovanni Cappellotto
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.
@@ -0,0 +1,81 @@
1
+ #The Thounds Ruby Gem
2
+
3
+ A Ruby wrapper for the Thounds REST API
4
+
5
+ ##Documentation
6
+
7
+ The full Thounds API reference could be found at [http://developers.thounds.com/API](http://developers.thounds.com/API)
8
+
9
+ ##Installation
10
+
11
+ gem install thounds
12
+
13
+ ##Follow @thounds on Twitter
14
+
15
+ You should [follow @thounds on Twitter](http://twitter.com/thounds) for announcements,
16
+ updates, and news about the thounds gem.
17
+
18
+ ##Usage Examples
19
+
20
+ require "rubygems"
21
+ require "thounds"
22
+
23
+ # Certain methods require authentication. To get your Thounds OAuth credentials,
24
+ # register an app at http://thounds.com/oauth_clients/new
25
+ Thounds.configure do |config|
26
+ config.consumer_key = YOUR_CONSUMER_KEY
27
+ config.consumer_secret = YOUR_CONSUMER_SECRET
28
+ config.oauth_token = YOUR_OAUTH_TOKEN
29
+ config.oauth_token_secret = YOUR_OAUTH_TOKEN_SECRET
30
+ end
31
+
32
+ # Get informations about your profile
33
+ Thounds.profile do |me|
34
+ puts me.name
35
+ end
36
+
37
+ ##Contributing
38
+
39
+ In the spirit of [free software](http://www.fsf.org/licensing/essays/free-sw.html), **everyone** is encouraged to help improve this project.
40
+
41
+ Here are some ways *you* can contribute:
42
+
43
+ * by using alpha, beta, and prerelease versions
44
+ * by reporting bugs
45
+ * by suggesting new features
46
+ * by writing or editing documentation
47
+ * by writing specifications
48
+ * by writing code (**no patch is too small**: fix typos, add comments, clean up inconsistent whitespace)
49
+ * by refactoring code
50
+ * by closing [issues](http://github.com/potomak/thounds/issues)
51
+ * by reviewing patches
52
+ <!-- * [financially](http://pledgie.com/campaigns/TODO) -->
53
+
54
+ All contributors will be added to the [HISTORY](https://github.com/potomak/thounds/blob/master/HISTORY.mkd)
55
+ file and will receive the respect and gratitude of the community.
56
+
57
+ ##Submitting an Issue
58
+
59
+ We use the [GitHub issue tracker](http://github.com/potomak/thounds/issues) to track bugs and
60
+ features. Before submitting a bug report or feature request, check to make sure it hasn't already
61
+ been submitted. You can indicate support for an existing issuse by voting it up. When submitting a
62
+ bug report, please include a [Gist](http://gist.github.com/) that includes a stack trace and any
63
+ details that may be necessary to reproduce the bug, including your gem version, Ruby version, and
64
+ operating system. Ideally, a bug report should include a pull request with failing specs.
65
+
66
+ ##Submitting a Pull Request
67
+
68
+ 1. Fork the project.
69
+ 2. Create a topic branch.
70
+ 3. Implement your feature or bug fix.
71
+ 4. Add documentation for your feature or bug fix.
72
+ 5. Run `bundle exec rake doc:yard`. If your changes are not 100% documented, go back to step 4.
73
+ 6. Add specs for your feature or bug fix.
74
+ 7. Run `bundle exec rake spec`. If your changes are not 100% covered, go back to step 6.
75
+ 8. Commit and push your changes.
76
+ 9. Submit a pull request. Please do not include changes to the gemspec, version, or history file. (If you want to create your own version for some reason, please do so in a separate commit.)
77
+
78
+ ##Copyright
79
+
80
+ Copyright (c) 2010 Giovanni Cappellotto.
81
+ See [LICENSE](https://github.com/potomak/thounds/blob/master/LICENSE.mkd) for details.
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ namespace :doc do
10
+ require 'yard'
11
+ YARD::Rake::YardocTask.new do |task|
12
+ task.files = ['HISTORY.mkd', 'LICENSE.mkd', 'lib/**/*.rb']
13
+ task.options = [
14
+ '--protected',
15
+ '--output-dir', 'doc/yard',
16
+ '--tag', 'format:Supported formats',
17
+ '--tag', 'authenticated:Requires Authentication',
18
+ '--tag', 'rate_limited:Rate Limited',
19
+ '--markup', 'markdown',
20
+ ]
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ require 'faraday'
2
+
3
+ # @private
4
+ module Faraday
5
+ # @private
6
+ class Request::Multipart < Faraday::Middleware
7
+ def call(env)
8
+ if env[:body].is_a?(Hash)
9
+ env[:body].each do |key, value|
10
+ if value.is_a?(File)
11
+ env[:body][key] = Faraday::UploadIO.new(value, mime_type(value), value.path)
12
+ end
13
+ end
14
+ end
15
+
16
+ @app.call(env)
17
+ end
18
+
19
+ private
20
+
21
+ def mime_type(file)
22
+ case file.path
23
+ when /\.jpe?g/i then 'image/jpeg'
24
+ when /\.gif$/i then 'image/gif'
25
+ when /\.png$/i then 'image/png'
26
+ else 'application/octet-stream'
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'faraday'
2
+ require 'simple_oauth'
3
+
4
+ # @private
5
+ module Faraday
6
+ # @private
7
+ class Request::OAuth < Faraday::Middleware
8
+ def call(env)
9
+ params = env[:body].is_a?(Hash) ? env[:body] : {}
10
+ signature_params = params.reject{|k,v| v.respond_to?(:content_type) }
11
+ header = SimpleOAuth::Header.new(env[:method], env[:url], signature_params, @options)
12
+
13
+ env[:request_headers]['Authorization'] = header.to_s
14
+
15
+ @app.call(env)
16
+ end
17
+
18
+ def initialize(app, options)
19
+ @app, @options = app, options
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ require 'faraday'
2
+
3
+ # @private
4
+ module Faraday
5
+ # @private
6
+ class Response::RaiseHttp4xx < Response::Middleware
7
+ def self.register_on_complete(env)
8
+ env[:response].on_complete do |response|
9
+ case response[:status].to_i
10
+ when 400
11
+ raise Thounds::BadRequest, error_message(response)
12
+ when 401
13
+ raise Thounds::Unauthorized, error_message(response)
14
+ when 403
15
+ raise Thounds::Forbidden, error_message(response)
16
+ when 404
17
+ raise Thounds::NotFound, error_message(response)
18
+ when 406
19
+ raise Thounds::NotAcceptable, error_message(response)
20
+ end
21
+ end
22
+ end
23
+
24
+ def initialize(app)
25
+ super
26
+ @parser = nil
27
+ end
28
+
29
+ private
30
+
31
+ def self.error_message(response)
32
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{response[:status]}#{error_body(response[:body])}"
33
+ end
34
+
35
+ def self.error_body(body)
36
+ if body.nil?
37
+ nil
38
+ elsif body['error']
39
+ ": #{body['error']}"
40
+ elsif body['errors']
41
+ first = body['errors'].to_a.first
42
+ if first.kind_of? Hash
43
+ ": #{first['message'].chomp}"
44
+ else
45
+ ": #{first.chomp}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,31 @@
1
+ require 'faraday'
2
+
3
+ # @private
4
+ module Faraday
5
+ # @private
6
+ class Response::RaiseHttp5xx < Response::Middleware
7
+ def self.register_on_complete(env)
8
+ env[:response].on_complete do |response|
9
+ case response[:status].to_i
10
+ when 500
11
+ raise Thounds::InternalServerError, error_message(response, "Something is technically wrong.")
12
+ when 502
13
+ raise Thounds::BadGateway, error_message(response, "Thounds is down or being upgraded.")
14
+ when 503
15
+ raise Thounds::ServiceUnavailable, error_message(response, "(__-){ Thounds is over capacity.")
16
+ end
17
+ end
18
+ end
19
+
20
+ def initialize(app)
21
+ super
22
+ @parser = nil
23
+ end
24
+
25
+ private
26
+
27
+ def self.error_message(response, body=nil)
28
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: #{[response[:status].to_s + ':', body].compact.join(' ')} Check http://status.thounds.com/ for updates on the status of the Thounds service."
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../thounds/error', __FILE__)
2
+ require File.expand_path('../thounds/configuration', __FILE__)
3
+ require File.expand_path('../thounds/api', __FILE__)
4
+ require File.expand_path('../thounds/client', __FILE__)
5
+
6
+ module Thounds
7
+ extend Configuration
8
+
9
+ # Alias for Thounds::Client.new
10
+ #
11
+ # @return [Thounds::Client]
12
+ def self.client(options={})
13
+ Thounds::Client.new(options)
14
+ end
15
+
16
+ # Delegate to Thounds::Client
17
+ def self.method_missing(method, *args, &block)
18
+ #return super unless client.respond_to?(method)
19
+ client.send(method, *args, &block)
20
+ end
21
+
22
+ # Delegate to Thounds::Client
23
+ # def self.respond_to?(method)
24
+ # return client.respond_to?(method) || super
25
+ # end
26
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../connection', __FILE__)
2
+ require File.expand_path('../request', __FILE__)
3
+ require File.expand_path('../authentication', __FILE__)
4
+
5
+ module Thounds
6
+ # @private
7
+ class API
8
+ # @private
9
+ attr_accessor *Configuration::VALID_OPTIONS_KEYS
10
+
11
+ # Creates a new API
12
+ def initialize(options={})
13
+ options = Thounds.options.merge(options)
14
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
15
+ send("#{key}=", options[key])
16
+ end
17
+ end
18
+
19
+ include Connection
20
+ include Request
21
+ include Authentication
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module Thounds
2
+ # @private
3
+ module Authentication
4
+ private
5
+
6
+ # Authentication hash
7
+ #
8
+ # @return [Hash]
9
+ def authentication
10
+ {
11
+ :consumer_key => consumer_key,
12
+ :consumer_secret => consumer_secret,
13
+ :token => oauth_token,
14
+ :token_secret => oauth_token_secret
15
+ }
16
+ end
17
+
18
+ # Check whether user is authenticated
19
+ #
20
+ # @return [Boolean]
21
+ def authenticated?
22
+ authentication.values.all?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ module Thounds
2
+ # Wrapper for the Thounds REST API
3
+ #
4
+ # @note See the {http://developers.thounds.com/doc Thounds API Documentation} for more informations.
5
+ # @see http://developers.thounds.com
6
+ class Client < API
7
+ # Require client method modules after initializing the Client class in
8
+ # order to avoid a superclass mismatch error, allowing those modules to be
9
+ # Client-namespaced.
10
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f}
11
+
12
+ alias :api_endpoint :endpoint
13
+
14
+ attr_reader :proxy
15
+
16
+ def initialize(options={})
17
+ super(options)
18
+ @proxy = Proxy.new
19
+ end
20
+
21
+ # Delegate to Thounds::Client
22
+ def method_missing(method, *args, &block)
23
+ options = args.last.is_a?(Hash) ? args.pop : {}
24
+ id = args.last ? args.pop : nil
25
+
26
+ # puts "method: #{method}"
27
+ # puts "options: #{options.inspect}"
28
+ # puts "id: #{id}"
29
+
30
+ @proxy.append(method, id, options)
31
+
32
+ if block_given?
33
+ @proxy.compose_request
34
+ yield send(:request, @proxy.verb, @proxy.path, @proxy.options)
35
+ end
36
+
37
+ self
38
+
39
+ # begin
40
+ # send(verb, path, options)
41
+ # rescue Yajl::ParseError => e
42
+ # puts "error: #{e}"
43
+ # end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Thounds
3
+ class Client
4
+ class Proxy
5
+ attr_reader :options, :verb, :path
6
+
7
+ def initialize
8
+ @verb = :get
9
+ @keys = []
10
+ @ids = {}
11
+ @options = {}
12
+ @path = ""
13
+ end
14
+
15
+ def append(key, id=nil, options={})
16
+ @verb = key.to_sym if ["get", "post", "put", "delete"].include? key.to_s
17
+ @keys << key unless ["get", "post", "put", "delete"].include? key.to_s
18
+ @ids[key.to_sym] = id if id
19
+ @options = @options.merge(options) if options
20
+ end
21
+
22
+ def compose_request
23
+ # puts "@keys: #{@keys.inspect}"
24
+ # puts "@ids: #{@ids.inspect}"
25
+ # puts "@options: #{@options.inspect}"
26
+
27
+ # compose request path
28
+ @path = @keys.collect do |key|
29
+ if id = @ids.delete(key.to_sym)
30
+ "#{key}/#{id}"
31
+ else
32
+ key
33
+ end
34
+ end.join("/")
35
+
36
+ # puts to_s
37
+
38
+ self
39
+ end
40
+
41
+ def to_s
42
+ "#{@verb.to_s.upcase} /#{@path} OPTIONS: #{@options.inspect}"
43
+ end
44
+ end
45
+ end
46
+ end