MattHall-campaign_monitor 1.3.2.2
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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +52 -0
- data/Rakefile +31 -0
- data/TODO +6 -0
- data/campaign_monitor.gemspec +53 -0
- data/init.rb +1 -0
- data/install.rb +0 -0
- data/lib/campaign_monitor/base.rb +55 -0
- data/lib/campaign_monitor/campaign.rb +240 -0
- data/lib/campaign_monitor/client.rb +228 -0
- data/lib/campaign_monitor/helpers.rb +27 -0
- data/lib/campaign_monitor/list.rb +211 -0
- data/lib/campaign_monitor/misc.rb +46 -0
- data/lib/campaign_monitor/result.rb +31 -0
- data/lib/campaign_monitor/subscriber.rb +43 -0
- data/lib/campaign_monitor.rb +270 -0
- data/support/class_enhancements.rb +35 -0
- data/support/faster-xml-simple/lib/faster_xml_simple.rb +187 -0
- data/support/faster-xml-simple/test/regression_test.rb +47 -0
- data/support/faster-xml-simple/test/test_helper.rb +17 -0
- data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +46 -0
- data/test/campaign_monitor_test.rb +90 -0
- data/test/campaign_test.rb +110 -0
- data/test/client_test.rb +129 -0
- data/test/list_test.rb +115 -0
- data/test/test_helper.rb +27 -0
- metadata +97 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
class CampaignMonitor
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def handle_response(response)
|
5
|
+
return [] if response.empty?
|
6
|
+
|
7
|
+
if response["Code"].to_i == 0
|
8
|
+
# success!
|
9
|
+
yield(response)
|
10
|
+
elsif response["Code"].to_i == 100
|
11
|
+
raise InvalidAPIKey
|
12
|
+
else
|
13
|
+
# error!
|
14
|
+
raise ApiError, response["Code"] + ": " + response["Message"]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def timestamp_format
|
19
|
+
'%Y-%m-%d %H:%M:%S'
|
20
|
+
end
|
21
|
+
|
22
|
+
def formatted_timestamp(datetime, format=timestamp_format)
|
23
|
+
datetime.strftime(format)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'soap/wsdlDriver'
|
2
|
+
|
3
|
+
class CampaignMonitor
|
4
|
+
# Provides access to the subscribers and info about subscribers
|
5
|
+
# associated with a Mailing List
|
6
|
+
class List < Base
|
7
|
+
include CampaignMonitor::Helpers
|
8
|
+
|
9
|
+
id_field "ListID"
|
10
|
+
name_field "Title"
|
11
|
+
|
12
|
+
VALID_ATTRIBUTES=%w{ConfirmOptIn UnsubscribePage ConfirmationSuccessPage ListID Title}
|
13
|
+
|
14
|
+
# Example
|
15
|
+
# @list = new List(12345)
|
16
|
+
def initialize(attrs={})
|
17
|
+
super
|
18
|
+
@attributes=attrs
|
19
|
+
end
|
20
|
+
|
21
|
+
# Example
|
22
|
+
#
|
23
|
+
# @list = @client.new_list.defaults
|
24
|
+
|
25
|
+
def defaults
|
26
|
+
defaults={"ConfirmOptIn" => "false",
|
27
|
+
"UnsubscribePage" => "",
|
28
|
+
"ConfirmationSuccessPage" => ""}
|
29
|
+
@attributes=defaults.merge(@attributes)
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
# AR like
|
34
|
+
def save
|
35
|
+
id ? Update : Create
|
36
|
+
end
|
37
|
+
|
38
|
+
# Loads a list by it's ID
|
39
|
+
#
|
40
|
+
# @list = List.GetDetail(1234)
|
41
|
+
def self.GetDetail(id)
|
42
|
+
list=self.new("ListID" => id)
|
43
|
+
list.GetDetail(true)
|
44
|
+
list.result.code == 101 ? nil : list
|
45
|
+
end
|
46
|
+
|
47
|
+
# loads a list by it's ID
|
48
|
+
#
|
49
|
+
# @list = List.GetDetail(1234)
|
50
|
+
def self.[](k)
|
51
|
+
GetDetail(k)
|
52
|
+
end
|
53
|
+
|
54
|
+
def GetDetail(overwrite=false)
|
55
|
+
@result=Result.new(cm_client.List_GetDetail("ListID" => id))
|
56
|
+
@attributes=@result.raw.merge(@attributes)
|
57
|
+
@attributes.merge!(@result.raw) if overwrite
|
58
|
+
@result.success?
|
59
|
+
end
|
60
|
+
|
61
|
+
def Update
|
62
|
+
# if we're dealing with a half baked object that Client#lists has given
|
63
|
+
# us then we need to popular all the fields before we can attempt an update
|
64
|
+
unless @fully_baked
|
65
|
+
self.GetDetail
|
66
|
+
@fully_baked=true
|
67
|
+
end
|
68
|
+
@result=Result.new(cm_client.List_Update(@attributes))
|
69
|
+
@result.success?
|
70
|
+
end
|
71
|
+
|
72
|
+
def Delete
|
73
|
+
@result=Result.new(cm_client.List_Delete("ListID" => id))
|
74
|
+
@result.success?
|
75
|
+
end
|
76
|
+
|
77
|
+
def Create
|
78
|
+
@result=Result.new(cm_client.List_Create(@attributes))
|
79
|
+
self.id = @result.content if @result.success?
|
80
|
+
@result.success?
|
81
|
+
end
|
82
|
+
|
83
|
+
# Example
|
84
|
+
# @list = new List(12345)
|
85
|
+
# result = @list.add_subscriber("ralph.wiggum@simpsons.net")
|
86
|
+
#
|
87
|
+
# if result.succeeded?
|
88
|
+
# puts "Added Subscriber"
|
89
|
+
# end
|
90
|
+
def add_subscriber(email, name=nil, custom_fields=nil)
|
91
|
+
if custom_fields.nil?
|
92
|
+
Result.new(cm_client.Subscriber_Add("ListID" => self.id, "Email" => email, "Name" => name))
|
93
|
+
else
|
94
|
+
add_subscriber_with_custom_fields(email, name, custom_fields)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_and_resubscribe(email, name=nil, custom_fields=nil)
|
99
|
+
if custom_fields.nil?
|
100
|
+
Result.new(cm_client.Subscriber_AddAndResubscribe("ListID" => self.id, "Email" => email, "Name" => name))
|
101
|
+
else
|
102
|
+
add_and_resubscribe_with_custom_fields(email, name, custom_fields)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Example
|
107
|
+
# @list = new List(12345)
|
108
|
+
# result = @list.remove_subscriber("ralph.wiggum@simpsons.net")
|
109
|
+
#
|
110
|
+
# if result.succeeded?
|
111
|
+
# puts "Deleted Subscriber"
|
112
|
+
# end
|
113
|
+
def remove_subscriber(email)
|
114
|
+
Result.new(cm_client.Subscriber_Unsubscribe("ListID" => self.id, "Email" => email))
|
115
|
+
end
|
116
|
+
|
117
|
+
# email The subscriber's email address.
|
118
|
+
# name The subscriber's name.
|
119
|
+
# custom_fields A hash of field name => value pairs.
|
120
|
+
def add_subscriber_with_custom_fields(email, name, custom_fields)
|
121
|
+
response = cm_client.using_soap do |driver|
|
122
|
+
driver.addSubscriberWithCustomFields \
|
123
|
+
:ApiKey => cm_client.api_key,
|
124
|
+
:ListID => self.id,
|
125
|
+
:Email => email,
|
126
|
+
:Name => name,
|
127
|
+
:CustomFields => { :SubscriberCustomField => custom_fields_array(custom_fields) }
|
128
|
+
end
|
129
|
+
|
130
|
+
response.subscriber_AddWithCustomFieldsResult
|
131
|
+
end
|
132
|
+
|
133
|
+
# email The subscriber's email address.
|
134
|
+
# name The subscriber's name.
|
135
|
+
# custom_fields A hash of field name => value pairs.
|
136
|
+
def add_and_resubscribe_with_custom_fields(email, name, custom_fields)
|
137
|
+
response = cm_client.using_soap do |driver|
|
138
|
+
driver.addAndResubscribeWithCustomFields \
|
139
|
+
:ApiKey => cm_client.api_key,
|
140
|
+
:ListID => self.id,
|
141
|
+
:Email => email,
|
142
|
+
:Name => name,
|
143
|
+
:CustomFields => { :SubscriberCustomField => custom_fields_array(custom_fields) }
|
144
|
+
end
|
145
|
+
|
146
|
+
response.subscriber_AddAndResubscribeWithCustomFieldsResult
|
147
|
+
end
|
148
|
+
|
149
|
+
# Example
|
150
|
+
# current_date = DateTime.new
|
151
|
+
# @list = new List(12345)
|
152
|
+
# @subscribers = @list.active_subscribers(current_date)
|
153
|
+
#
|
154
|
+
# for subscriber in @subscribers
|
155
|
+
# puts subscriber.email
|
156
|
+
# end
|
157
|
+
def active_subscribers(date)
|
158
|
+
response = cm_client.Subscribers_GetActive('ListID' => self.id, 'Date' => formatted_timestamp(date))
|
159
|
+
handle_response(response) do
|
160
|
+
response['Subscriber'].collect{|s| Subscriber.new(s['EmailAddress'], s['Name'], s['Date'])}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Example
|
165
|
+
# current_date = DateTime.new
|
166
|
+
# @list = new List(12345)
|
167
|
+
# @subscribers = @list.unsubscribed(current_date)
|
168
|
+
#
|
169
|
+
# for subscriber in @subscribers
|
170
|
+
# puts subscriber.email
|
171
|
+
# end
|
172
|
+
def unsubscribed(date)
|
173
|
+
date = formatted_timestamp(date) unless date.is_a?(String)
|
174
|
+
|
175
|
+
response = cm_client.Subscribers_GetUnsubscribed('ListID' => self.id, 'Date' => date)
|
176
|
+
|
177
|
+
handle_response(response) do
|
178
|
+
response['Subscriber'].collect{|s| Subscriber.new(s['EmailAddress'], s['Name'], s['Date'])}
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Example
|
183
|
+
# current_date = DateTime.new
|
184
|
+
# @list = new List(12345)
|
185
|
+
# @subscribers = @list.bounced(current_date)
|
186
|
+
#
|
187
|
+
# for subscriber in @subscribers
|
188
|
+
# puts subscriber.email
|
189
|
+
# end
|
190
|
+
def bounced(date)
|
191
|
+
response = cm_client.Subscribers_GetBounced('ListID' => self.id, 'Date' => formatted_timestamp(date))
|
192
|
+
|
193
|
+
handle_response(response) do
|
194
|
+
response["Subscriber"].collect{|s| Subscriber.new(s["EmailAddress"], s["Name"], s["Date"])}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
protected
|
200
|
+
|
201
|
+
# Converts hash of custom field name/values to array of hashes for the SOAP API.
|
202
|
+
def custom_fields_array(custom_fields)
|
203
|
+
arr = []
|
204
|
+
custom_fields.each do |key, value|
|
205
|
+
arr << { "Key" => key, "Value" => value }
|
206
|
+
end
|
207
|
+
arr
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class CampaignMonitor
|
2
|
+
|
3
|
+
# Encapsulates
|
4
|
+
class SubscriberBounce #:nodoc:
|
5
|
+
attr_reader :email_address, :bounce_type, :list_id
|
6
|
+
|
7
|
+
def initialize(email_address, list_id, bounce_type)
|
8
|
+
@email_address = email_address
|
9
|
+
@bounce_type = bounce_type
|
10
|
+
@list_id = list_id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Encapsulates
|
15
|
+
class SubscriberOpen #:nodoc:
|
16
|
+
attr_reader :email_address, :list_id, :opens
|
17
|
+
|
18
|
+
def initialize(email_address, list_id, opens)
|
19
|
+
@email_address = email_address
|
20
|
+
@list_id = list_id
|
21
|
+
@opens = opens
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Encapsulates
|
26
|
+
class SubscriberClick #:nodoc:
|
27
|
+
attr_reader :email_address, :list_id, :clicked_links
|
28
|
+
|
29
|
+
def initialize(email_address, list_id, clicked_links)
|
30
|
+
@email_address = email_address
|
31
|
+
@list_id = list_id
|
32
|
+
@clicked_links = clicked_links
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Encapsulates
|
37
|
+
class SubscriberUnsubscribe #:nodoc:
|
38
|
+
attr_reader :email_address, :list_id
|
39
|
+
|
40
|
+
def initialize(email_address, list_id)
|
41
|
+
@email_address = email_address
|
42
|
+
@list_id = list_id
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class CampaignMonitor
|
2
|
+
# Encapsulates the response received from the CampaignMonitor webservice.
|
3
|
+
class Result
|
4
|
+
attr_reader :message, :code, :raw
|
5
|
+
|
6
|
+
def initialize(response)
|
7
|
+
@message = response["Message"]
|
8
|
+
@code = response["Code"].to_i
|
9
|
+
@raw = response
|
10
|
+
end
|
11
|
+
|
12
|
+
def success?
|
13
|
+
code == 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def failed?
|
17
|
+
not success?
|
18
|
+
end
|
19
|
+
|
20
|
+
def content
|
21
|
+
# if we're a string (likely from SOAP)
|
22
|
+
return raw if raw.is_a?(String)
|
23
|
+
# if we're a hash
|
24
|
+
raw["__content__"]
|
25
|
+
end
|
26
|
+
|
27
|
+
alias :succeeded? :success?
|
28
|
+
alias :failure? :failed?
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class CampaignMonitor
|
2
|
+
# Provides the ability to add/remove subscribers from a list
|
3
|
+
class Subscriber < Base
|
4
|
+
include CampaignMonitor::Helpers
|
5
|
+
|
6
|
+
attr_accessor :email_address, :name, :date_subscribed
|
7
|
+
|
8
|
+
def initialize(email_address, name=nil, date=nil)
|
9
|
+
@email_address = email_address
|
10
|
+
@name = name
|
11
|
+
@date_subscribed = date_subscribed
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
# Example
|
16
|
+
# @subscriber = Subscriber.new("ralph.wiggum@simpsons.net")
|
17
|
+
# @subscriber.add(12345)
|
18
|
+
def add(list_id)
|
19
|
+
Result.new(cm_client.Subscriber_Add("ListID" => list_id, "Email" => @email_address, "Name" => @name))
|
20
|
+
end
|
21
|
+
|
22
|
+
# Example
|
23
|
+
# @subscriber = Subscriber.new("ralph.wiggum@simpsons.net")
|
24
|
+
# @subscriber.add_and_resubscribe(12345)
|
25
|
+
def add_and_resubscribe(list_id)
|
26
|
+
Result.new(cm_client.Subscriber_AddAndResubscribe("ListID" => list_id, "Email" => @email_address, "Name" => @name))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Example
|
30
|
+
# @subscriber = Subscriber.new("ralph.wiggum@simpsons.net")
|
31
|
+
# @subscriber.unsubscribe(12345)
|
32
|
+
def unsubscribe(list_id)
|
33
|
+
Result.new(cm_client.Subscriber_Unsubscribe("ListID" => list_id, "Email" => @email_address))
|
34
|
+
end
|
35
|
+
|
36
|
+
def is_subscribed?(list_id)
|
37
|
+
result = cm_client.Subscribers_GetIsSubscribed("ListID" => list_id, "Email" => @email_address)
|
38
|
+
return true if result == 'True'
|
39
|
+
return false if result == 'False'
|
40
|
+
raise "Invalid value for is_subscribed?: #{result}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'cgi'
|
3
|
+
require 'net/http'
|
4
|
+
require 'xmlsimple'
|
5
|
+
require 'date'
|
6
|
+
gem 'soap4r'
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), '../support/class_enhancements.rb')
|
9
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/helpers.rb')
|
10
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/misc.rb')
|
11
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/base.rb')
|
12
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/client.rb')
|
13
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/list.rb')
|
14
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/subscriber.rb')
|
15
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/result.rb')
|
16
|
+
require File.join(File.dirname(__FILE__), 'campaign_monitor/campaign.rb')
|
17
|
+
|
18
|
+
# A wrapper class to access the Campaign Monitor API. Written using the wonderful
|
19
|
+
# Flickr interface by Scott Raymond as a guide on how to access remote web services
|
20
|
+
#
|
21
|
+
# For more information on the Campaign Monitor API, visit http://campaignmonitor.com/api
|
22
|
+
#
|
23
|
+
# Author:: Jordan Brock <jordan@spintech.com.au>
|
24
|
+
# Copyright:: Copyright (c) 2006 Jordan Brock <jordan@spintech.com.au>
|
25
|
+
# License:: MIT <http://www.opensource.org/licenses/mit-license.php>
|
26
|
+
#
|
27
|
+
# USAGE:
|
28
|
+
# require 'campaign_monitor'
|
29
|
+
# cm = CampaignMonitor.new(API_KEY) # creates a CampaignMonitor object
|
30
|
+
# # Can set CAMPAIGN_MONITOR_API_KEY in environment.rb
|
31
|
+
# cm.clients # Returns an array of clients associated with
|
32
|
+
# # the user account
|
33
|
+
# cm.campaigns(client_id)
|
34
|
+
# cm.lists(client_id)
|
35
|
+
# cm.add_subscriber(list_id, email, name)
|
36
|
+
#
|
37
|
+
# == CLIENT
|
38
|
+
# client = Client[client_id] # find an existing client
|
39
|
+
# client = Client.new(attributes)
|
40
|
+
# client.Create
|
41
|
+
# client.Delete
|
42
|
+
# client.GetDetail
|
43
|
+
# client.UpdateAccessAndBilling
|
44
|
+
# client.UpdateBasics
|
45
|
+
# client.update # update basics, access, and billing
|
46
|
+
# client.lists # OR
|
47
|
+
# client.GetLists
|
48
|
+
# client.lists.build # to create a new unsaved list for a client
|
49
|
+
# client.campaigns # OR
|
50
|
+
# client.GetCampaigns
|
51
|
+
#
|
52
|
+
# == LIST
|
53
|
+
# list = List[list_id] # find an existing list
|
54
|
+
# list = List.new(attributes)
|
55
|
+
# list.Create
|
56
|
+
# list.Delete
|
57
|
+
# list.Update
|
58
|
+
# list.add_subscriber(email, name)
|
59
|
+
# list.remove_subscriber(email)
|
60
|
+
# list.active_subscribers(date)
|
61
|
+
# list.unsubscribed(date)
|
62
|
+
# list.bounced(date)
|
63
|
+
#
|
64
|
+
# == CAMPAIGN
|
65
|
+
# campaign = Campaign.new(campaign_id)
|
66
|
+
# campaign.clicks
|
67
|
+
# campaign.opens
|
68
|
+
# campaign.bounces
|
69
|
+
# campaign.unsubscribes
|
70
|
+
# campaign.number_recipients
|
71
|
+
# campaign.number_clicks
|
72
|
+
# campaign.number_opens
|
73
|
+
# campaign.number_bounces
|
74
|
+
# campaign.number_unsubscribes
|
75
|
+
#
|
76
|
+
#
|
77
|
+
# == SUBSCRIBER
|
78
|
+
# subscriber = Subscriber.new(email)
|
79
|
+
# subscriber.add(list_id)
|
80
|
+
# subscriber.unsubscribe(list_id)
|
81
|
+
#
|
82
|
+
# == Data Types
|
83
|
+
# SubscriberBounce
|
84
|
+
# SubscriberClick
|
85
|
+
# SubscriberOpen
|
86
|
+
# SubscriberUnsubscribe
|
87
|
+
# Result
|
88
|
+
#
|
89
|
+
class CampaignMonitor
|
90
|
+
include CampaignMonitor::Helpers
|
91
|
+
|
92
|
+
class InvalidAPIKey < StandardError
|
93
|
+
end
|
94
|
+
|
95
|
+
class ApiError < StandardError
|
96
|
+
end
|
97
|
+
|
98
|
+
attr_reader :api_key, :api_url
|
99
|
+
|
100
|
+
# Replace this API key with your own (http://www.campaignmonitor.com/api/)
|
101
|
+
def initialize(api_key=CAMPAIGN_MONITOR_API_KEY)
|
102
|
+
@api_key = api_key
|
103
|
+
@api_url = 'http://api.createsend.com/api/api.asmx'
|
104
|
+
CampaignMonitor::Base.client=self
|
105
|
+
end
|
106
|
+
|
107
|
+
# Takes a CampaignMonitor API method name and set of parameters;
|
108
|
+
# returns an XmlSimple object with the response
|
109
|
+
def request(method, params)
|
110
|
+
request_xml=http_get(request_url(method, params))
|
111
|
+
begin
|
112
|
+
response = PARSER.xml_in(request_xml, { 'keeproot' => false,
|
113
|
+
'forcearray' => %w[List Campaign Subscriber Client SubscriberOpen SubscriberUnsubscribe SubscriberClick SubscriberBounce],
|
114
|
+
'noattr' => true })
|
115
|
+
response.delete('d1p1:type')
|
116
|
+
response.delete("d1p1:http://www.w3.org/2001/XMLSchema-instance:type")
|
117
|
+
response
|
118
|
+
# rescue XML::Parser::ParseError
|
119
|
+
rescue XML::Error
|
120
|
+
{ "Code" => 500, "Message" => request_xml.split(/\r?\n/).first, "FullError" => request_xml }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Takes a CampaignMonitor API method name and set of parameters; returns the correct URL for the REST API.
|
125
|
+
def request_url(method, params={})
|
126
|
+
params.merge!('ApiKey' => api_key)
|
127
|
+
|
128
|
+
query = params.collect do |key, value|
|
129
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
|
130
|
+
end.sort * '&'
|
131
|
+
|
132
|
+
"#{api_url}/#{method}?#{query}"
|
133
|
+
end
|
134
|
+
|
135
|
+
# Does an HTTP GET on a given URL and returns the response body
|
136
|
+
def http_get(url)
|
137
|
+
response=Net::HTTP.get_response(URI.parse(url))
|
138
|
+
response.body.to_s
|
139
|
+
end
|
140
|
+
|
141
|
+
# By overriding the method_missing method, it is possible to easily support all of the methods
|
142
|
+
# available in the API
|
143
|
+
def method_missing(method_id, params = {})
|
144
|
+
puts " CM: #{method_id} (#{params.inspect})" if $debug
|
145
|
+
res=request(method_id.id2name.gsub(/_/, '.'), params)
|
146
|
+
puts " returning: #{res.inspect}" if $debug
|
147
|
+
res
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns an array of Client objects associated with the API Key
|
151
|
+
#
|
152
|
+
# Example
|
153
|
+
# @cm = CampaignMonitor.new()
|
154
|
+
# @clients = @cm.clients
|
155
|
+
#
|
156
|
+
# for client in @clients
|
157
|
+
# puts client.name
|
158
|
+
# end
|
159
|
+
def clients
|
160
|
+
handle_response(User_GetClients()) do |response|
|
161
|
+
response["Client"].collect{|c| Client.new({"ClientID" => c["ClientID"], "CompanyName" => c["Name"]})}
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def new_client
|
166
|
+
Client.new(nil)
|
167
|
+
end
|
168
|
+
|
169
|
+
def system_date
|
170
|
+
User_GetSystemDate()
|
171
|
+
end
|
172
|
+
|
173
|
+
def parsed_system_date
|
174
|
+
DateTime.strptime(system_date, timestamp_format)
|
175
|
+
end
|
176
|
+
|
177
|
+
def countries
|
178
|
+
handle_response(User_GetCountries()) do | response |
|
179
|
+
response["string"]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def timezones
|
184
|
+
handle_response(User_GetTimezones()) do | response |
|
185
|
+
response["string"]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Returns an array of Campaign objects associated with the specified Client ID
|
190
|
+
#
|
191
|
+
# Example
|
192
|
+
# @cm = CampaignMonitor.new()
|
193
|
+
# @campaigns = @cm.campaigns(12345)
|
194
|
+
#
|
195
|
+
# for campaign in @campaigns
|
196
|
+
# puts campaign.subject
|
197
|
+
# end
|
198
|
+
def campaigns(client_id)
|
199
|
+
handle_response(Client_GetCampaigns("ClientID" => client_id)) do |response|
|
200
|
+
response["Campaign"].collect{|c| Campaign.new(c) }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns an array of Subscriber Lists for the specified Client ID
|
205
|
+
#
|
206
|
+
# Example
|
207
|
+
# @cm = CampaignMonitor.new()
|
208
|
+
# @lists = @cm.lists(12345)
|
209
|
+
#
|
210
|
+
# for list in @lists
|
211
|
+
# puts list.name
|
212
|
+
# end
|
213
|
+
def lists(client_id)
|
214
|
+
handle_response(Client_GetLists("ClientID" => client_id)) do |response|
|
215
|
+
response["List"].collect{|l| List.new({"ListID" => l["ListID"], "Title" => l["Name"]})}
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# A quick method of adding a subscriber to a list. Returns a Result object
|
220
|
+
#
|
221
|
+
# Example
|
222
|
+
# @cm = CampaignMonitor.new()
|
223
|
+
# result = @cm.add_subscriber(12345, "ralph.wiggum@simpsons.net", "Ralph Wiggum")
|
224
|
+
#
|
225
|
+
# if result.succeeded?
|
226
|
+
# puts "Subscriber Added to List"
|
227
|
+
# end
|
228
|
+
def add_subscriber(list_id, email, name)
|
229
|
+
Result.new(Subscriber_Add("ListID" => list_id, "Email" => email, "Name" => name))
|
230
|
+
end
|
231
|
+
|
232
|
+
def using_soap
|
233
|
+
driver = wsdl_driver_factory.create_rpc_driver
|
234
|
+
driver.wiredump_dev = STDERR if $debug
|
235
|
+
response = yield(driver)
|
236
|
+
driver.reset_stream
|
237
|
+
|
238
|
+
response
|
239
|
+
end
|
240
|
+
|
241
|
+
protected
|
242
|
+
|
243
|
+
def wsdl_driver_factory
|
244
|
+
SOAP::WSDLDriverFactory.new("#{api_url}?WSDL")
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
# If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
|
250
|
+
# except it uses the xml/libxml library for xml parsing (rather than REXML).
|
251
|
+
# If libxml isn't installed, we just fall back on XmlSimple.
|
252
|
+
|
253
|
+
PARSER =
|
254
|
+
begin
|
255
|
+
require 'xml/libxml'
|
256
|
+
# Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
|
257
|
+
# have to use a version greater than '0.3.8.2'.
|
258
|
+
raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
|
259
|
+
$:.push(File.join(File.dirname(__FILE__), '..', 'support', 'faster-xml-simple', 'lib'))
|
260
|
+
require 'faster_xml_simple'
|
261
|
+
p 'Using libxml-ruby'
|
262
|
+
FasterXmlSimple
|
263
|
+
rescue LoadError
|
264
|
+
begin
|
265
|
+
require 'rexml-expansion-fix'
|
266
|
+
rescue LoadError => e
|
267
|
+
p 'Cannot load rexml security patch'
|
268
|
+
end
|
269
|
+
XmlSimple
|
270
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ClassEnhancements
|
2
|
+
|
3
|
+
def inherited_property(accessor, default = nil)
|
4
|
+
instance_eval <<-RUBY, __FILE__, __LINE__ + 1
|
5
|
+
@#{accessor} = default
|
6
|
+
|
7
|
+
def set_#{accessor}(value)
|
8
|
+
@#{accessor} = value
|
9
|
+
end
|
10
|
+
alias #{accessor} set_#{accessor}
|
11
|
+
|
12
|
+
def get_#{accessor}
|
13
|
+
return @#{accessor} if instance_variable_defined?(:@#{accessor})
|
14
|
+
superclass.send(:get_#{accessor})
|
15
|
+
end
|
16
|
+
RUBY
|
17
|
+
|
18
|
+
# @path = default
|
19
|
+
#
|
20
|
+
# def set_path(value)
|
21
|
+
# @path = value
|
22
|
+
# end
|
23
|
+
# alias_method path, set_path
|
24
|
+
|
25
|
+
# def get_path
|
26
|
+
# return @path if instance_variable_defined?(:path)
|
27
|
+
# superclass.send(:path)
|
28
|
+
# end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Class #:nodoc:
|
34
|
+
include ClassEnhancements
|
35
|
+
end
|