smoodit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -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
data/.yardopts ADDED
@@ -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
data/HISTORY.mkd ADDED
@@ -0,0 +1,3 @@
1
+ 0.0.1 - November 26, 2006
2
+ -------------------------
3
+ * [Initial release](https://github.com/potomak/smoodit/commit/...)
data/LICENSE.mkd ADDED
@@ -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.
data/README.mkd ADDED
@@ -0,0 +1,155 @@
1
+ #The Smood it Ruby Gem
2
+
3
+ A Ruby wrapper for the Smood it REST API
4
+
5
+ ##Documentation
6
+
7
+ The full Smood it API reference could be found at [http://smood.it/api](http://smood.it/api)
8
+
9
+ ##Installation
10
+
11
+ gem install smoodit
12
+
13
+ ##Follow @smoodit on Twitter
14
+
15
+ You should [follow @smoodit on Twitter](http://twitter.com/smoodit) for announcements,
16
+ updates, and news about the smoodit gem.
17
+
18
+ ##Usage Examples
19
+
20
+ require "rubygems"
21
+ require "smoodit"
22
+
23
+ # Certain methods require authentication. To get your Smood it OAuth credentials,
24
+ # register an app at http://smood.it/oauth_clients/new
25
+ Smoodit.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
+ Smoodit.profile do |me|
34
+ puts me.name
35
+ end
36
+
37
+ # Get informations about giovanni's profile
38
+ Smoodit.giovanni do |giovanni|
39
+ puts giovanni.name
40
+ end
41
+
42
+ # Get giovanni's followers
43
+ Smoodit.giovanni.followers do |response|
44
+ response.followers.each do |smooder|
45
+ puts smooder.name
46
+ end
47
+ end
48
+
49
+ # Get giovanni's following
50
+ Smoodit.giovanni.following do |response|
51
+ response.following.each do |smooder|
52
+ puts smooder.name
53
+ end
54
+ end
55
+
56
+ # Follow giovanni
57
+ Smoodit.giovanni do |giovanni|
58
+ Smoodit.users(giovanni.id).follow.post do |response, status|
59
+ if status == 201 # created
60
+ puts "you don't follow giovanni anymore"
61
+ else
62
+ puts "an error has occurred"
63
+ end
64
+ end
65
+ end
66
+
67
+ # Unfollow giovanni
68
+ Smoodit.giovanni do |giovanni|
69
+ Smoodit.users(giovanni.id).unfollow.post do |response, status|
70
+ if status == 204 # no content
71
+ puts "you don't follow giovanni anymore"
72
+ else
73
+ puts "an error has occurred"
74
+ end
75
+ end
76
+ end
77
+
78
+ # Get your smoods
79
+ Smoodit.profile.smoods do |response|
80
+ response.smoods.each do |smood|
81
+ puts smood.mood
82
+ end
83
+ end
84
+
85
+ # Get giovanni's smoods
86
+ Smoodit.giovanni.smoods do |response|
87
+ response.smoods.each do |smood|
88
+ puts smood.mood
89
+ end
90
+ end
91
+
92
+ # Create a new smood
93
+ Smoodit.smoods.post(:smood => {:mood => :joy}) do |response, status|
94
+ if status == 201 # created
95
+ puts "you've smooded"
96
+ else
97
+ puts "an error has occurred"
98
+ end
99
+ end
100
+
101
+ # Delete smood
102
+ smood_id = 123
103
+ Smoodit.smoods(smood_id).delete do |response, status|
104
+ if status == 204 # no content
105
+ puts "you've smooded"
106
+ else
107
+ puts "an error has occurred"
108
+ end
109
+ end
110
+
111
+ ##Contributing
112
+
113
+ In the spirit of [free software](http://www.fsf.org/licensing/essays/free-sw.html), **everyone** is encouraged to help improve this project.
114
+
115
+ Here are some ways *you* can contribute:
116
+
117
+ * by using alpha, beta, and prerelease versions
118
+ * by reporting bugs
119
+ * by suggesting new features
120
+ * by writing or editing documentation
121
+ * by writing specifications
122
+ * by writing code (**no patch is too small**: fix typos, add comments, clean up inconsistent whitespace)
123
+ * by refactoring code
124
+ * by closing [issues](http://github.com/potomak/smoodit/issues)
125
+ * by reviewing patches
126
+ <!-- * [financially](http://pledgie.com/campaigns/TODO) -->
127
+
128
+ All contributors will be added to the [HISTORY](https://github.com/potomak/smoodit/blob/master/HISTORY.mkd)
129
+ file and will receive the respect and gratitude of the community.
130
+
131
+ ##Submitting an Issue
132
+
133
+ We use the [GitHub issue tracker](http://github.com/potomak/smoodit/issues) to track bugs and
134
+ features. Before submitting a bug report or feature request, check to make sure it hasn't already
135
+ been submitted. You can indicate support for an existing issuse by voting it up. When submitting a
136
+ bug report, please include a [Gist](http://gist.github.com/) that includes a stack trace and any
137
+ details that may be necessary to reproduce the bug, including your gem version, Ruby version, and
138
+ operating system. Ideally, a bug report should include a pull request with failing specs.
139
+
140
+ ##Submitting a Pull Request
141
+
142
+ 1. Fork the project.
143
+ 2. Create a topic branch.
144
+ 3. Implement your feature or bug fix.
145
+ 4. Add documentation for your feature or bug fix.
146
+ 5. Run `bundle exec rake doc:yard`. If your changes are not 100% documented, go back to step 4.
147
+ 6. Add specs for your feature or bug fix.
148
+ 7. Run `bundle exec rake spec`. If your changes are not 100% covered, go back to step 6.
149
+ 8. Commit and push your changes.
150
+ 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.)
151
+
152
+ ##Copyright
153
+
154
+ Copyright (c) 2010 Giovanni Cappellotto.
155
+ See [LICENSE](https://github.com/potomak/smoodit/blob/master/LICENSE.mkd) for details.
data/Rakefile ADDED
@@ -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 Smoodit::BadRequest, error_message(response)
12
+ when 401
13
+ raise Smoodit::Unauthorized, error_message(response)
14
+ when 403
15
+ raise Smoodit::Forbidden, error_message(response)
16
+ when 404
17
+ raise Smoodit::NotFound, error_message(response)
18
+ when 406
19
+ raise Smoodit::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 Smoodit::InternalServerError, error_message(response, "Something is technically wrong.")
12
+ when 502
13
+ raise Smoodit::BadGateway, error_message(response, "Smood it is down or being upgraded.")
14
+ when 503
15
+ raise Smoodit::ServiceUnavailable, error_message(response, "(__-){ Smood it 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.smood.it/ for updates on the status of the Smood it service."
29
+ end
30
+ end
31
+ 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 Smoodit
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 = Smoodit.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 Smoodit
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
+ # -*- encoding: utf-8 -*-
2
+ module Smoodit
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
@@ -0,0 +1,55 @@
1
+ module Smoodit
2
+ # Wrapper for the Smoodit REST API
3
+ #
4
+ # @note See the {http://smood.it/api Smoodit API Documentation} for more informations.
5
+ # @see http://smood.it/api
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 Smoodit::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
+ raw = @proxy.options.delete(:raw)
35
+ response, status = send(:request, @proxy.verb, @proxy.path, @proxy.options, raw)
36
+ case block.arity
37
+ when 0, -1
38
+ yield
39
+ when 1
40
+ yield response
41
+ when 2
42
+ yield response, status
43
+ end
44
+ end
45
+
46
+ self
47
+
48
+ # begin
49
+ # send(verb, path, options)
50
+ # rescue Yajl::ParseError => e
51
+ # puts "error: #{e}"
52
+ # end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,94 @@
1
+ require 'faraday'
2
+ require File.expand_path('../version', __FILE__)
3
+
4
+ module Smoodit
5
+ # Defines constants and methods related to configuration
6
+ module Configuration
7
+ # An array of valid keys in the options hash when configuring a {Smoodit::API}
8
+ VALID_OPTIONS_KEYS = [
9
+ :adapter,
10
+ :consumer_key,
11
+ :consumer_secret,
12
+ :endpoint,
13
+ :format,
14
+ :oauth_token,
15
+ :oauth_token_secret,
16
+ :proxy,
17
+ :user_agent].freeze
18
+
19
+ # An array of valid request/response formats
20
+ #
21
+ # @note Not all methods support the XML format.
22
+ VALID_FORMATS = [
23
+ :json,
24
+ :xml].freeze
25
+
26
+ # The adapter that will be used to connect if none is set
27
+ #
28
+ # @note The default faraday adapter is Net::HTTP.
29
+ DEFAULT_ADAPTER = Faraday.default_adapter
30
+
31
+ # By default, don't set an application key
32
+ DEFAULT_CONSUMER_KEY = nil
33
+
34
+ # By default, don't set an application secret
35
+ DEFAULT_CONSUMER_SECRET = nil
36
+
37
+ # The endpoint that will be used to connect if none is set
38
+ #
39
+ # @note This is configurable in case you want to use HTTP instead of HTTPS, specify a different API version, or use a Smoodit-compatible endpoint.
40
+ #DEFAULT_ENDPOINT = 'http://smood.it/'.freeze
41
+ DEFAULT_ENDPOINT = 'http://localhost:3000/'.freeze
42
+
43
+ # The response format appended to the path and sent in the 'Accept' header if none is set
44
+ #
45
+ # @note JSON is preferred over XML because it is more concise and faster to parse.
46
+ DEFAULT_FORMAT = :json
47
+
48
+ # By default, don't set a user oauth token
49
+ DEFAULT_OAUTH_TOKEN = nil
50
+
51
+ # By default, don't set a user oauth secret
52
+ DEFAULT_OAUTH_TOKEN_SECRET = nil
53
+
54
+ # By default, don't use a proxy server
55
+ DEFAULT_PROXY = nil
56
+
57
+ # The user agent that will be sent to the API endpoint if none is set
58
+ DEFAULT_USER_AGENT = "Smoodit Ruby Gem #{Smoodit::VERSION}".freeze
59
+
60
+ # @private
61
+ attr_accessor *VALID_OPTIONS_KEYS
62
+
63
+ # When this module is extended, set all configuration options to their default values
64
+ def self.extended(base)
65
+ base.reset
66
+ end
67
+
68
+ # Convenience method to allow configuration options to be set in a block
69
+ def configure
70
+ yield self
71
+ end
72
+
73
+ # Create a hash of options and their values
74
+ def options
75
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
76
+ option.merge!(key => send(key))
77
+ end
78
+ end
79
+
80
+ # Reset all configuration options to defaults
81
+ def reset
82
+ self.adapter = DEFAULT_ADAPTER
83
+ self.consumer_key = DEFAULT_CONSUMER_KEY
84
+ self.consumer_secret = DEFAULT_CONSUMER_SECRET
85
+ self.endpoint = DEFAULT_ENDPOINT
86
+ self.format = DEFAULT_FORMAT
87
+ self.oauth_token = DEFAULT_OAUTH_TOKEN
88
+ self.oauth_token_secret = DEFAULT_OAUTH_TOKEN_SECRET
89
+ self.proxy = DEFAULT_PROXY
90
+ self.user_agent = DEFAULT_USER_AGENT
91
+ self
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,38 @@
1
+ require 'faraday_middleware'
2
+ Dir[File.expand_path('../../faraday/*.rb', __FILE__)].each{|f| require f}
3
+
4
+ module Smoodit
5
+ # @private
6
+ module Connection
7
+ private
8
+
9
+ def connection(raw=false)
10
+ options = {
11
+ :headers => {
12
+ 'Accept' => "application/#{format}",
13
+ 'Content-type' => "application/#{format}",
14
+ 'User-Agent' => user_agent
15
+ },
16
+ :proxy => proxy,
17
+ :ssl => {:verify => false},
18
+ :url => api_endpoint,
19
+ }
20
+
21
+ Faraday::Connection.new(options) do |builder|
22
+ builder.use Faraday::Request::Multipart
23
+ builder.use Faraday::Request::Yajl if format == :json
24
+ builder.use Faraday::Request::OAuth, authentication if authenticated?
25
+ builder.adapter(adapter)
26
+ builder.use Faraday::Response::RaiseHttp5xx
27
+ unless raw
28
+ case format.to_s.downcase
29
+ when 'json' then builder.use Faraday::Response::ParseJson
30
+ when 'xml' then builder.use Faraday::Response::ParseXml
31
+ end
32
+ end
33
+ builder.use Faraday::Response::RaiseHttp4xx
34
+ builder.use Faraday::Response::Mashify unless raw
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ module Smoodit
2
+ # Custom error class for rescuing from all Smood it errors
3
+ class Error < StandardError; end
4
+
5
+ # Raised when Smood it returns the HTTP status code 400
6
+ class BadRequest < Error; end
7
+
8
+ # Raised when Smood it returns the HTTP status code 401
9
+ class Unauthorized < Error; end
10
+
11
+ # Raised when Smood it returns the HTTP status code 403
12
+ class Forbidden < Error; end
13
+
14
+ # Raised when Smood it returns the HTTP status code 404
15
+ class NotFound < Error; end
16
+
17
+ # Raised when Smood it returns the HTTP status code 406
18
+ class NotAcceptable < Error; end
19
+
20
+ # Raised when Smood it returns the HTTP status code 500
21
+ class InternalServerError < Error; end
22
+
23
+ # Raised when Smood it returns the HTTP status code 502
24
+ class BadGateway < Error; end
25
+
26
+ # Raised when Smood it returns the HTTP status code 503
27
+ class ServiceUnavailable < Error; end
28
+ end