icontact-api 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ .Ti?c}7y?x�I*�J-�U���|QE�kJ3g ZÆhIrh֠@�O���;����=C4H?3�
2
+ ��N�����2s,9��:{K�H�e�ӄ�N��|�f�Y' !4���&�֊.�2 ��DA�j��2H����'N�R����'區��]�ۆV�;3��\�����
3
+ �*�]Do��9�i���`-k�*��bg��'��RDc�F �u0E��gM;k�=KpE�b���҃QZ� ���2��ı
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2009-01-16
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,13 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/icontact-api.rb
6
+ lib/icontact/api.rb
7
+ script/console
8
+ script/destroy
9
+ script/generate
10
+ spec/api_spec.rb
11
+ spec/spec.opts
12
+ spec/spec_helper.rb
13
+ tasks/rspec.rake
@@ -0,0 +1,82 @@
1
+ = icontact-api
2
+
3
+ == DESCRIPTION:
4
+
5
+ This gem provides a thin wrapper around the iContact 2.0 API.
6
+
7
+ == FEATURES/PROBLEMS:
8
+
9
+ * automatically signs each request
10
+ * handles packing and unpacking into json
11
+ * query params can be passed as an options hash
12
+
13
+ == SYNOPSIS:
14
+
15
+ Normally you will want to subclass the Icontact::Api class and define your API_KEY and API_SECRET, and optionally you may wish to hard-code a username and password for the API.
16
+
17
+ @api = MyApi.new(username, password)
18
+ @api.get('/a/000000/c/000000/messages', :limit=>10, :offset=>0)
19
+
20
+ Please see the icontact developer documentation for a full listing of the supported resources and url structure.
21
+
22
+ This gem is not officially supported by iContact. Please contact the author with bug reports, feature requests, or questions about this gem.
23
+
24
+
25
+ == REQUIREMENTS:
26
+
27
+ * requires JSON gem
28
+
29
+ == INSTALL:
30
+
31
+ * sudo gem install icontact-api
32
+
33
+ == USAGE
34
+
35
+ for convenience create a class like this that keeps track of your API_KEY, API_SECRET, and optionally an api username and password:
36
+
37
+ require 'icontact-api'
38
+ class BetaApi < Icontact::Api
39
+ API_USERNAME='username'
40
+ API_PASSWORD='password'
41
+ API_KEY = 'YOUR_API_KEY'
42
+ API_SECRET = 'YOUR_API_SECRET'
43
+ DOMAIN = "http://app.beta.icontact.com/icp"
44
+
45
+ def initialize(username = BetaApi::API_USERNAME, password = BetaApi::API_PASSWORD)
46
+ super(username, password)
47
+ self.key = API_KEY
48
+ self.secret = API_SECRET
49
+ self.domain = DOMAIN
50
+ end
51
+ end
52
+
53
+ Then you can use it like:
54
+
55
+ @api = BetaApi.new
56
+ @api.get('/a')
57
+ @api.post('/a/00000/c/0000/messages', data)
58
+
59
+ == LICENSE:
60
+
61
+ (The MIT License)
62
+
63
+ Copyright (c) 2009 Kevin Olbrich
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining
66
+ a copy of this software and associated documentation files (the
67
+ 'Software'), to deal in the Software without restriction, including
68
+ without limitation the rights to use, copy, modify, merge, publish,
69
+ distribute, sublicense, and/or sell copies of the Software, and to
70
+ permit persons to whom the Software is furnished to do so, subject to
71
+ the following conditions:
72
+
73
+ The above copyright notice and this permission notice shall be
74
+ included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
77
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
78
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
79
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
80
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
81
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
82
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,27 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/icontact-api'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('icontact-api', Icontact::Api::VERSION) do |p|
7
+ p.developer('Kevin Olbrich', 'kevin.olbrich@gmail.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = p.name # TODO this is default value
10
+ p.extra_deps = [
11
+ ['json','>= 1.1.3'],
12
+ ]
13
+ p.extra_dev_deps = [
14
+ ['newgem', ">= #{::Newgem::VERSION}"]
15
+ ]
16
+
17
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
18
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
19
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
20
+ p.rsync_args = '-av --delete --ignore-errors'
21
+ end
22
+
23
+ require 'newgem/tasks' # load /tasks/*.rake
24
+ Dir['tasks/**/*.rake'].each { |t| load t }
25
+
26
+ # TODO - want other tests/tasks run by default? Add them to the list
27
+ # task :default => [:spec, :features]
@@ -0,0 +1,5 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'icontact/api'
5
+ #require 'icontact-api/api'
@@ -0,0 +1,112 @@
1
+ require 'rubygems'
2
+ require 'net/http'
3
+ require 'digest'
4
+ require 'json'
5
+
6
+ class Icontact
7
+ class Api
8
+ VERSION = "0.1"
9
+ API_VERSION = "2.0"
10
+ DOMAIN = 'http://app.icontact.com/icp'
11
+ API_KEY = "API_KEY"
12
+ API_SECRET = "API_SECRET"
13
+ attr_accessor :username
14
+ attr_accessor :password
15
+ attr_accessor :key
16
+ attr_accessor :secret
17
+ attr_accessor :domain
18
+
19
+ def initialize(username, password)
20
+ self.username = username
21
+ self.password = password
22
+ self.domain = DOMAIN
23
+ self.key = API_KEY
24
+ self.secret = API_SECRET
25
+ end
26
+
27
+ # Package up any options into a query string and format it properly for the server
28
+ # arrays become comma separated lists and Times are expressed as iso8601
29
+ def self.package_query_params(params={})
30
+ return nil if params.nil? || params.empty?
31
+ massaged_params = params.map do |key, value|
32
+ case value
33
+ when Array:
34
+ "#{key}=#{value.join(',')}"
35
+ when Time:
36
+ "#{key}=#{value.strftime("%Y-%m-%dT%H:%M:%S")}#{"%+0.2d:00" % (value.gmtoff / 3600)}"
37
+ else
38
+ "#{key}=#{value}"
39
+ end
40
+ end
41
+ "?#{massaged_params.join('&')}"
42
+ end
43
+
44
+ # override this to use a different encoding method for sending data (like xml)
45
+ def self.body_encoder(data)
46
+ data.to_json
47
+ end
48
+
49
+ # override this method to use a different response parser (like REXML for an xml response)
50
+ # when the response is not actually a JSON object an exception is thrown and the raw response is returned in the body instead.
51
+ def self.parse_response(code, response)
52
+ {'code'=>code, 'body' => (JSON.parse(response) rescue response)}
53
+ end
54
+
55
+ def request_signature(method, timestamp, random, url)
56
+ Digest::SHA1.hexdigest("#{secret}#{password}#{timestamp}#{random}#{method.to_s.upcase}#{url}")
57
+ end
58
+
59
+ # populate headers required by the icontact server on each request for authentication
60
+ # Accept and Content-Type are set to application/json to use JSON objects for the
61
+ # data exchange. Also accepts text/xml for either, but then you have to deal with XML encoding and decoding
62
+ # manually
63
+ def apply_headers(method, req, url)
64
+ timestamp = Time.now.getgm.to_i
65
+ random = Kernel.rand(999999)
66
+ req.add_field('API_VERSION', API_VERSION)
67
+ req.add_field('ACCEPT','application/json')
68
+ req.add_field('Content-Type','application/json')
69
+ req.add_field('API_KEY', self.key)
70
+ req.add_field('API_USERNAME', self.username)
71
+ req.add_field('API_TIMESTAMP', timestamp)
72
+ req.add_field('API_NUMBER', random)
73
+ req.add_field('API_SIGNATURE', request_signature(method, timestamp, random, url))
74
+ return req
75
+ end
76
+
77
+ # dynamically create methods for get and delete. These methods do not require a body to be sent
78
+ [:get, :delete].each do |meth|
79
+ define_method(meth) do |url, *options|
80
+ request(meth, url, nil, options)
81
+ end
82
+ end
83
+
84
+ # dynamically create methods for get and delete. These methods require a body to be sent
85
+ [:post, :put].each do |meth|
86
+ define_method(meth) do |url, data, *options|
87
+ request(meth, url, data, options)
88
+ end
89
+ end
90
+
91
+ # Actually make the get, put, post, or delete request
92
+ def request(kind, url, data, options)
93
+ # options passed as optional parameter show up as an array
94
+ options = options.first if options.kind_of? Array
95
+ query_options = self.class.package_query_params(options)
96
+ full_url = URI.parse("#{self.domain}#{url}#{query_options}")
97
+
98
+ # create an object of the class required to process this method
99
+ klass = Object.module_eval("::Net::HTTP::#{kind.to_s.capitalize}", __FILE__, __LINE__)
100
+ request = klass.new([full_url.path, full_url.query].compact.join('?'))
101
+ request = apply_headers(kind, request, full_url)
102
+
103
+ # take passed data and encode it
104
+ request.body = self.class.body_encoder(data) if data
105
+
106
+ Net::HTTP.start(full_url.host, full_url.port) do |http|
107
+ response = http.request(request)
108
+ return self.class.parse_response(response.code, response.body)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/icontact-api.rb'}"
9
+ puts "Loading icontact-api gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,177 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Icontact::Api do
4
+ before(:each) do
5
+ @mock_time = mock('Time', :getgm => 999999)
6
+ Time.stub!(:now).and_return(@mock_time)
7
+ Kernel.stub!(:rand).and_return(111)
8
+ end
9
+
10
+ describe "api" do
11
+ before(:each) do
12
+ @api = Icontact::Api.new('mock_username', 'mock_password')
13
+ @response = mock('response',:code=>200, :body=>"body")
14
+ @mock_http_request = mock('http', :request=>@response)
15
+ Net::HTTP.stub!(:start).and_yield(@mock_http_request)
16
+ end
17
+
18
+ describe "an http request", :shared=>true do
19
+ it "should apply headers to the request" do
20
+ @mock_request = mock("Request", :body= => true)
21
+ @api.should_receive(:apply_headers).and_return(@mock_request)
22
+ do_request
23
+ end
24
+
25
+ it "should package query params" do
26
+ @api.class.should_receive(:package_query_params)
27
+ do_request(:limit=>10)
28
+ end
29
+
30
+ it "should send the request" do
31
+ Net::HTTP.should_receive(:start)
32
+ do_request
33
+ end
34
+
35
+ it "should parse the server response into a hash" do
36
+ @api.class.should_receive(:parse_response)
37
+ do_request
38
+ end
39
+ end
40
+
41
+ describe "an http request with a body", :shared=>true do
42
+ it_should_behave_like "an http request"
43
+
44
+ it "should package the data into the body" do
45
+ @api.class.should_receive(:body_encoder)
46
+ do_request
47
+ end
48
+ end
49
+
50
+ describe ".get" do
51
+
52
+ def do_request(options={})
53
+ @api.get("/a", options)
54
+ end
55
+
56
+ it_should_behave_like "an http request"
57
+ end
58
+
59
+ describe ".post" do
60
+ def do_request(options={})
61
+ @api.post("/a", {}, options)
62
+ end
63
+
64
+ it_should_behave_like "an http request with a body"
65
+ end
66
+
67
+ describe ".put" do
68
+ def do_request(options={})
69
+ @api.put("/a", {}, options)
70
+ end
71
+
72
+ it_should_behave_like "an http request with a body"
73
+ end
74
+
75
+ describe '.delete' do
76
+ def do_request(options={})
77
+ @api.delete("/a", options)
78
+ end
79
+
80
+ it_should_behave_like "an http request"
81
+ end
82
+ end
83
+
84
+ describe ".request_signature" do
85
+ before(:each) do
86
+ @api = Icontact::Api.new('username','password')
87
+ Kernel.stub!(:rand).and_return(111)
88
+ @mock_time = mock('Time', :getgm => 999999)
89
+ Time.stub!(:now).and_return(@mock_time)
90
+ Digest::SHA1.stub!(:hexdigest).and_return('api_signature')
91
+ end
92
+
93
+ it "should generate an API Signature" do
94
+ Digest::SHA1.should_receive(:hexdigest).with('API_SECRETpasswordtimestamp/urlrandomGET').and_return('api_signature')
95
+ @api.request_signature('get','timestamp''/url', 'random', '').should == "api_signature"
96
+ end
97
+ end
98
+
99
+ describe ".apply_headers" do
100
+ before(:each) do
101
+ @request = mock('Request', :add_field=>true)
102
+ @api = Icontact::Api.new('username','password')
103
+ end
104
+
105
+ def do_apply_headers
106
+ @api.apply_headers(:get, @request, 'http://fakeurl.com')
107
+ end
108
+
109
+ it "should add an API_VERSION header to indicate we are using the 2.0 version of the API" do
110
+ @request.should_receive(:add_field).with('API_VERSION', @api.class::API_VERSION)
111
+ do_apply_headers
112
+ end
113
+
114
+ it "should add an ACCEPT header indicating we want a JSON object back" do
115
+ @request.should_receive(:add_field).with('ACCEPT', 'application/json')
116
+ do_apply_headers
117
+ end
118
+
119
+ it "should add a Content-Type header indicating that passed data is JSON encoded" do
120
+ @request.should_receive(:add_field).with('Content-Type', 'application/json')
121
+ do_apply_headers
122
+ end
123
+
124
+ it "should add an API_KEY header to verify that our application is authrorized to use the API" do
125
+ @request.should_receive(:add_field).with('API_KEY', @api.class::API_KEY)
126
+ do_apply_headers
127
+ end
128
+
129
+ it "should add an API_USERNAME header to verify that our user is authorized to use the API" do
130
+ @request.should_receive(:add_field).with('API_USERNAME', 'username')
131
+ do_apply_headers
132
+ end
133
+
134
+ it "should add an API_TIMESTAMP header to prevent old requests from being replayed" do
135
+ @request.should_receive(:add_field).with('API_TIMESTAMP', 999999)
136
+ do_apply_headers
137
+ end
138
+
139
+ it "should add an API_NUMBER header" do
140
+ @request.should_receive(:add_field).with('API_NUMBER', 111)
141
+ do_apply_headers
142
+ end
143
+
144
+ it "should add an API_SIGNATURE header to ensure this api request is valid" do
145
+ @api.should_receive(:request_signature).and_return('api_signature')
146
+ @request.should_receive(:add_field).with('API_SIGNATURE', 'api_signature')
147
+ do_apply_headers
148
+ end
149
+ end
150
+
151
+ describe "class methods" do
152
+ it ".body_encoder should encode the data to be sent in JSON" do
153
+ data = {:messageIds=>[1,2,3,4,5]}
154
+ Icontact::Api::body_encoder(data).should == data.to_json
155
+ end
156
+
157
+ it ".parse_response should parse the JSON response into a hash" do
158
+ body = {:messageIds=>[1,2,3,4,5]}.to_json
159
+ Icontact::Api::parse_response(200, body).should == {"body"=>{"messageIds"=>[1, 2, 3, 4, 5]}, "code"=>200}
160
+ end
161
+
162
+ describe ".package_query_params" do
163
+ # the "string".split('').sort trick is used because the string may come back in a different order each time because
164
+ # it is generated from an unordered hash, this trick allows comparison
165
+ it "should package a hash into a query string according to the API requirements" do
166
+ options = {:limit=>10, :offset=>10, :messageId=>[1,2,3,4], :createdAt=>Time.at(1234567890)}
167
+ Icontact::Api::package_query_params(options).split('').sort.should ==
168
+ "?limit=10&messageId=1,2,3,4&createdAt=2009-02-13T18:31:30-05:00&offset=10".split('').sort
169
+ end
170
+
171
+ it "should return nil if passed an empty hash" do
172
+ Icontact::Api::package_query_params({}).should be_nil
173
+ end
174
+ end
175
+
176
+ end
177
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'rspec'
6
+ require 'spec'
7
+ end
8
+
9
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
10
+ require 'icontact-api'
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: icontact-api
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Olbrich
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDPDCCAiSgAwIBAgIBADANBgkqhkiG9w0BAQUFADBEMRYwFAYDVQQDDA1rZXZp
14
+ bi5vbGJyaWNoMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
15
+ FgNjb20wHhcNMDkwMzA3MTUwMzQ5WhcNMTAwMzA3MTUwMzQ5WjBEMRYwFAYDVQQD
16
+ DA1rZXZpbi5vbGJyaWNoMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJ
17
+ k/IsZAEZFgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvza3W
18
+ J5Dloirbhpge6teyZNfvOzuo478vtqnU/c6S8o2EerBkmWm88J+ipItO3U2HDPgP
19
+ a7THrx41/QEj1oG15mO6wtBLf0Z+AOJFAmf+Th8x3b46b3Voo1+suON67fCqCz+U
20
+ L5V2I5NBNywCte5Nzjh7knLkHr+rUCCKAIPK6vq+sASMIgmlhzZUuQfdRZMhRVZP
21
+ clMwf9sIp7LUTq2b/LCdP2dlGFydb1cyvaHjho+X/pk5uWKcr1OkrZtYFdxyeGU4
22
+ ZTtqEd5vaNTacYf0vGBfPfiolIfbmOa8Pgfyj8zkjBug/iukM/YGmwL1KAk8Qs+/
23
+ gInxSkyPxa7zkYTzAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0G
24
+ A1UdDgQWBBS+y2GRZjETz6d3jHKosqOZ6Ll+zjANBgkqhkiG9w0BAQUFAAOCAQEA
25
+ f3hCt6NBuESjAN4fkpbcfi3/Nj06aNl6CAfryfKaOaIfLcypT5nqP1qtqqGih5ne
26
+ QCe7jmtZHOGFC/SSlCS8obHSkCGn2cfUl/InfpF/YQnZV0Kp8esihuVmEjO0SgEU
27
+ yf46wW9Nh4byKctkgKMlWnIqwAyk4G1dD/le6MGJutb4pv5hT9qm1vaTFkAcy1Qu
28
+ 1VMZa+MH6xnINGdFyV8T7AYL5BaQTbp2WYsfbOvy3ZfxbpP5O3wc3wter/Cyp8pu
29
+ Wvn0/+13roT+v5T5yFIpu6NbSpuqvRaKZvS+n2ZgwS10rUPFydzn+335umE4vsfH
30
+ 4Umf0rf1f8h+GJia5xXYww==
31
+ -----END CERTIFICATE-----
32
+
33
+ date: 2009-03-24 00:00:00 -04:00
34
+ default_executable:
35
+ dependencies:
36
+ - !ruby/object:Gem::Dependency
37
+ name: json
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 1.1.3
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: newgem
48
+ type: :development
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.2.3
55
+ version:
56
+ - !ruby/object:Gem::Dependency
57
+ name: hoe
58
+ type: :development
59
+ version_requirement:
60
+ version_requirements: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.8.0
65
+ version:
66
+ description: This gem provides a thin wrapper around the iContact 2.0 API.
67
+ email:
68
+ - kevin.olbrich@gmail.com
69
+ executables: []
70
+
71
+ extensions: []
72
+
73
+ extra_rdoc_files:
74
+ - History.txt
75
+ - Manifest.txt
76
+ - README.rdoc
77
+ files:
78
+ - History.txt
79
+ - Manifest.txt
80
+ - README.rdoc
81
+ - Rakefile
82
+ - lib/icontact-api.rb
83
+ - lib/icontact/api.rb
84
+ - script/console
85
+ - script/destroy
86
+ - script/generate
87
+ - spec/api_spec.rb
88
+ - spec/spec.opts
89
+ - spec/spec_helper.rb
90
+ - tasks/rspec.rake
91
+ has_rdoc: true
92
+ homepage:
93
+ post_install_message:
94
+ rdoc_options:
95
+ - --main
96
+ - README.rdoc
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: "0"
104
+ version:
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: "0"
110
+ version:
111
+ requirements: []
112
+
113
+ rubyforge_project: icontact-api
114
+ rubygems_version: 1.3.1
115
+ signing_key:
116
+ specification_version: 2
117
+ summary: This gem provides a thin wrapper around the iContact 2.0 API.
118
+ test_files: []
119
+
Binary file