leadspend 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
File without changes
@@ -0,0 +1,14 @@
1
+ === 1.0.2 / 2012-08-23
2
+ * Moved username and password into options for client initialization
3
+
4
+ === 1.0.1 / 2012-08-23
5
+ * Added configurable JSON backends with reasonable defaults
6
+ * to use a particular backend, the supporting gem(s) must be installed (Yajl, JSON, Rails)
7
+ * Added support for the "role", "timeout", "retry" extended attributes on results
8
+ * Now using Hoe for gemspec
9
+ * Added MIT-LICENSE
10
+
11
+ === 1.0.0 / 2012-08-22
12
+ * Support for Leadspend API according to their spec documentation.
13
+ * unit tests require the fakeweb gem.
14
+
@@ -0,0 +1,14 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ lib/leadspend.rb
7
+ lib/leadspend/exceptions.rb
8
+ lib/leadspend/result.rb
9
+ lib/leadspend/client.rb
10
+ lib/leadspend/parser/json_parser.rb
11
+ lib/leadspend/parser/yajl_parser.rb
12
+ lib/leadspend/parser/rails_parser.rb
13
+ test/unit/test_leadspend_client.rb
14
+ test/mocks/leadspend/server.rb
@@ -0,0 +1,59 @@
1
+ = leadspend
2
+
3
+ * http://www.github.com/justindossey/leadspend
4
+
5
+ == DESCRIPTION:
6
+ Leadspend client access library.
7
+
8
+ == SYNOPSIS:
9
+
10
+ client = Leadspend::Client.new(:username => LEADSPEND_USERNAME,
11
+ :password => LEADSPEND_PASSWORD,
12
+ :ca_file => CA_FILE,
13
+ :timeout => 5)
14
+ is_valid_email = client.validate(params[:email]) # true if verified or unknown, false otherwise
15
+
16
+ == REQUIREMENTS:
17
+
18
+ * Ruby (of course) with OpenSSL support
19
+ * Your preferred JSON gem (json, yajl), or ActiveSupport if you use Rails
20
+ * FakeWeb for testing: https://github.com/chrisk/fakeweb
21
+ * Hoe for building the gem
22
+
23
+ == INSTALL:
24
+
25
+ * sudo gem install leadspend
26
+
27
+ == DEVELOPERS
28
+
29
+ Read the source!
30
+ After checking out the source, run:
31
+
32
+ $ rake newb
33
+
34
+ This task will install any missing dependencies, run the tests/specs,
35
+ and generate the RDoc.
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2012 Justin Dossey.
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
59
+
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ # Hoe.plugin :compiler
7
+ # Hoe.plugin :gem_prelude_sucks
8
+ # Hoe.plugin :inline
9
+ # Hoe.plugin :racc
10
+ # Hoe.plugin :rcov
11
+ # Hoe.plugin :rubyforge
12
+
13
+ Hoe.spec 'leadspend' do
14
+ developer('Justin Dossey', 'jbd@podomatic.com')
15
+ end
16
+
17
+ # vim: syntax=ruby
@@ -0,0 +1,18 @@
1
+ ##
2
+ # Leadspend API implementation for Ruby
3
+ # = Leadspend
4
+ # This (top-level) module contains constants based on the API specification.
5
+ module Leadspend
6
+ VERSION = '1.0.2'
7
+ DEFAULT_SERVERS = %w{primary.api.leadspend.com secondary.api.leadspend.com}
8
+ DEFAULT_VERSION = "v2"
9
+ MIN_TIMEOUT = 3
10
+ MAX_TIMEOUT = 15
11
+ RESULT_STATUSES = ['unknown','verified','disposable', 'unreachable', 'undeliverable', 'illegitimate']
12
+ end
13
+ require "#{File.dirname(__FILE__)}/leadspend/exceptions"
14
+ require "#{File.dirname(__FILE__)}/leadspend/parser"
15
+ require "#{File.dirname(__FILE__)}/leadspend/result"
16
+ require "#{File.dirname(__FILE__)}/leadspend/client"
17
+
18
+
@@ -0,0 +1,138 @@
1
+ require 'net/https'
2
+ ##
3
+ # = Leadspend Client
4
+ # The primary interface to Leadspend.
5
+ # Use it like so:
6
+ # client = Leadspend::Client.new(LEADSPEND_USERNAME, LEADSPEND_PASSWORD, :ca_file => CA_FILE, :timeout => 5)
7
+ # is_valid_email = client.validate(params[:email) # true if verified or unknown, false otherwise
8
+ # If you want more information about the response, use something like
9
+ # leadspend_result = client.fetch_result(params[:email])
10
+ # This will return a Leadspend::Result object representing the JSON response,
11
+ # with convenience methods like unreachable? and illegitimate?.
12
+
13
+ class Leadspend::Client
14
+ # Instantiate a client.
15
+ # Recommended options: :ca_file is the full path to a CA Cert file.
16
+ # :timeout is the server-side timeout in seconds, between 3 and 15. If a
17
+ # result is not available within the timeout, the response will be an
18
+ # "unknown" result.
19
+ def initialize(opts={})
20
+ options = opts
21
+ if defined?(HashWithIndifferentAccess)
22
+ options = HashWithIndifferentAccess.new(opts)
23
+ end
24
+ @username = options[:username]
25
+ @password = options[:password]
26
+ if @username.nil? or @password.nil?
27
+ raise Leadspend::Exceptions::LeadspendException, "No username or password specified!"
28
+ end
29
+ @servers = options[:servers] || Leadspend::DEFAULT_SERVERS
30
+ @api_version = options[:version] || Leadspend::DEFAULT_VERSION
31
+ # path to the CA file: download http://curl.haxx.se/ca/cacert.pem and put
32
+ # it someplace on your server.
33
+ @ca_file = options[:ca_file]
34
+
35
+ # set the JSON parser to use. Use the one specified, or choose a reasonable default.
36
+ case options[:json_parser]
37
+ when 'yajl'
38
+ require "#{File.dirname(__FILE__)}/parser/yajl_parser"
39
+ Leadspend::Result.json_parser=Leadspend::Parser::YajlParser
40
+ when 'rails'
41
+ require "#{File.dirname(__FILE__)}/parser/rails_parser"
42
+ Leadspend::Result.json_parser=Leadspend::Parser::RailsParser
43
+ when 'json'
44
+ require "#{File.dirname(__FILE__)}/parser/json_parser"
45
+ Leadspend::Result.json_parser=Leadspend::Parser::JSONParser
46
+ else
47
+ if defined? Rails
48
+ require "#{File.dirname(__FILE__)}/parser/rails_parser"
49
+ Leadspend::Result.json_parser=Leadspend::Parser::RailsParser
50
+ else
51
+ require "#{File.dirname(__FILE__)}/parser/json_parser"
52
+ Leadspend::Result.json_parser=Leadspend::Parser::JSONParser
53
+ end
54
+ end
55
+
56
+ @server_index = 0
57
+
58
+ @request_options = {}
59
+ # optional: allow a server timeout. Minimum is 3, max is 15
60
+ if options[:timeout]
61
+ @request_options[:timeout] = options[:timeout].to_i
62
+ if @request_options[:timeout] < Leadspend::MIN_TIMEOUT
63
+ @request_options[:timeout] = Leadspend::MIN_TIMEOUT
64
+ elsif @request_options[:timeout] > Leadspend::MAX_TIMEOUT
65
+ @request_options[:timeout] = Leadspend::MAX_TIMEOUT
66
+ end
67
+ end
68
+ end
69
+
70
+ # Return a boolean based on whether an address is valid or not.
71
+ # Valid statuses: unknown, validated.
72
+ # Invalid statuses: anything else.
73
+ def validate(address)
74
+ result = fetch_result(address)
75
+ return result.verified? || result.unknown?
76
+ end
77
+
78
+ # fetch a result from Leadspend, doing failover if necessary. R
79
+ # Returns a Leadspend::Result object if successful, or an exception if there was a failure.
80
+ def fetch_result(address)
81
+ retry_once = true
82
+ begin
83
+ result = query("/#{@api_version}/validity", address, @request_options)
84
+ rescue Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Errno::ECONNRESET, IOError,
85
+ Leadspend::Exceptions::ServerException, Leadspend::Exceptions::ServerBusyException
86
+ if retry_once
87
+ retry_once = false
88
+ @server_index = (@server_index + 1) % @servers.length
89
+ retry
90
+ else
91
+ raise $!
92
+ end
93
+ end
94
+ end
95
+
96
+ private
97
+ # do a full uri escape on a value for HTTP
98
+ def escape_param(param) # :nodoc:
99
+ URI::escape(param.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
100
+ end
101
+
102
+ # Do a request to Leadspend and return a Leadspend::Result or exception.
103
+ def query(base, address, param_hash) # :nodoc:
104
+ http = Net::HTTP.new(@servers[@server_index], 443)
105
+ http.use_ssl = true
106
+ if @ca_file
107
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
108
+ http.ca_file = @ca_file
109
+ end
110
+ if param_hash.empty?
111
+ request_path = [base, escape_param(address)].join('/')
112
+ else
113
+ param_str = param_hash.map{|k,v| [k.to_s, escape_param(v)].join('=')}.join('&')
114
+ request_path = [[base, escape_param(address)].join('/'), param_str].join('?')
115
+ end
116
+ http.start do
117
+ request = Net::HTTP::Get.new(request_path)
118
+ request.basic_auth @username, @password
119
+ response = http.request(request)
120
+ case response.code.to_i
121
+ when 200
122
+ return Leadspend::Result.new(response.body)
123
+ when 202
124
+ return Leadspend::Result.unknown(address)
125
+ when 400
126
+ raise Leadspend::Exceptions::BadRequestException, response.body
127
+ when 401
128
+ raise Leadspend::Exceptions::UnauthorizedRequestException, response.body
129
+ when 500
130
+ raise Leadspend::Exceptions::ServerException, response.body
131
+ when 503
132
+ raise Leadspend::Exceptions::ServerBusyException, response.body
133
+ else
134
+ raise Leadspend::Exceptions::UnknownResponseException, response.body
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,13 @@
1
+ ##
2
+ # = Leadspend Exceptions.
3
+ # The status code from the Leadspend server determines which exception is raised by the client.
4
+ module Leadspend
5
+ module Exceptions
6
+ class LeadspendException < Exception; end
7
+ class BadRequestException < LeadspendException ; end
8
+ class UnknownResponseException < LeadspendException ; end
9
+ class UnauthorizedRequestException < LeadspendException ; end
10
+ class ServerException < LeadspendException; end
11
+ class ServerBusyException < LeadspendException ; end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Leadspend
2
+ module Parser
3
+ class JSONParser
4
+ def self.encode(object)
5
+ JSON.generate(object)
6
+ end
7
+ def self.decode(string)
8
+ JSON.parse(string)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support'
2
+ module Leadspend
3
+ module Parser
4
+ class RailsParser
5
+ def self.encode(object)
6
+ ActiveSupport::JSON.encode(object)
7
+ end
8
+ def self.decode(string)
9
+ ActiveSupport::JSON.decode(string)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+
@@ -0,0 +1,14 @@
1
+ require 'yajl'
2
+ module Leadspend
3
+ module Parser
4
+ class YajlParser
5
+ def self.encode(object)
6
+ Yajl::Encoder.encode(object)
7
+ end
8
+ def self.decode(string)
9
+ Yajl::Parser.parse(string)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,89 @@
1
+ require 'json'
2
+
3
+ class Leadspend::Result
4
+ @@json_parser=nil
5
+ def initialize(json_string)
6
+ @raw = json_string
7
+ @result = self.class.decode_json(json_string)
8
+ end
9
+
10
+ def self.json_parser=(p)
11
+ @@json_parser = p
12
+ end
13
+
14
+ def raw
15
+ @raw
16
+ end
17
+
18
+ def result
19
+ @result['result']
20
+ end
21
+
22
+ Leadspend::RESULT_STATUSES.each do |status|
23
+ define_method("#{status}?") { result == status }
24
+ end
25
+
26
+ def self.method_missing(meth, *args, &block)
27
+ if Leadspend::RESULT_STATUSES.index(meth.to_s)
28
+ generate_result(meth.to_s, *args)
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ def self.respond_to?(meth)
35
+ Leadspend::RESULT_STATUSES.include?(meth.to_s) || super
36
+ end
37
+
38
+ def ==(other)
39
+ other.is_a?(Leadspend::Result) and other.address == self.address and other.result == self.result
40
+ end
41
+
42
+ def address
43
+ @result['address']
44
+ end
45
+
46
+ # extended attributes
47
+
48
+ def role?
49
+ result['role']
50
+ end
51
+
52
+ def full?
53
+ undeliverable? and result['full']
54
+ end
55
+
56
+ def timeout?
57
+ unknown? and result['timeout']
58
+ end
59
+
60
+ def retry_seconds
61
+ unknown? and result['retry']
62
+ end
63
+
64
+
65
+ private
66
+ def self.generate_result(status, address, opts={})
67
+ new(encode_json({'result' => status, 'address' => address}.merge(opts)))
68
+ end
69
+
70
+ def self.decode_json(json_string)
71
+ json_parser.decode(json_string)
72
+ end
73
+
74
+ def self.encode_json(object)
75
+ json_parser.encode(object)
76
+ end
77
+
78
+ def self.json_parser
79
+ if @@json_parser.nil?
80
+ unless defined?(Leadspend::Parser::JSONParser)
81
+ require "#{File.dirname(__FILE__)}/parser/json_parser"
82
+ end
83
+ @@json_parser = Leadspend::Parser::JSONParser
84
+ end
85
+ @@json_parser
86
+ end
87
+
88
+
89
+ end
@@ -0,0 +1,82 @@
1
+ require 'rubygems'
2
+ require 'fakeweb'
3
+ require "#{File.dirname(__FILE__)}/../../../init"
4
+ class Leadspend::Server
5
+ def initialize(opts={})
6
+ @username = opts[:username]
7
+ @password = opts[:password]
8
+ options = opts
9
+ @servers = options[:servers] || Leadspend::DEFAULT_SERVERS
10
+ @api_version = options[:version] || Leadspend::DEFAULT_VERSION
11
+ FakeWeb.allow_net_connect = false
12
+ register_all_urls
13
+ end
14
+
15
+ def unregister_all_urls
16
+ FakeWeb.clean_registry
17
+ end
18
+
19
+ def register_all_urls
20
+ @servers.each do |server|
21
+ Leadspend::RESULT_STATUSES.each do |status|
22
+
23
+ http_status = [200, 'OK']
24
+ email = "#{status}-#{http_status.first}@example.com"
25
+ #$stderr.puts("Registering #{url_for(server, email)}")
26
+ FakeWeb.register_uri(:get, url_for(server, email),
27
+ :body => Leadspend::Result.send(status, email).raw,
28
+ :status => http_status)
29
+ [Leadspend::MIN_TIMEOUT, Leadspend::MAX_TIMEOUT, (Leadspend::MIN_TIMEOUT-1), (Leadspend::MAX_TIMEOUT+1)].each do |timeout|
30
+ #$stderr.puts("Registering #{url_for(server, email, :timeout => timeout)}")
31
+ FakeWeb.register_uri(:get, url_for(server, email, :timeout => timeout),
32
+ :body => Leadspend::Result.send(status, email).raw,
33
+ :status => http_status)
34
+ end
35
+
36
+ # non-200 statuses
37
+
38
+ # for 202, have it be "unknown".
39
+ http_status = [202, 'Accepted']
40
+ email = "#{status}-#{http_status.first}@example.com"
41
+ FakeWeb.register_uri(:get, url_for(server, email),
42
+ :body => Leadspend::Result.unknown(email).raw,
43
+ :status => http_status)
44
+
45
+
46
+ # 401 and 400 should cause the client to raise an exception
47
+ [[400, 'Bad Request'], [401, 'Unauthorized']].each do |http_status|
48
+ email = "verified-#{http_status.first}@example.com"
49
+ FakeWeb.register_uri(:get, url_for(server, email), :body => 'Error!', :status => http_status)
50
+ end
51
+ end
52
+ end
53
+
54
+ # for 500 and 503, make this work on secondary, but not primary-- this means we can test failover
55
+ [[500, 'Internal Server Error'],[503, 'Service Unavailable']].each do |http_status|
56
+ email = "verified-#{http_status.first}@example.com"
57
+ FakeWeb.register_uri(:get, url_for(@servers.first, email), :body => 'Error!', :status => http_status)
58
+ new_http_status = [200, 'OK']
59
+ FakeWeb.register_uri(:get, url_for(@servers.last, email),
60
+ :body => Leadspend::Result.verified(email).raw,
61
+ :status => new_http_status )
62
+
63
+ # also register an "alwaysfail" address to see that the proper exception is raised
64
+ email = "alwaysfail-#{http_status.first}@example.com"
65
+ @servers.each do |server|
66
+ FakeWeb.register_uri(:get, url_for(server, email), :body => 'Error!', :status => http_status)
67
+ end
68
+ end
69
+ end
70
+
71
+ def url_for(server, email, opts={})
72
+ opts_str = ''
73
+ unless opts.empty?
74
+ opts_str += '?' + opts.map { |k,v| "#{k.to_s}=#{escape_param(v)}"}.join('&')
75
+ end
76
+ "https://#{@username}:#{@password}@#{server}/#{@api_version}/validity/#{escape_param email}#{opts_str}"
77
+ end
78
+
79
+ def escape_param(param)
80
+ URI::escape(param.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
81
+ end
82
+ end
@@ -0,0 +1,100 @@
1
+ require "#{File.dirname(__FILE__)}/../mocks/leadspend/server"
2
+ require 'test/unit'
3
+ class Leadspend::TestLeadspendClient < Test::Unit::TestCase
4
+ def setup
5
+ @server = Leadspend::Server.new(:username => 'test', :password => 'test')
6
+ @client = Leadspend::Client.new(:username => 'test', :password => 'test')
7
+ end
8
+
9
+ def test_yajl_backend
10
+ @client = Leadspend::Client.new(:username => 'test', :password => 'test', :json_parser => 'yajl')
11
+ verified_email="verified-200@example.com"
12
+ unknown_email="unknown-200@example.com"
13
+ assert @client.validate(verified_email)
14
+ assert @client.validate(unknown_email)
15
+ end
16
+
17
+ def test_rails_backend
18
+ @client = Leadspend::Client.new(:username => 'test', :password => 'test', :json_parser => 'rails')
19
+ verified_email="verified-200@example.com"
20
+ unknown_email="unknown-200@example.com"
21
+ assert @client.validate(verified_email)
22
+ assert @client.validate(unknown_email)
23
+ end
24
+
25
+ def test_result_consistency
26
+ verified_email="verified-200@example.com"
27
+ unknown_email="unknown-200@example.com"
28
+ assert Leadspend::Result.verified(verified_email).verified?
29
+ assert Leadspend::Result.unknown(unknown_email).unknown?
30
+ end
31
+
32
+ def test_validate
33
+ verified_email="verified-200@example.com"
34
+ unknown_email="unknown-200@example.com"
35
+ assert @client.validate(verified_email)
36
+ assert @client.validate(unknown_email)
37
+ end
38
+
39
+ def test_ok_results
40
+ Leadspend::RESULT_STATUSES.each do |status|
41
+ email = "#{status}-200@example.com"
42
+ assert_equal Leadspend::Result.send(status, email), @client.fetch_result(email)
43
+ end
44
+ end
45
+
46
+ def test_accepted_results
47
+ Leadspend::RESULT_STATUSES.each do |status|
48
+ email = "#{status}-202@example.com"
49
+ assert_equal Leadspend::Result.unknown(email), @client.fetch_result(email)
50
+ end
51
+ end
52
+
53
+ def test_400_results
54
+ status='verified'
55
+ email = "#{status}-400@example.com"
56
+ assert_raise(Leadspend::Exceptions::BadRequestException) do
57
+ @client.fetch_result(email)
58
+ end
59
+ end
60
+
61
+ def test_401_results
62
+ status='verified'
63
+ email = "#{status}-401@example.com"
64
+ assert_raise(Leadspend::Exceptions::UnauthorizedRequestException) do
65
+ @client.fetch_result(email)
66
+ end
67
+ end
68
+
69
+ def test_500_failover_results
70
+ status='verified'
71
+ email = "#{status}-500@example.com"
72
+ assert_equal Leadspend::Result.send(status, email), @client.fetch_result(email)
73
+ end
74
+
75
+ def test_500_everywhere
76
+ status='alwaysfail'
77
+ email = "#{status}-500@example.com"
78
+ assert_raise(Leadspend::Exceptions::ServerException) do
79
+ @client.fetch_result(email)
80
+ end
81
+ end
82
+
83
+ def test_503_failover_results
84
+ status='verified'
85
+ email = "#{status}-503@example.com"
86
+ assert_equal Leadspend::Result.send(status, email), @client.fetch_result(email)
87
+ end
88
+
89
+ def test_503_everywhere
90
+ status='alwaysfail'
91
+ email = "#{status}-503@example.com"
92
+ assert_raise(Leadspend::Exceptions::ServerBusyException) do
93
+ @client.fetch_result(email)
94
+ end
95
+ end
96
+
97
+ def teardown
98
+ @server.unregister_all_urls unless @server.nil?
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leadspend
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 2
10
+ version: 1.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Justin Dossey
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain:
17
+ - |
18
+ -----BEGIN CERTIFICATE-----
19
+ MIIDMDCCAhigAwIBAgIBADANBgkqhkiG9w0BAQUFADA+MQwwCgYDVQQDDANqYmQx
20
+ GTAXBgoJkiaJk/IsZAEZFglwb2RvbWF0aWMxEzARBgoJkiaJk/IsZAEZFgNjb20w
21
+ HhcNMTIwODIzMTc1NjI2WhcNMTMwODIzMTc1NjI2WjA+MQwwCgYDVQQDDANqYmQx
22
+ GTAXBgoJkiaJk/IsZAEZFglwb2RvbWF0aWMxEzARBgoJkiaJk/IsZAEZFgNjb20w
23
+ ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5RGjRB6bqQgjXJJGqgsnP
24
+ o+eYygOuuJiteU8x5KEAj9VgM7GdOkBszpwDxRfBuZo8yrCmtDowD+yvTdNochOD
25
+ PTXcDaEshBsRr8j8ZW8LKUE8uFwwHGH1eeUSIzt2DytosC/MAvUbDQCD/2aqWshW
26
+ wvO2I08bSRyusrxAGILYcB3CWx0WTU/Gr5aVBaHBRRi3Ebmu2pFzRYQuDnJx7Xiq
27
+ kB9yGx8cBwRqT8YEu+vRiM+2t77xXN6mVYoP4hsNafOURHCJuW3R8r5rkbq2OP+y
28
+ EDIGIUnQS7oTndT1Xw7o2czQud2+uWAl+TMCCaN3sX10c4L05i3vKiIcioiqIzON
29
+ AgMBAAGjOTA3MB0GA1UdDgQWBBTwCGTQ7oaGQqyQXzsTDrgeDwlglTALBgNVHQ8E
30
+ BAMCBLAwCQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQo4JD6kU2Jf2+Qk0
31
+ 1/bcV1i/x2W/NBY0U3GGMg9hpVZ0U5iUM3hyEfH6fFI36qL+SeQN3OZWefdoKT1W
32
+ B9deFyS4nG4u3KX5I8StJDN1TVm/6pd2oFadkhBeOJohiYspa5XjTxdn47zZOTIU
33
+ LI+e36qne3wsTZRNw3xtp3cHgXSOKvAW8GVmJHk/2fvvzP3M14xjLSecu9gz3leB
34
+ CCypHKDQ9StNcMuvHsRyFOoojb2iJygucIcOXBy0bQEOzUVFDzwaLYNAciAUlOPs
35
+ es1G1v2drcgWtxkPCQNzgqw2rOq6B5UHqxBh9IB3xEXZ1YYaU4Si6jDLtEWy76Fa
36
+ DHOLCQ==
37
+ -----END CERTIFICATE-----
38
+
39
+ date: 2012-08-23 00:00:00 Z
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ prerelease: false
44
+ requirement: &id001 !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ hash: 19
50
+ segments:
51
+ - 3
52
+ - 10
53
+ version: "3.10"
54
+ type: :development
55
+ version_requirements: *id001
56
+ - !ruby/object:Gem::Dependency
57
+ name: hoe
58
+ prerelease: false
59
+ requirement: &id002 !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ~>
63
+ - !ruby/object:Gem::Version
64
+ hash: 7
65
+ segments:
66
+ - 3
67
+ - 0
68
+ version: "3.0"
69
+ type: :development
70
+ version_requirements: *id002
71
+ description: Leadspend client access library.
72
+ email:
73
+ - jbd@podomatic.com
74
+ executables: []
75
+
76
+ extensions: []
77
+
78
+ extra_rdoc_files:
79
+ - History.txt
80
+ - Manifest.txt
81
+ - README.txt
82
+ files:
83
+ - .autotest
84
+ - History.txt
85
+ - Manifest.txt
86
+ - README.txt
87
+ - Rakefile
88
+ - lib/leadspend.rb
89
+ - lib/leadspend/exceptions.rb
90
+ - lib/leadspend/result.rb
91
+ - lib/leadspend/client.rb
92
+ - lib/leadspend/parser/json_parser.rb
93
+ - lib/leadspend/parser/yajl_parser.rb
94
+ - lib/leadspend/parser/rails_parser.rb
95
+ - test/unit/test_leadspend_client.rb
96
+ - test/mocks/leadspend/server.rb
97
+ - .gemtest
98
+ homepage: http://www.github.com/justindossey/leadspend
99
+ licenses: []
100
+
101
+ post_install_message:
102
+ rdoc_options:
103
+ - --main
104
+ - README.txt
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: 3
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ requirements: []
126
+
127
+ rubyforge_project: leadspend
128
+ rubygems_version: 1.8.15
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: Leadspend client access library.
132
+ test_files:
133
+ - test/unit/test_leadspend_client.rb
@@ -0,0 +1,4 @@
1
+
2
+ �:��o�����"�ݎ)��U���F���$�i
3
+ �TR�|9�b�$,_lpc�.��ѴY�Z,yn���R�.r�+� ��N�>D��5B��#JIGr���%Ͷ'�9��۲��0���_j�El����?H���Hn9$��@�+�l+^���^���8���^CG�45R[�*�>�sη��9j�-�,�f�� G-�O�|7O
4
+ ҄��5�p�*�a�*�gp� K��1ƳW7$)�c��v��&&�ʏ�,R%nv�