express_pigeon 1.0.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.env.example +1 -0
- data/.gitignore +19 -16
- data/.rspec +1 -0
- data/.rubocop.yml +17 -0
- data/.rubocop_todo.yml +15 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CONTRIBUTING.md +21 -0
- data/Gemfile +13 -8
- data/Guardfile +56 -0
- data/LICENSE +9 -2
- data/README.md +4 -124
- data/Rakefile +1 -2
- data/express_pigeon.gemspec +31 -16
- data/lib/express_pigeon/api/campaigns.rb +62 -0
- data/lib/express_pigeon/api/contacts.rb +42 -0
- data/lib/express_pigeon/api/lists.rb +49 -0
- data/lib/express_pigeon/api/messages.rb +56 -0
- data/lib/express_pigeon/api.rb +66 -0
- data/lib/express_pigeon/autoresponders.rb +0 -0
- data/lib/express_pigeon/contacts.rb +71 -0
- data/lib/express_pigeon/lists.rb +111 -0
- data/lib/express_pigeon/meta_hash.rb +20 -0
- data/lib/express_pigeon/templates.rb +4 -0
- data/lib/express_pigeon/transactional_emails.rb +4 -0
- data/lib/express_pigeon/version.rb +1 -1
- data/lib/express_pigeon.rb +16 -442
- data/spec/express_pigeon/api/campaigns_spec.rb +100 -0
- data/spec/express_pigeon/api/contacts_spec.rb +146 -0
- data/spec/express_pigeon/api/lists_spec.rb +23 -0
- data/spec/express_pigeon/api/messages_spec.rb +36 -0
- data/spec/express_pigeon/contacts_spec.rb +111 -0
- data/spec/express_pigeon/lists_spec.rb +131 -0
- data/spec/fixtures/contacts.csv +2 -0
- data/spec/fixtures/contacts.csv.zip +0 -0
- data/spec/spec_helper.rb +100 -12
- data/vendor/cache/ast-2.0.0.gem +0 -0
- data/vendor/cache/astrolabe-1.3.0.gem +0 -0
- data/vendor/cache/awesome_print-1.2.0.gem +0 -0
- data/vendor/cache/byebug-3.5.1.gem +0 -0
- data/vendor/cache/celluloid-0.16.0.gem +0 -0
- data/vendor/cache/coderay-1.1.0.gem +0 -0
- data/vendor/cache/colorize-0.7.5.gem +0 -0
- data/vendor/cache/columnize-0.9.0.gem +0 -0
- data/vendor/cache/debugger-linecache-1.2.0.gem +0 -0
- data/vendor/cache/diff-lcs-1.2.5.gem +0 -0
- data/vendor/cache/docile-1.1.5.gem +0 -0
- data/vendor/cache/dotenv-1.0.2.gem +0 -0
- data/vendor/cache/ffi-1.9.6.gem +0 -0
- data/vendor/cache/formatador-0.2.5.gem +0 -0
- data/vendor/cache/guard-2.10.5.gem +0 -0
- data/vendor/cache/guard-compat-1.2.0.gem +0 -0
- data/vendor/cache/guard-rspec-4.5.0.gem +0 -0
- data/vendor/cache/hitimes-1.2.2.gem +0 -0
- data/vendor/cache/httmultiparty-0.3.16.gem +0 -0
- data/vendor/cache/httparty-0.13.3.gem +0 -0
- data/vendor/cache/json-1.8.1.gem +0 -0
- data/vendor/cache/listen-2.8.4.gem +0 -0
- data/vendor/cache/lumberjack-1.0.9.gem +0 -0
- data/vendor/cache/method_source-0.8.2.gem +0 -0
- data/vendor/cache/mimemagic-0.2.1.gem +0 -0
- data/vendor/cache/multi_json-1.10.1.gem +0 -0
- data/vendor/cache/multi_xml-0.5.5.gem +0 -0
- data/vendor/cache/multipart-post-2.0.0.gem +0 -0
- data/vendor/cache/nenv-0.1.1.gem +0 -0
- data/vendor/cache/parser-2.2.0.pre.8.gem +0 -0
- data/vendor/cache/powerpack-0.0.9.gem +0 -0
- data/vendor/cache/pry-0.10.1.gem +0 -0
- data/vendor/cache/pry-byebug-2.0.0.gem +0 -0
- data/vendor/cache/rainbow-2.0.0.gem +0 -0
- data/vendor/cache/rake-10.4.2.gem +0 -0
- data/vendor/cache/rb-fsevent-0.9.4.gem +0 -0
- data/vendor/cache/rb-inotify-0.9.5.gem +0 -0
- data/vendor/cache/rspec-3.1.0.gem +0 -0
- data/vendor/cache/rspec-core-3.1.7.gem +0 -0
- data/vendor/cache/rspec-expectations-3.1.2.gem +0 -0
- data/vendor/cache/rspec-mocks-3.1.3.gem +0 -0
- data/vendor/cache/rspec-support-3.1.2.gem +0 -0
- data/vendor/cache/rubocop-0.28.0.gem +0 -0
- data/vendor/cache/ruby-progressbar-1.7.1.gem +0 -0
- data/vendor/cache/simplecov-0.9.1.gem +0 -0
- data/vendor/cache/simplecov-html-0.8.0.gem +0 -0
- data/vendor/cache/slop-3.6.0.gem +0 -0
- data/vendor/cache/thor-0.19.1.gem +0 -0
- data/vendor/cache/timers-4.0.1.gem +0 -0
- metadata +183 -53
- data/.rvmrc +0 -52
- data/.travis.yml +0 -8
- data/CHANGELOG +0 -6
- data/bin/console +0 -12
- data/express_pigeon-rb.yml +0 -10
- data/lib/active_model/validations/date_format_validator.rb +0 -20
- data/script/lint +0 -6
- data/script/multispec +0 -23
- data/spec/web_forms_spec.rb +0 -164
@@ -0,0 +1,66 @@
|
|
1
|
+
# require_relative 'api/campaign'
|
2
|
+
# require_relative 'api/contact'
|
3
|
+
# require_relative 'api/list'
|
4
|
+
# require_relative 'api/message'
|
5
|
+
#
|
6
|
+
# module ExpressPigeon
|
7
|
+
# module API
|
8
|
+
# def http(path, method, params = {})
|
9
|
+
# uri = URI.parse "#{ROOT}#{path}"
|
10
|
+
# req = Net::HTTP.const_get("#{method}").new "#{ROOT}#{path}"
|
11
|
+
# req['X-auth-key'] = AUTH_KEY
|
12
|
+
# if params
|
13
|
+
# req.body = params.to_json
|
14
|
+
# req['Content-type'] = 'application/json'
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# if block_given?
|
18
|
+
# Net::HTTP.start(uri.host, uri.port, use_ssl: USE_SSL) do |http|
|
19
|
+
# http.request req do |res|
|
20
|
+
# res.read_body do |seg|
|
21
|
+
# yield seg
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# else
|
26
|
+
# resp = Net::HTTP.start(uri.host, uri.port, use_ssl: USE_SSL) do |http|
|
27
|
+
# http.request req
|
28
|
+
# end
|
29
|
+
# parsed = JSON.parse(resp.body)
|
30
|
+
# if parsed.is_a? Hash
|
31
|
+
# MetaHash.new parsed
|
32
|
+
# else
|
33
|
+
# parsed
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# def get(path, &block)
|
39
|
+
# http path, 'Get', nil, &block
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# def post(path, params = {})
|
43
|
+
# http path, 'Post', params
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# def del(path, params = {})
|
47
|
+
# http path, 'Delete', params
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def self.campaigns
|
51
|
+
# Campaigns.new
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# def self.lists
|
55
|
+
# Lists.new
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# def self.contacts
|
59
|
+
# Contacts.new
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# def self.messages
|
63
|
+
# Messages.new
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# end
|
File without changes
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module ExpressPigeon
|
2
|
+
# Contacts
|
3
|
+
#
|
4
|
+
# Contacts end point allows you to create, read, update and delete contacts
|
5
|
+
# on your lists. A contact consists of required email and various standard
|
6
|
+
# and custom fields.
|
7
|
+
class Contacts
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
base_uri('https://api.expresspigeon.com/contacts')
|
11
|
+
debug_output(nil)
|
12
|
+
|
13
|
+
def initialize(auth_key)
|
14
|
+
self.class.headers('X-auth-key' => auth_key)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Read a single contact by email
|
18
|
+
#
|
19
|
+
# GET https://api.expresspigeon.com/contacts
|
20
|
+
def find(email_address)
|
21
|
+
self.class.get('/', query: { email: email_address })
|
22
|
+
end
|
23
|
+
|
24
|
+
# Create or update contacts
|
25
|
+
#
|
26
|
+
# POST https://api.expresspigeon.com/contacts
|
27
|
+
def create(list_id, contacts)
|
28
|
+
fail "Contacts must be an Array received #{contacts.class.name}." unless contacts.is_a?(Array)
|
29
|
+
|
30
|
+
options = {
|
31
|
+
'list_id' => list_id,
|
32
|
+
'contacts' => contacts
|
33
|
+
}
|
34
|
+
|
35
|
+
self.class.post(
|
36
|
+
'/',
|
37
|
+
body: options.to_json,
|
38
|
+
headers: {
|
39
|
+
'Content-Type' => 'application/json'
|
40
|
+
}
|
41
|
+
)
|
42
|
+
end
|
43
|
+
alias_method :update, :create
|
44
|
+
|
45
|
+
# Delete a single contact
|
46
|
+
#
|
47
|
+
# DELETE https://api.expresspigeon.com/contacts
|
48
|
+
def delete(_email_address)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Move contacts between lists
|
52
|
+
#
|
53
|
+
# POST https://api.expresspigeon.com/contacts/move
|
54
|
+
def move(source_list_id, target_list_id, email_addresses)
|
55
|
+
fail "Email address must be an Array received #{email_addresses.class.name}." unless email_addresses.is_a?(Array)
|
56
|
+
|
57
|
+
options = {}
|
58
|
+
options['source_list'] = source_list_id
|
59
|
+
options['target_list'] = target_list_id
|
60
|
+
options['contacts'] = email_addresses
|
61
|
+
|
62
|
+
self.class.post(
|
63
|
+
'/move',
|
64
|
+
body: options.to_json,
|
65
|
+
headers: {
|
66
|
+
'Content-Type' => 'application/json'
|
67
|
+
}
|
68
|
+
)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module ExpressPigeon
|
2
|
+
# Lists
|
3
|
+
#
|
4
|
+
# Lists are sets of contacts a campaign can be sent to. A list consists of
|
5
|
+
# name, from name, reply-to fields and physical address that will be
|
6
|
+
# displayed in newsletter. Lists can be created, read, updated, deleted and
|
7
|
+
# filled up with contacts.
|
8
|
+
#
|
9
|
+
# Note: each list has properties, including physical address. Such address
|
10
|
+
# is merged into footers of newsletters when campaigns are sent to a list.
|
11
|
+
# It allows to send to different lists of contacts and display different
|
12
|
+
# physical addresses at the bottom of newsletters depending which list such
|
13
|
+
# email was sent to. This is a useful feature for agencies who manage email
|
14
|
+
# marketing campaigns on behalf of their clients.
|
15
|
+
class Lists
|
16
|
+
include HTTMultiParty
|
17
|
+
|
18
|
+
base_uri('https://api.expresspigeon.com/lists')
|
19
|
+
debug_output(nil)
|
20
|
+
|
21
|
+
def initialize(auth_key)
|
22
|
+
self.class.headers('X-auth-key' => auth_key)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create a new list
|
26
|
+
# POST https://api.expresspigeon.com/lists
|
27
|
+
#
|
28
|
+
# name: Name of a newly created list
|
29
|
+
# from_name: Default "from" name used when sending campaigns to this list
|
30
|
+
# reply_to: Default reply To email address used when sending campaigns to this list
|
31
|
+
def create(name:, from_name:, reply_to:)
|
32
|
+
self.class.post(
|
33
|
+
'/',
|
34
|
+
body: {
|
35
|
+
name: name,
|
36
|
+
from_name: from_name,
|
37
|
+
reply_to: reply_to
|
38
|
+
}.to_json,
|
39
|
+
headers: {
|
40
|
+
'Content-Type' => 'application/json'
|
41
|
+
}
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check the status of list upload
|
46
|
+
# GET https://api.expresspigeon.com/lists/upload_status/{upload_id}
|
47
|
+
def upload_status(upload_id)
|
48
|
+
self.class.get("/upload_status/#{upload_id}")
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get all lists
|
52
|
+
# GET https://api.expresspigeon.com/lists
|
53
|
+
def index
|
54
|
+
self.class.get('/')
|
55
|
+
end
|
56
|
+
|
57
|
+
# Upload contacts to list
|
58
|
+
# POST https://api.expresspigeon.com/lists/{list_id}/upload
|
59
|
+
def upload(list_id, path)
|
60
|
+
fail "No file found at '#{path}'." unless File.exist?(path)
|
61
|
+
|
62
|
+
self.class.post(
|
63
|
+
"/#{list_id}/upload",
|
64
|
+
query: { contacts_file: File.new(path, 'r') },
|
65
|
+
detect_mime_type: true
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Delete a list
|
70
|
+
# DELETE https://api.expresspigeon.com/lists/{list_id}
|
71
|
+
def delete(list_id)
|
72
|
+
self.class.delete("/#{list_id}")
|
73
|
+
end
|
74
|
+
|
75
|
+
# Download contacts from list
|
76
|
+
# GET https://api.expresspigeon.com/lists/{list_id}/csv
|
77
|
+
def download_csv(list_id, download_path)
|
78
|
+
fail "File found at '#{download_path}' but will not overwrite." if File.exist?(download_path)
|
79
|
+
|
80
|
+
response = self.class.get("/#{list_id}/csv")
|
81
|
+
|
82
|
+
File.open(download_path, 'wb') do |f|
|
83
|
+
f.write response.body
|
84
|
+
end
|
85
|
+
|
86
|
+
response
|
87
|
+
end
|
88
|
+
|
89
|
+
# Update existing list
|
90
|
+
# PUT https://api.expresspigeon.com/lists
|
91
|
+
def update(list_id, name: nil, from_name: nil, reply_to: nil)
|
92
|
+
options = {}
|
93
|
+
options['name'] = name unless name.nil?
|
94
|
+
options['from_name'] = from_name unless from_name.nil?
|
95
|
+
options['reply_to'] = reply_to unless reply_to.nil?
|
96
|
+
|
97
|
+
# if we didn't provide any options then it's a NOOP
|
98
|
+
return nil if options.empty?
|
99
|
+
|
100
|
+
options['id'] = list_id
|
101
|
+
|
102
|
+
self.class.put(
|
103
|
+
'/',
|
104
|
+
body: options.to_json,
|
105
|
+
headers: {
|
106
|
+
'Content-Type' => 'application/json'
|
107
|
+
}
|
108
|
+
)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# class MetaHash < Hash
|
2
|
+
# def initialize(delegate)
|
3
|
+
# super
|
4
|
+
# @delegate = delegate
|
5
|
+
# @delegate.each_key do |k|
|
6
|
+
# v = @delegate[k] # lets go only one level down for now
|
7
|
+
# if v.is_a? Hash
|
8
|
+
# @delegate[k] = MetaHash.new(v)
|
9
|
+
# end
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# def method_missing(m, *_args, &_block)
|
14
|
+
# @delegate[m.to_s]
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def to_s
|
18
|
+
# @delegate.to_s
|
19
|
+
# end
|
20
|
+
# end
|