sessionm-resthome 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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 "httparty", ">= 0"
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.1"
12
+ gem "rcov", ">= 0"
13
+ gem "fakeweb", ">= 0"
14
+ gem "json", ">= 0"
15
+ gem "rspec", ">= 0"
16
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ crack (0.1.8)
5
+ fakeweb (1.2.8)
6
+ git (1.2.5)
7
+ httparty (0.6.1)
8
+ crack (= 0.1.8)
9
+ jeweler (1.5.1)
10
+ bundler (~> 1.0.0)
11
+ git (>= 1.2.5)
12
+ rake
13
+ json (1.2.4)
14
+ rake (0.8.7)
15
+ rcov (0.9.8)
16
+ rspec (1.3.0)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bundler (~> 1.0.0)
23
+ fakeweb
24
+ httparty
25
+ jeweler (~> 1.5.1)
26
+ json
27
+ rcov
28
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Cykod LLC
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.rdoc ADDED
@@ -0,0 +1,140 @@
1
+ = RESTHome
2
+
3
+ Simple wrapper class generator for consuming RESTful web services
4
+
5
+ == RESTful Example
6
+
7
+ RESTHome's are used to communicate to RESTful Web Services.
8
+
9
+ Let's say you are working with B2B.dev. They provide a simple RESTful API for interacting with customer data.
10
+
11
+ API looks like
12
+ GET http://api.b2b.dev/customers.json - list of your customers
13
+ GET http://api.b2b.dev/customers/<id>.json - customer data
14
+ PUT http://api.b2b.dev/customers/<id>.json - edit customer data
15
+ DELETE http://api.b2b.dev/customers/<id>.json - delete customer
16
+ POST http://api.b2b.dev/customers.json - create a new customer
17
+
18
+ JSON response looks like {'customer': {'id': 99, 'first_name': 'Joe', 'last_name': 'Smith'}}
19
+
20
+ Create a simple RESTHome service to interact with B2B.dev api.
21
+
22
+ class B2BService < RESTHome
23
+ rest :customer, :customers, '/customers.json'
24
+
25
+ def initialize(api_key)
26
+ self.base_uri = 'http://api.b2b.dev'
27
+ self.basic_auth = {:username => api_key, :password => 'x'}
28
+ end
29
+ end
30
+
31
+ service = B2BService.new 'XXXXX'
32
+ service.customers # returns an array of customers
33
+ customer = service.customer 99 # returns the data for customer 99, i.e. {:first_name => 'Joe', :last_name => 'Smith'}
34
+ service.edit_customer 99, :first_name => 'Joesph', :last_name => 'Smithie' # edits customer 99
35
+ service.delete_customer 99 # deletes customer 99
36
+ service.create_customer :first_name => 'John', :last_name => 'Doe' # creates a new customer
37
+
38
+ == Lorem Lipsum Example
39
+
40
+ Create a simple lorem lipsum generator, using http://www.lipsum.com.
41
+
42
+ lipsum = RESTHome.new
43
+ lipsum.base_uri = 'http://www.lipsum.com'
44
+ lipsum.route :generate, '/feed/json', :method => :post
45
+ words = lipsum.generate(:what => 'words', :amount => 20) do |res|
46
+ res['feed']['lipsum']
47
+ end
48
+
49
+
50
+ class LoremLipsumService < RESTHome
51
+ base_uri 'http://www.lipsum.com'
52
+
53
+ route :generate, '/feed/json', :method => :post do |res|
54
+ res['feed']['lipsum']
55
+ end
56
+ end
57
+
58
+ service = LoremLipsumService.new
59
+ words = service.generate(:what => 'words', :amount => 20)
60
+
61
+ == LastFM Example query arguments
62
+
63
+ How to replace query parameters with function arguments.
64
+
65
+ class LastFmWebService < RESTHome
66
+ base_uri 'http://ws.audioscrobbler.com'
67
+
68
+ namespace '/2.0' do
69
+ route :track, '/', :query => {'method' => 'track.getinfo', 'artist' => :arg1, 'track' => :arg2}, :resource => 'track'
70
+ end
71
+
72
+ def initialize(api_key)
73
+ @api_key = api_key
74
+ end
75
+
76
+ def build_options!(options)
77
+ options[:query] ||= {}
78
+ options[:query]['format'] = 'json'
79
+ options[:query]['api_key'] = @api_key
80
+ end
81
+ end
82
+
83
+ service = LastFmWebService.new 'xxxxxxxxx'
84
+ service.track 'cher', 'believe'
85
+
86
+ == Twilio Example send SMS message
87
+
88
+ TwilioWebService.service.send_sms_message '5551112222', 'Verification Code: 2121'
89
+
90
+ == Amazon Simple Email Service (SES)
91
+
92
+ How to replace body parameters with function arguments. Complete Amazon SES model in examples folder.
93
+
94
+ require 'digest/sha2'
95
+ require 'base64'
96
+
97
+ class AmazonSESService < RESTHome
98
+ base_uri 'https://email.us-east-1.amazonaws.com'
99
+
100
+ @@digest256 = OpenSSL::Digest::Digest.new("sha256")
101
+
102
+ route :verify_email_address, '/', :body => {'Action' => 'VerifyEmailAddress', 'EmailAddress' => :arg1}, :method => :post, :expected_status => 200, :no_body => true do |res|
103
+ res['VerifyEmailAddressResponse']
104
+ end
105
+
106
+ def initialize(access_key, secret)
107
+ @access_key = access_key
108
+ @secret = secret
109
+ end
110
+
111
+ def build_options!(options)
112
+ date = Time.now.getutc.httpdate
113
+ options[:headers] ||= {}
114
+ options[:headers]['Date'] = date
115
+ options[:headers]['X-Amzn-Authorization'] = "AWS3-HTTPS AWSAccessKeyId=#{@access_key},Algorithm=HMACSHA256,Signature=#{AmazonSESService.sign_request(@secret, date)}"
116
+ end
117
+
118
+ def self.sign_request(secret, date)
119
+ Base64.encode64(OpenSSL::HMAC.digest(@@digest256, secret, date)).gsub("\n","")
120
+ end
121
+ end
122
+
123
+ service = AmazonSESService.new :access_key_id => 'my-access-key', :secret_access_key => 'it-s-a-secret'
124
+ service.verify_email_address 'test@test.dev'
125
+
126
+ == Contributing to RESTHome
127
+
128
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
129
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
130
+ * Fork the project
131
+ * Start a feature/bugfix branch
132
+ * Commit and push until you are happy with your contribution
133
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
134
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
135
+
136
+ == Copyright
137
+
138
+ Copyright (c) 2010 Cykod LLC. See LICENSE.txt for
139
+ further details.
140
+
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "resthome"
16
+ gem.homepage = "http://github.com/cykod/resthome"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{RESTful web services consumer}
19
+ gem.description = %Q{Simple wrapper class generator for consuming RESTful web services}
20
+ gem.email = "doug@cykod.com"
21
+ gem.authors = ["Doug Youch"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ task :default => :spec
30
+
31
+ require 'rake/rdoctask'
32
+ Rake::RDocTask.new do |rdoc|
33
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
34
+
35
+ rdoc.rdoc_dir = 'rdoc'
36
+ rdoc.title = "resthome #{version}"
37
+ rdoc.rdoc_files.include('README*')
38
+ rdoc.rdoc_files.include('lib/**/*.rb')
39
+ end
40
+
41
+ for file in Dir['tasks/*.rake']
42
+ load file
43
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.0
@@ -0,0 +1,84 @@
1
+ require 'resthome'
2
+ require 'digest/sha2'
3
+ require 'base64'
4
+
5
+ class AmazonProductWebService < RESTHome
6
+ base_uri 'http://ecs.amazonaws.com'
7
+
8
+ DEFAULT_VERSION = '2009-03-31'
9
+
10
+ @@digest256 = OpenSSL::Digest::Digest.new("sha256")
11
+
12
+ attr_accessor :version, :access_key, :secret, :associate_tag
13
+
14
+ namespace '/onca' do
15
+ route :item_search, '/xml', :query => {'Keywords' => :arg1, 'SearchIndex' => :arg2, 'Operation' => 'ItemSearch', 'Service' => 'AWSECommerceService'} do |res|
16
+ res['ItemSearchResponse']['Items']['Item']
17
+ end
18
+
19
+ route :item_lookup, '/xml', :query => {'ItemId' => :arg1, 'Operation' => 'ItemLookup', 'Service' => 'AWSECommerceService', 'ResponseGroup' => 'Small'} do |res|
20
+ res['ItemLookupResponse']['Items']['Item']
21
+ end
22
+ end
23
+
24
+ def initialize(access_key, secret)
25
+ @access_key = access_key
26
+ @secret = secret
27
+ @version = DEFAULT_VERSION
28
+ @host = URI.parse(self.class.base_uri).host
29
+ end
30
+
31
+ def build_options!(options)
32
+ options[:query] ||= {}
33
+ options[:query]['AWSAccessKeyId'] = @access_key
34
+ options[:query]['Version'] = @version
35
+ options[:query]['Timestamp'] = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
36
+ options[:query]['AssociateTag'] = self.associate_tag if self.associate_tag
37
+ end
38
+
39
+ def sign_request(method, path, options)
40
+ signed_query = self.class.sign_request_v2(@secret, options[:query], method, @host, path)
41
+ options.delete :query
42
+ signed_query
43
+ end
44
+
45
+ def aws_request(method, path, options)
46
+ build_options! options
47
+ url = build_url(path)
48
+ signed_query = sign_request(method, path, options)
49
+ if method == :post
50
+ options[:body] = signed_query
51
+ else
52
+ url += "?#{signed_query}"
53
+ end
54
+
55
+ @request_method = method
56
+ @request_url = url
57
+ @request_options = options
58
+
59
+ @response = self.class.send(method, url, options)
60
+ end
61
+
62
+ alias_method :original_request, :request
63
+ alias_method :request, :aws_request
64
+
65
+ # copied from RightAws::AwsUtils
66
+ def self.amz_escape(param)
67
+ param.to_s.gsub(/([^a-zA-Z0-9._~-]+)/n) do
68
+ '%' + $1.unpack('H2' * $1.size).join('%').upcase
69
+ end
70
+ end
71
+
72
+ # copied from RightAws::AwsUtils
73
+ def self.sign_request_v2(aws_secret_access_key, service_hash, http_verb, host, uri)
74
+ canonical_string = service_hash.keys.sort.map do |key|
75
+ "#{self.amz_escape(key)}=#{self.amz_escape(service_hash[key])}"
76
+ end.join('&')
77
+
78
+ string_to_sign = "#{http_verb.to_s.upcase}\n#{host.downcase}\n#{uri}\n#{canonical_string}"
79
+
80
+ signature = self.amz_escape(Base64.encode64(OpenSSL::HMAC.digest(@@digest256, aws_secret_access_key, string_to_sign)).strip)
81
+
82
+ "#{canonical_string}&Signature=#{signature}"
83
+ end
84
+ end
@@ -0,0 +1,74 @@
1
+ require 'resthome'
2
+ require 'digest/sha2'
3
+ require 'base64'
4
+
5
+ class AmazonSESService < RESTHome
6
+ base_uri 'https://email.us-east-1.amazonaws.com'
7
+
8
+ @@digest256 = OpenSSL::Digest::Digest.new("sha256")
9
+
10
+ route :verify_email_address, '/', :body => {'Action' => 'VerifyEmailAddress', 'EmailAddress' => :arg1}, :method => :post, :expected_status => 200, :no_body => true do |res|
11
+ res['VerifyEmailAddressResponse']
12
+ end
13
+
14
+ route :list_verified_email_addresses, '/', :body => {'Action' => 'ListVerifiedEmailAddresses'}, :method => :post, :expected_status => 200, :no_body => true do |res|
15
+ res['ListVerifiedEmailAddressesResponse']['ListVerifiedEmailAddressesResult']
16
+ end
17
+
18
+ route :delete_verified_email_address, '/', :body => {'Action' => 'DeleteVerifiedEmailAddress', 'EmailAddress' => :arg1}, :method => :post, :expected_status => 200, :no_body => true do |res|
19
+ res['DeleteVerifiedEmailAddressResponse']
20
+ end
21
+
22
+ route :get_send_quota, '/', :body => {'Action' => 'GetSendQuota'}, :method => :post, :expected_status => 200, :no_body => true do |res|
23
+ res['GetSendQuotaResponse']
24
+ end
25
+
26
+ route :get_send_statistics, '/', :body => {'Action' => 'GetSendStatistics'}, :method => :post, :expected_status => 200, :no_body => true do |res|
27
+ res['GetSendStatisticsResponse']
28
+ end
29
+
30
+ route :send_email, '/', :body => {'Action' => 'SendEmail'}, :method => :post, :expected_status => 200 do |res|
31
+ res['SendEmailResponse']
32
+ end
33
+
34
+ route :send_text_email, '/', :body => {'Action' => 'SendEmail', 'Destination.ToAddresses.member.1' => :arg1, 'Message.Subject.Data' => :arg2, 'Message.Body.Text.Data' => :arg3, 'Source' => :arg4}, :method => :post, :expected_status => 200, :no_body => true do |res|
35
+ res['SendEmailResponse']
36
+ end
37
+
38
+ route :send_html_email, '/', :body => {'Action' => 'SendEmail', 'Destination.ToAddresses.member.1' => :arg1, 'Message.Subject.Data' => :arg2, 'Message.Body.Html.Data' => :arg3, 'Source' => :arg4}, :method => :post, :expected_status => 200, :no_body => true do |res|
39
+ res['SendEmailResponse']
40
+ end
41
+
42
+ route :send_raw_email, '/', :body => {'Action' => 'SendRawEmail', 'RawMessage.Data' => :arg1}, :method => :post, :expected_status => 200, :no_body => true do |res|
43
+ res['SendRawEmailResponse']
44
+ end
45
+
46
+ def initialize(options={})
47
+ @access_key = options[:access_key_id]
48
+ @secret = options[:secret_access_key]
49
+ end
50
+
51
+ def build_options!(options)
52
+ @error_response = nil
53
+ date = Time.now.getutc.httpdate
54
+ options[:headers] ||= {}
55
+ options[:headers]['Date'] = date
56
+ options[:headers]['X-Amzn-Authorization'] = "AWS3-HTTPS AWSAccessKeyId=#{@access_key},Algorithm=HMACSHA256,Signature=#{AmazonSESService.sign_request(@secret, date)}"
57
+ end
58
+
59
+ def self.sign_request(secret, date)
60
+ Base64.encode64(OpenSSL::HMAC.digest(@@digest256, secret, date)).gsub("\n","")
61
+ end
62
+
63
+ def error_response
64
+ @error_response ||= HTTParty::Parser.call self.response.body, HTTParty::Parser.format_from_mimetype(self.response.headers['content-type'])
65
+ end
66
+
67
+ def deliver(mail)
68
+ message = mail.is_a?(Hash) ? Mail.new(mail).to_s : mail.to_s
69
+ message = Base64.encode64 message
70
+ self.send_raw_email message
71
+ end
72
+
73
+ alias :deliver! :deliver
74
+ end
@@ -0,0 +1,55 @@
1
+ require 'resthome'
2
+ require 'json'
3
+
4
+ class ChargifyWebService < RESTHome
5
+
6
+ headers 'Content-Type' => 'application/json'
7
+
8
+ rest :customer, :customers, '/customers.json'
9
+ route :find_customer, '/customers/lookup.json', :resource => 'customer'
10
+ # find_customer_by_reference
11
+ route :customer_subscriptions, '/customers/:customer_id/subscriptions.json', :resource => :subscription
12
+
13
+ route :product_families, '/product_families.xml', :resource => :product_families
14
+
15
+ route :products, '/products.json', :resource => :product
16
+ route :product, '/products/:product_id.json', :resource => :product
17
+ route :find_product_by_handle, '/products/handle/:handle.json', :resource => :product
18
+
19
+ rest :subscription, :subscriptions, '/subscriptions.json'
20
+ route :cancel_subscription, '/subscriptions/:subscription_id.json', :resource => :subscription, :method => :delete, :expected_status => [200, 204]
21
+ route :reactivate_subscription, '/subscriptions/:subscription_id/reactivate.xml', :resource => :subscription, :method => :put, :expected_status => 200
22
+ route :subscription_transactions, '/subscriptions/:subscription_id/transactions.json', :resource => :transaction
23
+ # Chargify offers the ability to upgrade or downgrade a Customer's subscription in the middle of a billing period.
24
+ route :create_subscription_migration, '/subscriptions/:subscription_id/migrations.json', :expected_status => 200
25
+ route :reactivate_subscription, '/subscriptions/:subscription_id/reactivate.xml', :resource => :subscription, :method => :put, :expected_status => 200
26
+ route :create_subscription_credit, '/subscriptions/:subscription_id/credits.json', :resource => :credit
27
+ route :reset_subscription_balance, '/subscriptions/:subscription_id/reset_balance.xml', :resource => :subscription, :method => :put, :expected_status => 200
28
+
29
+ route :transactions, '/transactions.json', :resource => :transaction
30
+
31
+ route :create_charge, '/subscriptions/:subscription_id/charges.json', :resource => :charge
32
+
33
+ route :components, '/product_families/:product_family_id/components.json', :resource => :component
34
+ route :component_usages, '/subscriptions/:subscription_id/components/:component_id/usages.json', :resource => :usage
35
+ route :create_component_usage, '/subscriptions/:subscription_id/components/:component_id/usages.json', :resource => :usage, :expected_status => 200
36
+
37
+ route :coupon, '/product_families/:product_family_id/coupons/:coupon_id.json', :resource => :coupon
38
+ route :find_coupon, '/product_families/:product_family_id/coupons/find.json', :resource => :coupon
39
+ # find_coupon_by_code
40
+
41
+ route :subscription_components, '/subscriptions/:subscription_id/components.json', :resource => :component
42
+ route :edit_subscription_component, '/subscriptions/:subscription_id/components/:component_id.json', :resource => :component
43
+
44
+ def initialize(api_key, subdomain)
45
+ self.base_uri = "https://#{subdomain}.chargify.com"
46
+ self.basic_auth = {:username => api_key, :password => 'x'}
47
+ end
48
+
49
+ def build_options!(options)
50
+ super
51
+ options[:body] = options[:body].to_json if options[:body]
52
+ end
53
+
54
+ def parse_response!; end
55
+ end
@@ -0,0 +1,33 @@
1
+ require 'resthome'
2
+
3
+ class LastFmWebService < RESTHome
4
+ base_uri 'http://ws.audioscrobbler.com'
5
+
6
+ namespace '/2.0' do
7
+ route :user_neighbors, '/', :query => {'method' => 'user.getneighbours', 'user' => :arg1} do |res|
8
+ res['neighbours']['user']
9
+ end
10
+
11
+ route :track, '/', :query => {'method' => 'track.getinfo', 'artist' => :arg1, 'track' => :arg2}, :resource => 'track'
12
+
13
+ route :user_albums, '/', :query => {'method' => 'library.getalbums', 'user' => :arg1}, :resource => 'albums'
14
+
15
+ route :user_top_albums, '/', :query => {'method' => 'user.gettopalbums', 'user' => :arg1} do |res|
16
+ res['topalbums']['album']
17
+ end
18
+
19
+ route :user_top_tracks, '/', :query => {'method' => 'user.gettoptracks', 'user' => :arg1} do |res|
20
+ res['toptracks']['track']
21
+ end
22
+ end
23
+
24
+ def initialize(api_key)
25
+ @api_key = api_key
26
+ end
27
+
28
+ def build_options!(options)
29
+ options[:query] ||= {}
30
+ options[:query]['format'] = 'json'
31
+ options[:query]['api_key'] = @api_key
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ require 'resthome'
2
+
3
+ class TwilioWebService < RESTHome
4
+ base_uri 'https://api.twilio.com'
5
+
6
+ namespace '/2010-04-01' do
7
+ route :accounts, '/Accounts'
8
+
9
+ namespace '/Accounts' do
10
+ route :create_sms_message, '/:sid/SMS/Messages', :expected_status => 201 do |res|
11
+ res['TwilioResponse']['SMSMessage']
12
+ end
13
+ end
14
+ end
15
+
16
+ attr_accessor :number
17
+
18
+ def initialize(account_sid, auth_token, number)
19
+ @number = number
20
+ self.basic_auth = {:username => account_sid, :password => auth_token}
21
+ end
22
+
23
+ def self.service
24
+ config = YAML.load_file("#{Rails.root}/config/twilio.yml")
25
+ TwilioWebService.new config['twilio']['sid'], config['twilio']['token'], config['twilio']['number']
26
+ end
27
+
28
+ def send_sms_message(cell_phone, message)
29
+ self.create_sms_message self.basic_auth[:username], {'From' => @number, 'To' => cell_phone, 'Body' => message}
30
+ end
31
+ end
@@ -0,0 +1,89 @@
1
+ require 'resthome'
2
+ require 'nokogiri'
3
+
4
+ class WordpressWebService < RESTHome
5
+ attr_accessor :error
6
+
7
+ headers 'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)'
8
+
9
+ def initialize(url, username, password)
10
+ @uri = URI.parse(url.gsub(/\/$/, ''))
11
+ @username = username
12
+ @password = password
13
+ self.base_uri = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
14
+
15
+ self.route :wp_login_get, "#{@uri.path}/wp-login.php", :method => :get, :return => :parse_login_page
16
+ self.route :wp_login_post, "#{@uri.path}/wp-login.php", :method => :post, :return => :parse_login_page
17
+
18
+ self.route :wp_export_get, "#{@uri.path}/wp-admin/export.php", :method => :get, :return => :parse_export_form
19
+ self.route :wp_export, "#{@uri.path}/wp-admin/export.php", :method => :get
20
+ end
21
+
22
+ def parse_login_page(response)
23
+ return @error = 'Login page not found' unless response.code == 200
24
+
25
+ parent = Nokogiri::HTML.parse(response.body).css('body').first
26
+ login_form = parent.css('#loginform')
27
+ return @error = 'Login form not found' unless login_form.size > 0
28
+
29
+ login_error = parent.css('#login_error')
30
+ return @error = 'Login failed' if login_error.size > 0
31
+
32
+ login_form = login_form.first
33
+ @inputs = {}
34
+ login_form.css('input').each do |input|
35
+ next unless input.attributes['name']
36
+ @inputs[input.attributes['name'].to_s] = (input.attributes['value'] || '').to_s
37
+ end
38
+ end
39
+
40
+ def login
41
+ self.wp_login_get
42
+ return false if @inputs.nil?
43
+ @inputs['log'] = @username
44
+ @inputs['pwd'] = @password
45
+ begin
46
+ self.wp_login_post @inputs, :no_follow => true
47
+ rescue HTTParty::RedirectionTooDeep => e
48
+ save_cookies e.response.header.to_hash['set-cookie']
49
+ end
50
+ @error ? false : true
51
+ end
52
+
53
+ def parse_export_form(response)
54
+ parent = Nokogiri::HTML.parse(response.body).css('body').first
55
+ forms = parent.css('form')
56
+ return @error = 'Export form not found' unless forms.size > 0
57
+ export_form = forms.shift
58
+ while export_form && export_form.css('#mm_start').length == 0
59
+ export_form = forms.shift
60
+ end
61
+ return @error = 'Export form not found' unless export_form
62
+
63
+ @inputs = {}
64
+ export_form.css('input').each do |input|
65
+ next unless input.attributes['name']
66
+ @inputs[input.attributes['name'].to_s] = (input.attributes['value'] || '').to_s
67
+ end
68
+
69
+ export_form.css('select').each do |input|
70
+ next unless input.attributes['name']
71
+ value = ''
72
+ input.css('option').each do |option|
73
+ value = option.attributes['value'] if option.attributes['selected']
74
+ end
75
+
76
+ @inputs[input.attributes['name'].to_s] = (value || '').to_s
77
+ end
78
+
79
+ @inputs
80
+ end
81
+
82
+ def export
83
+ self.wp_export_get
84
+ return false if @error
85
+ self.wp_export :query => @inputs, :format => :plain
86
+ return self.response.body if self.response.headers['content-type'].to_s =~ /xml/
87
+ false
88
+ end
89
+ end