rbet 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. data/README.rdoc +39 -0
  2. data/Rakefile +56 -0
  3. data/lib/rbet.rb +31 -0
  4. data/lib/rbet/auth.rxml +8 -0
  5. data/lib/rbet/client.rb +87 -0
  6. data/lib/rbet/error.rb +50 -0
  7. data/lib/rbet/list.rb +149 -0
  8. data/lib/rbet/list_add.rxml +8 -0
  9. data/lib/rbet/list_list_all.rxml +6 -0
  10. data/lib/rbet/list_retrieve.rxml +6 -0
  11. data/lib/rbet/list_retrieve_subscribers.rxml +6 -0
  12. data/lib/rbet/list_send_email.rxml +12 -0
  13. data/lib/rbet/ping.rxml +4 -0
  14. data/lib/rbet/renderable.rb +41 -0
  15. data/lib/rbet/subscriber.rb +137 -0
  16. data/lib/rbet/subscriber_add.rxml +15 -0
  17. data/lib/rbet/subscriber_delete.rxml +7 -0
  18. data/lib/rbet/subscriber_retrieve.rxml +8 -0
  19. data/lib/rbet/subscriber_retrieve_by_id.rxml +8 -0
  20. data/lib/rbet/subscriber_update.rxml +17 -0
  21. data/lib/rbet/tracker.rb +57 -0
  22. data/lib/rbet/tracker_retrieve_summary.rxml +8 -0
  23. data/lib/rbet/triggered_send.rb +60 -0
  24. data/lib/rbet/triggered_send.rxml +21 -0
  25. data/lib/rbet/version.rb +13 -0
  26. data/test/client_test.rb +18 -0
  27. data/test/help.rb +121 -0
  28. data/test/list_test.rb +18 -0
  29. data/test/subscriber_test.rb +18 -0
  30. data/test/templates/diagnostics_ping_success.rxml +5 -0
  31. data/test/templates/list_add_failure.rxml +6 -0
  32. data/test/templates/list_add_success.rxml +9 -0
  33. data/test/templates/list_retrieve_all_success.rxml +12 -0
  34. data/test/templates/list_retrieve_bylistid_success.rxml +15 -0
  35. data/test/templates/subscriber_add_success.rxml +6 -0
  36. data/test/templates/subscriber_retrieve_failed.rxml +9 -0
  37. data/test/templates/subscriber_retrieve_success.rxml +15 -0
  38. metadata +92 -0
@@ -0,0 +1,39 @@
1
+ == Ruby Library for ExactTarget
2
+
3
+ This is an attempt to make integrating easier with ExactTarget. ExactTarget is
4
+ an email newsletter system designed to make it easy to setup timely newsletters.
5
+
6
+ Exact Target: http://www.exacttarget.com/
7
+
8
+ Exact Target API:
9
+ http://developers.exacttarget.com/Web/help/Overview/Introduction_to_ExactTarget_API_Help.htm
10
+
11
+ == Adding rbet to a Rails Project
12
+
13
+ If you are using Git to manage your rails project and would like to add rbet as a submodule:
14
+
15
+ git submodule add git://github.com/sbraford/rbet.git vendor/rbet
16
+
17
+ Then in the bottom of your environment.rb, or in an initializer, add:
18
+
19
+ require File.join(RAILS_ROOT, 'vendor', 'rbet', 'lib', 'et.rb')
20
+
21
+ == Development Notes
22
+
23
+ Original development work was performed by Todd A. Fisher.
24
+
25
+ Forking development to GitHub + minor development additions/changes by Shanti A. Braford.
26
+
27
+ == Contributing
28
+
29
+ If you'd like to contribute, fork a copy of the repo on GitHub.
30
+
31
+ When you have patch(es) ready, contact me at:shantibraford@gmail.com
32
+
33
+ == Notes
34
+
35
+ 2000 character limit for each attribute
36
+
37
+ == Win32 Notes
38
+
39
+ This has not been tested on Windows. May the force be with you, young win32 jedi =)
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'lib/rbet/version'
6
+
7
+ spec = Gem::Specification.new do |s|
8
+ s.name = 'rbet'
9
+ s.version = RBET::Version.to_s
10
+ s.has_rdoc = true
11
+ s.extra_rdoc_files = %w(README.rdoc)
12
+ s.rdoc_options = %w(--main README.rdoc)
13
+ s.summary = "A ruby wrapper for the Exact Target API"
14
+ s.author = 'See Contributing Section'
15
+ s.email = 'kevin@conceptsahead.com'
16
+ s.homepage = 'http://github.com/n3bulous/rbet'
17
+ s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
18
+ # s.executables = ['rbet']
19
+
20
+ # s.add_dependency('gem_name', '~> 0.0.1')
21
+ end
22
+
23
+ Rake::GemPackageTask.new(spec) do |pkg|
24
+ pkg.gem_spec = spec
25
+ end
26
+
27
+ Rake::TestTask.new do |t|
28
+ t.libs << 'test'
29
+ t.test_files = FileList["test/*_test.rb"]
30
+ t.verbose = true
31
+ end
32
+
33
+ begin
34
+ require 'rcov/rcovtask'
35
+
36
+ Rcov::RcovTask.new(:coverage) do |t|
37
+ t.libs = ['test']
38
+ t.test_files = FileList["test/*_test.rb"]
39
+ t.verbose = true
40
+ t.rcov_opts = ['--text-report', "-x #{Gem.path}", '-x /Library/Ruby', '-x /usr/lib/ruby']
41
+ end
42
+
43
+ task :default => :coverage
44
+
45
+ rescue LoadError
46
+ warn "\n**** Install rcov (sudo gem install relevance-rcov) to get coverage stats ****\n"
47
+ task :default => :test
48
+ end
49
+
50
+
51
+ desc 'Generate the gemspec to serve this Gem from Github'
52
+ task :github do
53
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
54
+ File.open(file, 'w') {|f| f << spec.to_ruby }
55
+ puts "Created gemspec: #{file}"
56
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ # Copyright (c) 2007 Todd A. Fisher
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included
13
+ # in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ require 'rubygems'
25
+ gem 'activesupport'
26
+ require 'active_support'
27
+
28
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/rbet"))
29
+ %w(renderable error client subscriber list tracker triggered_send).each do |lib|
30
+ require lib
31
+ end
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" ?>
2
+ <exacttarget>
3
+ <authorization>
4
+ <username><%= @username %></username>
5
+ <password><%= @password %></password>
6
+ </authorization>
7
+ <%= @system %>
8
+ </exacttarget>
@@ -0,0 +1,87 @@
1
+ #
2
+ # Copyright (c) 2007 Todd A. Fisher
3
+ #
4
+ # Portions Copyright (c) 2008 Shanti A. Braford
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included
15
+ # in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+ require 'net/https'
26
+ require 'uri'
27
+ require 'erb'
28
+
29
+ module RBET
30
+ class Client
31
+ attr_reader :username, :password, :headers
32
+ include RBET::Renderable
33
+
34
+ # Initializes a new ET::Client object
35
+ #
36
+ # Usaage:
37
+ #
38
+ # client = ET::Client.new('tester','tester11', {:service_url => 'http://127.0.0.1:99999/test/', :use_ssl => false})
39
+ # client.status
40
+ # => "Running"
41
+ # client.live?
42
+ # => true
43
+ #
44
+ def initialize(username,password,options={})
45
+ @username = username
46
+ @password = password
47
+ service_url = options[:service_url] ? options[:service_url] : 'https://www.exacttarget.com/api/integrate.asp?qf=xml'
48
+ @uri = URI.parse(service_url)
49
+ @url = Net::HTTP.new(@uri.host, @uri.port)
50
+ @url.use_ssl = options.key?(:use_ssl) ? options[:use_ssl] : true
51
+ @url.set_debug_output options.key?(:debug_output) ? options[:debug_output] : nil
52
+ @headers = {
53
+ 'Content-Type' => 'application/x-www-form-urlencoded'
54
+ }
55
+ end
56
+
57
+ # Boolean value of whether the service is running or not currently
58
+ def live?
59
+ @current_status ||= status
60
+ @current_status == 'Running'
61
+ end
62
+
63
+ # Returns the string value from the ExactTarget API ping method. ("Running" when the system is operational)
64
+ def status
65
+ response = send do|io|
66
+ io << render_template('ping')
67
+ end
68
+ Error.check_response_error(response)
69
+ doc = Hpricot.XML( response.read_body )
70
+ @current_status = doc.at("Ping").inner_html
71
+ end
72
+
73
+ # usage:
74
+ # send do|io|
75
+ # io << 'more xml'
76
+ # end
77
+ def send
78
+ @system = ""
79
+ yield @system
80
+
81
+ result = 'qf=xml&xml=' + render_template( 'auth' )
82
+
83
+ @url.post( @uri.path, result, @headers.merge('Content-length' => result.length.to_s) )
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ # Copyright (c) 2007 Todd A. Fisher
3
+ #
4
+ # Portions Copyright (c) 2008 Shanti A. Braford
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included
15
+ # in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+ module RBET
26
+ class Error < RuntimeError
27
+ attr_reader :code, :message
28
+ def initialize(error_code,error_msg)
29
+ @code = error_code
30
+ @message = error_msg
31
+ end
32
+
33
+ def to_s
34
+ "Code: #{@code}. Message: #{@message}"
35
+ end
36
+
37
+ # raise a new error object from an HTTP response if it contains an error
38
+ def self.check_response_error(response)
39
+ if response.class != Net::HTTPOK
40
+ raise Error.new(-1,'Network error')
41
+ end
42
+ doc = Hpricot.XML(response.body)
43
+ error_code = doc.at("error")
44
+ error_msg = doc.at("error_description")
45
+ if( error_code and error_msg )
46
+ raise Error.new(error_code.inner_html.to_i,error_msg.inner_html)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,149 @@
1
+ #
2
+ # Copyright (c) 2007 Todd A. Fisher
3
+ #
4
+ # Portions Copyright (c) 2008 Shanti A. Braford
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included
15
+ # in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+ module RBET
26
+ #
27
+ # Subscriber list
28
+ # usage:
29
+ #
30
+ # # create a new subscriber list
31
+ # super_list = List.add 'Super list', :type => :public
32
+ # => ET::List
33
+ #
34
+ # # retrieve the list by name
35
+ # basic_list = List.retrieve_by_name('My Super List')
36
+ # => ET::List
37
+ #
38
+ # # retrieve by id
39
+ # basic_list = List.retrieve_by_id(12322)
40
+ # => ET::List
41
+ #
42
+ # # send an email to a list
43
+ # list_id = 147000
44
+ # email_template_id = 9999123
45
+ # list = ET::List.new('username', 'password')
46
+ # list.send_email(list_id, email_template_id, {:first_name => 'John', :last_name => 'Wayne'})
47
+ #
48
+ class List < Client
49
+ attr_reader :attributes
50
+
51
+ def initialize(username,password,options={})
52
+ super
53
+ @attributes = {}
54
+ end
55
+
56
+ # get all the lists
57
+ def all
58
+ response = send do|io|
59
+ io << render_template('list_list_all')
60
+ end
61
+ Error.check_response_error(response)
62
+ doc = Hpricot.XML( response.read_body )
63
+ listids = []
64
+ (doc/"listid").each do|listid|
65
+ listids << listid.inner_html.to_i
66
+ end
67
+ listids
68
+ end
69
+
70
+ # returns a new list object by id
71
+ def retrieve_by_id( id )
72
+ @search_type = "listid"
73
+ @search_value = id
74
+ response = send do|io|
75
+ io << render_template('list_retrieve')
76
+ end
77
+ Error.check_response_error(response)
78
+ load_list( response.read_body )
79
+ end
80
+
81
+ # returns a new list object by list name
82
+ def retrieve_by_name( name )
83
+ @search_type = "listname"
84
+ @search_value = name
85
+ response = send do|io|
86
+ io << render_template('list_retrieve')
87
+ end
88
+ Error.check_response_error(response)
89
+ load_list( response.read_body )
90
+ end
91
+
92
+ # defaults type to private if not private or public
93
+ # returns the new list id
94
+ def add(name, type='private')
95
+ @list_name = name
96
+ @list_type = type
97
+ @list_type = 'private' if type != 'public' or type != 'private'
98
+ response = send do|io|
99
+ io << render_template('list_add')
100
+ end
101
+ Error.check_response_error(response)
102
+ doc = Hpricot.XML( response.read_body )
103
+ doc.at("list_description").inner_html.to_i
104
+ end
105
+
106
+ def subscriber_emails(list_id)
107
+ @list_id = list_id
108
+ response = send do|io|
109
+ io << render_template('list_retrieve_subscribers')
110
+ end
111
+ Error.check_response_error(response)
112
+ body = response.read_body
113
+ doc = Hpricot.XML( body )
114
+ emails = []
115
+ (doc/"Email__Address").each do |row|
116
+ emails << row.inner_html
117
+ end
118
+ emails
119
+ end
120
+
121
+ # Sends an email to the list specified
122
+ def send_email(list_id, email_id, attrs = {})
123
+ defaults = {:from_name => '', :from_email => '', :additional => '',
124
+ :multipart_mime => true, :track_links => true, :send_date => 'immediate', :send_time => ''}
125
+ @list_id, @email_id = list_id, email_id
126
+ @extra_attrs = defaults.merge(attrs)
127
+ response = send do|io|
128
+ io << render_template('list_send_email')
129
+ end
130
+ Error.check_response_error(response)
131
+ #puts "Response Body: #{response.read_body} \n"
132
+ doc = Hpricot.XML( response.read_body )
133
+ doc.at("job_description").inner_html.to_i rescue nil
134
+ end
135
+
136
+ private
137
+
138
+ def load_list( body )
139
+ doc = Hpricot.XML( body )
140
+ doc.at("list").each_child do|child|
141
+ if child.respond_to?(:name) and child.respond_to?(:inner_html)
142
+ @attributes[child.name] = child.inner_html
143
+ end
144
+ end
145
+ self
146
+ end
147
+
148
+ end
149
+ end
@@ -0,0 +1,8 @@
1
+ <system>
2
+ <system_name>list</system_name>
3
+ <action>add</action>
4
+ <search_type></search_type>
5
+ <search_value></search_value>
6
+ <list_type><%= @list_type %></list_type>
7
+ <list_name><%= @list_name %></list_name>
8
+ </system>
@@ -0,0 +1,6 @@
1
+ <system>
2
+ <system_name>list</system_name>
3
+ <action>retrieve</action>
4
+ <search_type>listname</search_type>
5
+ <search_value></search_value>
6
+ </system>
@@ -0,0 +1,6 @@
1
+ <system>
2
+ <system_name>list</system_name>
3
+ <action>retrieve</action>
4
+ <search_type><%= @search_type %></search_type>
5
+ <search_value><%= @search_value %></search_value>
6
+ </system>
@@ -0,0 +1,6 @@
1
+ <system>
2
+ <system_name>list</system_name>
3
+ <action>retrieve_sub</action>
4
+ <search_type>listid</search_type>
5
+ <search_value><%= @list_id %></search_value>
6
+ </system>
@@ -0,0 +1,12 @@
1
+ <system>
2
+ <system_name>job</system_name>
3
+ <action>send</action>
4
+ <search_type>emailid</search_type>
5
+ <search_value><%= @email_id %></search_value>
6
+ <% @extra_attrs.each do|name, value| %>
7
+ <<%= name.to_s %>><%= value.to_s %></<%= name %>>
8
+ <% end %>
9
+ <lists>
10
+ <list><%= @list_id %></list>
11
+ </lists>
12
+ </system>
@@ -0,0 +1,4 @@
1
+ <system>
2
+ <system_name>diagnostics</system_name>
3
+ <action>Ping</action>
4
+ </system>
@@ -0,0 +1,41 @@
1
+ #
2
+ # Copyright (c) 2007 Todd A. Fisher
3
+ #
4
+ # Portions Copyright (c) 2008 Shanti A. Braford
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included
15
+ # in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+ module RBET
26
+ module Renderable
27
+ def set_template_path(path)
28
+ @template_path = path
29
+ end
30
+
31
+ def template_path(name)
32
+ File.join( (@template_path || File.dirname(__FILE__)), "#{name}.rxml")
33
+ end
34
+
35
+ def render_template( name )
36
+ erb = ERB.new( File.open( template_path(name) ,"r").read, 0, "<>")
37
+ erb.result( binding )
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,137 @@
1
+ #
2
+ # Copyright (c) 2007 Todd A. Fisher
3
+ #
4
+ # Portions Copyright (c) 2008 Shanti A. Braford
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included
15
+ # in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ require 'rubygems'
26
+ require 'hpricot'
27
+
28
+ module RBET
29
+
30
+ #
31
+ # usage:
32
+ #
33
+ # # get an existing subscriber
34
+ # subscriber = Subscriber.load!('user@example.com')
35
+ # => ET::Subscriber
36
+ #
37
+ # # subscribe a new user to an existing list
38
+ # subscriber = Subscriber.add('user@example.com',list)
39
+ # => ET::Subscriber
40
+ #
41
+ class Subscriber < Client
42
+ attr_accessor :attrs
43
+ attr_reader :email, :status
44
+
45
+ def initialize(username,password,options={})
46
+ super
47
+ @attrs = {}
48
+ end
49
+
50
+ def load!(email)
51
+ @email = email
52
+ response = send do|io|
53
+ io << render_template('subscriber_retrieve')
54
+ end
55
+ Error.check_response_error(response)
56
+ load_response(response.read_body)
57
+ end
58
+
59
+ def load_response(body)
60
+ doc = Hpricot.XML(body)
61
+ subscriber = doc.at(:subscriber)
62
+ # load elements into the attrs hash
63
+ @attrs = {}
64
+ subscriber.each_child do|attr_element|
65
+ if attr_element.elem?
66
+ name = attr_element.name.gsub(/__/,' ')
67
+ value = attr_element.inner_html
68
+ @attrs[name] = value
69
+ if name == 'Email Address'
70
+ @email = value
71
+ elsif name == 'Status'
72
+ @status = value
73
+ end
74
+ end
75
+ end
76
+ end
77
+ private :load_response
78
+
79
+ # desc:
80
+ # add this user as a new subscriber to the list, with a set of attributes
81
+ # params:
82
+ # listid: id of the e-mail list to subscribe this user to
83
+ # email: E-mail address of subscriber
84
+ def add( email, listid, attributes ={} )
85
+ @email = email
86
+ @subscriber_listid = listid
87
+ @attributes = attributes
88
+ response = send do|io|
89
+ io << render_template('subscriber_add')
90
+ end
91
+ Error.check_response_error(response)
92
+ doc = Hpricot.XML(response.read_body)
93
+ doc.at("subscriber_description").inner_html.to_i
94
+ end
95
+
96
+ # desc:
97
+ # update this a subscriber
98
+ # params:
99
+ # listid: id of the e-mail list to subscribe this user to
100
+ # email: E-mail address of subscriber
101
+ # subscriberid: id for the subscriber to update
102
+ def update(subscriberid, email, listid, attributes ={} )
103
+ @email = email
104
+ @listid = listid
105
+ @subscriberid = subscriberid
106
+ @attributes = attributes
107
+ response = send do|io|
108
+ io << render_template('subscriber_update')
109
+ end
110
+ Error.check_response_error(response)
111
+ doc = Hpricot.XML(response.read_body)
112
+ doc.at("subscriber_description").inner_html.to_i
113
+ end
114
+
115
+ # desc:
116
+ # delete this user as a new subscriber to the list, or completely from ET
117
+ # params:
118
+ # listid: id of the e-mail list to unsubscribe this user from
119
+ # email: E-mail address of subscriber
120
+ # subscriberid: id for the subscriber to delete COMPLETELY
121
+ def delete(subscriberid, email, listid, attributes ={} )
122
+ @email = email
123
+ @subscriber_listid = listid
124
+ @subscriberid = subscriberid
125
+
126
+ puts render_template('subscriber_delete')
127
+ response = send do|io|
128
+ io << render_template('subscriber_delete')
129
+ end
130
+ Error.check_response_error(response)
131
+ doc = Hpricot.XML(response.read_body)
132
+ doc.at("subscriber_info").inner_html
133
+ end
134
+
135
+
136
+ end
137
+ end
@@ -0,0 +1,15 @@
1
+ <system>
2
+ <system_name>subscriber</system_name>
3
+ <action>add</action>
4
+ <search_type>listid</search_type>
5
+ <search_value><%= @subscriber_listid %></search_value>
6
+ <search_value2></search_value2>
7
+ <values>
8
+ <Email__Address><%= @email %></Email__Address>
9
+ <status>active</status>
10
+ <% @attributes.each do|name,value| %>
11
+ <<%= name %>><%= (value.is_a?(Array)) ? value.join(',') : value %></<%= name %>>
12
+ <% end %>
13
+ </values>
14
+ <update>true</update>
15
+ </system>
@@ -0,0 +1,7 @@
1
+ <system>
2
+ <system_name>subscriber</system_name>
3
+ <action>delete</action>
4
+ <search_type><%= @subscriberid.nil? ? "listid" : "subid" %></search_type>
5
+ <search_value><%= @subscriberid.nil? ? @subscriber_listid : @subscriberid %></search_value>
6
+ <search_value2><%= @email if @subscriberid.nil? %></search_value2>
7
+ </system>
@@ -0,0 +1,8 @@
1
+ <system>
2
+ <system_name>subscriber</system_name>
3
+ <action>retrieve</action>
4
+ <search_type>listid</search_type>
5
+ <search_value><%= @list_id %></search_value>
6
+ <search_value2><%= @email %></search_value2>
7
+ <showChannelID></showChannelID>
8
+ </system>
@@ -0,0 +1,8 @@
1
+ <system>
2
+ <system_name>subscriber</system_name>
3
+ <action>retrieve</action>
4
+ <search_type>subid</search_type>
5
+ <search_value><%= @subid %></search_value>
6
+ <search_value2></search_value2>
7
+ <showChannelID></showChannelID>
8
+ </system>
@@ -0,0 +1,17 @@
1
+ <system>
2
+ <system_name>subscriber</system_name>
3
+ <action>edit</action>
4
+ <search_type><%= @subscriberid.nil? ? "listid" : "subid" %></search_type>
5
+ <search_value><%= @subscriberid.nil? ? @listid : @subscriberid %></search_value>
6
+ <search_value2><%= @email unless @subscriberid.nil? %></search_value2>
7
+ <values>
8
+ <Email__Address><%= @email %></Email__Address>
9
+ <% unless @listid.nil? %>
10
+ <status>active</status>
11
+ <% end %>
12
+ <% @attributes.each do|name,value| %>
13
+ <<%= name %>><%= (value.is_a?(Array)) ? value.join(',') : value %></<%= name %>>
14
+ <% end %>
15
+ </values>
16
+ <update>true</update>
17
+ </system>
@@ -0,0 +1,57 @@
1
+ #
2
+ # Copyright (c) 2008 Shanti A. Braford
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included
13
+ # in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'rubygems'
24
+ require 'hpricot'
25
+
26
+ module RBET
27
+
28
+ #
29
+ # usage:
30
+ #
31
+ # # First load the Tracker client
32
+ # tracker_client = ET::Tracker.new('username', 'password')
33
+ #
34
+ # # get job summary
35
+ # summary = job_client.retrieve_summary(12345) # pass a job_id
36
+ # => {'sentCount' => 163, 'deliveredCount' => 159, ... }
37
+ #
38
+ #
39
+ class Tracker < Client
40
+
41
+ def initialize(username,password,options={})
42
+ super
43
+ end
44
+
45
+ # retrieves tracking information for a particular job id
46
+ def retrieve_summary( job_id )
47
+ @job_id = job_id
48
+ response = send do|io|
49
+ io << render_template('tracker_retrieve_summary')
50
+ end
51
+ Error.check_response_error(response)
52
+ h = Hash.from_xml(response.read_body)
53
+ h['exacttarget']['system']['tracking']['emailSummary']
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ <system>
2
+ <system_name>tracking</system_name>
3
+ <action>retrieve</action>
4
+ <sub_action>summary</sub_action>
5
+ <search_type>jobID</search_type>
6
+ <search_value><%= @job_id %></search_value>
7
+ <search_value2></search_value2>
8
+ </system>
@@ -0,0 +1,60 @@
1
+ #
2
+ # Copyright (c) 2008 Shanti A. Braford
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included
13
+ # in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'rubygems'
24
+ require 'hpricot'
25
+
26
+ module RBET
27
+
28
+ #
29
+ # usage:
30
+ #
31
+ # # First load the Trigger client
32
+ # trigger = ET::TriggeredSend.new('username', 'password')
33
+ #
34
+ # # send message
35
+ # summary = trigger.deliver("someone@domain.org", "message-key", {:first_name => 'John', :last_name => 'Wayne'})
36
+ # => 0 # success
37
+ #
38
+ #
39
+ class TriggeredSend < Client
40
+
41
+ def initialize(username, password, options={})
42
+ super
43
+ end
44
+
45
+ # deliver triggered email
46
+ def deliver(email, external_key, attributes={} )
47
+ @email = email
48
+ @external_key = external_key
49
+ @attributes = attributes
50
+ raise "external_key can't be nil" unless @external_key
51
+ response = send do|io|
52
+ io << render_template('triggered_send')
53
+ end
54
+ Error.check_response_error(response)
55
+ doc = Hpricot.XML(response.read_body)
56
+ doc.at("triggered_send_description").inner_html.to_i
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,21 @@
1
+ <system>
2
+ <system_name>triggeredsend</system_name>
3
+ <action>add</action>
4
+ <TriggeredSend xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
5
+ xmlns:xsd='http://www.w3.org/2001/XMLSchema'
6
+ xmlns='http://exacttarget.com/wsdl/partnerAPI'>
7
+ <TriggeredSendDefinition>
8
+ <CustomerKey><%= @external_key %></CustomerKey>
9
+ </TriggeredSendDefinition>
10
+ <Subscribers>
11
+ <SubscriberKey><%= @email %></SubscriberKey>
12
+ <EmailAddress><%= @email %></EmailAddress>
13
+ <% @attributes.each do |key, value| %>
14
+ <Attributes>
15
+ <Name><%= key %></Name>
16
+ <Value><%= value %></Value>
17
+ </Attributes>
18
+ <% end %>
19
+ </Subscribers>
20
+ </TriggeredSend>
21
+ </system>
@@ -0,0 +1,13 @@
1
+ module RBET
2
+ module Version
3
+
4
+ MAJOR = 1
5
+ MINOR = 0
6
+ TINY = 0
7
+
8
+ def self.to_s # :nodoc:
9
+ [MAJOR, MINOR, TINY].join('.')
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__),"help.rb")
2
+
3
+ class TestClient < Test::Unit::TestCase
4
+ include RBET::TestCase
5
+
6
+ def test_client_send_ping
7
+ client = RBET::Client.new('tester','tester11', {:service_url => 'http://127.0.0.1:9999/test/', :use_ssl => false})
8
+ result = client.send do|io|
9
+ io << %q(<system>
10
+ <system_name>diagnostics</system_name>
11
+ <action>Ping</action>
12
+ </system>)
13
+ end
14
+ assert_equal Net::HTTPOK, result.class
15
+ assert_match /<Ping>Running<\/Ping>/, result.body
16
+ end
17
+
18
+ end
@@ -0,0 +1,121 @@
1
+ require 'test/unit'
2
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
3
+ require 'rbet'
4
+ require 'webrick'
5
+ require 'thread'
6
+ require 'rubygems'
7
+ gem 'hpricot'
8
+ require 'hpricot'
9
+
10
+ # shut up, webrick :-)
11
+ class ::WEBrick::HTTPServer
12
+ def access_log(config, req, res)
13
+ # nop
14
+ end
15
+ end
16
+ class ::WEBrick::BasicLog
17
+ def log(level, data)
18
+ # nop
19
+ end
20
+ end
21
+
22
+ class RBETService
23
+ include RBET::Renderable
24
+ def initialize
25
+ set_template_path( File.join(File.dirname(__FILE__), "templates") )
26
+ end
27
+ end
28
+
29
+ class DiagnosticsService < RBETService
30
+ def ping(params)
31
+ render_template("diagnostics_ping_success")
32
+ end
33
+ end
34
+
35
+ class ListService < RBETService
36
+ def add(params)
37
+ list_type = params['list_type']
38
+ if list_type != 'private' and list_type != 'public'
39
+ render_template("list_add_failure")
40
+ else
41
+ render_template("list_add_success")
42
+ end
43
+ end
44
+
45
+ def retrieve(params)
46
+ render_template("list_retrieve_all_success")
47
+ end
48
+ end
49
+
50
+ class SubscriberService < RBETService
51
+
52
+ def retrieve(params)
53
+ if params['search_value2']
54
+ @email = params['search_value2']
55
+ render_template("subscriber_retrieve_success")
56
+ else
57
+ render_template("subscriber_retrieve_failed")
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ # list for subscriber requests and respond like ET would
64
+ class SubscriberRBETService < ::WEBrick::HTTPServlet::AbstractServlet
65
+
66
+ def do_POST(req, res)
67
+
68
+ xml_body = String.new(req.body)
69
+ xml_body.gsub!(/qf=xml&xml=/,'')
70
+ doc = Hpricot.XML(xml_body)
71
+ system = doc.at(:system)
72
+ system_name = system.at(:system_name).inner_html.strip.downcase
73
+ action = system.at(:action).inner_html.strip.downcase
74
+
75
+ params = {}
76
+ # load all the system parameters into a hash
77
+ system.each_child do|element|
78
+ next unless element.elem?
79
+ params[element.name] = element.inner_html.strip
80
+ end
81
+
82
+ response = service_for(system_name).send(action, params)
83
+
84
+ res.body = %Q(<?xml version="1.0" ?>
85
+ <exacttarget>
86
+ #{response}
87
+ </exacttarget>)
88
+
89
+ res['Content-Type'] = "text/xml"
90
+ end
91
+
92
+ private
93
+ def service_for(system_name)
94
+ eval("#{system_name.capitalize}Service.new") #render_template("#{system_name}_#{action}_success")
95
+ end
96
+
97
+ end
98
+
99
+ module RBET
100
+ module TestCase
101
+
102
+ def setup
103
+ # create the server
104
+ @server = WEBrick::HTTPServer.new({:BindAddress => "localhost", :Port => 9999})
105
+
106
+ # setup test server (simulates exact target)
107
+ @server.mount("/test/", SubscriberRBETService)
108
+
109
+ # start up the server in a background thread
110
+ @thread = Thread.new(@server) do|server|
111
+ server.start
112
+ end
113
+ end
114
+
115
+ def teardown
116
+ @server.shutdown
117
+ #@thread.join
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__),"help.rb")
2
+
3
+ class ListClient < Test::Unit::TestCase
4
+ include RBET::TestCase
5
+ def setup
6
+ super
7
+ @client = RBET::List.new('tester','tester11', :service_url => 'http://127.0.0.1:9999/test/', :use_ssl => false, :debug_output => $stderr)
8
+ end
9
+
10
+ def test_list_all
11
+ @client.all
12
+ end
13
+
14
+ def test_list_add
15
+ @client.add('sample list')
16
+ end
17
+
18
+ end
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__),"help.rb")
2
+
3
+ class SubscriberClient < Test::Unit::TestCase
4
+ include RBET::TestCase
5
+
6
+ def test_subscriber_load
7
+ client = RBET::Subscriber.new('tester', 'tester11', :service_url => 'http://127.0.0.1:9999/test/', :use_ssl => false)
8
+ client.load!('jdoe@email.com')
9
+ assert_equal 'jdoe@email.com', client.attrs['Email Address']
10
+ assert_equal 'John', client.attrs['First Name']
11
+ assert_equal 'Doe', client.attrs['Last Name']
12
+ assert_equal "", client.attrs['Title']
13
+ assert_equal nil, client.attrs['Not Event Defined']
14
+ assert_equal 'jdoe@email.com', client.email
15
+ assert_equal 'Active', client.status
16
+ end
17
+
18
+ end
@@ -0,0 +1,5 @@
1
+ <system>
2
+ <diagnostics>
3
+ <Ping>Running</Ping>
4
+ </diagnostics>
5
+ </system>)
@@ -0,0 +1,6 @@
1
+ <?xml version='1.0'?>
2
+ <exacttarget>
3
+ <system>
4
+ <list><error>93</error><error_description>You did not specify a valid list type.</error_description></list>
5
+ </system>
6
+ </exacttarget>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" ?>
2
+ <exacttarget>
3
+ <system>
4
+ <list>
5
+ <list_info>List was added successfully</list_info>
6
+ <list_description>80080</list_description>
7
+ </list>
8
+ </system>
9
+ </exacttarget>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" ?>
2
+ <exacttarget>
3
+ <system>
4
+ <list>
5
+ <listid>12345</listid>
6
+ <listid>67890</listid>
7
+ <listid>80080</listid>
8
+ <listid>80081</listid>
9
+ <listid>80082</listid>
10
+ </list>
11
+ </system>
12
+ </exacttarget>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" ?>
2
+ <exacttarget>
3
+ <system>
4
+ <list>
5
+ <list_name>API-API Test List</list_name>
6
+ <list_type>Public</list_type>
7
+ <modified>8/18/2003 10:11:59 AM</modified>
8
+ <subscriber_count>129</subscriber_count>
9
+ <active_total>126</active_total>
10
+ <held_count>1</held_count>
11
+ <bounce_count>2</bounce_count>
12
+ <unsub_count>0</unsub_count>
13
+ </list>
14
+ </system>
15
+ </exacttarget>
@@ -0,0 +1,6 @@
1
+ <system>
2
+ <subscriber>
3
+ <subscriber_info>Subscriber was added/updated successfully</subscriber_info>
4
+ <subscriber_description>12334566</subscriber_description>
5
+ </subscriber>
6
+ </system>
@@ -0,0 +1,9 @@
1
+ <?xml version='1.0'?>
2
+ <exacttarget>
3
+ <system>
4
+ <subscriber>
5
+ <error>1</error>
6
+ <error_description>Subscriber not found with ListID = <%= @listid %> Email Address = <%= @email %></error_description>
7
+ </subscriber>
8
+ </system>
9
+ </exacttarget>
@@ -0,0 +1,15 @@
1
+ <system>
2
+ <subscriber>
3
+ <subid>125704849</subid>
4
+ <listid>63718</listid>
5
+ <list_name>Newsletter List</list_name>
6
+ <Email__Address><%= @email %></Email__Address>
7
+ <Status>Active</Status>
8
+ <Email__Type>HTML</Email__Type>
9
+ <First__Name>John</First__Name>
10
+ <Last__Name>Doe</Last__Name>
11
+ <Title />
12
+ <Region />
13
+ <showChannelID>123456</showChannelID>
14
+ </subscriber>
15
+ </system>
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbet
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - See Contributing Section
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: kevin@conceptsahead.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - lib/rbet/auth.rxml
28
+ - lib/rbet/client.rb
29
+ - lib/rbet/error.rb
30
+ - lib/rbet/list.rb
31
+ - lib/rbet/list_add.rxml
32
+ - lib/rbet/list_list_all.rxml
33
+ - lib/rbet/list_retrieve.rxml
34
+ - lib/rbet/list_retrieve_subscribers.rxml
35
+ - lib/rbet/list_send_email.rxml
36
+ - lib/rbet/ping.rxml
37
+ - lib/rbet/renderable.rb
38
+ - lib/rbet/subscriber.rb
39
+ - lib/rbet/subscriber_add.rxml
40
+ - lib/rbet/subscriber_delete.rxml
41
+ - lib/rbet/subscriber_retrieve.rxml
42
+ - lib/rbet/subscriber_retrieve_by_id.rxml
43
+ - lib/rbet/subscriber_update.rxml
44
+ - lib/rbet/tracker.rb
45
+ - lib/rbet/tracker_retrieve_summary.rxml
46
+ - lib/rbet/triggered_send.rb
47
+ - lib/rbet/triggered_send.rxml
48
+ - lib/rbet/version.rb
49
+ - lib/rbet.rb
50
+ - test/client_test.rb
51
+ - test/help.rb
52
+ - test/list_test.rb
53
+ - test/subscriber_test.rb
54
+ - test/templates/diagnostics_ping_success.rxml
55
+ - test/templates/list_add_failure.rxml
56
+ - test/templates/list_add_success.rxml
57
+ - test/templates/list_retrieve_all_success.rxml
58
+ - test/templates/list_retrieve_bylistid_success.rxml
59
+ - test/templates/subscriber_add_success.rxml
60
+ - test/templates/subscriber_retrieve_failed.rxml
61
+ - test/templates/subscriber_retrieve_success.rxml
62
+ has_rdoc: true
63
+ homepage: http://github.com/n3bulous/rbet
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --main
69
+ - README.rdoc
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.5
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: A ruby wrapper for the Exact Target API
91
+ test_files: []
92
+