Skip to content
This repository has been archived by the owner on Aug 9, 2022. It is now read-only.

Commit

Permalink
support for creating campaigns
Browse files Browse the repository at this point in the history
  • Loading branch information
joshgoebel committed Feb 26, 2009
1 parent ce09a4a commit e32f9b4
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 44 deletions.
3 changes: 2 additions & 1 deletion campaign_monitor.gemspec
@@ -1,7 +1,7 @@
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = 'campaign_monitor'
s.version = "1.3.0"
s.version = "1.3.2"
s.summary = 'Provides access to the Campaign Monitor API.'
s.description = <<-EOF
A simple wrapper class that provides basic access to the Campaign Monitor API.
Expand All @@ -15,6 +15,7 @@ Gem::Specification.new do |s|
s.require_path = 'lib'

s.add_dependency 'xml-simple', ['>= 1.0.11']
s.add_dependency 'soapr4', ['>= 1.5.8']

s.files = [
'campaign_monitor.gemspec',
Expand Down
5 changes: 4 additions & 1 deletion lib/campaign_monitor.rb
Expand Up @@ -3,6 +3,7 @@
require 'net/http'
require 'xmlsimple'
require 'date'
gem 'soap4r'

require File.join(File.dirname(__FILE__), '../support/class_enhancements.rb')
require File.join(File.dirname(__FILE__), 'campaign_monitor/helpers.rb')
Expand Down Expand Up @@ -110,7 +111,8 @@ def request(method, params)
response.delete('d1p1:type')
response.delete("d1p1:http://www.w3.org/2001/XMLSchema-instance:type")
response
rescue XML::Parser::ParseError
# rescue XML::Parser::ParseError
rescue XML::Error
{ "Code" => 500, "Message" => request_xml.split(/\r?\n/).first, "FullError" => request_xml }
end
end
Expand Down Expand Up @@ -225,6 +227,7 @@ def add_subscriber(list_id, email, name)

def using_soap
driver = wsdl_driver_factory.create_rpc_driver
driver.wiredump_dev = STDERR if $debug
response = yield(driver)
driver.reset_stream

Expand Down
95 changes: 53 additions & 42 deletions lib/campaign_monitor/campaign.rb
Expand Up @@ -33,6 +33,9 @@ class Campaign < Base
id_field "CampaignID"
name_field "Subject"

class MissingParameter < StandardError
end

# attr_reader :id, :subject, :sent_date, :total_recipients, :cm_client

data_types "TotalRecipients" => "to_i"
Expand All @@ -44,6 +47,35 @@ def initialize(attrs={})
@attributes=attrs
end

def Create
required_params=%w{CampaignName CampaignSubject FromName FromEmail ReplyTo HtmlUrl TextUrl}
required_params.each do |f|
raise MissingParameter, "'#{f}' is required to call Create" unless self[f]
end
response = cm_client.using_soap do |driver|
opts=attributes.merge(:ApiKey => cm_client.api_key, :SubscriberListIDs => @lists.map {|x| x.id})
driver.createCampaign opts
end
@result=Result.new(response["Campaign.CreateResult"])
self.id=@result.content if @result.success?
@result.success?
end

def Send(options={})
required_params=%w{ConfirmationEmail SendDate}
required_params.each do |f|
raise MissingParameter, "'#{f}' is required to call Send" unless options[f]
end
options.merge!("CampaignID" => self.id)
@result=Result.new(@cm_client.Campaign_Send(options))
@result.success?
end

def add_list(list)
@lists||=[]
@lists << list
end

# Example
# @campaign = Campaign.new(12345)
# @subscriber_opens = @campaign.opens
Expand Down Expand Up @@ -102,56 +134,35 @@ def GetUnsubscribes

def GetSummary
@result=Result.new(cm_client.Campaign_GetSummary('CampaignID' => self.id))
@summary=@result.raw if @result.success?
@summary=parse_summary(@result.raw) if @result.success?
@result.success?
end

# Example
# @campaign = Campaign.new(12345)
# puts @campaign.number_recipients
def number_recipients
@number_recipients ||= summary[:number_recipients]
end

# Example
# @campaign = Campaign.new(12345)
# puts @campaign.number_opened
def number_opened
@number_opened ||= summary[:number_opened]
end

# Example
# @campaign = Campaign.new(12345)
# puts @campaign.number_clicks
def number_clicks
@number_clicks ||= summary[:number_clicks]
end

# Example
# @campaign = Campaign.new(12345)
# puts @campaign.number_unsubscribed
def number_unsubscribed
@number_unsubscribed ||= summary[:number_unsubscribed]
# hook up the old API calls
def method_missing(m, *args)
if %w{number_bounced number_unsubscribed number_clicks number_opened number_recipients}.include?(m.to_s)
summary[m]
else
super
end
end

# Example
# @campaign = Campaign.new(12345)
# puts @campaign.number_bounced
def number_bounced
@number_bounced ||= summary[:number_bounced]
def summary(refresh=false)
self.GetSummary if refresh or @summary.nil?
@summary
end

private
def summary
if @summary.nil?
summary = cm_client.Campaign_GetSummary('CampaignID' => self.id)
@summary = {
:number_recipients => summary['Recipients'].to_i,
:number_opened => summary['TotalOpened'].to_i,
:number_clicks => summary['Click'].to_i,
:number_unsubscribed => summary['Unsubscribed'].to_i,
:number_bounced => summary['Bounced'].to_i
}
def parse_summary(summary)
@summary = {
:number_recipients => summary['Recipients'].to_i,
:number_opened => summary['TotalOpened'].to_i,
:number_clicks => summary['Clicks'].to_i,
:number_unsubscribed => summary['Unsubscribed'].to_i,
:number_bounced => summary['Bounced'].to_i
}
summary.each do |key, value|
@summary[key]=value.to_i
end
@summary
end
Expand Down
4 changes: 4 additions & 0 deletions lib/campaign_monitor/client.rb
Expand Up @@ -96,6 +96,10 @@ def GetCampaigns

alias campaigns GetCampaigns

def new_campaign(attrs={})
Campaign.new(attrs.merge("ClientID" => self.id))
end


# Calls Client.GetDetails to load a specific client
# Client#result will have the result of the API call
Expand Down
3 changes: 3 additions & 0 deletions lib/campaign_monitor/result.rb
Expand Up @@ -18,6 +18,9 @@ def failed?
end

def content
# if we're a string (likely from SOAP)
return raw if raw.is_a?(String)
# if we're a hash
raw["__content__"]
end

Expand Down
98 changes: 98 additions & 0 deletions test/campaign_test.rb
@@ -0,0 +1,98 @@
require 'rubygems'
require 'lib/campaign_monitor'
require 'test/unit'
require 'test/test_helper'

CLIENT_NAME = 'Spacely Space Sprockets'
CLIENT_CONTACT_NAME = 'George Jetson'
LIST_NAME = 'List #1'

class CampaignMonitorTest < Test::Unit::TestCase

def setup
@cm = CampaignMonitor.new(ENV["API_KEY"])
# find an existing client and make sure we know it's values
@client=find_test_client(@cm.clients)
assert_not_nil @client, "Please create a '#{CLIENT_NAME}' (company name) client so tests can run."

# delete all existing lists
@client.lists.each { |l| l.Delete }
@list = @client.lists.build.defaults
end


def teardown
end

def test_finds_named_campaign
@campaign=@client.campaigns.detect { |x| x["Subject"] == "Big Deal" }
assert_not_nil @campaign
assert_equal 1, @campaign["TotalRecipients"]
end

def test_summary_interface
@campaign=@client.campaigns.detect { |x| x["Subject"] == "Big Deal" }
assert_not_nil @campaign
# old
assert_equal 1, @campaign.number_recipients
assert_equal 0, @campaign.number_opened
assert_equal 0, @campaign.number_clicks
assert_equal 0, @campaign.number_unsubscribed
assert_equal 0, @campaign.number_bounced
# new
assert_equal 1, @campaign.summary["Recipients"]
assert_equal 0, @campaign.summary["TotalOpened"]
assert_equal 0, @campaign.summary["Clicks"]
assert_equal 0, @campaign.summary["Unsubscribed"]
assert_equal 0, @campaign.summary["Bounced"]
end

def test_creating_a_campaign
return
@campaign=@client.new_campaign
# create two lists
@beef=@client.lists.build.defaults
@beef["Title"]="Beef"
@beef.Create
assert_success @beef.result
@chicken=@client.lists.build.defaults
@chicken["Title"]="Chicken"
@chicken.Create
assert_success @chicken.result

@campaign.add_list @beef
@campaign.add_list @chicken
@campaign["CampaignName"]="Noodles #{secure_digest(Time.now.to_s)}"
@campaign["CampaignSubject"]="Noodly #{secure_digest(Time.now.to_s)}"
puts @campaign.inspect
@campaign["FromName"] = "George Bush"
@campaign["FromEmail"] = "george@aol.com"
@campaign["ReplyTo"] = "george@aol.com"
@campaign["HtmlUrl"] = "http://www.google.com/robots.txt"
@campaign["TextUrl"] = "http://www.google.com/robots.txt"
@campaign.Create
puts @campaign.result.inspect
assert_success @campaign.result
assert_not_nil @campaign.id
assert_equal 32, @campaign.id.length
# test sending
@campaign.Send("ConfirmationEmail" => "george@aol.com", "SendDate" => "Immediately")
assert_success @campaign.result

end

def test_GetSummary
@campaign=@client.campaigns.detect { |x| x["Subject"] == "Big Deal" }
assert_not_nil @campaign
@campaign.GetSummary
assert @campaign.result.success?
end


protected

def find_test_client(clients)
clients.detect { |c| c.name == CLIENT_NAME }
end

end
11 changes: 11 additions & 0 deletions test/test_helper.rb
@@ -1,3 +1,6 @@
require 'ruby-debug'
require 'digest'

CAMPAIGN_MONITOR_API_KEY=nil

if ENV["API_KEY"].nil?
Expand All @@ -13,4 +16,12 @@ def assert_not_empty(v)
assert !v.strip.empty?, "expected to not be empty" if v.is_a?(String)
end

def assert_success(result)
assert result.succeeded?, "#{result.code}: #{result.message}"
end

def secure_digest(*args)
Digest::SHA1.hexdigest(args.flatten.join('--'))
end

end

0 comments on commit e32f9b4

Please sign in to comment.