createsend 0.0.1
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/.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
|