createsend 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/Gemfile +3 -0
- data/README.md +3 -0
- data/Rakefile +23 -0
- data/config.example.yaml +2 -0
- data/createsend.gemspec +26 -0
- data/lib/campaign.rb +90 -0
- data/lib/client.rb +117 -0
- data/lib/createsend.rb +103 -0
- data/lib/list.rb +99 -0
- data/lib/subscriber.rb +49 -0
- data/lib/template.rb +38 -0
- data/test/campaign_test.rb +98 -0
- data/test/client_test.rb +107 -0
- data/test/createsend_test.rb +96 -0
- data/test/fixtures/active_subscribers.json +67 -0
- data/test/fixtures/add_subscriber.json +1 -0
- data/test/fixtures/apikey.json +3 -0
- data/test/fixtures/bounced_subscribers.json +9 -0
- data/test/fixtures/campaign_bounces.json +16 -0
- data/test/fixtures/campaign_clicks.json +23 -0
- data/test/fixtures/campaign_lists.json +10 -0
- data/test/fixtures/campaign_opens.json +32 -0
- data/test/fixtures/campaign_summary.json +9 -0
- data/test/fixtures/campaign_unsubscribes.json +9 -0
- data/test/fixtures/campaigns.json +18 -0
- data/test/fixtures/client_details.json +25 -0
- data/test/fixtures/clients.json +10 -0
- data/test/fixtures/countries.json +247 -0
- data/test/fixtures/create_campaign.json +1 -0
- data/test/fixtures/create_client.json +1 -0
- data/test/fixtures/create_custom_field.json +1 -0
- data/test/fixtures/create_list.json +1 -0
- data/test/fixtures/create_template.json +1 -0
- data/test/fixtures/custom_api_error.json +4 -0
- data/test/fixtures/custom_fields.json +20 -0
- data/test/fixtures/drafts.json +14 -0
- data/test/fixtures/import_subscribers.json +7 -0
- data/test/fixtures/list_details.json +7 -0
- data/test/fixtures/list_stats.json +26 -0
- data/test/fixtures/lists.json +10 -0
- data/test/fixtures/segments.json +10 -0
- data/test/fixtures/subscriber_details.json +20 -0
- data/test/fixtures/subscriber_history.json +45 -0
- data/test/fixtures/suppressionlist.json +12 -0
- data/test/fixtures/systemdate.json +3 -0
- data/test/fixtures/template_details.json +6 -0
- data/test/fixtures/templates.json +14 -0
- data/test/fixtures/timezones.json +99 -0
- data/test/fixtures/unsubscribed_subscribers.json +21 -0
- data/test/helper.rb +36 -0
- data/test/list_test.rb +107 -0
- data/test/subscriber_test.rb +73 -0
- data/test/template_test.rb +38 -0
- metadata +256 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
require "bundler/version"
|
3
|
+
require "shoulda/tasks"
|
4
|
+
require 'lib/createsend'
|
5
|
+
|
6
|
+
require "rake/testtask"
|
7
|
+
Rake::TestTask.new(:test) do |test|
|
8
|
+
test.ruby_opts = ["-rubygems"] if defined? Gem
|
9
|
+
test.libs << "lib" << "test"
|
10
|
+
test.pattern = "test/**/*_test.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Build the gem"
|
14
|
+
task :build do
|
15
|
+
system "gem build createsend.gemspec"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Build and release the gem"
|
19
|
+
task :release => :build do
|
20
|
+
system "gem push createsend-#{CreateSend::VER}.gem"
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default => :test
|
data/config.example.yaml
ADDED
data/createsend.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'bundler/version'
|
3
|
+
|
4
|
+
require File.expand_path('lib/createsend')
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.add_development_dependency('fakeweb', '~> 1.3')
|
8
|
+
s.add_development_dependency('jnunemaker-matchy', '~> 0.4.0')
|
9
|
+
s.add_development_dependency('mocha', '~> 0.9')
|
10
|
+
s.add_development_dependency('shoulda', '~> 2.11')
|
11
|
+
s.add_runtime_dependency('hashie', '~> 0.4.0')
|
12
|
+
s.add_runtime_dependency('httparty', '~> 0.6.1')
|
13
|
+
s.name = "createsend"
|
14
|
+
s.author = "James Dennes"
|
15
|
+
s.description = %q{A wrapper for the CreateSend API v3}
|
16
|
+
s.email = ["jdennes@gmail.com"]
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.homepage = "http://github.com/campaignmonitor/createsend-ruby/"
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.summary = %q{Wrapper for the CreateSend API v3}
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.version = CreateSend::VER
|
24
|
+
s.platform = Gem::Platform::RUBY
|
25
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if s.respond_to? :required_rubygems_version=
|
26
|
+
end
|
data/lib/campaign.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'createsend'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Campaign
|
5
|
+
attr_reader :campaign_id
|
6
|
+
|
7
|
+
def initialize(campaign_id)
|
8
|
+
@campaign_id = campaign_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.create(client_id, subject, name, from_name, from_email, reply_to, html_url,
|
12
|
+
text_url, list_ids, segments)
|
13
|
+
options = { :body => {
|
14
|
+
:Subject => subject,
|
15
|
+
:Name => name,
|
16
|
+
:FromName => from_name,
|
17
|
+
:FromEmail => from_email,
|
18
|
+
:ReplyTo => reply_to,
|
19
|
+
:HtmlUrl => html_url,
|
20
|
+
:TextUrl => text_url,
|
21
|
+
:ListIDs => list_ids ,
|
22
|
+
:Segments => segments }.to_json }
|
23
|
+
response = CreateSend.post "/campaigns/#{client_id}.json", options
|
24
|
+
response.parsed_response
|
25
|
+
end
|
26
|
+
|
27
|
+
def send(confirmation_email, send_date="immediately")
|
28
|
+
options = { :body => {
|
29
|
+
:ConfirmationEmail => confirmation_email,
|
30
|
+
:SendDate => send_date }.to_json }
|
31
|
+
response = post "send", options
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete
|
35
|
+
response = CreateSend.delete "/campaigns/#{campaign_id}.json", {}
|
36
|
+
end
|
37
|
+
|
38
|
+
def summary
|
39
|
+
response = get "summary", {}
|
40
|
+
Hashie::Mash.new(response)
|
41
|
+
end
|
42
|
+
|
43
|
+
def lists
|
44
|
+
response = get "lists", {}
|
45
|
+
response.map{|item| Hashie::Mash.new(item)}
|
46
|
+
end
|
47
|
+
|
48
|
+
def segments
|
49
|
+
# TODO: This needs to be implemented
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
|
53
|
+
def opens(date)
|
54
|
+
options = { :query => { :date => date } }
|
55
|
+
response = get "opens", options
|
56
|
+
response.map{|item| Hashie::Mash.new(item)}
|
57
|
+
end
|
58
|
+
|
59
|
+
def clicks(date)
|
60
|
+
options = { :query => { :date => date } }
|
61
|
+
response = get "clicks", options
|
62
|
+
response.map{|item| Hashie::Mash.new(item)}
|
63
|
+
end
|
64
|
+
|
65
|
+
def unsubscribes(date)
|
66
|
+
options = { :query => { :date => date } }
|
67
|
+
response = get "unsubscribes", options
|
68
|
+
response.map{|item| Hashie::Mash.new(item)}
|
69
|
+
end
|
70
|
+
|
71
|
+
def bounces
|
72
|
+
response = get "bounces", {}
|
73
|
+
response.map{|item| Hashie::Mash.new(item)}
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def get(action, options = {})
|
79
|
+
CreateSend.get uri_for(action), options
|
80
|
+
end
|
81
|
+
|
82
|
+
def post(action, options = {})
|
83
|
+
CreateSend.post uri_for(action), options
|
84
|
+
end
|
85
|
+
|
86
|
+
def uri_for(action)
|
87
|
+
"/campaigns/#{campaign_id}/#{action}.json"
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/lib/client.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'createsend'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Client
|
5
|
+
attr_reader :client_id
|
6
|
+
|
7
|
+
def initialize(client_id)
|
8
|
+
@client_id = client_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.create(company, contact_name, email, timezone, country)
|
12
|
+
options = { :body => {
|
13
|
+
:CompanyName => company,
|
14
|
+
:ContactName => contact_name,
|
15
|
+
:EmailAddress => email,
|
16
|
+
:TimeZone => timezone,
|
17
|
+
:Country => country }.to_json }
|
18
|
+
CreateSend.post "/clients.json", options
|
19
|
+
end
|
20
|
+
|
21
|
+
def details
|
22
|
+
response = CreateSend.get "/clients/#{client_id}.json", {}
|
23
|
+
Hashie::Mash.new(response)
|
24
|
+
end
|
25
|
+
|
26
|
+
def campaigns
|
27
|
+
response = get 'campaigns'
|
28
|
+
response.map{|item| Hashie::Mash.new(item)}
|
29
|
+
end
|
30
|
+
|
31
|
+
def drafts
|
32
|
+
response = get 'drafts'
|
33
|
+
response.map{|item| Hashie::Mash.new(item)}
|
34
|
+
end
|
35
|
+
|
36
|
+
def lists
|
37
|
+
response = get 'lists'
|
38
|
+
response.map{|item| Hashie::Mash.new(item)}
|
39
|
+
end
|
40
|
+
|
41
|
+
def segments
|
42
|
+
response = get 'segments'
|
43
|
+
response.map{|item| Hashie::Mash.new(item)}
|
44
|
+
end
|
45
|
+
|
46
|
+
def suppressionlist
|
47
|
+
response = get 'suppressionlist'
|
48
|
+
response.map{|item| Hashie::Mash.new(item)}
|
49
|
+
end
|
50
|
+
|
51
|
+
def templates
|
52
|
+
response = get 'templates'
|
53
|
+
response.map{|item| Hashie::Mash.new(item)}
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_basics(company, contact_name, email, timezone, country)
|
57
|
+
options = { :body => {
|
58
|
+
:CompanyName => company,
|
59
|
+
:ContactName => contact_name,
|
60
|
+
:EmailAddress => email,
|
61
|
+
:TimeZone => timezone,
|
62
|
+
:Country => country }.to_json }
|
63
|
+
put 'setbasics', options
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_access(username, password, access_level)
|
67
|
+
options = { :body => {
|
68
|
+
:Username => username,
|
69
|
+
:Password => password,
|
70
|
+
:AccessLevel => access_level }.to_json }
|
71
|
+
put 'setaccess', options
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_payg_billing(currency, can_purchase_credits, client_pays, markup_percentage,
|
75
|
+
markup_on_delivery=0, markup_per_recipient=0, markup_on_design_spam_test=0)
|
76
|
+
options = { :body => {
|
77
|
+
:Currency => currency,
|
78
|
+
:CanPurchaseCredits => can_purchase_credits,
|
79
|
+
:ClientPays => client_pays,
|
80
|
+
:MarkupPercentage => markup_percentage,
|
81
|
+
:MarkupOnDelivery => markup_on_delivery,
|
82
|
+
:MarkupPerRecipient => markup_per_recipient,
|
83
|
+
:MarkupOnDesignSpamTest => markup_on_design_spam_test }.to_json }
|
84
|
+
put 'setpaygbilling', options
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_monthly_billing(currency, can_purchase_credits, client_pays, markup_percentage)
|
88
|
+
options = { :body => {
|
89
|
+
:Currency => currency,
|
90
|
+
:CanPurchaseCredits => can_purchase_credits,
|
91
|
+
:ClientPays => client_pays,
|
92
|
+
:MarkupPercentage => markup_percentage }.to_json }
|
93
|
+
put 'setmonthlybilling', options
|
94
|
+
end
|
95
|
+
|
96
|
+
def delete
|
97
|
+
CreateSend.delete "/clients/#{client_id}.json", {}
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def get(action, options = {})
|
103
|
+
CreateSend.get uri_for(action), options
|
104
|
+
end
|
105
|
+
|
106
|
+
def post(action, options = {})
|
107
|
+
CreateSend.post uri_for(action), options
|
108
|
+
end
|
109
|
+
|
110
|
+
def put(action, options = {})
|
111
|
+
CreateSend.put uri_for(action), options
|
112
|
+
end
|
113
|
+
|
114
|
+
def uri_for(action)
|
115
|
+
"/clients/#{client_id}/#{action}.json"
|
116
|
+
end
|
117
|
+
end
|
data/lib/createsend.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'uri'
|
3
|
+
require 'httparty'
|
4
|
+
require 'hashie'
|
5
|
+
Hash.send :include, Hashie::HashExtensions
|
6
|
+
|
7
|
+
CreateSendOptions = { 'api_key' => nil, 'base_uri' => "http://api.createsend.com/api/v3" } if not Object.const_defined? :CreateSendOptions # :nodoc:
|
8
|
+
if File.exists?('config.yaml')
|
9
|
+
config = YAML.load_file('config.yaml')
|
10
|
+
CreateSendOptions['base_uri'] = config['base_uri']
|
11
|
+
CreateSendOptions['api_key'] = config['api_key']
|
12
|
+
end
|
13
|
+
|
14
|
+
libdir = File.dirname(__FILE__)
|
15
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
16
|
+
|
17
|
+
require 'client'
|
18
|
+
require 'campaign'
|
19
|
+
require 'list'
|
20
|
+
require 'subscriber'
|
21
|
+
require 'template'
|
22
|
+
|
23
|
+
class CreateSendError < StandardError
|
24
|
+
attr_reader :data
|
25
|
+
def initialize(data)
|
26
|
+
@data = data
|
27
|
+
super "The CreateSend API responded with the following error - #{@data.Code}: #{@data.Message}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ClientError < StandardError; end
|
32
|
+
class ServerError < StandardError; end
|
33
|
+
class BadRequest < CreateSendError; end
|
34
|
+
class Unauthorized < ClientError; end
|
35
|
+
class NotFound < ClientError; end
|
36
|
+
class Unavailable < StandardError; end
|
37
|
+
|
38
|
+
class CreateSend
|
39
|
+
include HTTParty
|
40
|
+
headers 'Content-Type' => 'application/json'
|
41
|
+
base_uri CreateSendOptions['base_uri']
|
42
|
+
basic_auth CreateSendOptions['api_key'], 'x'
|
43
|
+
|
44
|
+
VER = "0.0.1" unless defined?(CreateSend::VER)
|
45
|
+
|
46
|
+
def self.api_key(api_key=nil)
|
47
|
+
return @@api_key unless api_key
|
48
|
+
CreateSendOptions['api_key'] = api_key
|
49
|
+
@@api_key = api_key
|
50
|
+
basic_auth @@api_key, 'x'
|
51
|
+
end
|
52
|
+
|
53
|
+
def apikey(site_url, username, password)
|
54
|
+
site_url = CGI.escape(site_url)
|
55
|
+
self.class.basic_auth username, password
|
56
|
+
response = CreateSend.get("/apikey.json?SiteUrl=#{site_url}")
|
57
|
+
# Revert basic_auth to use @@api_key, 'x'
|
58
|
+
self.class.basic_auth @@api_key, 'x'
|
59
|
+
Hashie::Mash.new(response)
|
60
|
+
end
|
61
|
+
|
62
|
+
def clients
|
63
|
+
response = CreateSend.get('/clients.json')
|
64
|
+
response.map{|item| Hashie::Mash.new(item)}
|
65
|
+
end
|
66
|
+
|
67
|
+
def countries
|
68
|
+
response = CreateSend.get('/countries.json')
|
69
|
+
response.parsed_response
|
70
|
+
end
|
71
|
+
|
72
|
+
def systemdate
|
73
|
+
response = CreateSend.get('/systemdate.json')
|
74
|
+
Hashie::Mash.new(response)
|
75
|
+
end
|
76
|
+
|
77
|
+
def timezones
|
78
|
+
response = CreateSend.get('/timezones.json')
|
79
|
+
response.parsed_response
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.get(*args); handle_response super end
|
83
|
+
def self.post(*args); handle_response super end
|
84
|
+
def self.put(*args); handle_response super end
|
85
|
+
def self.delete(*args); handle_response super end
|
86
|
+
|
87
|
+
def self.handle_response(response)
|
88
|
+
case response.code
|
89
|
+
when 400
|
90
|
+
raise BadRequest.new(Hashie::Mash.new response)
|
91
|
+
when 401
|
92
|
+
raise Unauthorized.new
|
93
|
+
when 404
|
94
|
+
raise NotFound.new
|
95
|
+
when 400...500
|
96
|
+
raise ClientError.new
|
97
|
+
when 500...600
|
98
|
+
raise ServerError.new
|
99
|
+
else
|
100
|
+
response
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/list.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'createsend'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class List
|
5
|
+
attr_reader :list_id
|
6
|
+
|
7
|
+
def initialize(list_id)
|
8
|
+
@list_id = list_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.create(client_id, title, unsubscribe_page, confirmed_opt_in, confirmation_success_page)
|
12
|
+
options = { :body => {
|
13
|
+
:Title => title,
|
14
|
+
:UnsubscribePage => unsubscribe_page,
|
15
|
+
:ConfirmedOptIn => confirmed_opt_in,
|
16
|
+
:ConfirmationSuccessPage => confirmation_success_page }.to_json }
|
17
|
+
response = CreateSend.post "/lists/#{client_id}.json", options
|
18
|
+
response.parsed_response
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete
|
22
|
+
response = CreateSend.delete "/lists/#{list_id}.json", {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_custom_field(field_name, data_type, options=[])
|
26
|
+
options = { :body => {
|
27
|
+
:FieldName => field_name,
|
28
|
+
:DataType => data_type,
|
29
|
+
:Options => options }.to_json }
|
30
|
+
response = post "customfields", options
|
31
|
+
response.parsed_response
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_custom_field(custom_field_key)
|
35
|
+
custom_field_key = CGI.escape(custom_field_key)
|
36
|
+
response = CreateSend.delete "/lists/#{list_id}/customfields/#{custom_field_key}.json", {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def details
|
40
|
+
response = CreateSend.get "/lists/#{list_id}.json", {}
|
41
|
+
Hashie::Mash.new(response)
|
42
|
+
end
|
43
|
+
|
44
|
+
def custom_fields
|
45
|
+
response = get "customfields"
|
46
|
+
response.map{|item| Hashie::Mash.new(item)}
|
47
|
+
end
|
48
|
+
|
49
|
+
def stats
|
50
|
+
response = get "stats"
|
51
|
+
Hashie::Mash.new(response)
|
52
|
+
end
|
53
|
+
|
54
|
+
def active(date)
|
55
|
+
options = { :query => { :date => date } }
|
56
|
+
response = get "active", options
|
57
|
+
response.map{|item| Hashie::Mash.new(item)}
|
58
|
+
end
|
59
|
+
|
60
|
+
def bounced(date)
|
61
|
+
options = { :query => { :date => date } }
|
62
|
+
response = get "bounced", options
|
63
|
+
response.map{|item| Hashie::Mash.new(item)}
|
64
|
+
end
|
65
|
+
|
66
|
+
def unsubscribed(date)
|
67
|
+
options = { :query => { :date => date } }
|
68
|
+
response = get "unsubscribed", options
|
69
|
+
response.map{|item| Hashie::Mash.new(item)}
|
70
|
+
end
|
71
|
+
|
72
|
+
def update(title, unsubscribe_page, confirmed_opt_in, confirmation_success_page)
|
73
|
+
options = { :body => {
|
74
|
+
:Title => title,
|
75
|
+
:UnsubscribePage => unsubscribe_page,
|
76
|
+
:ConfirmedOptIn => confirmed_opt_in,
|
77
|
+
:ConfirmationSuccessPage => confirmation_success_page }.to_json }
|
78
|
+
response = CreateSend.put "/lists/#{list_id}.json", options
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def get(action, options = {})
|
84
|
+
CreateSend.get uri_for(action), options
|
85
|
+
end
|
86
|
+
|
87
|
+
def post(action, options = {})
|
88
|
+
CreateSend.post uri_for(action), options
|
89
|
+
end
|
90
|
+
|
91
|
+
def put(action, options = {})
|
92
|
+
CreateSend.put uri_for(action), options
|
93
|
+
end
|
94
|
+
|
95
|
+
def uri_for(action)
|
96
|
+
"/lists/#{list_id}/#{action}.json"
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|